rapier-markdown-kit 1.1.2 → 1.1.4

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,7 +1,8 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
 
3
3
  // `rotate`: degrees in (-180, 180], one decimal, omitted when 0; never written for a Rapier drawing (its turn lives in its SVG).
4
- export const fields = new Set(['align', 'width', 'wrap', 'x', 'y', 'rotate']);
4
+ // `opacity`: a picture's fade, a whole percent from 5 to 100, omitted at 100; the picture's bytes never change.
5
+ export const fields = new Set(['align', 'width', 'wrap', 'x', 'y', 'rotate', 'opacity']);
5
6
  export const alignments = new Set(['left', 'center', 'right', 'justify']);
6
7
  // `behind`/`front`: out of flow; the paragraph lays out as though the picture were absent.
7
8
  export const wraps = new Set(['around', 'box', 'behind', 'front']);
@@ -20,6 +21,7 @@ export function validLayout(value) {
20
21
  (!has(value, 'x') || percent(value.x) && (has(value, 'wrap') || has(value, 'width'))) &&
21
22
  (!has(value, 'y') || typeof value.y === 'number' && Number.isFinite(value.y) && value.y >= -50 && has(value, 'wrap')) &&
22
23
  (!has(value, 'rotate') || oneDecimalDegrees(value.rotate)) &&
24
+ (!has(value, 'opacity') || Number.isInteger(value.opacity) && value.opacity >= 5 && value.opacity <= 100) &&
23
25
  !(has(value, 'align') && (has(value, 'wrap') || has(value, 'x')));
24
26
  }
25
27
 
@@ -51,6 +53,9 @@ export function parseLayout(comment) {
51
53
  const magnitude = Number(number[2] + (number[3] ? '.' + number[3] : ''));
52
54
  if (number[1] && magnitude === 0) return null;
53
55
  value.rotate = number[1] ? -magnitude : magnitude;
56
+ } else if (key === 'opacity') {
57
+ if (!/^[1-9]\d{0,2}%$/.test(raw)) return null;
58
+ value.opacity = Number(raw.slice(0, -1));
54
59
  } else value[key] = raw;
55
60
  }
56
61
  return validLayout(value) ? value : null;
