bunki 0.4.2 → 0.5.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/dist/cli.js +60 -34
- package/dist/index.js +60 -34
- package/dist/types.d.ts +2 -0
- package/dist/utils/markdown-utils.d.ts +1 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -32690,42 +32690,65 @@ core_default.registerLanguage("diff", diff);
|
|
|
32690
32690
|
core_default.registerLanguage("python", python);
|
|
32691
32691
|
core_default.registerLanguage("json", json);
|
|
32692
32692
|
core_default.registerLanguage("swift", swift);
|
|
32693
|
-
var
|
|
32694
|
-
|
|
32695
|
-
|
|
32696
|
-
|
|
32697
|
-
|
|
32698
|
-
|
|
32699
|
-
|
|
32700
|
-
})
|
|
32701
|
-
|
|
32702
|
-
|
|
32703
|
-
|
|
32704
|
-
|
|
32705
|
-
|
|
32706
|
-
|
|
32707
|
-
|
|
32708
|
-
|
|
32709
|
-
|
|
32710
|
-
|
|
32711
|
-
token.
|
|
32712
|
-
if (
|
|
32713
|
-
token.
|
|
32714
|
-
|
|
32715
|
-
|
|
32716
|
-
|
|
32717
|
-
|
|
32718
|
-
|
|
32719
|
-
preprocess(markdown2) {
|
|
32720
|
-
return markdown2;
|
|
32693
|
+
var noFollowExceptions = new Set;
|
|
32694
|
+
function createMarked() {
|
|
32695
|
+
const marked = new B(markedHighlight({
|
|
32696
|
+
emptyLangClass: "hljs",
|
|
32697
|
+
langPrefix: "hljs language-",
|
|
32698
|
+
highlight(code, lang, info) {
|
|
32699
|
+
const language = core_default.getLanguage(lang) ? lang : "json";
|
|
32700
|
+
return core_default.highlight(code, { language }).value;
|
|
32701
|
+
}
|
|
32702
|
+
}));
|
|
32703
|
+
marked.setOptions({
|
|
32704
|
+
gfm: true,
|
|
32705
|
+
breaks: true
|
|
32706
|
+
});
|
|
32707
|
+
marked.use({
|
|
32708
|
+
walkTokens(token) {
|
|
32709
|
+
if (token.type === "link") {
|
|
32710
|
+
token.href = token.href || "";
|
|
32711
|
+
const isExternal = token.href && (token.href.startsWith("http://") || token.href.startsWith("https://") || token.href.startsWith("//"));
|
|
32712
|
+
if (isExternal) {
|
|
32713
|
+
token.isExternalLink = true;
|
|
32714
|
+
if (token.href.includes("youtube.com/watch") || token.href.includes("youtu.be/")) {
|
|
32715
|
+
token.isYouTubeLink = true;
|
|
32716
|
+
}
|
|
32717
|
+
}
|
|
32718
|
+
}
|
|
32721
32719
|
},
|
|
32722
|
-
|
|
32723
|
-
|
|
32724
|
-
|
|
32725
|
-
|
|
32720
|
+
hooks: {
|
|
32721
|
+
preprocess(markdown2) {
|
|
32722
|
+
return markdown2;
|
|
32723
|
+
},
|
|
32724
|
+
postprocess(html) {
|
|
32725
|
+
html = html.replace(/<a href="(https?:\/\/(www\.)?(youtube\.com\/watch\?v=|youtu\.be\/)([\w-]+)[^"]*)"[^>]*>(.*?)<\/a>/g, '<div class="video-container"><iframe src="https://www.youtube.com/embed/$4" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen loading="lazy"></iframe></div>');
|
|
32726
|
+
html = html.replace(/<img /g, '<img loading="lazy" ');
|
|
32727
|
+
return html.replace(/<a href="(https?:\/\/|\/\/)([^"]+)"/g, (match, protocol, rest) => {
|
|
32728
|
+
const fullUrl = protocol + rest;
|
|
32729
|
+
let relAttr = 'rel="noopener noreferrer';
|
|
32730
|
+
try {
|
|
32731
|
+
const url = new URL(fullUrl);
|
|
32732
|
+
const domain = url.hostname.replace(/^www\./, "");
|
|
32733
|
+
if (!noFollowExceptions.has(domain)) {
|
|
32734
|
+
relAttr += " nofollow";
|
|
32735
|
+
}
|
|
32736
|
+
} catch {
|
|
32737
|
+
relAttr += " nofollow";
|
|
32738
|
+
}
|
|
32739
|
+
relAttr += '"';
|
|
32740
|
+
return `<a href="${fullUrl}" target="_blank" ${relAttr}`;
|
|
32741
|
+
});
|
|
32742
|
+
}
|
|
32726
32743
|
}
|
|
32727
|
-
}
|
|
32728
|
-
|
|
32744
|
+
});
|
|
32745
|
+
return marked;
|
|
32746
|
+
}
|
|
32747
|
+
var marked = createMarked();
|
|
32748
|
+
function setNoFollowExceptions(exceptions) {
|
|
32749
|
+
noFollowExceptions = new Set(exceptions.map((domain) => domain.toLowerCase().replace(/^www\./, "")));
|
|
32750
|
+
marked = createMarked();
|
|
32751
|
+
}
|
|
32729
32752
|
function extractExcerpt(content, maxLength = 200) {
|
|
32730
32753
|
const plainText = content.replace(/^#.*$/gm, "").replace(/```[\s\S]*?```/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/[*_]{1,2}([^*_]+)[*_]{1,2}/g, "$1").replace(/\n+/g, " ").trim();
|
|
32731
32754
|
if (plainText.length <= maxLength) {
|
|
@@ -33055,6 +33078,9 @@ class SiteGenerator {
|
|
|
33055
33078
|
async initialize() {
|
|
33056
33079
|
console.log("Initializing site generator...");
|
|
33057
33080
|
await ensureDir(this.options.outputDir);
|
|
33081
|
+
if (this.options.config.noFollowExceptions) {
|
|
33082
|
+
setNoFollowExceptions(this.options.config.noFollowExceptions);
|
|
33083
|
+
}
|
|
33058
33084
|
let tagDescriptions = {};
|
|
33059
33085
|
const tagsTomlPath = path5.join(process.cwd(), "src", "tags.toml");
|
|
33060
33086
|
const tagsTomlFile = Bun.file(tagsTomlPath);
|
package/dist/index.js
CHANGED
|
@@ -30335,42 +30335,65 @@ core_default.registerLanguage("diff", diff);
|
|
|
30335
30335
|
core_default.registerLanguage("python", python);
|
|
30336
30336
|
core_default.registerLanguage("json", json);
|
|
30337
30337
|
core_default.registerLanguage("swift", swift);
|
|
30338
|
-
var
|
|
30339
|
-
|
|
30340
|
-
|
|
30341
|
-
|
|
30342
|
-
|
|
30343
|
-
|
|
30344
|
-
|
|
30345
|
-
})
|
|
30346
|
-
|
|
30347
|
-
|
|
30348
|
-
|
|
30349
|
-
|
|
30350
|
-
|
|
30351
|
-
|
|
30352
|
-
|
|
30353
|
-
|
|
30354
|
-
|
|
30355
|
-
|
|
30356
|
-
token.
|
|
30357
|
-
if (
|
|
30358
|
-
token.
|
|
30359
|
-
|
|
30360
|
-
|
|
30361
|
-
|
|
30362
|
-
|
|
30363
|
-
|
|
30364
|
-
preprocess(markdown2) {
|
|
30365
|
-
return markdown2;
|
|
30338
|
+
var noFollowExceptions = new Set;
|
|
30339
|
+
function createMarked() {
|
|
30340
|
+
const marked = new B(markedHighlight({
|
|
30341
|
+
emptyLangClass: "hljs",
|
|
30342
|
+
langPrefix: "hljs language-",
|
|
30343
|
+
highlight(code, lang, info) {
|
|
30344
|
+
const language = core_default.getLanguage(lang) ? lang : "json";
|
|
30345
|
+
return core_default.highlight(code, { language }).value;
|
|
30346
|
+
}
|
|
30347
|
+
}));
|
|
30348
|
+
marked.setOptions({
|
|
30349
|
+
gfm: true,
|
|
30350
|
+
breaks: true
|
|
30351
|
+
});
|
|
30352
|
+
marked.use({
|
|
30353
|
+
walkTokens(token) {
|
|
30354
|
+
if (token.type === "link") {
|
|
30355
|
+
token.href = token.href || "";
|
|
30356
|
+
const isExternal = token.href && (token.href.startsWith("http://") || token.href.startsWith("https://") || token.href.startsWith("//"));
|
|
30357
|
+
if (isExternal) {
|
|
30358
|
+
token.isExternalLink = true;
|
|
30359
|
+
if (token.href.includes("youtube.com/watch") || token.href.includes("youtu.be/")) {
|
|
30360
|
+
token.isYouTubeLink = true;
|
|
30361
|
+
}
|
|
30362
|
+
}
|
|
30363
|
+
}
|
|
30366
30364
|
},
|
|
30367
|
-
|
|
30368
|
-
|
|
30369
|
-
|
|
30370
|
-
|
|
30365
|
+
hooks: {
|
|
30366
|
+
preprocess(markdown2) {
|
|
30367
|
+
return markdown2;
|
|
30368
|
+
},
|
|
30369
|
+
postprocess(html) {
|
|
30370
|
+
html = html.replace(/<a href="(https?:\/\/(www\.)?(youtube\.com\/watch\?v=|youtu\.be\/)([\w-]+)[^"]*)"[^>]*>(.*?)<\/a>/g, '<div class="video-container"><iframe src="https://www.youtube.com/embed/$4" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen loading="lazy"></iframe></div>');
|
|
30371
|
+
html = html.replace(/<img /g, '<img loading="lazy" ');
|
|
30372
|
+
return html.replace(/<a href="(https?:\/\/|\/\/)([^"]+)"/g, (match, protocol, rest) => {
|
|
30373
|
+
const fullUrl = protocol + rest;
|
|
30374
|
+
let relAttr = 'rel="noopener noreferrer';
|
|
30375
|
+
try {
|
|
30376
|
+
const url = new URL(fullUrl);
|
|
30377
|
+
const domain = url.hostname.replace(/^www\./, "");
|
|
30378
|
+
if (!noFollowExceptions.has(domain)) {
|
|
30379
|
+
relAttr += " nofollow";
|
|
30380
|
+
}
|
|
30381
|
+
} catch {
|
|
30382
|
+
relAttr += " nofollow";
|
|
30383
|
+
}
|
|
30384
|
+
relAttr += '"';
|
|
30385
|
+
return `<a href="${fullUrl}" target="_blank" ${relAttr}`;
|
|
30386
|
+
});
|
|
30387
|
+
}
|
|
30371
30388
|
}
|
|
30372
|
-
}
|
|
30373
|
-
|
|
30389
|
+
});
|
|
30390
|
+
return marked;
|
|
30391
|
+
}
|
|
30392
|
+
var marked = createMarked();
|
|
30393
|
+
function setNoFollowExceptions(exceptions) {
|
|
30394
|
+
noFollowExceptions = new Set(exceptions.map((domain) => domain.toLowerCase().replace(/^www\./, "")));
|
|
30395
|
+
marked = createMarked();
|
|
30396
|
+
}
|
|
30374
30397
|
function extractExcerpt(content, maxLength = 200) {
|
|
30375
30398
|
const plainText = content.replace(/^#.*$/gm, "").replace(/```[\s\S]*?```/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/[*_]{1,2}([^*_]+)[*_]{1,2}/g, "$1").replace(/\n+/g, " ").trim();
|
|
30376
30399
|
if (plainText.length <= maxLength) {
|
|
@@ -30927,6 +30950,9 @@ class SiteGenerator {
|
|
|
30927
30950
|
async initialize() {
|
|
30928
30951
|
console.log("Initializing site generator...");
|
|
30929
30952
|
await ensureDir(this.options.outputDir);
|
|
30953
|
+
if (this.options.config.noFollowExceptions) {
|
|
30954
|
+
setNoFollowExceptions(this.options.config.noFollowExceptions);
|
|
30955
|
+
}
|
|
30930
30956
|
let tagDescriptions = {};
|
|
30931
30957
|
const tagsTomlPath = path5.join(process.cwd(), "src", "tags.toml");
|
|
30932
30958
|
const tagsTomlFile = Bun.file(tagsTomlPath);
|
package/dist/types.d.ts
CHANGED
|
@@ -56,6 +56,8 @@ export interface SiteConfig {
|
|
|
56
56
|
css?: CSSConfig;
|
|
57
57
|
/** Optional number of tags to display on homepage (sorted by count). If not set, all tags are shown */
|
|
58
58
|
maxTagsOnHomepage?: number;
|
|
59
|
+
/** Optional list of domains to exclude from nofollow attribute. Links to these domains will have follow attribute. */
|
|
60
|
+
noFollowExceptions?: string[];
|
|
59
61
|
/** Additional custom configuration options */
|
|
60
62
|
[key: string]: any;
|
|
61
63
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Post } from "../types";
|
|
2
|
+
export declare function setNoFollowExceptions(exceptions: string[]): void;
|
|
2
3
|
export declare function extractExcerpt(content: string, maxLength?: number): string;
|
|
3
4
|
export declare function convertMarkdownToHtml(markdownContent: string): string;
|
|
4
5
|
export declare function parseMarkdownFile(filePath: string): Promise<Post | null>;
|
package/package.json
CHANGED