@shapeshift-labs/frontier-lang-css 0.1.7 → 0.1.9

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/dist/index.d.ts CHANGED
@@ -13,6 +13,7 @@ export interface CssProjectionOptions {
13
13
  readonly cssModuleCompositionGraphHash?: string;
14
14
  readonly icssGraphHash?: string;
15
15
  readonly scopedCascadeGraphHash?: string;
16
+ readonly selectorTargetGraphHash?: string;
16
17
  readonly targetPath?: string;
17
18
  readonly semanticIndexId?: string;
18
19
  readonly sourceSpansBySemanticNodeId?: Readonly<Record<string, CssSourceSpan>>;
@@ -143,6 +144,7 @@ export interface CssSemanticRecord {
143
144
  readonly scopeKey?: string;
144
145
  readonly statementText?: string;
145
146
  readonly scopedCascadeGraphHash?: string;
147
+ readonly selectorTargetGraphHash?: string;
146
148
  readonly sourceSpan: CssSourceSpan;
147
149
  readonly sourceHash: string;
148
150
  readonly parser?: 'postcss' | string;
@@ -222,86 +224,90 @@ export interface CssSemanticSheet {
222
224
  }
223
225
 
224
226
  export interface CssSemanticMergeEvidence {
225
- readonly kind: 'frontier.lang.cssSemanticMergeEvidence';
226
- readonly version: 1;
227
- readonly status: 'ready' | 'needs-review' | string;
228
- readonly sourcePath?: string;
229
- readonly sourceHash: string;
230
- readonly sheetHash: string;
227
+ readonly kind: 'frontier.lang.cssSemanticMergeEvidence'; readonly version: 1;
228
+ readonly status: 'ready' | 'needs-review' | string; readonly sourcePath?: string; readonly sourceHash: string; readonly sheetHash: string;
231
229
  readonly records: readonly CssSemanticRecord[];
232
230
  readonly cssModules?: CssModuleEvidence;
233
231
  readonly proofGaps: readonly CssSemanticProofGap[];
234
- readonly autoMergeClaim: false;
235
- readonly semanticEquivalenceClaim: false;
236
- readonly cssModuleGeneratedNameEquivalenceClaim: false;
237
- readonly cssModuleUseSiteEquivalenceClaim: false;
238
- readonly browserCascadeEquivalenceClaim: false;
239
- readonly browserRenderEquivalenceClaim: false;
232
+ readonly autoMergeClaim: false; readonly semanticEquivalenceClaim: false;
233
+ readonly cssModuleGeneratedNameEquivalenceClaim: false; readonly cssModuleUseSiteEquivalenceClaim: false;
234
+ readonly browserCascadeEquivalenceClaim: false; readonly browserRenderEquivalenceClaim: false;
240
235
  }
241
236
 
242
237
  export interface CssSafeMergeConflict {
243
- readonly code: string;
244
- readonly gateId: 'css-semantic-merge' | string;
245
- readonly sourcePath?: string;
238
+ readonly code: string; readonly gateId: 'css-semantic-merge' | string; readonly sourcePath?: string;
246
239
  readonly details: Readonly<Record<string, unknown>> & { readonly reasonCode: string; readonly conflictKey: string };
247
240
  }
248
241
 
249
242
  export interface CssSafeMergeAdmission {
250
- readonly status: 'auto-merge-candidate' | 'blocked' | string;
251
- readonly action: 'apply-css' | 'human-review' | string;
252
- readonly reviewRequired: boolean;
253
- readonly reasonCodes: readonly string[];
243
+ readonly status: 'auto-merge-candidate' | 'blocked' | string; readonly action: 'apply-css' | 'human-review' | string;
244
+ readonly reviewRequired: boolean; readonly reasonCodes: readonly string[];
254
245
  }
255
246
 
256
247
  export interface CssSafeMergeResult {
257
- readonly kind: 'frontier.lang.cssSafeMerge';
258
- readonly version: 1;
259
- readonly id: string;
260
- readonly sourcePath?: string;
261
- readonly status: 'merged' | 'blocked' | string;
262
- readonly operation: string;
263
- readonly mergedSourceText?: string;
264
- readonly mergedSourceHash?: string;
248
+ readonly kind: 'frontier.lang.cssSafeMerge'; readonly version: 1; readonly id: string; readonly sourcePath?: string;
249
+ readonly status: 'merged' | 'blocked' | string; readonly operation: string;
250
+ readonly mergedSourceText?: string; readonly mergedSourceHash?: string;
265
251
  readonly conflicts: readonly CssSafeMergeConflict[];
266
252
  readonly admission: CssSafeMergeAdmission;
267
- readonly autoMergeClaim: false;
268
- readonly semanticEquivalenceClaim: false;
269
- readonly baseSheetHash?: string;
270
- readonly workerSheetHash?: string;
271
- readonly headSheetHash?: string;
272
- readonly workerChangedDeclarations?: number;
273
- readonly headChangedDeclarations?: number;
274
- readonly workerChangedCssModuleContracts?: number;
275
- readonly headChangedCssModuleContracts?: number;
276
- readonly parserEvidence?: CssSafeMergeParserEvidence;
253
+ readonly autoMergeClaim: false; readonly semanticEquivalenceClaim: false;
254
+ readonly baseSheetHash?: string; readonly workerSheetHash?: string; readonly headSheetHash?: string;
255
+ readonly workerChangedDeclarations?: number; readonly headChangedDeclarations?: number;
256
+ readonly workerChangedCssModuleContracts?: number; readonly headChangedCssModuleContracts?: number;
257
+ readonly parserEvidence?: CssSafeMergeParserEvidence; readonly selectorTargetEvidence?: CssSafeMergeSelectorTargetEvidence;
277
258
  }
278
259
 
279
260
  export interface CssSafeMergeParserEvidence {
280
- readonly kind: 'frontier.lang.cssSafeMergeParserEvidence';
281
- readonly version: 1;
282
- readonly parserNames: readonly string[];
261
+ readonly kind: 'frontier.lang.cssSafeMergeParserEvidence'; readonly version: 1; readonly parserNames: readonly string[];
283
262
  readonly sourceCodeLocationInfo: boolean; readonly parserBackedSourceSpans: boolean; readonly parserBackedDeclarationSpans: boolean; readonly parserBackedTriviaHashes: boolean;
284
- readonly scopedCascadeGraphHashPresent: boolean; readonly parseErrors: number;
285
- readonly sides: Readonly<Record<string, CssSafeMergeParserSideEvidence>>;
263
+ readonly scopedCascadeGraphHashPresent: boolean; readonly parseErrors: number; readonly sides: Readonly<Record<string, CssSafeMergeParserSideEvidence>>;
286
264
  }
287
265
 
288
266
  export interface CssSafeMergeParserSideEvidence {
289
- readonly parserName: string;
290
- readonly sourceCodeLocationInfo: boolean; readonly parserBackedSourceSpans: boolean; readonly parserBackedDeclarationSpans: boolean; readonly parserBackedTriviaHashes: boolean;
267
+ readonly parserName: string; readonly sourceCodeLocationInfo: boolean; readonly parserBackedSourceSpans: boolean; readonly parserBackedDeclarationSpans: boolean; readonly parserBackedTriviaHashes: boolean;
291
268
  readonly scopedCascadeGraphHashPresent: boolean; readonly parseErrors: number; readonly recordCount: number; readonly declarationCount: number;
292
269
  }
293
270
 
271
+ export interface CssSafeMergeSelectorTargetEvidence {
272
+ readonly kind: 'frontier.lang.cssSafeMergeSelectorTargetEvidence'; readonly version: 1; readonly selectorTargetGraphHashPresent: boolean; readonly parserBackedRuleSpans: boolean;
273
+ readonly selectorMoveCount: number; readonly workerSelectorMoves: number; readonly headSelectorMoves: number;
274
+ readonly sides: Readonly<Record<string, CssSafeMergeSelectorTargetSideEvidence>>;
275
+ readonly moves: Readonly<Record<'worker' | 'head', readonly CssSafeMergeSelectorMove[]>>;
276
+ readonly rebasedChangeCount?: number; readonly rebaseProofs?: readonly CssSafeMergeSelectorTargetRebaseProof[];
277
+ }
278
+
279
+ export interface CssSafeMergeSelectorTargetSideEvidence {
280
+ readonly ruleCount: number; readonly selectorCount: number; readonly declarationCount: number; readonly scopedRuleCount: number;
281
+ readonly selectorTargetGraphHashPresent: boolean; readonly parserBackedRuleSpans: boolean; readonly selectorSpecificityRecords: number;
282
+ }
283
+
284
+ export interface CssSafeMergeSelectorMove {
285
+ readonly side: string; readonly property: string; readonly beforeRuleKey: string; readonly afterRuleKey: string;
286
+ readonly beforeSelectors?: readonly string[]; readonly afterSelectors?: readonly string[]; readonly beforeScopes?: readonly string[]; readonly afterScopes?: readonly string[];
287
+ readonly declarationHash: string; readonly beforeSelectorTargetGraphHash?: string; readonly afterSelectorTargetGraphHash?: string; readonly selectorTargetGraphHashPresent: boolean;
288
+ }
289
+
290
+ export interface CssSafeMergeSelectorTargetRebaseProof {
291
+ readonly kind: 'css-selector-target-rebase'; readonly side: string; readonly fromRuleKey: string; readonly toRuleKey: string; readonly property: string; readonly cascadeKey: string;
292
+ }
293
+
294
+ export interface CssSelectorTargetEquivalence {
295
+ readonly fromRuleKey?: string; readonly toRuleKey?: string; readonly fromSelectors?: readonly string[]; readonly toSelectors?: readonly string[]; readonly graphHash?: string;
296
+ }
297
+
294
298
  export interface CssSafeMergeInput {
295
299
  readonly id?: string; readonly sourcePath?: string; readonly baseSourceText?: string; readonly workerSourceText?: string; readonly headSourceText?: string;
296
300
  readonly cssModule?: boolean; readonly cssModules?: boolean;
297
301
  readonly generatedClassNameMap?: Readonly<Record<string, string>>;
298
302
  readonly generatedClassNameMapHash?: string; readonly jsTsUseSiteGraphHash?: string; readonly cssModuleCompositionGraphHash?: string; readonly icssGraphHash?: string; readonly scopedCascadeGraphHash?: string;
303
+ readonly selectorTargetGraphHash?: string; readonly selectorTargetEquivalences?: readonly CssSelectorTargetEquivalence[];
299
304
  readonly baseGeneratedClassNameMap?: Readonly<Record<string, string>>; readonly workerGeneratedClassNameMap?: Readonly<Record<string, string>>; readonly headGeneratedClassNameMap?: Readonly<Record<string, string>>;
300
305
  readonly baseGeneratedClassNameMapHash?: string; readonly workerGeneratedClassNameMapHash?: string; readonly headGeneratedClassNameMapHash?: string;
301
306
  readonly baseJsTsUseSiteGraphHash?: string; readonly workerJsTsUseSiteGraphHash?: string; readonly headJsTsUseSiteGraphHash?: string;
302
307
  readonly baseCssModuleCompositionGraphHash?: string; readonly workerCssModuleCompositionGraphHash?: string; readonly headCssModuleCompositionGraphHash?: string;
303
308
  readonly baseIcssGraphHash?: string; readonly workerIcssGraphHash?: string; readonly headIcssGraphHash?: string;
304
309
  readonly baseScopedCascadeGraphHash?: string; readonly workerScopedCascadeGraphHash?: string; readonly headScopedCascadeGraphHash?: string;
310
+ readonly baseSelectorTargetGraphHash?: string; readonly workerSelectorTargetGraphHash?: string; readonly headSelectorTargetGraphHash?: string;
305
311
  }
306
312
 
307
313
  export declare function toCssAst(document: FrontierLangDocument, options?: CssProjectionOptions): CssAstStylesheet;
@@ -61,6 +61,7 @@ function postcssRuleRecord(node, scopes, sourceHash, options) {
61
61
  })),
