switch to eslint-config-standard

This commit is contained in:
Jason Miller
2018-04-05 11:44:32 -04:00
parent 3f55698439
commit 387f4cf9a3
3 changed files with 70 additions and 49 deletions

View File

@@ -24,7 +24,7 @@ const PARSE5_OPTS = {
* @param {Boolean} [options.compress=true] Compress resulting critical CSS * @param {Boolean} [options.compress=true] Compress resulting critical CSS
*/ */
module.exports = class CrittersWebpackPlugin { module.exports = class CrittersWebpackPlugin {
constructor(options) { constructor (options) {
this.options = options || {}; this.options = options || {};
this.urlFilter = this.options.filter; this.urlFilter = this.options.filter;
if (this.urlFilter instanceof RegExp) { if (this.urlFilter instanceof RegExp) {
@@ -33,7 +33,7 @@ module.exports = class CrittersWebpackPlugin {
} }
/** Invoked by Webpack during plugin initialization */ /** Invoked by Webpack during plugin initialization */
apply(compiler) { apply (compiler) {
const outputPath = compiler.options.output.path; const outputPath = compiler.options.output.path;
// hook into the compiler to get a Compilation instance... // hook into the compiler to get a Compilation instance...
@@ -47,7 +47,7 @@ module.exports = class CrittersWebpackPlugin {
let externalStylesProcessed = Promise.resolve(); let externalStylesProcessed = Promise.resolve();
// `external:false` skips processing of external sheets // `external:false` skips processing of external sheets
if (this.options.external!==false) { if (this.options.external !== false) {
const externalSheets = document.querySelectorAll('link[rel="stylesheet"]'); const externalSheets = document.querySelectorAll('link[rel="stylesheet"]');
externalStylesProcessed = Promise.all(externalSheets.map( externalStylesProcessed = Promise.all(externalSheets.map(
link => this.embedLinkedStylesheet(link, compilation, outputPath) link => this.embedLinkedStylesheet(link, compilation, outputPath)
@@ -71,7 +71,7 @@ module.exports = class CrittersWebpackPlugin {
} }
/** Inline the target stylesheet referred to by a <link rel="stylesheet"> (assuming it passes `options.filter`) */ /** Inline the target stylesheet referred to by a <link rel="stylesheet"> (assuming it passes `options.filter`) */
embedLinkedStylesheet(link, compilation, outputPath) { embedLinkedStylesheet (link, compilation, outputPath) {
const href = link.getAttribute('href'); const href = link.getAttribute('href');
const document = link.ownerDocument; const document = link.ownerDocument;
@@ -105,12 +105,12 @@ module.exports = class CrittersWebpackPlugin {
} }
/** Parse the stylesheet within a <style> element, then reduce it to contain only rules used by the document. */ /** Parse the stylesheet within a <style> element, then reduce it to contain only rules used by the document. */
processStyle(style) { processStyle (style) {
const done = Promise.resolve(); const done = Promise.resolve();
const document = style.ownerDocument; const document = style.ownerDocument;
// basically `.textContent` // basically `.textContent`
let sheet = style.childNodes.length>0 && style.childNodes.map( node => node.nodeValue ).join('\n'); let sheet = style.childNodes.length > 0 && style.childNodes.map(node => node.nodeValue).join('\n');
// store a reference to the previous serialized stylesheet for reporting stats // store a reference to the previous serialized stylesheet for reporting stats
const before = sheet; const before = sheet;
@@ -122,7 +122,7 @@ module.exports = class CrittersWebpackPlugin {
// Walk all CSS rules, transforming unused rules to comments (which get removed) // Walk all CSS rules, transforming unused rules to comments (which get removed)
visit(ast, rule => { visit(ast, rule => {
if (rule.type==='rule') { if (rule.type === 'rule') {
// Filter the selector list down to only those matche // Filter the selector list down to only those matche
rule.selectors = rule.selectors.filter(sel => { rule.selectors = rule.selectors.filter(sel => {
// Strip pseudo-elements and pseudo-classes, since we only care that their associated elements exist. // Strip pseudo-elements and pseudo-classes, since we only care that their associated elements exist.
@@ -131,23 +131,22 @@ module.exports = class CrittersWebpackPlugin {
return document.querySelector(sel, document) != null; return document.querySelector(sel, document) != null;
}); });
// If there are no matched selectors, remove the rule: // If there are no matched selectors, remove the rule:
if (rule.selectors.length===0) { if (rule.selectors.length === 0) {
return false; return false;
} }
} }
// If there are no remaining rules, remove the whole rule. // If there are no remaining rules, remove the whole rule.
return !rule.rules || rule.rules.length!==0; return !rule.rules || rule.rules.length !== 0;
}); });
sheet = css.stringify(ast, { compress: this.options.compress!==false }); sheet = css.stringify(ast, { compress: this.options.compress !== false });
return done.then(() => { return done.then(() => {
// If all rules were removed, get rid of the style element entirely // If all rules were removed, get rid of the style element entirely
if (sheet.trim().length===0) { if (sheet.trim().length === 0) {
sheet.parentNode.removeChild(sheet); sheet.parentNode.removeChild(sheet);
} } else {
else {
// replace the inline stylesheet with its critical'd counterpart // replace the inline stylesheet with its critical'd counterpart
while (style.lastChild) { while (style.lastChild) {
style.removeChild(style.lastChild); style.removeChild(style.lastChild);
@@ -163,27 +162,25 @@ module.exports = class CrittersWebpackPlugin {
} }
}; };
/** Recursively walk all rules in a stylesheet. /** Recursively walk all rules in a stylesheet.
* The iterator can explicitly return `false` to remove the current node. * The iterator can explicitly return `false` to remove the current node.
*/ */
function visit(node, fn) { function visit (node, fn) {
if (node.stylesheet) return visit(node.stylesheet, fn); if (node.stylesheet) return visit(node.stylesheet, fn);
node.rules = node.rules.filter(rule => { node.rules = node.rules.filter(rule => {
if (rule.rules) { if (rule.rules) {
visit(rule, fn); visit(rule, fn);
} }
return fn(rule)!==false; return fn(rule) !== false;
}); });
} }
/** Enhance an htmlparser2-style DOM with basic manipulation methods. */ /** Enhance an htmlparser2-style DOM with basic manipulation methods. */
function makeDomInteractive(document) { function makeDomInteractive (document) {
defineProperties(document, DocumentExtensions); defineProperties(document, DocumentExtensions);
// Find the first <html> element within the document // Find the first <html> element within the document
document.documentElement = document.childNodes.filter( child => String(child.tagName).toLowerCase()==='html' )[0]; // document.documentElement = document.childNodes.filter( child => String(child.tagName).toLowerCase()==='html' )[0];
// Extend Element.prototype with DOM manipulation methods. // Extend Element.prototype with DOM manipulation methods.
// Note: document.$$scratchElement is also used by createTextNode() // Note: document.$$scratchElement is also used by createTextNode()
@@ -203,62 +200,64 @@ function makeDomInteractive(document) {
} }
/** Essentially Object.defineProperties() except any functions are assigned as values rather than descriptors. */ /** Essentially Object.defineProperties() except any functions are assigned as values rather than descriptors. */
function defineProperties(obj, properties) { function defineProperties (obj, properties) {
for (const i in properties) { for (const i in properties) {
const value = properties[i]; const value = properties[i];
Object.defineProperty(obj, i, typeof value === 'function' ? { value } : value); Object.defineProperty(obj, i, typeof value === 'function' ? { value } : value);
} }
} }
/** {document,Element}.getElementsByTagName() is the only traversal method required by nwmatcher. */ /** {document,Element}.getElementsByTagName() is the only traversal method required by nwmatcher.
function getElementsByTagName(tagName) { * Note: if perf issues arise, 2 faster but more verbose implementations are benchmarked here:
* https://esbench.com/bench/5ac3b647f2949800a0f619e1
*/
function getElementsByTagName (tagName) {
// Only return Element/Document nodes // Only return Element/Document nodes
if (this.nodeType!==1 && this.nodeType!==9 || this.type==='directive') return []; if ((this.nodeType !== 1 && this.nodeType !== 9) || this.type === 'directive') return [];
return Array.prototype.concat.apply( return Array.prototype.concat.apply(
// Add current element if it matches tag // Add current element if it matches tag
(tagName === '*' || (this.tagName && (this.tagName == tagName || this.nodeName === tagName.toUpperCase()))) ? [this] : [], (tagName === '*' || (this.tagName && (this.tagName === tagName || this.nodeName === tagName.toUpperCase()))) ? [this] : [],
// Check children recursively // Check children recursively
this.children.map(child => getElementsByTagName.call(child, tagName)) this.children.map(child => getElementsByTagName.call(child, tagName))
); );
} }
/** Methods and descriptors to mix into Element.prototype */ /** Methods and descriptors to mix into Element.prototype */
const ElementExtensions = { const ElementExtensions = {
nodeName: { nodeName: {
get() { get () {
return this.tagName.toUpperCase(); return this.tagName.toUpperCase();
} }
}, },
insertBefore(child, referenceNode) { insertBefore (child, referenceNode) {
if (!referenceNode) return this.appendChild(child); if (!referenceNode) return this.appendChild(child);
treeAdapter.insertBefore(this, child, referenceNode); treeAdapter.insertBefore(this, child, referenceNode);
return child; return child;
}, },
appendChild(child) { appendChild (child) {
treeAdapter.appendChild(this, child); treeAdapter.appendChild(this, child);
return child; return child;
}, },
removeChild(child) { removeChild (child) {
treeAdapter.detachNode(child); treeAdapter.detachNode(child);
}, },
setAttribute(name, value) { setAttribute (name, value) {
if (this.attribs == null) this.attribs = {}; if (this.attribs == null) this.attribs = {};
if (value == null) value = ''; if (value == null) value = '';
this.attribs[name] = value; this.attribs[name] = value;
}, },
removeAttribute(name) { removeAttribute (name) {
if (this.attribs != null) { if (this.attribs != null) {
delete this.attribs[name]; delete this.attribs[name];
} }
}, },
getAttribute(name) { getAttribute (name) {
return this.attribs != null && this.attribs[name]; return this.attribs != null && this.attribs[name];
}, },
hasAttribute(name) { hasAttribute (name) {
return this.attribs != null && this.attribs[name] != null; return this.attribs != null && this.attribs[name] != null;
}, },
getAttributeNode(name) { getAttributeNode (name) {
const value = this.getAttribute(name); const value = this.getAttribute(name);
if (value != null) return { specified: true, value }; if (value != null) return { specified: true, value };
}, },
@@ -270,19 +269,30 @@ const DocumentExtensions = {
// document is just an Element in htmlparser2, giving it a nodeType of ELEMENT_NODE. // document is just an Element in htmlparser2, giving it a nodeType of ELEMENT_NODE.
// nwmatcher requires that it at least report a correct nodeType of DOCUMENT_NODE. // nwmatcher requires that it at least report a correct nodeType of DOCUMENT_NODE.
nodeType: { nodeType: {
get() { get () {
return 9; return 9;
} }
}, },
nodeName: { nodeName: {
get() { get () {
return '#document'; return '#document';
} }
}, },
createElement(name) { documentElement: {
get () {
// Find the first <html> element within the document
return this.childNodes.filter(child => String(child.tagName).toLowerCase() === 'html')[0];
}
},
body: {
get () {
return this.querySelector('body');
}
},
createElement (name) {
return treeAdapter.createElement(name, null, []); return treeAdapter.createElement(name, null, []);
}, },
createTextNode(text) { createTextNode (text) {
// there is no dedicated createTextNode equivalent in htmlparser2's DOM, so // there is no dedicated createTextNode equivalent in htmlparser2's DOM, so
// we have to insert Text and then remove and return the resulting Text node. // we have to insert Text and then remove and return the resulting Text node.
const scratch = this.$$scratchElement; const scratch = this.$$scratchElement;
@@ -291,14 +301,14 @@ const DocumentExtensions = {
treeAdapter.detachNode(node); treeAdapter.detachNode(node);
return node; return node;
}, },
querySelector(sel) { querySelector (sel) {
return this.$match.first(sel, this.documentElement); return this.$match.first(sel, this.documentElement);
}, },
querySelectorAll(sel) { querySelectorAll (sel) {
return this.$match.select(sel, this.documentElement); return this.$match.select(sel, this.documentElement);
}, },
getElementsByTagName, getElementsByTagName,
// nwmatcher uses inexistence of `document.addEventListener` to detect IE: // nwmatcher uses inexistence of `document.addEventListener` to detect IE:
// https://github.com/dperini/nwmatcher/blob/3edb471e12ce7f7d46dc1606c7f659ff45675a29/src/nwmatcher.js#L353 // https://github.com/dperini/nwmatcher/blob/3edb471e12ce7f7d46dc1606c7f659ff45675a29/src/nwmatcher.js#L353
addEventListener: Object addEventListener: Object
}; };

View File

@@ -9,14 +9,19 @@
"lint": "eslint src" "lint": "eslint src"
}, },
"eslintConfig": { "eslintConfig": {
"extends": "eslint-config-developit", "extends": [
"standard",
"standard-jsx"
],
"rules": { "rules": {
"indent": [ "indent": [
2, 2,
2 2
], ],
"object-shorthand": 0, "semi": [
"prefer-arrow-callback": 0, 2,
"always"
],
"prefer-const": 1 "prefer-const": 1
} }
}, },
@@ -43,7 +48,13 @@
"css-loader": "^0.28.11", "css-loader": "^0.28.11",
"ejs-loader": "^0.3.1", "ejs-loader": "^0.3.1",
"eslint": "^4.18.2", "eslint": "^4.18.2",
"eslint-config-developit": "^1.1.1", "eslint-config-standard": "^11.0.0",
"eslint-config-standard-jsx": "^5.0.0",
"eslint-plugin-import": "^2.10.0",
"eslint-plugin-node": "^6.0.1",
"eslint-plugin-promise": "^3.7.0",
"eslint-plugin-react": "^7.7.0",
"eslint-plugin-standard": "^3.0.1",
"extract-text-webpack-plugin": "^4.0.0-beta.0", "extract-text-webpack-plugin": "^4.0.0-beta.0",
"fork-ts-checker-notifier-webpack-plugin": "^0.4.0", "fork-ts-checker-notifier-webpack-plugin": "^0.4.0",
"fork-ts-checker-webpack-plugin": "^0.4.1", "fork-ts-checker-webpack-plugin": "^0.4.1",

View File

@@ -3,17 +3,17 @@ import { options } from 'preact';
const classNameDescriptor = { const classNameDescriptor = {
enumerable: false, enumerable: false,
configurable: true, configurable: true,
get() { get () {
return this.class; return this.class;
}, },
set(value) { set (value) {
this.class = value; this.class = value;
} }
}; };
let old = options.vnode; const old = options.vnode;
options.vnode = vnode => { options.vnode = vnode => {
let a = vnode.attributes; const a = vnode.attributes;
if (a != null) { if (a != null) {
if ('className' in a) { if ('className' in a) {
a.class = a.className; a.class = a.className;