@jant/core 0.3.36 → 0.3.38
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/bin/commands/export.js +1 -1
- package/bin/commands/import-site.js +529 -0
- package/bin/commands/reset-password.js +3 -2
- package/dist/client/assets/heic-to-DIRPI3VF.js +1 -0
- package/dist/client/assets/url-FWFqPJPb.js +1 -0
- package/dist/client/client.css +1 -1
- package/dist/client/client.js +4012 -3276
- package/dist/index.js +10285 -5809
- package/package.json +11 -3
- package/src/__tests__/helpers/app.ts +9 -9
- package/src/__tests__/helpers/db.ts +91 -93
- package/src/app.tsx +157 -27
- package/src/auth.ts +20 -2
- package/src/client/archive-nav.js +187 -0
- package/src/client/audio-player.ts +478 -0
- package/src/client/audio-processor.ts +84 -0
- package/src/client/avatar-upload.ts +3 -2
- package/src/client/components/__tests__/jant-compose-dialog.test.ts +645 -49
- package/src/client/components/__tests__/jant-compose-editor.test.ts +208 -16
- package/src/client/components/__tests__/jant-post-form.test.ts +19 -9
- package/src/client/components/__tests__/jant-settings-avatar.test.ts +2 -2
- package/src/client/components/__tests__/jant-settings-general.test.ts +3 -3
- package/src/client/components/collection-sidebar-types.ts +7 -9
- package/src/client/components/compose-types.ts +101 -4
- package/src/client/components/jant-collection-form.ts +43 -7
- package/src/client/components/jant-collection-sidebar.ts +88 -84
- package/src/client/components/jant-compose-dialog.ts +1655 -219
- package/src/client/components/jant-compose-editor.ts +732 -168
- package/src/client/components/jant-compose-fullscreen.ts +23 -78
- package/src/client/components/jant-media-lightbox.ts +2 -0
- package/src/client/components/jant-nav-manager.ts +24 -284
- package/src/client/components/jant-post-form.ts +89 -9
- package/src/client/components/jant-post-menu.ts +1019 -0
- package/src/client/components/jant-settings-avatar.ts +3 -3
- package/src/client/components/jant-settings-general.ts +38 -4
- package/src/client/components/jant-text-preview.ts +232 -0
- package/src/client/components/nav-manager-types.ts +4 -19
- package/src/client/components/post-form-template.ts +107 -12
- package/src/client/components/post-form-types.ts +11 -4
- package/src/client/compose-bridge.ts +410 -109
- package/src/client/image-processor.ts +26 -8
- package/src/client/media-metadata.ts +247 -0
- package/src/client/multipart-upload.ts +160 -0
- package/src/client/post-form-bridge.ts +52 -1
- package/src/client/settings-bridge.ts +0 -12
- package/src/client/thread-context.ts +140 -0
- package/src/client/tiptap/create-editor.ts +46 -0
- package/src/client/tiptap/extensions.ts +5 -0
- package/src/client/tiptap/image-node.ts +2 -8
- package/src/client/tiptap/paste-image.ts +2 -13
- package/src/client/tiptap/slash-commands.ts +173 -63
- package/src/client/toast.ts +101 -3
- package/src/client/types/sortablejs.d.ts +15 -0
- package/src/client/upload-with-metadata.ts +54 -0
- package/src/client/video-processor.ts +207 -0
- package/src/client.ts +5 -2
- package/src/db/__tests__/migrations.test.ts +118 -0
- package/src/db/index.ts +52 -0
- package/src/db/migrations/0000_baseline.sql +269 -0
- package/src/db/migrations/0001_fts_setup.sql +31 -0
- package/src/db/migrations/meta/0000_snapshot.json +703 -119
- package/src/db/migrations/meta/0001_snapshot.json +1337 -0
- package/src/db/migrations/meta/_journal.json +4 -39
- package/src/db/schema.ts +409 -145
- package/src/i18n/__tests__/detect.test.ts +115 -0
- package/src/i18n/context.tsx +2 -2
- package/src/i18n/detect.ts +85 -1
- package/src/i18n/i18n.ts +1 -1
- package/src/i18n/index.ts +2 -1
- package/src/i18n/locales/en.po +487 -1217
- package/src/i18n/locales/en.ts +1 -1
- package/src/i18n/locales/zh-Hans.po +613 -996
- package/src/i18n/locales/zh-Hans.ts +1 -1
- package/src/i18n/locales/zh-Hant.po +624 -1007
- package/src/i18n/locales/zh-Hant.ts +1 -1
- package/src/i18n/middleware.ts +6 -0
- package/src/index.ts +5 -7
- package/src/lib/__tests__/blurhash-placeholder.test.ts +75 -0
- package/src/lib/__tests__/constants.test.ts +0 -1
- package/src/lib/__tests__/markdown-to-tiptap.test.ts +358 -0
- package/src/lib/__tests__/nanoid.test.ts +26 -0
- package/src/lib/__tests__/schemas.test.ts +181 -63
- package/src/lib/__tests__/slug.test.ts +126 -0
- package/src/lib/__tests__/sse.test.ts +6 -6
- package/src/lib/__tests__/summary.test.ts +264 -0
- package/src/lib/__tests__/theme.test.ts +1 -1
- package/src/lib/__tests__/timeline.test.ts +33 -30
- package/src/lib/__tests__/tiptap-to-markdown.test.ts +346 -0
- package/src/lib/__tests__/view.test.ts +141 -66
- package/src/lib/blurhash-placeholder.ts +102 -0
- package/src/lib/constants.ts +3 -1
- package/src/lib/emoji-catalog.ts +885 -68
- package/src/lib/errors.ts +11 -8
- package/src/lib/feed.ts +78 -32
- package/src/lib/html.ts +2 -1
- package/src/lib/icon-catalog.ts +5033 -1
- package/src/lib/icons.ts +3 -2
- package/src/lib/index.ts +0 -1
- package/src/lib/markdown-to-tiptap.ts +286 -0
- package/src/lib/media-helpers.ts +12 -3
- package/src/lib/nanoid.ts +29 -0
- package/src/lib/navigation.ts +1 -1
- package/src/lib/render.tsx +20 -2
- package/src/lib/resolve-config.ts +6 -2
- package/src/lib/schemas.ts +224 -55
- package/src/lib/search-snippet.ts +34 -0
- package/src/lib/slug.ts +96 -0
- package/src/lib/sse.ts +6 -6
- package/src/lib/storage.ts +115 -7
- package/src/lib/summary.ts +66 -0
- package/src/lib/theme.ts +11 -8
- package/src/lib/timeline.ts +74 -34
- package/src/lib/tiptap-render.ts +5 -10
- package/src/lib/tiptap-to-markdown.ts +305 -0
- package/src/lib/upload.ts +190 -29
- package/src/lib/url.ts +31 -0
- package/src/lib/view.ts +204 -37
- package/src/middleware/__tests__/auth.test.ts +191 -11
- package/src/middleware/__tests__/onboarding.test.ts +12 -10
- package/src/middleware/auth.ts +63 -9
- package/src/middleware/onboarding.ts +1 -1
- package/src/middleware/secure-headers.ts +40 -0
- package/src/preset.css +45 -2
- package/src/routes/__tests__/compose.test.ts +17 -24
- package/src/routes/api/__tests__/collections.test.ts +109 -61
- package/src/routes/api/__tests__/nav-items.test.ts +46 -29
- package/src/routes/api/__tests__/posts.test.ts +132 -68
- package/src/routes/api/__tests__/search.test.ts +15 -2
- package/src/routes/api/__tests__/upload-multipart.test.ts +534 -0
- package/src/routes/api/collections.ts +51 -42
- package/src/routes/api/custom-urls.ts +80 -0
- package/src/routes/api/export.ts +31 -0
- package/src/routes/api/nav-items.ts +23 -19
- package/src/routes/api/posts.ts +43 -39
- package/src/routes/api/search.ts +3 -4
- package/src/routes/api/upload-multipart.ts +245 -0
- package/src/routes/api/upload.ts +85 -19
- package/src/routes/auth/__tests__/setup.test.ts +20 -60
- package/src/routes/auth/setup.tsx +26 -33
- package/src/routes/auth/signin.tsx +3 -7
- package/src/routes/compose.tsx +10 -55
- package/src/routes/dash/__tests__/settings-avatar.test.ts +1 -1
- package/src/routes/dash/custom-urls.tsx +414 -0
- package/src/routes/dash/settings.tsx +304 -232
- package/src/routes/feed/__tests__/rss.test.ts +27 -28
- package/src/routes/feed/rss.ts +6 -4
- package/src/routes/feed/sitemap.ts +2 -12
- package/src/routes/pages/__tests__/collections.test.ts +5 -6
- package/src/routes/pages/__tests__/featured.test.ts +41 -22
- package/src/routes/pages/archive.tsx +175 -39
- package/src/routes/pages/collection.tsx +22 -10
- package/src/routes/pages/collections.tsx +3 -3
- package/src/routes/pages/featured.tsx +28 -4
- package/src/routes/pages/home.tsx +16 -15
- package/src/routes/pages/latest.tsx +1 -11
- package/src/routes/pages/new.tsx +39 -0
- package/src/routes/pages/page.tsx +95 -49
- package/src/routes/pages/search.tsx +1 -1
- package/src/services/__tests__/api-token.test.ts +135 -0
- package/src/services/__tests__/collection.test.ts +275 -227
- package/src/services/__tests__/custom-url.test.ts +213 -0
- package/src/services/__tests__/media.test.ts +162 -22
- package/src/services/__tests__/navigation.test.ts +109 -68
- package/src/services/__tests__/post-timeline.test.ts +205 -32
- package/src/services/__tests__/post.test.ts +713 -234
- package/src/services/__tests__/search.test.ts +67 -10
- package/src/services/api-token.ts +166 -0
- package/src/services/auth.ts +17 -2
- package/src/services/collection.ts +397 -131
- package/src/services/custom-url.ts +188 -0
- package/src/services/export.ts +802 -0
- package/src/services/index.ts +26 -19
- package/src/services/media.ts +100 -22
- package/src/services/navigation.ts +158 -47
- package/src/services/path.ts +339 -0
- package/src/services/post.ts +687 -154
- package/src/services/search.ts +160 -75
- package/src/styles/components.css +58 -7
- package/src/styles/tokens.css +84 -6
- package/src/styles/ui.css +2964 -457
- package/src/types/bindings.ts +4 -1
- package/src/types/config.ts +12 -4
- package/src/types/constants.ts +15 -3
- package/src/types/entities.ts +74 -35
- package/src/types/operations.ts +11 -24
- package/src/types/props.ts +51 -16
- package/src/types/views.ts +45 -22
- package/src/ui/color-themes.ts +133 -23
- package/src/ui/compose/ComposeDialog.tsx +239 -17
- package/src/ui/compose/ComposePrompt.tsx +1 -1
- package/src/ui/dash/CrudPageHeader.tsx +1 -1
- package/src/ui/dash/ListItemRow.tsx +1 -1
- package/src/ui/dash/StatusBadge.tsx +3 -1
- package/src/ui/dash/appearance/AdvancedContent.tsx +22 -1
- package/src/ui/dash/appearance/ColorThemeContent.tsx +22 -2
- package/src/ui/dash/appearance/FontThemeContent.tsx +1 -1
- package/src/ui/dash/appearance/NavigationContent.tsx +5 -45
- package/src/ui/dash/index.ts +0 -3
- package/src/ui/dash/settings/AccountContent.tsx +3 -57
- package/src/ui/dash/settings/AccountMenuContent.tsx +147 -0
- package/src/ui/dash/settings/ApiTokensContent.tsx +232 -0
- package/src/ui/dash/settings/AvatarContent.tsx +8 -0
- package/src/ui/dash/settings/SessionsContent.tsx +159 -0
- package/src/ui/dash/settings/SettingsRootContent.tsx +45 -15
- package/src/ui/feed/LinkCard.tsx +89 -40
- package/src/ui/feed/NoteCard.tsx +39 -25
- package/src/ui/feed/PostStatusBadges.tsx +67 -0
- package/src/ui/feed/QuoteCard.tsx +38 -23
- package/src/ui/feed/ThreadPreview.tsx +90 -26
- package/src/ui/feed/TimelineFeed.tsx +3 -2
- package/src/ui/feed/TimelineItem.tsx +15 -6
- package/src/ui/feed/__tests__/thread-preview.test.ts +107 -0
- package/src/ui/feed/thread-preview-state.ts +61 -0
- package/src/ui/font-themes.ts +2 -2
- package/src/ui/layouts/BaseLayout.tsx +2 -2
- package/src/ui/layouts/SiteLayout.tsx +105 -92
- package/src/ui/pages/ArchivePage.tsx +923 -98
- package/src/ui/pages/ComposePage.tsx +54 -0
- package/src/ui/pages/PostPage.tsx +30 -45
- package/src/ui/pages/SearchPage.tsx +181 -37
- package/src/ui/shared/AdminBreadcrumb.tsx +29 -0
- package/src/ui/shared/CollectionsSidebar.tsx +47 -37
- package/src/ui/shared/MediaGallery.tsx +445 -149
- package/src/ui/shared/PostFooter.tsx +204 -0
- package/src/ui/shared/StarRating.tsx +27 -0
- package/src/ui/shared/__tests__/format-chars.test.ts +35 -0
- package/src/ui/shared/index.ts +0 -1
- package/dist/client/assets/url-8Dj-5CLW.js +0 -1
- package/src/client/media-upload.ts +0 -161
- package/src/client/page-slug-bridge.ts +0 -42
- package/src/db/migrations/0000_square_wallflower.sql +0 -118
- package/src/db/migrations/0001_add_search_fts.sql +0 -34
- package/src/db/migrations/0002_add_media_attachments.sql +0 -3
- package/src/db/migrations/0003_add_navigation_links.sql +0 -8
- package/src/db/migrations/0004_add_storage_provider.sql +0 -3
- package/src/db/migrations/0005_v2_schema_migration.sql +0 -268
- package/src/db/migrations/0006_rename_slug_to_path.sql +0 -5
- package/src/db/migrations/0007_post_collections_m2m.sql +0 -94
- package/src/db/migrations/0008_add_collection_dividers.sql +0 -8
- package/src/db/migrations/0009_drop_collection_show_divider.sql +0 -2
- package/src/db/migrations/0010_add_performance_indexes.sql +0 -16
- package/src/db/migrations/0011_add_path_registry.sql +0 -23
- package/src/db/migrations/0012_add_tiptap_columns.sql +0 -2
- package/src/db/migrations/0013_replace_featured_with_visibility.sql +0 -8
- package/src/db/migrations/meta/0003_snapshot.json +0 -821
- package/src/lib/__tests__/sqid.test.ts +0 -65
- package/src/lib/sqid.ts +0 -79
- package/src/routes/api/__tests__/pages.test.ts +0 -218
- package/src/routes/api/pages.ts +0 -73
- package/src/routes/dash/__tests__/pages.test.ts +0 -226
- package/src/routes/dash/index.tsx +0 -109
- package/src/routes/dash/media.tsx +0 -135
- package/src/routes/dash/pages.tsx +0 -245
- package/src/routes/dash/posts.tsx +0 -338
- package/src/routes/dash/redirects.tsx +0 -263
- package/src/routes/pages/post.tsx +0 -59
- package/src/services/__tests__/page.test.ts +0 -298
- package/src/services/__tests__/path-registry.test.ts +0 -165
- package/src/services/__tests__/redirect.test.ts +0 -159
- package/src/services/page.ts +0 -216
- package/src/services/path-registry.ts +0 -160
- package/src/services/redirect.ts +0 -97
- package/src/ui/dash/PageForm.tsx +0 -187
- package/src/ui/dash/PostList.tsx +0 -95
- package/src/ui/dash/media/MediaListContent.tsx +0 -206
- package/src/ui/dash/media/ViewMediaContent.tsx +0 -208
- package/src/ui/dash/pages/PagesContent.tsx +0 -75
- package/src/ui/dash/posts/PostForm.tsx +0 -260
- package/src/ui/layouts/DashLayout.tsx +0 -247
- package/src/ui/pages/SinglePage.tsx +0 -23
- package/src/ui/shared/ThreadView.tsx +0 -136
package/src/lib/errors.ts
CHANGED
|
@@ -97,20 +97,23 @@ export function assertFound<T>(
|
|
|
97
97
|
return value;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
const UUID_RE =
|
|
101
|
+
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
102
|
+
|
|
100
103
|
/**
|
|
101
|
-
*
|
|
104
|
+
* Validates a route parameter as a UUID.
|
|
105
|
+
* Throws ValidationError if the format is invalid.
|
|
102
106
|
*
|
|
103
|
-
* @param value -
|
|
104
|
-
* @returns
|
|
107
|
+
* @param value - UUID string from the route
|
|
108
|
+
* @returns The validated UUID string
|
|
105
109
|
* @example
|
|
106
110
|
* ```ts
|
|
107
|
-
* const id =
|
|
111
|
+
* const id = parseIdParam(c.req.param("id"));
|
|
108
112
|
* ```
|
|
109
113
|
*/
|
|
110
|
-
export function
|
|
111
|
-
|
|
112
|
-
if (isNaN(id) || id < 1) {
|
|
114
|
+
export function parseIdParam(value: string): string {
|
|
115
|
+
if (!UUID_RE.test(value)) {
|
|
113
116
|
throw new ValidationError("Invalid ID");
|
|
114
117
|
}
|
|
115
|
-
return
|
|
118
|
+
return value;
|
|
116
119
|
}
|
package/src/lib/feed.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* ```
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import type { FeedData, SitemapData } from "../types.js";
|
|
13
|
+
import type { FeedData, PostView, SitemapData } from "../types.js";
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Escape special XML characters.
|
|
@@ -24,6 +24,67 @@ function escapeXml(str: string): string {
|
|
|
24
24
|
.replace(/'/g, "'");
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Escape content for safe embedding inside a CDATA section.
|
|
29
|
+
*
|
|
30
|
+
* CDATA sections end at the first `]]>` sequence. If the content contains
|
|
31
|
+
* `]]>`, we split it by closing the current CDATA section and opening a new
|
|
32
|
+
* one: `]]>` becomes `]]]]><![CDATA[>`.
|
|
33
|
+
*
|
|
34
|
+
* @param str - Raw string to embed in CDATA
|
|
35
|
+
* @returns String safe to place inside `<![CDATA[...]]>`
|
|
36
|
+
*/
|
|
37
|
+
function escapeCdata(str: string): string {
|
|
38
|
+
return str.replaceAll("]]>", "]]]]><![CDATA[>");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Render a star rating as HTML for feed content.
|
|
43
|
+
*/
|
|
44
|
+
function renderRatingHtml(rating: number): string {
|
|
45
|
+
const filled = "★".repeat(rating);
|
|
46
|
+
const empty = "☆".repeat(5 - rating);
|
|
47
|
+
return `<p>${filled}${empty} ${rating}/5</p>`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Build the full HTML content for a feed item, combining format-specific
|
|
52
|
+
* fields (quote text, source URL) with body and rating.
|
|
53
|
+
*/
|
|
54
|
+
function buildFeedContent(post: PostView): string {
|
|
55
|
+
const parts: string[] = [];
|
|
56
|
+
|
|
57
|
+
if (post.format === "quote" && post.quoteText) {
|
|
58
|
+
const attribution = post.title || post.url || "";
|
|
59
|
+
const cite = post.url ? ` cite="${escapeXml(post.url)}"` : "";
|
|
60
|
+
parts.push(
|
|
61
|
+
`<blockquote${cite}><p>${escapeXml(post.quoteText)}</p></blockquote>`,
|
|
62
|
+
);
|
|
63
|
+
if (attribution) {
|
|
64
|
+
const source = post.url
|
|
65
|
+
? `<a href="${escapeXml(post.url)}">${escapeXml(post.title || "Source")}</a>`
|
|
66
|
+
: escapeXml(attribution);
|
|
67
|
+
parts.push(`<p>— ${source}</p>`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (post.format === "link" && post.url) {
|
|
72
|
+
parts.push(
|
|
73
|
+
`<p><a href="${escapeXml(post.url)}">${escapeXml(post.url)}</a></p>`,
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (post.bodyHtml) {
|
|
78
|
+
parts.push(post.bodyHtml);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (post.rating && post.rating > 0) {
|
|
82
|
+
parts.push(renderRatingHtml(post.rating));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return parts.join("\n");
|
|
86
|
+
}
|
|
87
|
+
|
|
27
88
|
/**
|
|
28
89
|
* Default RSS 2.0 renderer.
|
|
29
90
|
*
|
|
@@ -35,23 +96,23 @@ export function defaultRssRenderer(data: FeedData): string {
|
|
|
35
96
|
|
|
36
97
|
const items = posts
|
|
37
98
|
.map((post) => {
|
|
38
|
-
const link = `${siteUrl}${post.permalink}
|
|
99
|
+
const link = escapeXml(`${siteUrl}${post.permalink}`);
|
|
39
100
|
const title = post.title || `Post #${post.id}`;
|
|
40
101
|
const pubDate = new Date(post.publishedAt).toUTCString();
|
|
41
102
|
|
|
42
103
|
// Add enclosure for first media attachment
|
|
43
104
|
const firstMedia = post.media[0];
|
|
44
105
|
const enclosure = firstMedia
|
|
45
|
-
? `\n <enclosure url="${firstMedia.url}" type="${firstMedia.mimeType}"${firstMedia.size ? ` length="${firstMedia.size}"` : ""}/>`
|
|
106
|
+
? `\n <enclosure url="${escapeXml(firstMedia.url)}" type="${escapeXml(firstMedia.mimeType)}"${firstMedia.size ? ` length="${firstMedia.size}"` : ""}/>`
|
|
46
107
|
: "";
|
|
47
108
|
|
|
48
109
|
return `
|
|
49
110
|
<item>
|
|
50
|
-
<title><![CDATA[${escapeXml(title)}]]></title>
|
|
111
|
+
<title><![CDATA[${escapeCdata(escapeXml(title))}]]></title>
|
|
51
112
|
<link>${link}</link>
|
|
52
113
|
<guid isPermaLink="true">${link}</guid>
|
|
53
114
|
<pubDate>${pubDate}</pubDate>
|
|
54
|
-
<description><![CDATA[${post
|
|
115
|
+
<description><![CDATA[${escapeCdata(buildFeedContent(post))}]]></description>${enclosure}
|
|
55
116
|
</item>`;
|
|
56
117
|
})
|
|
57
118
|
.join("");
|
|
@@ -60,10 +121,10 @@ export function defaultRssRenderer(data: FeedData): string {
|
|
|
60
121
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
|
61
122
|
<channel>
|
|
62
123
|
<title>${escapeXml(siteName)}</title>
|
|
63
|
-
<link>${siteUrl}</link>
|
|
124
|
+
<link>${escapeXml(siteUrl)}</link>
|
|
64
125
|
<description>${escapeXml(siteDescription)}</description>
|
|
65
126
|
<language>${siteLanguage}</language>
|
|
66
|
-
<atom:link href="${siteUrl}/feed" rel="self" type="application/rss+xml"/>
|
|
127
|
+
<atom:link href="${escapeXml(siteUrl)}/feed" rel="self" type="application/rss+xml"/>
|
|
67
128
|
${items}
|
|
68
129
|
</channel>
|
|
69
130
|
</rss>`;
|
|
@@ -80,7 +141,7 @@ export function defaultAtomRenderer(data: FeedData): string {
|
|
|
80
141
|
|
|
81
142
|
const entries = posts
|
|
82
143
|
.map((post) => {
|
|
83
|
-
const link = `${siteUrl}${post.permalink}
|
|
144
|
+
const link = escapeXml(`${siteUrl}${post.permalink}`);
|
|
84
145
|
const title = post.title || `Post #${post.id}`;
|
|
85
146
|
|
|
86
147
|
return `
|
|
@@ -90,7 +151,7 @@ export function defaultAtomRenderer(data: FeedData): string {
|
|
|
90
151
|
<id>${link}</id>
|
|
91
152
|
<published>${post.publishedAt}</published>
|
|
92
153
|
<updated>${post.updatedAt}</updated>
|
|
93
|
-
<content type="html"><![CDATA[${post
|
|
154
|
+
<content type="html"><![CDATA[${escapeCdata(buildFeedContent(post))}]]></content>
|
|
94
155
|
</entry>`;
|
|
95
156
|
})
|
|
96
157
|
.join("");
|
|
@@ -101,9 +162,9 @@ export function defaultAtomRenderer(data: FeedData): string {
|
|
|
101
162
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
|
102
163
|
<title>${escapeXml(siteName)}</title>
|
|
103
164
|
<subtitle>${escapeXml(siteDescription)}</subtitle>
|
|
104
|
-
<link href="${siteUrl}" rel="alternate"/>
|
|
105
|
-
<link href="${siteUrl}/feed/atom.xml" rel="self"/>
|
|
106
|
-
<id>${siteUrl}/</id>
|
|
165
|
+
<link href="${escapeXml(siteUrl)}" rel="alternate"/>
|
|
166
|
+
<link href="${escapeXml(siteUrl)}/feed/atom.xml" rel="self"/>
|
|
167
|
+
<id>${escapeXml(siteUrl)}/</id>
|
|
107
168
|
<updated>${now}</updated>
|
|
108
169
|
${entries}
|
|
109
170
|
</feed>`;
|
|
@@ -112,17 +173,17 @@ export function defaultAtomRenderer(data: FeedData): string {
|
|
|
112
173
|
/**
|
|
113
174
|
* Default Sitemap renderer.
|
|
114
175
|
*
|
|
115
|
-
* @param data - Sitemap data with PostView[]
|
|
176
|
+
* @param data - Sitemap data with PostView[]
|
|
116
177
|
* @returns Sitemap XML string
|
|
117
178
|
*/
|
|
118
179
|
export function defaultSitemapRenderer(data: SitemapData): string {
|
|
119
|
-
const { siteUrl, posts
|
|
180
|
+
const { siteUrl, posts } = data;
|
|
120
181
|
|
|
121
182
|
const postUrls = posts
|
|
122
183
|
.map((post) => {
|
|
123
|
-
const loc = `${siteUrl}${post.permalink}
|
|
184
|
+
const loc = escapeXml(`${siteUrl}${post.permalink}`);
|
|
124
185
|
const lastmod = post.updatedAt.split("T")[0];
|
|
125
|
-
const priority = post.
|
|
186
|
+
const priority = post.featured ? "0.8" : "0.6";
|
|
126
187
|
|
|
127
188
|
return `
|
|
128
189
|
<url>
|
|
@@ -133,23 +194,9 @@ export function defaultSitemapRenderer(data: SitemapData): string {
|
|
|
133
194
|
})
|
|
134
195
|
.join("");
|
|
135
196
|
|
|
136
|
-
const pageUrls = pages
|
|
137
|
-
.map((page) => {
|
|
138
|
-
const loc = `${siteUrl}/${page.slug}`;
|
|
139
|
-
const lastmod = page.updatedAt.split("T")[0];
|
|
140
|
-
|
|
141
|
-
return `
|
|
142
|
-
<url>
|
|
143
|
-
<loc>${loc}</loc>
|
|
144
|
-
<lastmod>${lastmod}</lastmod>
|
|
145
|
-
<priority>0.7</priority>
|
|
146
|
-
</url>`;
|
|
147
|
-
})
|
|
148
|
-
.join("");
|
|
149
|
-
|
|
150
197
|
const homepageUrl = `
|
|
151
198
|
<url>
|
|
152
|
-
<loc>${siteUrl}/</loc>
|
|
199
|
+
<loc>${escapeXml(siteUrl)}/</loc>
|
|
153
200
|
<priority>1.0</priority>
|
|
154
201
|
<changefreq>daily</changefreq>
|
|
155
202
|
</url>`;
|
|
@@ -158,6 +205,5 @@ export function defaultSitemapRenderer(data: SitemapData): string {
|
|
|
158
205
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
159
206
|
${homepageUrl}
|
|
160
207
|
${postUrls}
|
|
161
|
-
${pageUrls}
|
|
162
208
|
</urlset>`;
|
|
163
209
|
}
|