Skip to content

Commit

Permalink
Merge 5ecf96a into ab4c113
Browse files Browse the repository at this point in the history
  • Loading branch information
papandreou committed Aug 26, 2019
2 parents ab4c113 + 5ecf96a commit 1613574
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 78 deletions.
17 changes: 9 additions & 8 deletions lib/extractReferencedCustomPropertyNames.js
@@ -1,16 +1,17 @@
const postcssValuesParser = require('postcss-values-parser');
const postcssValueParser = require('postcss-value-parser');

function extractReferencedCustomPropertyNames(cssValue) {
const tokens = postcssValuesParser(cssValue).tokens;
const rootNode = postcssValueParser(cssValue);
const customPropertyNames = new Set();
for (let i = 0; i < tokens.length - 3; i += 1) {
for (const node of rootNode.nodes) {
if (
tokens[i][1] === 'var' &&
tokens[i + 1][0] === '(' &&
tokens[i + 2][1] === '--' &&
tokens[i + 3][0] === 'word'
node.type === 'function' &&
node.value === 'var' &&
node.nodes.length === 1 &&
node.nodes[0].type === 'word' &&
/^--/.test(node.nodes[0].value)
) {
customPropertyNames.add(`--${tokens[i + 3][1]}`);
customPropertyNames.add(node.nodes[0].value);
}
}
return customPropertyNames;
Expand Down
55 changes: 31 additions & 24 deletions lib/injectSubsetDefinitions.js
@@ -1,34 +1,31 @@
const postcssValuesParser = require('postcss-values-parser');
const unquote = require('./unquote');
const postcssValueParser = require('postcss-value-parser');

function injectSubsetDefinitions(cssValue, webfontNameMap, replaceOriginal) {
const subsetFontNames = new Set(
Object.values(webfontNameMap).map(name => name.toLowerCase())
);
const tokens = postcssValuesParser(cssValue).tokens;
let resultStr = '';
const rootNode = postcssValueParser(cssValue);
let isPreceededByWords = false;
for (let i = 0; i < tokens.length; i += 1) {
const token = tokens[i];
for (const [i, node] of rootNode.nodes.entries()) {
let possibleFontFamily;
let lastFontFamilyTokenIndex = i;
if (token[0] === 'string') {
possibleFontFamily = unquote(token[1]);
} else if (token[0] === 'word') {
if (node.type === 'string') {
possibleFontFamily = node.value;
} else if (node.type === 'word' || node.type === 'space') {
if (!isPreceededByWords) {
const wordSequence = [];
for (let j = i; j < tokens.length; j += 1) {
if (tokens[j][0] === 'word') {
wordSequence.push(tokens[j][1]);
for (let j = i; j < rootNode.nodes.length; j += 1) {
if (rootNode.nodes[j].type === 'word') {
wordSequence.push(rootNode.nodes[j].value);
lastFontFamilyTokenIndex = j;
} else if (tokens[j][0] !== 'space') {
} else if (rootNode.nodes[j].type !== 'space') {
break;
}
}
possibleFontFamily = wordSequence.join(' ');
}
isPreceededByWords = true;
} else if (token[0] !== 'space') {
} else {
isPreceededByWords = false;
}
if (possibleFontFamily) {
Expand All @@ -37,22 +34,32 @@ function injectSubsetDefinitions(cssValue, webfontNameMap, replaceOriginal) {
// Bail out, a subset font is already listed
return cssValue;
} else if (webfontNameMap[possibleFontFamilyLowerCase]) {
resultStr += `'${webfontNameMap[possibleFontFamilyLowerCase].replace(
/'/g,
"\\'"
)}'`;
const newToken = {
type: 'string',
value: webfontNameMap[possibleFontFamilyLowerCase].replace(
/'/g,
"\\'"
),
quote: "'"
};
if (replaceOriginal) {
tokens.splice(i, lastFontFamilyTokenIndex - i + 1);
i -= 1;
continue;
rootNode.nodes.splice(
rootNode.nodes.indexOf(node),
lastFontFamilyTokenIndex - i + 1,
newToken
);
} else {
resultStr += ', ';
rootNode.nodes.splice(rootNode.nodes.indexOf(node), 0, newToken, {
type: 'div',
value: ',',
after: ' '
});
}
return postcssValueParser.stringify(rootNode);
}
}
resultStr += token[1];
}
return resultStr;
return cssValue;
}

module.exports = injectSubsetDefinitions;
60 changes: 16 additions & 44 deletions lib/stripLocalTokens.js
@@ -1,51 +1,23 @@
const postcssValuesParser = require('postcss-values-parser');
const postcssValueParser = require('postcss-value-parser');

module.exports = function stripLocalTokens(cssValue) {
const tokens = postcssValuesParser(cssValue).tokens;
for (let i = 0; i < tokens.length - 3; i += 1) {
if (
tokens[i][0] === 'word' &&
tokens[i][1].toLowerCase() === 'local' &&
tokens[i + 1][0] === '(' &&
(tokens[i + 2][0] === 'string' || tokens[i + 2][0] === 'word') &&
tokens[i + 3][0] === ')'
) {
let startIndex = i;
let numTokensToRemove = 4;
let commaBefore = false;
let commaAfter = false;
while (
startIndex > 0 &&
['space', 'comma'].includes(tokens[startIndex - 1][0])
) {
if (tokens[startIndex - 1][0] === 'comma') {
commaBefore = true;
const rootNode = postcssValueParser(cssValue);
for (let i = 0; i < rootNode.nodes.length; i += 1) {
const node = rootNode.nodes[i];
if (node.type === 'function' && node.value.toLowerCase() === 'local') {
let numTokensToRemove = 1;
if (i + 1 < rootNode.nodes.length) {
const nextToken = rootNode.nodes[i + 1];
if (nextToken.type === 'div' && nextToken.value === ',') {
numTokensToRemove += 1;
if (i + 2 < rootNode.nodes.length) {
rootNode.nodes[i + 2].before = node.before;
}
}
startIndex -= 1;
numTokensToRemove += 1;
}

while (
startIndex + numTokensToRemove < tokens.length &&
['space', 'comma'].includes(tokens[startIndex + numTokensToRemove][0])
) {
if (tokens[startIndex + numTokensToRemove][0] === 'comma') {
commaAfter = true;
}
numTokensToRemove += 1;
}
if (commaBefore && commaAfter) {
tokens.splice(
startIndex,
numTokensToRemove,
['comma', ','],
['space', ' ']
);
} else {
tokens.splice(startIndex, numTokensToRemove);
}
i = startIndex - 1;
rootNode.nodes.splice(i, numTokensToRemove);
i -= 1;
}
}
return tokens.map(token => token[1]).join('');
return postcssValueParser.stringify(rootNode);
};
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -51,7 +51,7 @@
"font-tracer": "^1.1.0",
"fontkit": "^1.8.0",
"lodash.groupby": "^4.6.0",
"postcss-values-parser": "^2.0.1",
"postcss-value-parser": "^4.0.2",
"pretty-bytes": "^5.1.0",
"urltools": "^0.4.1",
"yargs": "^12.0.2"
Expand Down
33 changes: 33 additions & 0 deletions test/extractReferencedCustomPropertyNames.js
@@ -0,0 +1,33 @@
const expect = require('unexpected')
.clone()
.use(require('unexpected-set'));

const extractReferencedCustomPropertyNames = require('../lib/extractReferencedCustomPropertyNames');

describe('extractReferencedCustomPropertyNames', function() {
it('should return the empty set when no custom properties are referenced', function() {
expect(
extractReferencedCustomPropertyNames('foo(bar), local(abc), bla-bla'),
'to equal',
new Set()
);
});

it('should return the name of a referenced custom property', function() {
expect(
extractReferencedCustomPropertyNames('foo(bar), var(--abc), bla-bla'),
'to equal',
new Set(['--abc'])
);
});

it('should return the names of multiple referenced custom properties', function() {
expect(
extractReferencedCustomPropertyNames(
'foo(bar), var(--abc), bla-bla, var(--def)'
),
'to equal',
new Set(['--abc', '--def'])
);
});
});
2 changes: 1 addition & 1 deletion test/stripLocalTokens.js
Expand Up @@ -61,7 +61,7 @@ describe('stripLocalTokens', function() {
expect(
`url('foo') , local(bar) , local(quux) , url('baz')`,
'to come out as',
"url('foo'), url('baz')"
"url('foo') , url('baz')"
);
});

Expand Down

0 comments on commit 1613574

Please sign in to comment.