62
62
  customProperties: declarations.filter((declaration) => declaration.property.startsWith('--')).map((declaration) => declaration.property),
63
63
  scopedCascadeGraphHash: scopes.length ? options.scopedCascadeGraphHash : undefined,
64
+ selectorTargetGraphHash: options.selectorTargetGraphHash,
64
65
  sourceSpan: sourceSpanFromPostcss(node.source, options.sourcePath),
65
66
  sourceHash,
66
67
  rawTextHash: hashSemanticValue({ kind: 'frontier.lang.css.rawRuleText.v1', text: node.toString() }),
@@ -9,7 +9,8 @@ function sheetOptions(input, side, sourcePath) {
9
9
  jsTsUseSiteGraphHash: input[`${prefix}JsTsUseSiteGraphHash`] ?? input.jsTsUseSiteGraphHash,
10
10
  cssModuleCompositionGraphHash: input[`${prefix}CssModuleCompositionGraphHash`] ?? input.cssModuleCompositionGraphHash,
11
11
  icssGraphHash: input[`${prefix}IcssGraphHash`] ?? input.icssGraphHash,
12
- scopedCascadeGraphHash: input[`${prefix}ScopedCascadeGraphHash`] ?? input.scopedCascadeGraphHash
12
+ scopedCascadeGraphHash: input[`${prefix}ScopedCascadeGraphHash`] ?? input.scopedCascadeGraphHash,
13
+ selectorTargetGraphHash: input[`${prefix}SelectorTargetGraphHash`] ?? input.selectorTargetGraphHash
13
14
  };
