@terra-symposium/docs 0.1.73 → 0.1.75

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.
Files changed (37) hide show
  1. package/README.md +1 -1
  2. package/bin/terra-docs.mjs +151 -115
  3. package/lib-dist/components/StaticWorkspace.d.ts.map +1 -1
  4. package/lib-dist/components/StaticWorkspace.js +4 -4
  5. package/lib-dist/components/StaticWorkspace.js.map +1 -1
  6. package/lib-dist/components/terra/Workspace.d.ts.map +1 -1
  7. package/lib-dist/components/terra/Workspace.js +1 -1
  8. package/lib-dist/components/terra/Workspace.js.map +1 -1
  9. package/lib-dist/components/terra/pages/docs/_editable.d.ts +2 -1
  10. package/lib-dist/components/terra/pages/docs/_editable.d.ts.map +1 -1
  11. package/lib-dist/components/terra/pages/docs/_editable.js +2 -2
  12. package/lib-dist/components/terra/pages/docs/_editable.js.map +1 -1
  13. package/lib-dist/components/terra/pages/docs/_main.d.ts +2 -1
  14. package/lib-dist/components/terra/pages/docs/_main.d.ts.map +1 -1
  15. package/lib-dist/components/terra/pages/docs/_main.js +5 -5
  16. package/lib-dist/components/terra/pages/docs/_main.js.map +1 -1
  17. package/lib-dist/components/terra/pages/docs/_sidebar.d.ts.map +1 -1
  18. package/lib-dist/components/terra/pages/docs/_sidebar.js +5 -2
  19. package/lib-dist/components/terra/pages/docs/_sidebar.js.map +1 -1
  20. package/lib-dist/components/terra/pages/docs/_toolbar.d.ts.map +1 -1
  21. package/lib-dist/components/terra/pages/docs/_toolbar.js +1 -4
  22. package/lib-dist/components/terra/pages/docs/_toolbar.js.map +1 -1
  23. package/lib-dist/components/terra/ui.d.ts +3 -1
  24. package/lib-dist/components/terra/ui.d.ts.map +1 -1
  25. package/lib-dist/components/terra/ui.js +11 -3
  26. package/lib-dist/components/terra/ui.js.map +1 -1
  27. package/lib-dist/lib/host.d.ts +2 -0
  28. package/lib-dist/lib/host.d.ts.map +1 -1
  29. package/lib-dist/lib/workspace-types.d.ts.map +1 -1
  30. package/lib-dist/style.css +1 -1
  31. package/package.json +2 -1
  32. package/site/astro.config.mjs +45 -43
  33. package/site/base-path-remark-plugin.mjs +30 -23
  34. package/site/docs-content-plugin.mjs +68 -57
  35. package/site/src/components/DocsSiteSearch.tsx +106 -91
  36. package/site/src/lib/catalog.ts +110 -96
  37. package/site/src/styles/search.css +114 -43
@@ -1,151 +1,165 @@
1
1
  /// <reference types="vite/client" />
2
2
 
3
3
  import type { DocsNavNode } from '../../../src/components/navigation.js';
4
+ import { getHue } from '@terra-symposium/styling';
4
5
 
5
6
  type SidebarFrontmatter = {
6
- label?: string;
7
- order?: number;
8
- hidden?: boolean;
7
+ label?: string;
8
+ order?: number;
9
+ hidden?: boolean;
9
10
  };
10
11
 
11
12
  type DocsFrontmatter = {
12
- title?: string;
13
- description?: string;
14
- hue?: number | null;
15
- label?: string;
16
- order?: number;
17
- hidden?: boolean;
18
- visibility?: 'visible' | 'hidden';
19
- sidebar?: SidebarFrontmatter;
13
+ title?: string;
14
+ description?: string;
15
+ hue?: number | null;
16
+ label?: string;
17
+ order?: number;
18
+ hidden?: boolean;
19
+ visibility?: 'visible' | 'hidden';
20
+ sidebar?: SidebarFrontmatter;
20
21
  };
21
22
 
22
23
  type ContentModule = {
23
- Content?: unknown;
24
- default?: unknown;
25
- frontmatter?: DocsFrontmatter;
24
+ Content?: unknown;
25
+ default?: unknown;
26
+ frontmatter?: DocsFrontmatter;
26
27
  };
27
28
 
