@abreen/tada 1.5.1 → 1.5.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.
Files changed (54) hide show
  1. package/build/globals.ts +1 -1
  2. package/package.json +3 -2
  3. package/src/code/index.ts +5 -4
  4. package/src/index.ts +1 -1
  5. package/src/navigate/index.ts +27 -21
  6. package/src/navigate/lifecycle.ts +1 -1
  7. package/src/navigate/style.scss +2 -2
  8. package/src/search/index.ts +19 -16
  9. package/src/toc/index.ts +1 -1
  10. package/src/top/index.ts +3 -3
  11. package/src/util.ts +7 -6
  12. package/templates/_nav.html +1 -0
  13. package/bin/validators.test.ts +0 -205
  14. package/build/build-manifest.test.ts +0 -369
  15. package/build/code.test.ts +0 -272
  16. package/build/colors.test.ts +0 -66
  17. package/build/globals.test.ts +0 -100
  18. package/build/json-schema.test.ts +0 -57
  19. package/build/log.test.ts +0 -117
  20. package/build/markdown-plugins.test.ts +0 -456
  21. package/build/pagefind.test.ts +0 -192
  22. package/build/pdf-text.test.ts +0 -52
  23. package/build/reachability.test.ts +0 -80
  24. package/build/serve.test.ts +0 -59
  25. package/build/toc-plugin.test.ts +0 -120
  26. package/build/utils/content-files.test.ts +0 -56
  27. package/build/utils/derive-theme.test.ts +0 -111
  28. package/build/utils/file-types.test.ts +0 -79
  29. package/build/utils/front-matter.test.ts +0 -77
  30. package/build/utils/include.test.ts +0 -117
  31. package/build/utils/paths.test.ts +0 -91
  32. package/build/utils/trace-layout.test.ts +0 -570
  33. package/build/utils/trace-svg.test.ts +0 -425
  34. package/build/utils/trace.test.ts +0 -169
  35. package/build/validate-config-links.test.ts +0 -239
  36. package/build/validate-internal-links-plugin.test.ts +0 -134
  37. package/build/watch-reachability-state.test.ts +0 -198
  38. package/fonts/google-sans-code/ttf/GoogleSansCodeVariable-Italic.ttf +0 -0
  39. package/fonts/google-sans-code/ttf/GoogleSansCodeVariable.ttf +0 -0
  40. package/fonts/inter/ttf/InterVariable-Italic.ttf +0 -0
  41. package/src/anchor/index.test.ts +0 -64
  42. package/src/code/index.test.ts +0 -71
  43. package/src/header/index.test.ts +0 -89
  44. package/src/navigate/eligible.test.ts +0 -101
  45. package/src/navigate/index.test.ts +0 -82
  46. package/src/navigate/lifecycle.test.ts +0 -26
  47. package/src/print/index.test.ts +0 -71
  48. package/src/question/index.test.ts +0 -82
  49. package/src/search/index.test.ts +0 -203
  50. package/src/timezone/index.test.ts +0 -400
  51. package/src/toc/index.test.ts +0 -237
  52. package/src/top/index.test.ts +0 -46
  53. package/src/trace/index.test.ts +0 -554
  54. package/src/util.test.ts +0 -135
