vowel 0.5.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.5.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",
@@ -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",
@@ -991,7 +1027,12 @@ function writeFile(destination, database, config) {
991
1027
 
992
1028
  const treeContentSlugged = slugger.runSync(treeContent)
993
1029
 
994
- 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
+ })
995
1036
 
996
1037
  visit(treeContent, testPaths, ({ children: [child] }, i, p) => {
997
1038
 
@@ -1011,7 +1052,7 @@ function writeFile(destination, database, config) {
1011
1052
  const target = database.target.getWithTrackers(targetFilePath, destination.path)
1012
1053
 
1013
1054
  if (target) {
1014
- const article = h('article', makeHead(target.metadata, target.metadata.prettyURL))
1055
+ const article = h('article', makeHead(target.metadata, target.metadata.prettyURL, database, config))
1015
1056
 
1016
1057
  p.children.splice(i, 1, article)
1017
1058
  }
@@ -1046,7 +1087,7 @@ function writeFile(destination, database, config) {
1046
1087
  const list = h(`ul.${dirClasses}`,
1047
1088
  targets.map(target => {
1048
1089
  return h('li',
1049
- h('article', makeHead(target.metadata, target.metadata.prettyURL))
1090
+ h('article', makeHead(target.metadata, target.metadata.prettyURL, database, config))
1050
1091
  )
1051
1092
  })
1052
1093
  )
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) {