Skip to content

Commit

Permalink
fix: values should be replaced in selectors as well
Browse files Browse the repository at this point in the history
  • Loading branch information
jquense committed Feb 15, 2019
1 parent 1383b62 commit e0baf2f
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 107 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"autotest": "chokidar src test -c 'npm test'",
"cover": "nyc mocha",
"travis": "yarn lint && yarn cover",
"prepublish": "yarn test"
"prepublishOnly": "yarn test"
},
"repository": {
"type": "git",
Expand All @@ -34,12 +34,12 @@
"chokidar-cli": "^1.0.1",
"codecov.io": "^0.1.2",
"coveralls": "^3.0.2",
"mocha": "^5.2.0",
"eslint": "^5.9.0",
"mocha": "^5.2.0",
"nyc": "^13.1.0"
},
"dependencies": {
"icss-replace-symbols": "^1.1.0",
"icss-utils": "^4.0.0",
"postcss": "^7.0.6"
}
}
99 changes: 49 additions & 50 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,119 +1,118 @@
'use strict';
'use strict'

const postcss = require('postcss');
const ICSSReplaceSymbols = require('icss-replace-symbols');
const replaceSymbols = require('icss-replace-symbols');
const postcss = require('postcss')
const ICSSUtils = require('icss-utils')

const matchImports = /^(.+?|\([\s\S]+?\))\s+from\s+("[^"]*"|'[^']*'|[\w-]+)$/;
const matchValueDefinition = /(?:\s+|^)([\w-]+):?\s+(.+?)\s*$/g;
const matchImport = /^([\w-]+)(?:\s+as\s+([\w-]+))?/;
const matchImports = /^(.+?|\([\s\S]+?\))\s+from\s+("[^"]*"|'[^']*'|[\w-]+)$/
const matchValueDefinition = /(?:\s+|^)([\w-]+):?\s+(.+?)\s*$/g
const matchImport = /^([\w-]+)(?:\s+as\s+([\w-]+))?/

let options = {};
let importIndex = 0;
let options = {}
let importIndex = 0
let createImportedName =
(options && options.createImportedName) ||
((importName /*, path*/) =>
`i__const_${importName.replace(/\W/g, '_')}_${importIndex++}`);
`i__const_${importName.replace(/\W/g, '_')}_${importIndex++}`)

module.exports = postcss.plugin(
'postcss-modules-values',
() => (css, result) => {
const importAliases = [];
const definitions = {};
const importAliases = []
const definitions = {}

const addDefinition = atRule => {
let matches;
let matches
while ((matches = matchValueDefinition.exec(atRule.params))) {
let [, /*match*/ key, value] = matches;
let [, /*match*/ key, value] = matches
// Add to the definitions, knowing that values can refer to each other
definitions[key] = replaceSymbols.replaceAll(definitions, value);
atRule.remove();
definitions[key] = ICSSUtils.replaceValueSymbols(value, definitions)
atRule.remove()
}
};
}

const addImport = atRule => {
const matches = matchImports.exec(atRule.params);
const matches = matchImports.exec(atRule.params)
if (matches) {
let [, /*match*/ aliases, path] = matches;
let [, /*match*/ aliases, path] = matches
// We can use constants for path names
if (definitions[path]) {
path = definitions[path];
path = definitions[path]
}
const imports = aliases
.replace(/^\(\s*([\s\S]+)\s*\)$/, '$1')
.split(/\s*,\s*/)
.map(alias => {
const tokens = matchImport.exec(alias);
const tokens = matchImport.exec(alias)
if (tokens) {
const [, /*match*/ theirName, myName = theirName] = tokens;
const importedName = createImportedName(myName);
definitions[myName] = importedName;
return { theirName, importedName };
const [, /*match*/ theirName, myName = theirName] = tokens
const importedName = createImportedName(myName)
definitions[myName] = importedName
return { theirName, importedName }
} else {
throw new Error(`@import statement "${alias}" is invalid!`);
throw new Error(`@import statement "${alias}" is invalid!`)
}
});
importAliases.push({ path, imports });
atRule.remove();
})
importAliases.push({ path, imports })
atRule.remove()
}
};
}

/* Look at all the @value statements and treat them as locals or as imports */
css.walkAtRules('value', atRule => {
if (matchImports.exec(atRule.params)) {
addImport(atRule);
addImport(atRule)
} else {
if (atRule.params.indexOf('@value') !== -1) {
result.warn('Invalid value definition: ' + atRule.params);
result.warn('Invalid value definition: ' + atRule.params)
}

addDefinition(atRule);
addDefinition(atRule)
}
});
})

/* We want to export anything defined by now, but don't add it to the CSS yet or
it well get picked up by the replacement stuff */
const exportDeclarations = Object.keys(definitions).map(key =>
postcss.decl({
value: definitions[key],
prop: key,
raws: { before: '\n ' }
raws: { before: '\n ' },
})
);
)

/* If we have no definitions, don't continue */
if (!Object.keys(definitions).length) {
return;
return
}

/* Perform replacements */
ICSSReplaceSymbols.default(css, definitions);
ICSSUtils.replaceSymbols(css, definitions)

/* Add export rules if any */
if (exportDeclarations.length > 0) {
const exportRule = postcss.rule({
selector: ':export',
raws: { after: '\n' }
});
exportRule.append(exportDeclarations);
css.prepend(exportRule);
raws: { after: '\n' },
})
exportRule.append(exportDeclarations)
css.prepend(exportRule)
}

/* Add import rules */
importAliases.reverse().forEach(({ path, imports }) => {
const importRule = postcss.rule({
selector: `:import(${path})`,
raws: { after: '\n' }
});
raws: { after: '\n' },
})
imports.forEach(({ theirName, importedName }) => {
importRule.append({
value: theirName,
prop: importedName,
raws: { before: '\n ' }
});
});
raws: { before: '\n ' },
})
})

css.prepend(importRule);
});
css.prepend(importRule)
})
}
);
)
Loading

0 comments on commit e0baf2f

Please sign in to comment.