Commit 8e4d2c53 authored by 张俊's avatar 张俊

[feat]更新转化文件

parent 7062b53f
......@@ -22,44 +22,411 @@ function dealVueStyleNode(dirPath, partten) {
files.forEach(file => dealVueStyleNodeSingleFile(path.resolve(dirPath, file)));
}
const rewriter = vueStyleRewriter();
function dealVueStyleNodeSingleFile(file) {
const html = fs.readFileSync(file, 'utf-8');
let styleIndex = 0;
const rewritedHtml = rewriter(html, (style) => {
// 使用 cheerio 加载 HTML 文档
// 第三个参数表示不加载到document中
const $ = cheerio.load(html, {
const $ = cheerio.load(style, {
lowerCaseTags: false,
xmlMode: true,
normalizeWhitespace: false,
decodeEntities: false,
}, false);
// 修改 HTML 文档中的内容
$('style').each((index, styleEl) => {
styleEl = $(styleEl);
const lang = styleEl.attr('lang');
if (!lang || lang == 'scss') {
if (!lang || lang.indexOf('scss') == 0) {
const scssString = styleEl.text();
try {
const result = parseScss(scssString, file);
styleEl.text(result.css);
console.log(`file: ${file} style-node: ${index} deal style success.`);
styleEl.text(`
${result.css}
`);
console.log(`file: ${file} style-node: ${styleIndex} deal style success.`);
} catch (e) {
console.warn(`file: ${file} style-node: ${index} deal style error.`, e);
console.warn(`file: ${file} style-node: ${styleIndex} deal style error.`, e);
}
styleEl.attr('lang', 'css');
if (lang && lang.indexOf('scoped') >= 0) {
styleEl.attr('scoped', true);
}
})
if ($('style').length) {
fs.writeFileSync(file, $.html());
styleEl.attr('lang', 'css');
}
});
styleIndex ++;
return $.html();
});
if (styleIndex > 0) {
// // 将修改后的 HTML 文档写入文件
// fs.writeFileSync('index.html', $.html());
fs.writeFileSync(file, rewritedHtml);
}
}
function parseScss(scssString, file) {
const result = sass.compileString(scssString, { url: file });
const replaceTagSelector = 'tag::replace';
const result = sass.compileString(`${replaceTagSelector} {${scssString}}`, { url: file });
result.css = result.css
// + "\n\t" + result.css
.replace(/tag::replace([\.:\[])/g, '&$1')
.replace(/tag::replace[\s]*[\{]/g, '& {')
.replace(/tag::replace[\s]*/g, '');
return result;
}
dealVueStyleNode(dirPath, partten);
function vueStyleRewriter() {
// 从 node_modules\vue-template-compiler\build.js 中 复用解析代码
/**
* Always return false.
*/
const no = (a, b, c) => false;
// HTML5 tags https://html.spec.whatwg.org/multipage/indices.html#elements-3
// Phrasing Content https://html.spec.whatwg.org/multipage/dom.html#phrasing-content
const isNonPhrasingTag = makeMap('address,article,aside,base,blockquote,body,caption,col,colgroup,dd,' +
'details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,' +
'h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,' +
'optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,' +
'title,tr,track');
/**
* Make a map and return a function for checking if a key
* is in that map.
*/
function makeMap(str, expectsLowerCase) {
const map = Object.create(null);
const list = str.split(',');
for (let i = 0; i < list.length; i++) {
map[list[i]] = true;
}
return expectsLowerCase ? val => map[val.toLowerCase()] : val => map[val];
}
const unicodeRegExp = /a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/;
/**
* Not type-checking this file because it's mostly vendor code.
*/
// Regular Expressions for parsing tags and attributes
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/;
const dynamicArgAttribute = /^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+?\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/;
const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z${unicodeRegExp.source}]*`;
const qnameCapture = `((?:${ncname}\\:)?${ncname})`;
const startTagOpen = new RegExp(`^<${qnameCapture}`);
const startTagClose = /^\s*(\/?)>/;
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`);
const doctype = /^<!DOCTYPE [^>]+>/i;
// #7298: escape - to avoid being passed as HTML comment when inlined in page
const comment = /^<!\--/;
const conditionalComment = /^<!\[/;
// Special Elements (can contain anything)
const isPlainTextElement = makeMap('script,style', true);
const reCache = {};
const decodingMap = {
'&lt;': '<',
'&gt;': '>',
'&quot;': '"',
'&amp;': '&',
'&#10;': '\n',
'&#9;': '\t',
'&#39;': "'"
};
const encodedAttr = /&(?:lt|gt|quot|amp|#39);/g;
const encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#39|#10|#9);/g;
// #5992
const isIgnoreNewlineTag = makeMap('pre,textarea', true);
const shouldIgnoreFirstNewline = (tag, html) => tag && isIgnoreNewlineTag(tag) && html[0] === '\n';
function decodeAttr(value, shouldDecodeNewlines) {
const re = shouldDecodeNewlines ? encodedAttrWithNewLines : encodedAttr;
return value.replace(re, match => decodingMap[match]);
}
function parseHTML(html, options) {
const stack = [];
const expectHTML = options.expectHTML;
const isUnaryTag = options.isUnaryTag || no;
const canBeLeftOpenTag = options.canBeLeftOpenTag || no;
let index = 0;
let last, lastTag;
while (html) {
last = html;
// Make sure we're not in a plaintext content element like script/style
if (!lastTag || !isPlainTextElement(lastTag)) {
let textEnd = html.indexOf('<');
if (textEnd === 0) {
// Comment:
if (comment.test(html)) {
const commentEnd = html.indexOf('-->');
if (commentEnd >= 0) {
if (options.shouldKeepComment && options.comment) {
options.comment(html.substring(4, commentEnd), index, index + commentEnd + 3);
}
advance(commentEnd + 3);
continue;
}
}
// http://en.wikipedia.org/wiki/Conditional_comment#Downlevel-revealed_conditional_comment
if (conditionalComment.test(html)) {
const conditionalEnd = html.indexOf(']>');
if (conditionalEnd >= 0) {
advance(conditionalEnd + 2);
continue;
}
}
// Doctype:
const doctypeMatch = html.match(doctype);
if (doctypeMatch) {
advance(doctypeMatch[0].length);
continue;
}
// End tag:
const endTagMatch = html.match(endTag);
if (endTagMatch) {
const curIndex = index;
advance(endTagMatch[0].length);
parseEndTag(endTagMatch[1], curIndex, index);
continue;
}
// Start tag:
const startTagMatch = parseStartTag();
if (startTagMatch) {
handleStartTag(startTagMatch);
if (shouldIgnoreFirstNewline(startTagMatch.tagName, html)) {
advance(1);
}
continue;
}
}
let text, rest, next;
if (textEnd >= 0) {
rest = html.slice(textEnd);
while (!endTag.test(rest) &&
!startTagOpen.test(rest) &&
!comment.test(rest) &&
!conditionalComment.test(rest)) {
// < in plain text, be forgiving and treat it as text
next = rest.indexOf('<', 1);
if (next < 0)
break;
textEnd += next;
rest = html.slice(textEnd);
}
text = html.substring(0, textEnd);
}
if (textEnd < 0) {
text = html;
}
if (text) {
advance(text.length);
}
if (options.chars && text) {
options.chars(text, index - text.length, index);
}
}
else {
let endTagLength = 0;
const stackedTag = lastTag.toLowerCase();
const reStackedTag = reCache[stackedTag] ||
(reCache[stackedTag] = new RegExp('([\\s\\S]*?)(</' + stackedTag + '[^>]*>)', 'i'));
const rest = html.replace(reStackedTag, function (all, text, endTag) {
endTagLength = endTag.length;
if (!isPlainTextElement(stackedTag) && stackedTag !== 'noscript') {
text = text
.replace(/<!\--([\s\S]*?)-->/g, '$1') // #7298
.replace(/<!\[CDATA\[([\s\S]*?)]]>/g, '$1');
}
if (shouldIgnoreFirstNewline(stackedTag, text)) {
text = text.slice(1);
}
if (options.chars) {
options.chars(text);
}
return '';
});
index += html.length - rest.length;
html = rest;
parseEndTag(stackedTag, index - endTagLength, index);
}
if (html === last) {
options.chars && options.chars(html);
if (process.env.NODE_ENV !== 'production' && !stack.length && options.warn) {
options.warn(`Mal-formatted tag at end of template: "${html}"`, {
start: index + html.length
});
}
break;
}
}
// Clean up any remaining tags
parseEndTag();
function advance(n) {
index += n;
html = html.substring(n);
}
function parseStartTag() {
const start = html.match(startTagOpen);
if (start) {
const match = {
tagName: start[1],
attrs: [],
start: index
};
advance(start[0].length);
let end, attr;
while (!(end = html.match(startTagClose)) &&
(attr = html.match(dynamicArgAttribute) || html.match(attribute))) {
attr.start = index;
advance(attr[0].length);
attr.end = index;
match.attrs.push(attr);
}
if (end) {
match.unarySlash = end[1];
advance(end[0].length);
match.end = index;
return match;
}
}
}
function handleStartTag(match) {
const tagName = match.tagName;
const unarySlash = match.unarySlash;
if (expectHTML) {
if (lastTag === 'p' && isNonPhrasingTag(tagName)) {
parseEndTag(lastTag);
}
if (canBeLeftOpenTag(tagName) && lastTag === tagName) {
parseEndTag(tagName);
}
}
const unary = isUnaryTag(tagName) || !!unarySlash;
const l = match.attrs.length;
const attrs = new Array(l);
for (let i = 0; i < l; i++) {
const args = match.attrs[i];
const value = args[3] || args[4] || args[5] || '';
const shouldDecodeNewlines = tagName === 'a' && args[1] === 'href'
? options.shouldDecodeNewlinesForHref
: options.shouldDecodeNewlines;
attrs[i] = {
name: args[1],
value: decodeAttr(value, shouldDecodeNewlines)
};
if (process.env.NODE_ENV !== 'production' && options.outputSourceRange) {
attrs[i].start = args.start + args[0].match(/^\s*/).length;
attrs[i].end = args.end;
}
}
if (!unary) {
stack.push({
tag: tagName,
lowerCasedTag: tagName.toLowerCase(),
attrs: attrs,
start: match.start,
end: match.end
});
lastTag = tagName;
}
if (options.start) {
options.start(tagName, attrs, unary, match.start, match.end);
}
}
function parseEndTag(tagName, start, end) {
let pos, lowerCasedTagName;
if (start == null)
start = index;
if (end == null)
end = index;
// Find the closest opened tag of the same type
if (tagName) {
lowerCasedTagName = tagName.toLowerCase();
for (pos = stack.length - 1; pos >= 0; pos--) {
if (stack[pos].lowerCasedTag === lowerCasedTagName) {
break;
}
}
}
else {
// If no tag name is provided, clean shop
pos = 0;
}
if (pos >= 0) {
// Close all the open elements, up the stack
for (let i = stack.length - 1; i >= pos; i--) {
if (process.env.NODE_ENV !== 'production' && (i > pos || !tagName) && options.warn) {
options.warn(`tag <${stack[i].tag}> has no matching end tag.`, {
start: stack[i].start,
end: stack[i].end
});
}
if (options.end) {
options.end(stack[i].tag, start, end);
}
}
// Remove the open elements from the stack
stack.length = pos;
lastTag = pos && stack[pos - 1].tag;
}
else if (lowerCasedTagName === 'br') {
if (options.start) {
options.start(tagName, [], true, start, end);
}
}
else if (lowerCasedTagName === 'p') {
if (options.start) {
options.start(tagName, [], false, start, end);
}
if (options.end) {
options.end(tagName, start, end);
}
}
}
}
return function parseVUE(vueString, replaceStyle) {
const items = [];
let currentParent;
parseHTML(vueString, {
shouldKeepComment: true,
start(tag, attrs, unary, start, end) {
if (!unary) {
currentParent = {
tag, attrs, unary, start, end
};
}
else {
currentParent = null;
}
if (currentParent != null && currentParent.tag == 'style') {
} else {
items.push(vueString.substring(start, end));
}
},
end(tag, start, end) {
if (currentParent != null && currentParent.tag == 'style') {
const tagStr = vueString.substring(currentParent.start, end);
items.push(replaceStyle(tagStr));
} else {
items.push(vueString.substring(start, end));
}
currentParent = null;
},
chars(text, start, end) {
if (currentParent != null && currentParent.tag == 'style') {
} else {
items.push(text);
}
},
comment(text, start, end) {
// adding anything as a sibling to the root node is forbidden
// comments should still be allowed, but ignored
items.push(vueString.substring(start, end));
}
})
return items.join("")
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment