@flyingrobots/bijou 7.0.0 → 7.1.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 +2 -0
- package/dist/core/graphql-bijou-block.d.ts +94 -0
- package/dist/core/graphql-bijou-block.d.ts.map +1 -0
- package/dist/core/graphql-bijou-block.js +570 -0
- package/dist/core/graphql-bijou-block.js.map +1 -0
- package/dist/core/render/differ.d.ts.map +1 -1
- package/dist/core/render/differ.js +10 -1
- package/dist/core/render/differ.js.map +1 -1
- package/dist/core/theme/builder.d.ts +91 -0
- package/dist/core/theme/builder.d.ts.map +1 -0
- package/dist/core/theme/builder.js +238 -0
- package/dist/core/theme/builder.js.map +1 -0
- package/dist/core/theme/doctor.d.ts +15 -0
- package/dist/core/theme/doctor.d.ts.map +1 -1
- package/dist/core/theme/doctor.js +55 -6
- package/dist/core/theme/doctor.js.map +1 -1
- package/dist/core/theme/index.d.ts +5 -3
- package/dist/core/theme/index.d.ts.map +1 -1
- package/dist/core/theme/index.js +3 -2
- package/dist/core/theme/index.js.map +1 -1
- package/dist/core/theme/presets.d.ts +17 -1
- package/dist/core/theme/presets.d.ts.map +1 -1
- package/dist/core/theme/presets.js +135 -1
- package/dist/core/theme/presets.js.map +1 -1
- package/dist/core/ui-scene-ir.d.ts +195 -0
- package/dist/core/ui-scene-ir.d.ts.map +1 -0
- package/dist/core/ui-scene-ir.js +571 -0
- package/dist/core/ui-scene-ir.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -78,6 +78,8 @@ fake duplication rather than a real second API.
|
|
|
78
78
|
|
|
79
79
|
### Theme Authoring
|
|
80
80
|
- **`extendTheme()`**: Build a custom theme from a known-good preset.
|
|
81
|
+
- **`defineThemeSafePairs()`**: Declare reusable foreground/background
|
|
82
|
+
contrast matrices for `doctorTheme()` and inspector surfaces.
|
|
81
83
|
- **`doctorTheme()`**: Structured checks for invalid colors, weak contrast,
|
|
82
84
|
and suspicious token reuse.
|
|
83
85
|
- **`themeContrastRatio()`**: Deterministic foreground/background contrast
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { type UiLayoutIntent, type UiSceneIr, type UiSceneLoweringOptions, type UiSceneLowerMode, type UiSourceMapEntry, type UiStyleRef, type UiTargetProfile, type UiTextRef } from './ui-scene-ir.js';
|
|
2
|
+
export declare const BIJOU_BLOCK_ARTIFACT_VERSION: "bijou-block/1";
|
|
3
|
+
export declare const GRAPHQL_BIJOU_BLOCK_DEBUG_SUMMARY_VERSION: "graphql-bijou-block-debug/1";
|
|
4
|
+
export type BijouBlockArtifactVersion = typeof BIJOU_BLOCK_ARTIFACT_VERSION;
|
|
5
|
+
export type GraphqlBijouBlockDebugSummaryVersion = typeof GRAPHQL_BIJOU_BLOCK_DEBUG_SUMMARY_VERSION;
|
|
6
|
+
export interface CompileGraphqlBijouBlockOptions {
|
|
7
|
+
readonly sourceName?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface BijouBlockFieldAction {
|
|
10
|
+
readonly id: string;
|
|
11
|
+
readonly command: string;
|
|
12
|
+
readonly keybindings: readonly string[];
|
|
13
|
+
}
|
|
14
|
+
export interface BijouBlockFieldBinding {
|
|
15
|
+
readonly id: string;
|
|
16
|
+
readonly targetProperty: string;
|
|
17
|
+
readonly source: {
|
|
18
|
+
readonly kind: 'state' | 'query' | 'computed';
|
|
19
|
+
readonly path: string;
|
|
20
|
+
};
|
|
21
|
+
readonly when?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface BijouBlockGroup {
|
|
24
|
+
readonly id: string;
|
|
25
|
+
readonly label?: string;
|
|
26
|
+
readonly source: string;
|
|
27
|
+
readonly layout: UiLayoutIntent;
|
|
28
|
+
}
|
|
29
|
+
export interface BijouBlockField {
|
|
30
|
+
readonly fieldName: string;
|
|
31
|
+
readonly nodeId: string;
|
|
32
|
+
readonly groupId?: string;
|
|
33
|
+
readonly graphqlType: string;
|
|
34
|
+
readonly source: string;
|
|
35
|
+
readonly layout: UiLayoutIntent;
|
|
36
|
+
readonly text: UiTextRef;
|
|
37
|
+
readonly style?: UiStyleRef;
|
|
38
|
+
readonly action?: BijouBlockFieldAction;
|
|
39
|
+
readonly binding?: BijouBlockFieldBinding;
|
|
40
|
+
}
|
|
41
|
+
export interface BijouBlockArtifact {
|
|
42
|
+
readonly artifactVersion: BijouBlockArtifactVersion;
|
|
43
|
+
readonly id: string;
|
|
44
|
+
readonly component: string;
|
|
45
|
+
readonly sourceTypeName: string;
|
|
46
|
+
readonly sourceName: string;
|
|
47
|
+
readonly sourceHash: string;
|
|
48
|
+
readonly rootNodeId: string;
|
|
49
|
+
readonly groups: readonly BijouBlockGroup[];
|
|
50
|
+
readonly fields: readonly BijouBlockField[];
|
|
51
|
+
readonly targetProfiles: readonly UiTargetProfile[];
|
|
52
|
+
}
|
|
53
|
+
export interface GraphqlBijouBlockDebugGroupFact {
|
|
54
|
+
readonly id: string;
|
|
55
|
+
readonly label?: string;
|
|
56
|
+
readonly source: string;
|
|
57
|
+
readonly childNodeIds: readonly string[];
|
|
58
|
+
}
|
|
59
|
+
export interface GraphqlBijouBlockDebugFieldFact {
|
|
60
|
+
readonly fieldName: string;
|
|
61
|
+
readonly nodeId: string;
|
|
62
|
+
readonly groupId?: string;
|
|
63
|
+
readonly source: string;
|
|
64
|
+
readonly i18nKey?: string;
|
|
65
|
+
readonly tokenRefs: readonly string[];
|
|
66
|
+
readonly actionId?: string;
|
|
67
|
+
readonly bindingId?: string;
|
|
68
|
+
}
|
|
69
|
+
export interface GraphqlBijouBlockDebugLowerModeFact {
|
|
70
|
+
readonly mode: UiSceneLowerMode;
|
|
71
|
+
readonly surfaceHash: string;
|
|
72
|
+
readonly rows: readonly string[];
|
|
73
|
+
}
|
|
74
|
+
export interface GraphqlBijouBlockDebugSummary {
|
|
75
|
+
readonly summaryVersion: GraphqlBijouBlockDebugSummaryVersion;
|
|
76
|
+
readonly artifactVersion: BijouBlockArtifactVersion;
|
|
77
|
+
readonly artifactId: string;
|
|
78
|
+
readonly artifactHash: string;
|
|
79
|
+
readonly sceneHash: string;
|
|
80
|
+
readonly summaryHash: string;
|
|
81
|
+
readonly rootNodeId: string;
|
|
82
|
+
readonly groups: readonly GraphqlBijouBlockDebugGroupFact[];
|
|
83
|
+
readonly fields: readonly GraphqlBijouBlockDebugFieldFact[];
|
|
84
|
+
readonly sourceMap: readonly UiSourceMapEntry[];
|
|
85
|
+
readonly i18nKeys: readonly string[];
|
|
86
|
+
readonly tokenRefs: readonly string[];
|
|
87
|
+
readonly actionIds: readonly string[];
|
|
88
|
+
readonly bindingIds: readonly string[];
|
|
89
|
+
readonly lowerModes: readonly GraphqlBijouBlockDebugLowerModeFact[];
|
|
90
|
+
}
|
|
91
|
+
export declare function compileGraphqlBijouBlock(source: string, options?: CompileGraphqlBijouBlockOptions): BijouBlockArtifact;
|
|
92
|
+
export declare function lowerBijouBlockToUiScene(artifact: BijouBlockArtifact): UiSceneIr;
|
|
93
|
+
export declare function createGraphqlBijouBlockDebugSummary(artifact: BijouBlockArtifact, options?: UiSceneLoweringOptions): GraphqlBijouBlockDebugSummary;
|
|
94
|
+
//# sourceMappingURL=graphql-bijou-block.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphql-bijou-block.d.ts","sourceRoot":"","sources":["../../src/core/graphql-bijou-block.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,cAAc,EAEnB,KAAK,SAAS,EACd,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,SAAS,EAEf,MAAM,kBAAkB,CAAC;AAG1B,eAAO,MAAM,4BAA4B,EAAG,eAAwB,CAAC;AACrE,eAAO,MAAM,yCAAyC,EAAG,6BAAsC,CAAC;AAChG,MAAM,MAAM,yBAAyB,GAAG,OAAO,4BAA4B,CAAC;AAC5E,MAAM,MAAM,oCAAoC,GAAG,OAAO,yCAAyC,CAAC;AAEpG,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,UAAU,CAAC;QAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;CACjC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,qBAAqB,CAAC;IACxC,QAAQ,CAAC,OAAO,CAAC,EAAE,sBAAsB,CAAC;CAC3C;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,eAAe,EAAE,yBAAyB,CAAC;IACpD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAC;IAC5C,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAC;IAC5C,QAAQ,CAAC,cAAc,EAAE,SAAS,eAAe,EAAE,CAAC;CACrD;AAED,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,mCAAmC;IAClD,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,cAAc,EAAE,oCAAoC,CAAC;IAC9D,QAAQ,CAAC,eAAe,EAAE,yBAAyB,CAAC;IACpD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,SAAS,+BAA+B,EAAE,CAAC;IAC5D,QAAQ,CAAC,MAAM,EAAE,SAAS,+BAA+B,EAAE,CAAC;IAC5D,QAAQ,CAAC,SAAS,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAChD,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,SAAS,mCAAmC,EAAE,CAAC;CACrE;AAmCD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,+BAAoC,GAC5C,kBAAkB,CA+BpB;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,SAAS,CAoEhF;AAED,wBAAgB,mCAAmC,CACjD,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,GAAE,sBAA2B,GACnC,6BAA6B,CAiC/B"}
|
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
import { UI_SCENE_IR_VERSION, hashUiSceneValue, lowerUiSceneToTerminalProof, } from './ui-scene-ir.js';
|
|
2
|
+
export const BIJOU_BLOCK_ARTIFACT_VERSION = 'bijou-block/1';
|
|
3
|
+
export const GRAPHQL_BIJOU_BLOCK_DEBUG_SUMMARY_VERSION = 'graphql-bijou-block-debug/1';
|
|
4
|
+
const DEFAULT_SOURCE_NAME = 'inline.graphql';
|
|
5
|
+
const DEBUG_LOWER_MODES = ['normal', 'node-ids', 'i18n-keys', 'token-refs'];
|
|
6
|
+
const IDENTIFIER_PATTERN = '[A-Za-z_][A-Za-z0-9_]*';
|
|
7
|
+
const FIELD_PATTERN = new RegExp(`^(${IDENTIFIER_PATTERN})\\s*:\\s*([A-Za-z0-9_!\\[\\]]+)(.*)$`);
|
|
8
|
+
const TYPE_PATTERN = new RegExp(`^type\\s+(${IDENTIFIER_PATTERN})\\b(.*)$`);
|
|
9
|
+
const DIRECTIVE_PATTERN = new RegExp(`@(${IDENTIFIER_PATTERN})\\s*\\(((?:[^()"\\\\]|"(?:[^"\\\\]|\\\\.)*")*)\\)`, 'g');
|
|
10
|
+
const ARG_PATTERN = new RegExp(`(${IDENTIFIER_PATTERN})\\s*:\\s*("(?:[^"\\\\]|\\\\.)*"|-?\\d+)`, 'g');
|
|
11
|
+
export function compileGraphqlBijouBlock(source, options = {}) {
|
|
12
|
+
const sourceName = normalizeSourceName(options.sourceName ?? DEFAULT_SOURCE_NAME);
|
|
13
|
+
const parsed = parseConstrainedGraphqlBijouBlock(source);
|
|
14
|
+
const blockDirective = directiveByName(parsed.typeDirectives, 'bijouBlock');
|
|
15
|
+
const blockId = blockDirective == null ? undefined : optionalStringArg(blockDirective, 'id');
|
|
16
|
+
const component = blockDirective == null ? undefined : optionalStringArg(blockDirective, 'component');
|
|
17
|
+
if (blockId == null || component == null) {
|
|
18
|
+
throw new Error('GraphQL Bijou block source must include @bijouBlock(id:, component:).');
|
|
19
|
+
}
|
|
20
|
+
const targetProfiles = targetProfilesFor(parsed.typeDirectives);
|
|
21
|
+
const groups = groupsFor(parsed.typeDirectives, parsed.typeName, sourceName);
|
|
22
|
+
const fields = parsed.fields.map((field) => bijouBlockFieldFor(field, parsed.typeName, sourceName));
|
|
23
|
+
const rootNodeId = `${blockId}.root`;
|
|
24
|
+
assertUniqueBlockIdentities(groups, fields, rootNodeId);
|
|
25
|
+
const artifactBody = {
|
|
26
|
+
artifactVersion: BIJOU_BLOCK_ARTIFACT_VERSION,
|
|
27
|
+
id: blockId,
|
|
28
|
+
component,
|
|
29
|
+
sourceTypeName: parsed.typeName,
|
|
30
|
+
sourceName,
|
|
31
|
+
rootNodeId,
|
|
32
|
+
groups,
|
|
33
|
+
fields,
|
|
34
|
+
targetProfiles,
|
|
35
|
+
};
|
|
36
|
+
return {
|
|
37
|
+
...artifactBody,
|
|
38
|
+
sourceHash: hashUiSceneValue(artifactBody),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export function lowerBijouBlockToUiScene(artifact) {
|
|
42
|
+
const groups = artifact.groups ?? [];
|
|
43
|
+
assertUniqueBlockIdentities(groups, artifact.fields, artifact.rootNodeId);
|
|
44
|
+
const nodes = [
|
|
45
|
+
{
|
|
46
|
+
id: artifact.rootNodeId,
|
|
47
|
+
kind: 'group',
|
|
48
|
+
component: artifact.component,
|
|
49
|
+
children: rootChildNodeIds(groups, artifact.fields),
|
|
50
|
+
metadata: {
|
|
51
|
+
artifactVersion: artifact.artifactVersion,
|
|
52
|
+
sourceTypeName: artifact.sourceTypeName,
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
const actions = [];
|
|
57
|
+
const bindings = [];
|
|
58
|
+
const tokenUses = [];
|
|
59
|
+
const i18nUses = [];
|
|
60
|
+
const sourceMap = [];
|
|
61
|
+
for (const group of groups) {
|
|
62
|
+
nodes.push(nodeForGroup(artifact, group));
|
|
63
|
+
sourceMap.push({ nodeId: group.id, source: group.source });
|
|
64
|
+
}
|
|
65
|
+
for (const field of artifact.fields) {
|
|
66
|
+
nodes.push(nodeForField(artifact, field));
|
|
67
|
+
sourceMap.push({ nodeId: field.nodeId, source: field.source });
|
|
68
|
+
appendTokenUses(tokenUses, field);
|
|
69
|
+
appendI18nUse(i18nUses, field.nodeId, field.text);
|
|
70
|
+
if (field.action != null) {
|
|
71
|
+
actions.push({
|
|
72
|
+
id: field.action.id,
|
|
73
|
+
command: field.action.command,
|
|
74
|
+
keybindings: field.action.keybindings,
|
|
75
|
+
label: field.text,
|
|
76
|
+
targetNodeId: field.nodeId,
|
|
77
|
+
});
|
|
78
|
+
appendI18nUse(i18nUses, field.action.id, field.text, 'action');
|
|
79
|
+
}
|
|
80
|
+
if (field.binding != null) {
|
|
81
|
+
bindings.push({
|
|
82
|
+
id: field.binding.id,
|
|
83
|
+
targetNodeId: field.nodeId,
|
|
84
|
+
targetProperty: field.binding.targetProperty,
|
|
85
|
+
source: field.binding.source,
|
|
86
|
+
when: field.binding.when,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
irVersion: UI_SCENE_IR_VERSION,
|
|
92
|
+
id: artifact.id,
|
|
93
|
+
sourceHash: artifact.sourceHash,
|
|
94
|
+
rootNodeId: artifact.rootNodeId,
|
|
95
|
+
nodes,
|
|
96
|
+
bindings,
|
|
97
|
+
actions,
|
|
98
|
+
tokenUses,
|
|
99
|
+
i18nUses,
|
|
100
|
+
sourceMap,
|
|
101
|
+
targetProfiles: artifact.targetProfiles,
|
|
102
|
+
portability: { level: 'portable' },
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export function createGraphqlBijouBlockDebugSummary(artifact, options = {}) {
|
|
106
|
+
const scene = lowerBijouBlockToUiScene(artifact);
|
|
107
|
+
const body = {
|
|
108
|
+
summaryVersion: GRAPHQL_BIJOU_BLOCK_DEBUG_SUMMARY_VERSION,
|
|
109
|
+
artifactVersion: artifact.artifactVersion,
|
|
110
|
+
artifactId: artifact.id,
|
|
111
|
+
artifactHash: hashUiSceneValue(artifact),
|
|
112
|
+
sceneHash: hashUiSceneValue(scene),
|
|
113
|
+
rootNodeId: artifact.rootNodeId,
|
|
114
|
+
groups: debugGroupFacts(artifact),
|
|
115
|
+
fields: artifact.fields.map(debugFieldFact),
|
|
116
|
+
sourceMap: scene.sourceMap,
|
|
117
|
+
i18nKeys: sortedUniqueStrings(scene.i18nUses.map((use) => use.key)),
|
|
118
|
+
tokenRefs: sortedUniqueStrings(scene.tokenUses.map((use) => use.token)),
|
|
119
|
+
actionIds: sortedUniqueStrings(scene.actions.map((action) => action.id)),
|
|
120
|
+
bindingIds: sortedUniqueStrings(scene.bindings.map((binding) => binding.id)),
|
|
121
|
+
lowerModes: DEBUG_LOWER_MODES.map((mode) => {
|
|
122
|
+
const proof = lowerUiSceneToTerminalProof(scene, {
|
|
123
|
+
...options,
|
|
124
|
+
lowerMode: mode,
|
|
125
|
+
});
|
|
126
|
+
return {
|
|
127
|
+
mode,
|
|
128
|
+
surfaceHash: proof.lowering.surfaceHash,
|
|
129
|
+
rows: surfaceRows(proof.lowering.surface),
|
|
130
|
+
};
|
|
131
|
+
}),
|
|
132
|
+
};
|
|
133
|
+
return {
|
|
134
|
+
...body,
|
|
135
|
+
summaryHash: hashUiSceneValue({ ...body, summaryHash: undefined }),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function parseConstrainedGraphqlBijouBlock(source) {
|
|
139
|
+
const typeDirectiveTexts = [];
|
|
140
|
+
const fields = [];
|
|
141
|
+
let typeName;
|
|
142
|
+
let insideType = false;
|
|
143
|
+
let currentField;
|
|
144
|
+
for (const rawLine of source.replace(/\r\n?/g, '\n').split('\n')) {
|
|
145
|
+
const trimmed = stripGraphqlLineComment(rawLine).trim();
|
|
146
|
+
if (trimmed.length === 0) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (typeName == null) {
|
|
150
|
+
const match = TYPE_PATTERN.exec(trimmed);
|
|
151
|
+
if (match == null) {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
typeName = match[1];
|
|
155
|
+
const rest = match[2] ?? '';
|
|
156
|
+
typeDirectiveTexts.push(rest);
|
|
157
|
+
insideType = rest.includes('{');
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (!insideType) {
|
|
161
|
+
typeDirectiveTexts.push(trimmed);
|
|
162
|
+
insideType = trimmed.includes('{');
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
if (trimmed.startsWith('}')) {
|
|
166
|
+
if (currentField != null) {
|
|
167
|
+
fields.push(fieldFromDraft(currentField));
|
|
168
|
+
currentField = undefined;
|
|
169
|
+
}
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
const fieldMatch = FIELD_PATTERN.exec(trimmed);
|
|
173
|
+
if (fieldMatch != null) {
|
|
174
|
+
if (currentField != null) {
|
|
175
|
+
fields.push(fieldFromDraft(currentField));
|
|
176
|
+
}
|
|
177
|
+
currentField = {
|
|
178
|
+
fieldName: fieldMatch[1],
|
|
179
|
+
graphqlType: fieldMatch[2],
|
|
180
|
+
directiveTexts: [fieldMatch[3] ?? ''],
|
|
181
|
+
};
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (trimmed.startsWith('@') && currentField != null) {
|
|
185
|
+
currentField.directiveTexts.push(trimmed);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (typeName == null) {
|
|
189
|
+
throw new Error('GraphQL Bijou block source must include a type definition.');
|
|
190
|
+
}
|
|
191
|
+
if (currentField != null) {
|
|
192
|
+
fields.push(fieldFromDraft(currentField));
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
typeName,
|
|
196
|
+
typeDirectives: parseDirectives(typeDirectiveTexts.join('\n')),
|
|
197
|
+
fields,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function fieldFromDraft(draft) {
|
|
201
|
+
return {
|
|
202
|
+
fieldName: draft.fieldName,
|
|
203
|
+
graphqlType: draft.graphqlType,
|
|
204
|
+
directives: parseDirectives(draft.directiveTexts.join('\n')),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function parseDirectives(source) {
|
|
208
|
+
const directives = [];
|
|
209
|
+
for (const match of source.matchAll(DIRECTIVE_PATTERN)) {
|
|
210
|
+
directives.push({
|
|
211
|
+
name: match[1],
|
|
212
|
+
args: parseDirectiveArgs(match[2] ?? ''),
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
return directives;
|
|
216
|
+
}
|
|
217
|
+
function parseDirectiveArgs(source) {
|
|
218
|
+
const args = {};
|
|
219
|
+
for (const match of source.matchAll(ARG_PATTERN)) {
|
|
220
|
+
const key = match[1];
|
|
221
|
+
const rawValue = match[2];
|
|
222
|
+
args[key] = rawValue.startsWith('"') ? parseQuotedArg(rawValue) : Number(rawValue);
|
|
223
|
+
}
|
|
224
|
+
return args;
|
|
225
|
+
}
|
|
226
|
+
function parseQuotedArg(rawValue) {
|
|
227
|
+
try {
|
|
228
|
+
return JSON.parse(rawValue);
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
throw new Error(`Invalid GraphQL Bijou block string argument: ${rawValue}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function bijouBlockFieldFor(field, typeName, sourceName) {
|
|
235
|
+
const textDirective = requireDirective(field, 'bijouText');
|
|
236
|
+
const i18nDirective = requireDirective(field, 'bijouI18n');
|
|
237
|
+
const tokenDirective = directiveByName(field.directives, 'bijouToken');
|
|
238
|
+
const actionDirective = directiveByName(field.directives, 'bijouAction');
|
|
239
|
+
const bindingDirective = directiveByName(field.directives, 'bijouBind');
|
|
240
|
+
const nodeId = requiredStringArg(textDirective, 'id', `@bijouText on ${field.fieldName} must include id:.`);
|
|
241
|
+
return {
|
|
242
|
+
fieldName: field.fieldName,
|
|
243
|
+
nodeId,
|
|
244
|
+
groupId: optionalStringArg(textDirective, 'group'),
|
|
245
|
+
graphqlType: field.graphqlType,
|
|
246
|
+
source: `${sourceName}#type.${typeName}.field.${field.fieldName}`,
|
|
247
|
+
layout: layoutFor(textDirective),
|
|
248
|
+
text: {
|
|
249
|
+
kind: 'i18n',
|
|
250
|
+
key: requiredStringArg(i18nDirective, 'key', `@bijouI18n on ${field.fieldName} must include key:.`),
|
|
251
|
+
fallback: requiredStringArg(i18nDirective, 'fallback', `@bijouI18n on ${field.fieldName} must include fallback:.`),
|
|
252
|
+
},
|
|
253
|
+
style: tokenDirective == null ? undefined : styleFor(tokenDirective),
|
|
254
|
+
action: actionDirective == null ? undefined : actionFor(actionDirective),
|
|
255
|
+
binding: bindingDirective == null ? undefined : bindingFor(bindingDirective),
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function groupsFor(directives, typeName, sourceName) {
|
|
259
|
+
return directivesByName(directives, 'bijouGroup').map((directive) => {
|
|
260
|
+
const id = requiredStringArg(directive, 'id', '@bijouGroup must include id:.');
|
|
261
|
+
const label = optionalStringArg(directive, 'label');
|
|
262
|
+
const group = {
|
|
263
|
+
id,
|
|
264
|
+
source: `${sourceName}#type.${typeName}.group.${id}`,
|
|
265
|
+
layout: layoutFor(directive),
|
|
266
|
+
};
|
|
267
|
+
if (label != null) {
|
|
268
|
+
group.label = label;
|
|
269
|
+
}
|
|
270
|
+
return group;
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
function rootChildNodeIds(groups, fields) {
|
|
274
|
+
if (groups.length === 0) {
|
|
275
|
+
return fields.map((field) => field.nodeId);
|
|
276
|
+
}
|
|
277
|
+
return [
|
|
278
|
+
...groups.map((group) => group.id),
|
|
279
|
+
...fields.flatMap((field) => field.groupId == null ? [field.nodeId] : []),
|
|
280
|
+
];
|
|
281
|
+
}
|
|
282
|
+
function nodeForGroup(artifact, group) {
|
|
283
|
+
const node = {
|
|
284
|
+
id: group.id,
|
|
285
|
+
kind: 'group',
|
|
286
|
+
component: artifact.component,
|
|
287
|
+
parentId: artifact.rootNodeId,
|
|
288
|
+
children: artifact.fields
|
|
289
|
+
.filter((field) => field.groupId === group.id)
|
|
290
|
+
.map((field) => field.nodeId),
|
|
291
|
+
layout: group.layout,
|
|
292
|
+
metadata: metadataForGroup(group),
|
|
293
|
+
};
|
|
294
|
+
return node;
|
|
295
|
+
}
|
|
296
|
+
function metadataForGroup(group) {
|
|
297
|
+
const metadata = {
|
|
298
|
+
graphqlGroup: group.id,
|
|
299
|
+
};
|
|
300
|
+
if (group.label != null) {
|
|
301
|
+
metadata['label'] = group.label;
|
|
302
|
+
}
|
|
303
|
+
return metadata;
|
|
304
|
+
}
|
|
305
|
+
function nodeForField(artifact, field) {
|
|
306
|
+
const node = {
|
|
307
|
+
id: field.nodeId,
|
|
308
|
+
kind: 'text',
|
|
309
|
+
component: artifact.component,
|
|
310
|
+
parentId: field.groupId ?? artifact.rootNodeId,
|
|
311
|
+
layout: field.layout,
|
|
312
|
+
text: field.text,
|
|
313
|
+
style: field.style,
|
|
314
|
+
actions: field.action == null ? undefined : [field.action.id],
|
|
315
|
+
metadata: {
|
|
316
|
+
graphqlField: field.fieldName,
|
|
317
|
+
graphqlType: field.graphqlType,
|
|
318
|
+
},
|
|
319
|
+
};
|
|
320
|
+
return node;
|
|
321
|
+
}
|
|
322
|
+
function targetProfilesFor(directives) {
|
|
323
|
+
const targetDirective = requireDirective({ fieldName: 'type', directives }, 'bijouTarget', 'GraphQL Bijou block source must include @bijouTarget(kind:, cols:, rows:).');
|
|
324
|
+
const kind = requiredStringArg(targetDirective, 'kind', '@bijouTarget must include kind:.');
|
|
325
|
+
if (kind !== 'bijou-terminal') {
|
|
326
|
+
throw new Error(`Unsupported GraphQL Bijou block target kind: ${kind}`);
|
|
327
|
+
}
|
|
328
|
+
return [
|
|
329
|
+
{
|
|
330
|
+
kind,
|
|
331
|
+
cols: requiredPositiveIntegerArg(targetDirective, 'cols', '@bijouTarget bijou-terminal must include positive cols:.'),
|
|
332
|
+
rows: requiredPositiveIntegerArg(targetDirective, 'rows', '@bijouTarget bijou-terminal must include positive rows:.'),
|
|
333
|
+
},
|
|
334
|
+
];
|
|
335
|
+
}
|
|
336
|
+
function layoutFor(directive) {
|
|
337
|
+
const layout = {};
|
|
338
|
+
copyOptionalIntegerArg(directive, layout, 'x');
|
|
339
|
+
copyOptionalIntegerArg(directive, layout, 'y');
|
|
340
|
+
copyOptionalIntegerArg(directive, layout, 'width');
|
|
341
|
+
copyOptionalIntegerArg(directive, layout, 'height');
|
|
342
|
+
return layout;
|
|
343
|
+
}
|
|
344
|
+
function styleFor(directive) {
|
|
345
|
+
const style = {};
|
|
346
|
+
const fg = optionalStringArg(directive, 'fg');
|
|
347
|
+
const bg = optionalStringArg(directive, 'bg');
|
|
348
|
+
const border = optionalStringArg(directive, 'border');
|
|
349
|
+
if (fg != null) {
|
|
350
|
+
style.fg = { token: fg };
|
|
351
|
+
}
|
|
352
|
+
if (bg != null) {
|
|
353
|
+
style.bg = { token: bg };
|
|
354
|
+
}
|
|
355
|
+
if (border != null) {
|
|
356
|
+
style.border = { token: border };
|
|
357
|
+
}
|
|
358
|
+
return style;
|
|
359
|
+
}
|
|
360
|
+
function actionFor(directive) {
|
|
361
|
+
const id = requiredStringArg(directive, 'id', '@bijouAction must include id:.');
|
|
362
|
+
const command = requiredStringArg(directive, 'command', '@bijouAction must include command:.');
|
|
363
|
+
const key = optionalStringArg(directive, 'key');
|
|
364
|
+
return {
|
|
365
|
+
id,
|
|
366
|
+
command,
|
|
367
|
+
keybindings: key == null ? [] : [key],
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
function bindingFor(directive) {
|
|
371
|
+
const kind = requiredStringArg(directive, 'kind', '@bijouBind must include kind:.');
|
|
372
|
+
if (kind !== 'state' && kind !== 'query' && kind !== 'computed') {
|
|
373
|
+
throw new Error(`Unsupported @bijouBind kind: ${kind}`);
|
|
374
|
+
}
|
|
375
|
+
return {
|
|
376
|
+
id: requiredStringArg(directive, 'id', '@bijouBind must include id:.'),
|
|
377
|
+
targetProperty: optionalStringArg(directive, 'targetProperty') ?? 'text',
|
|
378
|
+
source: {
|
|
379
|
+
kind,
|
|
380
|
+
path: requiredStringArg(directive, 'path', '@bijouBind must include path:.'),
|
|
381
|
+
},
|
|
382
|
+
when: optionalStringArg(directive, 'when'),
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
function requireDirective(owner, name, message) {
|
|
386
|
+
const directive = directiveByName(owner.directives, name);
|
|
387
|
+
if (directive == null) {
|
|
388
|
+
throw new Error(message ?? `GraphQL Bijou block field ${owner.fieldName} must include @${name}(...).`);
|
|
389
|
+
}
|
|
390
|
+
return directive;
|
|
391
|
+
}
|
|
392
|
+
function directiveByName(directives, name) {
|
|
393
|
+
const matches = directives.filter((directive) => directive.name === name);
|
|
394
|
+
if (matches.length > 1) {
|
|
395
|
+
throw new Error(`GraphQL Bijou block source has duplicate @${name} directives.`);
|
|
396
|
+
}
|
|
397
|
+
return matches[0];
|
|
398
|
+
}
|
|
399
|
+
function directivesByName(directives, name) {
|
|
400
|
+
return directives.filter((directive) => directive.name === name);
|
|
401
|
+
}
|
|
402
|
+
function requiredStringArg(directive, name, message) {
|
|
403
|
+
const value = optionalStringArg(directive, name);
|
|
404
|
+
if (value == null) {
|
|
405
|
+
throw new Error(message);
|
|
406
|
+
}
|
|
407
|
+
return value;
|
|
408
|
+
}
|
|
409
|
+
function optionalStringArg(directive, name) {
|
|
410
|
+
const value = directive.args[name];
|
|
411
|
+
return typeof value === 'string' ? value : undefined;
|
|
412
|
+
}
|
|
413
|
+
function requiredPositiveIntegerArg(directive, name, message) {
|
|
414
|
+
const value = optionalIntegerArg(directive, name);
|
|
415
|
+
if (value == null || value <= 0) {
|
|
416
|
+
throw new Error(message);
|
|
417
|
+
}
|
|
418
|
+
return value;
|
|
419
|
+
}
|
|
420
|
+
function optionalIntegerArg(directive, name) {
|
|
421
|
+
const value = directive.args[name];
|
|
422
|
+
return typeof value === 'number' && Number.isInteger(value) ? value : undefined;
|
|
423
|
+
}
|
|
424
|
+
function copyOptionalIntegerArg(directive, layout, name) {
|
|
425
|
+
const value = optionalIntegerArg(directive, name);
|
|
426
|
+
if (value != null) {
|
|
427
|
+
layout[name] = value;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
function appendTokenUses(tokenUses, field) {
|
|
431
|
+
if (field.style?.fg?.token != null) {
|
|
432
|
+
tokenUses.push({ nodeId: field.nodeId, slot: 'fg', token: field.style.fg.token });
|
|
433
|
+
}
|
|
434
|
+
if (field.style?.bg?.token != null) {
|
|
435
|
+
tokenUses.push({ nodeId: field.nodeId, slot: 'bg', token: field.style.bg.token });
|
|
436
|
+
}
|
|
437
|
+
if (field.style?.border?.token != null) {
|
|
438
|
+
tokenUses.push({ nodeId: field.nodeId, slot: 'border', token: field.style.border.token });
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
function appendI18nUse(i18nUses, id, text, kind = 'node') {
|
|
442
|
+
if (text.kind !== 'i18n') {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
i18nUses.push(kind === 'node'
|
|
446
|
+
? { nodeId: id, key: text.key }
|
|
447
|
+
: { actionId: id, key: text.key });
|
|
448
|
+
}
|
|
449
|
+
function assertUniqueBlockIdentities(groups, fields, rootNodeId) {
|
|
450
|
+
assertUniqueValues(fields.map((field) => field.fieldName), 'field name');
|
|
451
|
+
assertUniqueValues(groups.map((group) => group.id), 'group id');
|
|
452
|
+
assertUniqueValues([rootNodeId, ...groups.map((group) => group.id), ...fields.map((field) => field.nodeId)], 'node id');
|
|
453
|
+
const groupIds = new Set(groups.map((group) => group.id));
|
|
454
|
+
for (const field of fields) {
|
|
455
|
+
if (field.groupId != null && !groupIds.has(field.groupId)) {
|
|
456
|
+
throw new Error(`GraphQL Bijou block field ${field.fieldName} references missing group: ${field.groupId}`);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
assertUniqueValues(fields.flatMap((field) => field.action == null ? [] : [field.action.id]), 'action id');
|
|
460
|
+
assertUniqueValues(fields.flatMap((field) => field.binding == null ? [] : [field.binding.id]), 'binding id');
|
|
461
|
+
}
|
|
462
|
+
function debugGroupFacts(artifact) {
|
|
463
|
+
const groups = artifact.groups ?? [];
|
|
464
|
+
return groups.map((group) => {
|
|
465
|
+
const fact = {
|
|
466
|
+
id: group.id,
|
|
467
|
+
source: group.source,
|
|
468
|
+
childNodeIds: artifact.fields
|
|
469
|
+
.filter((field) => field.groupId === group.id)
|
|
470
|
+
.map((field) => field.nodeId),
|
|
471
|
+
};
|
|
472
|
+
if (group.label != null) {
|
|
473
|
+
fact.label = group.label;
|
|
474
|
+
}
|
|
475
|
+
return fact;
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
function debugFieldFact(field) {
|
|
479
|
+
const fact = {
|
|
480
|
+
fieldName: field.fieldName,
|
|
481
|
+
nodeId: field.nodeId,
|
|
482
|
+
source: field.source,
|
|
483
|
+
tokenRefs: styleTokenRefs(field.style),
|
|
484
|
+
};
|
|
485
|
+
if (field.groupId != null) {
|
|
486
|
+
fact.groupId = field.groupId;
|
|
487
|
+
}
|
|
488
|
+
if (field.text.kind === 'i18n') {
|
|
489
|
+
fact.i18nKey = field.text.key;
|
|
490
|
+
}
|
|
491
|
+
if (field.action != null) {
|
|
492
|
+
fact.actionId = field.action.id;
|
|
493
|
+
}
|
|
494
|
+
if (field.binding != null) {
|
|
495
|
+
fact.bindingId = field.binding.id;
|
|
496
|
+
}
|
|
497
|
+
return fact;
|
|
498
|
+
}
|
|
499
|
+
function styleTokenRefs(style) {
|
|
500
|
+
return sortedUniqueStrings([
|
|
501
|
+
style?.fg?.token,
|
|
502
|
+
style?.bg?.token,
|
|
503
|
+
style?.border?.token,
|
|
504
|
+
].filter((token) => token != null));
|
|
505
|
+
}
|
|
506
|
+
function surfaceRows(surface) {
|
|
507
|
+
const rows = [];
|
|
508
|
+
for (let y = 0; y < surface.height; y++) {
|
|
509
|
+
let row = '';
|
|
510
|
+
for (let x = 0; x < surface.width; x++) {
|
|
511
|
+
const cell = surface.get(x, y);
|
|
512
|
+
row += cell.empty ? ' ' : cell.char;
|
|
513
|
+
}
|
|
514
|
+
rows.push(row.trimEnd());
|
|
515
|
+
}
|
|
516
|
+
return rows;
|
|
517
|
+
}
|
|
518
|
+
function sortedUniqueStrings(values) {
|
|
519
|
+
return [...new Set(values)].sort(compareCodeUnits);
|
|
520
|
+
}
|
|
521
|
+
function compareCodeUnits(a, b) {
|
|
522
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
523
|
+
}
|
|
524
|
+
function assertUniqueValues(values, label) {
|
|
525
|
+
const seen = new Set();
|
|
526
|
+
for (const value of values) {
|
|
527
|
+
if (seen.has(value)) {
|
|
528
|
+
throw new Error(`Duplicate GraphQL Bijou block ${label}: ${value}`);
|
|
529
|
+
}
|
|
530
|
+
seen.add(value);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
function normalizeSourceName(sourceName) {
|
|
534
|
+
const trimmed = sourceName.trim();
|
|
535
|
+
if (trimmed.length === 0) {
|
|
536
|
+
throw new Error('GraphQL Bijou block sourceName cannot be empty.');
|
|
537
|
+
}
|
|
538
|
+
if (trimmed.startsWith('/')
|
|
539
|
+
|| trimmed.startsWith('\\\\')
|
|
540
|
+
|| trimmed.startsWith('//')
|
|
541
|
+
|| /^[A-Za-z]:[\\/]/.test(trimmed)
|
|
542
|
+
|| trimmed.includes('\0')) {
|
|
543
|
+
throw new Error('GraphQL Bijou block sourceName must be a relative or logical name.');
|
|
544
|
+
}
|
|
545
|
+
return trimmed;
|
|
546
|
+
}
|
|
547
|
+
function stripGraphqlLineComment(line) {
|
|
548
|
+
let quoted = false;
|
|
549
|
+
let escaped = false;
|
|
550
|
+
for (let index = 0; index < line.length; index++) {
|
|
551
|
+
const char = line[index];
|
|
552
|
+
if (escaped) {
|
|
553
|
+
escaped = false;
|
|
554
|
+
continue;
|
|
555
|
+
}
|
|
556
|
+
if (char === '\\') {
|
|
557
|
+
escaped = true;
|
|
558
|
+
continue;
|
|
559
|
+
}
|
|
560
|
+
if (char === '"') {
|
|
561
|
+
quoted = !quoted;
|
|
562
|
+
continue;
|
|
563
|
+
}
|
|
564
|
+
if (!quoted && char === '#') {
|
|
565
|
+
return line.slice(0, index);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
return line;
|
|
569
|
+
}
|
|
570
|
+
//# sourceMappingURL=graphql-bijou-block.js.map
|