vowel 0.4.0 → 0.6.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.4.0",
4
+ "version": "0.6.0",
5
5
  "bin": "bin.js",
6
6
  "main": "index.js",
7
7
  "scripts": {
@@ -58,6 +58,7 @@
58
58
  "remark-html": "^16.0.1",
59
59
  "remark-parse": "^11.0.0",
60
60
  "remark-rehype": "^11.1.2",
61
+ "sharp": "^0.35.3",
61
62
  "unified": "^11.0.5",
62
63
  "unist-util-find": "^3.0.0",
63
64
  "unist-util-is": "^6.0.0",
@@ -67,8 +68,8 @@
67
68
  "unist-util-visit": "^5.0.0",
68
69
  "unist-util-visit-parents": "^6.0.0",
69
70
  "url-metadata": "^5.4.1",
70
- "votive": "^0.2.0",
71
71
  "voot": "^0.1.0",
72
+ "votive": "^0.4.0",
72
73
  "xast-util-sitemap": "^2.0.0",
73
74
  "xast-util-to-xml": "^4.0.0",
74
75
  "xml": "^1.0.1",
@@ -1,10 +1,38 @@
1
+ import { randomUUID } from "node:crypto"
1
2
  import fs from "fs/promises"
3
+ import sharp from 'sharp'
4
+ import path from "node:path"
5
+ import {createImagePath, imageSizes, imageExts } from "./../../utils.js"
2
6
 
3
7
  /** @import * as Votive from "votive" */
4
8
 
9
+
5
10
  /** @type {Votive.ProcessorWrite} */
6
11
  async function writeImage(destination, database, config) {
12
+ const { uuid, sourcePath } = destination.abstract
13
+
14
+ const defaultFormat = path.extname(sourcePath)
15
+
16
+ const image = sharp(destination.path)
17
+
18
+ const images = imageSizes.flatMap(size => {
19
+ [...imageExts, defaultFormat].map(ext => {
20
+ const filePath = createImagePath({
21
+ targetFilePath: sourcePath,
22
+ size,
23
+ ext,
24
+ targetDirectory: config.destinationFolder,
25
+ uuid
26
+ })
27
+
28
+ return image.clone().resize(size).toFile(filePath)
29
+ })
30
+ })
31
+
32
+ await Promise.all(images)
33
+
7
34
  const buffer = await fs.readFile(destination.path)
35
+
8
36
  return {
9
37
  data: buffer,
10
38
  }
@@ -12,11 +40,13 @@ async function writeImage(destination, database, config) {
12
40
 
13
41
  /** @type {Votive.ProcessorRead} */
14
42
  function readImagePath(string) {
43
+ const uuid =randomUUID()
15
44
 
16
45
  const data = {
17
46
  metadata: {},
18
47
  abstract: {
19
- path: string
48
+ sourcePath: string,
49
+ uuid
20
50
  }
21
51
  }
22
52
 
@@ -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, testHashtags, createHashtagPage, toTitleCase, hashtagRegexSingle } from "./../../utils.js"
22
+ import { testURL, testHashtags, createHashtagPage, toTitleCase, hashtagRegexSingle, createImagePaths, imageSizes } 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'
@@ -50,7 +50,46 @@ User-agent: CCBot
50
50
  Disallow: /`
51
51
 
52
52
 
53
- function makeHead(metadata, url) {
53
+
54
+ /**
55
+ * @param {string} imagePath
56
+ * @param {Votive.Database} database
57
+ * @param {string} dependent
58
+ */
59
+ function createDynamicImage(imagePath, database, dependent, alt, itemprop) {
60
+ console.log({ imagePath })
61
+ const relativePath = imagePath.startsWith("/") ? path.relative("/", imagePath) : imagePath
62
+ const image = database.target.getWithTrackers(relativePath, dependent)
63
+ console.log({ relativePath, image })
64
+ const formats = createImagePaths(image.abstract.sourcePath, "./", image.abstract.uuid)
65
+
66
+
67
+ const sources = formats.map((format, index) => {
68
+ const isImg = index === formats.length - 1
69
+
70
+ const sizes = format.map((size, index) => `/${size} ${imageSizes[index]}w`).join(", ")
71
+ const type = "image/" + path.extname(format[0]).slice(1)
72
+ return h(isImg ? "img" : "source", {
73
+ type,
74
+ srcset: sizes,
75
+ loading: isImg && "lazy",
76
+ src: isImg && "/" + format.at(-1),
77
+ sizes: "100vw",
78
+ alt: isImg && alt
79
+ })
80
+ })
81
+
82
+
83
+ return h("picture", { itemprop: itemprop && "image" }, sources)
84
+ }
85
+
86
+ /**
87
+ * @param {object} metadata
88
+ * @param {string} url
89
+ * @param {Votive.Database} database
90
+ * @param {Votive.VotiveConfig} config
91
+ */
92
+ function makeHead(metadata, url, database, config) {
54
93
 
55
94
  const treeMainHead = []
56
95
 
@@ -75,19 +114,16 @@ function makeHead(metadata, url) {
75
114
  )
76
115
  }
77
116
 
78
- if (metadata.image) treeMainHead.push(
79
- h("img", {
80
- src: metadata.image,
81
- itemprop: "image"
82
- })
83
- )
84
117
 
85
- if (!metadata.image && metadata.first_image && url) treeMainHead.push(
86
- h("img", {
87
- src: metadata.first_image,
88
- itemprop: "image"
89
- })
90
- )
118
+
119
+
120
+ if (metadata.image || (metadata.first_image && url)) {
121
+ const metaImage = metadata.image || metadata.first_image
122
+
123
+ treeMainHead.push(
124
+ createDynamicImage(metaImage, database, url, null, true)
125
+ )
126
+ }
91
127
 
92
128
  if (metadata.fm_description) treeMainHead.push(
93
129
  h("p",
@@ -233,7 +269,7 @@ function readFile(string, filePath, destinationPath, database, config) {
233
269
  type: "text",
234
270
  value: match[4]
235
271
  },
236
-
272
+
237
273
  ...convertTagsToLinks(remainder)
238
274
  ]
239
275
  }
@@ -297,6 +333,7 @@ function readFile(string, filePath, destinationPath, database, config) {
297
333
  abstract,
298
334
  metadata: tagMetadata
299
335
  })
336
+
300
337
  })
301
338
  }
302
339
  }
@@ -728,7 +765,9 @@ function writeFile(destination, database, config) {
728
765
  dependent: destination.path,
729
766
  query: {}
730
767
  })
731
- }).filter(({ path }) => path)
768
+ }).filter(({ path, dir }) => {
769
+ return path && path !== "tags.html" && dir !== "tags"
770
+ })
732
771
 
733
772
  const treeStyleSheets = []
734
773
 
@@ -988,7 +1027,12 @@ function writeFile(destination, database, config) {
988
1027
 
989
1028
  const treeContentSlugged = slugger.runSync(treeContent)
990
1029
 
991
- const treeMainHead = makeHead(metadata)
1030
+ const treeMainHead = makeHead(metadata, null, database, config)
1031
+
1032
+ visit(treeContent, { tagName: "img" }, (node, index, parent) => {
1033
+ const { src, alt } = node.properties
1034
+ parent.children.splice(index, 1, createDynamicImage(src, database, destination.path, alt))
1035
+ })
992
1036
 
993
1037
  visit(treeContent, testPaths, ({ children: [child] }, i, p) => {
994
1038
 
@@ -1008,7 +1052,7 @@ function writeFile(destination, database, config) {
1008
1052
  const target = database.target.getWithTrackers(targetFilePath, destination.path)
1009
1053
 
1010
1054
  if (target) {
1011
- const article = h('article', makeHead(target.metadata, target.metadata.prettyURL))
1055
+ const article = h('article', makeHead(target.metadata, target.metadata.prettyURL, database, config))
1012
1056
 
1013
1057
  p.children.splice(i, 1, article)
1014
1058
  }
@@ -1033,9 +1077,18 @@ function writeFile(destination, database, config) {
1033
1077
 
1034
1078
  if (count) targets.splice(Number(count))
1035
1079
 
1036
- const list = h("section",
1080
+ const escapedDir = folder.replace("_", "--").replace(path.sep, "_")
1081
+ const escapedDirs = escapedDir.split("_").filter(a => a).map((segment, index, array) => {
1082
+ return "_" + array.slice(0, index + 1).join("_")
1083
+ })
1084
+ escapedDirs.unshift("_")
1085
+ const dirClasses = escapedDirs.join(".")
1086
+
1087
+ const list = h(`ul.${dirClasses}`,
1037
1088
  targets.map(target => {
1038
- return h('article', makeHead(target.metadata, target.metadata.prettyURL))
1089
+ return h('li',
1090
+ h('article', makeHead(target.metadata, target.metadata.prettyURL, database, config))
1091
+ )
1039
1092
  })
1040
1093
  )
1041
1094
 
@@ -1133,6 +1186,7 @@ function writeFile(destination, database, config) {
1133
1186
  const globalNavItems = everything.filter(item => {
1134
1187
  return item.dir === ""
1135
1188
  && item.path !== "index.html"
1189
+ && item.path !== "tags.html"
1136
1190
  })
1137
1191
  .map(getChildren)
1138
1192
 
@@ -226,15 +226,23 @@
226
226
  border-left: 5px solid var(--primary-border-color);
227
227
  }
228
228
 
229
- article {
229
+ main>article {
230
230
  border: 1px solid var(--primary-border-color);
231
- background: var(--soft-background);
232
231
  padding: 2rem 2rem 2rem;
233
232
  border-radius: calc(1rem + 5px);
234
233
  display: flex;
235
234
  flex-direction: column;
236
235
  }
237
236
 
237
+ main>ul._ {
238
+ list-style: none;
239
+ padding: 0;
240
+
241
+ & article {
242
+ padding-bottom: 1em;
243
+ }
244
+ }
245
+
238
246
  th,
239
247
  td {
240
248
  border-bottom: 1px solid var(--border-color-softer);
package/utils.js CHANGED
@@ -1,7 +1,47 @@
1
1
  import {fromMarkdown} from 'mdast-util-from-markdown'
2
2
  import {toHast} from 'mdast-util-to-hast'
3
3
  import {toHtml} from 'hast-util-to-html'
4
+ import path from "node:path"
5
+ import { randomUUID } from "node:crypto"
4
6
 
7
+ export const imageSizes = [414, 768, 1440, 1920]
8
+ export const imageExts = ["avif", "webp"]
9
+
10
+ /**
11
+ * @param {object} params
12
+ * @property {string} targetFilePath
13
+ * @property {number} size
14
+ * @property {string} targetDirectory
15
+ * @property {string} uuid
16
+ */
17
+ export function createImagePath({ targetFilePath, size, ext, targetDirectory, uuid }) {
18
+ const { dir, name } = path.parse(targetFilePath)
19
+ return path.format({
20
+ dir: path.relative(".", path.normalize(path.join(targetDirectory, dir))),
21
+ name: `${name}-${uuid}-${size}`,
22
+ ext
23
+ })
24
+ }
25
+
26
+ /**
27
+ * @param {string} targetFilePath
28
+ * @param {string} targetDirectory
29
+ * @param {string} uuid
30
+ */
31
+ export function createImagePaths(targetFilePath, targetDirectory, uuid) {
32
+ const defaultExt = path.extname(targetFilePath)
33
+ return [...imageExts, defaultExt].map(ext => {
34
+ return imageSizes.map(size => {
35
+ return createImagePath({
36
+ targetFilePath,
37
+ size,
38
+ ext,
39
+ targetDirectory,
40
+ uuid
41
+ })
42
+ })
43
+ })
44
+ }
5
45
 
6
46
  /** @param {string} text */
7
47
  export function testURL(text) {