Comparing version
@@ -22,2 +22,7 @@ import { CssSyntaxError, ProcessOptions } from './postcss.js' | ||
/** | ||
* Offset of exclusive end position in source file. | ||
*/ | ||
endOffset?: number | ||
/** | ||
* Absolute path to the source file. | ||
@@ -33,2 +38,7 @@ */ | ||
/** | ||
* Offset of inclusive start position in source file. | ||
*/ | ||
offset: number | ||
/** | ||
* Source code. | ||
@@ -136,2 +146,5 @@ */ | ||
/** | ||
* Returns `CssSyntaxError` with information about the error and its position. | ||
*/ | ||
error( | ||
@@ -157,5 +170,2 @@ message: string, | ||
): CssSyntaxError | ||
/** | ||
* Returns `CssSyntaxError` with information about the error and its position. | ||
*/ | ||
error( | ||
@@ -172,3 +182,13 @@ message: string, | ||
): CssSyntaxError | ||
/** | ||
* Converts source line and column to offset. | ||
* | ||
* @param line Source line. | ||
* @param column Source column. | ||
* @return Source offset. | ||
*/ | ||
fromLineAndColumn(line: number, column: number): number | ||
/** | ||
* Converts source offset to line and column. | ||
@@ -179,2 +199,3 @@ * | ||
fromOffset(offset: number): { col: number; line: number } | null | ||
/** | ||
@@ -181,0 +202,0 @@ * Reads the input source map and returns a symbol position |
@@ -12,3 +12,3 @@ 'use strict' | ||
let fromOffsetCache = Symbol('fromOffsetCache') | ||
let lineToIndexCache = Symbol('lineToIndexCache') | ||
@@ -18,2 +18,17 @@ let sourceMapAvailable = Boolean(SourceMapConsumer && SourceMapGenerator) | ||
function getLineToIndex(input) { | ||
if (input[lineToIndexCache]) return input[lineToIndexCache] | ||
let lines = input.css.split('\n') | ||
let lineToIndex = new Array(lines.length) | ||
let prevIndex = 0 | ||
for (let i = 0, l = lines.length; i < l; i++) { | ||
lineToIndex[i] = prevIndex | ||
prevIndex += lines[i].length + 1 | ||
} | ||
input[lineToIndexCache] = lineToIndex | ||
return lineToIndex | ||
} | ||
class Input { | ||
@@ -73,3 +88,3 @@ get from() { | ||
error(message, line, column, opts = {}) { | ||
let endColumn, endLine, result | ||
let endColumn, endLine, endOffset, offset, result | ||
@@ -80,3 +95,4 @@ if (line && typeof line === 'object') { | ||
if (typeof start.offset === 'number') { | ||
let pos = this.fromOffset(start.offset) | ||
offset = start.offset | ||
let pos = this.fromOffset(offset) | ||
line = pos.line | ||
@@ -87,5 +103,7 @@ column = pos.col | ||
column = start.column | ||
offset = this.fromLineAndColumn(line, column) | ||
} | ||
if (typeof end.offset === 'number') { | ||
let pos = this.fromOffset(end.offset) | ||
endOffset = end.offset | ||
let pos = this.fromOffset(endOffset) | ||
endLine = pos.line | ||
@@ -96,7 +114,11 @@ endColumn = pos.col | ||
endColumn = end.column | ||
endOffset = this.fromLineAndColumn(end.line, end.column) | ||
} | ||
} else if (!column) { | ||
let pos = this.fromOffset(line) | ||
offset = line | ||
let pos = this.fromOffset(offset) | ||
line = pos.line | ||
column = pos.col | ||
} else { | ||
offset = this.fromLineAndColumn(line, column) | ||
} | ||
@@ -129,3 +151,3 @@ | ||
result.input = { column, endColumn, endLine, line, source: this.css } | ||
result.input = { column, endColumn, endLine, endOffset, line, offset, source: this.css } | ||
if (this.file) { | ||
@@ -141,20 +163,12 @@ if (pathToFileURL) { | ||
fromLineAndColumn(line, column) { | ||
let lineToIndex = getLineToIndex(this) | ||
let index = lineToIndex[line - 1] | ||
return index + column - 1 | ||
} | ||
fromOffset(offset) { | ||
let lastLine, lineToIndex | ||
if (!this[fromOffsetCache]) { | ||
let lines = this.css.split('\n') | ||
lineToIndex = new Array(lines.length) | ||
let prevIndex = 0 | ||
let lineToIndex = getLineToIndex(this) | ||
let lastLine = lineToIndex[lineToIndex.length - 1] | ||
for (let i = 0, l = lines.length; i < l; i++) { | ||
lineToIndex[i] = prevIndex | ||
prevIndex += lines[i].length + 1 | ||
} | ||
this[fromOffsetCache] = lineToIndex | ||
} else { | ||
lineToIndex = this[fromOffsetCache] | ||
} | ||
lastLine = lineToIndex[lineToIndex.length - 1] | ||
let min = 0 | ||
@@ -161,0 +175,0 @@ if (offset >= lastLine) { |
import AtRule = require('./at-rule.js') | ||
import { AtRuleProps } from './at-rule.js' | ||
@@ -69,2 +68,18 @@ import Comment, { CommentProps } from './comment.js' | ||
* code of a node. | ||
* | ||
* However, `end.offset` of a non `Root` node is the exclusive position. | ||
* See https://github.com/postcss/postcss/pull/1879 for details. | ||
* | ||
* ```js | ||
* const root = postcss.parse('a { color: black }') | ||
* const a = root.first | ||
* const color = a.first | ||
* | ||
* // The offset of `Root` node is the inclusive position | ||
* css.source.end // { line: 1, column: 19, offset: 18 } | ||
* | ||
* // The offset of non `Root` node is the exclusive position | ||
* a.source.end // { line: 1, column: 18, offset: 18 } | ||
* color.source.end // { line: 1, column: 16, offset: 16 } | ||
* ``` | ||
*/ | ||
@@ -428,3 +443,3 @@ end?: Position | ||
rangeBy( | ||
opts?: Pick<WarningOptions, 'endIndex' | 'index' | 'word'> | ||
opts?: Pick<WarningOptions, 'end' | 'endIndex' | 'index' | 'start' | 'word'> | ||
): Node.Range | ||
@@ -431,0 +446,0 @@ |
@@ -37,7 +37,4 @@ 'use strict' | ||
// Not all custom syntaxes support `offset` in `source.start` and `source.end` | ||
if ( | ||
position && | ||
typeof position.offset !== 'undefined' | ||
) { | ||
return position.offset; | ||
if (position && typeof position.offset !== 'undefined') { | ||
return position.offset | ||
} | ||
@@ -212,3 +209,3 @@ | ||
positionBy(opts) { | ||
positionBy(opts = {}) { | ||
let pos = this.source.start | ||
@@ -218,5 +215,6 @@ if (opts.index) { | ||
} else if (opts.word) { | ||
let inputString = ('document' in this.source.input) | ||
? this.source.input.document | ||
: this.source.input.css | ||
let inputString = | ||
'document' in this.source.input | ||
? this.source.input.document | ||
: this.source.input.css | ||
let stringRepresentation = inputString.slice( | ||
@@ -235,5 +233,6 @@ sourceOffset(inputString, this.source.start), | ||
let line = this.source.start.line | ||
let inputString = ('document' in this.source.input) | ||
? this.source.input.document | ||
: this.source.input.css | ||
let inputString = | ||
'document' in this.source.input | ||
? this.source.input.document | ||
: this.source.input.css | ||
let offset = sourceOffset(inputString, this.source.start) | ||
@@ -251,3 +250,3 @@ let end = offset + index | ||
return { column, line } | ||
return { column, line, offset: end } | ||
} | ||
@@ -261,6 +260,11 @@ | ||
rangeBy(opts) { | ||
rangeBy(opts = {}) { | ||
let inputString = | ||
'document' in this.source.input | ||
? this.source.input.document | ||
: this.source.input.css | ||
let start = { | ||
column: this.source.start.column, | ||
line: this.source.start.line | ||
line: this.source.start.line, | ||
offset: sourceOffset(inputString, this.source.start) | ||
} | ||
@@ -270,13 +274,19 @@ let end = this.source.end | ||
column: this.source.end.column + 1, | ||
line: this.source.end.line | ||
line: this.source.end.line, | ||
offset: | ||
typeof this.source.end.offset === 'number' | ||
? // `source.end.offset` is exclusive, so we don't need to add 1 | ||
this.source.end.offset | ||
: // Since line/column in this.source.end is inclusive, | ||
// the `sourceOffset(... , this.source.end)` returns an inclusive offset. | ||
// So, we add 1 to convert it to exclusive. | ||
sourceOffset(inputString, this.source.end) + 1 | ||
} | ||
: { | ||
column: start.column + 1, | ||
line: start.line | ||
line: start.line, | ||
offset: start.offset + 1 | ||
} | ||
if (opts.word) { | ||
let inputString = ('document' in this.source.input) | ||
? this.source.input.document | ||
: this.source.input.css | ||
let stringRepresentation = inputString.slice( | ||
@@ -289,5 +299,3 @@ sourceOffset(inputString, this.source.start), | ||
start = this.positionInside(index) | ||
end = this.positionInside( | ||
index + opts.word.length, | ||
) | ||
end = this.positionInside(index + opts.word.length) | ||
} | ||
@@ -298,3 +306,4 @@ } else { | ||
column: opts.start.column, | ||
line: opts.start.line | ||
line: opts.start.line, | ||
offset: sourceOffset(inputString, opts.start) | ||
} | ||
@@ -308,3 +317,4 @@ } else if (opts.index) { | ||
column: opts.end.column, | ||
line: opts.end.line | ||
line: opts.end.line, | ||
offset: sourceOffset(inputString, opts.end) | ||
} | ||
@@ -322,3 +332,7 @@ } else if (typeof opts.endIndex === 'number') { | ||
) { | ||
end = { column: start.column + 1, line: start.line } | ||
end = { | ||
column: start.column + 1, | ||
line: start.line, | ||
offset: start.offset + 1 | ||
} | ||
} | ||
@@ -398,2 +412,3 @@ | ||
} else if (name === 'source') { | ||
if (value == null) continue | ||
let inputId = inputs.get(value.input) | ||
@@ -438,3 +453,3 @@ if (inputId == null) { | ||
warn(result, text, opts) { | ||
warn(result, text, opts = {}) { | ||
let data = { node: this } | ||
@@ -441,0 +456,0 @@ for (let i in opts) data[i] = opts[i] |
@@ -10,3 +10,3 @@ 'use strict' | ||
constructor(plugins = []) { | ||
this.version = '8.5.3' | ||
this.version = '8.5.4' | ||
this.plugins = this.normalize(plugins) | ||
@@ -13,0 +13,0 @@ } |
@@ -15,3 +15,3 @@ 'use strict' | ||
this.opts = opts | ||
this.css = undefined | ||
this.css = '' | ||
this.map = undefined | ||
@@ -18,0 +18,0 @@ } |
@@ -28,3 +28,3 @@ import { | ||
document(node: Document): void | ||
raw(node: AnyNode, own: null | string, detect?: string): string | ||
raw(node: AnyNode, own: null | string, detect?: string): boolean | string | ||
rawBeforeClose(root: Root): string | undefined | ||
@@ -39,3 +39,3 @@ rawBeforeComment(root: Root, node: Comment): string | undefined | ||
rawSemicolon(root: Root): boolean | undefined | ||
rawValue(node: AnyNode, prop: string): string | ||
rawValue(node: AnyNode, prop: string): number | string | ||
root(node: Root): void | ||
@@ -42,0 +42,0 @@ rule(node: Rule): void |
{ | ||
"name": "postcss", | ||
"version": "8.5.3", | ||
"version": "8.5.4", | ||
"description": "Tool for transforming styles with JS plugins", | ||
@@ -77,3 +77,3 @@ "engines": { | ||
"dependencies": { | ||
"nanoid": "^3.3.8", | ||
"nanoid": "^3.3.11", | ||
"picocolors": "^1.1.1", | ||
@@ -80,0 +80,0 @@ "source-map-js": "^1.2.1" |
@@ -12,3 +12,3 @@ # PostCSS | ||
PostCSS is used by industry leaders including Wikipedia, Twitter, Alibaba, | ||
and JetBrains. The [Autoprefixer] and [Stylelint] PostCSS plugins is one of the most popular CSS tools. | ||
and JetBrains. The [Autoprefixer] and [Stylelint] PostCSS plugins are some of the most popular CSS tools. | ||
@@ -15,0 +15,0 @@ --- |
204295
1.15%7010
0.85%Updated