vowel 0.3.3 → 0.4.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vowel",
3
3
  "type": "module",
4
- "version": "0.3.3",
4
+ "version": "0.4.0",
5
5
  "bin": "bin.js",
6
6
  "main": "index.js",
7
7
  "scripts": {
@@ -19,7 +19,7 @@ import { h } from 'hastscript'
19
19
  import { normalizeHeadings } from 'mdast-normalize-headings'
20
20
  import { readFileSync } from "fs"
21
21
  import { remove } from "unist-util-remove"
22
- import { testURL } from "./../../utils.js"
22
+ import { testURL, testHashtags, createHashtagPage, toTitleCase, hashtagRegexSingle } from "./../../utils.js"
23
23
  import { toHast } from 'mdast-util-to-hast'
24
24
  import { toString as hastToString } from 'hast-util-to-string'
25
25
  import { toString as mdastToString } from 'mdast-util-to-string'
@@ -103,14 +103,6 @@ function makeHead(metadata, url) {
103
103
  return treeMainHead
104
104
  }
105
105
 
106
- function toTitleCase(string) {
107
- if (!string) return
108
- return string.split(" ").map(word => {
109
- const letters = word.split("")
110
- letters[0] = letters[0].toUpperCase()
111
- return letters.join("")
112
- }).join(" ")
113
- }
114
106
 
115
107
  function readURL(data) {
116
108
  const hast = fromHtml(data)
@@ -140,7 +132,7 @@ function readURL(data) {
140
132
 
141
133
 
142
134
  /** @type {Votive.ReadText} */
143
- function readMarkdown(string, filePath, destinationPath, database, config) {
135
+ function readFile(string, filePath, destinationPath, database, config) {
144
136
  const mdast = fromMarkdown(string, {
145
137
  // Micromark extensions
146
138
  extensions: [
@@ -198,6 +190,7 @@ function readMarkdown(string, filePath, destinationPath, database, config) {
198
190
  visit(mdast, (node, index, parent) => {
199
191
  if (node.type === "text" && parent.children.length === 1 && parent.type === "paragraph") {
200
192
  const validURL = testURL(node.value)
193
+
201
194
  if (validURL) {
202
195
 
203
196
  jobs.push({
@@ -205,6 +198,107 @@ function readMarkdown(string, filePath, destinationPath, database, config) {
205
198
  runner: "text",
206
199
  destination: destinationPath
207
200
  })
201
+
202
+ return
203
+ }
204
+
205
+ const hashtags = testHashtags(node.value)
206
+
207
+ // TODO: Tags should not appear in menus
208
+ // TODO: Make this work when tags are embedded in text
209
+
210
+ if (hashtags) {
211
+ function convertTagsToLinks(value) {
212
+ const match = value.match(hashtagRegexSingle)
213
+ if (match) {
214
+ const remainder = value.slice(match[0].length)
215
+ const child = {
216
+ type: "link",
217
+ url: `/tags/${match[3]}`,
218
+ children: [
219
+ {
220
+ type: "text",
221
+ value: match[0]
222
+ }
223
+ ]
224
+ }
225
+
226
+ return [
227
+ {
228
+ type: "text",
229
+ value: match[1]
230
+ },
231
+ child,
232
+ {
233
+ type: "text",
234
+ value: match[4]
235
+ },
236
+
237
+ ...convertTagsToLinks(remainder)
238
+ ]
239
+ }
240
+ return [
241
+ {
242
+ type: "text",
243
+ value: value
244
+ }
245
+ ]
246
+ }
247
+
248
+ parent.children = convertTagsToLinks(node.value)
249
+
250
+ const markdown = `/tags/**`
251
+ const mdast = fromMarkdown(markdown)
252
+
253
+ const extant = database.target.get("tags.html")
254
+
255
+ // FIXME: Update abstract format
256
+ if (!extant) {
257
+ // Delete if unnecessary
258
+ database.target.create({
259
+ path: `tags.html`,
260
+ abstract: mdast,
261
+ metadata: {
262
+ breadcrumb: "Tags",
263
+ title: "Tags",
264
+ prettyURL: "/tags",
265
+ }
266
+ })
267
+ }
268
+
269
+ database.dependency.track({}, "tags", null, destinationPath, "tags.html")
270
+ database.target.markStale("tags.html")
271
+
272
+ if (hashtags) {
273
+ if (!metadata.tags) {
274
+ metadata.tags = []
275
+ } else if (!Array.isArray(metadata.tags)) {
276
+ metadata.tags = []
277
+ }
278
+
279
+ metadata.tags = []
280
+
281
+ hashtags.forEach(hashtag => {
282
+ const title = toTitleCase(hashtag)
283
+ metadata.tags.push(hashtag)
284
+
285
+ const abstract = createHashtagPage(hashtag)
286
+
287
+ const tagMetadata = {
288
+ breadcrumb: title,
289
+ title: title,
290
+ prettyURL: `/tags/${hashtag}`,
291
+ type: "tag",
292
+ tag: hashtag
293
+ }
294
+
295
+ const created = database.target.create({
296
+ path: `tags/${hashtag}.html`,
297
+ abstract,
298
+ metadata: tagMetadata
299
+ })
300
+ })
301
+ }
208
302
  }
209
303
  }
210
304
  })
@@ -364,7 +458,7 @@ function getMetadata(tree, filePath) {
364
458
  }
365
459
 
366
460
  /** @type {Votive.ReadAbstract} */
367
- function readAbstract(abstract, database, config) {
461
+ function transformFile(abstract, database, config) {
368
462
  const jobs = []
369
463
  return { abstract, jobs }
370
464
  }
@@ -580,13 +674,31 @@ function readFolder(folder, database, config, isRoot) {
580
674
  }
581
675
 
582
676
  /** @type {Votive.ProcessorWrite} */
583
- function writeHTML(destination, database, config) {
677
+ function writeFile(destination, database, config) {
584
678
  const isRoot = destination.path === "index.html"
585
679
 
680
+ // console.log(destination.metadata)
681
+
682
+ if (destination.metadata.type === "tag") {
683
+ if (!destination.metadata.tag) return false
684
+
685
+ const pages = database.target.getManyWithTrackers({
686
+ recursive: true,
687
+ dependent: destination,
688
+ query: {
689
+ tags: destination.metadata.tag
690
+ }
691
+ })
692
+
693
+ if (!pages.length) return false
694
+ }
695
+
586
696
  const settings = database.setting.getByFolder(destination.dir + path.sep)
587
697
 
588
698
  const { abstract, metadata, ...rest } = destination
589
699
 
700
+ if (metadata.tags) metadata.tags = JSON.parse(metadata.tags)
701
+
590
702
  /** @param {string} filePath */
591
703
  function listFolders(filePath) {
592
704
  if (!filePath) return []
@@ -907,10 +1019,15 @@ function writeHTML(destination, database, config) {
907
1019
  const folder = path.relative("/", dir)
908
1020
  // const url = new URL(child.value, "thismessage://")
909
1021
  const count = url.searchParams.get("count")
1022
+ const tag = url.searchParams.get("tag")
1023
+ const query = tag
1024
+ ? { tags: tag }
1025
+ : {}
1026
+
910
1027
  const targets = database.target.getManyWithTrackers({
911
1028
  folder,
912
1029
  recursive,
913
- query: {},
1030
+ query,
914
1031
  dependent: destination.path
915
1032
  })
916
1033
 
@@ -1152,26 +1269,26 @@ function router(args) {
1152
1269
 
1153
1270
 
1154
1271
  /** @type {Votive.VotiveProcessor} */
1155
- const markdownReader = {
1272
+ const readMarkdown = {
1156
1273
  extensions: [".md"],
1157
1274
  format: "text",
1158
- readFile: readMarkdown,
1275
+ readFile,
1159
1276
  readResource: readURL,
1160
- transformFile: readAbstract,
1161
- readFolder: readFolder,
1277
+ transformFile,
1278
+ readFolder,
1162
1279
  }
1163
1280
 
1164
- const htmlWriter = {
1281
+ const writeHTML = {
1165
1282
  extensions: [".html"],
1166
1283
  format: "text",
1167
- writeFile: writeHTML
1284
+ writeFile
1168
1285
  }
1169
1286
 
1170
1287
 
1171
1288
  /** @type {Votive.VotivePlugin} */
1172
1289
  const vowelMarkdownPlugin = {
1173
1290
  name: "vowel",
1174
- processors: [markdownReader, htmlWriter],
1291
+ processors: [readMarkdown, writeHTML],
1175
1292
  router
1176
1293
  }
1177
1294
 
@@ -9,7 +9,7 @@
9
9
 
10
10
  @layer default {
11
11
  :root {
12
-
12
+ --accent-00: oklch(1 0.030170139248992922 90.24115342246611);
13
13
  --accent-01: oklch(0.9536456092315344 0.030170139248992922 90.24115342246611);
14
14
  --accent-02: oklch(0.8924089806120152 0.08826670827983002 90.24115342246611);
15
15
  --accent-03: oklch(0.844618 0.14828222329121668 90.24115342246611);
@@ -21,6 +21,7 @@
21
21
  --accent-09: oklch(0.38727951482578865 0.05695363236371703 90.24115342246611);
22
22
  --accent-10: oklch(0.24916012628129958 0.03201699687903088 90.24115342246611);
23
23
  --accent-11: oklch(0.11046170738630641 0.01528852137867617 90.24115342246611);
24
+ --danger-00: oklch(1 0.037138530373020395 -25.754653176550182);
24
25
  --danger-01: oklch(0.9536456092315344 0.037138530373020395 -25.754653176550182);
25
26
  --danger-02: oklch(0.8924089806120152 0.0908858065656466 -25.754653176550182);
26
27
  --danger-03: oklch(0.844618 0.15656415898125758 -25.754653176550182);
@@ -32,6 +33,7 @@
32
33
  --danger-09: oklch(0.38727951482578865 0.1036689817070561 -25.754653176550182);
33
34
  --danger-10: oklch(0.24916012628129958 0.058004850702477094 -25.754653176550182);
34
35
  --danger-11: oklch(0.11046170738630641 0.02748297973358925 -25.754653176550182);
36
+ --info-00: oklch(1 0.032559707682643824 244.1900622367698);
35
37
  --info-01: oklch(0.9536456092315344 0.032559707682643824 244.1900622367698);
36
38
  --info-02: oklch(0.8924089806120152 0.07422782322853594 244.1900622367698);
37
39
  --info-03: oklch(0.844618 0.12605888808084453 244.1900622367698);
@@ -43,6 +45,7 @@
43
45
  --info-09: oklch(0.38727951482578865 0.12889889174890792 244.1900622367698);
44
46
  --info-10: oklch(0.24916012628129958 0.0769636599555286 244.1900622367698);
45
47
  --info-11: oklch(0.11046170738630641 0.034552898697749426 244.1900622367698);
48
+ --primary-00: oklch(1 0.033943473040194294 -82.72000000000003);
46
49
  --primary-01: oklch(0.9536456092315344 0.033943473040194294 -82.72000000000003);
47
50
  --primary-02: oklch(0.8924089806120152 0.07208713732898053 -82.72000000000003);
48
51
  --primary-03: oklch(0.844618 0.10967407324412015 -82.72000000000003);
@@ -54,6 +57,7 @@
54
57
  --primary-09: oklch(0.38727951482578865 0.22519086267101945 -82.72000000000003);
55
58
  --primary-10: oklch(0.24916012628129958 0.1489244571729748 -82.72000000000003);
56
59
  --primary-11: oklch(0.11046170738630641 0.07262669982202441 -82.72000000000003);
60
+ --secondary-00: oklch(1 0.03523506763462919 174.9674);
57
61
  --secondary-01: oklch(0.9536456092315344 0.03523506763462919 174.9674);
58
62
  --secondary-02: oklch(0.8924089806120152 0.12226651611616707 174.9674);
59
63
  --secondary-03: oklch(0.844618 0.159299 174.9674);
@@ -65,6 +69,7 @@
65
69
  --secondary-09: oklch(0.38727951482578865 0.037032483883832935 174.9674);
66
70
  --secondary-10: oklch(0.24916012628129958 0.02375390884349093 174.9674);
67
71
  --secondary-11: oklch(0.11046170738630641 0.011400212679566413 174.9674);
72
+ --success-00: oklch(1 0.024257111887574123 148.30000439636984);
68
73
  --success-01: oklch(0.9536456092315344 0.024257111887574123 148.30000439636984);
69
74
  --success-02: oklch(0.8924089806120152 0.07351482341637697 148.30000439636984);
70
75
  --success-03: oklch(0.844618 0.12466168066207778 148.30000439636984);
@@ -76,6 +81,7 @@
76
81
  --success-09: oklch(0.38727951482578865 0.0457513376060701 148.30000439636984);
77
82
  --success-10: oklch(0.24916012628129958 0.02575933593360364 148.30000439636984);
78
83
  --success-11: oklch(0.11046170738630641 0.012313506052849059 148.30000439636984);
84
+ --tertiary-00: oklch(1 0.034046389815560296 2.791302501092794);
79
85
  --tertiary-01: oklch(0.9536456092315344 0.034046389815560296 2.791302501092794);
80
86
  --tertiary-02: oklch(0.8924089806120152 0.08421751016426371 2.791302501092794);
81
87
  --tertiary-03: oklch(0.844618 0.14726059081820986 2.791302501092794);
@@ -87,6 +93,7 @@
87
93
  --tertiary-09: oklch(0.38727951482578865 0.09664947566806639 2.791302501092794);
88
94
  --tertiary-10: oklch(0.24916012628129958 0.053320044751899345 2.791302501092794);
89
95
  --tertiary-11: oklch(0.11046170738630641 0.025277009084351466 2.791302501092794);
96
+ --warning-00: oklch(1 0.033978843637678835 61.19378984733035);
90
97
  --warning-01: oklch(0.9536456092315344 0.033978843637678835 61.19378984733035);
91
98
  --warning-02: oklch(0.8924089806120152 0.09727044978770355 61.19378984733035);
92
99
  --warning-03: oklch(0.844618 0.16243636817381144 61.19378984733035);
@@ -100,13 +107,42 @@
100
107
  --warning-11: oklch(0.11046170738630641 0.017183679327988338 61.19378984733035);
101
108
 
102
109
 
103
- --text-color: light-dark(var(--primary-11), var(--primary-01));
104
- --link-color: light-dark(var(--secondary-07), var(--secondary-03));
105
- --link-hover-color: light-dark(var(--secondary-06), var(--secondary-04));
106
- --border-color: light-dark(var(--primary-03), var(--primary-09));
107
- --main-background: light-dark(var(--primary-01), var(--primary-11));
108
- --code-background: light-dark(var(--primary-02), var(--primary-10));
109
- --soft-background: light-dark(var(--primary-02), var(--primary-10));
110
+ /* main */
111
+ --primary-text-color: light-dark(var(--primary-11), var(--primary-01));
112
+ --primary-heading-color: light-dark(var(--primary-10), var(--primary-02));
113
+ --primary-link-color: light-dark(var(--secondary-07), var(--secondary-03));
114
+ --primary-link-hover-color: light-dark(var(--secondary-06), var(--secondary-04));
115
+ --primary-border-color: light-dark(var(--primary-03), var(--primary-09));
116
+
117
+ /* secondary */
118
+ --secondary-text-color: light-dark(var(--secondary-11), var(--secondary-01));
119
+ --secondary-heading-color: light-dark(var(--secondary-09), var(--secondary-03));
120
+
121
+ /* backgrounds */
122
+ --main-background: light-dark(var(--primary-00), var(--primary-11));
123
+ --code-background: light-dark(var(--primary-01), var(--primary-10));
124
+ --soft-background: light-dark(var(--primary-01), var(--primary-10));
125
+
126
+ /* alerts */
127
+ --warning-background: light-dark(var(--warning-01), var(--warning-10));
128
+ --warning-text: light-dark(var(--warning-10), var(--warning-01));
129
+ --warning-border: light-dark(var(--warning-02), var(--warning-08));
130
+ --warning-heading: light-dark(var(--warning-08), var(--warning-02));
131
+
132
+ --danger-background: light-dark(var(--danger-01), var(--danger-10));
133
+ --danger-text: light-dark(var(--danger-10), var(--danger-01));
134
+ --danger-border: light-dark(var(--danger-02), var(--danger-08));
135
+ --danger-heading: light-dark(var(--danger-08), var(--danger-02));
136
+
137
+ --success-background: light-dark(var(--success-01), var(--success-10));
138
+ --success-text: light-dark(var(--success-10), var(--success-01));
139
+ --success-border: light-dark(var(--success-02), var(--success-08));
140
+ --success-heading: light-dark(var(--success-08), var(--success-02));
141
+
142
+ --note-background: light-dark(var(--note-01), var(--note-10));
143
+ --note-text: light-dark(var(--note-10), var(--note-01));
144
+ --node-border: light-dark(var(--node-02), var(--node-08));
145
+ --note-heading: light-dark(var(--note-08), var(--note-02));
110
146
  }
111
147
 
112
148
  :root {
@@ -169,15 +205,15 @@
169
205
  /* Colors */
170
206
 
171
207
  html {
172
- color: var(--text-color);
208
+ color: var(--primary-text-color);
173
209
  background: var(--main-background);
174
210
  }
175
211
 
176
212
  a:where(:not([rel=home])) {
177
- color: var(--link-color);
213
+ color: var(--primary-link-color);
178
214
 
179
215
  &:hover {
180
- color: var(--link-hover-color);
216
+ color: var(--primary-link-hover-color);
181
217
  }
182
218
  }
183
219
 
@@ -187,11 +223,11 @@
187
223
  }
188
224
 
189
225
  blockquote {
190
- border-left: 5px solid var(--border-color);
226
+ border-left: 5px solid var(--primary-border-color);
191
227
  }
192
228
 
193
229
  article {
194
- border: 1px solid var(--border-color);
230
+ border: 1px solid var(--primary-border-color);
195
231
  background: var(--soft-background);
196
232
  padding: 2rem 2rem 2rem;
197
233
  border-radius: calc(1rem + 5px);
@@ -205,7 +241,7 @@
205
241
  }
206
242
 
207
243
  hr {
208
- border-top: 1px solid var(--text-color);
244
+ border-top: 1px solid var(--primary-text-color);
209
245
  }
210
246
 
211
247
  /* Frontmatter */
@@ -284,7 +320,7 @@
284
320
  }
285
321
 
286
322
  nav {
287
- border: 1px solid var(--border-color);
323
+ border: 1px solid var(--primary-border-color);
288
324
  padding: 0px 6px;
289
325
  width: 100%;
290
326
 
@@ -313,7 +349,7 @@
313
349
  &:after {
314
350
  display: block;
315
351
  content: '';
316
- border-bottom: 1px solid var(--border-color);
352
+ border-bottom: 1px solid var(--primary-border-color);
317
353
  flex-basis: 100%;
318
354
  margin-block: 0.7rem;
319
355
  }
@@ -389,7 +425,7 @@
389
425
  p:where([itemprop=description]),
390
426
  main>p:first-of-type {
391
427
  font-size: 1.3em;
392
- color: var(--secondary-10);
428
+ color: var(--secondary-text-color);
393
429
  }
394
430
 
395
431
  article a {
@@ -443,46 +479,46 @@
443
479
 
444
480
  aside.alert.note {
445
481
  --icon: 'ℹ️';
446
- background: var(--info-02);
447
- color: var(--info-10);
448
- border-left: 3px solid var(--info-03);
482
+ background: var(--info-background);
483
+ color: var(--info-text);
484
+ border-left: 3px solid var(--info-border);
449
485
 
450
486
  h2 {
451
- color: var(--info-08);
487
+ color: var(--info-heading);
452
488
  }
453
489
  }
454
490
 
455
491
  aside.alert.success {
456
492
  --icon: '💡';
457
- background: var(--success-02);
458
- color: var(--success-10);
459
- border-left: 3px solid var(--success-03);
493
+ background: var(--success-background);
494
+ color: var(--success-text);
495
+ border-left: 3px solid var(--success-border);
460
496
 
461
497
  h2 {
462
- color: var(--success-08);
498
+ color: var(--success-heading);
463
499
  }
464
500
  }
465
501
 
466
502
  aside.alert.warning {
467
503
  --icon: '⚠️';
468
- background: var(--warning-02);
469
- color: var(--warning-10);
470
- border-left: 3px solid var(--warning-03);
504
+ background: var(--warning-background);
505
+ color: var(--warning-text);
506
+ border-left: 3px solid var(--warning-border);
471
507
 
472
508
  h2 {
473
- color: var(--warning-08);
509
+ color: var(--warning-heading);
474
510
  }
475
511
  }
476
512
 
477
513
 
478
514
  aside.alert.danger {
479
515
  --icon: '⛔️';
480
- background: var(--danger-02);
481
- color: var(--danger-10);
482
- border-left: 3px solid var(--danger-03);
516
+ background: var(--danger-background);
517
+ color: var(--danger-text);
518
+ border-left: 3px solid var(--danger-border);
483
519
 
484
520
  h2 {
485
- color: var(--danger-08);
521
+ color: var(--danger-border);
486
522
  }
487
523
  }
488
524
 
package/utils.js CHANGED
@@ -1,3 +1,8 @@
1
+ import {fromMarkdown} from 'mdast-util-from-markdown'
2
+ import {toHast} from 'mdast-util-to-hast'
3
+ import {toHtml} from 'hast-util-to-html'
4
+
5
+
1
6
  /** @param {string} text */
2
7
  export function testURL(text) {
3
8
  if (text.match(/^https?:\/\/[\S]+$/)) {
@@ -8,3 +13,28 @@ export function testURL(text) {
8
13
  }
9
14
  }
10
15
  }
16
+
17
+ export const hashtagRegexSingle = /(^|\s)(#([\w\-\/]+))($|\b)/
18
+ export const hashtagRegexGlobal = /(?:^|\s)(#[\w\-\/]+)(?:$|\b)/g
19
+
20
+ export function testHashtags(text) {
21
+ const match = text.match(hashtagRegexGlobal)
22
+ if(match) return match.map(a => a.trim().slice(1))
23
+ }
24
+
25
+
26
+ export function toTitleCase(string) {
27
+ if (!string) return
28
+ return string.split(" ").map(word => {
29
+ const letters = word.split("")
30
+ letters[0] = letters[0].toUpperCase()
31
+ return letters.join("")
32
+ }).join(" ")
33
+ }
34
+
35
+ export function createHashtagPage(tag) {
36
+ const markdown = `# ${toTitleCase(tag)}\n\n/**?tag=${tag}`
37
+ const mdast = fromMarkdown(markdown)
38
+
39
+ return mdast
40
+ }