Skip to content

Commit

Permalink
Add jest and prettier
Browse files Browse the repository at this point in the history
  • Loading branch information
TrySound committed May 23, 2017
1 parent 7f4028c commit 3751427
Show file tree
Hide file tree
Showing 15 changed files with 3,634 additions and 277 deletions.
23 changes: 0 additions & 23 deletions .eslintrc

This file was deleted.

4 changes: 1 addition & 3 deletions .gitignore
@@ -1,5 +1,3 @@
.DS_Store
node_modules
coverage
lib
node_modules
yarn.lock
1 change: 0 additions & 1 deletion .travis.yml
Expand Up @@ -3,7 +3,6 @@ node_js:
- "4"
- "6"
- "node"
script: npm run travis

after_success:
- cat ./coverage/lcov.info | node_modules/.bin/coveralls --verbose
Expand Down
49 changes: 31 additions & 18 deletions package.json
Expand Up @@ -3,17 +3,32 @@
"version": "1.2.0",
"description": "A CSS Modules transform to extract local aliases for inline imports",
"main": "lib/index.js",
"files": [
"lib"
],
"scripts": {
"lint": "eslint src",
"build": "babel --out-dir lib src",
"watch": "chokidar src -c 'npm run build'",
"posttest": "npm run lint && npm run build",
"test": "mocha --compilers js:babel/register",
"autotest": "chokidar src test -c 'npm test'",
"precover": "npm run lint && npm run build",
"cover": "babel-istanbul cover node_modules/.bin/_mocha",
"travis": "npm run cover -- --report lcovonly",
"prepublish": "npm run build"
"test": "jest --coverage",
"precommit": "lint-staged",
"prepublish": "yarn run test && yarn run build"
},
"lint-staged": {
"*.js": [
"prettier --single-quote --no-semi --write",
"git add"
]
},
"babel": {
"presets": [
[
"env",
{
"targets": {
"node": 4
}
}
]
]
},
"repository": {
"type": "git",
Expand All @@ -24,9 +39,6 @@
"postcss",
"plugin"
],
"files": [
"lib"
],
"author": "Glen Maddern",
"license": "ISC",
"bugs": {
Expand All @@ -37,14 +49,15 @@
"postcss": "^6.0.1"
},
"devDependencies": {
"babel": "^5.4.7",
"babel-cli": "^6.24.1",
"babel-eslint": "^7.2.2",
"babel-istanbul": "^0.4.0",
"babelify": "^7.3.0",
"chokidar-cli": "^1.0.1",
"babel-jest": "^20.0.3",
"babel-preset-env": "^1.5.1",
"codecov.io": "^0.1.2",
"coveralls": "^2.11.2",
"eslint": "^1.5.0",
"mocha": "^3.1.2"
"husky": "^0.13.3",
"jest": "^20.0.3",
"lint-staged": "^3.4.2",
"prettier": "^1.3.1"
}
}
163 changes: 87 additions & 76 deletions src/index.js
@@ -1,19 +1,19 @@
import postcss from 'postcss';
import topologicalSort from './topologicalSort';
const postcss = require('postcss')
const topologicalSort = require('./topologicalSort')

const declWhitelist = ['composes'];
const declFilter = new RegExp( `^(${declWhitelist.join( '|' )})$` );
const matchImports = /^(.+?)\s+from\s+(?:"([^"]+)"|'([^']+)'|(global))$/;
const icssImport = /^:import\((?:"([^"]+)"|'([^']+)')\)/;
const declWhitelist = ['composes']
const declFilter = new RegExp(`^(${declWhitelist.join('|')})$`)
const matchImports = /^(.+?)\s+from\s+(?:"([^"]+)"|'([^']+)'|(global))$/
const icssImport = /^:import\((?:"([^"]+)"|'([^']+)')\)/

const VISITED_MARKER = 1;
const VISITED_MARKER = 1

function createParentName(rule, root) {
return `__${root.index(rule.parent)}_${rule.selector}`;
return `__${root.index(rule.parent)}_${rule.selector}`
}

function serializeImports(imports) {
return imports.map(importPath => '`' + importPath + '`').join(', ');
return imports.map(importPath => '`' + importPath + '`').join(', ')
}

/**
Expand All @@ -38,132 +38,143 @@ function serializeImports(imports) {
* }
*/
function addImportToGraph(importId, parentId, graph, visited) {
const siblingsId = parentId + '_' + 'siblings';
const visitedId = parentId + '_' + importId;
const siblingsId = parentId + '_' + 'siblings'
const visitedId = parentId + '_' + importId

if (visited[visitedId] !== VISITED_MARKER) {
if (!Array.isArray(visited[siblingsId])) visited[siblingsId] = [];
if (!Array.isArray(visited[siblingsId])) visited[siblingsId] = []

const siblings = visited[siblingsId];
const siblings = visited[siblingsId]

if (Array.isArray(graph[importId]))
graph[importId] = graph[importId].concat(siblings);
else
graph[importId] = siblings.slice();
graph[importId] = graph[importId].concat(siblings)
else graph[importId] = siblings.slice()

visited[visitedId] = VISITED_MARKER;
siblings.push(importId);
visited[visitedId] = VISITED_MARKER
siblings.push(importId)
}
}

const processor = postcss.plugin('modules-extract-imports', function (options = {}) {
const failOnWrongOrder = options.failOnWrongOrder;
module.exports = postcss.plugin('modules-extract-imports', function(
options = {}
) {
const failOnWrongOrder = options.failOnWrongOrder

return css => {
const graph = {};
const visited = {};
const graph = {}
const visited = {}

const existingImports = {};
const importDecls = {};
const imports = {};
const existingImports = {}
const importDecls = {}
const imports = {}

let importIndex = 0;
let importIndex = 0

const createImportedName = typeof options.createImportedName !== 'function'
? (importName/*, path*/) => `i__imported_${importName.replace(/\W/g, '_')}_${importIndex++}`
: options.createImportedName;
? (importName /*, path*/) =>
`i__imported_${importName.replace(/\W/g, '_')}_${importIndex++}`
: options.createImportedName

// Check the existing imports order and save refs
css.walkRules(rule => {
const matches = icssImport.exec(rule.selector);
const matches = icssImport.exec(rule.selector)

if (matches) {
const [/*match*/, doubleQuotePath, singleQuotePath] = matches;
const importPath = doubleQuotePath || singleQuotePath;
const [, /*match*/ doubleQuotePath, singleQuotePath] = matches
const importPath = doubleQuotePath || singleQuotePath

addImportToGraph(importPath, 'root', graph, visited);
addImportToGraph(importPath, 'root', graph, visited)

existingImports[importPath] = rule;
existingImports[importPath] = rule
}
});
})

// Find any declaration that supports imports
css.walkDecls(declFilter, decl => {
let matches = decl.value.match(matchImports);
let tmpSymbols;
let matches = decl.value.match(matchImports)
let tmpSymbols

if (matches) {
let [/*match*/, symbols, doubleQuotePath, singleQuotePath, global] = matches;
let [
,
/*match*/ symbols,
doubleQuotePath,
singleQuotePath,
global
] = matches

if (global) {
// Composing globals simply means changing these classes to wrap them in global(name)
tmpSymbols = symbols.split(/\s+/).map(s => `global(${s})`);
tmpSymbols = symbols.split(/\s+/).map(s => `global(${s})`)
} else {
const importPath = doubleQuotePath || singleQuotePath;
const parentRule = createParentName(decl.parent, css);
const importPath = doubleQuotePath || singleQuotePath
const parentRule = createParentName(decl.parent, css)

addImportToGraph(importPath, parentRule, graph, visited);
addImportToGraph(importPath, parentRule, graph, visited)

importDecls[importPath] = decl;
imports[importPath] = imports[importPath] || {};
importDecls[importPath] = decl
imports[importPath] = imports[importPath] || {}

tmpSymbols = symbols.split(/\s+/).map(s => {
if (!imports[importPath][s]) {
imports[importPath][s] = createImportedName(s, importPath);
imports[importPath][s] = createImportedName(s, importPath)
}

return imports[importPath][s];
});
return imports[importPath][s]
})
}

decl.value = tmpSymbols.join(' ');
decl.value = tmpSymbols.join(' ')
}
});
})

const importsOrder = topologicalSort(graph, failOnWrongOrder);
const importsOrder = topologicalSort(graph, failOnWrongOrder)

if (importsOrder instanceof Error) {
const importPath = importsOrder.nodes.find(importPath => importDecls.hasOwnProperty(importPath));
const decl = importDecls[importPath];
const importPath = importsOrder.nodes.find(importPath =>
importDecls.hasOwnProperty(importPath)
)
const decl = importDecls[importPath]

const errMsg = 'Failed to resolve order of composed modules ' + serializeImports(importsOrder.nodes) + '.';
const errMsg =
'Failed to resolve order of composed modules ' +
serializeImports(importsOrder.nodes) +
'.'

throw decl.error(errMsg, {
plugin: 'modules-extract-imports',
word: 'composes',
});
word: 'composes'
})
}

let lastImportRule;
let lastImportRule
importsOrder.forEach(path => {
const importedSymbols = imports[path];
let rule = existingImports[path];
const importedSymbols = imports[path]
let rule = existingImports[path]

if (!rule && importedSymbols) {
rule = postcss.rule({
selector: `:import("${path}")`,
raws: {after: '\n'},
});
raws: { after: '\n' }
})

if (lastImportRule)
css.insertAfter(lastImportRule, rule);
else
css.prepend(rule);
if (lastImportRule) css.insertAfter(lastImportRule, rule)
else css.prepend(rule)
}

lastImportRule = rule;
lastImportRule = rule

if (!importedSymbols) return;
if (!importedSymbols) return

Object.keys(importedSymbols).forEach(importedSymbol => {
rule.append(postcss.decl({
value: importedSymbol,
prop: importedSymbols[importedSymbol],
raws: {before: '\n '},
}));
});
});
};
});

export default processor;
rule.append(
postcss.decl({
value: importedSymbol,
prop: importedSymbols[importedSymbol],
raws: { before: '\n ' }
})
)
})
})
}
})

0 comments on commit 3751427

Please sign in to comment.