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 +3 -2
- package/plugins/images/index.js +31 -1
- package/plugins/markdown/index.js +74 -20
- package/stylesheets/DefaultStyles.css +10 -2
- package/utils.js +40 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vowel",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "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",
|
package/plugins/images/index.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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 }) =>
|
|
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
|
|
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('
|
|
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) {
|