@markii/stdlib 0.8.1 → 0.10.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/dist/contracts.d.ts +1 -16
- package/dist/contracts.js +66 -22
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/layout.d.ts +54 -0
- package/dist/layout.js +78 -0
- package/dist/text-align.d.ts +35 -0
- package/dist/text-align.js +31 -0
- package/package.json +1 -1
package/dist/contracts.d.ts
CHANGED
|
@@ -1,18 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The neutral, framework-agnostic definition of Mark's standard component
|
|
3
|
-
* *contracts* (docs/integration.md/§13.6): name + kind + attribute schema +
|
|
4
|
-
* semantics, as pure data — zero React, zero dependency on any other
|
|
5
|
-
* `@markii/*` package. A renderer (today `@markii/react`, tomorrow a
|
|
6
|
-
* hypothetical `@markii/gnome`) implements these same contracts against its
|
|
7
|
-
* own component framework; this module is the seam that makes "one format,
|
|
8
|
-
* many renderers" a checkable fact rather than a hope.
|
|
9
|
-
*
|
|
10
|
-
* A contract never describes markup, styling, or a component
|
|
11
|
-
* implementation — only what a directive named `name` means: how it is
|
|
12
|
-
* written (`kind`, matching the three directive forms from docs/format.md/§13:
|
|
13
|
-
* `inline` -> `:name[...]`, `leaf` -> `::name{...}`, `container` ->
|
|
14
|
-
* `:::name{...} ... :::`) and what attributes it accepts.
|
|
15
|
-
*/
|
|
16
1
|
/**
|
|
17
2
|
* Which of the three directive forms a component is written as. Matches
|
|
18
3
|
* `remark-directive`'s three node types one-to-one:
|
|
@@ -49,7 +34,7 @@ export interface ComponentContract {
|
|
|
49
34
|
/**
|
|
50
35
|
* The standard component set, seeded from the components that ship with
|
|
51
36
|
* `@markii/react` today (`packages/platforms/markii-react/src/components/
|
|
52
|
-
* {callout,kbd,rating,details,card,badge,figure,tabs,tab}.tsx`). Each
|
|
37
|
+
* {callout,kbd,rating,divider,details,card,badge,figure,tabs,tab}.tsx`). Each
|
|
53
38
|
* contract was written by reading the real implementation — `kind` from how
|
|
54
39
|
* the component is registered in `defaultRegistry`, `attributes` from
|
|
55
40
|
* exactly the props the component reads (no invented attributes).
|
package/dist/contracts.js
CHANGED
|
@@ -13,38 +13,54 @@
|
|
|
13
13
|
* `inline` -> `:name[...]`, `leaf` -> `::name{...}`, `container` ->
|
|
14
14
|
* `:::name{...} ... :::`) and what attributes it accepts.
|
|
15
15
|
*/
|
|
16
|
+
import { LAYOUT_ATTRIBUTES, layoutWrapperAxis, otherLayoutAxis, } from './layout.js';
|
|
17
|
+
import { TEXT_ALIGN_ATTRIBUTE } from './text-align.js';
|
|
16
18
|
/**
|
|
17
|
-
* Builds one of docs/format.md's
|
|
18
|
-
* `center`/`right`/`wide`/`narrow`/`full
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* hand-copied
|
|
22
|
-
* otherwise be easy to miss across
|
|
19
|
+
* Builds one of docs/format.md's layout-wrapper container contracts,
|
|
20
|
+
* `center`/`left`/`right`/`wide`/`narrow`/`full`/`fit`, which are otherwise
|
|
21
|
+
* identical in shape and differ only in `name`, the preset-specific half of
|
|
22
|
+
* `description`, and which of the two layout axes they leave open. A tiny
|
|
23
|
+
* helper rather than one hand-copied literal per preset, since a typo in
|
|
24
|
+
* one copy's `kind`/`attributes` would otherwise be easy to miss across a
|
|
25
|
+
* run of near-duplicate blocks.
|
|
26
|
+
*
|
|
27
|
+
* A wrapper decides ONE axis by its name and accepts the OTHER as an
|
|
28
|
+
* attribute (docs/spec.md §3), so an alignment wrapper declares `width` and
|
|
29
|
+
* a width wrapper declares `align`, taken from `./layout.ts`'s one
|
|
30
|
+
* definition of those two schemas. An attribute for the wrapper's own axis
|
|
31
|
+
* is deliberately absent from the contract: the name already decided it,
|
|
32
|
+
* and writing it is ignored rather than an error.
|
|
23
33
|
*
|
|
24
34
|
* `whatItDoes` is the preset-specific clause (e.g. "Centers narrower-than-
|
|
25
35
|
* column plain markdown..."); the shared clause about why these exist (the
|
|
26
|
-
* attribute mechanism cannot reach plain markdown)
|
|
27
|
-
*
|
|
36
|
+
* attribute mechanism cannot reach plain markdown) is appended identically
|
|
37
|
+
* for all of them.
|
|
28
38
|
*/
|
|
29
39
|
function layoutWrapperContract(name, whatItDoes) {
|
|
40
|
+
const ownAxis = layoutWrapperAxis(name);
|
|
41
|
+
if (ownAxis === undefined) {
|
|
42
|
+
throw new Error(`"${name}" is not a layout-wrapper name`);
|
|
43
|
+
}
|
|
44
|
+
const openAxis = otherLayoutAxis(ownAxis);
|
|
30
45
|
return {
|
|
31
46
|
name,
|
|
32
47
|
kind: 'container',
|
|
33
|
-
attributes: {},
|
|
34
|
-
description: `${whatItDoes}
|
|
35
|
-
'
|
|
36
|
-
'
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
'
|
|
41
|
-
'
|
|
48
|
+
attributes: { [openAxis]: LAYOUT_ATTRIBUTES[openAxis] },
|
|
49
|
+
description: `${whatItDoes} A wrapper reaches plain markdown that a directive ` +
|
|
50
|
+
'attribute structurally cannot: a GFM table or a bare image has no ' +
|
|
51
|
+
'`{...}` to write `width=`/`align=` into. It sets one of the two ' +
|
|
52
|
+
`layout axes by its name and takes the other, \`${openAxis}\`, as an ` +
|
|
53
|
+
`attribute, so \`:::${name}{${openAxis}=...}\` applies both to the ` +
|
|
54
|
+
`one scope. An \`${ownAxis}\` attribute is ignored here, since the ` +
|
|
55
|
+
'name already decided that axis. Nesting two wrappers composes the ' +
|
|
56
|
+
'same way, e.g. `::::center :::narrow ... ::: ::::` (the outer fence ' +
|
|
57
|
+
'needs more colons than the inner one).',
|
|
42
58
|
};
|
|
43
59
|
}
|
|
44
60
|
/**
|
|
45
61
|
* The standard component set, seeded from the components that ship with
|
|
46
62
|
* `@markii/react` today (`packages/platforms/markii-react/src/components/
|
|
47
|
-
* {callout,kbd,rating,details,card,badge,figure,tabs,tab}.tsx`). Each
|
|
63
|
+
* {callout,kbd,rating,divider,details,card,badge,figure,tabs,tab}.tsx`). Each
|
|
48
64
|
* contract was written by reading the real implementation — `kind` from how
|
|
49
65
|
* the component is registered in `defaultRegistry`, `attributes` from
|
|
50
66
|
* exactly the props the component reads (no invented attributes).
|
|
@@ -69,6 +85,7 @@ export const STANDARD_COMPONENTS = {
|
|
|
69
85
|
required: false,
|
|
70
86
|
description: 'Optional header text shown above the body. Absent means no header line is rendered.',
|
|
71
87
|
},
|
|
88
|
+
text: TEXT_ALIGN_ATTRIBUTE,
|
|
72
89
|
},
|
|
73
90
|
description: "A colored box for an aside, warning, or danger note. Body is the directive's inner markdown, rendered as-is.",
|
|
74
91
|
},
|
|
@@ -95,6 +112,30 @@ export const STANDARD_COMPONENTS = {
|
|
|
95
112
|
},
|
|
96
113
|
description: 'A leaf directive rendering a row of stars, e.g. `::rating{value=3 max=5}`. Has no body — both attributes are optional and degrade gracefully rather than throwing.',
|
|
97
114
|
},
|
|
115
|
+
divider: {
|
|
116
|
+
name: 'divider',
|
|
117
|
+
kind: 'leaf',
|
|
118
|
+
attributes: {
|
|
119
|
+
label: {
|
|
120
|
+
type: 'string',
|
|
121
|
+
required: false,
|
|
122
|
+
description: 'Optional short text shown in the break, centered unless `label-align` says otherwise. Absent or empty means an unlabeled divider.',
|
|
123
|
+
},
|
|
124
|
+
variant: {
|
|
125
|
+
type: 'string',
|
|
126
|
+
required: false,
|
|
127
|
+
enum: ['line', 'dots', 'ornament'],
|
|
128
|
+
description: 'Which break to draw: a solid hairline, a dotted hairline, or a centered ornament with no hairline. Defaults to `line` when absent or not one of the allowed values.',
|
|
129
|
+
},
|
|
130
|
+
'label-align': {
|
|
131
|
+
type: 'string',
|
|
132
|
+
required: false,
|
|
133
|
+
enum: ['left', 'center', 'right'],
|
|
134
|
+
description: 'Where the label sits along the rule. Defaults to `center` when absent or not one of the allowed values.',
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
description: 'A leaf directive drawing a section break, e.g. `::divider{label="Part 2" variant="dots"}`. Has no body, and every attribute is optional. A plain `---` thematic break keeps its own CommonMark meaning; this directive is for a break that carries a label or a chosen look.',
|
|
138
|
+
},
|
|
98
139
|
details: {
|
|
99
140
|
name: 'details',
|
|
100
141
|
kind: 'container',
|
|
@@ -121,6 +162,7 @@ export const STANDARD_COMPONENTS = {
|
|
|
121
162
|
required: false,
|
|
122
163
|
description: 'Optional header text shown above the body. Absent means no title line is rendered.',
|
|
123
164
|
},
|
|
165
|
+
text: TEXT_ALIGN_ATTRIBUTE,
|
|
124
166
|
},
|
|
125
167
|
description: 'A titled panel, e.g. `:::card{title="Notes"} ... :::`. Body is the directive\'s inner markdown, rendered as-is.',
|
|
126
168
|
},
|
|
@@ -250,21 +292,23 @@ export const STANDARD_COMPONENTS = {
|
|
|
250
292
|
enum: ['2', '3', '4'],
|
|
251
293
|
description: 'Fixed column count for the row. Defaults to auto-fit (a responsive number of equal-width columns) when absent or not one of the allowed values — an invalid `cols` is never an error.',
|
|
252
294
|
},
|
|
295
|
+
text: TEXT_ALIGN_ATTRIBUTE,
|
|
253
296
|
},
|
|
254
|
-
description: "docs/format.md's one layout container, e.g. `:::row{cols=3} ... :::`. Its block children become equal-width cells that wrap responsively and stack on narrow viewports — and simply stack in a plain markdown viewer. No spans, no per-cell sizing, no other knobs.",
|
|
297
|
+
description: "docs/format.md's one layout container, e.g. `:::row{cols=3} ... :::`. Its block children become equal-width cells that wrap responsively and stack on narrow viewports — and simply stack in a plain markdown viewer. No spans, no per-cell sizing, no other knobs. A row always fills the column, so the reserved `align` has nothing to place on it; `text` is what aligns the content inside its cells.",
|
|
255
298
|
},
|
|
256
299
|
cell: {
|
|
257
300
|
name: 'cell',
|
|
258
301
|
kind: 'container',
|
|
259
|
-
attributes: {},
|
|
260
|
-
description: "A transparent grouping container, e.g. `:::cell ... :::`. Its only job is making several blocks count as ONE cell of a `row`: a row's cells are its direct block children, so two blocks are two cells unless a `cell` groups them — and two adjacent task lists, which markdown merges into a single list, can only become two cells by putting one `cell` around each.
|
|
302
|
+
attributes: { text: TEXT_ALIGN_ATTRIBUTE },
|
|
303
|
+
description: "A transparent grouping container, e.g. `:::cell ... :::`. Its only job is making several blocks count as ONE cell of a `row`: a row's cells are its direct block children, so two blocks are two cells unless a `cell` groups them — and two adjacent task lists, which markdown merges into a single list, can only become two cells by putting one `cell` around each. Its only presentation of its own is `text`, which overrides the enclosing row's; outside a `row` it is inert. The enclosing `row` fence must use MORE colons than its `cell` children (directive container nesting rule), hence `::::row` wrapping `:::cell`.",
|
|
261
304
|
},
|
|
262
305
|
center: layoutWrapperContract('center', 'Centers narrower-than-column plain markdown (a table, an image) within its scope and sets text alignment for everything in scope, e.g. `:::center ... :::`.'),
|
|
263
|
-
left: layoutWrapperContract('left', 'Left-aligns plain markdown within its scope and sets text alignment for everything in scope, e.g. `:::left ... :::`. Mostly matches the ambient default; it exists to override an alignment inherited from an enclosing scope, such as opting one cell back out of `:::row{
|
|
306
|
+
left: layoutWrapperContract('left', 'Left-aligns plain markdown within its scope and sets text alignment for everything in scope, e.g. `:::left ... :::`. Mostly matches the ambient default; it exists to override an alignment inherited from an enclosing scope, such as opting one cell back out of `:::row{text=center}`.'),
|
|
264
307
|
right: layoutWrapperContract('right', 'Right-aligns narrower-than-column plain markdown (a table, an image) within its scope and sets text alignment for everything in scope, e.g. `:::right ... :::`.'),
|
|
265
308
|
wide: layoutWrapperContract('wide', "Sizes its scope's content to docs/format.md's wide-column width preset, e.g. `:::wide ... :::`."),
|
|
266
309
|
narrow: layoutWrapperContract('narrow', "Sizes its scope's content to docs/format.md's narrow-column width preset, e.g. `:::narrow ... :::`."),
|
|
267
310
|
full: layoutWrapperContract('full', "Sizes its scope's content to the full available document-column width, e.g. `:::full ... :::`."),
|
|
311
|
+
fit: layoutWrapperContract('fit', 'Shrinks its scope to the width of its own content rather than filling the column, e.g. `:::fit ... :::`. Pair it with an alignment to place the result, as in `:::fit{align=right} ... :::`.'),
|
|
268
312
|
};
|
|
269
313
|
/**
|
|
270
314
|
* Looks `name` up in `STANDARD_COMPONENTS`, returning `undefined` if it
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1,3 @@
|
|
|
1
1
|
export { getContract, STANDARD_COMPONENTS, type AttributeSchema, type ComponentContract, type ComponentKind, } from './contracts.js';
|
|
2
|
+
export { ALIGN_PRESETS, LAYOUT_ATTRIBUTE_KEYS, LAYOUT_ATTRIBUTES, WIDTH_PRESETS, layoutWrapperAxis, otherLayoutAxis, type LayoutAxis, } from './layout.js';
|
|
3
|
+
export { TEXT_ALIGN_ATTRIBUTE, TEXT_ALIGN_COMPONENTS, TEXT_ALIGN_PRESETS, type TextAlignPreset, } from './text-align.js';
|
package/dist/index.js
CHANGED
|
@@ -1 +1,3 @@
|
|
|
1
1
|
export { getContract, STANDARD_COMPONENTS, } from './contracts.js';
|
|
2
|
+
export { ALIGN_PRESETS, LAYOUT_ATTRIBUTE_KEYS, LAYOUT_ATTRIBUTES, WIDTH_PRESETS, layoutWrapperAxis, otherLayoutAxis, } from './layout.js';
|
|
3
|
+
export { TEXT_ALIGN_ATTRIBUTE, TEXT_ALIGN_COMPONENTS, TEXT_ALIGN_PRESETS, } from './text-align.js';
|
package/dist/layout.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The neutral definition of docs/format.md's layout system: the two
|
|
3
|
+
* reserved attributes every block directive can carry (`width`, `align`)
|
|
4
|
+
* and their closed preset vocabularies. Zero dependency, matching this
|
|
5
|
+
* package's own posture — every renderer (`@markii/react`, `@markii/html`,
|
|
6
|
+
* and any future one) builds its class-mapping logic off these same value
|
|
7
|
+
* lists instead of hand-copying the literals, which is how the two
|
|
8
|
+
* existing renderers drifted into two near-identical copies in the first
|
|
9
|
+
* place.
|
|
10
|
+
*
|
|
11
|
+
* This module carries VALUES only (the attribute names, the preset lists,
|
|
12
|
+
* and the two attributes expressed as `AttributeSchema`s for a tool that
|
|
13
|
+
* documents or completes attributes). It says nothing about markup,
|
|
14
|
+
* classes, or rendering; see each renderer's own `layout.ts` for that.
|
|
15
|
+
*/
|
|
16
|
+
import type { AttributeSchema } from './contracts.js';
|
|
17
|
+
/** The two attribute names docs/format.md reserves on every block directive. */
|
|
18
|
+
export declare const LAYOUT_ATTRIBUTE_KEYS: readonly ["width", "align"];
|
|
19
|
+
/**
|
|
20
|
+
* One of the two layout axes. `width` sizes a block's box; `align` places
|
|
21
|
+
* that box within the column. They are independent: every block has a
|
|
22
|
+
* value on both, and setting one never implies the other.
|
|
23
|
+
*/
|
|
24
|
+
export type LayoutAxis = (typeof LAYOUT_ATTRIBUTE_KEYS)[number];
|
|
25
|
+
/** The axis a wrapper of the other axis takes as an attribute (docs/spec.md §3). */
|
|
26
|
+
export declare function otherLayoutAxis(axis: LayoutAxis): LayoutAxis;
|
|
27
|
+
/**
|
|
28
|
+
* The closed `width=` preset vocabulary (docs/format.md), listed narrowest
|
|
29
|
+
* to widest so the list reads as the scale it is: `fit` hugs the block's
|
|
30
|
+
* own content, `normal` is the default column width, and `full` fills the
|
|
31
|
+
* column. Order is user-visible: a completion popup offers the values in
|
|
32
|
+
* this order.
|
|
33
|
+
*/
|
|
34
|
+
export declare const WIDTH_PRESETS: readonly ["fit", "narrow", "normal", "wide", "full"];
|
|
35
|
+
/** The closed `align=` preset vocabulary (docs/format.md), in the order the docs list them. */
|
|
36
|
+
export declare const ALIGN_PRESETS: readonly ["left", "center", "right"];
|
|
37
|
+
/**
|
|
38
|
+
* The layout axis the wrapper container named `name` sets by its NAME
|
|
39
|
+
* (docs/format.md, "The same presets as wrappers"), or `undefined` when
|
|
40
|
+
* `name` is not one of the seven wrapper names.
|
|
41
|
+
*
|
|
42
|
+
* This is the one place the seven names are classified. A wrapper owns its
|
|
43
|
+
* own axis and takes the OTHER axis as an attribute, so both renderers and
|
|
44
|
+
* the completion layer need the same answer to "which axis does this name
|
|
45
|
+
* already decide?" — deriving it here keeps a hand-copied per-name mapping
|
|
46
|
+
* out of all three.
|
|
47
|
+
*/
|
|
48
|
+
export declare function layoutWrapperAxis(name: string): LayoutAxis | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* The two reserved layout attributes as `AttributeSchema`s, so a tool that
|
|
51
|
+
* completes or documents attributes reads them exactly like a component's
|
|
52
|
+
* own.
|
|
53
|
+
*/
|
|
54
|
+
export declare const LAYOUT_ATTRIBUTES: Readonly<Record<'width' | 'align', AttributeSchema>>;
|
package/dist/layout.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/** The two attribute names docs/format.md reserves on every block directive. */
|
|
2
|
+
export const LAYOUT_ATTRIBUTE_KEYS = ['width', 'align'];
|
|
3
|
+
/** The axis a wrapper of the other axis takes as an attribute (docs/spec.md §3). */
|
|
4
|
+
export function otherLayoutAxis(axis) {
|
|
5
|
+
return axis === 'width' ? 'align' : 'width';
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The closed `width=` preset vocabulary (docs/format.md), listed narrowest
|
|
9
|
+
* to widest so the list reads as the scale it is: `fit` hugs the block's
|
|
10
|
+
* own content, `normal` is the default column width, and `full` fills the
|
|
11
|
+
* column. Order is user-visible: a completion popup offers the values in
|
|
12
|
+
* this order.
|
|
13
|
+
*/
|
|
14
|
+
export const WIDTH_PRESETS = [
|
|
15
|
+
'fit',
|
|
16
|
+
'narrow',
|
|
17
|
+
'normal',
|
|
18
|
+
'wide',
|
|
19
|
+
'full',
|
|
20
|
+
];
|
|
21
|
+
/** The closed `align=` preset vocabulary (docs/format.md), in the order the docs list them. */
|
|
22
|
+
export const ALIGN_PRESETS = ['left', 'center', 'right'];
|
|
23
|
+
/**
|
|
24
|
+
* Wrapper-name lookups as sets rather than `Array.includes` scans: a `Set`
|
|
25
|
+
* answers "is this a wrapper name" without ever resolving through a
|
|
26
|
+
* prototype chain, so a directive literally named `constructor` or
|
|
27
|
+
* `__proto__` misses cleanly. Built from the two preset lists above, so the
|
|
28
|
+
* wrapper vocabulary can never drift from the attribute vocabulary; there
|
|
29
|
+
* is no `normal` wrapper, since the default width needs no wrapper at all.
|
|
30
|
+
*/
|
|
31
|
+
const ALIGN_WRAPPER_NAMES = new Set(ALIGN_PRESETS);
|
|
32
|
+
const WIDTH_WRAPPER_NAMES = new Set(WIDTH_PRESETS.filter((preset) => preset !== 'normal'));
|
|
33
|
+
/**
|
|
34
|
+
* The layout axis the wrapper container named `name` sets by its NAME
|
|
35
|
+
* (docs/format.md, "The same presets as wrappers"), or `undefined` when
|
|
36
|
+
* `name` is not one of the seven wrapper names.
|
|
37
|
+
*
|
|
38
|
+
* This is the one place the seven names are classified. A wrapper owns its
|
|
39
|
+
* own axis and takes the OTHER axis as an attribute, so both renderers and
|
|
40
|
+
* the completion layer need the same answer to "which axis does this name
|
|
41
|
+
* already decide?" — deriving it here keeps a hand-copied per-name mapping
|
|
42
|
+
* out of all three.
|
|
43
|
+
*/
|
|
44
|
+
export function layoutWrapperAxis(name) {
|
|
45
|
+
if (ALIGN_WRAPPER_NAMES.has(name))
|
|
46
|
+
return 'align';
|
|
47
|
+
if (WIDTH_WRAPPER_NAMES.has(name))
|
|
48
|
+
return 'width';
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The two reserved layout attributes as `AttributeSchema`s, so a tool that
|
|
53
|
+
* completes or documents attributes reads them exactly like a component's
|
|
54
|
+
* own.
|
|
55
|
+
*/
|
|
56
|
+
export const LAYOUT_ATTRIBUTES = {
|
|
57
|
+
width: {
|
|
58
|
+
type: 'string',
|
|
59
|
+
required: false,
|
|
60
|
+
enum: WIDTH_PRESETS,
|
|
61
|
+
description: 'Sets how wide the directive renders, from narrowest to widest: ' +
|
|
62
|
+
'`fit` shrinks the block to its own content, then `narrow`, ' +
|
|
63
|
+
'`normal` at the default column width, `wide`, and `full`. ' +
|
|
64
|
+
'`normal` is the explicit default and produces no class, the same ' +
|
|
65
|
+
'as leaving `width` off entirely. An invalid value is ignored as if ' +
|
|
66
|
+
'absent; nothing errors.',
|
|
67
|
+
},
|
|
68
|
+
align: {
|
|
69
|
+
type: 'string',
|
|
70
|
+
required: false,
|
|
71
|
+
enum: ALIGN_PRESETS,
|
|
72
|
+
description: 'Places the directive within the column: `left`, `center`, or ' +
|
|
73
|
+
"`right`, defaulting to `left`. It moves the block's box and never " +
|
|
74
|
+
'its contents, so it only shows when the box is narrower than the ' +
|
|
75
|
+
'column: pair it with a `width` such as `fit` or `narrow`. An ' +
|
|
76
|
+
'invalid value is ignored as if absent; nothing errors.',
|
|
77
|
+
},
|
|
78
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `text` attribute (docs/format.md, "Aligning text inside a component";
|
|
3
|
+
* docs/spec.md §3): the standard set's one content-alignment attribute.
|
|
4
|
+
*
|
|
5
|
+
* `text` is deliberately NOT part of the layout system in `./layout.ts`.
|
|
6
|
+
* `width` and `align` are reserved on every directive and are intercepted
|
|
7
|
+
* by the renderer before a component ever sees them, because they mean the
|
|
8
|
+
* same thing on every block. `text` means "align the text inside THIS
|
|
9
|
+
* component", which only a component can act on, so it reaches the
|
|
10
|
+
* component like any other attribute of its own and appears in each of
|
|
11
|
+
* those components' contracts.
|
|
12
|
+
*
|
|
13
|
+
* This module carries values only: the closed value list and the schema
|
|
14
|
+
* four contracts share. It says nothing about markup or classes; each
|
|
15
|
+
* renderer's own `layout.ts` maps a value to a class.
|
|
16
|
+
*/
|
|
17
|
+
import type { AttributeSchema } from './contracts.js';
|
|
18
|
+
/** The closed `text=` value vocabulary, in the order docs/format.md lists them. */
|
|
19
|
+
export declare const TEXT_ALIGN_PRESETS: readonly ["left", "center", "right"];
|
|
20
|
+
/** One of the closed `text=` values. */
|
|
21
|
+
export type TextAlignPreset = (typeof TEXT_ALIGN_PRESETS)[number];
|
|
22
|
+
/**
|
|
23
|
+
* The standard components that accept `text` (docs/spec.md §3). Listed here
|
|
24
|
+
* so `./contracts.ts` builds all four from one source, and so a test can
|
|
25
|
+
* assert the set both renderers honor is exactly this one.
|
|
26
|
+
*/
|
|
27
|
+
export declare const TEXT_ALIGN_COMPONENTS: readonly ["row", "cell", "card", "callout"];
|
|
28
|
+
/**
|
|
29
|
+
* The shared `text` schema. Identical wording on all four components on
|
|
30
|
+
* purpose: the attribute means the same thing everywhere, and a reader who
|
|
31
|
+
* learned it on `callout` should not have to re-read it on `card`. The
|
|
32
|
+
* row-specific cascade is spelled out because it is the one place `text`
|
|
33
|
+
* reaches past the component it was written on.
|
|
34
|
+
*/
|
|
35
|
+
export declare const TEXT_ALIGN_ATTRIBUTE: AttributeSchema;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** The closed `text=` value vocabulary, in the order docs/format.md lists them. */
|
|
2
|
+
export const TEXT_ALIGN_PRESETS = ['left', 'center', 'right'];
|
|
3
|
+
/**
|
|
4
|
+
* The standard components that accept `text` (docs/spec.md §3). Listed here
|
|
5
|
+
* so `./contracts.ts` builds all four from one source, and so a test can
|
|
6
|
+
* assert the set both renderers honor is exactly this one.
|
|
7
|
+
*/
|
|
8
|
+
export const TEXT_ALIGN_COMPONENTS = [
|
|
9
|
+
'row',
|
|
10
|
+
'cell',
|
|
11
|
+
'card',
|
|
12
|
+
'callout',
|
|
13
|
+
];
|
|
14
|
+
/**
|
|
15
|
+
* The shared `text` schema. Identical wording on all four components on
|
|
16
|
+
* purpose: the attribute means the same thing everywhere, and a reader who
|
|
17
|
+
* learned it on `callout` should not have to re-read it on `card`. The
|
|
18
|
+
* row-specific cascade is spelled out because it is the one place `text`
|
|
19
|
+
* reaches past the component it was written on.
|
|
20
|
+
*/
|
|
21
|
+
export const TEXT_ALIGN_ATTRIBUTE = {
|
|
22
|
+
type: 'string',
|
|
23
|
+
required: false,
|
|
24
|
+
enum: TEXT_ALIGN_PRESETS,
|
|
25
|
+
description: 'Aligns the text inside this component: `left`, `center`, or `right`. ' +
|
|
26
|
+
'On a `row` it applies to every cell, a cell with its own `text` ' +
|
|
27
|
+
'overrides it, and an alignment wrapper written inside a cell wins ' +
|
|
28
|
+
'over both. Unlike the reserved `align`, which places the whole box ' +
|
|
29
|
+
'within the column, `text` never moves the box. An invalid value is ' +
|
|
30
|
+
'ignored as if absent; nothing errors.',
|
|
31
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markii/stdlib",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Neutral, framework-agnostic standard component contracts for Mark (.mk.md) — the kind/attribute-schema seam every renderer (e.g. @markii/react) implements against. No React, zero dependencies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"markdown",
|