14
15
  }
15
16
 
@@ -0,0 +1,139 @@
1
+ function mergeSelectorTargetEvidence(sheets, changed) {
2
+ const entries = Object.entries(sheets).map(([side, sheet]) => [side, sheetSelectorTargetEvidence(sheet)]);
3
+ const moves = { worker: selectorTargetMoves(changed.worker, 'worker'), head: selectorTargetMoves(changed.head, 'head') };
4
+ return {
5
+ kind: 'frontier.lang.cssSafeMergeSelectorTargetEvidence',
6
+ version: 1,
7
+ selectorTargetGraphHashPresent: entries.every(([, evidence]) => evidence.selectorTargetGraphHashPresent === true),
8
+ parserBackedRuleSpans: entries.every(([, evidence]) => evidence.parserBackedRuleSpans === true),
9
+ selectorMoveCount: moves.worker.length + moves.head.length,
10
+ workerSelectorMoves: moves.worker.length,
11
+ headSelectorMoves: moves.head.length,
12
+ sides: Object.fromEntries(entries),
13
+ moves
14
+ };
15
+ }
16
+
17
+ function sheetSelectorTargetEvidence(sheet) {
18
+ const rules = (sheet.records ?? []).filter((record) => record.kind === 'rule');
19
+ return {
20
+ ruleCount: rules.length,
21
+ selectorCount: rules.reduce((sum, record) => sum + (record.selectors?.length ?? 0), 0),
22
+ declarationCount: rules.reduce((sum, record) => sum + (record.declarations?.length ?? 0), 0),
23
+ scopedRuleCount: rules.filter((record) => (record.scopes ?? []).length > 0).length,
24
+ selectorTargetGraphHashPresent: rules.length === 0 || rules.every((record) => Boolean(record.selectorTargetGraphHash)),
25
+ parserBackedRuleSpans: rules.every((record) => record.parser === 'postcss' && record.sourceSpan?.startOffset !== undefined),
26
+ selectorSpecificityRecords: rules.filter((record) => Array.isArray(record.specificity)).length
27
+ };
28
+ }
29
+
30
+ function selectorTargetMoves(changes, side) {
31
+ const deletions = changes.filter((change) => change.kind === 'delete' && change.before);
32
+ const additions = changes.filter((change) => change.kind === 'add' && change.after);
33
+ const moves = [];
34
+ const usedAdditions = new Set();
35
+ for (const deletion of deletions) {
36
+ const addition = additions.find((candidate) => !usedAdditions.has(candidate) && sameDeclarationTargetSignature(deletion.before, candidate.after) && deletion.before.ruleKey !== candidate.after.ruleKey);
37
+ if (!addition) continue;
38
+ usedAdditions.add(addition);
39
+ moves.push({
40
+ side,
41
+ property: deletion.before.property,
42
+ beforeRuleKey: deletion.before.ruleKey,
43
+ afterRuleKey: addition.after.ruleKey,
44
+ beforeSelectors: deletion.before.selectors,
45
+ afterSelectors: addition.after.selectors,
46
+ beforeScopes: deletion.before.scopes,
47
+ afterScopes: addition.after.scopes,
48
+ declarationHash: addition.after.declarationHash,
49
+ beforeSelectorTargetGraphHash: deletion.before.selectorTargetGraphHash,
50
+ afterSelectorTargetGraphHash: addition.after.selectorTargetGraphHash,
51
+ selectorTargetGraphHashPresent: Boolean(deletion.before.selectorTargetGraphHash && addition.after.selectorTargetGraphHash)
52
+ });
53
+ }
54
+ return moves;
55
+ }
56
+
57
+ function planSelectorTargetRebase(id, sourcePath, selectorTargetEvidence, changed, options = {}) {
58
+ const planned = { worker: [...changed.worker], head: [...changed.head] };
59
+ const worker = selectorTargetMoveSidePlan(id, sourcePath, selectorTargetEvidence.moves.worker, selectorTargetEvidence.moves.head, planned.head, options);
60
+ const head = selectorTargetMoveSidePlan(id, sourcePath, selectorTargetEvidence.moves.head, selectorTargetEvidence.moves.worker, planned.worker, options);
61
+ return {
62
+ changed: planned,
63
+ conflicts: [...worker.conflicts, ...head.conflicts],
64
+ evidence: { ...selectorTargetEvidence, rebasedChangeCount: worker.rebaseProofs.length + head.rebaseProofs.length, rebaseProofs: [...worker.rebaseProofs, ...head.rebaseProofs] }
65
+ };
66
+ }
67
+
68
+ function selectorTargetMoveSidePlan(id, sourcePath, moves, oppositeMoves, oppositeChanges, options) {
69
+ const conflicts = [];
70
+ const rebaseProofs = [];
71
+ for (const move of moves) {
72
+ if (oppositeMoves.some((oppositeMove) => sameSelectorMove(move, oppositeMove))) continue;
73
+ for (let index = 0; index < oppositeChanges.length; index += 1) {
74
+ const change = oppositeChanges[index];
75
+ if (!selectorMoveTouchesChange(move, change)) continue;
76
+ if (canRebaseChange(move, change, options)) {
77
+ const rebased = rebaseChangeToSelectorMove(change, move);
78
+ oppositeChanges[index] = rebased.change;
79
+ rebaseProofs.push(rebased.proof);
80
+ } else conflicts.push(conflict(id, sourcePath, change.key, move, change));
81
+ }
82
+ }
83
+ return { conflicts, rebaseProofs };
84
+ }
85
+
86
+ function canRebaseChange(move, change, options) {
87
+ return change.kind === 'add' && change.after && hasSelectorTargetEquivalence(move, options);
88
+ }
89
+
90
+ function hasSelectorTargetEquivalence(move, options) {
91
+ return (options.selectorTargetEquivalences ?? []).some((entry) => {
92
+ const ruleKeysMatch = entry.fromRuleKey === move.beforeRuleKey && entry.toRuleKey === move.afterRuleKey;
93
+ const selectorsMatch = selectorListKey(entry.fromSelectors) === selectorListKey(move.beforeSelectors) && selectorListKey(entry.toSelectors) === selectorListKey(move.afterSelectors);
94
+ const graphMatches = !entry.graphHash || entry.graphHash === move.beforeSelectorTargetGraphHash || entry.graphHash === move.afterSelectorTargetGraphHash;
95
+ return graphMatches && (ruleKeysMatch || selectorsMatch);
96
+ });
97
+ }
98
+
99
+ function rebaseChangeToSelectorMove(change, move) {
100
+ const after = { ...change.after, ruleKey: move.afterRuleKey, selectors: move.afterSelectors, scopes: move.afterScopes ?? [], key: cascadeKey(move.afterScopes, move.afterSelectors, change.after.property), rebasedFromRuleKey: move.beforeRuleKey };
101
+ return {
102
+ change: { ...change, key: after.key, after },
103
+ proof: { kind: 'css-selector-target-rebase', side: change.side, fromRuleKey: move.beforeRuleKey, toRuleKey: move.afterRuleKey, property: change.after.property, cascadeKey: after.key }
104
+ };
105
+ }
106
+
107
+ function conflict(id, sourcePath, cascadeKey, selectorMove, change) {
108
+ return {
109
+ code: 'css-selector-target-conflict',
110
+ gateId: 'css-semantic-merge',
111
+ sourcePath,
112
+ details: {
113
+ reasonCode: 'css-selector-target-rebase-unproved',
114
+ conflictKey: `css#${id}#css-selector-target-rebase-unproved#${cascadeKey ?? sourcePath ?? 'source'}`,
115
+ cascadeKey,
116
+ selectorMove,
117
+ opposite: changeDetails(change)
118
+ }
119
+ };
120
+ }
121
+
122
+ function selectorMoveTouchesChange(move, change) {
123
+ const entry = change.after ?? change.before;
124
+ return entry?.ruleKey === move.beforeRuleKey || entry?.ruleKey === move.afterRuleKey;
125
+ }
126
+
127
+ function sameDeclarationTargetSignature(left, right) {
128
+ return Boolean(left && right && left.property === right.property && left.value === right.value && left.important === right.important);
129
+ }
130
+
131
+ function sameSelectorMove(left, right) {
132
+ return left.property === right.property && left.beforeRuleKey === right.beforeRuleKey && left.afterRuleKey === right.afterRuleKey && left.declarationHash === right.declarationHash;
133
+ }
134
+
135
+ function cascadeKey(scopes = [], selectors = [], property) { return [...scopes, selectors.join(','), property].join('::'); }
136
+ function selectorListKey(value = []) { return Array.isArray(value) ? value.join(',') : undefined; }
137
+ function changeDetails(change) { return { kind: change.kind, property: (change.after ?? change.before)?.property, value: change.after?.value, important: change.after?.important }; }
138
+
139
+ export { mergeSelectorTargetEvidence, planSelectorTargetRebase };
@@ -1,4 +1,5 @@
1
1
  import { cssModuleContractChanges, cssModuleContractConflicts, sheetOptions, unsupportedSourceShapeConflicts } from './semantic-merge-css-modules.js';
