From f791a0ffa97fe178f00de0560fb817f0229624a1 Mon Sep 17 00:00:00 2001 From: Ola Rubaj <52197250+olayway@users.noreply.github.com> Date: Fri, 4 Aug 2023 17:18:04 +0200 Subject: [PATCH 01/28] [.github/workflows][s]: add E2E workflow --- .github/workflows/e2e.yml | 57 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 .github/workflows/e2e.yml diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 00000000..fcc2971d --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,57 @@ +name: Run E2E Tests + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Check out E2E tests repo + uses: actions/checkout@v2 + with: + repository: datopian/flowershow-template-e2e + + - name: Check out this repo into test-app + uses: actions/checkout@v2 + with: + path: test-app + + - name: Use Node.js + uses: actions/setup-node@v2 + with: + node-version: '16.x' + + - name: Install dependencies of E2E tests + run: | + npm ci + npx playwright install --with-deps + + - name: Install dependencies of this repo + run: npm ci + working-directory: test-app + + - name: Replace template /content with fixture content + run: | + rm -rf test-app/content + cp -r fixtures/content test-app/content + + - name: Build the app + run: npm run export + working-directory: test-app + + - name: Run the tests + run: npx playwright test + + - uses: actions/upload-artifact@v3 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 From 9bbcc3634c0c3c922eaed63b1a7073a2ac17f34f Mon Sep 17 00:00:00 2001 From: Ola Rubaj <52197250+olayway@users.noreply.github.com> Date: Fri, 4 Aug 2023 17:25:33 +0200 Subject: [PATCH 02/28] [.gitignore][xs]: rm contentlayer, add markdowndb --- .gitignore | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 4cd37960..8e877cbe 100644 --- a/.gitignore +++ b/.gitignore @@ -35,9 +35,8 @@ yarn-error.log* # vercel .vercel - -# Contentlayer -.contentlayer - +# editor .obsidian -sandbox + +# markdowndb +markdown.db From 4757eb268a6d33781003fdd37befc46932816dcd Mon Sep 17 00:00:00 2001 From: Ola Rubaj <52197250+olayway@users.noreply.github.com> Date: Fri, 4 Aug 2023 17:26:25 +0200 Subject: [PATCH 03/28] [next.config.mjs][xs]: rm contentlayer hook --- next.config.mjs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/next.config.mjs b/next.config.mjs index 5f45fa23..85c5821f 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,6 +1,4 @@ -import { withContentlayer } from "next-contentlayer"; - -export default withContentlayer({ +export default { eslint: { ignoreDuringBuilds: true, }, @@ -10,4 +8,4 @@ export default withContentlayer({ }; return config; }, -}); +}; From a7d8133a35544e605064cf97206edffb2c847112 Mon Sep 17 00:00:00 2001 From: Ola Rubaj <52197250+olayway@users.noreply.github.com> Date: Fri, 4 Aug 2023 18:49:46 +0200 Subject: [PATCH 04/28] [.eslintrc][xs]: rm old nx reference --- .eslintrc.json | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 3e8c1e1a..a1c83c0b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,10 +1,5 @@ { - "extends": [ - "plugin:@nrwl/nx/react", - "next", - "next/core-web-vitals", - "../../.eslintrc.json" - ], + "extends": ["next", "next/core-web-vitals", "../../.eslintrc.json"], "ignorePatterns": [".obsidian/**/*", ".next/**/*", "out/**/*"], "overrides": [ { From a7831556555e26c13e3a43eeb3c5e0bd108ce0cc Mon Sep 17 00:00:00 2001 From: Ola Rubaj <52197250+olayway@users.noreply.github.com> Date: Fri, 4 Aug 2023 18:54:34 +0200 Subject: [PATCH 05/28] [styles/prism.css][s]: code highlighting styles upgrade --- styles/prism.css | 77 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 7 deletions(-) diff --git a/styles/prism.css b/styles/prism.css index ecd059ec..c3ed023f 100644 --- a/styles/prism.css +++ b/styles/prism.css @@ -1,3 +1,7 @@ +/** PrismJS prism-vsc-dark-plus theme styles + * https://github.com/timlrx/rehype-prism-plus +*/ + pre[class*="language-"], code[class*="language-"] { color: #d4d4d4; @@ -25,7 +29,7 @@ code[class*="language-"]::selection, pre[class*="language-"] *::selection, code[class*="language-"] *::selection { text-shadow: none; - background: #264f78; + background: #75a7ca; } @media print { @@ -39,16 +43,15 @@ pre[class*="language-"] { padding: 1em; margin: 0.5em 0; overflow: auto; - background: #1e1e1e; + background: rgba(0, 0, 0, 0.5); } :not(pre) > code[class*="language-"] { padding: 0.1em 0.3em; border-radius: 0.3em; color: #db4c69; - background: #1e1e1e; + background: #f9f2f4; } - /********************************************************* * Tokens */ @@ -230,7 +233,6 @@ pre[class*="language-"] { .token.namespace { color: #4ec9b0; } - /********************************************************* * Language Specific */ @@ -263,17 +265,78 @@ code[class*="language-html"] { .language-html .token.punctuation { color: #808080; } - /********************************************************* * Line highlighting */ +pre[data-line] { + position: relative; +} + pre[class*="language-"] > code[class*="language-"] { position: relative; z-index: 1; } -.line-highlight.line-highlight { +.line-highlight { + position: absolute; + left: 0; + right: 0; + padding: inherit 0; + margin-top: 1em; background: #f7ebc6; box-shadow: inset 5px 0 0 #f7d87c; z-index: 0; + pointer-events: none; + line-height: inherit; + white-space: pre; +} + +pre { + overflow-x: auto; +} + +/** Below styles were copied from https://github.com/timlrx/rehype-prism-plus */ + +/** + * Inspired by gatsby remark prism - https://www.gatsbyjs.com/plugins/gatsby-remark-prismjs/ + * 1. Make the element just wide enough to fit its content. + * 2. Always fill the visible space in .code-highlight. + */ +.code-highlight { + float: left; /* 1 */ + min-width: 100%; /* 2 */ +} + +.code-line { + display: block; + padding-left: 16px; + padding-right: 16px; + margin-left: -16px; + margin-right: -16px; + border-left: 4px solid rgba(0, 0, 0, 0); /* Set placeholder for highlight accent border color to transparent */ +} + +.code-line.inserted { + background-color: rgba(16, 185, 129, 0.2); /* Set inserted line (+) color */ +} + +.code-line.deleted { + background-color: rgba(239, 68, 68, 0.2); /* Set deleted line (-) color */ +} + +.highlight-line { + margin-left: -16px; + margin-right: -16px; + background-color: rgba(55, 65, 81, 0.5); /* Set highlight bg color */ + border-left: 4px solid rgb(59, 130, 246); /* Set highlight accent border color */ +} + +.line-number::before { + display: inline-block; + width: 1rem; + text-align: right; + margin-right: 16px; + margin-left: -8px; + color: rgb(156, 163, 175); /* Line number color */ + content: attr(line); } From 99d4a605a6a30b788c9ba473efa547f54f4cb2c1 Mon Sep 17 00:00:00 2001 From: Ola Rubaj <52197250+olayway@users.noreply.github.com> Date: Fri, 4 Aug 2023 19:03:58 +0200 Subject: [PATCH 06/28] [package.json][m]: dependencies upgrade pt.1 --- package.json | 63 +++++++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/package.json b/package.json index 82c0f18f..5faac99f 100644 --- a/package.json +++ b/package.json @@ -1,63 +1,70 @@ { - "name": "@flowershow/template", - "private": true, - "version": "1.0.0", + "name": "flowershow", + "private": "true", + "version": "2.0.3", "scripts": { - "dev": "next dev", + "dev": "npm run generate && next dev", + "prebuild": "npm run generate", "build": "next build", - "postbuild": "cross-env NODE_OPTIONS='--experimental-json-modules --experimental-modules' node ./scripts/search.mjs", "start": "next start", - "export": "npm run build && next export" + "export": "npm run build && next export", + "mddb": "mddb ./content", + "generate": "cross-env NODE_OPTIONS=\"--experimental-json-modules --experimental-modules\" node -r esbuild-register ./scripts/prebuild.mjs" }, "dependencies": { "@docsearch/react": "^3.2.0", "@headlessui/react": "^1.6.6", - "@heroicons/react": "^1.0.4", - "@silvenon/remark-smartypants": "^1.0.0", "@splidejs/react-splide": "^0.7.12", - "@tailwindcss/line-clamp": "^0.4.2", - "@tailwindcss/typography": "^0.5.2", "clsx": "^1.2.1", - "contentlayer": "^0.2.8", "crypto-js": "^4.1.1", "d3": "^7.6.1", "d3-ternary": "^2.0.14", "date-fns": "^2.29.2", "fuse.js": "^6.6.2", + "@heroicons/react": "^1.0.6", + "@portaljs/remark-callouts": "^1.0.5", + "@portaljs/remark-embed": "^1.0.4", + "@portaljs/remark-wiki-link": "^1.0.4", + "@silvenon/remark-smartypants": "^2.0.0", + "@tailwindcss/typography": "^0.5.9", + "@types/node": "18.14.2", + "@types/react": "18.0.28", + "@types/react-dom": "18.0.11", "gray-matter": "^4.0.3", - "hastscript": "^7.0.2", "itemsjs": "^2.1.15", "kbar": "^0.1.0-beta.37", - "mdx-mermaid": "^2.0.0-rc5", - "mermaid": "9.3.0", - "next": "^13.0.4", - "next-contentlayer": "^0.2.9", - "next-seo": "^6.0.0", "next-themes": "^0.2.1", + "hastscript": "^7.2.0", + "mddb": "^0.1.9", + "mdx-mermaid": "2.0.0-rc7", + "next": "13.3.0", + "next-mdx-remote": "^4.4.1", + "next-seo": "^5.15.0", "react": "^18.2.0", "react-aria": "^3.20.0", "react-dom": "^18.2.0", "react-stately": "^3.18.0", "rehype-autolink-headings": "^6.1.1", - "rehype-mathjax": "^4.0.2", - "rehype-prism-plus": "^1.4.2", - "rehype-slug": "^5.0.1", - "remark-callouts": "^2.0.0", - "remark-embed-plus": "^1.0.4", - "remark-gfm": "^3.0.0", + "rehype-katex": "^6.0.2", + "rehype-prism-plus": "^1.5.1", + "rehype-slug": "^5.1.0", + "remark-gfm": "^3.0.1", "remark-math": "^5.1.1", "remark-smartypants": "^2.0.0", "remark-toc": "^8.0.1", - "remark-wiki-link-plus": "^1.1.1", "sort-array": "^4.1.5", "strip-markdown": "^5.0.0", - "typed.js": "^2.0.16" + "typed.js": "^2.0.12", + "typescript": "^4.9.5" }, "devDependencies": { - "autoprefixer": "^10.4.4", + "autoprefixer": "^10.4.13", "cross-env": "^7.0.3", - "postcss": "^8.4.12", + "esbuild-register": "^3.4.2", + "globby": "^13.1.3", + "postcss": "^8.4.21", + "prettier": "^2.8.4", "remark": "^14.0.2", - "tailwindcss": "^3.1.8" + "tailwindcss": "^3.2.7" } } From 22ec8d88eafb2177d41316bce1bae6d48fd8351b Mon Sep 17 00:00:00 2001 From: Ola Rubaj <52197250+olayway@users.noreply.github.com> Date: Fri, 4 Aug 2023 19:05:47 +0200 Subject: [PATCH 07/28] [/][xs]: add types.d.ts with @portaljs/remark-wiki-link declaration --- types.d.ts | 1 + 1 file changed, 1 insertion(+) create mode 100644 types.d.ts diff --git a/types.d.ts b/types.d.ts new file mode 100644 index 00000000..bd3988d1 --- /dev/null +++ b/types.d.ts @@ -0,0 +1 @@ +declare module "@portaljs/remark-wiki-link"; From e54f31fc1d3ffeb6245abc2a09fad8d8b8dc29e9 Mon Sep 17 00:00:00 2001 From: Ola Rubaj <52197250+olayway@users.noreply.github.com> Date: Fri, 4 Aug 2023 19:06:39 +0200 Subject: [PATCH 08/28] [/][s]: replace jsconfig with tsconfig --- jsconfig.json | 16 ---------------- tsconfig.json | 29 +++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 16 deletions(-) delete mode 100644 jsconfig.json create mode 100644 tsconfig.json diff --git a/jsconfig.json b/jsconfig.json deleted file mode 100644 index 8ef2a24a..00000000 --- a/jsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": ".", - "paths": { - "contentlayer/generated": ["./.contentlayer/generated"], - "@/*": ["./*"] - } - }, - "include": [ - "next-env.d.ts", - "**/*.tsx", - "**/*.ts", - ".contentlayer/generated" - ], - "exclude": ["node_modules"] -} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..3200e5e7 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@portaljs/core": ["node_modules/@portaljs/core/src"], + "@portaljs/remark-callouts": [ + "node_modules/@portaljs/remark-callouts/src" + ], + "@portaljs/remark-embed": ["node_modules/@portaljs/remark-embed/src"], + "@/*": ["./*"] + }, + "target": "es2020", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": false, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "incremental": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve" + }, + "include": ["types.d.ts", "next-env.d.ts", "**/*.tsx", "**/*.ts"], + "exclude": ["node_modules"] +} From 3e554fb7f490eb3eea4dace320bdcf7a01705f8c Mon Sep 17 00:00:00 2001 From: Ola Rubaj <52197250+olayway@users.noreply.github.com> Date: Fri, 4 Aug 2023 19:07:29 +0200 Subject: [PATCH 09/28] [scripts/search][s]: upgrade script to use mddb instead of contentlayer --- scripts/search.mjs | 55 +++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/scripts/search.mjs b/scripts/search.mjs index 1c1bd59c..698a17a2 100644 --- a/scripts/search.mjs +++ b/scripts/search.mjs @@ -1,25 +1,40 @@ import { writeFileSync } from "fs"; -import { allDocuments } from "../.contentlayer/generated/index.mjs"; -const omit = (obj = {}, keys = []) => { - const result = Object.assign({}, obj); - keys.forEach((key) => { - delete result[key]; - }); - return result; -}; +import config from "../content/config.mjs"; +import clientPromise from "../lib/mddb.mjs"; -const coreContent = allDocuments - .map((doc) => - omit( - { +// const omit = (obj = {}, keys = []) => { +// const result = Object.assign({}, obj); +// keys.forEach((key) => { +// delete result[key]; +// }); +// return result; +// }; + +export default async function search() { + const mddb = await clientPromise; + const allFiles = await mddb.getFiles({ extensions: ["md", "mdx"] }); + const coreContent = allFiles + .filter((doc) => !doc.metadata?.isDraft) + .map( + (doc) => ({ ...doc, - sourceDir: - doc._raw.sourceFileDir === "." ? null : doc._raw.sourceFileDir, - }, - ["body", "_raw", "_id"] - ) - ) - .filter((doc) => !doc.isDraft); + sourceDir: doc.file_path, + urlPath: doc.url_path, + }) + // TODO old contentlayer related code + // omit( + // { + // ...doc, + // sourceDir: doc.file_path + // }, + // ["body", "_raw", "_id"] + // ) + ); -writeFileSync("public/search.json", JSON.stringify(coreContent)); + if (config?.search?.provider === "kbar") { + writeFileSync("public/search.json", JSON.stringify(coreContent)); + console.log("Local search index generated..."); + } + return; +} From 8dbfc6d613216250f8034675b82fc88a4dd5f31d Mon Sep 17 00:00:00 2001 From: Ola Rubaj <52197250+olayway@users.noreply.github.com> Date: Fri, 4 Aug 2023 19:09:53 +0200 Subject: [PATCH 10/28] [/][xs]: add prettierignore --- .prettierignore | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .prettierignore diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..11d0f52b --- /dev/null +++ b/.prettierignore @@ -0,0 +1,9 @@ +.obsidian/ +.next/ +out/ +dist/ +excalidraw/ +content/ +meta/ +.github/ +pnpm-lock.yaml From 379213bfab349a32bd33ae19cc6111f6ec38a330 Mon Sep 17 00:00:00 2001 From: Ola Rubaj <52197250+olayway@users.noreply.github.com> Date: Fri, 4 Aug 2023 19:44:00 +0200 Subject: [PATCH 11/28] [/][xs]: rm contentlayer.config.js --- contentlayer.config.js | 380 ----------------------------------------- 1 file changed, 380 deletions(-) delete mode 100644 contentlayer.config.js diff --git a/contentlayer.config.js b/contentlayer.config.js deleted file mode 100644 index 504a2770..00000000 --- a/contentlayer.config.js +++ /dev/null @@ -1,380 +0,0 @@ -/* eslint import/no-unresolved: off */ -import { defineDocumentType, defineNestedType, makeSource } from "contentlayer/source-files"; -import { h } from "hastscript"; -import { remark } from "remark"; -import rehypeAutolinkHeadings from "rehype-autolink-headings"; -import rehypeMathjax from "rehype-mathjax"; -import rehypePrismPlus from "rehype-prism-plus"; -import rehypeSlug from "rehype-slug"; -import callouts from "remark-callouts"; -import remarkEmbed from "remark-embed-plus"; -import remarkGfm from "remark-gfm"; -import remarkMath from "remark-math"; -import smartypants from "remark-smartypants"; -import remarkToc from "remark-toc"; -import wikiLinkPlugin from "remark-wiki-link-plus"; -import mdxMermaid from 'mdx-mermaid'; -import stripMarkdown from "strip-markdown"; - -import { siteConfig } from "./config/siteConfig"; -import { filterMarkdown } from "./lib/filterMarkdown"; - -const sharedFields = { - title: { type: "string" }, - description: { type: "string" }, - image: { type: "string" }, - layout: { type: "string", default: "docs" }, - editLink: { type: "boolean" }, - toc: { type: "boolean" }, - isDraft: { type: "boolean" }, - data: { type: "list", of: { type: "string" }, default: [] }, - aliases: { type: "list", of: { type: "string" } }, -}; - -const computedFields = { - description: { - type: "string", - /* eslint no-underscore-dangle: off */ - resolve: async (doc) => { - // use frontmatter description if exists - if (doc.description) return doc.description; - - const content = filterMarkdown(doc.body.raw) - - // remove markdown formatting - const stripped = await remark() - .use(stripMarkdown, { - remove: ["heading", "blockquote", "list", "image", "html", "code"], - }) - .process(content); - - if (stripped.value) { - const description = stripped.value.toString().slice(0, 200); - return description + "..."; - } - }, - }, - url_path: { - type: "string", - /* eslint no-underscore-dangle: off */ - resolve: (post) => post._raw.flattenedPath, - }, - slug: { - type: "string", - /* eslint no-underscore-dangle: off */ - resolve: (doc) => doc._raw.flattenedPath.replace(/^(.+?\/)*/, ""), - }, -}; - -const Page = defineDocumentType(() => ({ - name: "Page", - filePathPattern: "**/*.md*", - contentType: "mdx", - fields: { - ...sharedFields, - created: { type: "date" }, - authors: { - type: "list", - of: { type: "string" }, - }, - }, - computedFields, -})); - -const Blog = defineDocumentType(() => ({ - name: "Blog", - filePathPattern: `${siteConfig.blogDir}/**/!(index)*.md*`, - contentType: "mdx", - fields: { - ...sharedFields, - layout: { type: "string", default: "blog" }, - created: { - type: "date", - }, - authors: { - type: "list", - of: { type: "string" }, - }, - categories: { - type: "list", - of: { type: "string" } - }, - tags: { - type: "list", - of: { type: "string" }, - }, - }, - computedFields, -})); - -export const Person = defineDocumentType(() => ({ - name: "Person", - filePathPattern: `${siteConfig.peopleDir}/!(index)*.md*`, - contentType: "mdx", - fields: { - ...sharedFields, - layout: { type: "string", default: "people" }, - id: { - type: "string", - }, - name: { - type: "string", - required: true, - }, - avatar: { - type: "string", - default: siteConfig.avatarPlaceholder, - }, - email: { - type: "string", - }, - twitter: { - type: "string", - }, - linkedin: { - type: "string", - }, - github: { - type: "string", - }, - }, - computedFields, -})); - -const Podcast = defineDocumentType(() => ({ - name: "Podcast", - contentType: "mdx", - filePathPattern: "podcast/**/*.md*", - fields: { - ...sharedFields, - date: { type: "date" }, - author: { type: "string" }, - src: { type: "string" }, - audioType: { type: "string", default: "audio/x-m4a" }, - layout: { type: "string", default: "podcast" }, - }, - computedFields -})) - -const statusOptions = [ - "active", - "incubating", - "inactive", - "completed" -] - -const resolutionOptions = [ - "dormant", - "retired", - "merged", - "cancelled" -] - -const Initiative = defineDocumentType(() => ({ - name: "Initiative", - contentType: "mdx", - filePathPattern: "initiatives/**/*.md*", - fields: { - ...sharedFields, - layout: { type: "string", default: "initiatives" }, - homepage: { type: "json" }, - start: { type: "json" }, - end: { type: "json" }, - team: { type: "list", of: { type: "string" }, default: [] }, - alumni: { type: "json" }, - size: { type: "enum", options: ["xl", "l", "m", "s", "xs"] }, - state: { type: "enum", options: ["open", "closed"] }, - status: { type: "enum", options: statusOptions }, - resolution: { type: "enum", options: resolutionOptions }, - created: { type: "date" }, - }, - computedFields: { - ...computedFields, - alumni: { - type: "list", - resolve: doc => { - if (!Array.isArray(doc.alumni)) return [] - return doc.alumni - } - } - } -})) - -const Residency = defineDocumentType(() => ({ - name: "Residency", - contentType: "mdx", - filePathPattern: "programs/**/*.md*", - fields: { - ...sharedFields, - layout: { type: "string", default: "residencies" }, - start: { type: "json" }, - end: { type: "json" }, - facilitators: { type: "json" }, - location: { type: "string" }, - cost: { type: "string" }, - "apply-button": { type: "string" }, - created: { type: "date" } - }, - computedFields -})) - -/* Ecosystem document types */ - -const NestedUrl = defineNestedType(() => ({ - name: 'NestedUrl', - fields: { - url: { type: 'string' }, - cached: { type: 'string' }, - cached_new: { type: 'string' } - } -})); - -const SocialChangeFields = defineNestedType(() => ({ - name: 'SocialChange', - fields: { - inner: { type: 'json' }, - cultural: { type: 'json' }, - systems: { type: 'json' } - } -})); - -const resolveArrays = ['topic', 'activity', 'people', 'locations'].reduce( - (el, key) => ({ - ...el, - [key]: { - type: 'json', - resolve: (doc) => (doc[key] == 0 ? [] : doc[key]) - } - }), - {} -); - -const Profile = defineDocumentType(() => ({ - name: 'Profile', - filePathPattern: 'ecosystem/profiles/**/*.md*', - contentType: 'mdx', - fields: { - ...sharedFields, - layout: { type: 'string', default: 'profile' }, - id: { type: 'string' }, - url: { type: 'string' }, - tagline: { type: 'json' }, - activity: { type: 'json' }, - topic: { type: 'json' }, - regions: { type: 'json' }, - locations: { type: 'json' }, - started: { type: 'json' }, - ended: { type: 'string' }, - active: { type: 'string' }, - people: { type: 'json' }, - notes_data_entry: { type: 'string' }, - facebook: { type: 'json' }, - twitter: { type: 'json' }, - instagram: { type: 'json' }, - linkedin: { type: 'json' }, - youtube: { type: 'json' }, - blog: { type: 'json' }, - logo: { type: 'nested', of: NestedUrl }, - image: { type: 'nested', of: NestedUrl }, - curation_status: { type: 'string' }, - social_change: { type: 'nested', of: SocialChangeFields } - }, - computedFields: { - ...computedFields, - ...resolveArrays - } -})); - -const Topic = defineDocumentType(() => ({ - name: 'Topic', - filePathPattern: 'ecosystem/topics/**/*.md*', - contentType: 'mdx', - fields: { - ...sharedFields, - id: { type: 'string' }, - image: { type: 'string' }, - emoji: { type: 'json' }, - super_topic: { type: 'string' } - }, - computedFields -})); - -const contentLayerExcludeDefaults = [ - "node_modules", - ".git", - ".yarn", - ".cache", - ".next", - ".contentlayer", - "package.json", - "tsconfig.json", -]; - -/* eslint import/no-default-export: off */ -export default makeSource({ - contentDirPath: siteConfig.content, - contentDirExclude: contentLayerExcludeDefaults.concat([ - ".flowershow", - ".obsidian", - ...siteConfig.contentExclude, - ]), - contentDirInclude: siteConfig.contentInclude, - documentTypes: [Blog, Person, Podcast, Profile, Topic, Initiative, Residency, Page], - mdx: { - cwd: process.cwd(), - remarkPlugins: [ - remarkEmbed, - remarkGfm, - [smartypants, { quotes: false, dashes: "oldschool" }], - remarkMath, - callouts, - [wikiLinkPlugin, { markdownFolder: siteConfig.content }], - [ - remarkToc, - { - heading: "Table of contents", - // maxDepth: "3", - tight: true, - }, - ], - mdxMermaid - ], - rehypePlugins: [ - rehypeSlug, - [ - rehypeAutolinkHeadings, - { - test(element) { - return ( - ["h2", "h3", "h4", "h5", "h6"].includes(element.tagName) && - element.properties?.id !== "table-of-contents" && - element.properties?.className !== "blockquote-heading" - ); - }, - content() { - return [ - h( - "svg", - { - xmlns: "http://www.w3.org/2000/svg", - fill: "#ab2b65", - viewBox: "0 0 20 20", - className: "w-5 h-5", - }, - [ - h("path", { - fillRule: "evenodd", - clipRule: "evenodd", - d: "M9.493 2.853a.75.75 0 00-1.486-.205L7.545 6H4.198a.75.75 0 000 1.5h3.14l-.69 5H3.302a.75.75 0 000 1.5h3.14l-.435 3.148a.75.75 0 001.486.205L7.955 14h2.986l-.434 3.148a.75.75 0 001.486.205L12.456 14h3.346a.75.75 0 000-1.5h-3.14l.69-5h3.346a.75.75 0 000-1.5h-3.14l.435-3.147a.75.75 0 00-1.486-.205L12.045 6H9.059l.434-3.147zM8.852 7.5l-.69 5h2.986l.69-5H8.852z", - }), - ] - ), - ]; - }, - }, - ], - rehypeMathjax, - [rehypePrismPlus, { ignoreMissing: true }], - ], - }, -}); From ef52baf0755cb862d0885ccac283ca537cddc6bd Mon Sep 17 00:00:00 2001 From: Ola Rubaj <52197250+olayway@users.noreply.github.com> Date: Fri, 4 Aug 2023 19:45:46 +0200 Subject: [PATCH 12/28] [tailwind.config.js][xs]: rename to tailwind.config.cjs --- tailwind.config.js => tailwind.config.cjs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) rename tailwind.config.js => tailwind.config.cjs (90%) diff --git a/tailwind.config.js b/tailwind.config.cjs similarity index 90% rename from tailwind.config.js rename to tailwind.config.cjs index 09f82f18..3b27c95a 100644 --- a/tailwind.config.js +++ b/tailwind.config.cjs @@ -7,6 +7,8 @@ module.exports = { "./components/**/*.{js,ts,jsx,tsx}", "./layouts/**/*.{js,ts,jsx,tsx}", "./content/**/*.{md,mdx}", + "./node_modules/@portaljs/core/dist/*.js", + "./node_modules/@portaljs/core/*.js", ], darkMode: "class", theme: { @@ -41,7 +43,6 @@ module.exports = { }, /* eslint global-require: off */ plugins: [ - require("@tailwindcss/typography"), - require('@tailwindcss/line-clamp'), + require("@tailwindcss/typography") ], }; From f26b48de525ac8a5755efba94da09546a1c8996e Mon Sep 17 00:00:00 2001 From: Ola Rubaj <52197250+olayway@users.noreply.github.com> Date: Fri, 4 Aug 2023 20:10:13 +0200 Subject: [PATCH 13/28] [/][xs]: rm nx's project.json --- project.json | 51 --------------------------------------------------- 1 file changed, 51 deletions(-) delete mode 100644 project.json diff --git a/project.json b/project.json deleted file mode 100644 index 3e41ba67..00000000 --- a/project.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "template", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "sourceRoot": "packages/template", - "projectType": "library", - "targets": { - "build": { - "executor": "nx:run-commands", - "outputs": ["{options.outputPath}"], - "inputs": ["production", "^production", "siteContent"], - "options": { - "command": "npm run build", - "cwd": "packages/template", - "outputPath": "packages/template/.next" - } - }, - "export": { - "executor": "nx:run-commands", - "outputs": ["{options.outputPath}"], - "inputs": ["production", "^production", "siteContent"], - "options": { - "command": "npm run export", - "cwd": "packages/template", - "outputPath": "packages/template/out" - } - }, - "serve": { - "executor": "nx:run-commands", - "options": { - "command": "npm run dev", - "cwd": "packages/template" - } - }, - "test": { - "executor": "@nrwl/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "packages/template/jest.config.js", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nrwl/linter:eslint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": ["packages/template/**/*.{ts,tsx,js,jsx}"] - } - } - }, - "tags": [] -} From 37f359da2926145a5b5d48260137716e0ef50159 Mon Sep 17 00:00:00 2001 From: Ola Rubaj <52197250+olayway@users.noreply.github.com> Date: Mon, 7 Aug 2023 15:05:57 +0200 Subject: [PATCH 14/28] [components][m]: add MdxPage --- components/MdxPage.tsx | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 components/MdxPage.tsx diff --git a/components/MdxPage.tsx b/components/MdxPage.tsx new file mode 100644 index 00000000..2821d019 --- /dev/null +++ b/components/MdxPage.tsx @@ -0,0 +1,32 @@ +import React from "react"; +import { MDXRemote } from "next-mdx-remote"; +import { Mermaid, Pre } from "@portaljs/core"; + +import layouts from "../layouts"; + +// Custom components/renderers to pass to MDX. +// Since the MDX files aren't loaded by webpack, they have no knowledge of how +// to handle import statements. Instead, you must include components in scope +// here. +const components = { + mermaid: Mermaid, + pre: Pre, +}; + +export default function MdxPage({ source, frontMatter }) { + const Layout = ({ children }) => { + if (frontMatter.layout) { + const LayoutComponent = layouts[frontMatter.layout]; + return {children}; + } + return <>{children}; + }; + + return ( +
+ + + +
+ ); +} From 2c7db32da4caf69bb6d09472144996996b20dc2a Mon Sep 17 00:00:00 2001 From: Ola Rubaj <52197250+olayway@users.noreply.github.com> Date: Mon, 7 Aug 2023 15:15:10 +0200 Subject: [PATCH 15/28] [pages/_all][s]: upgrade to use mddb and ts --- pages/_all.jsx | 55 ------------------------- pages/_all.tsx | 109 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 55 deletions(-) delete mode 100644 pages/_all.jsx create mode 100644 pages/_all.tsx diff --git a/pages/_all.jsx b/pages/_all.jsx deleted file mode 100644 index af95fe9f..00000000 --- a/pages/_all.jsx +++ /dev/null @@ -1,55 +0,0 @@ -/* eslint import/no-default-export: off */ -import { allPages } from "contentlayer/generated"; -import { NextSeo } from "next-seo"; - -export default function All({ pages }) { - const labels = new Set(pages.map((p) => p.wikiPage.charAt(0))); - return ( - <> - -
-

A-Z Index

- {Array.from(labels).map((pageTitle) => ( -
-

{pageTitle}

-
-
    - {pages.map( - ({ wikiPage, wikiPath }) => - pageTitle === wikiPage.charAt(0) && ( -
  • - {wikiPage} -
  • - ) - )} -
-
- ))} -
- - ); -} - -export async function getStaticProps() { - const pages = allPages - .map((page) => { - /* eslint no-underscore-dangle: off */ - const wikiPath = page._raw.flattenedPath; - const wikiPage = wikiPath - .split("/") - .pop() - .replace(/-/g, " ") - .replace( - /^(\w)(.+)/, - (match, p1, p2) => p1.toUpperCase() + p2.toLowerCase() - ); - - return { wikiPage, wikiPath }; - }) - .filter((page) => page.wikiPath !== "") // exclude homepage - .sort((a, b) => a.wikiPage.localeCompare(b.wikiPage)); - - return { - props: { pages }, - }; -} diff --git a/pages/_all.tsx b/pages/_all.tsx new file mode 100644 index 00000000..7daa4218 --- /dev/null +++ b/pages/_all.tsx @@ -0,0 +1,109 @@ +/* eslint import/no-default-export: off */ +import React from "react"; +import { GetStaticProps, GetStaticPropsResult } from "next"; + +import { SimpleLayout } from "@portaljs/core"; +import clientPromise from "../lib/mddb.mjs"; +import type { CustomAppProps } from "./_app"; + +interface AllPageProps extends CustomAppProps { + pages: Array<{ urlPath: string; displayName: string }>; // TODO types +} + +export default function All({ pages, meta: { title } }: AllPageProps) { + const pagesGroupedByFirstLetter: { + [key: string]: Array<{ urlPath: string; displayName: string }>; + } = pages.reduce((acc, curr) => { + const firstLetter = curr.displayName.charAt(0); + if (!acc[firstLetter]) { + acc[firstLetter] = []; + } + acc[firstLetter].push(curr); + return acc; + }, {}); + + const letters = Object.keys(pagesGroupedByFirstLetter).sort(); + + // ORIGINAL VERSION + {/* <> + +
+

A-Z Index

+ {Array.from(labels).map((pageTitle) => ( +
+

{pageTitle}

+
+
    + {pages.map( + ({ wikiPage, wikiPath }) => + pageTitle === wikiPage.charAt(0) && ( +
  • + {wikiPage} +
  • + ) + )} +
+
+ ))} +
+ */} + + return ( + +
+ {letters.map((letter) => ( +
+

{letter}

+
+
    + {pagesGroupedByFirstLetter[letter].map( + ({ urlPath, displayName }) => ( +
  • + {displayName} +
  • + ) + )} +
+
+ ))} +
+
+ ); +} + +export const getStaticProps: GetStaticProps = async (): Promise< + GetStaticPropsResult +> => { + const mddb = await clientPromise; + const allPages = await mddb.getFiles({ extensions: ["md", "mdx"] }); + const allPagesList = allPages + .filter((page) => page.url_path !== "/") // exclude homepage + .map((page) => { + const urlPath = page.url_path; + const displayName = urlPath + .split("/") + .pop() + .replace(/-/g, " ") + .replace( + /^(\w)(.+)/, + (match, p1, p2) => p1.toUpperCase() + p2.toLowerCase() + ); + + return { urlPath, displayName }; + }) + .sort((a, b) => a.displayName.localeCompare(b.displayName)); + + return { + props: { + meta: { + title: "A-Z Index", + showSidebar: false, + showToc: false, + showComments: false, + showEditLink: false, + urlPath: "/_all", + }, + pages: allPagesList, + }, + }; +}; From 9c5c1e506c3e59aeb988061e4c6b06a178c1a3b1 Mon Sep 17 00:00:00 2001 From: Ola Rubaj <52197250+olayway@users.noreply.github.com> Date: Mon, 7 Aug 2023 15:38:57 +0200 Subject: [PATCH 16/28] [pages][s]: upgrade _app --- pages/_app.jsx | 129 ------------------------------------------------- pages/_app.tsx | 121 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 129 deletions(-) delete mode 100644 pages/_app.jsx create mode 100644 pages/_app.tsx diff --git a/pages/_app.jsx b/pages/_app.jsx deleted file mode 100644 index 6027d46b..00000000 --- a/pages/_app.jsx +++ /dev/null @@ -1,129 +0,0 @@ -/* eslint import/no-default-export: off */ -import { DefaultSeo, NextSeo } from "next-seo"; -import { ThemeProvider } from "next-themes"; -import { useRouter } from "next/router"; -import Script from "next/script"; -import { useEffect, useState } from "react"; -import "tailwindcss/tailwind.css"; - -import { Layout } from "../components/Layout"; -import { SearchProvider } from "../components/search"; -import { siteConfig } from "../config/siteConfig"; -import * as gtag from "../lib/gtag"; -import "../styles/docsearch.css"; -import "../styles/global.css"; -import "../styles/prism.css"; - -// ToC: get the html nodelist for headings -function collectHeadings(nodes) { - const sections = []; - - Array.from(nodes).forEach((node) => { - const { id, innerText: title, tagName: level } = node; - if (!(id && title)) { - return; - } - if (level === "H3") { - const parentSection = sections[sections.length - 1]; - if (parentSection) parentSection.children.push({ id, title }); - } else if (level === "H2") { - sections.push({ id, title, children: [] }); - } - - sections.push(...collectHeadings(node.children ?? [])); - }); - - return sections; -} - -function MyApp({ Component, pageProps }) { - const router = useRouter(); - - useEffect(() => { - if (siteConfig.analytics) { - const handleRouteChange = (url) => { - gtag.pageview(url); - }; - router.events.on("routeChangeComplete", handleRouteChange); - return () => { - router.events.off("routeChangeComplete", handleRouteChange); - }; - } - }, [router.events]); - - const [tableOfContents, setTableOfContents] = useState([]); - - useEffect(() => { - const headingNodes = document.querySelectorAll("h2,h3"); - const toc = collectHeadings(headingNodes); - setTableOfContents(toc ?? []); - }, [router.asPath]); // update table of contents on route change with next/link - - // Seo config - const url = siteConfig.authorUrl.replace(/\/+$/, ""); - const frontMatterImage = - typeof pageProps?.image === "string" && pageProps.image; - const seoImageURL = frontMatterImage && frontMatterImage.startsWith("http") - ? pageProps.image - : url + pageProps.image - - const seo = { - title: pageProps?.title, - description: pageProps?.description?.replace(/(\r\n|\n|\r)/gm, ""), // remove whitespaces - canonical: pageProps.url_path ? `${url}/${pageProps?.url_path}` : url, - openGraph: { - url: pageProps.url_path ? `${url}/${pageProps?.url_path}` : url, - images: pageProps?.image ? [ - { - url: seoImageURL, - width: 1200, - height: 627, - alt: pageProps?.title, - type: "image/png" - }, - ] : [] - } - } - - return ( - - - - {/* Global Site Tag (gtag.js) - Google Analytics */} - {siteConfig.analytics && ( -