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.
127 lines
2.8 KiB
127 lines
2.8 KiB
"use strict"; |
|
const reNewLine = /(?:\r?\n|\r)/gm; |
|
const Input = require("postcss/lib/input"); |
|
const Document = require("./document"); |
|
const getSyntax = require("./get-syntax"); |
|
const patch = require("./patch-postcss"); |
|
|
|
class LocalFixer { |
|
constructor (lines, style) { |
|
let line = 0; |
|
let column = style.startIndex; |
|
lines.some((lineEndIndex, lineNumber) => { |
|
if (lineEndIndex >= style.startIndex) { |
|
line = lineNumber--; |
|
if (lineNumber in lines) { |
|
column = style.startIndex - lines[lineNumber] - 1; |
|
} |
|
return true; |
|
} |
|
}); |
|
|
|
this.line = line; |
|
this.column = column; |
|
this.style = style; |
|
} |
|
object (object) { |
|
if (object) { |
|
if (object.line === 1) { |
|
object.column += this.column; |
|
} |
|
object.line += this.line; |
|
} |
|
} |
|
node (node) { |
|
this.object(node.source.start); |
|
this.object(node.source.end); |
|
} |
|
root (root) { |
|
this.node(root); |
|
root.walk(node => { |
|
this.node(node); |
|
}); |
|
} |
|
error (error) { |
|
if (error && error.name === "CssSyntaxError") { |
|
this.object(error); |
|
this.object(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 || getSyntax(style.lang, opts); |
|
let root = style.root; |
|
try { |
|
root = syntax.parse(style.content, Object.assign({}, opts, { |
|
map: false, |
|
}, style.opts)); |
|
} catch (error) { |
|
if (style.ignoreErrors) { |
|
return; |
|
} else if (!style.skipConvert) { |
|
this.error(error); |
|
} |
|
throw error; |
|
} |
|
if (!style.skipConvert) { |
|
this.root(root); |
|
} |
|
|
|
root.source.inline = Boolean(style.inline); |
|
root.source.lang = style.lang; |
|
root.source.syntax = syntax; |
|
return root; |
|
} |
|
} |
|
|
|
function docFixer (source, opts) { |
|
let match; |
|
const lines = []; |
|
reNewLine.lastIndex = 0; |
|
while ((match = reNewLine.exec(source))) { |
|
lines.push(match.index); |
|
} |
|
lines.push(source.length); |
|
return function parseStyle (style) { |
|
return new LocalFixer(lines, style).parse(opts); |
|
}; |
|
} |
|
|
|
function parseStyle (source, opts, styles) { |
|
patch(Document); |
|
|
|
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.beforeStart = source.slice(index, style.startIndex); |
|
if (style.endIndex) { |
|
index = style.endIndex; |
|
} else { |
|
index = style.startIndex + (style.content || root.source.input.css).length; |
|
} |
|
root.document = document; |
|
document.nodes.push(root); |
|
} |
|
}); |
|
} |
|
document.raws.afterEnd = index ? source.slice(index) : source; |
|
document.source = { |
|
input: new Input(source, opts), |
|
start: { |
|
line: 1, |
|
column: 1, |
|
}, |
|
opts, |
|
}; |
|
return document; |
|
} |
|
module.exports = parseStyle;
|
|
|