2
+ import { mergeSelectorTargetEvidence, planSelectorTargetRebase } from './semantic-merge-selector-targets.js';
2
3
 
3
4
  function safeMergeCssSource(input = {}, context = {}) {
4
5
  const parseSheet = context.parseCssSemanticSheet;
@@ -29,10 +30,11 @@ function safeMergeCssSource(input = {}, context = {}) {
29
30
  ];
30
31
  const moduleConflicts = cssModuleContractConflicts(id, sourcePath, moduleChanges);
31
32
  const sourceShapeConflicts = unsupportedSourceShapeConflicts(id, sourcePath, sheets, changed, hash);
32
- const conflicts = [...parserConflicts, ...proofConflicts, ...overlapConflicts, ...moduleConflicts, ...sourceShapeConflicts];
33
33
  const parserEvidence = mergeParserEvidence(sheets);
34
- if (conflicts.length) return blocked(id, sourcePath, 'css-semantic-merge-conflict', conflicts, { parserEvidence });
35
- const mergedIndex = applyDeclarationChanges(applyDeclarationChanges(indexes.base, changed.head), changed.worker);
34
+ const selectorTargetPlan = planSelectorTargetRebase(id, sourcePath, mergeSelectorTargetEvidence(sheets, changed), changed, input);
35
+ const conflicts = [...parserConflicts, ...proofConflicts, ...overlapConflicts, ...moduleConflicts, ...sourceShapeConflicts, ...selectorTargetPlan.conflicts];
36
+ if (conflicts.length) return blocked(id, sourcePath, 'css-semantic-merge-conflict', conflicts, { parserEvidence, selectorTargetEvidence: selectorTargetPlan.evidence });
37
+ const mergedIndex = applyDeclarationChanges(applyDeclarationChanges(indexes.base, selectorTargetPlan.changed.head), selectorTargetPlan.changed.worker);
36
38
  return merged(id, sourcePath, renderDeclarationIndex(mergedIndex), 'semantic-declaration-merge', hash, {
37
39
  baseSheetHash: sheets.base.sheetHash,
38
40
  workerSheetHash: sheets.worker.sheetHash,
@@ -41,7 +43,8 @@ function safeMergeCssSource(input = {}, context = {}) {
41
43
  headChangedDeclarations: changed.head.length,
42
44
  workerChangedCssModuleContracts: moduleChanges.worker.length,
43
45
  headChangedCssModuleContracts: moduleChanges.head.length,
44
- parserEvidence
46
+ parserEvidence,
47
+ selectorTargetEvidence: selectorTargetPlan.evidence
45
48
  });
46
49
  }
47
50
 
@@ -71,6 +74,7 @@ function declarationIndex(sheet) {
71
74
  value: declaration.value,
72
75
  important: declaration.important,
73
76
  declarationHash: declaration.declarationHash,
77
+ selectorTargetGraphHash: record.selectorTargetGraphHash,
74
78
  proofGaps: proofGapsForDeclaration(record, declaration)
75
79
  };
76
80
  declarations.set(entry.key, entry);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshift-labs/frontier-lang-css",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "CSS semantic merge evidence and projection adapter for Frontier Lang semantic source documents.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",