@linemap/core 0.1.0 → 0.2.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 CHANGED
@@ -15,10 +15,11 @@ const svg = render(layout(parseFlow(dotText)), { theme: 'dark' });
15
15
  - `parseFlow(text)` reads a linemap DOT file into a model; errors are thrown with one-line messages.
16
16
  - `layout(model, { hiddenLines, through, fixed })` places, routes and bundles it. Call it once
17
17
  per parsed model.
18
- - `render(model, { theme, css })` returns the SVG. Themes: `light`, `dark`, `minimal`, `neon`, `neond`.
18
+ - `render(model, { theme, css })` returns the SVG. Themes: `minimal` (default),
19
+ `light`, `dark`, `neon`, `neond`, each also as `-fancy` (shadows, glows, moving arrows; costlier).
19
20
  - `positions(model)` gives the computed positions of unpinned nodes, ready to pin with `pos`.
20
21
 
21
- The command line is [`linemap`](https://www.npmjs.com/package/linemap): `npx linemap flow.dot out.svg`.
22
+ The command line is [`@linemap/cli`](https://www.npmjs.com/package/@linemap/cli): `npx @linemap/cli flow.dot out.svg`.
22
23
  The DOT format, themes and the studio are described in the
23
24
  [project README](https://github.com/mergezalot/linemap#readme).
24
25
 
package/index.mjs CHANGED
@@ -6,9 +6,9 @@ import { route } from './src/route.mjs';
6
6
  import { bundle, markColor } from './src/bundle.mjs';
7
7
  import { inside } from './src/inside.mjs';
8
8
  import { render } from './src/render.mjs';
9
- import { THEMES, THEME_NAMES, PALETTE, themeCss, paintLines } from './src/theme.mjs';
9
+ import { THEMES, THEME_NAMES, DEFAULT_THEME, PALETTE, themeCss, paintLines } from './src/theme.mjs';
10
10
 
11
- export { parseFlow, crowding, render, canThrough, STYLE, markColor, THEMES, THEME_NAMES, PALETTE, themeCss, paintLines };
11
+ export { parseFlow, crowding, render, canThrough, STYLE, markColor, THEMES, THEME_NAMES, DEFAULT_THEME, PALETTE, themeCss, paintLines };
12
12
 
13
13
  // Every stage between parsing and rendering, in order. Mutates and returns the model.
14
14
  // Route, bundle and inside do not move items, so `crowding` gives the same answer after this.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linemap/core",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "DOT text -> model -> transit-map style SVG. No I/O, runs in node and the browser.",
5
5
  "keywords": [
6
6
  "flowchart",
package/src/render.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import { STYLE, groupRects, textWidth, edgeLabelSize } from './model.mjs';
3
3
  import { markColor } from './bundle.mjs';
4
4
  import { f } from './geom.mjs';
5
- import { getTheme, themeCss, accentStyle, shadowFilters, paintLines, tabText } from './theme.mjs';
5
+ import { getTheme, DEFAULT_THEME, themeCss, accentStyle, shadowFilters, paintLines, tabText } from './theme.mjs';
6
6
 
7
7
  const esc = (s) => String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
8
8
  // For attribute values: also keep newlines and tabs, which a parser would turn into spaces.
@@ -165,13 +165,13 @@ function legend(model, box, ctx = FLAT) {
165
165
 
166
166
  // Options:
167
167
  // legend false leaves out the legend and the room for it
168
- // theme a theme name (theme.mjs); default: the DOT file's `theme`, else light
168
+ // theme a theme name (theme.mjs); default: the DOT file's `theme`, else minimal
169
169
  // css more CSS, after the theme's: restyle any lm-* class
170
170
  // Elements carry data-* attributes (line ids, labels, shapes) for scripts; they change nothing drawn.
171
171
  export function render(model, { legend: withLegend = true, theme, css = '' } = {}) {
172
172
  // the CSS goes inside <style>, so it must not be able to end that element
173
173
  if (/<\/style/i.test(css)) throw new Error('css: must not contain "</style"');
174
- const themeName = theme ?? model.theme ?? 'light';
174
+ const themeName = theme ?? model.theme ?? DEFAULT_THEME;
175
175
  const T = getTheme(themeName);
176
176
  paintLines(model.lines, T);
177
177
  const fx = shadowFilters(T, themeName);
package/src/theme.mjs CHANGED
@@ -51,7 +51,7 @@ const SOFT = (color, k = 1) => ({
51
51
  group: [{ dy: 2, blur: 8, color, opacity: 0.05 * k }],
52
52
  small: [{ dy: 1, blur: 2, color, opacity: 0.1 * k }],
53
53
  });
54
- export const THEMES = {
54
+ const FANCY = {
55
55
  light: {
56
56
  label: 'Light',
57
57
  font: SANS,
@@ -161,9 +161,36 @@ export const THEMES = {
161
161
  },
162
162
  },
163
163
  };
164
+
165
+ // The plain themes leave out what costs the most to draw: the shadows and glows done with SVG blur
166
+ // filters (redrawn on every pan and zoom) and the travelling arrows (redrawn every frame, for as
167
+ // long as the map is on screen). The `-fancy` themes keep them. `edits` replaces parts of the
168
+ // fancy theme, for themes that lean on their shadows to set boxes apart.
169
+ const plain = (t, edits = {}) => {
170
+ const { shadow, line, ...rest } = t;
171
+ const { flow, ...still } = line ?? {};
172
+ return { ...rest, ...(Object.keys(still).length ? { line: still } : {}), ...edits };
173
+ };
174
+ const M = FANCY.minimal;
175
+ export const THEMES = {
176
+ // the default: minimal without its shadows, so its white cards get a faint outline instead
177
+ minimal: plain(M, {
178
+ node: { ...M.node, stroke: '#d5dbe3', width: 1.25 },
179
+ note: { ...M.note, stroke: '#e1e6ec' },
180
+ edgeLabel: { ...M.edgeLabel, stroke: '#d5dbe3' },
181
+ legend: { ...M.legend, stroke: '#d5dbe3' },
182
+ }),
183
+ light: plain(FANCY.light),
184
+ dark: plain(FANCY.dark),
185
+ neon: plain(FANCY.neon),
186
+ neond: plain(FANCY.neond),
187
+ ...Object.fromEntries(['minimal', 'light', 'dark', 'neon', 'neond'].map((n) =>
188
+ [`${n}-fancy`, { ...FANCY[n], label: `${FANCY[n].label} fancy` }])),
189
+ };
164
190
  export const THEME_NAMES = Object.keys(THEMES);
191
+ export const DEFAULT_THEME = 'minimal';
165
192
 
166
- export function getTheme(name = 'light') {
193
+ export function getTheme(name = DEFAULT_THEME) {
167
194
  const t = THEMES[name];
168
195
  if (!t) throw new Error(`unknown theme "${name}" (known: ${THEME_NAMES.join(', ')})`);
169
196
  return t;