diff --git a/.gitignore b/.gitignore index c4061e4..9bdffbe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,7 @@ .vscode node_modules/ dist -benchmark -bin +test *.sublime-project *.sublime-workspace diff --git a/build.js b/build.js new file mode 100644 index 0000000..87cb73b --- /dev/null +++ b/build.js @@ -0,0 +1,12 @@ +import Es from 'esbuild' +import fs from 'iofs' + +Es.buildSync({ + entryPoints: ['src/less-node/index.js'], + outdir: 'dist', + platform: 'node', + format: 'esm', + // minify: true, + bundle: true, + target: 'node12' +}) diff --git a/build/banner.js b/build/banner.js deleted file mode 100644 index aea4a6e..0000000 --- a/build/banner.js +++ /dev/null @@ -1,14 +0,0 @@ -import pkg from './../package.json' assert { type: 'json' } - -export default `/** - * Less - ${pkg.description} v${pkg.version} - * http://lesscss.org - * - * Copyright (c) 2009-${new Date().getFullYear()}, ${pkg.author.name} <${ - pkg.author.email -}> - * Licensed under the ${pkg.license} License. - * - * @license ${pkg.license} - */ -` diff --git a/build/rollup.js b/build/rollup.js deleted file mode 100644 index f0c6c52..0000000 --- a/build/rollup.js +++ /dev/null @@ -1,90 +0,0 @@ -import rollup from 'rollup' -import typescript from 'rollup-plugin-typescript2' -import commonjs from '@rollup/plugin-commonjs' -import json from '@rollup/plugin-json' -import resolve from '@rollup/plugin-node-resolve' -import terser from 'rollup-plugin-terser' -import banner from './banner' -import path from 'path') - -const rootPath = path.join(__dirname, '..') - -import minimist from 'minimist' - -const args = minimist(process.argv.slice(2)) - -let outDir = args.dist ? './dist' : './tmp' - -async function buildBrowser() { - let bundle = await rollup.rollup({ - input: './src/less-browser/bootstrap.js', - output: [ - { - file: 'less.js', - format: 'umd' - }, - { - file: 'less.min.js', - format: 'umd' - } - ], - plugins: [ - resolve(), - commonjs(), - json(), - typescript({ - verbosity: 2, - tsconfigDefaults: { - compilerOptions: { - allowJs: true, - sourceMap: true, - target: 'ES5' - } - }, - include: ['*.ts', '**/*.ts', '*.js', '**/*.js'], - exclude: ['node_modules'] // only transpile our source code - }), - terser({ - compress: true, - include: [/^.+\.min\.js$/], - output: { - comments: function (node, comment) { - if (comment.type == 'comment2') { - // preserve banner - return /@license/i.test(comment.value) - } - } - } - }) - ] - }) - - if (!args.out || args.out.indexOf('less.js') > -1) { - const file = args.out || `${outDir}/less.js` - console.log(`Writing ${file}...`) - await bundle.write({ - file: path.join(rootPath, file), - format: 'umd', - name: 'less', - banner - }) - } - - if (!args.out || args.out.indexOf('less.min.js') > -1) { - const file = args.out || `${outDir}/less.min.js` - console.log(`Writing ${file}...`) - await bundle.write({ - file: path.join(rootPath, file), - format: 'umd', - name: 'less', - sourcemap: true, - banner - }) - } -} - -async function build() { - await buildBrowser() -} - -build() diff --git a/index.js b/index.js deleted file mode 100644 index 7c440d5..0000000 --- a/index.js +++ /dev/null @@ -1 +0,0 @@ -export default './lib/less-node' diff --git a/package.json b/package.json index fcaaf43..4df0bb8 100644 --- a/package.json +++ b/package.json @@ -1,101 +1,24 @@ { - "name": "less", - "version": "4.1.3", - "description": "Leaner CSS", + "name": "@bytedo/less", + "version": "0.0.1", + "type": "module", + "description": "less精简版", "homepage": "http://lesscss.org", - "author": { - "name": "Alexis Sellier", - "email": "self@cloudhead.net" - }, + "author": "yutent", "contributors": [ "The Core Less Team" ], "repository": { "type": "git", - "url": "https://github.com/less/less.js.git" + "url": "https://github.com/bytedo/less.git" }, "license": "Apache-2.0", - "bin": { - "lessc": "./bin/lessc" - }, - "main": "index", - "module": "./lib/less-node/index", - "directories": { - "test": "./test" - }, - "browser": "./dist/less.js", - "engines": { - "node": ">=6" - }, + "main": "dist/index.js", + "files": [ + "dist/*" + ], "scripts": { - "test": "grunt test", - "grunt": "grunt", - "lint": "eslint '**/*.{ts,js}'", - "lint:fix": "eslint '**/*.{ts,js}' --fix", - "build": "npm-run-all clean compile", - "clean": "shx rm -rf ./lib tsconfig.tsbuildinfo", - "compile": "tsc -p tsconfig.build.json", - "copy:root": "shx cp -rf ./dist ../../", - "dev": "tsc -p tsconfig.build.json -w", - "prepublishOnly": "grunt dist" - }, - "optionalDependencies": { - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "needle": "^3.1.0", - "source-map": "~0.6.0" - }, - "devDependencies": { - "@less/test-data": "^4.1.0", - "@less/test-import-module": "^4.0.0", - "@rollup/plugin-commonjs": "^17.0.0", - "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^11.0.0", - "@typescript-eslint/eslint-plugin": "^4.28.0", - "@typescript-eslint/parser": "^4.28.0", - "benny": "^3.6.12", - "bootstrap-less-port": "0.3.0", - "chai": "^4.2.0", - "cross-env": "^7.0.3", - "diff": "^3.2.0", - "eslint": "^7.29.0", - "fs-extra": "^8.1.0", - "git-rev": "^0.2.1", - "globby": "^10.0.1", - "grunt": "^1.0.4", - "grunt-cli": "^1.3.2", - "grunt-contrib-clean": "^1.0.0", - "grunt-contrib-connect": "^1.0.2", - "grunt-eslint": "^23.0.0", - "grunt-saucelabs": "^9.0.1", - "grunt-shell": "^1.3.0", - "html-template-tag": "^3.2.0", - "jit-grunt": "^0.10.0", - "less-plugin-autoprefix": "^1.5.1", - "less-plugin-clean-css": "^1.5.1", - "minimist": "^1.2.0", - "mocha": "^6.2.1", - "mocha-headless-chrome": "^4.0.0", - "mocha-teamcity-reporter": "^3.0.0", - "nock": "^11.8.2", - "npm-run-all": "^4.1.5", - "performance-now": "^0.2.0", - "phin": "^2.2.3", - "promise": "^7.1.1", - "read-glob": "^3.0.0", - "resolve": "^1.17.0", - "rollup": "^2.52.2", - "rollup-plugin-terser": "^5.1.1", - "rollup-plugin-typescript2": "^0.29.0", - "semver": "^6.3.0", - "shx": "^0.3.2", - "time-grunt": "^1.3.0", - "ts-node": "^9.1.1", - "typescript": "^4.3.4", - "uikit": "2.27.4" + "build": "node build.js" }, "keywords": [ "compile less", @@ -121,9 +44,5 @@ "stylesheet", "variables in css", "css less" - ], - "dependencies": { - "copy-anything": "^2.0.1", - "parse-node-version": "^1.0.1" - } + ] } diff --git a/src/less-node/file-manager.js b/src/less-node/file-manager.js index a4d2f7c..588002a 100644 --- a/src/less-node/file-manager.js +++ b/src/less-node/file-manager.js @@ -1,16 +1,15 @@ import path from 'path' -import fs from './fs' +import fs from 'fs' import AbstractFileManager from '../less/environment/abstract-file-manager.js' -const FileManager = function () {} -FileManager.prototype = Object.assign(new AbstractFileManager(), { +export default class FileManager extends AbstractFileManager { supports() { return true - }, + } supportsSync() { return true - }, + } loadFile(filename, currentDirectory, options, environment, callback) { let fullFilename @@ -142,12 +141,10 @@ FileManager.prototype = Object.assign(new AbstractFileManager(), { } })(0) } - }, + } loadFileSync(filename, currentDirectory, options, environment) { options.syncImport = true return this.loadFile(filename, currentDirectory, options, environment) } -}) - -export default FileManager +} diff --git a/src/less-node/fs.js b/src/less-node/fs.js deleted file mode 100644 index c5063bf..0000000 --- a/src/less-node/fs.js +++ /dev/null @@ -1,6 +0,0 @@ - -export default fs from 'graceful-fs' - -// export default fs from 'fs' - - diff --git a/src/less-node/index.js b/src/less-node/index.js index e073813..b01a3ea 100644 --- a/src/less-node/index.js +++ b/src/less-node/index.js @@ -1,20 +1,17 @@ -import environment from './environment' +// import environment from './environment' import FileManager from './file-manager' import UrlFileManager from './url-file-manager' import createFromEnvironment from '../less' -const less = createFromEnvironment(environment, [ +const less = createFromEnvironment({}, [ new FileManager(), new UrlFileManager() ]) -import lesscHelper from './lessc-helper' import PluginLoader from './plugin-loader' -import fs from './fs.js' +import fs from 'fs' import options from '../less/default-options' -import imageSize from './image-size' // allow people to create less with their own environment less.createFromEnvironment = createFromEnvironment -less.lesscHelper = lesscHelper less.PluginLoader = PluginLoader less.fs = fs less.FileManager = FileManager @@ -23,7 +20,4 @@ less.UrlFileManager = UrlFileManager // Set up options less.options = options -// provide image-size functionality -imageSize(less.environment) - export default less diff --git a/src/less-node/lessc-helper.js b/src/less-node/lessc-helper.js index 519268b..c27afba 100644 --- a/src/less-node/lessc-helper.js +++ b/src/less-node/lessc-helper.js @@ -1,179 +1,165 @@ // lessc_helper.js // // helper functions for lessc -const lessc_helper = { - // Stylize a string - stylize: function (str, style) { - const styles = { - reset: [0, 0], - bold: [1, 22], - inverse: [7, 27], - underline: [4, 24], - yellow: [33, 39], - green: [32, 39], - red: [31, 39], - grey: [90, 39] - } - return `\x1b[${styles[style][0]}m${str}\x1b[${styles[style][1]}m` - }, - // Print command line options - printUsage: function () { - console.log( - 'usage: lessc [option option=parameter ...] [destination]' - ) - console.log('') - console.log( - "If source is set to `-' (dash or hyphen-minus), input is read from stdin." - ) - console.log('') - console.log('options:') - console.log( - ' -h, --help Prints help (this message) and exit.' - ) - console.log( - " --include-path=PATHS Sets include paths. Separated by `:'. `;' also supported on windows." - ) - console.log( - ' -M, --depends Outputs a makefile import dependency list to stdout.' - ) - console.log(' --no-color Disables colorized output.') - console.log( - ' --ie-compat Enables IE8 compatibility checks.' - ) - console.log( - ' --js Enables inline JavaScript in less files' - ) - console.log(' -l, --lint Syntax check only (lint).') - console.log( - ' -s, --silent Suppresses output of error messages.' - ) - console.log(' --strict-imports Forces evaluation of imports.') - console.log( - ' --insecure Allows imports from insecure https hosts.' - ) - console.log( - ' -v, --version Prints version number and exit.' - ) - console.log(' --verbose Be verbose.') - console.log( - ' --source-map[=FILENAME] Outputs a v3 sourcemap to the filename (or output filename.map).' - ) - console.log( - ' --source-map-rootpath=X Adds this path onto the sourcemap filename and less file paths.' - ) - console.log( - ' --source-map-basepath=X Sets sourcemap base path, defaults to current working directory.' - ) - console.log( - ' --source-map-include-source Puts the less files into the map instead of referencing them.' - ) - console.log( - ' --source-map-inline Puts the map (and any less files) as a base64 data uri into the output css file.' - ) - console.log( - ' --source-map-url=URL Sets a custom URL to map file, for sourceMappingURL comment' - ) - console.log(' in generated CSS file.') - console.log( - ' --source-map-no-annotation Excludes the sourceMappingURL comment from the output css file.' - ) - console.log( - ' -rp, --rootpath=URL Sets rootpath for url rewriting in relative imports and urls' - ) - console.log( - ' Works with or without the relative-urls option.' - ) - console.log( - ' -ru=, --rewrite-urls= Rewrites URLs to make them relative to the base less file.' - ) - console.log( - " all|local|off 'all' rewrites all URLs, 'local' just those starting with a '.'" - ) - console.log('') - console.log(' -m=, --math=') - console.log( - ' always Less will eagerly perform math operations always.' - ) - console.log( - ' parens-division Math performed except for division (/) operator' - ) - console.log( - ' parens | strict Math only performed inside parentheses' - ) - console.log( - ' strict-legacy Parens required in very strict terms (legacy --strict-math)' - ) - console.log('') - console.log( - ' -su=on|off Allows mixed units, e.g. 1px+1em or 1px*1px which have units' - ) - console.log(' --strict-units=on|off that cannot be represented.') - console.log( - " --global-var='VAR=VALUE' Defines a variable that can be referenced by the file." - ) - console.log( - " --modify-var='VAR=VALUE' Modifies a variable already declared in the file." - ) - console.log( - " --url-args='QUERYSTRING' Adds params into url tokens (e.g. 42, cb=42 or 'a=1&b=2')" - ) - console.log( - ' --plugin=PLUGIN=OPTIONS Loads a plugin. You can also omit the --plugin= if the plugin begins' - ) - console.log( - ' less-plugin. E.g. the clean css plugin is called less-plugin-clean-css' - ) - console.log( - ' once installed (npm install less-plugin-clean-css), use either with' - ) - console.log( - ' --plugin=less-plugin-clean-css or just --clean-css' - ) - console.log( - ' specify options afterwards e.g. --plugin=less-plugin-clean-css="advanced"' - ) - console.log(' or --clean-css="advanced"') - console.log(' --disable-plugin-rule Disallow @plugin statements') - console.log('') - console.log('-------------------------- Deprecated ----------------') - console.log( - ' -sm=on|off Legacy parens-only math. Use --math' - ) - console.log(' --strict-math=on|off ') - console.log('') - console.log(' --line-numbers=TYPE Outputs filename and line numbers.') - console.log( - " TYPE can be either 'comments', which will output" - ) - console.log( - " the debug info within comments, 'mediaquery'" - ) - console.log( - ' that will output the information within a fake' - ) - console.log( - ' media query which is compatible with the SASS' - ) - console.log( - " format, and 'all' which will do both." - ) - console.log( - ' -x, --compress Compresses output by removing some whitespaces.' - ) - console.log( - ' We recommend you use a dedicated minifer like less-plugin-clean-css' - ) - console.log('') - console.log('Report bugs to: http://github.com/less/less.js/issues') - console.log('Home page: ') +export function stylize(str, style) { + const styles = { + reset: [0, 0], + bold: [1, 22], + inverse: [7, 27], + underline: [4, 24], + yellow: [33, 39], + green: [32, 39], + red: [31, 39], + grey: [90, 39] } + return `\x1b[${styles[style][0]}m${str}\x1b[${styles[style][1]}m` } -// Exports helper functions -// eslint-disable-next-line no-prototype-builtins -for (const h in lessc_helper) { - if (lessc_helper.hasOwnProperty(h)) { - exports[h] = lessc_helper[h] - } +// Print command line options +export function printUsage() { + console.log( + 'usage: lessc [option option=parameter ...] [destination]' + ) + console.log('') + console.log( + "If source is set to `-' (dash or hyphen-minus), input is read from stdin." + ) + console.log('') + console.log('options:') + console.log( + ' -h, --help Prints help (this message) and exit.' + ) + console.log( + " --include-path=PATHS Sets include paths. Separated by `:'. `;' also supported on windows." + ) + console.log( + ' -M, --depends Outputs a makefile import dependency list to stdout.' + ) + console.log(' --no-color Disables colorized output.') + console.log( + ' --ie-compat Enables IE8 compatibility checks.' + ) + console.log( + ' --js Enables inline JavaScript in less files' + ) + console.log(' -l, --lint Syntax check only (lint).') + console.log( + ' -s, --silent Suppresses output of error messages.' + ) + console.log(' --strict-imports Forces evaluation of imports.') + console.log( + ' --insecure Allows imports from insecure https hosts.' + ) + console.log(' -v, --version Prints version number and exit.') + console.log(' --verbose Be verbose.') + console.log( + ' --source-map[=FILENAME] Outputs a v3 sourcemap to the filename (or output filename.map).' + ) + console.log( + ' --source-map-rootpath=X Adds this path onto the sourcemap filename and less file paths.' + ) + console.log( + ' --source-map-basepath=X Sets sourcemap base path, defaults to current working directory.' + ) + console.log( + ' --source-map-include-source Puts the less files into the map instead of referencing them.' + ) + console.log( + ' --source-map-inline Puts the map (and any less files) as a base64 data uri into the output css file.' + ) + console.log( + ' --source-map-url=URL Sets a custom URL to map file, for sourceMappingURL comment' + ) + console.log(' in generated CSS file.') + console.log( + ' --source-map-no-annotation Excludes the sourceMappingURL comment from the output css file.' + ) + console.log( + ' -rp, --rootpath=URL Sets rootpath for url rewriting in relative imports and urls' + ) + console.log( + ' Works with or without the relative-urls option.' + ) + console.log( + ' -ru=, --rewrite-urls= Rewrites URLs to make them relative to the base less file.' + ) + console.log( + " all|local|off 'all' rewrites all URLs, 'local' just those starting with a '.'" + ) + console.log('') + console.log(' -m=, --math=') + console.log( + ' always Less will eagerly perform math operations always.' + ) + console.log( + ' parens-division Math performed except for division (/) operator' + ) + console.log( + ' parens | strict Math only performed inside parentheses' + ) + console.log( + ' strict-legacy Parens required in very strict terms (legacy --strict-math)' + ) + console.log('') + console.log( + ' -su=on|off Allows mixed units, e.g. 1px+1em or 1px*1px which have units' + ) + console.log(' --strict-units=on|off that cannot be represented.') + console.log( + " --global-var='VAR=VALUE' Defines a variable that can be referenced by the file." + ) + console.log( + " --modify-var='VAR=VALUE' Modifies a variable already declared in the file." + ) + console.log( + " --url-args='QUERYSTRING' Adds params into url tokens (e.g. 42, cb=42 or 'a=1&b=2')" + ) + console.log( + ' --plugin=PLUGIN=OPTIONS Loads a plugin. You can also omit the --plugin= if the plugin begins' + ) + console.log( + ' less-plugin. E.g. the clean css plugin is called less-plugin-clean-css' + ) + console.log( + ' once installed (npm install less-plugin-clean-css), use either with' + ) + console.log( + ' --plugin=less-plugin-clean-css or just --clean-css' + ) + console.log( + ' specify options afterwards e.g. --plugin=less-plugin-clean-css="advanced"' + ) + console.log(' or --clean-css="advanced"') + console.log(' --disable-plugin-rule Disallow @plugin statements') + console.log('') + console.log('-------------------------- Deprecated ----------------') + console.log(' -sm=on|off Legacy parens-only math. Use --math') + console.log(' --strict-math=on|off ') + console.log('') + console.log(' --line-numbers=TYPE Outputs filename and line numbers.') + console.log( + " TYPE can be either 'comments', which will output" + ) + console.log( + " the debug info within comments, 'mediaquery'" + ) + console.log( + ' that will output the information within a fake' + ) + console.log( + ' media query which is compatible with the SASS' + ) + console.log( + " format, and 'all' which will do both." + ) + console.log( + ' -x, --compress Compresses output by removing some whitespaces.' + ) + console.log( + ' We recommend you use a dedicated minifer like less-plugin-clean-css' + ) + console.log('') + console.log('Report bugs to: http://github.com/less/less.js/issues') + console.log('Home page: ') } diff --git a/src/less-node/url-file-manager.js b/src/less-node/url-file-manager.js index c51a50e..d628ab4 100644 --- a/src/less-node/url-file-manager.js +++ b/src/less-node/url-file-manager.js @@ -8,7 +8,6 @@ import url from 'url' let request import AbstractFileManager from '../less/environment/abstract-file-manager.js' import logger from '../less/logger' -import needle from 'needle' const UrlFileManager = function () {} UrlFileManager.prototype = Object.assign(new AbstractFileManager(), { @@ -18,13 +17,6 @@ UrlFileManager.prototype = Object.assign(new AbstractFileManager(), { loadFile(filename, currentDirectory, options, environment) { return new Promise((fulfill, reject) => { - if (request === undefined) { - try { - request = needle - } catch (e) { - request = null - } - } if (!request) { reject({ type: 'File', diff --git a/src/less/index.js b/src/less/index.js index d838a18..72475c7 100644 --- a/src/less/index.js +++ b/src/less/index.js @@ -19,7 +19,6 @@ import ImportManager from './import-manager' import Parse from './parse' import Render from './render' import { version } from '../../package.json' -import parseVersion from 'parse-node-version' export default function (environment, fileManagers) { let sourceMapOutput, sourceMapBuilder, parseTree, importManager @@ -33,9 +32,9 @@ export default function (environment, fileManagers) { const render = Render(environment, parseTree, importManager) const parse = Parse(environment, parseTree, importManager) - const v = parseVersion(`v${version}`) + const v = version.split('.').map(n => +n) const initial = { - version: [v.major, v.minor, v.patch], + version: [v[0], v[1], v[2]], data, tree, Environment, diff --git a/src/less/parser/parser.js b/src/less/parser/parser.js index 4f191d1..ace89a5 100644 --- a/src/less/parser/parser.js +++ b/src/less/parser/parser.js @@ -145,7 +145,7 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) { // @param callback call `callback` when done. // @param [additionalData] An optional map which can contains vars - a map (key, value) of variables to apply // - parse: function (str, callback, additionalData) { + parse(str, callback, additionalData) { let root let err = null let globalVars diff --git a/src/less/utils.js b/src/less/utils.js index fb990f9..ae0a2ba 100644 --- a/src/less/utils.js +++ b/src/less/utils.js @@ -1,6 +1,27 @@ /* jshint proto: true */ import * as Constants from './constants' -import { copy } from 'copy-anything' + +function copy(obj = {}) { + if (Array.isArray(obj)) { + return obj.map(it => copy(it)) + } else if (typeof obj === 'object') { + let tmp = {} + for (let k in obj) { + if (obj[k] === void 0) { + continue + } else { + if (typeof obj[k] === 'object' && obj[k] !== null) { + tmp[k] = copy(obj[k]) + } else { + tmp[k] = obj[k] + } + } + } + return tmp + } else { + return obj + } +} export function getLocation(index, inputStream) { let n = index + 1 @@ -22,14 +43,7 @@ export function getLocation(index, inputStream) { } export function copyArray(arr) { - let i - const length = arr.length - const copy = new Array(length) - - for (i = 0; i < length; i++) { - copy[i] = arr[i] - } - return copy + return [...arr] } export function clone(obj) { @@ -46,10 +60,10 @@ export function defaults(obj1, obj2) { let newObj = obj2 || {} if (!obj2._defaults) { newObj = {} - const defaults = copy(obj1) - newObj._defaults = defaults + const _defaults = copy(obj1) + newObj._defaults = _defaults const cloned = obj2 ? copy(obj2) : {} - Object.assign(newObj, defaults, cloned) + Object.assign(newObj, _defaults, cloned) } return newObj }