-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathsvelte.config.js
189 lines (163 loc) · 5.45 KB
/
svelte.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// svelte.config.js
import adapter from "@sveltejs/adapter-static";
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
import { mdsvex } from "mdsvex";
import classNames from "rehype-class-names";
import rehypeTitleFigure from "rehype-title-figure";
import smartypants from "remark-smartypants";
import { visit } from "unist-util-visit";
const classNamesOptions = {
h2: "section",
h3: "subsection",
h4: "subsubsection",
a: "link",
figure: "figure",
};
const LOGGING = false;
function debugLog(message) {
if (LOGGING) {
console.log(message);
}
};
// Function to transform image paths correctly for blog posts
const blogImages = () => {
return (tree, file) => {
// Get the blog post slug from the file path
const routePath = file.filename.split("routes")[1] || "";
const blogMatch = routePath.match(/\/blog\/([^/]+)/);
debugLog(`[BlogImages] Processing file: ${file.filename}`);
// Only process blog post files
if (blogMatch && blogMatch[1]) {
const slug = blogMatch[1];
debugLog(`[BlogImages] Detected blog slug: ${slug}`);
// Process both image nodes and raw HTML nodes
// First, handle regular image nodes
visit(tree, "image", (node) => {
// Store the original URL for debugging
const originalUrl = node.url;
// Skip external URLs
if (node.url.startsWith("http")) {
debugLog(`[BlogImages] Keeping external URL: ${node.url}`);
return;
}
// Skip absolute paths outside of blog
if (node.url.startsWith("/") && !node.url.startsWith("/blog/")) {
debugLog(`[BlogImages] Keeping absolute path: ${node.url}`);
return;
}
// For all other cases, ensure the image has the correct blog post slug prefix
const cleanPath = node.url.startsWith("./")
? node.url.slice(2)
: node.url;
// Always use the pattern /blog/[slug]/[image.png]
if (node.url.startsWith(`/blog/${slug}/`)) {
debugLog(`[BlogImages] URL already has correct format: ${node.url}`);
} else {
node.url = `/blog/${slug}/${cleanPath}`;
debugLog(
`[BlogImages] Transformed to: ${node.url} (was: ${originalUrl})`
);
}
});
// Then handle raw HTML to catch any embedded <img> tags
visit(tree, "html", (node) => {
if (node.value && node.value.includes("<img")) {
const originalHtml = node.value;
// Simple regex to transform image src attributes
// This is a basic approach - for a production system you'd want to use a proper HTML parser
node.value = node.value.replace(/src="([^"]+)"/g, (match, src) => {
// Skip external URLs and absolute paths
if (
src.startsWith("http") ||
(src.startsWith("/") && !src.startsWith("/blog/"))
) {
return match;
}
// Clean the path
const cleanPath = src.startsWith("./") ? src.slice(2) : src;
// Create the new src with blog slug
const newSrc = `/blog/${slug}/${cleanPath}`;
debugLog(`[BlogImages] Transformed HTML img: ${src} -> ${newSrc}`);
return `src="${newSrc}"`;
});
if (originalHtml !== node.value) {
debugLog("[BlogImages] HTML node was transformed");
}
}
});
} else {
debugLog(
`[BlogImages] Not a blog post, skipping image path transformation`
);
}
};
};
const escapeQuotes = () => {
return (tree) => {
visit(tree, "image", (node) => {
if (node.alt) {
node.alt = node.alt.replace(/"/g, """);
}
});
};
};
const processMetadata = () => {
return (tree, file) => {
const { data } = file;
if (!data.fm) return;
// Ensure tags is always an array
if (typeof data.fm.tags === "string") {
data.fm.tags = data.fm.tags.split(",").map((tag) => tag.trim());
} else if (!Array.isArray(data.fm.tags)) {
data.fm.tags = [];
}
// Ensure author is properly formatted
if (typeof data.fm.author === "string") {
data.fm.author = [data.fm.author];
} else if (!Array.isArray(data.fm.author)) {
data.fm.author = [];
}
// Update the frontmatter with processed data
file.data.fm = data.fm;
};
};
/** @type {import('mdsvex').MdsvexOptions} */
const mdsvexOptions = {
extensions: [".md"],
remarkPlugins: [smartypants, escapeQuotes, processMetadata, blogImages],
rehypePlugins: [rehypeTitleFigure, [classNames, classNamesOptions]],
layout: {
blog: "src/lib/blocks/Post.svelte",
},
};
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter({
precompress: false,
strict: false, // Allow dynamic routes
}),
prerender: {
handleHttpError: "warn",
handleMissingId: "ignore",
entries: ["*"],
},
paths: {
base: process.env.NODE_ENV === "production" ? "" : "",
},
},
extensions: [".svelte", ".md"],
preprocess: [mdsvex(mdsvexOptions), vitePreprocess()],
// Omit warning about screenreaders announcing <img> elements as an image
onwarn: (warning, handler) => {
// Omit the warning about redundant alt text if we are on development mode
if (
warning.code === "a11y-img-redundant-alt" &&
warning.message.includes("Screenreaders already announce")
) {
return;
}
handler(warning);
},
};
export default config;