vowel 0.1.12 → 0.1.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vowel",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
4
4
  "bin": "./bin.js",
5
5
  "scripts": {
6
6
  "dev": "vite dev",
@@ -31,11 +31,18 @@
31
31
  "prettier": "^3.0.0",
32
32
  "prettier-plugin-svelte": "^3.0.0",
33
33
  "remark": "^15.0.1",
34
+ "remark-admonitions": "^1.2.1",
35
+ "remark-directive": "^3.0.0",
34
36
  "remark-frontmatter": "^5.0.0",
37
+ "remark-gfm": "^4.0.0",
35
38
  "remark-html": "^16.0.1",
39
+ "remark-images": "^4.0.0",
40
+ "remark-parse": "^11.0.0",
41
+ "remark-rehype": "^11.1.0",
36
42
  "spectre.css": "^0.5.9",
37
43
  "svelte": "^5.0.0-next.121",
38
44
  "typescript": "^5.0.0",
45
+ "unified": "^11.0.4",
39
46
  "url-metadata": "^3.4.9",
40
47
  "vite": "^5.0.12",
41
48
  "xml": "^1.0.1"
@@ -132,6 +132,8 @@
132
132
  img {
133
133
  border-style: none;
134
134
  height: auto;
135
+ border-radius: 5px;
136
+ overflow: hidden;
135
137
  }
136
138
 
137
139
  /* Layout */
@@ -352,7 +354,9 @@
352
354
  padding-right: 0;
353
355
  }
354
356
 
355
- :where(pre, blockquote, dl, figure, table, p, ul, ol, form, article, section):not(:last-child) {
357
+ :where(pre, blockquote, dl, figure, table, p, ul, ol, form, article, section, aside):not(
358
+ :last-child
359
+ ) {
356
360
  margin-bottom: 2.5rem;
357
361
  }
358
362
 
@@ -513,5 +517,53 @@
513
517
  article.item dl.icon {
514
518
  order: -1;
515
519
  }
520
+
521
+ aside.note {
522
+ &.note {
523
+ --icon: 'ℹ️';
524
+ --rgb: 71, 139, 230;
525
+ }
526
+ &.tip {
527
+ --icon: '💡';
528
+ --rgb: 87, 171, 90;
529
+ }
530
+ &.important {
531
+ --icon: '💬';
532
+ --rgb: 152, 110, 226;
533
+ }
534
+ &.warning {
535
+ --icon: '⚠️';
536
+ --rgb: 198, 144, 38;
537
+ }
538
+ &.caution {
539
+ --icon: '⛔️';
540
+ --rgb: 229, 83, 75;
541
+ }
542
+
543
+ border-left: 3px solid rgb(var(--rgb));
544
+ padding: 1.5rem 2rem;
545
+ background: rgba(var(--rgb), 0.04);
546
+
547
+ h2 {
548
+ margin: 0 0 0.5em 0;
549
+ font-size: 1.1em;
550
+ color: rgb(var(--rgb));
551
+ }
552
+
553
+ h2:before {
554
+ font-size: 0.8em;
555
+ margin-right: 0.7rem;
556
+ opacity: 0.9;
557
+ }
558
+
559
+ h2:before {
560
+ content: var(--icon);
561
+ }
562
+ }
563
+
564
+ li.checked,
565
+ li.unchecked {
566
+ padding-left: 0.8rem;
567
+ }
516
568
  }
517
569
  </style>
@@ -11,7 +11,11 @@
11
11
 
12
12
  let { props } = $props();
13
13
 
14
- let { ast, level, website, format } = $derived(props);
14
+ let { ast, level, website, format, identifier } = $derived(props);
15
+
16
+ if (identifier) {
17
+ console.log(identifier);
18
+ }
15
19
 
16
20
  function getElement(node) {
17
21
  if (node.type === 'heading') {
@@ -23,16 +27,33 @@
23
27
  paragraph: 'p',
24
28
  strong: 'strong',
25
29
  list: node.ordered ? 'ol' : 'ul',
26
- listItem: 'li',
30
+ // listItem: 'li',
27
31
  blockquote: 'blockquote',
28
32
  inlineCode: 'code',
29
33
  code: 'pre',
30
34
  figure: 'figure',
31
- figcaption: 'figcaption'
35
+ figcaption: 'figcaption',
36
+ delete: 's',
37
+ table: 'table',
38
+ tableRow: 'tr',
39
+ tableCell: 'td'
32
40
  };
33
41
 
34
- return elements[node.type];
42
+ // Handle list item separately
43
+ // Handle `pre` properly
44
+ // Handle `footnoteDefinition` and `footnoteReference`
45
+
46
+ if (elements[node.type]) return elements[node.type];
47
+ console.log(node);
35
48
  }
