feat: use better names for md files
This commit is contained in:
@@ -12,21 +12,25 @@ export function formatDate(date?: string | Date): string {
|
|||||||
return new Intl.DateTimeFormat("en-US", options).format(date);
|
return new Intl.DateTimeFormat("en-US", options).format(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function safeFileName(inputString: string): string {
|
export function safeFileName(input: string): string {
|
||||||
let fileName = inputString.toLowerCase();
|
return input
|
||||||
fileName = fileName.replace(/ /g, "_");
|
.normalize("NFKD")
|
||||||
fileName = fileName.replace(/[^\w.-]/g, "");
|
.replace(/[\u0300-\u036f]/g, "")
|
||||||
fileName = fileName.replaceAll(":", "");
|
.replace(/[\s-]+/g, "_")
|
||||||
return fileName;
|
.replace(/[^A-Za-z0-9._]+/g, "")
|
||||||
|
.replace(/_+/g, "_")
|
||||||
|
// Trim underscores/dots from ends and prevent leading dots
|
||||||
|
.replace(/^[_\.]+|[_\.]+$/g, "").replace(/^\.+/, "")
|
||||||
|
.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toUrlSafeString(input: string): string {
|
export function toUrlSafeString(input: string): string {
|
||||||
return input
|
return input
|
||||||
.trim() // Remove leading and trailing whitespace
|
.normalize("NFKD")
|
||||||
.toLowerCase() // Convert to lowercase
|
.replace(/[\u0300-\u036f]/g, "")
|
||||||
.replace(/[^a-z0-9\s-]/g, "") // Remove non-alphanumeric characters except spaces and hyphens
|
.replace(/[^A-Za-z0-9 _-]+/g, "")
|
||||||
.replace(/\s+/g, "-") // Replace spaces with hyphens
|
.replace(/\s+/g, " ")
|
||||||
.replace(/-+/g, "-"); // Remove consecutive hyphens
|
.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function extractHashTags(inputString: string) {
|
export function extractHashTags(inputString: string) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
formatDate,
|
formatDate,
|
||||||
isYoutubeLink,
|
isYoutubeLink,
|
||||||
safeFileName,
|
safeFileName,
|
||||||
|
toUrlSafeString,
|
||||||
} from "@lib/string.ts";
|
} from "@lib/string.ts";
|
||||||
import { createLogger } from "@lib/log/index.ts";
|
import { createLogger } from "@lib/log/index.ts";
|
||||||
import { createResource } from "@lib/marka/index.ts";
|
import { createResource } from "@lib/marka/index.ts";
|
||||||
@@ -86,7 +87,7 @@ async function processCreateArticle(
|
|||||||
|
|
||||||
streamResponse.enqueue("writing to disk");
|
streamResponse.enqueue("writing to disk");
|
||||||
|
|
||||||
await createResource(`articles/${title}.md`, newArticle);
|
await createResource(`articles/${toUrlSafeString(title)}.md`, newArticle);
|
||||||
|
|
||||||
streamResponse.enqueue("id: " + title);
|
streamResponse.enqueue("id: " + title);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,12 @@ import { Handlers } from "$fresh/server.ts";
|
|||||||
import { json } from "@lib/helpers.ts";
|
import { json } from "@lib/helpers.ts";
|
||||||
import * as tmdb from "@lib/tmdb.ts";
|
import * as tmdb from "@lib/tmdb.ts";
|
||||||
import { fileExtension } from "https://deno.land/x/file_extension@v2.1.0/mod.ts";
|
import { fileExtension } from "https://deno.land/x/file_extension@v2.1.0/mod.ts";
|
||||||
import { formatDate, isString, safeFileName } from "@lib/string.ts";
|
import {
|
||||||
|
formatDate,
|
||||||
|
isString,
|
||||||
|
safeFileName,
|
||||||
|
toUrlSafeString,
|
||||||
|
} from "@lib/string.ts";
|
||||||
import { AccessDeniedError, BadRequestError } from "@lib/errors.ts";
|
import { AccessDeniedError, BadRequestError } from "@lib/errors.ts";
|
||||||
import { createResource, fetchResource } from "@lib/marka/index.ts";
|
import { createResource, fetchResource } from "@lib/marka/index.ts";
|
||||||
import { ReviewResource } from "@lib/marka/schema.ts";
|
import { ReviewResource } from "@lib/marka/schema.ts";
|
||||||
@@ -59,9 +64,9 @@ export const handler: Handlers = {
|
|||||||
keywords,
|
keywords,
|
||||||
};
|
};
|
||||||
|
|
||||||
const fileName = `${safeFileName(name)}.md`;
|
const fileName = toUrlSafeString(name);
|
||||||
|
|
||||||
await createResource(`movies/${fileName}`, movie);
|
await createResource(`movies/${fileName}.md`, movie);
|
||||||
|
|
||||||
return json({ name: fileName });
|
return json({ name: fileName });
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import { FreshContext, Handlers } from "$fresh/server.ts";
|
import { FreshContext, Handlers } from "$fresh/server.ts";
|
||||||
import { fileExtension } from "https://deno.land/x/file_extension@v2.1.0/mod.ts";
|
import { fileExtension } from "https://deno.land/x/file_extension@v2.1.0/mod.ts";
|
||||||
import * as tmdb from "@lib/tmdb.ts";
|
import * as tmdb from "@lib/tmdb.ts";
|
||||||
import { formatDate, isString, safeFileName } from "@lib/string.ts";
|
import {
|
||||||
|
formatDate,
|
||||||
|
isString,
|
||||||
|
safeFileName,
|
||||||
|
toUrlSafeString,
|
||||||
|
} from "@lib/string.ts";
|
||||||
import { json } from "@lib/helpers.ts";
|
import { json } from "@lib/helpers.ts";
|
||||||
import {
|
import {
|
||||||
AccessDeniedError,
|
AccessDeniedError,
|
||||||
@@ -78,7 +83,7 @@ const POST = async (
|
|||||||
movie.content.image = finalPath;
|
movie.content.image = finalPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
await createResource(`movies/${safeFileName(movie.name)}.md`, movie);
|
await createResource(`movies/${toUrlSafeString(movie.name)}.md`, movie);
|
||||||
|
|
||||||
createRecommendationResource(movie, movieDetails.overview);
|
createRecommendationResource(movie, movieDetails.overview);
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import * as openai from "@lib/openai.ts";
|
|||||||
import { createLogger } from "@lib/log/index.ts";
|
import { createLogger } from "@lib/log/index.ts";
|
||||||
import recipeSchema from "@lib/recipeSchema.ts";
|
import recipeSchema from "@lib/recipeSchema.ts";
|
||||||
import { fileExtension } from "https://deno.land/x/file_extension@v2.1.0/mod.ts";
|
import { fileExtension } from "https://deno.land/x/file_extension@v2.1.0/mod.ts";
|
||||||
import { safeFileName } from "@lib/string.ts";
|
import { safeFileName, toUrlSafeString } from "@lib/string.ts";
|
||||||
import { parseJsonLdToRecipeSchema } from "./parseJsonLd.ts";
|
import { parseJsonLdToRecipeSchema } from "./parseJsonLd.ts";
|
||||||
import z from "zod";
|
import z from "zod";
|
||||||
import { createResource } from "@lib/marka/index.ts";
|
import { createResource } from "@lib/marka/index.ts";
|
||||||
@@ -58,7 +58,7 @@ async function processCreateRecipeFromUrl(
|
|||||||
recipe = res;
|
recipe = res;
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = safeFileName(recipe?.name || "");
|
const id = toUrlSafeString(recipe?.name || "");
|
||||||
|
|
||||||
if (!recipe) {
|
if (!recipe) {
|
||||||
streamResponse.enqueue("failed to parse recipe");
|
streamResponse.enqueue("failed to parse recipe");
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { formatDate, isString, safeFileName } from "@lib/string.ts";
|
|||||||
import { AccessDeniedError, BadRequestError } from "@lib/errors.ts";
|
import { AccessDeniedError, BadRequestError } from "@lib/errors.ts";
|
||||||
import { createResource, fetchResource } from "@lib/marka/index.ts";
|
import { createResource, fetchResource } from "@lib/marka/index.ts";
|
||||||
import { ReviewResource } from "@lib/marka/schema.ts";
|
import { ReviewResource } from "@lib/marka/schema.ts";
|
||||||
|
import { toUrlSafeString } from "@lib/string.ts";
|
||||||
|
|
||||||
function pickDirector(
|
function pickDirector(
|
||||||
credits: Awaited<ReturnType<typeof tmdb.getSeriesCredits>>,
|
credits: Awaited<ReturnType<typeof tmdb.getSeriesCredits>>,
|
||||||
@@ -71,9 +72,9 @@ export const handler: Handlers = {
|
|||||||
keywords: keywords,
|
keywords: keywords,
|
||||||
};
|
};
|
||||||
|
|
||||||
const fileName = `${safeFileName(name)}.md`;
|
const fileName = toUrlSafeString(name);
|
||||||
|
|
||||||
await createResource(`series/${fileName}`, series);
|
await createResource(`series/${fileName}.md`, series);
|
||||||
|
|
||||||
return json({ name: fileName });
|
return json({ name: fileName });
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user