Remove jQuery
* feature/no-jquery: More optimizations Really remove jQuery Refactor wrapify() completely without jQuery Begin refactor of wrapify
This commit is contained in:
commit
9e1dc45678
|
@ -82,3 +82,4 @@ gtag('config','{{ site.data.google_analytics.id }}');
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<script>(function(H){H.className=H.className.replace(/\bno-js\b/,'js')})(document.documentElement)</script>
|
<script>(function(H){H.className=H.className.replace(/\bno-js\b/,'js')})(document.documentElement)</script>
|
||||||
|
<script>(function(H){H.className=H.className.replace(/\bNoJs\b/,'WithJs')})(document.documentElement)</script>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// 3rd party libs
|
// 3rd party libs
|
||||||
window.jQuery = window.$ = require('jquery')
|
|
||||||
window.Prism = require('prismjs')
|
window.Prism = require('prismjs')
|
||||||
|
|
||||||
// All the others
|
// All the others
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import onmount from 'onmount'
|
import onmount from 'onmount'
|
||||||
import $ from 'jquery'
|
import { nextUntil } from '../helpers/dom'
|
||||||
|
import matches from 'dom101/matches'
|
||||||
|
|
||||||
// Ensure that search-index is set first
|
// Ensure that search-index is set first
|
||||||
import './searchable-item'
|
import './searchable-item'
|
||||||
|
@ -9,16 +10,13 @@ import './searchable-item'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
onmount('[data-js-searchable-header]', function () {
|
onmount('[data-js-searchable-header]', function () {
|
||||||
const $this = $(this)
|
const els = nextUntil(this, '[data-js-searchable-header]')
|
||||||
const $els = $this
|
.filter(el => matches(el, '[data-search-index]'))
|
||||||
.nextUntil('[data-js-searchable-header]')
|
|
||||||
.filter('[data-search-index]')
|
|
||||||
|
|
||||||
const keywords = $els
|
const keywords = els
|
||||||
.map(function () { return $(this).attr('data-search-index') })
|
.map(n => n.getAttribute('data-search-index'))
|
||||||
.get()
|
|
||||||
.join(' ')
|
.join(' ')
|
||||||
.split(' ')
|
.split(' ')
|
||||||
|
|
||||||
$this.attr('data-search-index', keywords.join(' '))
|
this.setAttribute('data-search-index', keywords.join(' '))
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
import matches from 'dom101/matches'
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Just like jQuery.append
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function appendMany (el, children) {
|
||||||
|
children.forEach(child => { el.appendChild(child) })
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Just like jQuery.nextUntil
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function nextUntil (el, selector) {
|
||||||
|
const nextEl = el.nextSibling
|
||||||
|
return nextUntilTick(nextEl, selector, [])
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextUntilTick (el, selector, acc) {
|
||||||
|
if (!el) return acc
|
||||||
|
|
||||||
|
const isMatch = matches(el, selector)
|
||||||
|
if (isMatch) return acc
|
||||||
|
|
||||||
|
return nextUntilTick(el.nextSibling, selector, [ ...acc, el ])
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Just like jQuery.before
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function before (reference, newNode) {
|
||||||
|
reference.parentNode.insertBefore(newNode, reference)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like jQuery.children('selector')
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function findChildren (el, selector) {
|
||||||
|
return [].slice.call(el.children)
|
||||||
|
.filter(child => matches(child, selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a div
|
||||||
|
* @private
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* createDiv({ class: 'foo' })
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function createDiv (props) {
|
||||||
|
const d = document.createElement('div')
|
||||||
|
Object.keys(props).forEach(key => {
|
||||||
|
d.setAttribute(key, props[key])
|
||||||
|
})
|
||||||
|
return d
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
/* blank */
|
|
@ -1,6 +1,7 @@
|
||||||
import wrapify from '../wrapify'
|
import wrapify from '../wrapify'
|
||||||
import ready from 'dom101/ready'
|
import ready from 'dom101/ready'
|
||||||
import onmount from 'onmount'
|
import onmount from 'onmount'
|
||||||
|
import addClass from 'dom101/add-class'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Behavior: Wrapping
|
* Behavior: Wrapping
|
||||||
|
@ -8,6 +9,9 @@ import onmount from 'onmount'
|
||||||
|
|
||||||
ready(() => {
|
ready(() => {
|
||||||
const body = document.querySelector('[data-js-main-body]')
|
const body = document.querySelector('[data-js-main-body]')
|
||||||
if (body) { wrapify(body) }
|
if (body) {
|
||||||
|
wrapify(body)
|
||||||
|
addClass(body, '-wrapified')
|
||||||
|
}
|
||||||
setTimeout(() => { onmount() })
|
setTimeout(() => { onmount() })
|
||||||
})
|
})
|
||||||
|
|
|
@ -22,17 +22,17 @@ exports[`h3 with class 1`] = `
|
||||||
<div
|
<div
|
||||||
class="body -hello"
|
class="body -hello"
|
||||||
>
|
>
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
(install)
|
(install)
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -72,9 +72,14 @@ exports[`multiple h2s 1`] = `
|
||||||
<div
|
<div
|
||||||
class="body"
|
class="body"
|
||||||
>
|
>
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
(install)
|
(install)
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -86,23 +91,18 @@ exports[`multiple h2s 1`] = `
|
||||||
<div
|
<div
|
||||||
class="body"
|
class="body"
|
||||||
>
|
>
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
(usage)
|
(usage)
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="h2-section"
|
class="h2-section"
|
||||||
>
|
>
|
||||||
|
@ -135,9 +135,14 @@ exports[`multiple h2s 1`] = `
|
||||||
<div
|
<div
|
||||||
class="body"
|
class="body"
|
||||||
>
|
>
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
(first)
|
(first)
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -149,22 +154,17 @@ exports[`multiple h2s 1`] = `
|
||||||
<div
|
<div
|
||||||
class="body"
|
class="body"
|
||||||
>
|
>
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
(second)
|
(second)
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -204,9 +204,14 @@ exports[`simple usage 1`] = `
|
||||||
<div
|
<div
|
||||||
class="body"
|
class="body"
|
||||||
>
|
>
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
(install)
|
(install)
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -218,21 +223,16 @@ exports[`simple usage 1`] = `
|
||||||
<div
|
<div
|
||||||
class="body"
|
class="body"
|
||||||
>
|
>
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
(usage)
|
(usage)
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -1,63 +1,110 @@
|
||||||
import $ from 'jquery'
|
import matches from 'dom101/matches'
|
||||||
|
import addClass from 'dom101/add-class'
|
||||||
|
import { appendMany, nextUntil, before, findChildren, createDiv } from '../helpers/dom'
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Wraps h2 sections into h2-section.
|
* Wraps h2 sections into h2-section.
|
||||||
* Wraps h3 sections into h3-section.
|
* Wraps h3 sections into h3-section.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default function wrapify (root) {
|
export default function wrapify (root) {
|
||||||
const $root = $(root)
|
// These are your H2 sections. Returns a list of .h2-section nodes.
|
||||||
const $h2sections = groupify($root, {
|
const sections = wrapifyH2(root)
|
||||||
tag: 'h2',
|
|
||||||
wrapper: '<div class="h2-section">',
|
// For each h2 section, wrap the H3's in them
|
||||||
body: '<div class="body h3-section-list" data-js-h3-section-list>'
|
sections.forEach(section => {
|
||||||
|
const bodies = findChildren(section, '[data-js-h3-section-list]')
|
||||||
|
bodies.forEach(body => { wrapifyH3(body) })
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
$h2sections.each(function () {
|
/**
|
||||||
const $body = $(this).children('[data-js-h3-section-list]')
|
* Wraps h2 sections into h2-section.
|
||||||
|
* Creates and HTML structure like so:
|
||||||
|
*
|
||||||
|
* .h2-section
|
||||||
|
* h2.
|
||||||
|
* (title)
|
||||||
|
* .body.h3-section-list.
|
||||||
|
* (body goes here)
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
groupify($body, {
|
function wrapifyH2 (root) {
|
||||||
tag: 'h3',
|
return groupify(root, {
|
||||||
wrapper: '<div class="h3-section">',
|
tag: 'h2',
|
||||||
body: '<div class="body">'
|
wrapperFn: () => createDiv({ class: 'h2-section' }),
|
||||||
|
bodyFn: () => createDiv({
|
||||||
|
class: 'body h3-section-list',
|
||||||
|
'data-js-h3-section-list': ''
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Groups stuff
|
* Wraps h3 sections into h3-section.
|
||||||
|
* Creates and HTML structure like so:
|
||||||
|
*
|
||||||
|
* .h3-section
|
||||||
|
* h3.
|
||||||
|
* (title)
|
||||||
|
* .body.
|
||||||
|
* (body goes here)
|
||||||
|
*
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function groupify ($this, { tag, wrapper, body }) {
|
function wrapifyH3 (root) {
|
||||||
const $first = $this.children(':first-child')
|
return groupify(root, {
|
||||||
let $result = $()
|
tag: 'h3',
|
||||||
|
wrapperFn: () => createDiv({ class: 'h3-section' }),
|
||||||
|
bodyFn: () => createDiv({ class: 'body' })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Groups all headings (a `tag` selector) under wrappers like `.h2-section`
|
||||||
|
* (build by `wrapperFn()`).
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function groupify (el, { tag, wrapperFn, bodyFn }) {
|
||||||
|
const first = el.children[0]
|
||||||
|
let result = []
|
||||||
|
|
||||||
// Handle the markup before the first h2
|
// Handle the markup before the first h2
|
||||||
if (!$first.is(tag)) {
|
if (first && !matches(first, tag)) {
|
||||||
const $sibs = $first.nextUntil(tag)
|
const sibs = nextUntil(first, tag)
|
||||||
$result = $result.add(wrap($first, null, $first.add($sibs)))
|
result.push(wrap(first, null, [ first, ...sibs ]))
|
||||||
}
|
}
|
||||||
|
|
||||||
$this.children(tag).each(function () {
|
// Find all h3's inside it
|
||||||
const $sibs = $(this).nextUntil(tag)
|
const children = findChildren(el, tag)
|
||||||
const $heading = $(this)
|
|
||||||
$result = $result.add(wrap($heading, $heading, $sibs))
|
children.forEach(child => {
|
||||||
|
const sibs = nextUntil(child, tag)
|
||||||
|
result.push(wrap(child, child, sibs))
|
||||||
})
|
})
|
||||||
|
|
||||||
return $result
|
return result
|
||||||
|
|
||||||
function wrap ($pivot, $first, $sibs) {
|
function wrap (pivot, first, sibs) {
|
||||||
const $wrap = $(wrapper)
|
const wrap = wrapperFn()
|
||||||
$wrap.addClass($pivot.attr('class'))
|
|
||||||
$pivot.before($wrap)
|
|
||||||
|
|
||||||
const $body = $(body)
|
const pivotClass = pivot.className
|
||||||
$body.addClass($pivot.attr('class'))
|
if (pivotClass) addClass(wrap, pivotClass)
|
||||||
$body.append($sibs)
|
before(pivot, wrap)
|
||||||
|
|
||||||
if ($first) $wrap.append($first)
|
const body = bodyFn()
|
||||||
$wrap.append($body)
|
if (pivotClass) addClass(body, pivotClass)
|
||||||
|
appendMany(body, sibs)
|
||||||
|
|
||||||
return $wrap
|
if (first) wrap.appendChild(first)
|
||||||
|
wrap.appendChild(body)
|
||||||
|
|
||||||
|
return wrap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang='en'><head>
|
<html class='NoJs' lang='en'><head>
|
||||||
|
|
||||||
{% include 2017/head.html %}
|
{% include 2017/head.html %}
|
||||||
{% include 2017/article-schema.html page=page %}
|
{% include 2017/article-schema.html page=page %}
|
||||||
|
|
|
@ -69,3 +69,18 @@ a:hover {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hide markdown before it's wrapped.
|
||||||
|
*/
|
||||||
|
|
||||||
|
html.WithJs .MarkdownBody {
|
||||||
|
& {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.-wrapified {
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 250ms linear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 130px;
|
height: 130px;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prelude */
|
/* Prelude */
|
||||||
|
|
|
@ -8,7 +8,6 @@ module.exports = {
|
||||||
app: './_js/app.js',
|
app: './_js/app.js',
|
||||||
vendor: [
|
vendor: [
|
||||||
// Large 3rd-party libs
|
// Large 3rd-party libs
|
||||||
'jquery',
|
|
||||||
'prismjs',
|
'prismjs',
|
||||||
|
|
||||||
// Prism plugins
|
// Prism plugins
|
||||||
|
@ -48,6 +47,12 @@ module.exports = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
// Never bundle jQuery
|
||||||
|
'jquery': join(__dirname, '..', '_js/helpers/noop.js')
|
||||||
|
}
|
||||||
|
},
|
||||||
stats: 'minimal',
|
stats: 'minimal',
|
||||||
plugins: [
|
plugins: [
|
||||||
// Optimize module ID's for vendor chunks
|
// Optimize module ID's for vendor chunks
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue