Comparing version 1.3.14 to 1.4.0
@@ -0,1 +1,11 @@ | ||
<a name="1.4.0"></a> | ||
# [1.4.0](https://github.com/kei-ito/esifycss/compare/v1.3.14...v1.4.0) (2020-01-18) | ||
### Features | ||
* output css ([#55](https://github.com/kei-ito/esifycss/issues/55)) ([701b733](https://github.com/kei-ito/esifycss/commit/701b733)) | ||
<a name="1.3.14"></a> | ||
@@ -2,0 +12,0 @@ ## [1.3.14](https://github.com/kei-ito/esifycss/compare/v1.3.13...v1.3.14) (2020-01-06) |
@@ -14,3 +14,5 @@ #!/usr/bin/env node | ||
.usage('[options] <include ...>') | ||
.option('--helper <path>', 'A path to the helper script.') | ||
.option('--helper <path>', 'A path where the helper script will be output. You can\'t use --helper with --css.') | ||
.option('--css <path>', 'A path where the css will be output. You can\'t use --css with --helper.') | ||
.option('--ext <ext>', 'An extension of scripts generated from css.') | ||
.option('--config <path>', 'A path to configuration files.') | ||
@@ -17,0 +19,0 @@ .option('--exclude <path ...>', 'Paths or patterns to be excluded.') |
@@ -9,2 +9,4 @@ "use strict"; | ||
helper: program.helper, | ||
css: program.css, | ||
ext: program.ext, | ||
exclude: program.exclude, | ||
@@ -11,0 +13,0 @@ esifycssPluginParameter: { |
@@ -7,7 +7,7 @@ "use strict"; | ||
for (let index = cssRanges.length; index--;) { | ||
const { css, start, end } = cssRanges[index]; | ||
const range = cssRanges[index]; | ||
minified = [ | ||
minified.slice(0, start), | ||
JSON.stringify(encodeString_1.encodeString(css, identifier)), | ||
minified.slice(end), | ||
minified.slice(0, range.start), | ||
JSON.stringify(encodeString_1.encodeString(range.css, identifier)), | ||
minified.slice(range.end), | ||
].join(''); | ||
@@ -14,0 +14,0 @@ } |
@@ -1,1 +0,4 @@ | ||
export declare const minifyScripts: (helperScript: string, files: string[]) => Promise<void>; | ||
export declare const minifyScripts: (output: { | ||
type: "script" | "css"; | ||
path: string; | ||
}, files: string[]) => Promise<void>; |
@@ -8,12 +8,29 @@ "use strict"; | ||
const setDictionary_1 = require("./setDictionary"); | ||
exports.minifyScripts = async (helperScript, files) => { | ||
const removeAddStyle_1 = require("./removeAddStyle"); | ||
exports.minifyScripts = async (output, files) => { | ||
const parseResult = await parseScripts_1.parseScripts(files); | ||
const identifier = createOptimizedIdentifier_1.createOptimizedIdentifier(parseResult.tokens); | ||
await Promise.all([...parseResult.scripts] | ||
.map(async ([file, { script, cssRanges }]) => { | ||
const minified = minifyCSSInScript_1.minifyCSSInScript(script, cssRanges, identifier); | ||
await fs_1.writeFile(file, minified); | ||
})); | ||
const helperCode = setDictionary_1.setDictionary(await fs_1.readFile(helperScript, 'utf8'), identifier.idList); | ||
await fs_1.writeFile(helperScript, helperCode); | ||
const outputPath = output.path; | ||
if (output.type === 'script') { | ||
await Promise.all([...parseResult.scripts].map(async ([file, { script, cssRanges }]) => { | ||
const minified = minifyCSSInScript_1.minifyCSSInScript(script, cssRanges, identifier); | ||
await fs_1.writeFile(file, minified); | ||
})); | ||
const helperCode = setDictionary_1.setDictionary(await fs_1.readFile(outputPath, 'utf8'), identifier.idList); | ||
await fs_1.writeFile(outputPath, helperCode); | ||
} | ||
else { | ||
const cssList = await Promise.all([...parseResult.scripts].map(async ([file, { script, cssRanges }]) => { | ||
const cssList = []; | ||
let code = script; | ||
for (let index = cssRanges.length; index--;) { | ||
const range = cssRanges[index]; | ||
cssList[index] = range.css; | ||
code = `${code.slice(0, range.start)}${code.slice(range.end).replace(/^\s*,\s*/, '')}`; | ||
} | ||
await fs_1.writeFile(file, removeAddStyle_1.removeAddStyle(code)); | ||
return cssList.join('\n'); | ||
})); | ||
await fs_1.writeFile(outputPath, cssList.join('\n')); | ||
} | ||
}; |
@@ -1,3 +0,2 @@ | ||
import { ISessionConfiguration, ISessionOptions, IReadonlyWatchOptions } from './types'; | ||
export declare const getChokidarOptions: (parameters: ISessionOptions) => IReadonlyWatchOptions; | ||
import { ISessionConfiguration, ISessionOptions } from './types'; | ||
export declare const getSessionConfiguration: (parameters: ISessionOptions) => ISessionConfiguration; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const path = require("path"); | ||
const plugin_1 = require("../postcssPlugin/plugin"); | ||
const ensureArray_1 = require("../util/ensureArray"); | ||
const getHash_1 = require("../util/getHash"); | ||
exports.getChokidarOptions = (parameters) => ({ | ||
useFsEvents: false, | ||
...parameters.chokidar, | ||
ignored: [ | ||
...ensureArray_1.ensureArray(parameters.chokidar && parameters.chokidar.ignored), | ||
...ensureArray_1.ensureArray(parameters.exclude), | ||
], | ||
ignoreInitial: false, | ||
}); | ||
const getChokidarOptions_1 = require("./getChokidarOptions"); | ||
const getOutputOption_1 = require("./getOutputOption"); | ||
const getExtensionOption_1 = require("./getExtensionOption"); | ||
const getIncludePatterns_1 = require("./getIncludePatterns"); | ||
exports.getSessionConfiguration = (parameters) => { | ||
const include = ensureArray_1.ensureArray(parameters.include || '*'); | ||
const extensions = new Set(parameters.extensions || ['.css']); | ||
const helper = parameters.helper || `helper.${getHash_1.getHash(include.join(','))}.css.js`; | ||
if (!path.extname(helper)) { | ||
throw new Error(`helper should have an extension (e.g. ".js", ".ts"): ${helper}`); | ||
} | ||
const include = getIncludePatterns_1.getIncludePatterns({ | ||
include: ensureArray_1.ensureArray(parameters.include || '*'), | ||
extensions: parameters.extensions || ['.css'], | ||
}); | ||
const output = getOutputOption_1.getOutputOption(parameters, include); | ||
return { | ||
watch: Boolean(parameters.watch), | ||
helper, | ||
extensions, | ||
ext: path.extname(helper), | ||
output, | ||
path: include, | ||
chokidar: exports.getChokidarOptions(parameters), | ||
ext: getExtensionOption_1.getExtensionOption(parameters, output), | ||
chokidar: getChokidarOptions_1.getChokidarOptions(parameters), | ||
stdout: parameters.stdout || process.stdout, | ||
@@ -31,0 +22,0 @@ stderr: parameters.stderr || process.stderr, |
@@ -11,7 +11,7 @@ /// <reference types="node" /> | ||
protected initialTask: Array<Promise<void>> | null; | ||
protected get helperScriptPath(): string; | ||
protected previousProcess?: Promise<void>; | ||
protected get helperPath(): string; | ||
constructor(parameters?: ISessionOptions); | ||
start(): Promise<void>; | ||
stop(): Promise<void>; | ||
getHelperScript(): Promise<string>; | ||
outputHelperScript(): Promise<void>; | ||
@@ -18,0 +18,0 @@ processCSS(filePath: string): Promise<{ |
@@ -13,2 +13,3 @@ "use strict"; | ||
const minifyScripts_1 = require("../minifier/minifyScripts"); | ||
const createExposedPromise_1 = require("../util/createExposedPromise"); | ||
class Session { | ||
@@ -20,3 +21,3 @@ constructor(parameters = {}) { | ||
} | ||
get helperScriptPath() { | ||
get helperPath() { | ||
const srcDirectory = path.join(__dirname, '..', 'helper'); | ||
@@ -32,10 +33,11 @@ return path.join(srcDirectory, `index${this.configuration.ext}`); | ||
} | ||
async getHelperScript() { | ||
const scriptCode = await fs_1.readFile(this.helperScriptPath); | ||
return `${scriptCode}`; | ||
} | ||
async outputHelperScript() { | ||
await fs_1.copyFile(this.helperScriptPath, this.configuration.helper); | ||
if (this.configuration.output.type === 'script') { | ||
await fs_1.copyFile(this.helperPath, this.configuration.output.path); | ||
} | ||
} | ||
async processCSS(filePath) { | ||
await this.previousProcess; | ||
const exposedPromise = createExposedPromise_1.createExposedPromise(); | ||
this.previousProcess = exposedPromise.promise; | ||
const postcssResult = await parseCSS_1.parseCSS({ | ||
@@ -45,11 +47,16 @@ plugins: this.configuration.postcssPlugins, | ||
file: filePath, | ||
}) | ||
.catch((error) => { | ||
exposedPromise.resolve(); | ||
throw error; | ||
}); | ||
const pluginResult = extractPluginResult_1.extractPluginResult(postcssResult); | ||
const scriptPath = path.join(`${filePath}${this.configuration.ext}`); | ||
const outputPath = path.join(`${filePath}${this.configuration.ext}`); | ||
this.processedFiles.add(filePath); | ||
const code = generateScript_1.generateScript(scriptPath, this.configuration.helper, pluginResult, postcssResult.root); | ||
return { dest: scriptPath, code }; | ||
const code = generateScript_1.generateScript(outputPath, this.configuration.output.path, pluginResult, postcssResult.root); | ||
exposedPromise.resolve(); | ||
return { dest: outputPath, code }; | ||
} | ||
async minifyScripts() { | ||
await minifyScripts_1.minifyScripts(this.configuration.helper, [...this.processedFiles].map((file) => `${file}${this.configuration.ext}`)); | ||
await minifyScripts_1.minifyScripts(this.configuration.output, [...this.processedFiles].map((file) => `${file}${this.configuration.ext}`)); | ||
} | ||
@@ -63,11 +70,6 @@ async startWatcher() { | ||
.on('all', (eventName, file, stats) => { | ||
if (this.configuration.extensions.has(path.extname(file))) { | ||
this.onFileEvent(eventName, file, stats) | ||
.catch((error) => { | ||
watcher.emit('error', error); | ||
}); | ||
} | ||
else { | ||
watcher.unwatch(file); | ||
} | ||
this.onFileEvent(eventName, file, stats) | ||
.catch((error) => { | ||
watcher.emit('error', error); | ||
}); | ||
}); | ||
@@ -132,7 +134,7 @@ await waitForInitialScanCompletion_1.waitForInitialScanCompletion(this.watcher); | ||
async onUnlink(file) { | ||
const scriptPath = path.join(`${file}${this.configuration.ext}`); | ||
const outputPath = path.join(`${file}${this.configuration.ext}`); | ||
this.processedFiles.delete(file); | ||
await fs_1.deleteFile(scriptPath, this.configuration.stdout); | ||
await fs_1.deleteFile(outputPath, this.configuration.stdout); | ||
} | ||
} | ||
exports.Session = Session; |
@@ -12,2 +12,4 @@ /// <reference types="node" /> | ||
helper?: string; | ||
ext?: string; | ||
css?: string; | ||
watch?: boolean; | ||
@@ -24,6 +26,9 @@ chokidar?: chokidar.WatchOptions; | ||
} | ||
export interface ISessionOutput { | ||
type: 'script' | 'css'; | ||
path: string; | ||
} | ||
export interface ISessionConfiguration { | ||
readonly watch: boolean; | ||
readonly helper: string; | ||
readonly extensions: ReadonlySet<string>; | ||
readonly output: ISessionOutput; | ||
readonly ext: string; | ||
@@ -30,0 +35,0 @@ readonly path: ReadonlyArray<string>; |
{ | ||
"name": "esifycss", | ||
"version": "1.3.14", | ||
"version": "1.4.0", | ||
"description": "Generates .js or .ts exports class names and custom properties", | ||
@@ -12,3 +12,3 @@ "author": { | ||
"engines": { | ||
"node": ">=8" | ||
"node": ">=10" | ||
}, | ||
@@ -57,3 +57,3 @@ "repository": "kei-ito/esifycss", | ||
"chokidar": "^3.3.1", | ||
"commander": "^4.0.1", | ||
"commander": "^4.1.0", | ||
"postcss": "^7.0.26", | ||
@@ -64,3 +64,3 @@ "postcss-selector-parser": "^6.0.2", | ||
"devDependencies": { | ||
"@commitlint/cli": "^8.3.4", | ||
"@commitlint/cli": "^8.3.5", | ||
"@commitlint/config-conventional": "^8.3.4", | ||
@@ -73,13 +73,13 @@ "@nlib/lint": "^3.17.0", | ||
"@types/jsdom": "^12.2.4", | ||
"@types/micromatch": "^3.1.1", | ||
"@types/micromatch": "^4.0.0", | ||
"@types/node": "^12.12.24", | ||
"@types/postcss-scss": "file:@types/postcss-scss", | ||
"@types/selenium-webdriver": "^4.0.6", | ||
"@typescript-eslint/eslint-plugin": "^2.14.0", | ||
"@typescript-eslint/parser": "^2.14.0", | ||
"@typescript-eslint/eslint-plugin": "^2.16.0", | ||
"@typescript-eslint/parser": "^2.16.0", | ||
"ava": "^2.4.0", | ||
"browserstack-local": "^1.4.3", | ||
"browserstack-local": "^1.4.4", | ||
"conventional-changelog-cli": "^2.0.31", | ||
"eslint": "^6.8.0", | ||
"husky": "^3.1.0", | ||
"husky": "^4.0.10", | ||
"lint-staged": "^9.5.0", | ||
@@ -89,6 +89,6 @@ "npm-run-all": "^4.1.5", | ||
"rimraf": "^3.0.0", | ||
"rollup": "^1.28.0", | ||
"rollup": "^1.29.0", | ||
"selenium-webdriver": "^4.0.0-alpha.5", | ||
"ts-node": "^8.5.4", | ||
"typescript": "^3.7.4" | ||
"ts-node": "^8.6.2", | ||
"typescript": "^3.7.5" | ||
}, | ||
@@ -141,2 +141,3 @@ "ava": { | ||
"rules": { | ||
"no-console": "off", | ||
"no-process-env": "off", | ||
@@ -186,2 +187,3 @@ "max-lines-per-function": "off", | ||
"files": [ | ||
"src/util/createExposedPromise.ts", | ||
"src/util/tokenizeString.ts", | ||
@@ -188,0 +190,0 @@ "src/minifier/extractCSSFromScript.ts" |
@@ -121,3 +121,5 @@ # EsifyCSS | ||
-V, --version output the version number | ||
--helper <path> A path to the helper script. | ||
--helper <path> A path where the helper script will be output. You can't use --helper with --css. | ||
--css <path> A path where the css will be output. You can't use --css with --helper. | ||
--ext <ext> An extension of scripts generated from css. | ||
--config <path> A path to configuration files. | ||
@@ -180,3 +182,3 @@ --exclude <path ...> Paths or patterns to be excluded. | ||
* Pattern(s) to be included | ||
* @default "** / *.css" | ||
* @default "*" | ||
*/ | ||
@@ -186,8 +188,15 @@ include?: string | Array<string>, | ||
* Pattern(s) to be excluded. | ||
* @default [] | ||
* @default ['node_modules'] | ||
*/ | ||
exclude?: anymatch.Matcher, | ||
/** | ||
* File extension(s) to be included. | ||
* @default ['.css'] | ||
*/ | ||
extensions?: Array<string>, | ||
/** | ||
* Where this plugin outputs the helper script. | ||
* The hash in the default value is calculated from the include. | ||
* If you use TypeScript, set a value like '*.ts'. | ||
* You can't use this option with the css option. | ||
* The {hash} in the default value is calculated from the include option. | ||
* @default "helper.{hash}.css.js" | ||
@@ -197,2 +206,13 @@ */ | ||
/** | ||
* File extension of generated script. | ||
* @default options.helper ? path.extname(options.helper) : '.js' | ||
*/ | ||
ext?: string, | ||
/** | ||
* Where this plugin outputs the css. | ||
* You can't use this option with the helper option. | ||
* @default undefined | ||
*/ | ||
css?: string, | ||
/** | ||
* It it is true, a watcher is enabled. | ||
@@ -270,36 +290,36 @@ * @default false | ||
export interface IPluginOptions { | ||
/** | ||
* When it is true, this plugin minifies classnames. | ||
* @default true | ||
*/ | ||
mangle?: boolean, | ||
/** | ||
* A function returns an unique number from a given file id. If you process | ||
* CSS files in multiple postcss processes, you should create an identifier | ||
* outside the processes and pass it as this value to keep the uniqueness | ||
* of mangled outputs. | ||
* @default esifycss.createIdentifier() | ||
*/ | ||
identifier?: IIdentifier, | ||
/** | ||
* Names starts with this value are not passed to mangler but replaced with | ||
* unprefixed names. | ||
* @default "raw-" | ||
*/ | ||
rawPrefix?: string, | ||
/** | ||
* A custom mangler: (*id*, *type*, *name*) => string. | ||
* - *id*: string. A filepath to the CSS. | ||
* - *type*: 'id' | 'class' | 'keyframes'. The type of *name* | ||
* - *name*: string. An identifier in the style. | ||
* | ||
* If mangler is set, `mangle` and `identifier` options are ignored. | ||
* | ||
* For example, If the plugin processes `.foo{color:green}` in `/a.css`, | ||
* The mangler is called with `("/a.css", "class", "foo")`. A mangler should | ||
* return an unique string for each input pattern or the styles will be | ||
* overwritten unexpectedly. | ||
* @default undefined | ||
*/ | ||
mangler?: IPluginMangler, | ||
/** | ||
* When it is true, this plugin minifies classnames. | ||
* @default true | ||
*/ | ||
mangle?: boolean, | ||
/** | ||
* A function returns an unique number from a given file id. If you process | ||
* CSS files in multiple postcss processes, you should create an identifier | ||
* outside the processes and pass it as this value to keep the uniqueness | ||
* of mangled outputs. | ||
* @default esifycss.createIdentifier() | ||
*/ | ||
identifier?: IIdentifier, | ||
/** | ||
* Names starts with this value are not passed to mangler but replaced with | ||
* unprefixed names. | ||
* @default "raw-" | ||
*/ | ||
rawPrefix?: string, | ||
/** | ||
* A custom mangler: (*id*, *type*, *name*) => string. | ||
* - *id*: string. A filepath to the CSS. | ||
* - *type*: 'id' | 'class' | 'keyframes'. The type of *name* | ||
* - *name*: string. An identifier in the style. | ||
* | ||
* If mangler is set, `mangle` and `identifier` options are ignored. | ||
* | ||
* For example, If the plugin processes `.foo{color:green}` in `/a.css`, | ||
* The mangler is called with `("/a.css", "class", "foo")`. A mangler should | ||
* return an unique string for each input pattern or the styles will be | ||
* overwritten unexpectedly. | ||
* @default undefined | ||
*/ | ||
mangler?: IPluginMangler, | ||
} | ||
@@ -306,0 +326,0 @@ ``` |
111435
133
1831
328
Updatedcommander@^4.1.0