vowel 0.1.46 → 0.2.2

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.
Files changed (115) hide show
  1. package/README.md +82 -20
  2. package/bin.js +2 -78
  3. package/docs-source/$features/cards.md +7 -0
  4. package/docs-source/$features/editing.md +7 -0
  5. package/docs-source/$features/emoji.md +7 -0
  6. package/docs-source/$features/frontmatter.md +7 -0
  7. package/docs-source/$features/lists.md +7 -0
  8. package/docs-source/$features/navigation.md +7 -0
  9. package/docs-source/$features/rich-previews.md +7 -0
  10. package/docs-source/$features/robots.md +7 -0
  11. package/docs-source/$features/rss.md +7 -0
  12. package/docs-source/$features/sitemap.md +7 -0
  13. package/docs-source/$features/speed.md +7 -0
  14. package/docs-source/$features/static.md +7 -0
  15. package/docs-source/$features/taxonomies.md +7 -0
  16. package/docs-source/.cache.json +9 -0
  17. package/docs-source/.obsidian/app.json +3 -0
  18. package/docs-source/.obsidian/appearance.json +3 -0
  19. package/docs-source/.obsidian/core-plugins-migration.json +30 -0
  20. package/docs-source/.obsidian/core-plugins.json +20 -0
  21. package/docs-source/.obsidian/workspace.json +168 -0
  22. package/docs-source/.stackblitzrc +3 -0
  23. package/docs-source/.vercel/README.txt +11 -0
  24. package/docs-source/.vercel/project.json +1 -0
  25. package/docs-source/about.md +3 -0
  26. package/docs-source/assets/styles.css +51 -0
  27. package/docs-source/blog/home.md +5 -0
  28. package/docs-source/blog/url-ui.md +21 -0
  29. package/docs-source/docs/.votive.db +0 -0
  30. package/docs-source/docs/deploy.md +67 -0
  31. package/docs-source/docs/file-structure.md +31 -0
  32. package/docs-source/docs/folder-settings.md +23 -0
  33. package/docs-source/docs/home.md +55 -0
  34. package/docs-source/docs/images.md +10 -0
  35. package/docs-source/docs/items.md +13 -0
  36. package/docs-source/docs/pages.md +141 -0
  37. package/docs-source/docs/settings.md +4 -0
  38. package/docs-source/docs/styling.md +34 -0
  39. package/docs-source/docs/taxonomies.md +37 -0
  40. package/docs-source/home.md +42 -0
  41. package/docs-source/roadmap.md +98 -0
  42. package/docs-source/settings.md +12 -0
  43. package/extractDate.js +83 -0
  44. package/getMetadata.js +41 -0
  45. package/index.js +669 -0
  46. package/jsconfig.json +9 -17
  47. package/package.json +61 -63
  48. package/regex.js +36 -0
  49. package/{src/lib/components → stylesheets}/DefaultStyles.css +5 -5
  50. package/utils.js +10 -0
  51. package/.cache.json +0 -1
  52. package/.prettierrc +0 -8
  53. package/.vscode/settings.json +0 -3
  54. package/CHANGELOG.md +0 -79
  55. package/server.js +0 -87
  56. package/src/app.d.ts +0 -12
  57. package/src/app.html +0 -13
  58. package/src/lib/components/Breadcrumbs.svelte +0 -19
  59. package/src/lib/components/ConditionalWrapper.svelte +0 -10
  60. package/src/lib/components/DefaultStyles.svelte +0 -11
  61. package/src/lib/components/FrontMatterTaxonomy.svelte +0 -48
  62. package/src/lib/components/Frontmatter.svelte +0 -56
  63. package/src/lib/components/FrontmatterProperty.svelte +0 -78
  64. package/src/lib/components/Markdown/Image.svelte +0 -50
  65. package/src/lib/components/Markdown/Link.svelte +0 -19
  66. package/src/lib/components/Markdown/LinkPreview.svelte +0 -45
  67. package/src/lib/components/Markdown/Text.svelte +0 -6
  68. package/src/lib/components/Markdown/index.svelte +0 -147
  69. package/src/lib/components/Markdown/validators.js +0 -29
  70. package/src/lib/components/Nav.svelte +0 -40
  71. package/src/lib/components/NoStyles.svelte +0 -5
  72. package/src/lib/components/Page.svelte +0 -90
  73. package/src/lib/components/ResetStyles.svelte +0 -7
  74. package/src/lib/components/Sitemap.svelte +0 -38
  75. package/src/lib/components/TypographyStyles.svelte +0 -10
  76. package/src/lib/components/index.js +0 -12
  77. package/src/lib/index.js +0 -1
  78. package/src/lib/utilities/buildURL.js +0 -18
  79. package/src/lib/utilities/checkFileExists.js +0 -16
  80. package/src/lib/utilities/createFolderClass.js +0 -4
  81. package/src/lib/utilities/createPageClass.js +0 -6
  82. package/src/lib/utilities/getFileLabel.js +0 -35
  83. package/src/lib/utilities/getFolder.js +0 -16
  84. package/src/lib/utilities/getFolderLabel.js +0 -12
  85. package/src/lib/utilities/getMetadata.js +0 -46
  86. package/src/lib/utilities/getPage.js +0 -25
  87. package/src/lib/utilities/getPagesByFolder.js +0 -95
  88. package/src/lib/utilities/index.js +0 -22
  89. package/src/lib/utilities/isActiveLink.js +0 -12
  90. package/src/lib/utilities/isObject.js +0 -8
  91. package/src/lib/utilities/loadCache.js +0 -28
  92. package/src/lib/utilities/mutateMarkdownAST.js +0 -68
  93. package/src/lib/utilities/mutateMarkdownFrontmatter.js +0 -113
  94. package/src/lib/utilities/parseDate.js +0 -43
  95. package/src/lib/utilities/processMarkdownFiles.js +0 -243
  96. package/src/lib/utilities/readMarkdownFile.js +0 -188
  97. package/src/lib/utilities/regexPatterns.js +0 -12
  98. package/src/lib/utilities/resolveHomeDirPath.js +0 -5
  99. package/src/lib/utilities/sendWebmention.js +0 -34
  100. package/src/lib/utilities/writeCache.js +0 -14
  101. package/src/routes/$vowel/published.json/+server.js +0 -54
  102. package/src/routes/+error.svelte +0 -110
  103. package/src/routes/[...path]/+layout.server.js +0 -78
  104. package/src/routes/[...path]/+page.server.js +0 -42
  105. package/src/routes/[...path]/+page.svelte +0 -186
  106. package/src/routes/feed.xml/+server.js +0 -120
  107. package/src/routes/robots.txt/+server.js +0 -54
  108. package/src/routes/sitemap.xml/+server.js +0 -68
  109. package/static/favicon.png +0 -0
  110. package/static/styles.css +0 -0
  111. package/svelte.config.js +0 -30
  112. package/vercel.json +0 -5
  113. package/vite.config.js +0 -84
  114. /package/{src/lib/components → stylesheets}/ResetStyles.css +0 -0
  115. /package/{src/lib/components → stylesheets}/TypographyStyles.css +0 -0