28
29
  export type SitePage = {
29
- file: string;
30
- slug: string;
31
- title: string;
32
- sidebarLabel?: string;
33
- description: string;
34
- hue?: number | null;
35
- hidden: boolean;
36
- order: number;
37
- content: unknown;
38
- markdown: string;
30
+ file: string;
31
+ slug: string;
32
+ title: string;
33
+ sidebarLabel?: string;
34
+ description: string;
35
+ hue?: number | null;
36
+ hidden: boolean;
37
+ order: number;
38
+ content: unknown;
39
+ markdown: string;
39
40
  };
40
41
 
41
42
  const modules = import.meta.glob<ContentModule>('/docs/**/*.{md,mdx}', { eager: true });
42
43
  const sources = import.meta.glob<string>('/docs/**/*.{md,mdx}', {
43
- query: '?raw',
44
- import: 'default',
45
- eager: true,
44
+ query: '?raw',
45
+ import: 'default',
46
+ eager: true,
46
47
  });
47
48
  const base = import.meta.env.BASE_URL;
48
49
 
49
50
  function titleFromSource(source: string, slug: string): string {
50
- const body = source.replace(/^---\s*\n[\s\S]*?\n---\s*\n/, '');
51
- const heading = /^#\s+(.+?)\s*#*\s*$/m.exec(body)?.[1]?.trim();
52
- if (heading) return heading;
53
- const name = slug.split('/').at(-1) || 'Overview';
54
- return name.replace(/[-_]+/g, ' ').replace(/\b\p{L}/gu, (letter) => letter.toUpperCase());
51
+ const body = source.replace(/^---\s*\n[\s\S]*?\n---\s*\n/, '');
52
+ const heading = /^#\s+(.+?)\s*#*\s*$/m.exec(body)?.[1]?.trim();
53
+ if (heading) return heading;
54
+ const name = slug.split('/').at(-1) || 'Overview';
55
+ return name.replace(/[-_]+/g, ' ').replace(/\b\p{L}/gu, (letter) => letter.toUpperCase());
55
56
  }
56
57
 
