2018-12-03 10:00:21 +08:00
|
|
|
/**
|
|
|
|
*
|
2021-06-30 14:34:24 +08:00
|
|
|
* @author yutent<yutent.io@gmail.com>
|
2018-12-03 10:00:21 +08:00
|
|
|
* @date 2018/11/01 09:37:55
|
|
|
|
*/
|
|
|
|
|
|
|
|
const vsc = require('vscode')
|
|
|
|
const path = require('path')
|
2021-06-30 14:34:24 +08:00
|
|
|
const scss = require('sass')
|
2018-12-03 10:00:21 +08:00
|
|
|
|
2018-12-03 10:57:30 +08:00
|
|
|
const fs = require('iofs')
|
2018-12-03 10:00:21 +08:00
|
|
|
const postcss = require('postcss')
|
|
|
|
const autoprefixer = require('autoprefixer')
|
|
|
|
|
2019-06-10 16:18:57 +08:00
|
|
|
const std = vsc.window.createOutputChannel('scss-to-css')
|
2021-08-04 17:44:33 +08:00
|
|
|
|
|
|
|
let prefixer
|
|
|
|
let options = {
|
|
|
|
compileOnSave: true,
|
|
|
|
autoPrefixer: true,
|
2021-10-14 09:36:37 +08:00
|
|
|
indentType: 'space',
|
2021-10-14 09:38:18 +08:00
|
|
|
indentWidth: 2,
|
2021-08-04 17:44:33 +08:00
|
|
|
output: 'compressed',
|
|
|
|
exclude: ''
|
|
|
|
}
|
|
|
|
|
2019-06-10 16:18:57 +08:00
|
|
|
std.out = function(msg) {
|
|
|
|
std.appendLine(msg)
|
|
|
|
}
|
2018-12-03 10:00:21 +08:00
|
|
|
|
2021-06-30 14:34:24 +08:00
|
|
|
// 编译scss
|
|
|
|
function render(style, file) {
|
|
|
|
try {
|
|
|
|
return (
|
|
|
|
scss.renderSync({
|
2021-08-04 17:44:33 +08:00
|
|
|
file,
|
2021-10-14 09:36:37 +08:00
|
|
|
outputStyle: style,
|
|
|
|
indentType: options.indentType,
|
|
|
|
indentWidth: options.indentWidth
|
2021-06-30 14:34:24 +08:00
|
|
|
}).css + ''
|
|
|
|
).trim()
|
|
|
|
} catch (err) {
|
|
|
|
std.out(err)
|
2021-08-04 17:44:33 +08:00
|
|
|
std.show(true)
|
2021-06-30 14:34:24 +08:00
|
|
|
// console.error(err)
|
|
|
|
}
|
2019-08-05 16:02:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const compileScss = (style, entry, output) => {
|
2019-02-14 13:38:11 +08:00
|
|
|
if (options.outdir) {
|
|
|
|
let tmp = output.replace(options.workspace, '.')
|
|
|
|
output = path.join(options.outdir, tmp)
|
|
|
|
}
|
2021-06-30 14:34:24 +08:00
|
|
|
|
|
|
|
let css = render(style, entry)
|
|
|
|
|
|
|
|
if (options.autoPrefixer) {
|
|
|
|
return prefixer.process(css, { from: '', to: '' }).then(result => {
|
|
|
|
return { css: result.css, output }
|
2019-06-10 16:18:57 +08:00
|
|
|
})
|
2021-06-30 14:34:24 +08:00
|
|
|
} else {
|
|
|
|
return Promise.resolve({ css, output })
|
|
|
|
}
|
2018-12-03 10:00:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const Compiler = {
|
|
|
|
compile(doc) {
|
|
|
|
let origin = doc.fileName || ''
|
2019-02-14 13:38:11 +08:00
|
|
|
let target = origin.replace(/\.scss$/, '')
|
2018-12-03 10:00:21 +08:00
|
|
|
let task = []
|
|
|
|
|
|
|
|
// 说明不是scss文件
|
|
|
|
if (origin === target) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-12-03 10:57:30 +08:00
|
|
|
task = options.output.map(style => {
|
2019-02-14 13:38:11 +08:00
|
|
|
let ext = '.css'
|
2018-12-03 10:00:21 +08:00
|
|
|
|
2018-12-03 10:57:30 +08:00
|
|
|
switch (style) {
|
2018-12-03 10:00:21 +08:00
|
|
|
case 'compressed':
|
2019-02-14 13:38:11 +08:00
|
|
|
ext = '.min' + ext
|
2018-12-03 10:00:21 +08:00
|
|
|
break
|
|
|
|
default:
|
2019-02-14 13:38:11 +08:00
|
|
|
ext = style.slice(0, 1) + ext
|
2018-12-03 10:00:21 +08:00
|
|
|
}
|
|
|
|
|
2018-12-03 10:57:30 +08:00
|
|
|
return { style, output: target + ext }
|
2018-12-03 10:00:21 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
// 编译单一类型, 则去掉文件名微调
|
|
|
|
if (task.length === 1) {
|
2019-02-14 13:38:11 +08:00
|
|
|
task[0].output = target + '.css'
|
2018-12-03 10:00:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
task = task.map(item => {
|
2019-08-05 16:02:59 +08:00
|
|
|
return compileScss(item.style, origin, item.output)
|
2018-12-03 10:00:21 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
Promise.all(task)
|
|
|
|
.then(list => {
|
2018-12-03 10:57:30 +08:00
|
|
|
list.forEach(it => {
|
|
|
|
fs.echo(it.css, it.output)
|
|
|
|
})
|
2018-12-03 10:00:21 +08:00
|
|
|
})
|
|
|
|
.catch(err => {
|
2018-12-21 15:57:39 +08:00
|
|
|
vsc.window.showInformationMessage(err)
|
2018-12-03 10:00:21 +08:00
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 条件过滤
|
|
|
|
* 用于保存时编译的动作, 右键编译时, 不过滤这2项
|
|
|
|
*/
|
|
|
|
filter(doc) {
|
|
|
|
// 未开启保存时编译
|
2018-12-03 10:57:30 +08:00
|
|
|
if (!options.compileOnSave) {
|
2018-12-03 10:00:21 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
let origin = doc.fileName || ''
|
|
|
|
|
|
|
|
// var.scss文件默认不编译
|
|
|
|
if (/\/var\.scss$/.test(origin)) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// 过滤不编译的文件
|
2018-12-03 10:57:30 +08:00
|
|
|
if (options.exclude) {
|
2019-12-02 09:21:43 +08:00
|
|
|
if (options.exclude.test(origin)) {
|
2018-12-03 10:00:21 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.compile(doc)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-05 04:24:17 +08:00
|
|
|
function __init__() {
|
|
|
|
let conf = vsc.workspace.getConfiguration('Scss2css')
|
2019-02-14 13:38:11 +08:00
|
|
|
let folders = vsc.workspace.workspaceFolders
|
|
|
|
let wsDir = ''
|
|
|
|
let configFile = ''
|
|
|
|
|
2019-01-05 04:24:17 +08:00
|
|
|
Object.assign(options, conf)
|
2019-02-14 13:38:11 +08:00
|
|
|
conf = null
|
2019-01-05 04:24:17 +08:00
|
|
|
|
|
|
|
options.output = options.output.split('|').map(it => it.trim())
|
|
|
|
|
2018-12-03 14:08:33 +08:00
|
|
|
if (folders && folders.length) {
|
2022-03-11 18:07:39 +08:00
|
|
|
wsDir = folders[0].uri.fsPath
|
2018-12-03 14:08:33 +08:00
|
|
|
}
|
2019-02-14 13:38:11 +08:00
|
|
|
|
|
|
|
if (wsDir) {
|
|
|
|
configFile = path.join(wsDir, '.scssrc')
|
2018-12-21 15:57:39 +08:00
|
|
|
} else {
|
|
|
|
let editor = vsc.window.activeTextEditor
|
|
|
|
if (editor) {
|
2019-02-14 13:38:11 +08:00
|
|
|
wsDir = path.dirname(editor.document.fileName)
|
|
|
|
configFile = path.join(wsDir, '.scssrc')
|
2018-12-21 15:57:39 +08:00
|
|
|
}
|
2018-12-03 14:08:33 +08:00
|
|
|
}
|
|
|
|
|
2020-08-03 11:01:23 +08:00
|
|
|
options.workspace = wsDir
|
2019-02-14 13:38:11 +08:00
|
|
|
|
2020-08-03 11:01:23 +08:00
|
|
|
// 有配置文件时, 优先使用配置文件的配置
|
|
|
|
if (fs.exists(configFile)) {
|
2019-02-14 13:38:11 +08:00
|
|
|
let tmp = JSON.parse(fs.cat(configFile).toString())
|
|
|
|
|
|
|
|
Object.assign(options, tmp)
|
|
|
|
tmp = null
|
|
|
|
|
|
|
|
if (options.outdir) {
|
|
|
|
options.outdir = path.join(options.workspace, options.outdir)
|
|
|
|
}
|
2018-12-03 14:08:33 +08:00
|
|
|
}
|
2019-02-14 13:38:11 +08:00
|
|
|
|
2019-12-02 09:21:43 +08:00
|
|
|
if (options.exclude) {
|
|
|
|
options.exclude = new RegExp(options.exclude, 'i')
|
|
|
|
}
|
|
|
|
|
2018-12-03 14:08:33 +08:00
|
|
|
prefixer = postcss().use(
|
|
|
|
autoprefixer({
|
2022-03-09 16:32:52 +08:00
|
|
|
overrideBrowserslist: options.browsers
|
2018-12-03 14:08:33 +08:00
|
|
|
})
|
|
|
|
)
|
2019-02-14 13:38:11 +08:00
|
|
|
}
|
2018-12-03 14:08:33 +08:00
|
|
|
|
2019-06-10 16:18:57 +08:00
|
|
|
function deactivate() {}
|
|
|
|
|
|
|
|
exports.activate = function(ctx) {
|
2019-01-05 04:24:17 +08:00
|
|
|
__init__()
|
|
|
|
|
|
|
|
vsc.workspace.onDidChangeConfiguration(__init__)
|
|
|
|
|
2018-12-03 10:00:21 +08:00
|
|
|
vsc.workspace.onDidSaveTextDocument(doc => {
|
2019-06-10 16:18:57 +08:00
|
|
|
std.clear()
|
2018-12-03 10:00:21 +08:00
|
|
|
Compiler.filter(doc)
|
|
|
|
})
|
2018-12-21 15:57:39 +08:00
|
|
|
|
|
|
|
let cmd = vsc.commands.registerCommand('Scss2css.compile', _ => {
|
|
|
|
let editor = vsc.window.activeTextEditor
|
|
|
|
|
|
|
|
if (editor) {
|
|
|
|
Compiler.compile(editor.document)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
ctx.subscriptions.push(cmd)
|
2018-12-03 10:00:21 +08:00
|
|
|
}
|
|
|
|
exports.deactivate = deactivate
|