49
+
50
+ const noteTypes = {
51
+ tip: 'Tip',
52
+ note: 'Note',
53
+ important: 'Important',
54
+ warning: 'Warning',
55
+ caution: 'Caution'
56
+ };
36
57
  </script>
37
58
 
38
59
  {#if ast}
@@ -70,9 +91,54 @@
70
91
  <Image {node} />
71
92
  {:else if node.type === 'url'}
72
93
  <LinkPreview url={node.value} metadata={node.metadata} {format} />
94
+ {:else if node.type === 'listItem'}
95
+ {@const isChecklistItem = node.hasOwnProperty('checked')}
96
+ {#if isChecklistItem}
97
+ <li
98
+ class={`checklist-item ${node.checked ? 'checked' : 'unchecked'}`}
99
+ style:list-style-type={`"${node.checked ? '☑' : '☐'}"`}
100
+ >
101
+ <svelte:self props={{ ast: node.children, level, format }} />
102
+ </li>
103
+ {:else}
104
+ <li>
105
+ <svelte:self props={{ ast: node.children, level, format }} />
106
+ </li>
107
+ {/if}
108
+ {:else if node.type === 'footnoteReference'}
109
+ <sup
110
+ ><a
111
+ href={`#footnote-definition-${node.identifier}`}
112
+ id={`footnote-${node.identifier}`}
113
+ aria-describedby="footnotes">{node.label}</a
114
+ ></sup
115
+ >
116
+ {:else if node.type === 'footnotes'}
117
+ <section id="footnotes">
118
+ <h2>Footnotes</h2>
119
+ <ol>
120
+ {#each node.children as footnote}
121
+ <li id={`footnote-definition-${footnote.identifier}`}>
122
+ <svelte:self
123
+ props={{ ast: footnote.children, level, format, identifier: footnote.identifier }}
124
+ />
125
+ </li>
126
+ {/each}
127
+ </ol>
128
+ </section>
129
+ {:else if node.type === 'containerDirective' && noteTypes[node.name]}
130
+ <aside class={`note ${node.name}`}>
131
+ <h2>
132
+ {noteTypes[node.name]}
133
+ </h2>
134
+ <svelte:self props={{ ast: node.children, level, format }}></svelte:self>
135
+ </aside>
73
136
  {:else if node.children}
74
137
  <svelte:element this={getElement(node)}>
75
138
  <svelte:self props={{ ast: node.children, level, format }} />
139
+ {#if identifier}
140
+ <a href={`#footnote-${identifier}`} aria-label="Back to content">↩</a>
141
+ {/if}
76
142
  </svelte:element>
77
143
  {:else if node.type === 'text'}
78
144
  <Text {node} />
@@ -1,7 +1,9 @@
1
1
  import fs from 'fs/promises';
2
2
  import { remark } from 'remark';
3
3
  import remarkFrontmatter from 'remark-frontmatter';
4
+ import remarkDirective from 'remark-directive';
4
5
  import remarkHTML from 'remark-html';
6
+ import remarkGFM from 'remark-gfm';
5
7
  import yaml from 'js-yaml';
6
8
  import { toString } from 'mdast-util-to-string';
7
9
  import path from 'path';
@@ -102,7 +104,32 @@ export default async function readMarkdownFile(filePath, cache) {
102
104
  const parsedMarkdown = markdownParser.parse(fileContent);
103
105
  const frontmatterNode = parsedMarkdown.children.find((node) => node.type === 'yaml');
104
106
  const frontmatter = frontmatterNode?.type === 'yaml' ? parseFrontmatter(frontmatterNode) : {};
105
- const ast = remark().use(remarkFrontmatter).parse(fileContent);
107
+ const ast = remark()
108
+ .use(remarkDirective)
109
+ .use(remarkFrontmatter)
110
+ .use(remarkGFM)
111
+ .parse(fileContent);
112
+
113
+ const footnotes = [];
114
+
115
+ for (let i = 0; i < ast.children.length; i++) {
116
+ if (ast.children[i].type === 'footnoteDefinition') {
117
+ footnotes.push(ast.children[i]);
118
+ }
119
+ }
120
+
121
+ if (footnotes.length) {
122
+ ast.children.push({
123
+ type: 'footnotes',
124
+ children: footnotes
125
+ });
126
+ }
127
+
128
+ // ast.children.sort((a, b) => {
129
+ // if (a.type !== 'footnoteDefinition' && b.type === 'footnoteDefinition') return -1;
130
+ // return 0;
131
+ // });
132
+
106
133
  const filteredAST = ast.children.filter((child) => child.type !== 'yaml');
107
134
 
108
135
  const imputedTitle = imputeTitleFromAST(filteredAST);