@ismail-elkorchi/css-parser 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -69
- package/dist/internal/cssom/declarations.d.ts +36 -0
- package/dist/internal/cssom/declarations.js +177 -0
- package/dist/internal/generated/css-data.d.ts +2 -0
- package/dist/internal/generated/css-data.js +16229 -0
- package/dist/internal/grammar/catalog-types.d.ts +26 -0
- package/dist/internal/grammar/value-definition.d.ts +63 -0
- package/dist/internal/grammar/value-definition.js +439 -0
- package/dist/internal/properties/matcher.d.ts +29 -0
- package/dist/internal/properties/matcher.js +791 -0
- package/dist/internal/properties/registry.d.ts +24 -0
- package/dist/internal/properties/registry.js +52 -0
- package/dist/internal/selectors/matcher.d.ts +96 -0
- package/dist/internal/selectors/matcher.js +616 -0
- package/dist/internal/selectors/parser.d.ts +2 -0
- package/dist/internal/selectors/parser.js +702 -0
- package/dist/internal/selectors/specificity.d.ts +3 -0
- package/dist/internal/selectors/specificity.js +77 -0
- package/dist/internal/selectors/types.d.ts +110 -0
- package/dist/internal/syntax/ast.d.ts +70 -0
- package/dist/internal/syntax/ast.js +1 -0
- package/dist/internal/syntax/characters.d.ts +8 -0
- package/dist/internal/syntax/characters.js +45 -0
- package/dist/internal/syntax/encoding.d.ts +15 -0
- package/dist/internal/syntax/encoding.js +161 -0
- package/dist/internal/syntax/input.d.ts +23 -0
- package/dist/internal/syntax/input.js +184 -0
- package/dist/internal/syntax/parser.d.ts +26 -0
- package/dist/internal/syntax/parser.js +581 -0
- package/dist/internal/syntax/resources.d.ts +28 -0
- package/dist/internal/syntax/resources.js +135 -0
- package/dist/internal/syntax/serialize.d.ts +10 -0
- package/dist/internal/syntax/serialize.js +630 -0
- package/dist/internal/syntax/token-stream.d.ts +16 -0
- package/dist/internal/syntax/token-stream.js +66 -0
- package/dist/internal/syntax/tokenizer.d.ts +21 -0
- package/dist/internal/syntax/tokenizer.js +571 -0
- package/dist/internal/syntax/tokens.d.ts +115 -0
- package/dist/internal/syntax/tokens.js +1 -0
- package/dist/internal/syntax/types.d.ts +46 -0
- package/dist/internal/syntax/types.js +1 -0
- package/dist/mod.d.ts +7 -1
- package/dist/mod.js +7 -1
- package/dist/public/edits.d.ts +12 -0
- package/dist/public/edits.js +195 -0
- package/dist/public/mod.d.ts +13 -35
- package/dist/public/mod.js +12 -1740
- package/dist/public/parse.d.ts +37 -0
- package/dist/public/parse.js +298 -0
- package/dist/public/traversal.d.ts +13 -0
- package/dist/public/traversal.js +96 -0
- package/dist/public/types.d.ts +78 -264
- package/package.json +32 -53
- package/THIRD_PARTY_NOTICES.md +0 -19
- package/dist/internal/csstree-runtime.d.ts +0 -20
- package/dist/internal/csstree-runtime.js +0 -21
- package/dist/internal/encoding/mod.d.ts +0 -1
- package/dist/internal/encoding/mod.js +0 -1
- package/dist/internal/encoding/sniff.d.ts +0 -14
- package/dist/internal/encoding/sniff.js +0 -95
- package/dist/internal/serializer/mod.d.ts +0 -1
- package/dist/internal/serializer/mod.js +0 -1
- package/dist/internal/serializer/serialize.d.ts +0 -3
- package/dist/internal/serializer/serialize.js +0 -89
- package/dist/internal/tokenizer/mod.d.ts +0 -2
- package/dist/internal/tokenizer/mod.js +0 -1
- package/dist/internal/tokenizer/tokenize.d.ts +0 -2
- package/dist/internal/tokenizer/tokenize.js +0 -39
- package/dist/internal/tokenizer/tokens.d.ts +0 -23
- package/dist/internal/tree/build.d.ts +0 -2
- package/dist/internal/tree/build.js +0 -85
- package/dist/internal/tree/mod.d.ts +0 -2
- package/dist/internal/tree/mod.js +0 -1
- package/dist/internal/tree/types.d.ts +0 -25
- package/dist/internal/vendor/csstree/LICENSE +0 -19
- package/dist/internal/vendor/csstree/csstree.esm.js +0 -12
- package/dist/internal/version.d.ts +0 -1
- package/dist/internal/version.js +0 -1
- package/dist/public/index.d.ts +0 -1
- package/dist/public/index.js +0 -1
- /package/dist/internal/{tokenizer/tokens.js → grammar/catalog-types.js} +0 -0
- /package/dist/internal/{tree → selectors}/types.js +0 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type { ResourceUsage, SourcePosition, SourceSpan } from "./types.js";
|
|
2
|
+
interface TokenBase {
|
|
3
|
+
readonly span: SourceSpan;
|
|
4
|
+
}
|
|
5
|
+
export interface IdentToken extends TokenBase {
|
|
6
|
+
readonly kind: "ident";
|
|
7
|
+
readonly value: string;
|
|
8
|
+
}
|
|
9
|
+
export interface FunctionToken extends TokenBase {
|
|
10
|
+
readonly kind: "function";
|
|
11
|
+
readonly value: string;
|
|
12
|
+
}
|
|
13
|
+
export interface AtKeywordToken extends TokenBase {
|
|
14
|
+
readonly kind: "at-keyword";
|
|
15
|
+
readonly value: string;
|
|
16
|
+
}
|
|
17
|
+
export interface HashToken extends TokenBase {
|
|
18
|
+
readonly kind: "hash";
|
|
19
|
+
readonly value: string;
|
|
20
|
+
readonly hashType: "id" | "unrestricted";
|
|
21
|
+
}
|
|
22
|
+
export interface StringToken extends TokenBase {
|
|
23
|
+
readonly kind: "string";
|
|
24
|
+
readonly value: string;
|
|
25
|
+
}
|
|
26
|
+
export interface BadStringToken extends TokenBase {
|
|
27
|
+
readonly kind: "bad-string";
|
|
28
|
+
}
|
|
29
|
+
export interface UrlToken extends TokenBase {
|
|
30
|
+
readonly kind: "url";
|
|
31
|
+
readonly value: string;
|
|
32
|
+
}
|
|
33
|
+
export interface BadUrlToken extends TokenBase {
|
|
34
|
+
readonly kind: "bad-url";
|
|
35
|
+
}
|
|
36
|
+
export interface DelimToken extends TokenBase {
|
|
37
|
+
readonly kind: "delim";
|
|
38
|
+
readonly value: number;
|
|
39
|
+
}
|
|
40
|
+
export interface NumericValue {
|
|
41
|
+
readonly value: number;
|
|
42
|
+
readonly numberType: "integer" | "number";
|
|
43
|
+
readonly representation: string;
|
|
44
|
+
readonly sign: "+" | "-" | null;
|
|
45
|
+
}
|
|
46
|
+
export interface NumberToken extends TokenBase, NumericValue {
|
|
47
|
+
readonly kind: "number";
|
|
48
|
+
}
|
|
49
|
+
export interface PercentageToken extends TokenBase, NumericValue {
|
|
50
|
+
readonly kind: "percentage";
|
|
51
|
+
}
|
|
52
|
+
export interface DimensionToken extends TokenBase, NumericValue {
|
|
53
|
+
readonly kind: "dimension";
|
|
54
|
+
readonly unit: string;
|
|
55
|
+
}
|
|
56
|
+
export interface UnicodeRangeToken extends TokenBase {
|
|
57
|
+
readonly kind: "unicode-range";
|
|
58
|
+
readonly start: number;
|
|
59
|
+
readonly end: number;
|
|
60
|
+
}
|
|
61
|
+
export interface WhitespaceToken extends TokenBase {
|
|
62
|
+
readonly kind: "whitespace";
|
|
63
|
+
}
|
|
64
|
+
export interface CdoToken extends TokenBase {
|
|
65
|
+
readonly kind: "cdo";
|
|
66
|
+
}
|
|
67
|
+
export interface CdcToken extends TokenBase {
|
|
68
|
+
readonly kind: "cdc";
|
|
69
|
+
}
|
|
70
|
+
export interface ColonToken extends TokenBase {
|
|
71
|
+
readonly kind: "colon";
|
|
72
|
+
}
|
|
73
|
+
export interface SemicolonToken extends TokenBase {
|
|
74
|
+
readonly kind: "semicolon";
|
|
75
|
+
}
|
|
76
|
+
export interface CommaToken extends TokenBase {
|
|
77
|
+
readonly kind: "comma";
|
|
78
|
+
}
|
|
79
|
+
export interface OpenSquareToken extends TokenBase {
|
|
80
|
+
readonly kind: "open-square";
|
|
81
|
+
}
|
|
82
|
+
export interface CloseSquareToken extends TokenBase {
|
|
83
|
+
readonly kind: "close-square";
|
|
84
|
+
}
|
|
85
|
+
export interface OpenParenToken extends TokenBase {
|
|
86
|
+
readonly kind: "open-paren";
|
|
87
|
+
}
|
|
88
|
+
export interface CloseParenToken extends TokenBase {
|
|
89
|
+
readonly kind: "close-paren";
|
|
90
|
+
}
|
|
91
|
+
export interface OpenCurlyToken extends TokenBase {
|
|
92
|
+
readonly kind: "open-curly";
|
|
93
|
+
}
|
|
94
|
+
export interface CloseCurlyToken extends TokenBase {
|
|
95
|
+
readonly kind: "close-curly";
|
|
96
|
+
}
|
|
97
|
+
export interface EofToken extends TokenBase {
|
|
98
|
+
readonly kind: "eof";
|
|
99
|
+
}
|
|
100
|
+
export type CssToken = IdentToken | FunctionToken | AtKeywordToken | HashToken | StringToken | BadStringToken | UrlToken | BadUrlToken | DelimToken | NumberToken | PercentageToken | DimensionToken | UnicodeRangeToken | WhitespaceToken | CdoToken | CdcToken | ColonToken | SemicolonToken | CommaToken | OpenSquareToken | CloseSquareToken | OpenParenToken | CloseParenToken | OpenCurlyToken | CloseCurlyToken | EofToken;
|
|
101
|
+
export type TokenizerDiagnosticCode = "unexpected-eof-in-comment" | "unexpected-eof-in-string" | "newline-in-string" | "unexpected-eof-in-escape" | "invalid-escape" | "unexpected-eof-in-url" | "invalid-url";
|
|
102
|
+
export interface TokenizerDiagnostic {
|
|
103
|
+
readonly kind: "tokenizer";
|
|
104
|
+
readonly code: TokenizerDiagnosticCode;
|
|
105
|
+
readonly message: string;
|
|
106
|
+
readonly span: SourceSpan;
|
|
107
|
+
readonly specRef: string;
|
|
108
|
+
}
|
|
109
|
+
export interface TokenizationResult {
|
|
110
|
+
readonly tokens: readonly Exclude<CssToken, EofToken>[];
|
|
111
|
+
readonly errors: readonly TokenizerDiagnostic[];
|
|
112
|
+
readonly end: SourcePosition;
|
|
113
|
+
readonly usage: ResourceUsage;
|
|
114
|
+
}
|
|
115
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export interface SourcePosition {
|
|
2
|
+
readonly offset: number;
|
|
3
|
+
readonly line: number;
|
|
4
|
+
readonly column: number;
|
|
5
|
+
}
|
|
6
|
+
export interface SourceSpan {
|
|
7
|
+
readonly start: SourcePosition;
|
|
8
|
+
readonly end: SourcePosition;
|
|
9
|
+
}
|
|
10
|
+
export interface InputCodePoint {
|
|
11
|
+
readonly value: number;
|
|
12
|
+
readonly span: SourceSpan;
|
|
13
|
+
}
|
|
14
|
+
export type ResourceLimitName = "maxInputBytes" | "maxBufferedBytes" | "maxTokens" | "maxNodes" | "maxDepth" | "maxSteps";
|
|
15
|
+
export interface ResourceLimits {
|
|
16
|
+
readonly maxInputBytes?: number;
|
|
17
|
+
readonly maxBufferedBytes?: number;
|
|
18
|
+
readonly maxTokens?: number;
|
|
19
|
+
readonly maxNodes?: number;
|
|
20
|
+
readonly maxDepth?: number;
|
|
21
|
+
readonly maxSteps?: number;
|
|
22
|
+
}
|
|
23
|
+
export type TokenizerResourceLimits = Pick<ResourceLimits, "maxInputBytes" | "maxTokens" | "maxSteps">;
|
|
24
|
+
export type ParserResourceLimits = Pick<ResourceLimits, "maxInputBytes" | "maxTokens" | "maxNodes" | "maxDepth" | "maxSteps">;
|
|
25
|
+
export type StreamTokenizerResourceLimits = TokenizerResourceLimits & Pick<ResourceLimits, "maxBufferedBytes">;
|
|
26
|
+
export type StreamParserResourceLimits = ParserResourceLimits & Pick<ResourceLimits, "maxBufferedBytes">;
|
|
27
|
+
export type SelectorResourceLimits = Pick<ResourceLimits, "maxNodes" | "maxDepth" | "maxSteps">;
|
|
28
|
+
export interface ResourceUsage {
|
|
29
|
+
readonly inputBytes: number;
|
|
30
|
+
readonly maxBufferedBytes: number;
|
|
31
|
+
readonly tokens: number;
|
|
32
|
+
readonly nodes: number;
|
|
33
|
+
readonly maxDepth: number;
|
|
34
|
+
readonly steps: number;
|
|
35
|
+
}
|
|
36
|
+
export interface EncodingOptions {
|
|
37
|
+
readonly transportEncodingLabel?: string;
|
|
38
|
+
readonly environmentEncodingLabel?: string;
|
|
39
|
+
readonly defaultEncodingLabel?: string;
|
|
40
|
+
readonly maxCharsetBytes?: number;
|
|
41
|
+
}
|
|
42
|
+
export interface EncodingDecision {
|
|
43
|
+
readonly encoding: string;
|
|
44
|
+
readonly source: "bom" | "transport" | "charset" | "environment" | "default";
|
|
45
|
+
readonly bomBytes: number;
|
|
46
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/mod.d.ts
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Standards-based CSS parsing, serialization, traversal, editing, property,
|
|
3
|
+
* declaration-block, and selector APIs.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
export * from "./public/mod.js";
|
package/dist/mod.js
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Standards-based CSS parsing, serialization, traversal, editing, property,
|
|
3
|
+
* declaration-block, and selector APIs.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
export * from "./public/mod.js";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CssStylesheet } from "../internal/syntax/ast.js";
|
|
2
|
+
import type { CssSourceEdit, PatchPlan, PatchPlanningErrorCode } from "./types.js";
|
|
3
|
+
export declare class PatchPlanningError extends Error {
|
|
4
|
+
readonly reason: PatchPlanningErrorCode;
|
|
5
|
+
readonly target?: number | undefined;
|
|
6
|
+
readonly code = "CSS_PATCH_PLANNING_FAILED";
|
|
7
|
+
constructor(reason: PatchPlanningErrorCode, target?: number | undefined);
|
|
8
|
+
}
|
|
9
|
+
/** Builds a deterministic source-preserving edit plan against a parsed tree. */
|
|
10
|
+
export declare function computePatch(source: string, stylesheet: CssStylesheet, edits: readonly CssSourceEdit[]): PatchPlan;
|
|
11
|
+
/** Applies a validated CSS source patch. */
|
|
12
|
+
export declare function applyPatch(source: string, plan: PatchPlan): string;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { walkCss } from "./traversal.js";
|
|
2
|
+
export class PatchPlanningError extends Error {
|
|
3
|
+
reason;
|
|
4
|
+
target;
|
|
5
|
+
code = "CSS_PATCH_PLANNING_FAILED";
|
|
6
|
+
constructor(reason, target) {
|
|
7
|
+
super(`Unable to plan CSS source edits: ${reason}` +
|
|
8
|
+
(target === undefined ? "" : ` (node ${String(target)})`));
|
|
9
|
+
this.reason = reason;
|
|
10
|
+
this.target = target;
|
|
11
|
+
this.name = "PatchPlanningError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function indexNodes(root) {
|
|
15
|
+
const nodes = new Map();
|
|
16
|
+
walkCss(root, (node) => {
|
|
17
|
+
if (nodes.has(node.id)) {
|
|
18
|
+
throw new PatchPlanningError("duplicate-node-id", node.id);
|
|
19
|
+
}
|
|
20
|
+
nodes.set(node.id, node);
|
|
21
|
+
});
|
|
22
|
+
return nodes;
|
|
23
|
+
}
|
|
24
|
+
function editRecord(value, order) {
|
|
25
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
26
|
+
throw new PatchPlanningError("invalid-edit", order);
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
function validatedEdit(value, order) {
|
|
31
|
+
const edit = editRecord(value, order);
|
|
32
|
+
const target = edit.target;
|
|
33
|
+
if (!Number.isSafeInteger(target) || target <= 0) {
|
|
34
|
+
throw new PatchPlanningError("invalid-edit", order);
|
|
35
|
+
}
|
|
36
|
+
const kind = edit.kind;
|
|
37
|
+
if (kind === "remove-node") {
|
|
38
|
+
return { kind, target: target };
|
|
39
|
+
}
|
|
40
|
+
if (kind === "replace-node" ||
|
|
41
|
+
kind === "insert-before" ||
|
|
42
|
+
kind === "insert-after") {
|
|
43
|
+
if (typeof edit.css !== "string") {
|
|
44
|
+
throw new PatchPlanningError("invalid-edit", target);
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
kind,
|
|
48
|
+
target: target,
|
|
49
|
+
css: edit.css
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
throw new PatchPlanningError("invalid-edit", target);
|
|
53
|
+
}
|
|
54
|
+
function replacementFor(source, nodes, edit, order) {
|
|
55
|
+
const node = nodes.get(edit.target);
|
|
56
|
+
if (node === undefined) {
|
|
57
|
+
throw new PatchPlanningError("node-not-found", edit.target);
|
|
58
|
+
}
|
|
59
|
+
const { start, end } = node.span;
|
|
60
|
+
if (start.offset < 0 ||
|
|
61
|
+
end.offset < start.offset ||
|
|
62
|
+
end.offset > source.length) {
|
|
63
|
+
throw new PatchPlanningError("span-out-of-bounds", edit.target);
|
|
64
|
+
}
|
|
65
|
+
switch (edit.kind) {
|
|
66
|
+
case "remove-node":
|
|
67
|
+
return { order, target: edit.target, start: start.offset, end: end.offset, text: "" };
|
|
68
|
+
case "replace-node":
|
|
69
|
+
return {
|
|
70
|
+
order,
|
|
71
|
+
target: edit.target,
|
|
72
|
+
start: start.offset,
|
|
73
|
+
end: end.offset,
|
|
74
|
+
text: edit.css
|
|
75
|
+
};
|
|
76
|
+
case "insert-before":
|
|
77
|
+
return {
|
|
78
|
+
order,
|
|
79
|
+
target: edit.target,
|
|
80
|
+
start: start.offset,
|
|
81
|
+
end: start.offset,
|
|
82
|
+
text: edit.css
|
|
83
|
+
};
|
|
84
|
+
case "insert-after":
|
|
85
|
+
return {
|
|
86
|
+
order,
|
|
87
|
+
target: edit.target,
|
|
88
|
+
start: end.offset,
|
|
89
|
+
end: end.offset,
|
|
90
|
+
text: edit.css
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/** Builds a deterministic source-preserving edit plan against a parsed tree. */
|
|
95
|
+
export function computePatch(source, stylesheet, edits) {
|
|
96
|
+
if (typeof source !== "string")
|
|
97
|
+
throw new TypeError("source must be a string");
|
|
98
|
+
if (!Array.isArray(edits)) {
|
|
99
|
+
throw new PatchPlanningError("invalid-edit");
|
|
100
|
+
}
|
|
101
|
+
const nodes = indexNodes(stylesheet);
|
|
102
|
+
const replacements = edits.map((edit, order) => replacementFor(source, nodes, validatedEdit(edit, order), order)).sort((left, right) => left.start - right.start ||
|
|
103
|
+
left.end - right.end ||
|
|
104
|
+
left.order - right.order);
|
|
105
|
+
let coveredUntil = 0;
|
|
106
|
+
for (const replacement of replacements) {
|
|
107
|
+
if (replacement.start < coveredUntil) {
|
|
108
|
+
throw new PatchPlanningError("overlapping-edits", replacement.target);
|
|
109
|
+
}
|
|
110
|
+
coveredUntil = Math.max(coveredUntil, replacement.end);
|
|
111
|
+
}
|
|
112
|
+
const operations = [];
|
|
113
|
+
let cursor = 0;
|
|
114
|
+
for (const replacement of replacements) {
|
|
115
|
+
if (cursor < replacement.start) {
|
|
116
|
+
operations.push({
|
|
117
|
+
kind: "copy",
|
|
118
|
+
start: cursor,
|
|
119
|
+
end: replacement.start
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
operations.push({
|
|
123
|
+
kind: "replace",
|
|
124
|
+
start: replacement.start,
|
|
125
|
+
end: replacement.end,
|
|
126
|
+
text: replacement.text
|
|
127
|
+
});
|
|
128
|
+
cursor = replacement.end;
|
|
129
|
+
}
|
|
130
|
+
if (cursor < source.length) {
|
|
131
|
+
operations.push({ kind: "copy", start: cursor, end: source.length });
|
|
132
|
+
}
|
|
133
|
+
const frozenOperations = Object.freeze(operations);
|
|
134
|
+
const plan = Object.freeze({
|
|
135
|
+
operations: frozenOperations,
|
|
136
|
+
result: applyOperations(source, frozenOperations)
|
|
137
|
+
});
|
|
138
|
+
return plan;
|
|
139
|
+
}
|
|
140
|
+
function applyOperations(source, operations) {
|
|
141
|
+
let cursor = 0;
|
|
142
|
+
let result = "";
|
|
143
|
+
for (const value of operations) {
|
|
144
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
145
|
+
throw new PatchPlanningError("invalid-plan");
|
|
146
|
+
}
|
|
147
|
+
const operation = value;
|
|
148
|
+
if (operation.kind === "copy") {
|
|
149
|
+
if (operation.start !== cursor ||
|
|
150
|
+
!Number.isSafeInteger(operation.end) ||
|
|
151
|
+
operation.end < cursor ||
|
|
152
|
+
operation.end > source.length) {
|
|
153
|
+
throw new PatchPlanningError("invalid-plan");
|
|
154
|
+
}
|
|
155
|
+
result += source.slice(cursor, operation.end);
|
|
156
|
+
cursor = operation.end;
|
|
157
|
+
}
|
|
158
|
+
else if (operation.kind === "replace") {
|
|
159
|
+
if (operation.start !== cursor ||
|
|
160
|
+
!Number.isSafeInteger(operation.end) ||
|
|
161
|
+
operation.end < cursor ||
|
|
162
|
+
operation.end > source.length ||
|
|
163
|
+
typeof operation.text !== "string") {
|
|
164
|
+
throw new PatchPlanningError("invalid-plan");
|
|
165
|
+
}
|
|
166
|
+
result += operation.text;
|
|
167
|
+
cursor = operation.end;
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
throw new PatchPlanningError("invalid-plan");
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (cursor !== source.length) {
|
|
174
|
+
throw new PatchPlanningError("invalid-plan");
|
|
175
|
+
}
|
|
176
|
+
return result;
|
|
177
|
+
}
|
|
178
|
+
/** Applies a validated CSS source patch. */
|
|
179
|
+
export function applyPatch(source, plan) {
|
|
180
|
+
if (typeof source !== "string")
|
|
181
|
+
throw new TypeError("source must be a string");
|
|
182
|
+
const input = plan;
|
|
183
|
+
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
184
|
+
throw new PatchPlanningError("invalid-plan");
|
|
185
|
+
}
|
|
186
|
+
const record = input;
|
|
187
|
+
if (!Array.isArray(record.operations) || typeof record.result !== "string") {
|
|
188
|
+
throw new PatchPlanningError("invalid-plan");
|
|
189
|
+
}
|
|
190
|
+
const result = applyOperations(source, record.operations);
|
|
191
|
+
if (result !== record.result) {
|
|
192
|
+
throw new PatchPlanningError("invalid-plan");
|
|
193
|
+
}
|
|
194
|
+
return result;
|
|
195
|
+
}
|
package/dist/public/mod.d.ts
CHANGED
|
@@ -1,35 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
export
|
|
12
|
-
export
|
|
13
|
-
export
|
|
14
|
-
export declare function parseDeclarationList(css: string, options?: ParseOptions): FragmentTree;
|
|
15
|
-
export declare function getParseErrorSpecRef(parseErrorId: string): string;
|
|
16
|
-
export declare function tokenize(css: string, options?: TokenizeOptions): readonly Token[];
|
|
17
|
-
export declare function tokenizeStream(stream: ReadableStream<Uint8Array>, options?: TokenizeOptions): AsyncIterable<Token>;
|
|
18
|
-
export declare function parseBytes(bytes: Uint8Array, options?: ParseOptions): StyleSheetTree;
|
|
19
|
-
export declare function parseStream(stream: ReadableStream<Uint8Array>, options?: ParseOptions): Promise<StyleSheetTree>;
|
|
20
|
-
export declare function serialize(treeOrNode: StyleSheetTree | FragmentTree | CssNode): string;
|
|
21
|
-
export declare function walk(tree: StyleSheetTree | FragmentTree, visitor: NodeVisitor): void;
|
|
22
|
-
export declare function walkByType(tree: StyleSheetTree | FragmentTree, type: string, visitor: NodeVisitor): void;
|
|
23
|
-
export declare function findById(tree: StyleSheetTree | FragmentTree, id: NodeId): CssNode | null;
|
|
24
|
-
export declare function findAllByType(tree: StyleSheetTree | FragmentTree, type: string): IterableIterator<CssNode>;
|
|
25
|
-
export declare function outline(tree: StyleSheetTree | FragmentTree): Outline;
|
|
26
|
-
export declare function chunk(tree: StyleSheetTree | FragmentTree, options?: ChunkOptions): Chunk[];
|
|
27
|
-
export declare function applyPatchPlan(originalCss: string, plan: PatchPlan): string;
|
|
28
|
-
export declare function computePatch(originalCss: string, edits: readonly Edit[]): PatchPlan;
|
|
29
|
-
export declare function compileSelectorList(selectorText: string): CompiledSelectorList;
|
|
30
|
-
export declare function extractStyleRuleSignals(cssOrTree: string | StyleSheetTree, options?: StyleSignalOptions): readonly StyleRuleSignal[];
|
|
31
|
-
export declare function extractInlineStyleSignals(styleText: string): readonly StyleDeclarationSignal[];
|
|
32
|
-
export declare function extractRenderSignals(cssOrTree: string | StyleSheetTree, options?: RenderSignalOptions): readonly RenderSignal[];
|
|
33
|
-
export declare function extractInlineRenderSignals(styleText: string, options?: RenderSignalOptions): readonly RenderSignal[];
|
|
34
|
-
export declare function matchesSelector<TNode extends SelectorNodeLike>(selector: string | CompiledSelectorList, node: TNode, root: TNode, options?: SelectorQueryOptions): boolean;
|
|
35
|
-
export declare function querySelectorAll<TNode extends SelectorNodeLike>(selector: string | CompiledSelectorList, root: TNode, options?: SelectorQueryOptions): readonly TNode[];
|
|
1
|
+
export { CssStreamError, parseBlockContents, parseCommaSeparatedComponentValues, parseComponentValue, parseComponentValues, parseDeclaration, parseRule, parseStylesheet, parseStylesheetBytes, parseStylesheetContents, parseStylesheetStream, tokenize, tokenizeBytes, tokenizeStream } from "./parse.js";
|
|
2
|
+
export { CssTreeStructureError, findNodeById, findNodesByKind, walkCss } from "./traversal.js";
|
|
3
|
+
export { applyPatch, computePatch, PatchPlanningError } from "./edits.js";
|
|
4
|
+
export { serializeCssSyntax as serialize, serializeCssComponentValues } from "../internal/syntax/serialize.js";
|
|
5
|
+
export { CssSerializationError } from "../internal/syntax/serialize.js";
|
|
6
|
+
export { SyntaxAbortError, SyntaxResourceError } from "../internal/syntax/resources.js";
|
|
7
|
+
export { CssDeclarationBlock } from "../internal/cssom/declarations.js";
|
|
8
|
+
export { resolveCssProperty } from "../internal/properties/registry.js";
|
|
9
|
+
export { validateCssPropertyValue } from "../internal/properties/matcher.js";
|
|
10
|
+
export { parseSelectorList } from "../internal/selectors/parser.js";
|
|
11
|
+
export { specificitiesOfSelectorList, specificityOfComplexSelector } from "../internal/selectors/specificity.js";
|
|
12
|
+
export { matchSelectorList, querySelectorList, SelectorTreeError } from "../internal/selectors/matcher.js";
|
|
13
|
+
export type * from "./types.js";
|