@@ -1,16 +0,0 @@
1
- export default function getFolder(website, path) {
2
- const dotPath = path
3
- .replace(/^\//, '') // Remove preceding slash
4
- .replace(/\/$/, '') // Remove trailing slash
5
- .replaceAll('/', '.'); // Convert to dots
6
-
7
- let drill = website;
8
-
9
- dotPath.split('.').forEach((segment) => {
10
- if (segment) {
11
- drill = drill[segment];
12
- }
13
- });
14
-
15
- return drill;
16
- }
@@ -1,12 +0,0 @@
1
- import { getFileLabel } from '.';
2
-
3
- const fallBackLabel = 'Untitled';
4
-
5
- export default function getFolderLabel(folder, shorter, date) {
6
- if (typeof folder !== 'object') return 'Untitled';
7
- return (
8
- getFileLabel(folder['_'], shorter, date) ||
9
- getFileLabel(folder['$'], shorter, date) ||
10
- fallBackLabel
11
- );
12
- }
@@ -1,46 +0,0 @@
1
- import { XMLParser } from "fast-xml-parser"
2
- import urlMetadata from 'url-metadata';
3
-
4
- export default async function getMetadata({ cache, url }) {
5
- if (!cache[url]) {
6
- try {
7
- const urlObject = new URL(url);
8
- const allMetadata = await urlMetadata(urlObject.href, {
9
- includeResponseBody: true,
10
- ensureSecureImageRequest: true
11
- });
12
-
13
- const parser = new XMLParser({
14
- unpairedTags: ["!doctype", "meta", "link", "hr", "br", "img"],
15
- ignoreAttributes: false,
16
- stopNodes: ["*.pre", "*.script"],
17
- processEntities: true,
18
- htmlEntities: true
19
- })
20
-
21
- let parsedData = parser.parse(allMetadata.responseBody)
22
- const webmentionEndpoint = parsedData?.html?.head?.link?.find(link => {
23
- return link["@_rel"] === "webmention"
24
- })?.["@_href"]
25
-
26
- const metadata = {
27
- image: allMetadata['og:image'],
28
- ogURL: allMetadata['og:url'],
29
- canonicalURL: allMetadata.canonical,
30
- title: allMetadata.title,
31
- ogTitle: allMetadata['og:title'],
32
- author: allMetadata.author,
33
- description: allMetadata.description,
34
- webmentionEndpoint
35
- };
36
-
37
- cache[url] = metadata;
38
-
39
- return { metadata }
40
- } catch (error) {
41
- console.log({ fetchingMetadataError: error })
42
- return { metadata: undefined }
43
- }
44
- }
45
- return { metadata: cache[url] }
46
- }
@@ -1,25 +0,0 @@
1
- // import objectPath from 'object-path';
2
-
3
- /**
4
- * Takes a file URL and a website object and returns the file object.
5
- * @param {import('./processMarkdownFiles').Directory} website - A website object.
6
- * @param {string} path - A `/`-delimited filepath.
7
- * @returns {import('./processMarkdownFiles').MarkdownFile}
8
- */
9
- export default function getPage(website, path) {
10
- let page = website;
11
-
12
- // const dotPath = path.replace(/^\//, '').replaceAll('/', '.') + (path ? '.' : '') + '$';
13
-
14
- const segments = path
15
- .replace(/^\//, '')
16
- .concat(path ? '/$' : '$')
17
- .split('/');
18
-
19
- segments.forEach((segment) => {
20
- if (segment === '_') return page[segment];
21
- if (typeof page === 'object' && page !== null) page = page[segment];
22
- });
23
-
24
- return page;
25
- }
@@ -1,95 +0,0 @@
1
- // @ts-ignore
2
- import { getFolder, getFileLabel } from '.';
3
-
4
- // @ts-ignore
5
- const excludedFileNames = ['_'];
6
-
7
- /**
8
- * Traverse a folder to get all of the pages.
9
- * @param {import('./processMarkdownFiles').Directory} folder - The path to the folder to retrieve.
10
- * @param {boolean} root - Whether this is the root of the recursion.
11
- * @returns {Array<Page>}
12
- */
13
- function traverseFolder(folder, root = false, property = '.') {
14
- let propertyKey = (property || '.').split('.')[0];
15
- let propertyValue = (property || '.').split('.')[1];
16
-
17
- let pages = [];
18
-
19
- for (let key in folder) {
20
- if (!key.startsWith('$') || key.length === 1) {
21
- if (key === '$') {
22
- if (!root) {
23
- if (propertyKey) {
24
- if (
25
- folder[key].hasOwnProperty(propertyKey) &&
26
- folder[key][propertyKey] === propertyValue
27
- ) {
28
- pages.push(folder[key]);
29
- }
30
- } else {
31
- pages.push(folder[key]);
32
- }
33
- }
34
- // if (
35
- // !root &&
36
- // folder[key].$?.hasOwnProperty(propertyKey) &&
37
- // folder[key][propertyKey] === propertyValue
38
- // )
39
- // pages.push(folder[key]);
40
- } else if (key !== '_') {
41
- const child = folder[key];
42
-
43
- // @ts-ignore
44
- pages.push(...traverseFolder(child, false, property));
45
- }
46
- }
47
- }
48
-
49
- // @ts-ignore
50
- return pages;
51
- }
52
-
53
- /**
54
- * Description
55
- * @param {Page} a
56
- * @param {Page} b
57
- * @returns {number}
58
- */
59
- function sortPage(a, b) {
60
- if (a.hasOwnProperty('date') && !b.hasOwnProperty('date')) return -1;
61
- else if (!a.hasOwnProperty('date') && b.hasOwnProperty('date')) return 1;
62
- else if (a.date && b.date) {
63
- const aDate = Number(new Date(a.date.output));
64
- const bDate = Number(new Date(b.date.output));
65
- return bDate - aDate;
66
- } else if (getFileLabel(a) > getFileLabel(b)) return 1;
67
- return -1;
68
- }
69
-
70
- /**
71
- * @typedef {import('./processMarkdownFiles').MarkdownFile} Page
72
- */
73
-
74
- /**
75
- * Recursively get all of the pages in a folder.
76
- * @param {import('./processMarkdownFiles').Directory} website - The entire website.
77
- * @param {string} path - The path to the folder to retrieve.
78
- * @param {number | undefined} count - Number of pages to return.
79
- * @returns {Array<Page>}
80
- */
81
- export default function getPagesByFolder(
82
- website,
83
- path,
84
- excludeRoot = true,
85
- count = undefined,
86
- property
87
- ) {
88
- const folder = getFolder(website, path);
89
-
90
- const pages = traverseFolder(folder, excludeRoot, property);
91
-
92
- pages.sort(sortPage);
93
-
94
- return pages.slice(0, count);
95
- }
@@ -1,22 +0,0 @@
1
- export { default as getPage } from './getPage';
2
- export { default as getFileLabel } from './getFileLabel';
3
- export { default as getFolderLabel } from './getFolderLabel';
4
- export { default as getFolder } from './getFolder';
5
- export { default as getPagesByFolder } from './getPagesByFolder';
6
- export { default as buildURL } from './buildURL';
7
- export { default as checkFileExists } from './checkFileExists';
8
- export { default as writeCache } from './writeCache';
9
- export { default as readMarkdownFile } from './readMarkdownFile';
10
- export { default as processMarkdownFiles } from './processMarkdownFiles';
11
- export { default as loadCache } from './loadCache';
12
- export { default as mutateMarkdownFrontmatter } from './mutateMarkdownFrontmatter';
13
- export { default as isObject } from './isObject';
14
- export { default as regexPatterns } from './regexPatterns';
15
- export { default as mutateMarkdownAST } from './mutateMarkdownAST';
16
- export { default as parseDate } from './parseDate';
17
- export { default as resolveHomeDirPath } from './resolveHomeDirPath';
18
- export { default as createPageClass } from './createPageClass';
19
- export { default as createFolderClass } from './createFolderClass';
20
- export { default as isActiveLink } from './isActiveLink';
21
- export { default as sendWebmention } from "./sendWebmention"
22
- export { default as getMetadata } from "./getMetadata"
@@ -1,12 +0,0 @@
1
- export default function isActiveLink(segments, key) {
2
- if (!segments?.[0] && !key) {
3
- return 'page';
4
- }
5
- if (segments.length === 1 && segments[0] === key) {
6
- return 'page';
7
- }
8
- if (segments.length > 1 && segments[0] === key) {
9
- return 'true';
10
- }
11
- return undefined;
12
- }
@@ -1,8 +0,0 @@
1
- /**
2
- * Check if a value is an object
3
- * @param {any} value - Value to check.
4
- * @returns {boolean}
5
- */
6
- export default function isObject(value) {
7
- return typeof value === 'object' && !Array.isArray(value) && value !== null;
8
- }
@@ -1,28 +0,0 @@
1
- import fs from 'fs/promises';
2
- import resolveHomeDirPath from './resolveHomeDirPath';
3
-
4
- /**
5
- * @typedef {Object<string, object>} Cache
6
- * @description A map of URLs to their metadata.
7
- */
8
-
9
- /**
10
- * Load a cache of URLs
11
- * @returns {Promise<Cache>}
12
- */
13
- export default async function loadCache(homeDir) {
14
- const cachePath = resolveHomeDirPath('.cache.json', homeDir);
15
-
16
- try {
17
- let data = await fs.readFile(cachePath);
18
- return JSON.parse(data);
19
- } catch (error) {
20
- if (error.code === 'ENOENT') {
21
- await fs.writeFile(cachePath, '{}', 'utf8');
22
- console.log('.cache.json created');
23
- } else {
24
- throw error;
25
- }
26
- }
27
- return {};
28
- }
@@ -1,68 +0,0 @@
1
- import { sendWebmention, getMetadata } from './';
2
-
3
- function isURL(string) {
4
- try {
5
- new URL(string)
6
- return true
7
- } catch (e) {
8
- return false
9
- }
10
- }
11
-
12
-
13
-
14
- export default async function mutateMarkdownAST(ast, cache, webmentions, pageURL) {
15
- const promises = ast.map(async (node) => {
16
- // TODO: Improve this URL regex
17
- if (node.type === 'paragraph') {
18
-
19
- // URLs
20
- if (
21
- node.children?.length === 1 &&
22
- node.children?.[0]?.type === "link" &&
23
- node.children?.[0]?.children?.length === 1
24
- ) {
25
- node.type = 'url';
26
- const { url } = node.children[0];
27
- node.url = url
28
-
29
- const { metadata } = await getMetadata({ cache, url })
30
-
31
- node.metadata = metadata;
32
- node.value = url;
33
- delete node.children;
34
-
35
- try {
36
- console.log("Looking for webmentions")
37
- if (webmentions && !webmentions.find(webmention => webmention.target === url)) {
38
- console.log("Found new page")
39
- webmentions.push({
40
- target: url,
41
- status: "new"
42
- })
43
- } else if (webmentions) {
44
- console.log("Found new webmention")
45
- const webmention = webmentions.find(webmention => webmention.target === url)
46
- if (webmention.status === "new" || webmention.status === "failure" || webmention.status === "429") {
47
- console.log("Sending webmention")
48
- webmention.status = await sendWebmention({ endpoint: metadata.webmentionEndpoint, target: webmention.target, source: pageURL })
49
- }
50
- }
51
- } catch (error) {
52
- console.log({ webmentionError: error })
53
- }
54
- } else if (node.children[0].type === 'image') {
55
- node.type = 'figure';
56
- if (node?.children[1]?.type === 'text') {
57
- node.children[1].type = 'figcaption';
58
- }
59
- }
60
- }
61
-
62
- if (node.children) {
63
- await mutateMarkdownAST(node.children, cache);
64
- }
65
- });
66
-
67
- await Promise.all(promises);
68
- }
@@ -1,113 +0,0 @@
1
- import urlMetadata from 'url-metadata';
2
- import { regexPatterns, isObject, parseDate, sendWebmention, getMetadata } from '.';
3
-
4
- /**
5
- * Description
6
- * @param {any} value - Any frontmatter value
7
- * @returns {any}
8
- */
9
- function imputeType(value) {
10
- if (value === null || value === undefined || Number.isNaN(value)) return 'nullish';
11
- if (typeof value === 'boolean') return 'boolean';
12
- if (typeof value === 'number') return 'number';
13
- if (parseDate(value)) return 'date';
14
- if (isObject(value)) return 'object';
15
- if (Array.isArray(value)) return 'array';
16
- if (typeof value === 'string') {
17
- if (value.match(regexPatterns.img)) return 'image';
18
- if (value.match(regexPatterns.pdf)) return 'pdf';
19
- if (value.match(regexPatterns.url)) return 'url';
20
- if (value.match(regexPatterns.path)) return 'path';
21
- return 'string';
22
- }
23
- console.error('Unknown frontmatter data type: ' + value);
24
- return 'other';
25
- }
26
-
27
- export default async function mutateMarkdownFrontmatter(frontmatter, cache, webmentions, pageURL) {
28
- const keys = Object.keys(frontmatter);
29
-
30
- const promises = keys.map(async (key) => {
31
- const input = frontmatter[key];
32
-
33
- const type = imputeType(input);
34
-
35
- switch (type) {
36
- case 'object': {
37
- await mutateMarkdownFrontmatter(input, cache);
38
- frontmatter[key] = {
39
- type: 'object',
40
- output: input
41
- };
42
- break;
43
- }
44
- case 'array': {
45
- await mutateMarkdownFrontmatter(input, cache);
46
- frontmatter[key] = {
47
- type: 'array',
48
- output: input
49
- };
50
- break;
51
- }
52
- case 'date': {
53
- frontmatter[key] = {
54
- type: 'date',
55
- output: parseDate(input),
56
- input
57
- };
58
- break;
59
- }
60
- case 'image': {
61
- frontmatter[key] = {
62
- type: 'image',
63
- output: input,
64
- input
65
- };
66
- break;
67
- }
68
- case 'pdf': {
69
- frontmatter[key] = {
70
- type: 'pdf',
71
- output: input,
72
- input
73
- };
74
- break;
75
- }
76
- case 'url': {
77
- const { metadata } = await getMetadata({
78
- cache,
79
- url: input
80
- })
81
-
82
- frontmatter[key] = {
83
- type: 'url',
84
- output: metadata || input,
85
- input
86
- };
87
-
88
- try {
89
- if (webmentions && !webmentions.find(webmention => webmention.target === input)) {
90
- webmentions.push({
91
- target: input,
92
- status: "new"
93
- })
94
- } else if (webmentions) {
95
- const webmention = webmentions.find(webmention => webmention.target === input)
96
- if (webmention.status === "new") {
97
- webmention.status = await sendWebmention({ endpoint: metadata.webmentionEndpoint, target: webmention.target, source: pageURL })
98
- }
99
- }
100
-
101
- } catch (error) {
102
- console.log({ webmentionsError: error })
103
- }
104
- break;
105
- }
106
- case 'nullish': {
107
- frontmatter[key] = undefined;
108
- }
109
- }
110
- });
111
-
112
- await Promise.all(promises);
113
- }
@@ -1,43 +0,0 @@
1
- import dates from 'any-date-parser';
2
- import ago from 'any-date-parser/src/formats/ago/ago.js';
3
- import chinese from 'any-date-parser/src/formats/chinese/chinese.js';
4
- import dayMonth from 'any-date-parser/src/formats/dayMonth/dayMonth.js';
5
- import dayMonthname from 'any-date-parser/src/formats/dayMonthname/dayMonthname.js';
6
- import monthDay from 'any-date-parser/src/formats/monthDay/monthDay.js';
7
- import monthnameDay from 'any-date-parser/src/formats/monthnameDay/monthnameDay.js';
8
- import today from 'any-date-parser/src/formats/today/today.js';
9
-
10
- dates.removeFormat(ago);
11
- dates.removeFormat(chinese);
12
- dates.removeFormat(dayMonth);
13
- dates.removeFormat(dayMonthname);
14
- dates.removeFormat(monthDay);
15
- dates.removeFormat(monthnameDay);
16
- dates.removeFormat(today);
17
-
18
- /*
19
- Left in the following formats:
20
-
21
- microsoftJson
22
- dayMonthYear
23
- dayMonthnameYear
24
- monthDayYear
25
- monthnameDayYear
26
- twitter
27
- yearMonthDay
28
- atSeconds
29
- time12Hours
30
- time24Hours
31
- */
32
-
33
- export default function parseDate(maybeDate) {
34
- if (!maybeDate) return false;
35
- if (maybeDate instanceof Date) return maybeDate;
36
- if (typeof maybeDate === 'number') return false;
37
- if (typeof maybeDate === 'string' && maybeDate.match(/^\d+$/)) return false;
38
- const parsedDate = dates.attempt(maybeDate);
39
- if (parsedDate.invalid) return false;
40
- const { month, day, year } = parsedDate;
41
- const date = new Date(`${year}-${month}-${day}`);
42
- return date;
43
- }