@@ -64,12 +69,18 @@ export function decodeLayoutAttribute(value) {
64
69
 
65
70
  export const parseLayoutAttribute = value => parseLayout(decodeLayoutAttribute(value));
66
71
 
72
+ // The picture's own CSS: its normal-flow width and x, and its fade.
67
73
  export function imageStyle(value) {
68
- if (!validLayout(value) || value.width == null) return '';
69
- const width = value.width;
70
- const left = value.x == null ? '' : ';display:block;margin-left:' +
71
- decimal(Number(Math.max(0, Math.min(100 - width, value.x - width / 2)).toFixed(6))) + '%;margin-right:0';
72
- return 'width:' + decimal(width) + '%;height:auto' + left;
74
+ if (!validLayout(value)) return '';
75
+ const parts = [];
76
+ if (value.width != null) {
77
+ const width = value.width;
78
+ const left = value.x == null ? '' : ';display:block;margin-left:' +
79
+ decimal(Number(Math.max(0, Math.min(100 - width, value.x - width / 2)).toFixed(6))) + '%;margin-right:0';
80
+ parts.push('width:' + decimal(width) + '%;height:auto' + left);
81
+ }
82
+ if (value.opacity != null && value.opacity < 100) parts.push('opacity:' + decimal(value.opacity / 100));
83
+ return parts.join(';');
73
84
  }
74
85
 
75
86
  // The one wrap-owner rule (layout/browser.js, layout/interchange.js, editor/share.js): prose after, else before, skipping pictures,
@@ -109,8 +120,9 @@ export function formatLayout(value) {
109
120
  if (!validLayout(value)) throw new TypeError('invalid_markdown_layout');
110
121
  const pairs = [];
111
122
  for (const key of fields) {
112
- if (has(value, key) && !(key === 'y' && value.y === 0) && !(key === 'rotate' && value.rotate === 0)) pairs.push(key + '=' +
113
- (key === 'width' || key === 'x' ? decimal(value[key]) + '%' : key === 'y' ? decimal(value.y) + 'em' :
123
+ if (has(value, key) && !(key === 'y' && value.y === 0) && !(key === 'rotate' && value.rotate === 0) &&
124
+ !(key === 'opacity' && value.opacity === 100)) pairs.push(key + '=' +
125
+ (key === 'width' || key === 'x' || key === 'opacity' ? decimal(value[key]) + '%' : key === 'y' ? decimal(value.y) + 'em' :
114
126
  key === 'rotate' ? decimal(value.rotate) + 'deg' : value[key]));
115
127
  }
116
128
  return pairs.length ? '<!--md-layout:v1 ' + pairs.join(' ') + '-->' : '';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rapier-markdown-kit",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "Read, write and style Self-contained Markdown: the universal stylesheet, picture layout, text marks, picture appendix, line planner and Will/1 markers. MIT, no dependencies.",
5
5
  "author": "Jack Skipworth",
6
6
  "license": "MIT",
package/style.css CHANGED
@@ -49,22 +49,22 @@
49
49
  --md-color-dark:var(--md-color);
50
50
  --md-highlight-color:var(--md-color-accent);
51
51
  --md-image-width:100%;
52
+ --md-drawing-width:0px;
52
53
  --md-task-box:clamp(14px,.92em,24px);
53
54
  --md-jump-gap:.9rem;
54
55
  --md-jump-marker-inline-start:-1.18rem;
55
56
  --md-jump-marker-center:1em;
56
57
  --md-diagram-ink:light-dark(#121212,#fafafa);
57
- --md-diagram-box:light-dark(#f2f1ef,#1d1d1d);
58
- --md-diagram-decision:light-dark(#d5eeea,#0e302c);
58
+ --md-diagram-box:light-dark(#f0f0f0,#1d1d1d);
59
59
  --md-diagram-accent:light-dark(#12a594,#12a594);
60
60
  --md-diagram-on-accent:light-dark(#000000,#000000);
61
- --md-diagram-step:light-dark(#0e8a7c,#12a594);
61
+ --md-diagram-step:light-dark(#666666,#999999);
62
62
  --md-diagram-stroke:2px;
63
63
  --md-diagram-hairline:1px;
64
64
  --md-diagram-caption-size:10px;
65
65
  --md-diagram-caption-track:.12em;
66
66
  --md-diagram-title-track:.16em;
67
- --md-diagram-step-scale:2.5;
67
+ --md-diagram-step-scale:.8;
68
68
  --md-diagram-node-fill:var(--md-diagram-box);
69
69
  --md-diagram-inner-line:color-mix(in srgb,var(--md-color-text) 12%,var(--md-color-bg));
70
70
  --md-diagram-node-line:color-mix(in srgb,var(--md-color-text) 20%,var(--md-color-bg));
@@ -170,16 +170,15 @@
170
170
  }
171
171
  /* Rapier's diagram look, one for a figure an agent lays out in Draw and for the drawing Mermaid makes from the
172
172
  author's source (Draw writes the same pairs into its SVG; _diagram-cells holds the two copies equal). Swiss
173
- editorial after the mid-century magazines: a box is a flat field of one grey with no outline, the words the page's
174
- own type in its ink; the one accent is meaning only -- the decision is its pale, the outcome (a round node, where a
175
- flow ends) the accent itself under black words. It keeps the corner the source asked for: a stadium, a diamond and
173
+ editorial after the mid-century magazines: nearly monochrome, a box or a decision a flat field of one grey with no
174
+ outline, the words the page's own type in its ink; the one accent is spent sparingly, on meaning only -- the outcome
175
+ (a round node, where a flow ends) under black words. It keeps the corner the source asked for: a stadium, a diamond and
176
176
  a parallelogram are what the author wrote; the roundings Mermaid adds to a plain box, an actor, a note and a
177
177
  cluster are not, and Rapier's boxes are square. An author's own style or classDef fill and stroke stay above all
178
178
  of it (they are materialised inline, and an inline declaration outranks this sheet). */
179
179
  :where(.md-render) svg.rapier-diagram .node :is(rect,circle,ellipse,polygon,path){
180
180
  fill:var(--md-diagram-box)!important;stroke:none!important;
181
181
  }
182
- :where(.md-render) svg.rapier-diagram .node polygon{fill:var(--md-diagram-decision)!important}
183
182
  :where(.md-render) svg.rapier-diagram[aria-roledescription^="flowchart"] .node:has(>circle) :is(circle,path){fill:var(--md-diagram-accent)!important}
184
183
  :where(.md-render) svg.rapier-diagram[aria-roledescription^="flowchart"] .node:has(>circle) :is(text,tspan){fill:var(--md-diagram-on-accent)!important}
185
184
  :where(.md-render) svg.rapier-diagram g.classGroup rect,:where(.md-render) svg.rapier-diagram .actor,:where(.md-render) svg.rapier-diagram .labelBox,:where(.md-render) svg.rapier-diagram .activation0,:where(.md-render) svg.rapier-diagram .activation1,:where(.md-render) svg.rapier-diagram .activation2{
@@ -191,8 +190,8 @@
191
190
  :where(.md-render) svg.rapier-diagram :is(.cluster-label,.cluster .label) :is(text,tspan){
192
191
  font-family:var(--md-font-mono)!important;font-size:var(--md-diagram-caption-size)!important;text-transform:uppercase;letter-spacing:var(--md-diagram-title-track)!important;
193
192
  }
194
- :where(.md-render) svg.rapier-diagram .nodeLabel,:where(.md-render) svg.rapier-diagram .classTitle,:where(.md-render) svg.rapier-diagram text.actor>tspan{font-weight:var(--md-fw-medium)!important}
195
- :where(.md-render) svg.rapier-diagram .node :is(text,tspan){font-weight:var(--md-fw-regular)!important}
193
+ :where(.md-render) svg.rapier-diagram .classTitle,:where(.md-render) svg.rapier-diagram text.actor>tspan{font-weight:var(--md-fw-medium)!important}
194
+ :where(.md-render) svg.rapier-diagram :is(.nodeLabel,.node text,.node tspan){font-weight:var(--md-fw-semibold)!important}
196
195
  :where(.md-render) svg.rapier-diagram rect.basic,:where(.md-render) svg.rapier-diagram rect.title-state,:where(.md-render) svg.rapier-diagram rect.outer,:where(.md-render) svg.rapier-diagram .actor,:where(.md-render) svg.rapier-diagram .note,:where(.md-render) svg.rapier-diagram .labelBox,:where(.md-render) svg.rapier-diagram .cluster rect,:where(.md-render) svg.rapier-diagram .statediagram-cluster rect{rx:0!important;ry:0!important}
197
196
  /* The line between two boxes is mid-ladder and one hairline weight everywhere: it is the road,
198
197
  not the destination. A lifeline and a divider are neither -- they are a box's own rule down
@@ -332,10 +331,12 @@
332
331
  :where(.md-render) svg.rapier-diagram .grid path{stroke:none!important}
333
332
  :where(.md-render) svg.rapier-diagram .grid .tick text{fill:var(--md-diagram-quiet)!important;font-size:var(--md-text-xs)!important}
334
333
  :where(.md-render) svg.rapier-diagram .today{stroke:var(--md-diagram-c6)!important}
335
- /* Paper cannot be scrolled sideways, so on paper a diagram goes back to fitting the page. */
334
+ /* Paper cannot be scrolled sideways, so on paper a diagram, and a wide drawing, go back to fitting the page. */
336
335
  @media print{
337
336
  :where(.md-render) .diagram-block{overflow:visible!important}
338
337
  :where(.md-render) svg.rapier-diagram{width:auto!important;max-width:100%!important}
338
+ .md-render img[data-md-drawing]{min-width:0!important}
339
+ .md-render :has(>img[data-md-drawing],>a>img[data-md-drawing]){overflow:visible!important}
339
340
  }
340
341
  :where(.md-render) .diagram-reason {
341
342
  margin: .4em 0 0;
@@ -704,6 +705,12 @@
704
705
  vertical-align:middle;
705
706
  }
706
707
  .md-render img[data-rapier-image-size]{width:min(var(--md-image-width),100%);height:auto}
708
+ /* A drawing (an SVG picture, as every Draw drawing is) shown at its own size carries that size, and shrinks to the column only
709
+ while its words stay legible: at 12/14 of it, Draw's default words (14 px) are 12 px, the smallest text a phone reads
710
+ (measured on a 390 px phone, the lane drawing-dark-wide). There it stops, and its block scrolls sideways, as a wide diagram
711
+ does; a drawing that fits, or shrinks less than that, is drawn as it always was. */
712
+ .md-render img[data-md-drawing]{min-width:calc(var(--md-drawing-width) * 12 / 14)}
713
+ .md-render :has(>img[data-md-drawing],>a>img[data-md-drawing]){overflow-x:auto}
707
714
  .md-render img:is([data-rapier-asset],[data-rapier-image-url]):not([data-rapier-asset-state="ready"]){background:color-mix(in srgb,var(--md-color-text) 5%,transparent)}
708
715
 
709
716
  .md-render dl{margin:0 0 var(--md-space-4)}