Changeset e29cc2e for trip-planner-front/node_modules/critters/src
- Timestamp:
- 11/25/21 22:08:24 (3 years ago)
- Branches:
- master
- Children:
- 8d391a1
- Parents:
- 59329aa
- Location:
- trip-planner-front/node_modules/critters/src
- Files:
-
- 5 deleted
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trip-planner-front/node_modules/critters/src/css.js
r59329aa re29cc2e 15 15 */ 16 16 17 import css from 'css';17 import { parse, stringify } from 'postcss'; 18 18 19 19 /** 20 20 * Parse a textual CSS Stylesheet into a Stylesheet instance. 21 * Stylesheet is a mutable ReworkCSSAST with format similar to CSSOM.22 * @see https://github.com/ reworkcss/css21 * Stylesheet is a mutable postcss AST with format similar to CSSOM. 22 * @see https://github.com/postcss/postcss/ 23 23 * @private 24 24 * @param {String} stylesheet 25 25 * @returns {css.Stylesheet} ast 26 26 */ 27 export function parseStylesheet 28 return css.parse(stylesheet);27 export function parseStylesheet(stylesheet) { 28 return parse(stylesheet); 29 29 } 30 30 31 31 /** 32 * Serialize a ReworkCSSStylesheet to a String of CSS.32 * Serialize a postcss Stylesheet to a String of CSS. 33 33 * @private 34 34 * @param {css.Stylesheet} ast A Stylesheet to serialize, such as one returned from `parseStylesheet()` 35 * @param {Object} options Options to pass to `css.stringify()`35 * @param {Object} options Options used by the stringify logic 36 36 * @param {Boolean} [options.compress] Compress CSS output (removes comments, whitespace, etc) 37 37 */ 38 export function serializeStylesheet (ast, options) { 39 return css.stringify(ast, options); 38 export function serializeStylesheet(ast, options) { 39 let cssStr = ''; 40 41 stringify(ast, (result, node, type) => { 42 if (!options.compress) { 43 cssStr += result; 44 return; 45 } 46 47 // Simple minification logic 48 if (node?.type === 'comment') return; 49 50 if (node?.type === 'decl') { 51 const prefix = node.prop + node.raws.between; 52 53 cssStr += result.replace(prefix, prefix.trim()); 54 return; 55 } 56 57 if (type === 'start') { 58 if (node.type === 'rule' && node.selectors) { 59 cssStr += node.selectors.join(',') + '{'; 60 } else { 61 cssStr += result.replace(/\s\{$/, '{'); 62 } 63 return; 64 } 65 66 if (type === 'end' && result === '}' && node?.raws?.semicolon) { 67 cssStr = cssStr.slice(0, -1); 68 } 69 70 cssStr += result.trim(); 71 }); 72 73 return cssStr; 40 74 } 41 75 … … 47 81 * @returns {(rule) => void} nonDestructiveIterator 48 82 */ 49 export function markOnly 50 return rule=> {83 export function markOnly(predicate) { 84 return (rule) => { 51 85 const sel = rule.selectors; 52 86 if (predicate(rule) === false) { … … 65 99 * @private 66 100 * @param {css.Rule} rule The Rule to apply marked selectors to (if they exist). 67 */68 export function applyMarkedSelectors 101 */ 102 export function applyMarkedSelectors(rule) { 69 103 if (rule.$$markedSelectors) { 70 104 rule.selectors = rule.$$markedSelectors; … … 81 115 * @param {Function} iterator Invoked on each node in the tree. Return `false` to remove that node. 82 116 */ 83 export function walkStyleRules (node, iterator) { 84 if (node.stylesheet) return walkStyleRules(node.stylesheet, iterator); 85 86 node.rules = node.rules.filter(rule => { 87 if (rule.rules) { 117 export function walkStyleRules(node, iterator) { 118 node.nodes = node.nodes.filter((rule) => { 119 if (hasNestedRules(rule)) { 88 120 walkStyleRules(rule, iterator); 89 121 } … … 101 133 * @param {Function} iterator Invoked on each node in the tree. Return `false` to remove that node from the first tree, true to remove it from the second. 102 134 */ 103 export function walkStyleRulesWithReverseMirror 135 export function walkStyleRulesWithReverseMirror(node, node2, iterator) { 104 136 if (node2 === null) return walkStyleRules(node, iterator); 105 137 106 if (node.stylesheet) return walkStyleRulesWithReverseMirror(node.stylesheet, node2.stylesheet, iterator); 138 [node.nodes, node2.nodes] = splitFilter( 139 node.nodes, 140 node2.nodes, 141 (rule, index, rules, rules2) => { 142 const rule2 = rules2[index]; 143 if (hasNestedRules(rule)) { 144 walkStyleRulesWithReverseMirror(rule, rule2, iterator); 145 } 146 rule._other = rule2; 147 rule.filterSelectors = filterSelectors; 148 return iterator(rule) !== false; 149 } 150 ); 151 } 107 152 108 [node.rules, node2.rules] = splitFilter(node.rules, node2.rules, (rule, index, rules, rules2) => { 109 const rule2 = rules2[index]; 110 if (rule.rules) {111 walkStyleRulesWithReverseMirror(rule, rule2, iterator);112 }113 rule. _other = rule2;114 rule. filterSelectors = filterSelectors;115 r eturn iterator(rule) !== false;116 });153 // Checks if a node has nested rules, like @media 154 // @keyframes are an exception since they are evaluated as a whole 155 function hasNestedRules(rule) { 156 return ( 157 rule.nodes && 158 rule.nodes.length && 159 rule.nodes.some((n) => n.type === 'rule' || n.type === 'atrule') && 160 rule.name !== 'keyframes' 161 ); 117 162 } 118 163 119 164 // Like [].filter(), but applies the opposite filtering result to a second copy of the Array without a second pass. 120 165 // This is just a quicker version of generating the compliment of the set returned from a filter operation. 121 function splitFilter 166 function splitFilter(a, b, predicate) { 122 167 const aOut = []; 123 168 const bOut = []; … … 133 178 134 179 // can be invoked on a style rule to subset its selectors (with reverse mirroring) 135 function filterSelectors 180 function filterSelectors(predicate) { 136 181 if (this._other) { 137 const [a, b] = splitFilter(this.selectors, this._other.selectors, predicate); 182 const [a, b] = splitFilter( 183 this.selectors, 184 this._other.selectors, 185 predicate 186 ); 138 187 this.selectors = a; 139 188 this._other.selectors = b; -
trip-planner-front/node_modules/critters/src/dom.js
r59329aa re29cc2e 16 16 17 17 import parse5 from 'parse5'; 18 import select from 'css-select'; 18 import { selectAll, selectOne } from 'css-select'; 19 import treeAdapter from 'parse5-htmlparser2-tree-adapter'; 19 20 20 21 // htmlparser2 has a relatively DOM-like tree format, which we'll massage into a DOM elsewhere 21 const treeAdapter = require('parse5-htmlparser2-tree-adapter');22 23 22 const PARSE5_OPTS = { 24 23 treeAdapter … … 31 30 */ 32 31 export function createDocument(html) { 33 const document = parse5.parse(html, PARSE5_OPTS); 32 const document = /** @type {HTMLDocument} */ ( 33 parse5.parse(html, PARSE5_OPTS) 34 ); 34 35 35 36 defineProperties(document, DocumentExtensions); … … 48 49 /** 49 50 * Serialize a Document to an HTML String 50 * @param { Document} document A Document, such as one created via `createDocument()`51 * @param {HTMLDocument} document A Document, such as one created via `createDocument()` 51 52 */ 52 53 export function serializeDocument(document) { … … 54 55 } 55 56 57 /** @typedef {treeAdapter.Document & typeof ElementExtensions} HTMLDocument */ 58 56 59 /** 57 60 * Methods and descriptors to mix into Element.prototype 61 * @private 58 62 */ 59 63 const ElementExtensions = { 60 /** @extends htmlparser2.Element.prototype */64 /** @extends treeAdapter.Element.prototype */ 61 65 62 66 nodeName: { … … 131 135 */ 132 136 const DocumentExtensions = { 133 /** @extends htmlparser2.Document.prototype */137 /** @extends treeAdapter.Document.prototype */ 134 138 135 139 // document is just an Element in htmlparser2, giving it a nodeType of ELEMENT_NODE. … … 196 200 197 201 querySelector(sel) { 198 return select .selectOne(sel, this.documentElement);202 return selectOne(sel, this.documentElement); 199 203 }, 200 204 … … 203 207 return this; 204 208 } 205 return select (sel, this.documentElement);209 return selectAll(sel, this.documentElement); 206 210 } 207 211 }; -
trip-planner-front/node_modules/critters/src/index.d.ts
r59329aa re29cc2e 15 15 */ 16 16 17 declare module 'critters' { 18 export interface Options { 19 path?: string; 20 publicPath?: string; 21 external?: boolean; 22 inlineThreshold?: number; 23 minimumExternalSize?: number; 24 pruneSource?: boolean; 25 mergeStylesheets?: boolean; 26 additionalStylesheets?: string[]; 27 preload?: 'body' | 'media' | 'swap' | 'js' | 'js-lazy'; 28 noscriptFallback?: boolean; 29 inlineFonts?: boolean; 30 preloadFonts?: boolean; 31 fonts?: boolean; 32 keyframes?: string; 33 compress?: boolean; 34 logLevel?: 'info' | 'warn' | 'error' | 'trace' | 'debug' | 'silent'; 35 reduceInlineStyles?: boolean; 36 logger?: Logger; 37 } 17 export default class Critters { 18 /** 19 * Create an instance of Critters with custom options. 20 * The `.process()` method can be called repeatedly to re-use this instance and its cache. 21 */ 22 constructor(options: Options); 23 /** 24 * Process an HTML document to inline critical CSS from its stylesheets. 25 * @param {string} html String containing a full HTML document to be parsed. 26 * @returns {string} A modified copy of the provided HTML with critical CSS inlined. 27 */ 28 process(html: string): Promise<string>; 29 /** 30 * Read the contents of a file from the specified filesystem or disk. 31 * Override this method to customize how stylesheets are loaded. 32 */ 33 readFile(filename: string): Promise<string> | string; 34 /** 35 * Given a stylesheet URL, returns the corresponding CSS asset. 36 * Overriding this method requires doing your own URL normalization, so it's generally better to override `readFile()`. 37 */ 38 getCssAsset(href: string): Promise<string | undefined> | string | undefined; 39 } 38 40 39 export interface Logger { 40 trace?: (message: string) => void; 41 debug?: (message: string) => void; 42 info?: (message: string) => void; 43 warn?: (message: string) => void; 44 error?: (message: string) => void; 45 } 41 export interface Options { 42 path?: string; 43 publicPath?: string; 44 external?: boolean; 45 inlineThreshold?: number; 46 minimumExternalSize?: number; 47 pruneSource?: boolean; 48 mergeStylesheets?: boolean; 49 additionalStylesheets?: string[]; 50 preload?: 'body' | 'media' | 'swap' | 'js' | 'js-lazy'; 51 noscriptFallback?: boolean; 52 inlineFonts?: boolean; 53 preloadFonts?: boolean; 54 fonts?: boolean; 55 keyframes?: string; 56 compress?: boolean; 57 logLevel?: 'info' | 'warn' | 'error' | 'trace' | 'debug' | 'silent'; 58 reduceInlineStyles?: boolean; 59 logger?: Logger; 60 } 46 61 47 class Critters{48 constructor(options: Options);49 process(html: string): Promise<string>;50 }51 52 e xport default Critters;62 export interface Logger { 63 trace?: (message: string) => void; 64 debug?: (message: string) => void; 65 info?: (message: string) => void; 66 warn?: (message: string) => void; 67 error?: (message: string) => void; 53 68 } -
trip-planner-front/node_modules/critters/src/index.js
r59329aa re29cc2e 30 30 /** 31 31 * The mechanism to use for lazy-loading stylesheets. 32 * 32 33 * Note: <kbd>JS</kbd> indicates a strategy requiring JavaScript (falls back to `<noscript>` unless disabled). 33 34 * … … 242 243 .replace(/^\//, ''); 243 244 } 245 246 // Ignore remote stylesheets 247 if (/^https:\/\//.test(normalizedPath) || href.startsWith('//')) { 248 return undefined; 249 } 250 244 251 const filename = path.resolve(outputPath, normalizedPath); 245 252 … … 484 491 } 485 492 }); 493 486 494 // If there are no matched selectors, remove the rule: 487 if ( rule.selectors.length === 0) {495 if (!rule.selector) { 488 496 return false; 489 497 } 490 498 491 if (rule. declarations) {492 for (let i = 0; i < rule. declarations.length; i++) {493 const decl = rule. declarations[i];499 if (rule.nodes) { 500 for (let i = 0; i < rule.nodes.length; i++) { 501 const decl = rule.nodes[i]; 494 502 495 503 // detect used fonts 496 if (decl.prop erty && decl.property.match(/\bfont(-family)?\b/i)) {504 if (decl.prop && decl.prop.match(/\bfont(-family)?\b/i)) { 497 505 criticalFonts += ' ' + decl.value; 498 506 } 499 507 500 508 // detect used keyframes 501 if ( 502 decl.property === 'animation' || 503 decl.property === 'animation-name' 504 ) { 509 if (decl.prop === 'animation' || decl.prop === 'animation-name') { 505 510 // @todo: parse animation declarations and extract only the name. for now we'll do a lazy match. 506 511 const names = decl.value.split(/\s+/); … … 515 520 516 521 // keep font rules, they're handled in the second pass: 517 if (rule.type === ' font-face') return;522 if (rule.type === 'atrule' && rule.name === 'font-face') return; 518 523 519 524 // If there are no remaining rules, remove the whole rule: 520 const rules = rule. rules && rule.rules.filter((rule) => !rule.$$remove);525 const rules = rule.nodes && rule.nodes.filter((rule) => !rule.$$remove); 521 526 return !rules || rules.length !== 0; 522 527 }) … … 547 552 548 553 // prune @keyframes rules 549 if (rule.type === ' keyframes') {554 if (rule.type === 'atrule' && rule.name === 'keyframes') { 550 555 if (keyframesMode === 'none') return false; 551 556 if (keyframesMode === 'all') return true; 552 return criticalKeyframeNames.indexOf(rule. name) !== -1;557 return criticalKeyframeNames.indexOf(rule.params) !== -1; 553 558 } 554 559 555 560 // prune @font-face rules 556 if (rule.type === ' font-face') {561 if (rule.type === 'atrule' && rule.name === 'font-face') { 557 562 let family, src; 558 for (let i = 0; i < rule. declarations.length; i++) {559 const decl = rule. declarations[i];560 if (decl.prop erty=== 'src') {563 for (let i = 0; i < rule.nodes.length; i++) { 564 const decl = rule.nodes[i]; 565 if (decl.prop === 'src') { 561 566 // @todo parse this properly and generate multiple preloads with type="font/woff2" etc 562 567 src = (decl.value.match(/url\s*\(\s*(['"]?)(.+?)\1\s*\)/) || [])[2]; 563 } else if (decl.prop erty=== 'font-family') {568 } else if (decl.prop === 'font-family') { 564 569 family = decl.value; 565 570 } … … 590 595 sheet = serializeStylesheet(ast, { 591 596 compress: this.options.compress !== false 592 }) .trim();597 }); 593 598 594 599 // If all rules were removed, get rid of the style element entirely
Note:
See TracChangeset
for help on using the changeset viewer.