@jarenjs/studio 0.34.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 +72 -0
- package/dist/types/assemble.d.ts +67 -0
- package/dist/types/component/editor.d.ts +68 -0
- package/dist/types/component/host.d.ts +45 -0
- package/dist/types/component/index.d.ts +262 -0
- package/dist/types/component/view.d.ts +232 -0
- package/dist/types/component/viewmodel.d.ts +22 -0
- package/dist/types/errors.d.ts +31 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/project.d.ts +31 -0
- package/dist/types/validate.d.ts +48 -0
- package/docs/PROJECT-FORMAT.md +112 -0
- package/package.json +69 -0
- package/schemas/jaren-project.draft-07.schema.json +41 -0
- package/schemas/jaren-project.schema.json +47 -0
- package/src/assemble.js +127 -0
- package/src/component/editor.js +59 -0
- package/src/component/host.js +53 -0
- package/src/component/index.js +47 -0
- package/src/component/view.js +198 -0
- package/src/component/viewmodel.js +150 -0
- package/src/errors.js +33 -0
- package/src/index.js +20 -0
- package/src/project.js +80 -0
- package/src/validate.js +191 -0
- package/styles/studio.css +227 -0
package/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# @jarenjs/studio
|
|
2
|
+
|
|
3
|
+
**The jaren project IDE — a jaren application as a multi-file project.**
|
|
4
|
+
|
|
5
|
+
CodePen's model, for JSON-all-the-way-down: an application is a small tree
|
|
6
|
+
of typed files (a view, the actions, the state, a schema, a data model,
|
|
7
|
+
queries, a flow), each edited on its own, each validated against its own
|
|
8
|
+
grammar, assembled into runnable artifacts, and — where the driver allows
|
|
9
|
+
— run live. The same document the human edits is the document an AI
|
|
10
|
+
authors; the studio is a controlled component whose value is that project.
|
|
11
|
+
|
|
12
|
+
This package ships in two layers, the suite's convention:
|
|
13
|
+
|
|
14
|
+
- **the engine** (`@jarenjs/studio`) — headless: parse a `jaren-project`
|
|
15
|
+
document, validate each file against its kind, assemble the runnable
|
|
16
|
+
artifacts, and classify a change as structural vs. state-only. Knows the
|
|
17
|
+
grammars, nothing of the DOM.
|
|
18
|
+
- **the component** (`@jarenjs/studio/component`) — the IDE itself, a
|
|
19
|
+
`createStudioComponent()` factory (like `@jarenjs/calc`): the shell is a
|
|
20
|
+
**JSLT view** (file rail with add/delete, an editable file name, a
|
|
21
|
+
template gallery, editor, docked coded-error strip, run stage, layout
|
|
22
|
+
switcher) over a pure `projectViewModel`, plus the two hard-problem
|
|
23
|
+
policies (`hostPolicy` reboot-vs-hot-update, `reconcileBuffer`). The
|
|
24
|
+
chrome and its derivation render headlessly and are tested as such; the
|
|
25
|
+
host registers the DOM-touching islands — the live nested-app stage
|
|
26
|
+
(hot-update via `app.setState`) and the drag splitter — which are
|
|
27
|
+
browser-verified. Mounted live at the website's `#/project`, where `app`
|
|
28
|
+
files boot, `jslt`/`query` files run against a data file, and files are
|
|
29
|
+
added, renamed, deleted and opened from templates.
|
|
30
|
+
|
|
31
|
+
## The project document
|
|
32
|
+
|
|
33
|
+
A thin envelope over typed files — the full contract is
|
|
34
|
+
[PROJECT-FORMAT.md](docs/PROJECT-FORMAT.md).
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
import { parseProject, validateFile, assembleArtifacts, classifyChange, describe }
|
|
38
|
+
from '@jarenjs/studio';
|
|
39
|
+
|
|
40
|
+
const project = parseProject({
|
|
41
|
+
project: '0.1',
|
|
42
|
+
files: [
|
|
43
|
+
{ name: 'app.json', kind: 'app', text: '{ "view": [ … ], "state": { … } }' },
|
|
44
|
+
{ name: 'npv.query', kind: 'query', text: '{ "$npv": ["$.rate", "$.cf[*]"] }' },
|
|
45
|
+
{ name: 'seed.data', kind: 'data', text: '{ "cf": [-1000, 300, 400] }' },
|
|
46
|
+
],
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe(project); // per-file kind / validity / role — the file rail
|
|
50
|
+
validateFile(project.files[1]); // { valid, kind, total, errors: [{ code, message, docPath }] }
|
|
51
|
+
assembleArtifacts(project); // the runnable set
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Why per-file validation
|
|
55
|
+
|
|
56
|
+
The published `jaren-query` / `jaren-jslt` grammars are *closed*, so a data
|
|
57
|
+
query using a host-registered operator (`$npv`, `$sqrt`) can't be checked
|
|
58
|
+
against them. The studio validates each file on **its own boundary** —
|
|
59
|
+
`jslt`/`query` files are *compiled* with the operator packs mounted, so
|
|
60
|
+
registered operators pass and a real mistake surfaces as its own coded
|
|
61
|
+
error with a JSON Pointer. There is deliberately no single composed
|
|
62
|
+
mega-schema; that is what lets a project mix an app, a store and a data
|
|
63
|
+
query at once. See [PROJECT-FORMAT.md](docs/PROJECT-FORMAT.md).
|
|
64
|
+
|
|
65
|
+
## Install
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
npm install @jarenjs/studio
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Zero third-party runtime dependencies — only other `@jarenjs/*` packages.
|
|
72
|
+
Node ≥ 24, ESM.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Files → runnable artifacts, and the change-classification the IDE
|
|
3
|
+
* needs to decide reboot-vs-hot-update.
|
|
4
|
+
*
|
|
5
|
+
* `assembleArtifacts` composes the project's files into the runnable set.
|
|
6
|
+
* This order ships the WHOLE-DOCUMENT contract: a runnable file (`app`,
|
|
7
|
+
* `fsm`, `dag`, `model`, `jslt`, `query`, `schema`) is its own artifact;
|
|
8
|
+
* `state`/`data` files are inputs, not artifacts. Fragment assembly —
|
|
9
|
+
* composing separate `state` + `view` + `actions` files into ONE
|
|
10
|
+
* `jaren-app` document (the true HTML/CSS/JS split) — is the model's
|
|
11
|
+
* headline enhancement and layers on top without changing this contract.
|
|
12
|
+
*
|
|
13
|
+
* `classifyChange` is the load-bearing UX datum: a `state`-only edit must
|
|
14
|
+
* HOT-DISPATCH into a running app (no reboot, the user keeps scroll and
|
|
15
|
+
* inputs), while a `view`/`actions` change must reboot. It compares a
|
|
16
|
+
* STRUCTURAL key (an app doc minus its `state`) via the suite's own
|
|
17
|
+
* `contentKey`, so the policy in the widget reads clean, tested data.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Compose the project's files into runnable artifacts (whole-document).
|
|
21
|
+
* @param {any} project - a normalized project (from `parseProject`)
|
|
22
|
+
* @returns {{ artifacts: Array<{ name: string, kind: string, role: string,
|
|
23
|
+
* doc: any, sourceFiles: string[] }>, errors: Array<{ file: string, message: string }> }}
|
|
24
|
+
*/
|
|
25
|
+
export declare function assembleArtifacts(project: any): {
|
|
26
|
+
artifacts: Array<{
|
|
27
|
+
name: string;
|
|
28
|
+
kind: string;
|
|
29
|
+
role: string;
|
|
30
|
+
doc: any;
|
|
31
|
+
sourceFiles: string[];
|
|
32
|
+
}>;
|
|
33
|
+
errors: Array<{
|
|
34
|
+
file: string;
|
|
35
|
+
message: string;
|
|
36
|
+
}>;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Classify what changed between two projects, PER artifact — the datum
|
|
40
|
+
* the widget's reboot-vs-hot-update policy consumes. `state-only` means
|
|
41
|
+
* an app's state moved but its structure did not (hot-dispatch it);
|
|
42
|
+
* `structural` means reboot; `none` means nothing changed.
|
|
43
|
+
* @param {any} prevProject
|
|
44
|
+
* @param {any} nextProject
|
|
45
|
+
* @returns {{ overall: 'none' | 'state-only' | 'structural',
|
|
46
|
+
* perArtifact: Record<string, 'none' | 'state-only' | 'structural'> }}
|
|
47
|
+
*/
|
|
48
|
+
export declare function classifyChange(prevProject: any, nextProject: any): {
|
|
49
|
+
overall: 'none' | 'state-only' | 'structural';
|
|
50
|
+
perArtifact: Record<string, 'none' | 'state-only' | 'structural'>;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Per-file metadata for the IDE file rail and the AI `list_files` tool:
|
|
54
|
+
* kind, validity, size, its role, and which runnable artifact it is (a
|
|
55
|
+
* `state`/`data` input is not itself an artifact).
|
|
56
|
+
* @param {any} project - a normalized project
|
|
57
|
+
* @param {{ operators?: { toOptions: () => any } }} [options]
|
|
58
|
+
*/
|
|
59
|
+
export declare function describe(project: any, options?: {
|
|
60
|
+
operators?: {
|
|
61
|
+
toOptions: () => any;
|
|
62
|
+
};
|
|
63
|
+
}): {
|
|
64
|
+
active: any;
|
|
65
|
+
layout: any;
|
|
66
|
+
files: any;
|
|
67
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The editor + rail vnode primitives — the baseline IDE, graduated
|
|
3
|
+
* from the site's studio-kit. Everything is a plain `@jarenjs/view` vnode
|
|
4
|
+
* (a tagged array), so the whole IDE renders through the same JSLT engine
|
|
5
|
+
* the rest of the suite uses; no imperative editor widget, no syntax
|
|
6
|
+
* highlighting (a later concern). The concrete kind→badge map lives here;
|
|
7
|
+
* its colours are in `styles/studio.css`.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* A baseline code editor: a `<textarea>` with the ergonomics that keep it
|
|
11
|
+
* from fighting the shell (no browser resize — the splitter owns width;
|
|
12
|
+
* spell/autocap/autocorrect off so a mobile keyboard does not rewrite
|
|
13
|
+
* JSON keys). Tab-to-indent and the debounce live in the shell's edit
|
|
14
|
+
* loop; the value is bound to the active file.
|
|
15
|
+
*
|
|
16
|
+
* `inputAction` is load-bearing, not a convenience: this is a CONTROLLED
|
|
17
|
+
* textarea, and the renderer reasserts a control's authoritative value
|
|
18
|
+
* after every settled render. If the document only learned about an edit
|
|
19
|
+
* on `change` (blur), any render in between would rewrite the box with
|
|
20
|
+
* the still-stale text — and writing `.value` clears the browser's
|
|
21
|
+
* dirty-value flag, so `change` would then never fire and the typing
|
|
22
|
+
* would vanish. Publishing each keystroke to the typing buffer keeps the
|
|
23
|
+
* authoritative value equal to what the user typed, so the reassert is a
|
|
24
|
+
* no-op and the caret survives.
|
|
25
|
+
* @param {{ value: any, action: string, inputAction?: string, rows?: number,
|
|
26
|
+
* readonly?: boolean }} options
|
|
27
|
+
*/
|
|
28
|
+
export declare function editorTextarea(options: {
|
|
29
|
+
value: any;
|
|
30
|
+
action: string;
|
|
31
|
+
inputAction?: string;
|
|
32
|
+
rows?: number;
|
|
33
|
+
readonly?: boolean;
|
|
34
|
+
}): (string | {
|
|
35
|
+
class: string;
|
|
36
|
+
rows: number;
|
|
37
|
+
spellcheck: string;
|
|
38
|
+
autocapitalize: string;
|
|
39
|
+
autocorrect: string;
|
|
40
|
+
autocomplete: string;
|
|
41
|
+
value: any;
|
|
42
|
+
readonly?: string | undefined;
|
|
43
|
+
on: {
|
|
44
|
+
change: string;
|
|
45
|
+
input?: undefined;
|
|
46
|
+
} | {
|
|
47
|
+
input: string;
|
|
48
|
+
change: string;
|
|
49
|
+
};
|
|
50
|
+
})[];
|
|
51
|
+
/** One line of the docked error strip. */
|
|
52
|
+
export declare function errorLine(content: any): any[];
|
|
53
|
+
/**
|
|
54
|
+
* The five concrete kind badge classes (colours are CONSTANTS in
|
|
55
|
+
* studio.css, not aliased status tokens): view (blue), query (cyan),
|
|
56
|
+
* json (slate), model (green), flow (amber).
|
|
57
|
+
*/
|
|
58
|
+
export declare const KIND_BADGE: Readonly<{
|
|
59
|
+
app: "view";
|
|
60
|
+
jslt: "view";
|
|
61
|
+
query: "query";
|
|
62
|
+
state: "json";
|
|
63
|
+
data: "json";
|
|
64
|
+
schema: "json";
|
|
65
|
+
model: "model";
|
|
66
|
+
fsm: "flow";
|
|
67
|
+
dag: "flow";
|
|
68
|
+
}>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The two hard-problem POLICIES, pure and tested — the DOM
|
|
3
|
+
* mechanics that consume them live in the widget.
|
|
4
|
+
*
|
|
5
|
+
* `hostPolicy` (reboot vs. hot-update): a `state-only` edit hot-dispatches
|
|
6
|
+
* the new state into the RUNNING nested app (the user keeps scroll and
|
|
7
|
+
* inputs, no reboot); a `structural` edit reboots; an unchanged artifact
|
|
8
|
+
* is skipped.
|
|
9
|
+
*
|
|
10
|
+
* `reconcileBuffer` (editor buffer ↔ document): a CLEAN buffer adopts an
|
|
11
|
+
* incoming write (share / undo / an AI edit lands); a DIRTY buffer whose
|
|
12
|
+
* text differs from the incoming write keeps the human's text and records
|
|
13
|
+
* the write as a recoverable draft — never a silent clobber, never a
|
|
14
|
+
* hidden write.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Per-artifact action a stage host should take between two project
|
|
18
|
+
* revisions: `reboot` (destroy + boot), `hot` (dispatch new state into
|
|
19
|
+
* the running app), or `skip` (nothing changed).
|
|
20
|
+
* @param {any} prevProject
|
|
21
|
+
* @param {any} nextProject
|
|
22
|
+
* @returns {Record<string, 'reboot' | 'hot' | 'skip'>}
|
|
23
|
+
*/
|
|
24
|
+
export declare function hostPolicy(prevProject: any, nextProject: any): Record<string, 'reboot' | 'hot' | 'skip'>;
|
|
25
|
+
/**
|
|
26
|
+
* Reconcile the editor's local typing buffer against an incoming
|
|
27
|
+
* committed text (a share/undo restore, or an AI write onto the same
|
|
28
|
+
* file). A clean buffer adopts; a dirty buffer that already matches the
|
|
29
|
+
* incoming text simply clears (the commit landed); a dirty buffer that
|
|
30
|
+
* differs keeps the human's text and surfaces the incoming version as a
|
|
31
|
+
* recoverable `conflict`.
|
|
32
|
+
* @param {{ text: string, dirty: boolean }} buffer
|
|
33
|
+
* @param {string} incoming - the file's committed text
|
|
34
|
+
* @returns {{ text: string, dirty: boolean, conflict: { incoming: string } | null }}
|
|
35
|
+
*/
|
|
36
|
+
export declare function reconcileBuffer(buffer: {
|
|
37
|
+
text: string;
|
|
38
|
+
dirty: boolean;
|
|
39
|
+
}, incoming: string): {
|
|
40
|
+
text: string;
|
|
41
|
+
dirty: boolean;
|
|
42
|
+
conflict: {
|
|
43
|
+
incoming: string;
|
|
44
|
+
} | null;
|
|
45
|
+
};
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The Studio COMPONENT — the IDE. Following the suite's component
|
|
3
|
+
* convention (`createXComponent`), `createStudioComponent(options)` hands
|
|
4
|
+
* the host the pieces it composes into the site's `@jarenjs/app` document:
|
|
5
|
+
* the JSLT view (`rules` + `mode`), the derivation (`viewModel`), the two
|
|
6
|
+
* hard-problem policies (`hostPolicy`, `reconcileBuffer`), and the engine
|
|
7
|
+
* surface. The reducer `project/*` actions, the DOM stage/splitter
|
|
8
|
+
* widgets, and the live site mount are wired at the host; the chrome and
|
|
9
|
+
* its derivation — everything renderable without a DOM — live here and
|
|
10
|
+
* are tested headlessly.
|
|
11
|
+
*/
|
|
12
|
+
import { classifyChange, parseProject } from '../index.js';
|
|
13
|
+
import { projectViewModel } from './viewmodel.js';
|
|
14
|
+
import { projectRules, projectModes, PROJECT_MODE, PROJECT_BASE } from './view.js';
|
|
15
|
+
import { hostPolicy, reconcileBuffer } from './host.js';
|
|
16
|
+
import { editorTextarea, errorLine, KIND_BADGE } from './editor.js';
|
|
17
|
+
/**
|
|
18
|
+
* Build the Studio component.
|
|
19
|
+
* @param {{ operators?: { toOptions: () => any } }} [options] - a host
|
|
20
|
+
* operator registry threaded to every per-file validator/derivation
|
|
21
|
+
*/
|
|
22
|
+
export declare function createStudioComponent(options?: {
|
|
23
|
+
operators?: {
|
|
24
|
+
toOptions: () => any;
|
|
25
|
+
};
|
|
26
|
+
}): {
|
|
27
|
+
mode: string;
|
|
28
|
+
rules: ({
|
|
29
|
+
match: string;
|
|
30
|
+
mode: string;
|
|
31
|
+
body: (string | (string | {
|
|
32
|
+
name: string;
|
|
33
|
+
class: string;
|
|
34
|
+
role: string;
|
|
35
|
+
'aria-orientation': string;
|
|
36
|
+
'aria-label': string;
|
|
37
|
+
'aria-valuemin': string;
|
|
38
|
+
'aria-valuemax': string;
|
|
39
|
+
'aria-valuenow': string;
|
|
40
|
+
tabindex: string;
|
|
41
|
+
props: {
|
|
42
|
+
ratio: string;
|
|
43
|
+
mode: string;
|
|
44
|
+
};
|
|
45
|
+
})[] | (string | any[] | {
|
|
46
|
+
class: string;
|
|
47
|
+
role: string;
|
|
48
|
+
'aria-label': string;
|
|
49
|
+
})[] | (string | {
|
|
50
|
+
$apply: string;
|
|
51
|
+
}[] | (string | (string | {
|
|
52
|
+
value: string;
|
|
53
|
+
})[] | {
|
|
54
|
+
class: string;
|
|
55
|
+
'aria-label': string;
|
|
56
|
+
value: string;
|
|
57
|
+
on: {
|
|
58
|
+
change: string;
|
|
59
|
+
};
|
|
60
|
+
})[] | {
|
|
61
|
+
class: string;
|
|
62
|
+
'aria-label': string;
|
|
63
|
+
})[] | (string | (string | {
|
|
64
|
+
class: string;
|
|
65
|
+
})[] | {
|
|
66
|
+
class: string;
|
|
67
|
+
$if?: undefined;
|
|
68
|
+
} | {
|
|
69
|
+
class?: undefined;
|
|
70
|
+
$if: ((string | (string | {
|
|
71
|
+
name: string;
|
|
72
|
+
props: string;
|
|
73
|
+
})[] | {
|
|
74
|
+
class: string;
|
|
75
|
+
})[] | {
|
|
76
|
+
$if?: undefined;
|
|
77
|
+
$eq: string[];
|
|
78
|
+
} | {
|
|
79
|
+
$if: ({
|
|
80
|
+
$if?: undefined;
|
|
81
|
+
$eq: string[];
|
|
82
|
+
} | {
|
|
83
|
+
$eq?: undefined;
|
|
84
|
+
$if: (string | (string | {
|
|
85
|
+
$apply: string[];
|
|
86
|
+
}[] | {
|
|
87
|
+
class: string;
|
|
88
|
+
})[])[];
|
|
89
|
+
} | {
|
|
90
|
+
$eq?: undefined;
|
|
91
|
+
$if: ((string | {
|
|
92
|
+
class: string;
|
|
93
|
+
})[] | {
|
|
94
|
+
$eq: string[];
|
|
95
|
+
})[];
|
|
96
|
+
})[];
|
|
97
|
+
$eq?: undefined;
|
|
98
|
+
})[];
|
|
99
|
+
})[] | (string | (string | {
|
|
100
|
+
class: string;
|
|
101
|
+
type: string;
|
|
102
|
+
on: {
|
|
103
|
+
click: string;
|
|
104
|
+
};
|
|
105
|
+
})[] | (string | any[] | {
|
|
106
|
+
class: string;
|
|
107
|
+
role: string;
|
|
108
|
+
'aria-label': string;
|
|
109
|
+
})[] | (string | {
|
|
110
|
+
$apply: string;
|
|
111
|
+
}[] | (string | {
|
|
112
|
+
class: string;
|
|
113
|
+
})[] | {
|
|
114
|
+
class: string;
|
|
115
|
+
})[] | {
|
|
116
|
+
class: string;
|
|
117
|
+
})[] | (string | (string | {
|
|
118
|
+
class: string;
|
|
119
|
+
rows: number;
|
|
120
|
+
spellcheck: string;
|
|
121
|
+
autocapitalize: string;
|
|
122
|
+
autocorrect: string;
|
|
123
|
+
autocomplete: string;
|
|
124
|
+
value: any;
|
|
125
|
+
readonly?: string | undefined;
|
|
126
|
+
on: {
|
|
127
|
+
change: string;
|
|
128
|
+
input?: undefined;
|
|
129
|
+
} | {
|
|
130
|
+
input: string;
|
|
131
|
+
change: string;
|
|
132
|
+
};
|
|
133
|
+
})[] | (string | (string | {
|
|
134
|
+
class: string;
|
|
135
|
+
value: string;
|
|
136
|
+
spellcheck: string;
|
|
137
|
+
autocapitalize: string;
|
|
138
|
+
autocomplete: string;
|
|
139
|
+
'aria-label': string;
|
|
140
|
+
on: {
|
|
141
|
+
input: string;
|
|
142
|
+
change: string;
|
|
143
|
+
};
|
|
144
|
+
})[] | (string | string[] | {
|
|
145
|
+
class: string;
|
|
146
|
+
})[] | {
|
|
147
|
+
class: string;
|
|
148
|
+
})[] | {
|
|
149
|
+
class: string;
|
|
150
|
+
$if?: undefined;
|
|
151
|
+
} | {
|
|
152
|
+
$if: (string | (string | {}[] | (string | {
|
|
153
|
+
type: string;
|
|
154
|
+
class: string;
|
|
155
|
+
title: string;
|
|
156
|
+
on: {
|
|
157
|
+
click: string;
|
|
158
|
+
};
|
|
159
|
+
})[] | {
|
|
160
|
+
class: string;
|
|
161
|
+
role: string;
|
|
162
|
+
})[])[];
|
|
163
|
+
class?: undefined;
|
|
164
|
+
} | {
|
|
165
|
+
$if: (string | (string | {
|
|
166
|
+
$apply: string;
|
|
167
|
+
}[] | {
|
|
168
|
+
class: string;
|
|
169
|
+
role: string;
|
|
170
|
+
})[])[];
|
|
171
|
+
class?: undefined;
|
|
172
|
+
})[] | {
|
|
173
|
+
class: string;
|
|
174
|
+
'data-mode': string;
|
|
175
|
+
'data-pane': string;
|
|
176
|
+
})[];
|
|
177
|
+
} | {
|
|
178
|
+
match: string;
|
|
179
|
+
mode: string;
|
|
180
|
+
body: (string | (string | {
|
|
181
|
+
type: string;
|
|
182
|
+
class: string;
|
|
183
|
+
title: string;
|
|
184
|
+
'aria-label': string;
|
|
185
|
+
on: {
|
|
186
|
+
click: {
|
|
187
|
+
action: string;
|
|
188
|
+
with: string;
|
|
189
|
+
};
|
|
190
|
+
};
|
|
191
|
+
})[] | (string | (string | {
|
|
192
|
+
class: string;
|
|
193
|
+
'data-badge': string;
|
|
194
|
+
})[] | (string | {
|
|
195
|
+
class: string;
|
|
196
|
+
})[] | {
|
|
197
|
+
$if?: undefined;
|
|
198
|
+
type: string;
|
|
199
|
+
class: {
|
|
200
|
+
$if: string[];
|
|
201
|
+
};
|
|
202
|
+
title: string;
|
|
203
|
+
on: {
|
|
204
|
+
click: {
|
|
205
|
+
action: string;
|
|
206
|
+
with: string;
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
} | {
|
|
210
|
+
class?: undefined;
|
|
211
|
+
type?: undefined;
|
|
212
|
+
title?: undefined;
|
|
213
|
+
on?: undefined;
|
|
214
|
+
$if: (string | (string | {
|
|
215
|
+
class: string;
|
|
216
|
+
title: string;
|
|
217
|
+
})[])[];
|
|
218
|
+
})[] | {
|
|
219
|
+
class: string;
|
|
220
|
+
})[];
|
|
221
|
+
} | {
|
|
222
|
+
match: string;
|
|
223
|
+
mode: string;
|
|
224
|
+
body: (string | {}[] | {
|
|
225
|
+
class: string;
|
|
226
|
+
type: string;
|
|
227
|
+
on: {
|
|
228
|
+
click: {
|
|
229
|
+
action: string;
|
|
230
|
+
with: string;
|
|
231
|
+
};
|
|
232
|
+
};
|
|
233
|
+
})[];
|
|
234
|
+
})[];
|
|
235
|
+
modes: Readonly<{
|
|
236
|
+
project: {
|
|
237
|
+
unmatched: string;
|
|
238
|
+
};
|
|
239
|
+
}>;
|
|
240
|
+
/** The IDE view model for the `$.project` slice. */
|
|
241
|
+
viewModel: (state: any) => any;
|
|
242
|
+
hostPolicy: typeof hostPolicy;
|
|
243
|
+
reconcileBuffer: typeof reconcileBuffer;
|
|
244
|
+
describe: (project: any) => {
|
|
245
|
+
active: any;
|
|
246
|
+
layout: any;
|
|
247
|
+
files: any;
|
|
248
|
+
};
|
|
249
|
+
validateFile: (file: any) => {
|
|
250
|
+
valid: boolean;
|
|
251
|
+
kind: string;
|
|
252
|
+
total: number;
|
|
253
|
+
errors: Array<{
|
|
254
|
+
code: string | null;
|
|
255
|
+
message: string;
|
|
256
|
+
docPath?: string;
|
|
257
|
+
}>;
|
|
258
|
+
};
|
|
259
|
+
classifyChange: typeof classifyChange;
|
|
260
|
+
parseProject: typeof parseProject;
|
|
261
|
+
};
|
|
262
|
+
export { projectViewModel, projectRules, projectModes, PROJECT_MODE, PROJECT_BASE, hostPolicy, reconcileBuffer, editorTextarea, errorLine, KIND_BADGE, };
|