@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.
@@ -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 five layout-wrapper container contracts —
18
- * `center`/`right`/`wide`/`narrow`/`full` — which are otherwise identical in
19
- * shape (`kind: 'container'`, no attributes) and differ only in `name` and
20
- * the preset-specific half of `description`. A tiny helper rather than five
21
- * hand-copied literals, since a typo in one copy's `kind`/`attributes` would
22
- * otherwise be easy to miss across five near-duplicate blocks.
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) and about composing with
27
- * a nested wrapper is appended identically for all five.
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} Takes no attributes — docs/format.md gives these five ` +
35
- 'wrapper names a closed, attribute-free form; unlike a `width`/`align` ' +
36
- 'attribute on a directive, a wrapper also reaches plain markdown a ' +
37
- 'directive attribute mechanism structurally cannot (a GFM table or a ' +
38
- 'bare image has no `{...}` to write `width=`/`align=` into). Nesting a ' +
39
- 'width wrapper (`wide`/`narrow`/`full`) inside an alignment wrapper ' +
40
- '(`center`/`right`) composes, e.g. `::::center :::narrow ... ::: ::::` ' +
41
- '(the outer fence needs more colons than the inner one).',
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. Takes no attributes and adds no look of its own; 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`.",
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{align=center}`.'),
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';
@@ -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.8.1",
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",