Files
postcss/lib/input.js
T

118 lines
2.6 KiB
JavaScript

let { resolve, isAbsolute } = require('path')
let { nanoid } = require('nanoid/non-secure')
let terminalHighlight = require('./terminal-highlight')
let CssSyntaxError = require('./css-syntax-error')
let PreviousMap = require('./previous-map')
class Input {
constructor (css, opts = {}) {
if (
css === null ||
typeof css === 'undefined' ||
(typeof css === 'object' && !css.toString)
) {
throw new Error(`PostCSS received ${css} instead of CSS string`)
}
this.css = css.toString()
if (this.css[0] === '\uFEFF' || this.css[0] === '\uFFFE') {
this.hasBOM = true
this.css = this.css.slice(1)
} else {
this.hasBOM = false
}
if (opts.from) {
if (/^\w+:\/\//.test(opts.from) || isAbsolute(opts.from)) {
this.file = opts.from
} else {
this.file = resolve(opts.from)
}
}
let map = new PreviousMap(this.css, opts)
if (map.text) {
this.map = map
let file = map.consumer().file
if (!this.file && file) this.file = this.mapResolve(file)
}
if (!this.file) {
this.id = '<input css ' + nanoid(6) + '>'
}
if (this.map) this.map.file = this.from
}
error (message, line, column, opts = {}) {
let result
let origin = this.origin(line, column)
if (origin) {
result = new CssSyntaxError(
message,
origin.line,
origin.column,
origin.source,
origin.file,
opts.plugin
)
} else {
result = new CssSyntaxError(
message,
line,
column,
this.css,
this.file,
opts.plugin
)
}
result.input = { line, column, source: this.css }
if (this.file) result.input.file = this.file
return result
}
origin (line, column) {
if (!this.map) return false
let consumer = this.map.consumer()
let from = consumer.originalPositionFor({ line, column })
if (!from.source) return false
let result = {
file: this.mapResolve(from.source),
line: from.line,
column: from.column
}
let source = consumer.sourceContentFor(from.source)
if (source) result.source = source
return result
}
mapResolve (file) {
if (/^\w+:\/\//.test(file)) {
return file
}
return resolve(this.map.consumer().sourceRoot || '.', file)
}
get from () {
return this.file || this.id
}
}
module.exports = Input
terminalHighlight.registerInput(Input)
/**
* @typedef {object} filePosition
* @property {string} file Path to file.
* @property {number} line Source line in file.
* @property {number} column Source column in file.
*/