spyret 0.2.0 → 0.3.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 +11 -4
- package/dist/spyret-browser.amd.js +28 -28
- package/dist/spyret-browser.global.js +28 -28
- package/dist/spyret-browser.js +28 -28
- package/dist/spyret-browser.mjs +26 -26
- package/dist/spyret.global.js +10 -10
- package/dist/spyret.js +10 -10
- package/dist/spyret.mjs +9 -9
- package/dist/spyret.pyret.js +29 -29
- package/docs/BROWSER_LIBRARY.md +9 -4
- package/docs/RELEASING.md +45 -6
- package/docs/SPYTIAL_HOOKS.md +8 -10
- package/docs/SPYTIAL_LANGUAGE.md +194 -0
- package/docs/SPYTIAL_RULES_REFERENCE.md +23 -21
- package/package.json +1 -1
- package/pyret/spytial.arr +82 -392
package/docs/BROWSER_LIBRARY.md
CHANGED
|
@@ -8,7 +8,10 @@ integration is a separate `spyret/browser` entry.
|
|
|
8
8
|
## Import a published version in CPO
|
|
9
9
|
|
|
10
10
|
A maintainer runs `npm run release:drive` and follows the
|
|
11
|
-
[
|
|
11
|
+
[CPO-save and Drive publishing instructions](RELEASING.md). The native JavaScript
|
|
12
|
+
requires CPO per-file authorization; public sharing alone is insufficient.
|
|
13
|
+
Verify the import with a second account using normal login before distributing it.
|
|
14
|
+
Use the import line the maintainer supplies:
|
|
12
15
|
|
|
13
16
|
```pyret
|
|
14
17
|
import shared-gdrive("spyret-vVERSION.arr", "WRAPPER_DRIVE_FILE_ID") as S
|
|
@@ -22,9 +25,11 @@ only one import for typed constructors and diagram functions.
|
|
|
22
25
|
|
|
23
26
|
## An ordinary native import in CPO
|
|
24
27
|
|
|
25
|
-
CPO
|
|
26
|
-
`dist/spyret.pyret.js`
|
|
27
|
-
|
|
28
|
+
CPO supports native Pyret modules through `gdrive-js`. Save the complete contents
|
|
29
|
+
of `dist/spyret.pyret.js` through a new CPO editor document **as `spyret.js`**,
|
|
30
|
+
without running it, following [the release workflow](RELEASING.md). Grant intended
|
|
31
|
+
users read access in Drive; their CPO per-file authorization must also be checked.
|
|
32
|
+
Do not convert the file to a Google document. With the saved file's ID:
|
|
28
33
|
|
|
29
34
|
```pyret
|
|
30
35
|
import gdrive-js("spyret.js", "YOUR_DRIVE_FILE_ID") as Spyret
|
package/docs/RELEASING.md
CHANGED
|
@@ -9,18 +9,57 @@ npm run release:drive
|
|
|
9
9
|
|
|
10
10
|
The script downloads the latest GitHub release and walks you through:
|
|
11
11
|
|
|
12
|
-
1.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
1. Open a new [CPO editor](https://code.pyret.org/editor) with normal Google login.
|
|
13
|
+
Replace **all** editor text (including the initial `use context` line) with the
|
|
14
|
+
contents of the prepared `.js` file. Name it `spyret-vVERSION.js`, **Save**, and
|
|
15
|
+
wait for saving to finish. **Do not Run** this document: it contains JavaScript.
|
|
16
|
+
In Google Drive, set the saved file to **Anyone with the link / Viewer** and
|
|
17
|
+
keep it under **My Drive**. Paste its CPO editor URL (`#program=...`), Drive
|
|
18
|
+
link, or file ID into the script. Use the saved file, not a CPO Share copy.
|
|
19
|
+
2. Upload the generated `.arr` wrapper to My Drive with the same sharing setting
|
|
20
|
+
and paste its Drive link into the script.
|
|
16
21
|
3. Copy the printed import into CPO and run the provided diagram example.
|
|
17
|
-
|
|
22
|
+
4. Test that same import with a **second account using normal CPO login** before
|
|
23
|
+
distributing it. The script prepares artifacts; it does not verify Google
|
|
24
|
+
permissions or perform either browser test.
|
|
18
25
|
|
|
19
|
-
|
|
26
|
+
### Why save the JavaScript through CPO?
|
|
27
|
+
|
|
28
|
+
CPO's normal login requests `drive.file`. Its `gdrive-js` loader uses an
|
|
29
|
+
authenticated request, so uploading a public JavaScript file directly to Drive
|
|
30
|
+
does not by itself authorize CPO to read it. Saving through CPO creates the file
|
|
31
|
+
with CPO's authorization. CPO saves the editor text without compiling it.
|
|
32
|
+
The outer `.arr` wrapper uses `shared-gdrive`, which has a public-file retrieval
|
|
33
|
+
path, so that file can still be uploaded directly.
|
|
34
|
+
|
|
35
|
+
For an existing JavaScript upload, **Open with → Code Pyret** in Google Drive,
|
|
36
|
+
if offered, is another way to grant per-file access without changing its ID.
|
|
37
|
+
Google documents this mechanism in its
|
|
38
|
+
[Drive authorization guidance](https://developers.google.com/workspace/drive/api/guides/handle-errors#appNotAuthorizedToFile).
|
|
39
|
+
Opening an arbitrary `editor#program=ID` link alone is not the same authorization
|
|
40
|
+
action. Pasting a link into this script only selects an ID; it grants no access.
|
|
41
|
+
|
|
42
|
+
This workflow still needs end-to-end verification with real CPO accounts.
|
|
43
|
+
Success as the publisher does not establish access for other users. If another
|
|
44
|
+
user gets a 403, they may need to authorize the JavaScript through Drive's
|
|
45
|
+
**Open with → Code Pyret** too. Do not advertise a setup-free import until the
|
|
46
|
+
second-account test passes. The old full-access login flow is not a prerequisite
|
|
47
|
+
or a recommended workaround: Google may block it.
|
|
48
|
+
|
|
49
|
+
Keep both filenames unchanged and preserve the file contents without conversion.
|
|
50
|
+
Use **My Drive**, not a Google **Shared drive**: CPO’s Drive loader omits the
|
|
51
|
+
shared-drive API flag, so files in Shared drives return 404 even when public.
|
|
52
|
+
A shortcut under My Drive does not change where a file lives.
|
|
20
53
|
The two upload files are in `release/vVERSION/upload/`; the CPO example is
|
|
21
54
|
saved separately as `release/vVERSION/import.arr`. Keep published Drive files
|
|
22
55
|
unchanged so existing imports continue to work.
|
|
23
56
|
|
|
57
|
+
If you previously uploaded directly to Drive (or used a Shared drive), rerun with
|
|
58
|
+
`npm run release:drive -- --tag v0.2.0 --out release/cpo-authorized` and follow
|
|
59
|
+
the CPO-save workflow above. Paste the new links when prompted so the wrapper
|
|
60
|
+
uses the new JavaScript file ID. The fresh output directory preserves the old
|
|
61
|
+
release artifacts; existing wrappers are never overwritten with a different ID.
|
|
62
|
+
|
|
24
63
|
To select a specific release, use `npm run release:drive -- --tag v0.2.0`.
|
|
25
64
|
The release must contain the browser module and Pyret rules; `v0.1.1` is headless
|
|
26
65
|
and cannot be used. No Google Cloud project, service account, or API setup is needed.
|
package/docs/SPYTIAL_HOOKS.md
CHANGED
|
@@ -13,8 +13,8 @@ data Tree:
|
|
|
13
13
|
sharing:
|
|
14
14
|
method _spytial(self) -> List<S.SpytialRule>:
|
|
15
15
|
[list:
|
|
16
|
-
S.orientation("children", [list: S.
|
|
17
|
-
S.align("siblings", S.
|
|
16
|
+
S.orientation("children", [list: S.below]),
|
|
17
|
+
S.align("siblings", S.horizontal)
|
|
18
18
|
]
|
|
19
19
|
end
|
|
20
20
|
end
|
|
@@ -22,13 +22,11 @@ end
|
|
|
22
22
|
|
|
23
23
|
Public constructors wrap their results as `constraint(Constraint)` or
|
|
24
24
|
`directive(Directive)` automatically. Compose rules with ordinary Pyret lists;
|
|
25
|
-
the serializer puts each rule in its proper YAML section.
|
|
26
|
-
|
|
25
|
+
the serializer puts each rule in its proper YAML section. Use named fields in
|
|
26
|
+
records for optional properties and typed constructors for nested style blocks:
|
|
27
27
|
|
|
28
28
|
```pyret
|
|
29
|
-
S.atom-style-
|
|
30
|
-
.with-selector("leaf")
|
|
31
|
-
.with-fill-style(S.default-fill-style.with-color("red")))
|
|
29
|
+
S.atom-style("leaf", {fill-style: S.fill-style({color: "red"})})
|
|
32
30
|
```
|
|
33
31
|
|
|
34
32
|
From the JavaScript host, after evaluating the program:
|
|
@@ -60,8 +58,9 @@ rule list directly. Capture and `toDataInstance` never invoke hooks, and omit
|
|
|
60
58
|
callable `_spytial` metadata on ordinary objects or outside a datatype's declared
|
|
61
59
|
slots. Other capture restrictions still apply.
|
|
62
60
|
|
|
63
|
-
See the [
|
|
64
|
-
|
|
61
|
+
See the [layout rule guide](SPYTIAL_LANGUAGE.md) for examples and the
|
|
62
|
+
[generated rule reference](SPYTIAL_RULES_REFERENCE.md) for every constructor,
|
|
63
|
+
enum and option. Pyret annotations check field types; serialization
|
|
65
64
|
checks numeric bounds, string patterns and incompatible directions. Selector
|
|
66
65
|
meaning and result arity remain Core's responsibility.
|
|
67
66
|
|
|
@@ -70,4 +69,3 @@ then run `npm run generate:spytial`. Commit the generated Pyret source, serializ
|
|
|
70
69
|
schema and reference together. `npm run check:spytial` and the tests detect drift;
|
|
71
70
|
unknown field types or enum vocabularies fail generation for explicit handling.
|
|
72
71
|
No Core runtime dependency is added to the published package.
|
|
73
|
-
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# Spyret's layout rule language
|
|
2
|
+
|
|
3
|
+
Spyret lets a Pyret program describe how its data should be drawn. The
|
|
4
|
+
`pyret/spytial.arr` library, imported as `S` below, provides typed constructors
|
|
5
|
+
for Spytial constraints and directives. Each constructor returns an
|
|
6
|
+
`S.SpytialRule`; put rules in an ordinary Pyret list. `S.diagram(value)` finds
|
|
7
|
+
`_spytial` hooks on reachable values, collects their rules, and displays the
|
|
8
|
+
diagram. See [layout hooks](SPYTIAL_HOOKS.md) for the hook contract and
|
|
9
|
+
[the README](../README.md#pyret-import-describe-display) for the CPO import.
|
|
10
|
+
This page describes the 0.3.0 source API. The published v0.2.0 wrapper uses
|
|
11
|
+
prefixed enum names and `atom-style-with`; update those calls when moving to
|
|
12
|
+
0.3.0. Style properties now use named records and typed blocks instead of
|
|
13
|
+
`.with-*` chains.
|
|
14
|
+
|
|
15
|
+
## A first diagram
|
|
16
|
+
|
|
17
|
+
```pyret
|
|
18
|
+
# Use the versioned wrapper import supplied by the library maintainer.
|
|
19
|
+
import shared-gdrive("spyret-vVERSION.arr", "WRAPPER_DRIVE_FILE_ID") as S
|
|
20
|
+
|
|
21
|
+
data Tree:
|
|
22
|
+
| leaf(value)
|
|
23
|
+
| branch(left, right)
|
|
24
|
+
sharing:
|
|
25
|
+
method _spytial(self) -> List<S.SpytialRule>:
|
|
26
|
+
[list:
|
|
27
|
+
S.orientation("left + right", [list: S.below]),
|
|
28
|
+
S.orientation("left", [list: S.left]),
|
|
29
|
+
S.orientation("right", [list: S.right]),
|
|
30
|
+
S.atom-style("leaf", {fill-style: S.fill-style({color: "#e0f2ff"})})
|
|
31
|
+
]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
S.diagram(branch(leaf(1), leaf(2)))
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The `left + right` selector finds parent-to-child pairs. For each pair,
|
|
39
|
+
`below` places the child below the parent. The next two rules put
|
|
40
|
+
left children to the left and right children to the right. The style rule fills
|
|
41
|
+
leaf nodes. Rule order does not turn later rules into overrides; Spytial applies
|
|
42
|
+
them together and reports conflicting constraints.
|
|
43
|
+
|
|
44
|
+
The same constructors work in a local `import file("spytial.arr") as S` if the
|
|
45
|
+
library is available as a file. That import supplies rule constructors; the
|
|
46
|
+
versioned wrapper also supplies `diagram` and `diagram-with-rules`.
|
|
47
|
+
|
|
48
|
+
## Selectors and direction
|
|
49
|
+
|
|
50
|
+
A selector is a **string containing a Spytial relational expression**, not a
|
|
51
|
+
Pyret function. A unary selector such as `"leaf"` selects nodes. A binary
|
|
52
|
+
selector such as `"left"` or `"left + right"` selects `(source, target)` pairs.
|
|
53
|
+
The expected arity depends on the rule. For orientation, the direction names
|
|
54
|
+
describe where the **target** goes relative to the source. Thus, if `left`
|
|
55
|
+
contains `(parent, child)`, `S.below` puts the child below its parent.
|
|
56
|
+
|
|
57
|
+
Common expressions are a type name (`"leaf"`), a field name (`"left"`), a
|
|
58
|
+
union (`"left + right"`), or a transitive closure (`"^(left + right)"`). Keep
|
|
59
|
+
operators inside the quoted Pyret string. See [Spytial Core's selector
|
|
60
|
+
documentation](https://github.com/sidprasad/spytial-core/blob/main/site/selectors.md)
|
|
61
|
+
for the full expression language and arity rules.
|
|
62
|
+
|
|
63
|
+
| Pyret direction | Meaning for the target |
|
|
64
|
+
| --- | --- |
|
|
65
|
+
| `S.above`, `S.below` | Strictly above or below; sideways offset is allowed. |
|
|
66
|
+
| `S.left`, `S.right` | Strictly left or right; vertical offset is allowed. |
|
|
67
|
+
| `S.directly-above`, `S.directly-below` | Above or below and horizontally centered. |
|
|
68
|
+
| `S.directly-left`, `S.directly-right` | Left or right and vertically centered. |
|
|
69
|
+
|
|
70
|
+
You can combine compatible directions, for example
|
|
71
|
+
`[list: S.below, S.left]`. Opposites such as `above` and
|
|
72
|
+
`below` cannot be combined. A `directly-*` direction can only be combined with
|
|
73
|
+
its matching plain direction. Spyret checks these combinations when it
|
|
74
|
+
serializes the rule list.
|
|
75
|
+
|
|
76
|
+
## Constraints: layout and visibility
|
|
77
|
+
|
|
78
|
+
| Constructor | What it does |
|
|
79
|
+
| --- | --- |
|
|
80
|
+
| `S.orientation(selector, directions)` | Places targets of a binary selector relative to sources. |
|
|
81
|
+
| `S.cyclic(selector)` | Arranges nodes in the order of a binary selector around a circle. |
|
|
82
|
+
| `S.align(selector, direction)` | Gives selected nodes or node pairs a common row (`S.horizontal`) or column (`S.vertical`). |
|
|
83
|
+
| `S.group(selector, name)` | Draws a box around selected nodes; a binary selector makes a group per first-column key. |
|
|
84
|
+
| `S.size(width, height)` | Sets node dimensions in pixels; select the affected nodes with `S.size-with(width, height, {selector: "..."})`. Both numbers must be positive. |
|
|
85
|
+
| `S.hide-atom(selector)` | Removes selected nodes and their edges from the diagram. |
|
|
86
|
+
|
|
87
|
+
For example:
|
|
88
|
+
|
|
89
|
+
```pyret
|
|
90
|
+
[list:
|
|
91
|
+
S.cyclic-with("next", {direction: S.counterclockwise}),
|
|
92
|
+
S.align("siblings", S.horizontal),
|
|
93
|
+
S.group("children", "Family"),
|
|
94
|
+
S.size-with(150, 80, {selector: "branch"}),
|
|
95
|
+
S.hide-atom("InternalNode")
|
|
96
|
+
]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Constraints can also use `{hold: S.never}` to require that a relation
|
|
100
|
+
**does not** hold. For instance, negating `S.above` means the target is
|
|
101
|
+
not strictly above the source; it does not require the target to be below.
|
|
102
|
+
`S.always` expresses the normal positive constraint.
|
|
103
|
+
|
|
104
|
+
## Directives: appearance and labels
|
|
105
|
+
|
|
106
|
+
| Constructor | What it does |
|
|
107
|
+
| --- | --- |
|
|
108
|
+
| `S.flag(name)` | Applies a global display flag such as `S.hide-disconnected` or `S.hide-disconnected-built-ins`. |
|
|
109
|
+
| `S.atom-style(selector, style)` | Styles the selected nodes' fill, border, icon, label, and label visibility. |
|
|
110
|
+
| `S.edge-style(field, style)` | Styles a relation's edge line and label, or hides the edge. |
|
|
111
|
+
| `S.attribute(field)` | Shows a field as text inside its source node instead of as an edge. |
|
|
112
|
+
| `S.tag(to-tag, name, value)` | Adds computed text to matching nodes while retaining the original edges. |
|
|
113
|
+
| `S.hide-field(field)` | Hides a field's drawn edges. |
|
|
114
|
+
| `S.inferred-edge(name, selector)` | Draws additional edges computed from a selector. |
|
|
115
|
+
|
|
116
|
+
`field` names a relation; optional `selector` and `filter` fields narrow where
|
|
117
|
+
field-based directives apply. `tag` takes a unary `to-tag` selector and a
|
|
118
|
+
`value` selector whose first column identifies the node receiving the tag.
|
|
119
|
+
|
|
120
|
+
```pyret
|
|
121
|
+
[list:
|
|
122
|
+
S.flag(S.hide-disconnected-built-ins),
|
|
123
|
+
S.atom-style("leaf", {border-style: S.border-style({
|
|
124
|
+
color: "#2563eb", width: 2
|
|
125
|
+
})}),
|
|
126
|
+
S.edge-style("left", {line-style: S.line-style({
|
|
127
|
+
color: "#64748b", pattern: S.dashed
|
|
128
|
+
})}),
|
|
129
|
+
S.attribute("value"),
|
|
130
|
+
S.hide-field("internal"),
|
|
131
|
+
S.inferred-edge("descendant", "^(left + right)")
|
|
132
|
+
]
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Use `atom-style`, `edge-style`, and `inferred-edge` for new styles. The exported
|
|
136
|
+
`icon`, `atom-color`, and `edge-color` constructors are older forms retained for
|
|
137
|
+
compatibility.
|
|
138
|
+
|
|
139
|
+
## Optional fields and reusable style blocks
|
|
140
|
+
|
|
141
|
+
Rules with optional fields have a short constructor for their required
|
|
142
|
+
arguments and a `-with` constructor that takes a Pyret record of named fields.
|
|
143
|
+
`atom-style` takes a selector and a style record; `edge-style` takes a field
|
|
144
|
+
and a style record. Within those records, nested styles use the named types
|
|
145
|
+
`S.TextStyle`, `S.LineStyle`, `S.FillStyle`, `S.BorderStyle`, and `S.IconStyle`.
|
|
146
|
+
For example, `S.text-style({color: "navy"})` makes a `TextStyle`. Leave any
|
|
147
|
+
field out to let Spytial Core supply its display default.
|
|
148
|
+
|
|
149
|
+
```pyret
|
|
150
|
+
S.orientation-with("children", [list: S.below], {hold: S.always})
|
|
151
|
+
|
|
152
|
+
S.group-with("children", "Family", {
|
|
153
|
+
add-edge: S.group-add-edge({
|
|
154
|
+
points: S.togroup,
|
|
155
|
+
line-style: S.line-style({weight: 2})
|
|
156
|
+
}),
|
|
157
|
+
text-style: S.text-style({color: "#7c3aed"})
|
|
158
|
+
})
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The group example draws a connector from each group key to its box. Its
|
|
162
|
+
`line-style` styles that connector; the group's own `text-style` styles its
|
|
163
|
+
caption. Most rule records also accept a `source: S.rule-source({...})` field;
|
|
164
|
+
this records the originating rule text and optional location
|
|
165
|
+
for error reports without changing layout.
|
|
166
|
+
|
|
167
|
+
The [generated rule reference](SPYTIAL_RULES_REFERENCE.md) lists every
|
|
168
|
+
constructor, option, enum, and style block for the currently pinned Core
|
|
169
|
+
language version. Spyret checks Pyret types through annotations, then checks
|
|
170
|
+
numeric bounds, string patterns, and direction compatibility while serializing.
|
|
171
|
+
|
|
172
|
+
## How rules become a diagram
|
|
173
|
+
|
|
174
|
+
`_spytial` returns `List<S.SpytialRule>`. Spyret turns each list into one YAML
|
|
175
|
+
document with `constraints` and `directives` sections; constructors choose the
|
|
176
|
+
correct section automatically. `S.diagram(value)` collects the hooks reachable
|
|
177
|
+
from `value`. To bypass hooks, call `S.diagram-with-rules(value, rules)`; an
|
|
178
|
+
existing YAML document can be passed as `S.diagram(value, yaml)`.
|
|
179
|
+
|
|
180
|
+
For example, `S.orientation("left", [list: S.below])` represents the
|
|
181
|
+
following constraint (the serializer quotes YAML keys and strings):
|
|
182
|
+
|
|
183
|
+
```yaml
|
|
184
|
+
constraints:
|
|
185
|
+
- orientation:
|
|
186
|
+
selector: left
|
|
187
|
+
directions: [below]
|
|
188
|
+
directives: []
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
For host code, `getSpytialSpec(value, runtime)` returns the collected YAML
|
|
192
|
+
documents as `string[]`, and `spytialRulesToYaml(rules, runtime)` serializes an
|
|
193
|
+
already evaluated list. See [layout hooks](SPYTIAL_HOOKS.md) for collection
|
|
194
|
+
order, error behavior, and runtime requirements.
|
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
Core 6.3.2; language 2026-09-18.
|
|
4
4
|
|
|
5
5
|
Import `pyret/spytial.arr` as `S`. Constructors return `S.SpytialRule` automatically.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
Enum values are qualified through `S`, for example `S.below` and `S.horizontal`.
|
|
7
|
+
Optional fields use Pyret records with named keys. Pass the record to `<rule>-with`;
|
|
8
|
+
`atom-style(selector, style)` and `edge-style(field, style)` take one directly.
|
|
9
|
+
Nested style blocks are typed constructors such as `S.fill-style({color: "red"})`.
|
|
10
|
+
Unset fields are omitted from YAML; Spytial Core supplies their defaults.
|
|
9
11
|
|
|
10
12
|
Numeric bounds, patterns and incompatible direction combinations are checked during serialization.
|
|
11
13
|
|
|
@@ -18,8 +20,8 @@ Numeric bounds, patterns and incompatible direction combinations are checked dur
|
|
|
18
20
|
| `size(width :: Number, height :: Number)` | `selector: String`, `source: RuleSource` |
|
|
19
21
|
| `hide-atom(selector :: String)` | `source: RuleSource` |
|
|
20
22
|
| `flag(name :: LayoutFlag)` | |
|
|
21
|
-
| `atom-style()` |
|
|
22
|
-
| `edge-style(field :: String)` | `selector
|
|
23
|
+
| `atom-style(selector :: String, style :: Any)` | A record with optional `fill-style`, `border-style`, `icon-style`, `text-style`, `show-label`, and `source` keys. |
|
|
24
|
+
| `edge-style(field :: String, style :: Any)` | A record with optional `selector`, `filter`, `line-style`, `text-style`, `show-label`, `hidden`, and `source` keys. |
|
|
23
25
|
| `attribute(field :: String)` | `selector: String`, `filter: String`, `text-style: TextStyle`, `source: RuleSource` |
|
|
24
26
|
| `tag(to-tag :: String, name :: String, value :: String)` | `text-style: TextStyle`, `source: RuleSource` |
|
|
25
27
|
| `hide-field(field :: String)` | `selector: String`, `filter: String`, `source: RuleSource` |
|
|
@@ -30,22 +32,22 @@ Numeric bounds, patterns and incompatible direction combinations are checked dur
|
|
|
30
32
|
|
|
31
33
|
## Enum values
|
|
32
34
|
|
|
33
|
-
- `TextSize`: `
|
|
34
|
-
- `LinePattern`: `
|
|
35
|
-
- `IconPlacement`: `
|
|
36
|
-
- `Direction`: `
|
|
37
|
-
- `Hold`: `
|
|
38
|
-
- `Rotation`: `
|
|
39
|
-
- `Alignment`: `
|
|
40
|
-
- `GroupEdgeDirection`: `group-edge
|
|
41
|
-
- `LayoutFlag`: `
|
|
35
|
+
- `TextSize`: `small`, `normal`, `large`
|
|
36
|
+
- `LinePattern`: `solid`, `dashed`, `dotted`
|
|
37
|
+
- `IconPlacement`: `full`, `badge`
|
|
38
|
+
- `Direction`: `above`, `below`, `left`, `right`, `directly-above`, `directly-below`, `directly-left`, `directly-right`
|
|
39
|
+
- `Hold`: `always`, `never`
|
|
40
|
+
- `Rotation`: `clockwise`, `counterclockwise`
|
|
41
|
+
- `Alignment`: `horizontal`, `vertical`
|
|
42
|
+
- `GroupEdgeDirection`: `no-group-edge`, `togroup`, `fromgroup`
|
|
43
|
+
- `LayoutFlag`: `hide-disconnected`, `hide-disconnected-built-ins`
|
|
42
44
|
|
|
43
45
|
## Blocks
|
|
44
46
|
|
|
45
|
-
- `text-style(size:
|
|
46
|
-
- `line-style(color:
|
|
47
|
-
- `fill-style(color:
|
|
48
|
-
- `border-style(color:
|
|
49
|
-
- `icon-style(path:
|
|
50
|
-
- `rule-source(text: String, location:
|
|
51
|
-
- `group-add-edge(points:
|
|
47
|
+
- `text-style({size: TextSize?, color: String?})`
|
|
48
|
+
- `line-style({color: String?, pattern: LinePattern?, weight: Number?, highlight: String?})`
|
|
49
|
+
- `fill-style({color: String?})`
|
|
50
|
+
- `border-style({color: String?, width: Number?})`
|
|
51
|
+
- `icon-style({path: String?, placement: IconPlacement?, opacity: Number?})`
|
|
52
|
+
- `rule-source({text: String, location: String?})`
|
|
53
|
+
- `group-add-edge({points: GroupEdgeDirection?, line-style: LineStyle?, text-style: TextStyle?})`
|