pull/19/head
宇天 2018-12-03 10:57:30 +08:00
parent c9dddc1937
commit 42c3bf113e
2 changed files with 64 additions and 56 deletions

View File

@ -10,9 +10,11 @@ const vsc = require('vscode')
const path = require('path') const path = require('path')
const cp = require('child_process') const cp = require('child_process')
const fs = require('iofs')
const scss = require('node-sass') const scss = require('node-sass')
const postcss = require('postcss') const postcss = require('postcss')
const autoprefixer = require('autoprefixer') const autoprefixer = require('autoprefixer')
const prefixer = postcss().use(autoprefixer())
const std = vsc.window.createOutputChannel('scss-to-css') const std = vsc.window.createOutputChannel('scss-to-css')
std.out = function() { std.out = function() {
@ -22,24 +24,47 @@ const log = function(...args) {
console.log.apply(console, args) console.log.apply(console, args)
} }
let compileOpts = { const render = function(style, file) {
return new Promise((resolve, reject) => {
scss.render({ outputStyle: style, file }, (err, { css }) => {
if (err) {
reject(err)
} else {
resolve(css)
}
})
})
}
let options = {
compileOnSave: true, compileOnSave: true,
autoPrefixer: true, autoPrefixer: true,
output: 'compressed', output: 'compressed',
sourcemap: false,
exclude: '' exclude: ''
} }
const exec = function(arr, cb) { // const exec = function(arr, cb) {
let cmd = arr.join(' ') // let cmd = arr.join(' ')
return new Promise((yes, no) => { // return new Promise((yes, no) => {
cp.exec(cmd, (err, out) => { // cp.exec(cmd, (err, out) => {
if (err) { // if (err) {
no('err: ' + err) // no('err: ' + err)
} else { // } else {
yes(arr) // yes(arr)
} // }
// })
// })
// }
const compileCss = (style, entry, output) => {
return render(style, entry).then(css => {
if (options.autoPrefixer) {
return prefixer.process(css, { from: '', to: '' }).then(result => {
return { css: result.css, output }
}) })
} else {
return { css, output }
}
}) })
} }
@ -48,57 +73,40 @@ const Compiler = {
let origin = doc.fileName || '' let origin = doc.fileName || ''
let target = origin.replace(/\.scss$/, '.') let target = origin.replace(/\.scss$/, '.')
let task = [] let task = []
let postArgs = ['postcss', '--no-map', '-r', '-u', 'autoprefixer']
// 说明不是scss文件 // 说明不是scss文件
if (origin === target) { if (origin === target) {
return return
} }
task = compileOpts.output.map(type => { task = options.output.map(style => {
let cmd = ['scss', '-C', '-t', type]
let ext = 'css' let ext = 'css'
if (compileOpts.sourcemap) { switch (style) {
cmd.push('--sourcemap=auto')
} else {
cmd.push('--sourcemap=none')
}
switch (type) {
case 'compressed': case 'compressed':
ext = 'min.' + ext ext = 'min.' + ext
break break
default: default:
ext = type.slice(0, 1) + '.' + ext ext = style.slice(0, 1) + '.' + ext
} }
cmd.push(origin, target + ext) return { style, output: target + ext }
return cmd
}) })
// 编译单一类型, 则去掉文件名微调 // 编译单一类型, 则去掉文件名微调
if (task.length === 1) { if (task.length === 1) {
task[0].pop() task[0].output = target + 'css'
task[0].push(target + 'css')
} }
task = task.map(item => { task = task.map(item => {
return exec(item) return compileCss(item.style, origin, item.output)
}) })
Promise.all(task) Promise.all(task)
.then(list => { .then(list => {
if (compileOpts.autoPrefixer) { list.forEach(it => {
let task2 = list.map(cmd => { fs.echo(it.css, it.output)
let arr = postArgs.concat()
arr.splice(1, 0, cmd.pop())
return exec(arr)
}) })
return Promise.all(task2)
} else {
return true
}
}) })
.catch(err => { .catch(err => {
log(err) log(err)
@ -110,9 +118,8 @@ const Compiler = {
* 用于保存时编译的动作, 右键编译时, 不过滤这2项 * 用于保存时编译的动作, 右键编译时, 不过滤这2项
*/ */
filter(doc) { filter(doc) {
log(doc)
// 未开启保存时编译 // 未开启保存时编译
if (!compileOpts.compileOnSave) { if (!options.compileOnSave) {
return return
} }
@ -124,8 +131,8 @@ const Compiler = {
} }
// 过滤不编译的文件 // 过滤不编译的文件
if (compileOpts.exclude) { if (options.exclude) {
let exp = new RegExp(compileOpts.exclude, 'i') let exp = new RegExp(options.exclude, 'i')
if (exp.test(origin)) { if (exp.test(origin)) {
return return
} }
@ -137,10 +144,10 @@ const Compiler = {
function activate(ctx) { function activate(ctx) {
// log('hello, the extend scss-compiler is running....') // log('hello, the extend scss-compiler is running....')
let options = vsc.workspace.getConfiguration('ScssCompiler') let conf = vsc.workspace.getConfiguration('Scss2css')
Object.assign(compileOpts, options) Object.assign(options, conf)
compileOpts.output = compileOpts.output.split('|') options.output = options.output.split('|').map(it => it.trim())
vsc.workspace.onDidSaveTextDocument(doc => { vsc.workspace.onDidSaveTextDocument(doc => {
Compiler.filter(doc) Compiler.filter(doc)

View File

@ -19,35 +19,30 @@
"contributes": { "contributes": {
"context": [ "context": [
{ {
"command": "ScssCompiler.compile", "command": "Scss2css.compile",
"title": "Compile this scss file" "title": "Compile this scss file"
} }
], ],
"configuration": { "configuration": {
"type": "object", "type": "object",
"title": "scss-compiler 配置", "title": "Scss-to-css 配置",
"properties": { "properties": {
"ScssCompiler.compileOnSave": { "Scss2css.compileOnSave": {
"type": "boolean", "type": "boolean",
"default": true, "default": true,
"description": "保存后自动编译" "description": "保存后自动编译"
}, },
"ScssCompiler.autoPrefixer": { "Scss2css.autoPrefixer": {
"type": "boolean", "type": "boolean",
"default": true, "default": true,
"description": "是否自动补全浏览器前缀(可以手动在项目目录添加 .browserslistrc)" "description": "是否自动补全浏览器前缀(可以手动在项目目录添加 .browserslistrc)"
}, },
"ScssCompiler.output": { "Scss2css.output": {
"type": "string", "type": "string",
"default": "compressed", "default": "compressed",
"description": "css 文件输出方式. 使用 \"nested\", \"expanded\", \"compact\" or \"compressed\" .\n PS. 如果需要同时编译多种, 可用'|' 分隔, 如 compact | compressed \n 注: 如果编译多种,会自动微调文件名, 编译单个则不微调。" "description": "css 文件输出方式. 使用 \"nested\", \"expanded\", \"compact\" or \"compressed\" .\n PS. 如果需要同时编译多种, 可用'|' 分隔, 如 compact | compressed \n 注: 如果编译多种,会自动微调文件名, 编译单个则不微调。"
}, },
"ScssCompiler.sourcemap": { "Scss2css.exclude": {
"type": "boolean",
"default": false,
"description": "是否生成sourcemap,默认否"
},
"ScssCompiler.exclude": {
"type": "string", "type": "string",
"default": "", "default": "",
"description": "要忽略的文件的正则表达式(默认不编译var.scss文件)。" "description": "要忽略的文件的正则表达式(默认不编译var.scss文件)。"
@ -61,5 +56,11 @@
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"vscode": "^1.1.21" "vscode": "^1.1.21"
},
"dependencies": {
"node-sass": "^4.10.0",
"iofs": "^1.1.0",
"postcss": "^7.0.6",
"autoprefixer": "^9.3.1"
} }
} }