@@ -1,237 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
- import { JSDOM } from 'jsdom';
3
- import mount, {
4
- getHighlightIndexes,
5
- headingToTableItem,
6
- alertToTableItem,
7
- switchCurrent,
8
- type Heading,
9
- type Alert,
10
- type Dinkus,
11
- } from './index';
12
-
13
- function dom(html: string) {
14
- return new JSDOM(`<body>${html}</body>`);
15
- }
16
-
17
- describe('getHighlightIndexes', () => {
18
- test('maps headings to their own index', () => {
19
- const items: Heading[] = [
20
- { level: '1', id: 'a', innerHtml: 'A' },
21
- { level: '2', id: 'b', innerHtml: 'B' },
22
- ];
23
- expect(getHighlightIndexes(items)).toEqual([0, 1]);
24
- });
25
-
26
- test('maps alerts to the preceding heading index', () => {
27
- const items: (Heading | Alert)[] = [
28
- { level: '1', id: 'a', innerHtml: 'A' },
29
- { type: 'warning', title: 'Watch out' },
30
- { level: '2', id: 'b', innerHtml: 'B' },
31
- ];
32
- expect(getHighlightIndexes(items)).toEqual([0, 0, 2]);
33
- });
34
-
35
- test('alert before any heading gets its own index', () => {
36
- const items: (Heading | Alert)[] = [
37
- { type: 'note', title: 'FYI' },
38
- { level: '1', id: 'a', innerHtml: 'A' },
39
- ];
40
- expect(getHighlightIndexes(items)).toEqual([0, 1]);
41
- });
42
-
43
- test('skips dinkus items entirely', () => {
44
- const items: (Heading | Dinkus)[] = [
45
- { level: '1', id: 'a', innerHtml: 'A' },
46
- { type: 'dinkus' },
47
- { level: '2', id: 'b', innerHtml: 'B' },
48
- ];
49
- expect(getHighlightIndexes(items)).toEqual([0, 1]);
50
- });
51
-
52
- test('returns empty array for empty input', () => {
53
- expect(getHighlightIndexes([])).toEqual([]);
54
- });
55
- });
56
-
57
- describe('headingToTableItem', () => {
58
- test('extracts level and innerHTML from a heading', () => {
59
- const { document } = dom('<h2 id="intro">Introduction</h2>').window;
60
- const el = document.querySelector('h2') as HTMLHeadingElement;
61
- const result = headingToTableItem(el);
62
- expect(result).toEqual({
63
- level: '2',
64
- id: 'intro',
65
- innerHtml: 'Introduction',
66
- });
67
- });
68
-
69
- test('separates subtitle from main text', () => {
70
- const { document } = dom(
71
- '<h3 id="s"><span class="heading-subtitle">v2</span>Setup</h3>',
72
- ).window;
73
- const el = document.querySelector('h3') as HTMLHeadingElement;
74
- const result = headingToTableItem(el);
75
- expect(result.level).toBe('3');
76
- expect(result.id).toBe('s');
77
- expect(result.innerHtml).toContain('Setup');
78
- expect(result.innerHtml).toContain('heading-subtitle');
79
- });
80
-
81
- test('uses innerHTML when no subtitle', () => {
82
- const { document } = dom('<h1 id="top"><em>Bold</em> title</h1>').window;
83
- const el = document.querySelector('h1') as HTMLHeadingElement;
84
- const result = headingToTableItem(el);
85
- expect(result.innerHtml).toBe('<em>Bold</em> title');
86
- });
87
- });
88
-
89
- describe('alertToTableItem', () => {
90
- test('returns warning alert with custom title', () => {
91
- const { document } = dom(
92
- '<div class="alert warning"><span class="title">Danger</span></div>',
93
- ).window;
94
- const el = document.querySelector('.alert') as HTMLElement;
95
- expect(alertToTableItem(el)).toEqual({ type: 'warning', title: 'Danger' });
96
- });
97
-
98
- test('returns note alert with default title', () => {
99
- const { document } = dom('<div class="alert note">Some note</div>').window;
100
- const el = document.querySelector('.alert') as HTMLElement;
101
- expect(alertToTableItem(el)).toEqual({ type: 'note', title: 'Note' });
102
- });
103
-
104
- test('returns default Warning title when no .title element', () => {
105
- const { document } = dom(
106
- '<div class="alert warning">Text only</div>',
107
- ).window;
108
- const el = document.querySelector('.alert') as HTMLElement;
109
- expect(alertToTableItem(el)).toEqual({ type: 'warning', title: 'Warning' });
110
- });
111
-
112
- test('returns null for non-warning/note alert types', () => {
113
- const { document } = dom('<div class="alert info">Some info</div>').window;
114
- const el = document.querySelector('.alert') as HTMLElement;
115
- expect(alertToTableItem(el)).toBeNull();
116
- });
117
- });
118
-
119
- describe('switchCurrent', () => {
120
- test('adds current class to new element', () => {
121
- const { document } = dom('<li>A</li><li>B</li>').window;
122
- const items = document.querySelectorAll('li');
123
- switchCurrent(null, items[0] as HTMLElement);
124
- expect(items[0].classList.contains('current')).toBe(true);
125
- });
126
-
127
- test('removes current from old and adds to new', () => {
128
- const { document } = dom('<li class="current">A</li><li>B</li>').window;
129
- const items = document.querySelectorAll('li');
130
- switchCurrent(items[0] as HTMLElement, items[1] as HTMLElement);
131
- expect(items[0].classList.contains('current')).toBe(false);
132
- expect(items[1].classList.contains('current')).toBe(true);
133
- });
134
- });
135
-
136
- describe('toc mount', () => {
137
- test('returns early when no nav.toc exists', () => {
138
- const win = dom('<div>No toc</div>').window;
139
- const cleanup = mount(win);
140
- expect(cleanup).toBeUndefined();
141
- });
142
-
143
- test('returns early when toc has no links', () => {
144
- const win = dom('<nav class="toc"><ol></ol></nav>').window;
145
- const cleanup = mount(win);
146
- expect(cleanup).toBeUndefined();
147
- });
148
-
149
- describe('code page', () => {
150
- function createCodePage(hash = '') {
151
- const html =
152
- '<nav class="toc"><ol>' +
153
- '<li><a href="#L1">main</a></li>' +
154
- '<li><a href="#L10">helper</a></li>' +
155
- '<li><a href="#L20">util</a></li>' +
156
- '</ol></nav>' +
157
- '<div class="body"></div>';
158
- return new JSDOM(`<body class="code">${html}</body>`, {
159
- url: `http://localhost/${hash}`,
160
- }).window;
161
- }
162
-
163
- test('highlights the matching toc entry for the current hash', () => {
164
- const win = createCodePage('#L10');
165
- mount(win);
166
-
167
- const items = win.document.querySelectorAll('nav.toc ol li');
168
- expect(items[1].classList.contains('current')).toBe(true);
169
- });
170
-
171
- test('highlights nearest entry when hash is between line ranges', () => {
172
- const win = createCodePage('#L15');
173
- mount(win);
174
-
175
- const items = win.document.querySelectorAll('nav.toc ol li');
176
- expect(items[1].classList.contains('current')).toBe(true);
177
- });
178
-
179
- test('parses range hashes like #L5-L10', () => {
180
- const win = createCodePage('#L5-L10');
181
- mount(win);
182
-
183
- const items = win.document.querySelectorAll('nav.toc ol li');
184
- expect(items[0].classList.contains('current')).toBe(true);
185
- });
186
-
187
- test('no current item when hash has no line number', () => {
188
- const win = createCodePage('');
189
- mount(win);
190
-
191
- const current = win.document.querySelector('nav.toc .current');
192
- expect(current).toBeNull();
193
- });
194
-
195
- test('cleanup removes hashchange listener', () => {
196
- const win = createCodePage('#L1');
197
- const cleanup = mount(win);
198
-
199
- expect(typeof cleanup).toBe('function');
200
- cleanup!();
201
- });
202
- });
203
-
204
- describe('regular page', () => {
205
- function createRegularPage() {
206
- const html =
207
- '<nav class="toc"><ol>' +
208
- '<li><a href="#intro">Introduction</a></li>' +
209
- '<li><a href="#setup">Setup</a></li>' +
210
- '</ol></nav>' +
211
- '<div class="body">' +
212
- '<h2 id="intro">Introduction</h2>' +
213
- '<p>Content</p>' +
214
- '<h2 id="setup">Setup</h2>' +
215
- '<p>More content</p>' +
216
- '</div>';
217
- return new JSDOM(`<body>${html}</body>`, { url: 'http://localhost/' })
218
- .window;
219
- }
220
-
221
- test('sets a current item on mount', () => {
222
- const win = createRegularPage();
223
- mount(win);
224
-
225
- const current = win.document.querySelector('nav.toc .current');
226
- expect(current).not.toBeNull();
227
- });
228
-
229
- test('cleanup removes scroll listener', () => {
230
- const win = createRegularPage();
231
- const cleanup = mount(win);
232
-
233
- expect(typeof cleanup).toBe('function');
234
- cleanup!();
235
- });
236
- });
237
- });
@@ -1,46 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
- import { JSDOM } from 'jsdom';
3
- import mount from './index';
4
-
5
- function create(html = '') {
6
- const dom = new JSDOM(`<body>${html}</body>`, { url: 'http://localhost/' });
7
- return dom.window;
8
- }
9
-
10
- describe('top', () => {
11
- test('creates a back-to-top link in the body', () => {
12
- const win = create();
13
- mount(win);
14
-
15
- const link = win.document.querySelector('a.button');
16
- expect(link).not.toBeNull();
17
- expect(link!.getAttribute('href')).toBe('#');
18
- });
19
-
20
- test('mounts link inside #to-top-container when present', () => {
21
- const win = create('<div id="to-top-container"></div>');
22
- mount(win);
23
-
24
- const container = win.document.getElementById('to-top-container')!;
25
- const link = container.querySelector('a.button');
26
- expect(link).not.toBeNull();
27
- });
28
-
29
- test('link starts hidden (no is-visible class)', () => {
30
- const win = create();
31
- mount(win);
32
-
33
- const link = win.document.querySelector('a.button')!;
34
- expect(link.classList.contains('is-visible')).toBe(false);
35
- expect(link.getAttribute('tabindex')).toBe('-1');
36
- });
37
-
38
- test('cleanup removes scroll listener', () => {
39
- const win = create();
40
- const cleanup = mount(win);
41
-
42
- expect(typeof cleanup).toBe('function');
43
- // Should not throw
44
- cleanup!();
45
- });
46
- });