数通智联化工云平台
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

202 lines
4.0 KiB

"use strict";
const Input = require("postcss/lib/input");
const Document = require("./document");
const reNewLine = /\r?\n|\r/g;
class Locations {
constructor(source) {
let match;
const lines = [];
reNewLine.lastIndex = 0;
while ((match = reNewLine.exec(source))) {
lines.push(match.index);
}
lines.push(source.length);
this.lines = lines;
this.source = source;
}
getOffsetFromLoc(loc) {
const lineIndex = loc.line - 2;
return (lineIndex >= 0 ? this.lines[lineIndex] : -1) + loc.column;
}
getLocFromOffset(offset) {
const lines = this.lines;
for (let index = 0; index < lines.length; index++) {
const lineEndIndex = lines[index];
if (lineEndIndex >= offset) {
const before = this.lines[index - 1];
return {
line: index + 1,
column: offset - (before != null ? before : -1),
};
}
}
const before = this.lines[this.lines.length - 2];
return {
line: lines.length,
column: offset - (before != null ? before : -1),
};
}
}
class LocalFixer {
constructor(locations, style) {
const { line, column } = locations.getLocFromOffset(style.startIndex);
this.line = line - 1;
this.column = column - 1;
this.style = style;
}
fixLocation(object) {
if (object) {
if (object.line === 1) {
object.column += this.column;
}
object.line += this.line;
if (typeof object.offset === "number") {
object.offset += this.style.startIndex;
}
if (typeof object.endLine === "number") {
if (object.endLine === 1) {
object.endColumn += this.column;
}
object.endLine += this.line;
}
}
}
node(node) {
this.fixLocation(node.source.start);
this.fixLocation(node.source.end);
}
root(root) {
this.node(root);
root.walk((node) => {
this.node(node);
});
}
error(error) {
if (error && error.name === "CssSyntaxError") {
this.fixLocation(error);
this.fixLocation(error.input);
error.message = error.message.replace(
/:\d+:\d+:/,
`:${error.line}:${error.column}:`
);
}
return error;
}
parse(opts) {
const style = this.style;
const syntax = style.syntax;
let root;
try {
root = syntax.parse(
style.content,
Object.assign(
{},
opts,
{
map: false,
},
style.opts
)
);
} catch (error) {
this.error(error);
throw error;
}
this.root(root);
root.source.inline = Boolean(style.inline);
root.source.lang = style.lang;
root.source.syntax = syntax;
patchRoot(root, syntax);
return root;
}
}
function docFixer(source, opts) {
const locations = new Locations(source);
return function parseStyle(style) {
return new LocalFixer(locations, style).parse(opts);
};
}
function parseStyles(source, opts, styles) {
const document = new Document();
let index = 0;
if (styles.length) {
const parseStyle = docFixer(source, opts);
styles
.sort((a, b) => a.startIndex - b.startIndex)
.forEach((style) => {
const root = parseStyle(style);
if (root) {
root.raws.codeBefore = source.slice(index, style.startIndex);
// Note: Stylelint is still using this property.
try {
Object.defineProperty(root.raws, "beforeStart", {
configurable: true,
get() {
return root.raws.codeBefore;
},
set(value) {
root.raws.codeBefore = value;
},
});
} catch {
// ignore
}
index =
style.startIndex + (style.content || root.source.input.css).length;
root.document = document;
document.nodes.push(root);
}
});
}
const last = document.nodes[document.nodes.length - 1];
if (last) {
last.raws.codeAfter = index ? source.slice(index) : source;
}
document.source = {
input: new Input(source, opts),
start: {
line: 1,
column: 1,
},
opts,
};
return document;
}
module.exports = parseStyles;
function patchRoot(root, syntax) {
const originalToString = root.toString;
try {
Object.defineProperty(root, "toString", {
configurable: true,
enumerable: false,
value(stringifier) {
return originalToString.call(this, stringifier || syntax);
},
});
} catch {
// ignore
}
}