From 9dd09b2cbbcf7d960832934fa7cbe33ff420f7b1 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Sat, 10 Sep 2022 02:31:42 +0100 Subject: [PATCH] feat: import posts from file --- package.json | 4 + pnpm-lock.yaml | 56 ++++++++++- src/components/dashboard/PagesManager.tsx | 108 ++++++++++++++++----- src/markdown/index.ts | 22 ++++- src/pages/dashboard/[subdomain]/editor.tsx | 6 +- 5 files changed, 163 insertions(+), 33 deletions(-) diff --git a/package.json b/package.json index 073ae877..b83e5827 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "form-data": "^4.0.0", "idb-keyval": "^6.2.0", "ioredis": "^5.2.2", + "js-yaml": "^4.1.0", "mailgun.js": "^5.2.2", "mdast-util-to-string": "^3.1.0", "nanoid": "^3.3.3", @@ -77,9 +78,11 @@ "rehype-raw": "^6.1.1", "rehype-sanitize": "^5.0.1", "rehype-stringify": "^9.0.3", + "remark-frontmatter": "^4.0.1", "remark-gfm": "^3.0.1", "remark-parse": "^10.0.1", "remark-rehype": "^10.1.0", + "remark-stringify": "^10.0.2", "sortablejs": "^1.15.0", "ua-parser-js": "^1.0.2", "unidata.js": "^0.6.21", @@ -104,6 +107,7 @@ "@types/async-busboy": "^1.1.1", "@types/busboy": "^1.5.0", "@types/cookie": "^0.5.1", + "@types/js-yaml": "^4.0.5", "@types/mjml": "^4.7.0", "@types/node": "^17.0.31", "@types/pica": "^9.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1db81bc0..45f23f93 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,7 @@ specifiers: '@types/async-busboy': ^1.1.1 '@types/busboy': ^1.5.0 '@types/cookie': ^0.5.1 + '@types/js-yaml': ^4.0.5 '@types/mjml': ^4.7.0 '@types/node': ^17.0.31 '@types/pica': ^9.0.0 @@ -70,6 +71,7 @@ specifiers: husky: ^8.0.1 idb-keyval: ^6.2.0 ioredis: ^5.2.2 + js-yaml: ^4.1.0 lint-staged: ^13.0.3 mailgun.js: ^5.2.2 mdast-util-to-string: ^3.1.0 @@ -93,9 +95,11 @@ specifiers: rehype-raw: ^6.1.1 rehype-sanitize: ^5.0.1 rehype-stringify: ^9.0.3 + remark-frontmatter: ^4.0.1 remark-gfm: ^3.0.1 remark-parse: ^10.0.1 remark-rehype: ^10.1.0 + remark-stringify: ^10.0.2 sortablejs: ^1.15.0 tailwindcss: ^3.0.24 typescript: ^4.5.5 @@ -153,6 +157,7 @@ dependencies: form-data: 4.0.0 idb-keyval: 6.2.0 ioredis: 5.2.2 + js-yaml: 4.1.0 mailgun.js: 5.2.2 mdast-util-to-string: 3.1.0 nanoid: 3.3.4 @@ -172,9 +177,11 @@ dependencies: rehype-raw: 6.1.1 rehype-sanitize: 5.0.1 rehype-stringify: 9.0.3 + remark-frontmatter: 4.0.1 remark-gfm: 3.0.1 remark-parse: 10.0.1 remark-rehype: 10.1.0 + remark-stringify: 10.0.2 sortablejs: 1.15.0 ua-parser-js: 1.0.2 unidata.js: 0.6.21 @@ -199,6 +206,7 @@ devDependencies: '@types/async-busboy': 1.1.1 '@types/busboy': 1.5.0 '@types/cookie': 0.5.1 + '@types/js-yaml': 4.0.5 '@types/mjml': 4.7.0 '@types/node': 17.0.45 '@types/pica': 9.0.1 @@ -2078,6 +2086,10 @@ packages: '@types/unist': 2.0.6 dev: false + /@types/js-yaml/4.0.5: + resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==} + dev: true + /@types/json-schema/7.0.11: resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} dev: true @@ -2993,7 +3005,6 @@ packages: /argparse/2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true /aria-hidden/1.1.3: resolution: {integrity: sha512-RhVWFtKH5BiGMycI72q2RAFMLQi8JP9bLuQXgR5a8Znp7P5KOIADSJeyfI8PCVxLEp067B2HbP5JIiI/PXIZeA==} @@ -5080,6 +5091,12 @@ packages: reusify: 1.0.4 dev: true + /fault/2.0.1: + resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==} + dependencies: + format: 0.2.2 + dev: false + /fetch-blob/2.1.2: resolution: {integrity: sha512-YKqtUDwqLyfyMnmbw8XD6Q8j9i/HggKtPEI+pZ1+8bvheBu78biSmNaXWusx1TauGqtUUGx/cBb1mKdq2rLYow==} engines: {node: ^10.17.0 || >=12.3.0} @@ -5192,6 +5209,11 @@ packages: mime-types: 2.1.35 dev: false + /format/0.2.2: + resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} + engines: {node: '>=0.4.x'} + dev: false + /fraction.js/4.2.0: resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} dev: true @@ -6195,7 +6217,6 @@ packages: hasBin: true dependencies: argparse: 2.0.1 - dev: true /jsesc/2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} @@ -6594,6 +6615,12 @@ packages: - supports-color dev: false + /mdast-util-frontmatter/1.0.0: + resolution: {integrity: sha512-7itKvp0arEVNpCktOET/eLFAYaZ+0cNjVtFtIPxgQ5tV+3i+D4SDDTjTzPWl44LT59PC+xdx+glNTawBdF98Mw==} + dependencies: + micromark-extension-frontmatter: 1.0.0 + dev: false + /mdast-util-gfm-autolink-literal/1.0.2: resolution: {integrity: sha512-FzopkOd4xTTBeGXhXSBU0OCDDh5lUj2rd+HQqG92Ld+jL4lpUfgX2AT2OHAVP9aEeDKp7G92fuooSZcYJA3cRg==} dependencies: @@ -6743,6 +6770,14 @@ packages: uvu: 0.5.4 dev: false + /micromark-extension-frontmatter/1.0.0: + resolution: {integrity: sha512-EXjmRnupoX6yYuUJSQhrQ9ggK0iQtQlpi6xeJzVD5xscyAI+giqco5fdymayZhJMbIFecjnE2yz85S9NzIgQpg==} + dependencies: + fault: 2.0.1 + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.1 + dev: false + /micromark-extension-gfm-autolink-literal/1.0.3: resolution: {integrity: sha512-i3dmvU0htawfWED8aHMMAzAVp/F0Z+0bPh3YrbTPPL1v4YAlCZpy5rBO5p0LPYiZo0zFVkoYh7vDU7yQSiCMjg==} dependencies: @@ -8222,6 +8257,15 @@ packages: unified: 10.1.2 dev: false + /remark-frontmatter/4.0.1: + resolution: {integrity: sha512-38fJrB0KnmD3E33a5jZC/5+gGAC2WKNiPw1/fdXJvijBlhA7RCsvJklrYJakS0HedninvaCYW8lQGf9C918GfA==} + dependencies: + '@types/mdast': 3.0.10 + mdast-util-frontmatter: 1.0.0 + micromark-extension-frontmatter: 1.0.0 + unified: 10.1.2 + dev: false + /remark-gfm/3.0.1: resolution: {integrity: sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==} dependencies: @@ -8252,6 +8296,14 @@ packages: unified: 10.1.2 dev: false + /remark-stringify/10.0.2: + resolution: {integrity: sha512-6wV3pvbPvHkbNnWB0wdDvVFHOe1hBRAx1Q/5g/EpH4RppAII6J8Gnwe7VbHuXaoKIF6LAg6ExTel/+kNqSQ7lw==} + dependencies: + '@types/mdast': 3.0.10 + mdast-util-to-markdown: 1.3.0 + unified: 10.1.2 + dev: false + /remove-accents/0.4.2: resolution: {integrity: sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==} dev: false diff --git a/src/components/dashboard/PagesManager.tsx b/src/components/dashboard/PagesManager.tsx index 55b5bbfe..0d00d4c1 100644 --- a/src/components/dashboard/PagesManager.tsx +++ b/src/components/dashboard/PagesManager.tsx @@ -21,6 +21,8 @@ import { delStorage, getStorage, setStorage } from "~/lib/storage" import { useQueryClient } from "@tanstack/react-query" import { Button } from "../ui/Button" import { UniLink } from "../ui/UniLink" +import { nanoid } from "nanoid" +import { renderPageContent } from "~/markdown" export const PagesManager: React.FC<{ isPost: boolean @@ -242,30 +244,90 @@ export const PagesManager: React.FC<{

{title}

- + + + + + New {isPost ? "Post" : "Page"} + + +
{description} diff --git a/src/markdown/index.ts b/src/markdown/index.ts index 4558c0d6..fa507217 100644 --- a/src/markdown/index.ts +++ b/src/markdown/index.ts @@ -1,6 +1,7 @@ import { unified } from "unified" import remarkParse from "remark-parse" import remarkRehype from "remark-rehype" +import remarkFrontmatter from "remark-frontmatter" import rehypeStringify from "rehype-stringify" import remarkGfm from "remark-gfm" import rehypeSanitize, { defaultSchema } from "rehype-sanitize" @@ -13,15 +14,18 @@ import { rehypeTable } from "./rehype-table" import { allowedBlockquoteAttrs, remarkCallout } from "./remark-callout" import { rehypeExternalLink } from "./rehyper-external-link" import { rehypeWrapCode } from "./rehype-wrap-code" +import jsYaml from "js-yaml" export type MarkdownEnv = { excerpt: string + frontMatter: Record __internal: Record } export type Rendered = { contentHTML: string excerpt: string + frontMatter: Record } refractor.alias("html", ["svelte", "vue"]) @@ -29,10 +33,23 @@ refractor.alias("html", ["svelte", "vue"]) const rehypePrism = rehypePrismGenerator(refractor) export const renderPageContent = async (content: string): Promise => { - const env: MarkdownEnv = { excerpt: "", __internal: {} } + const env: MarkdownEnv = { excerpt: "", __internal: {}, frontMatter: {} } const result = await unified() .use(remarkParse) + .use(rehypeStringify) + .use(remarkFrontmatter, ["yaml"]) + .use(() => (tree) => { + const yaml = tree.children.find((node) => node.type === "yaml") + try { + env.frontMatter = jsYaml.load((yaml as any)?.value) as Record< + string, + any + > + } catch (e) { + console.log(e) + } + }) .use(remarkGfm, {}) .use(remarkExcerpt, { env }) .use(remarkCallout) @@ -71,12 +88,11 @@ export const renderPageContent = async (content: string): Promise => { ignoreMissing: true, }) .use(rehypeTable) - .use(rehypeStringify) .use(rehypeExternalLink) .use(rehypeWrapCode) .process(content) const contentHTML = result.toString() - return { contentHTML, excerpt: env.excerpt } + return { contentHTML, excerpt: env.excerpt, frontMatter: env.frontMatter } } diff --git a/src/pages/dashboard/[subdomain]/editor.tsx b/src/pages/dashboard/[subdomain]/editor.tsx index 909a556b..58b96d7d 100644 --- a/src/pages/dashboard/[subdomain]/editor.tsx +++ b/src/pages/dashboard/[subdomain]/editor.tsx @@ -43,11 +43,6 @@ export default function SubdomainEditor() { if (!pageId) { const key = `draft-${subdomain}-local-${nanoid()}` setDraftKey(key) - setStorage(key, { - date: +new Date(), - isPost: isPost, - values, - }) queryClient.invalidateQueries(["getPagesBySite", subdomain]) } else { setDraftKey(`draft-${subdomain}-${pageId}`) @@ -184,6 +179,7 @@ export default function SubdomainEditor() { }) useEffect(() => { + console.log("!page.data", page.data) if (!page.data || !draftKey) return const local = getStorage(draftKey)