@fluffjs/fluff 0.4.0 → 0.4.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluffjs/fluff",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "module": "./index.js",
@@ -51,6 +51,7 @@ export type CompactBinding = [
51
51
  p?: [number, number[]][];
52
52
  }?
53
53
  ];
54
+ export type CompactMarkerConfig = [0, ([number | null, CompactDep[] | null] | [])[]] | [1, number, number, boolean, CompactDep[] | null, number | null] | [2, number, CompactDep[] | null, [number, number[]][] | null] | [3, number, CompactDep[] | null, [boolean, boolean, number | null][]] | [4];
54
55
  export declare abstract class FluffBase extends HTMLElement {
55
56
  static __e: ExpressionFn[];
56
57
  static __h: HandlerFn[];
@@ -59,7 +60,9 @@ export declare abstract class FluffBase extends HTMLElement {
59
60
  private static __expressionsReady;
60
61
  private static readonly __pendingInitCallbacks;
61
62
  static __setExpressionTable(expressions: ExpressionFn[], handlers: HandlerFn[], strings?: string[]): void;
62
- private static __decodeDep;
63
+ static __decodeDep(dep: number | number[]): string | string[];
64
+ static __decodeDeps(deps: (number | number[])[] | null): (string | string[])[] | undefined;
65
+ static __decodeMarkerConfig(compact: CompactMarkerConfig): unknown;
63
66
  private static __decodeBinding;
64
67
  static __areExpressionsReady(): boolean;
65
68
  static __addPendingInit(callback: () => void): void;
@@ -1,6 +1,23 @@
1
1
  import { Property } from '../utils/Property.js';
2
2
  import { Publisher } from '../utils/Publisher.js';
3
3
  const BINDING_TYPES = ['property', 'event', 'two-way', 'class', 'style', 'ref'];
4
+ /**
5
+ * Compact Marker Config Format (Decoder)
6
+ *
7
+ * Marker configs use the same string table as bindings. Type is numeric:
8
+ * 0=if, 1=for, 2=text, 3=switch, 4=break
9
+ *
10
+ * Format varies by type:
11
+ * - if: [0, branches[]] where branch = [exprId?, deps?]
12
+ * - for: [1, iteratorIdx, iterableExprId, hasEmpty, deps?, trackByIdx?]
13
+ * - text: [2, exprId, deps?, pipes?]
14
+ * - switch: [3, expressionExprId, deps?, cases[]]
15
+ * - break: [4]
16
+ *
17
+ * deps are interned as CompactDep[] (same as bindings)
18
+ * pipes are [pipeNameIdx, argExprIds[]][]
19
+ */
20
+ const MARKER_TYPES = ['if', 'for', 'text', 'switch', 'break'];
4
21
  export class FluffBase extends HTMLElement {
5
22
  static __e = [];
6
23
  static __h = [];
@@ -26,6 +43,80 @@ export class FluffBase extends HTMLElement {
26
43
  }
27
44
  return FluffBase.__s[dep];
28
45
  }
46
+ static __decodeDeps(deps) {
47
+ if (!deps)
48
+ return undefined;
49
+ return deps.map(d => FluffBase.__decodeDep(d));
50
+ }
51
+ static __decodeMarkerConfig(compact) {
52
+ const [typeNum] = compact;
53
+ const type = MARKER_TYPES[typeNum];
54
+ switch (typeNum) {
55
+ case 0: // if
56
+ {
57
+ const [, rawBranches] = compact;
58
+ const branches = rawBranches.map(b => {
59
+ if (b.length === 0)
60
+ return {};
61
+ const [branchExprId, branchDeps] = b;
62
+ const result = {};
63
+ if (branchExprId !== null)
64
+ result.exprId = branchExprId;
65
+ if (branchDeps)
66
+ result.deps = FluffBase.__decodeDeps(branchDeps);
67
+ return result;
68
+ });
69
+ return { type, branches };
70
+ }
71
+ case 1: // for
72
+ {
73
+ const [, iteratorIdx, iterableExprId, hasEmpty, deps, trackByIdx] = compact;
74
+ const result = {
75
+ type,
76
+ iterator: FluffBase.__s[iteratorIdx],
77
+ iterableExprId,
78
+ hasEmpty
79
+ };
80
+ if (deps)
81
+ result.deps = FluffBase.__decodeDeps(deps);
82
+ if (trackByIdx !== null)
83
+ result.trackBy = FluffBase.__s[trackByIdx];
84
+ return result;
85
+ }
86
+ case 2: // text
87
+ {
88
+ const [, exprId, deps, pipes] = compact;
89
+ const result = { type, exprId };
90
+ if (deps)
91
+ result.deps = FluffBase.__decodeDeps(deps);
92
+ if (pipes) {
93
+ result.pipes = pipes.map(([nameIdx, argExprIds]) => ({
94
+ name: FluffBase.__s[nameIdx],
95
+ argExprIds
96
+ }));
97
+ }
98
+ return result;
99
+ }
100
+ case 3: // switch
101
+ {
102
+ const [, expressionExprId, deps, cases] = compact;
103
+ const result = { type, expressionExprId };
104
+ if (deps)
105
+ result.deps = FluffBase.__decodeDeps(deps);
106
+ result.cases = cases.map(([isDefault, fallthrough, valueExprId]) => {
107
+ const c = { isDefault, fallthrough };
108
+ if (valueExprId !== null)
109
+ c.valueExprId = valueExprId;
110
+ return c;
111
+ });
112
+ return result;
113
+ }
114
+ case 4: // break
115
+ return { type };
116
+ default:
117
+ return { type: 'unknown' };
118
+ }
119
+ }
29
120
  static __decodeBinding(compact) {
30
121
  const [nameIdx, bType, deps, id, extras] = compact;
31
122
  const n = FluffBase.__s[nameIdx];
@@ -6,6 +6,9 @@ export declare class MarkerManager {
6
6
  private readonly host;
7
7
  private readonly shadowRoot;
8
8
  constructor(host: HTMLElement, shadowRoot: ShadowRoot);
9
+ private decodeConfig;
10
+ private isMarkerConfig;
11
+ private isCompactMarkerConfig;
9
12
  initializeFromConfig(entries: MarkerConfigEntries): void;
10
13
  ensureController(id: number, type: string, startMarker: Comment, endMarker: Comment | null): MarkerController | undefined;
11
14
  getController(id: number, startMarker: Comment): MarkerController | undefined;
@@ -1,4 +1,5 @@
1
1
  import { BreakController } from './BreakController.js';
2
+ import { FluffBase } from './FluffBase.js';
2
3
  import { ForController } from './ForController.js';
3
4
  import { IfController } from './IfController.js';
4
5
  import { MarkerConfigGuards } from './MarkerConfigGuards.js';
@@ -13,12 +14,45 @@ export class MarkerManager {
13
14
  this.host = host;
14
15
  this.shadowRoot = shadowRoot;
15
16
  }
17
+ decodeConfig(config) {
18
+ if (this.isCompactMarkerConfig(config)) {
19
+ const decoded = FluffBase.__decodeMarkerConfig(config);
20
+ if (this.isMarkerConfig(decoded)) {
21
+ return decoded;
22
+ }
23
+ throw new Error('Decoded marker config is invalid');
24
+ }
25
+ if (!Array.isArray(config)) {
26
+ return config;
27
+ }
28
+ throw new Error('Invalid marker config format');
29
+ }
30
+ isMarkerConfig(value) {
31
+ if (typeof value !== 'object' || value === null)
32
+ return false;
33
+ if (!('type' in value))
34
+ return false;
35
+ const typeVal = value.type;
36
+ return typeof typeVal === 'string' && ['if', 'for', 'text', 'switch', 'break'].includes(typeVal);
37
+ }
38
+ isCompactMarkerConfig(config) {
39
+ if (!Array.isArray(config))
40
+ return false;
41
+ if (config.length === 0)
42
+ return false;
43
+ const firstElement = config[0];
44
+ return typeof firstElement === 'number' && firstElement >= 0 && firstElement <= 4;
45
+ }
16
46
  initializeFromConfig(entries) {
17
47
  this.configs.clear();
18
- for (const [id, config] of entries) {
48
+ for (const [id, rawConfig] of entries) {
49
+ const config = this.decodeConfig(rawConfig);
19
50
  this.configs.set(id, config);
20
51
  }
21
- for (const [id, config] of entries) {
52
+ for (const [id] of entries) {
53
+ const config = this.configs.get(id);
54
+ if (!config)
55
+ continue;
22
56
  const { startMarker, endMarker } = this.findMarkers(id, config.type);
23
57
  if (!startMarker) {
24
58
  continue;
@@ -1,5 +1,6 @@
1
1
  import type { MarkerConfig } from '../interfaces/MarkerConfig.js';
2
- export type MarkerConfigEntries = [number, MarkerConfig][];
2
+ import type { CompactMarkerConfig } from './FluffBase.js';
3
+ export type MarkerConfigEntries = [number, MarkerConfig | CompactMarkerConfig][];
3
4
  export interface MarkerManagerInterface {
4
5
  initializeFromConfig: (entries: MarkerConfigEntries) => void;
5
6
  cleanup: () => void;