57
58
  function routeForFile(file: string): string {
58
- const relative = file.replace(/^\/?docs\//, '').replace(/\.(?:md|mdx)$/i, '');
59
- return relative.replace(/(?:^|\/)index$/i, '').replace(/^\/+|\/+$/g, '');
59
+ const relative = file.replace(/^\/?docs\//, '').replace(/\.(?:md|mdx)$/i, '');
60
+ return relative.replace(/(?:^|\/)index$/i, '').replace(/^\/+|\/+$/g, '');
60
61
  }
61
62
 
62
63
  const routes = new Map<string, string>();
63
64
  export const sitePages: SitePage[] = Object.entries(modules)
64
- .map(([file, module]) => {
65
- const slug = routeForFile(file);
66
- const previous = routes.get(slug);
67
- if (previous) {
68
- throw new Error(`Duplicate Docs route "${slug || '/'}": ${previous} and ${file}`);
69
- }
70
- routes.set(slug, file);
71
- const markdown = sources[file] ?? '';
72
- const frontmatter = module.frontmatter ?? {};
73
- return {
74
- file,
75
- slug,
76
- title: frontmatter.title ?? titleFromSource(markdown, slug),
77
- ...((frontmatter.sidebar?.label ?? frontmatter.label) ? { sidebarLabel: frontmatter.sidebar?.label ?? frontmatter.label } : {}),
78
- description: frontmatter.description ?? '',
79
- ...(frontmatter.hue !== undefined ? { hue: frontmatter.hue } : {}),
80
- hidden: frontmatter.sidebar?.hidden ?? frontmatter.hidden ?? frontmatter.visibility === 'hidden',
81
- order: frontmatter.sidebar?.order ?? frontmatter.order ?? Number.MAX_SAFE_INTEGER,
82
- content: module.Content ?? module.default,
83
- markdown: markdown.replace(/^---\s*\n[\s\S]*?\n---\s*\n/, ''),
84
- };
85
- })
86
- .sort((left, right) => left.order - right.order || left.file.localeCompare(right.file));
65
+ .map(([file, module]) => {
66
+ const slug = routeForFile(file);
67
+ const previous = routes.get(slug);
68
+ if (previous) {
69
+ throw new Error(`Duplicate Docs route "${slug || '/'}": ${previous} and ${file}`);
70
+ }
71
+ routes.set(slug, file);
72
+ const markdown = sources[file] ?? '';
73
+ const frontmatter = module.frontmatter ?? {};
74
+ return {
75
+ file,
76
+ slug,
77
+ title: frontmatter.title ?? titleFromSource(markdown, slug),
78
+ ...((frontmatter.sidebar?.label ?? frontmatter.label)
79
+ ? { sidebarLabel: frontmatter.sidebar?.label ?? frontmatter.label }
80
+ : {}),
81
+ description: frontmatter.description ?? '',
82
+ ...(frontmatter.hue !== undefined ? { hue: frontmatter.hue } : {}),
83
+ hidden:
84
+ frontmatter.sidebar?.hidden ?? frontmatter.hidden ?? frontmatter.visibility === 'hidden',
85
+ order: frontmatter.sidebar?.order ?? frontmatter.order ?? Number.MAX_SAFE_INTEGER,
86
+ content: module.Content ?? module.default,
87
+ markdown: markdown.replace(/^---\s*\n[\s\S]*?\n---\s*\n/, ''),
88
+ };
89
+ })
90
+ .sort((left, right) => left.order - right.order || left.file.localeCompare(right.file));
87
91
 
88
92
  if (sitePages.length === 0) {
89
- throw new Error('No Markdown files found in docs/. Add docs/index.md to start a Terra Docs site.');
93
+ throw new Error(
94
+ 'No Markdown files found in docs/. Add docs/index.md to start a Terra Docs site.',
95
+ );
90
96
  }
91
97
 
92
98
  type MutableNode = Omit<DocsNavNode, 'children'> & { children: Map<string, MutableNode> };
93
99
  const rootNodes = new Map<string, MutableNode>();
94
100
 
95
101
  function label(value: string): string {
96
- return value.replace(/[-_]+/g, ' ').replace(/\b\p{L}/gu, (letter) => letter.toUpperCase());
102
+ return value.replace(/[-_]+/g, ' ').replace(/\b\p{L}/gu, (letter) => letter.toUpperCase());
97
103
  }
98
104
 
99
105
  for (const page of sitePages.filter((item) => !item.hidden && item.slug !== '404')) {
100
- const segments = page.slug.split('/').filter(Boolean);
101
- let currentNodes = rootNodes;
102
- let current: MutableNode | undefined;
103
- let prefix = '';
104
- if (segments.length === 0) {
105
- const overview = currentNodes.get('overview') ?? {
106
- id: 'overview', title: 'Overview', children: new Map(),
107
- };
108
- if (!currentNodes.has('overview')) currentNodes.set('overview', overview);
109
- Object.assign(overview, pageMetadata(page, pageHref('', base)));
110
- continue;
111
- }
112
- for (const segment of segments) {
113
- prefix = prefix ? `${prefix}/${segment}` : segment;
114
- let node = currentNodes.get(segment);
115
- if (!node) {
116
- node = { id: prefix, title: label(segment), children: new Map() };
117
- currentNodes.set(segment, node);
118
- }
119
- current = node;
120
- currentNodes = node.children;
121
- }
122
- if (current) Object.assign(current, pageMetadata(page, pageHref(page.slug, base)));
106
+ const segments = page.slug.split('/').filter(Boolean);
107
+ let currentNodes = rootNodes;
108
+ let current: MutableNode | undefined;
109
+ let prefix = '';
110
+ if (segments.length === 0) {
111
+ const overview = currentNodes.get('overview') ?? {
112
+ id: 'overview',
113
+ title: 'Overview',
114
+ hue: getHue('Overview'),
115
+ children: new Map(),
116
+ };
117
+ if (!currentNodes.has('overview')) currentNodes.set('overview', overview);
118
+ Object.assign(overview, pageMetadata(page, pageHref('', base)));
119
+ continue;
120
+ }
121
+ for (const segment of segments) {
122
+ prefix = prefix ? `${prefix}/${segment}` : segment;
123
+ let node = currentNodes.get(segment);
124
+ if (!node) {
125
+ node = {
126
+ id: prefix,
127
+ title: label(segment),
128
+ ...(prefix === segment ? { hue: getHue(label(segment)) } : {}),
129
+ children: new Map(),
130
+ };
131
+ currentNodes.set(segment, node);
132
+ }
133
+ current = node;
134
+ currentNodes = node.children;
135
+ }
136
+ if (current) Object.assign(current, pageMetadata(page, pageHref(page.slug, base)));
123
137
  }
124
138
 
125
139
  function pageMetadata(page: SitePage, href: string): Partial<MutableNode> {
126
- return {
127
- id: page.slug || 'index',
128
- title: page.sidebarLabel ?? page.title,
129
- href,
130
- ...(page.description ? { description: page.description } : {}),
131
- ...(page.hue !== undefined ? { hue: page.hue } : {}),
132
- };
140
+ return {
141
+ id: page.slug || 'index',
142
+ title: page.sidebarLabel ?? page.title,
143
+ href,
144
+ ...(page.description ? { description: page.description } : {}),
145
+ ...(page.hue !== undefined ? { hue: page.hue } : {}),
146
+ };
133
147
  }
134
148
 
135
149
  function materialize(nodes: Map<string, MutableNode>): DocsNavNode[] {
136
- return [...nodes.values()].map(({ children, ...node }) => ({
137
- ...node,
138
- ...(children.size ? { children: materialize(children) } : {}),
139
- }));
150
+ return [...nodes.values()].map(({ children, ...node }) => ({
151
+ ...node,
152
+ ...(children.size ? { children: materialize(children) } : {}),
153
+ }));
140
154
  }
141
155
 
142
156
  export const siteNavigation = materialize(rootNodes);
143
157
 
144
158
  export function pageHref(slug: string, base = '/'): string {
145
- const prefix = base === '/' ? '' : `/${base.replace(/^\/+|\/+$/g, '')}`;
146
- return slug ? `${prefix}/${slug}/` : `${prefix}/`;
159
+ const prefix = base === '/' ? '' : `/${base.replace(/^\/+|\/+$/g, '')}`;
160
+ return slug ? `${prefix}/${slug}/` : `${prefix}/`;
147
161
  }
148
162
 
149
163
  export function pageForSlug(slug: string): SitePage | undefined {
150
- return sitePages.find((page) => page.slug === slug);
164
+ return sitePages.find((page) => page.slug === slug);
151
165
  }
@@ -1,56 +1,127 @@
1
1
  .terra-docs-search {
2
- position: fixed;
3
- top: 0.65rem;
4
- right: 1rem;
5
- z-index: 80;
6
- font: inherit;
2
+ position: fixed;
3
+ top: 0.65rem;
4
+ right: 1rem;
5
+ z-index: 80;
6
+ font: inherit;
7
7
  }
8
8
 
9
9
  .terra-docs-search-trigger {
10
- display: flex;
11
- align-items: center;
12
- gap: 0.55rem;
13
- min-height: 2.4rem;
14
- padding: 0.35rem 0.55rem;
15
- border: 1px solid rgb(var(--primary-6));
16
- border-radius: 0.45rem;
17
- background: rgb(var(--primary-2));
18
- color: rgb(var(--primary-11));
19
- font-size: 0.85rem;
20
- cursor: pointer;
10
+ display: flex;
11
+ align-items: center;
12
+ gap: 0.55rem;
13
+ min-height: 2.4rem;
14
+ padding: 0.35rem 0.55rem;
15
+ border: 1px solid rgb(var(--primary-6));
16
+ border-radius: 0.45rem;
17
+ background: rgb(var(--primary-2));
18
+ color: rgb(var(--primary-11));
19
+ font-size: 0.85rem;
20
+ cursor: pointer;
21
21
  }
22
22
 
23
- .terra-docs-search-trigger:hover { background: rgb(var(--primary-3)); }
24
- .terra-docs-search-trigger > span:first-child { font-size: 1.25rem; line-height: 1; }
25
- .terra-docs-search-trigger kbd { padding: 0.05rem 0.25rem; border: 1px solid rgb(var(--primary-6)); border-radius: 0.25rem; font-size: 0.7rem; }
23
+ .terra-docs-search-trigger:hover {
24
+ background: rgb(var(--primary-3));
25
+ }
26
+ .terra-docs-search-trigger > span:first-child {
27
+ font-size: 1.25rem;
28
+ line-height: 1;
29
+ }
30
+ .terra-docs-search-trigger kbd {
31
+ padding: 0.05rem 0.25rem;
32
+ border: 1px solid rgb(var(--primary-6));
33
+ border-radius: 0.25rem;
34
+ font-size: 0.7rem;
35
+ }
26
36
 
27
37
  .terra-docs-search-dialog {
28
- width: min(42rem, calc(100vw - 2rem));
29
- max-width: none;
30
- max-height: min(75vh, 42rem);
31
- padding: 0;
32
- border: 1px solid rgb(var(--primary-7));
33
- border-radius: 0.75rem;
34
- background: rgb(var(--primary-2));
35
- color: rgb(var(--primary-12));
36
- box-shadow: 0 1.5rem 5rem rgb(0 0 0 / 0.35);
38
+ width: min(42rem, calc(100vw - 2rem));
39
+ max-width: none;
40
+ max-height: min(75vh, 42rem);
41
+ padding: 0;
42
+ border: 1px solid rgb(var(--primary-7));
43
+ border-radius: 0.75rem;
44
+ background: rgb(var(--primary-2));
45
+ color: rgb(var(--primary-12));
46
+ box-shadow: 0 1.5rem 5rem rgb(0 0 0 / 0.35);
37
47
  }
38
48
 
39
- .terra-docs-search-dialog::backdrop { background: rgb(0 0 0 / 0.58); backdrop-filter: blur(2px); }
40
- .terra-docs-search-panel { overflow: hidden; }
41
- .terra-docs-search-input-row { display: flex; align-items: center; gap: 0.75rem; padding: 1rem; border-bottom: 1px solid rgb(var(--primary-5)); }
42
- .terra-docs-search-input-row > span { font-size: 1.3rem; }
43
- .terra-docs-search-input-row input { min-width: 0; flex: 1; border: 0; outline: 0; background: transparent; color: inherit; font: inherit; }
44
- .terra-docs-search-input-row button { border: 1px solid rgb(var(--primary-6)); border-radius: 0.3rem; background: transparent; color: inherit; font-size: 0.7rem; cursor: pointer; }
45
- .terra-docs-search-results { max-height: calc(75vh - 4rem); overflow: auto; padding: 0.5rem; }
46
- .terra-docs-search-results > p { padding: 1rem; color: rgb(var(--primary-10)); font-size: 0.9rem; }
47
- .terra-docs-search-results > a { display: grid; gap: 0.25rem; padding: 0.75rem; border-radius: 0.45rem; color: inherit; text-decoration: none; }
48
- .terra-docs-search-results > a:hover, .terra-docs-search-results > a:focus { outline: 0; background: rgb(var(--primary-4)); }
49
- .terra-docs-search-results > a span, .terra-docs-search-results > a small { color: rgb(var(--primary-10)); }
50
- .terra-docs-search-results > a small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
49
+ .terra-docs-search-dialog::backdrop {
50
+ background: rgb(0 0 0 / 0.58);
51
+ backdrop-filter: blur(2px);
52
+ }
53
+ .terra-docs-search-panel {
54
+ overflow: hidden;
55
+ }
56
+ .terra-docs-search-input-row {
57
+ display: flex;
58
+ align-items: center;
59
+ gap: 0.75rem;
60
+ padding: 1rem;
61
+ border-bottom: 1px solid rgb(var(--primary-5));
62
+ }
63
+ .terra-docs-search-input-row > span {
64
+ font-size: 1.3rem;
65
+ }
66
+ .terra-docs-search-input-row input {
67
+ min-width: 0;
68
+ flex: 1;
69
+ border: 0;
70
+ outline: 0;
71
+ background: transparent;
72
+ color: inherit;
73
+ font: inherit;
74
+ }
75
+ .terra-docs-search-input-row button {
76
+ border: 1px solid rgb(var(--primary-6));
77
+ border-radius: 0.3rem;
78
+ background: transparent;
79
+ color: inherit;
80
+ font-size: 0.7rem;
81
+ cursor: pointer;
82
+ }
83
+ .terra-docs-search-results {
84
+ max-height: calc(75vh - 4rem);
85
+ overflow: auto;
86
+ padding: 0.5rem;
87
+ }
88
+ .terra-docs-search-results > p {
89
+ padding: 1rem;
90
+ color: rgb(var(--primary-10));
91
+ font-size: 0.9rem;
92
+ }
93
+ .terra-docs-search-results > a {
94
+ display: grid;
95
+ gap: 0.25rem;
96
+ padding: 0.75rem;
97
+ border-radius: 0.45rem;
98
+ color: inherit;
99
+ text-decoration: none;
100
+ }
101
+ .terra-docs-search-results > a:hover,
102
+ .terra-docs-search-results > a:focus {
103
+ outline: 0;
104
+ background: rgb(var(--primary-4));
105
+ }
106
+ .terra-docs-search-results > a span,
107
+ .terra-docs-search-results > a small {
108
+ color: rgb(var(--primary-10));
109
+ }
110
+ .terra-docs-search-results > a small {
111
+ overflow: hidden;
112
+ text-overflow: ellipsis;
113
+ white-space: nowrap;
114
+ }
51
115
 
52
116
  @media (max-width: 640px) {
53
- .terra-docs-search { top: 0.5rem; right: 0.5rem; }
54
- .terra-docs-search-trigger { min-height: 2.1rem; }
55
- .terra-docs-search-trigger kbd { display: none; }
117
+ .terra-docs-search {
118
+ top: 0.5rem;
119
+ right: 0.5rem;
120
+ }
121
+ .terra-docs-search-trigger {
122
+ min-height: 2.1rem;
123
+ }
124
+ .terra-docs-search-trigger kbd {
125
+ display: none;
126
+ }
56
127
  }