mirror of
https://github.com/lainbo/component-party.git
synced 2026-04-05 04:59:02 +08:00
feat(app): add spa router to handle versus framework pages
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<footer class="bg-gray-900">
|
||||
<footer class="bg-gray-900 pb-20">
|
||||
<h2 id="footer-heading" class="sr-only">Footer</h2>
|
||||
<div class="mx-auto max-w-7xl px-6 pb-8 pt-16 sm:pt-24 lg:px-8 lg:pt-32">
|
||||
<div class="xl:grid xl:grid-cols-3 xl:gap-8">
|
||||
@@ -20,7 +20,7 @@
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-16 grid grid-cols-2 gap-8 xl:col-span-2 xl:mt-0">
|
||||
<div class="mt-16 grid grid-cols-1 sm:grid-cols-2 gap-8 xl:col-span-2 xl:mt-0">
|
||||
<% for (const navigation of it.navigations) { %>
|
||||
<div class="md:grid md:gap-8">
|
||||
<aside>
|
||||
@@ -28,7 +28,7 @@
|
||||
<%= navigation.title %>
|
||||
</h3>
|
||||
<nav>
|
||||
<ul role="list" class="mt-6 space-y-2">
|
||||
<ul role="list" class="mt-2 space-y-2">
|
||||
<% for (const link of navigation.links) { %>
|
||||
<li>
|
||||
<a href="<%= link.url %>" class="text-sm leading-6 text-gray-300 hover:text-white">
|
||||
@@ -43,10 +43,5 @@
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-16 border-t border-white/10 pt-8 sm:mt-20 lg:mt-24">
|
||||
<p class="text-xs leading-5 text-gray-400">
|
||||
© 2020 Your Company, Inc. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
@@ -8,11 +8,12 @@ function sortAllFilenames(files, filenamesSorted) {
|
||||
].filter(Boolean);
|
||||
}
|
||||
|
||||
export default [
|
||||
const frameworks = [
|
||||
{
|
||||
id: "svelte4",
|
||||
title: "Svelte 4",
|
||||
frameworkName: "Svelte",
|
||||
isCurrentVersion: true,
|
||||
img: "framework/svelte.svg",
|
||||
eslint: {
|
||||
files: ["**/svelte4/*.svelte"],
|
||||
@@ -30,6 +31,7 @@ export default [
|
||||
id: "react",
|
||||
title: "React",
|
||||
frameworkName: "React",
|
||||
isCurrentVersion: true,
|
||||
img: "framework/react.svg",
|
||||
eslint: {
|
||||
files: ["**/react/*.jsx", "**/react/*.tsx"],
|
||||
@@ -56,6 +58,7 @@ export default [
|
||||
id: "vue3",
|
||||
title: "Vue 3",
|
||||
frameworkName: "Vue",
|
||||
isCurrentVersion: true,
|
||||
img: "framework/vue.svg",
|
||||
eslint: {
|
||||
files: ["**/vue3/*.vue"],
|
||||
@@ -80,6 +83,7 @@ export default [
|
||||
id: "angular",
|
||||
title: "Angular",
|
||||
frameworkName: "Angular",
|
||||
isCurrentVersion: true,
|
||||
img: "framework/angular.svg",
|
||||
eslint: [
|
||||
{
|
||||
@@ -136,6 +140,7 @@ export default [
|
||||
id: "lit",
|
||||
title: "Lit",
|
||||
frameworkName: "Lit",
|
||||
isCurrentVersion: true,
|
||||
img: "framework/lit.svg",
|
||||
eslint: {
|
||||
files: ["**/lit/**"],
|
||||
@@ -155,6 +160,7 @@ export default [
|
||||
id: "vue2",
|
||||
title: "Vue 2",
|
||||
frameworkName: "Vue",
|
||||
isCurrentVersion: false,
|
||||
img: "framework/vue.svg",
|
||||
eslint: {
|
||||
files: ["**/vue2/*.vue"],
|
||||
@@ -176,6 +182,7 @@ export default [
|
||||
id: "ember",
|
||||
title: "Ember",
|
||||
frameworkName: "Ember",
|
||||
isCurrentVersion: true,
|
||||
img: "framework/ember.svg",
|
||||
eslint: {
|
||||
files: ["**/ember/**"],
|
||||
@@ -195,6 +202,7 @@ export default [
|
||||
id: "solid",
|
||||
title: "Solid.js",
|
||||
frameworkName: "Solid",
|
||||
isCurrentVersion: true,
|
||||
img: "framework/solid.svg",
|
||||
eslint: {
|
||||
files: ["**/solid/*.jsx"],
|
||||
@@ -213,6 +221,7 @@ export default [
|
||||
id: "alpine",
|
||||
title: "Alpine",
|
||||
frameworkName: "Alpine",
|
||||
isCurrentVersion: true,
|
||||
img: "framework/alpine.svg",
|
||||
eslint: {
|
||||
files: ["**/alpine/**"],
|
||||
@@ -230,6 +239,7 @@ export default [
|
||||
id: "mithril",
|
||||
title: "Mithril",
|
||||
frameworkName: "Mithril",
|
||||
isCurrentVersion: true,
|
||||
img: "framework/mithril.svg",
|
||||
eslint: {
|
||||
env: {
|
||||
@@ -252,6 +262,7 @@ export default [
|
||||
id: "aurelia2",
|
||||
title: "Aurelia 2",
|
||||
frameworkName: "Aurelia",
|
||||
isCurrentVersion: true,
|
||||
img: "framework/aurelia.svg",
|
||||
eslint: {
|
||||
env: {
|
||||
@@ -281,6 +292,7 @@ export default [
|
||||
id: "qwik",
|
||||
title: "Qwik",
|
||||
frameworkName: "Qwik",
|
||||
isCurrentVersion: true,
|
||||
img: "framework/qwik.svg",
|
||||
eslint: {
|
||||
env: {
|
||||
@@ -312,6 +324,7 @@ export default [
|
||||
id: "marko",
|
||||
title: "Marko",
|
||||
frameworkName: "Marko",
|
||||
isCurrentVersion: true,
|
||||
img: "framework/marko.svg",
|
||||
eslint: {
|
||||
files: ["!**"], // Marko’s linter/prettyprinter doesn’t use eslint
|
||||
@@ -328,6 +341,7 @@ export default [
|
||||
id: "aurelia1",
|
||||
title: "Aurelia 1",
|
||||
frameworkName: "Aurelia",
|
||||
isCurrentVersion: false,
|
||||
img: "framework/aurelia.svg",
|
||||
eslint: {
|
||||
env: {
|
||||
@@ -356,6 +370,7 @@ export default [
|
||||
id: "svelte5",
|
||||
title: "Svelte 5 (preview)",
|
||||
frameworkName: "Svelte",
|
||||
isCurrentVersion: false,
|
||||
img: "framework/svelte.svg",
|
||||
eslint: {
|
||||
files: ["**/TODO-THIS-IS-DISABLED-svelte5/*.svelte"],
|
||||
@@ -370,3 +385,12 @@ export default [
|
||||
mainPackageName: "svelte",
|
||||
},
|
||||
];
|
||||
|
||||
export function matchFrameworkId(id){
|
||||
return frameworks.find((framework) =>
|
||||
framework.id === id ||
|
||||
(framework.isCurrentVersion &&
|
||||
framework.frameworkName.toLowerCase() === id))
|
||||
}
|
||||
|
||||
export default frameworks;
|
||||
@@ -22,7 +22,8 @@
|
||||
"@veljs/svelte": "^0.1.11",
|
||||
"classnames": "^2.5.1",
|
||||
"eslint-plugin-svelte": "^2.35.1",
|
||||
"heroiconsvelte": "^1.0.2"
|
||||
"heroiconsvelte": "^1.0.2",
|
||||
"svelte-router-spa": "^7.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-eslint/eslint-plugin": "^17.2.1",
|
||||
|
||||
16
pnpm-lock.yaml
generated
16
pnpm-lock.yaml
generated
@@ -20,6 +20,9 @@ dependencies:
|
||||
heroiconsvelte:
|
||||
specifier: ^1.0.2
|
||||
version: 1.0.2(svelte@4.2.12)
|
||||
svelte-router-spa:
|
||||
specifier: ^7.0.1
|
||||
version: 7.0.1(svelte@4.2.12)
|
||||
|
||||
devDependencies:
|
||||
'@angular-eslint/eslint-plugin':
|
||||
@@ -6606,6 +6609,15 @@ packages:
|
||||
typescript: 5.3.3
|
||||
dev: true
|
||||
|
||||
/svelte-router-spa@7.0.1(svelte@4.2.12):
|
||||
resolution: {integrity: sha512-Oh1bVBkK4UYSXzBSrVa8kTRrPtkc9+C7TSVlUkoFXyAf4dQtRrGXqPbXGU0lR5MJ8VkwXU68XclGtpCeWm5gpg==}
|
||||
peerDependencies:
|
||||
svelte: ^3.36.0
|
||||
dependencies:
|
||||
svelte: 4.2.12
|
||||
url-params-parser: 1.0.4
|
||||
dev: false
|
||||
|
||||
/svelte@3.59.2:
|
||||
resolution: {integrity: sha512-vzSyuGr3eEoAtT/A6bmajosJZIUWySzY2CzB3w2pgPvnkUjGqlDnsNnA0PMO+mMAhuyMul6C2uuZzY6ELSkzyA==}
|
||||
engines: {node: '>= 8'}
|
||||
@@ -7037,6 +7049,10 @@ packages:
|
||||
dependencies:
|
||||
punycode: 2.3.1
|
||||
|
||||
/url-params-parser@1.0.4:
|
||||
resolution: {integrity: sha512-0m6BqGpY2OetTZ3UPTLKkbTfUHigsX2YhrzORT9iYiyUJ/SP2WJ3cggg2YWtvMs36GPwK9Q44ffddyarniu2Tg==}
|
||||
dev: false
|
||||
|
||||
/url-parse-lax@1.0.0:
|
||||
resolution: {integrity: sha512-BVA4lR5PIviy2PMseNd2jbFQ+jwSwQGdJejf5ctd1rEXt0Ypd7yanUK9+lYechVlN5VaTJGsu2U/3MDDu6KgBA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
411
src/App.svelte
411
src/App.svelte
@@ -1,399 +1,18 @@
|
||||
<script>
|
||||
import FRAMEWORKS from "../frameworks.mjs";
|
||||
import c from "classnames";
|
||||
import FrameworkLabel from "./components/FrameworkLabel.svelte";
|
||||
import { sections, snippets } from "./generatedContent/tree.js";
|
||||
import snippetsImporterByFrameworkId from "./generatedContent/framework/index.js";
|
||||
import { PlayIcon, PencilIcon, ArrowUpIcon } from "heroiconsvelte/24/outline";
|
||||
import CodeEditor from "./components/CodeEditor.svelte";
|
||||
import AppNotificationCenter from "./components/AppNotificationCenter.svelte";
|
||||
import createLocaleStorage from "./lib/createLocaleStorage.js";
|
||||
import { onMount } from "svelte";
|
||||
import Header from "./components/Header.svelte";
|
||||
import Aside from "./components/Aside.svelte";
|
||||
import GithubIcon from "./components/GithubIcon.svelte";
|
||||
|
||||
const frameworkIdsStorage = createLocaleStorage("framework_display");
|
||||
|
||||
function removeSearchParamKeyFromURL(k) {
|
||||
// Get the current search params as an object
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
|
||||
if (!searchParams.has(k)) {
|
||||
// The key doesn't exist, so don't do anything
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove the parameter you want to remove
|
||||
searchParams.delete(k);
|
||||
|
||||
let newUrl = window.location.pathname;
|
||||
if (searchParams.toString().length > 0) {
|
||||
// There are still search params, so include the `?` character
|
||||
newUrl += `?${searchParams}`;
|
||||
}
|
||||
|
||||
// Update the URL without reloading the page
|
||||
history.replaceState({}, "", newUrl);
|
||||
}
|
||||
|
||||
let frameworkIdsSelected = new Set();
|
||||
let snippetsByFrameworkId = new Map();
|
||||
|
||||
let frameworkIdsSelectedStorageInitialized = false;
|
||||
|
||||
const frameworkIdsFromURLKey = "f";
|
||||
|
||||
onMount(function handleInitialFrameworkIdsSelected() {
|
||||
let frameworkIdsSelectedOnInit = [];
|
||||
|
||||
const url = new URL(window.location.href);
|
||||
|
||||
const frameworkIdsFromURLStr = url.searchParams.get(frameworkIdsFromURLKey);
|
||||
|
||||
if (frameworkIdsFromURLStr) {
|
||||
const frameworkIdsFromURL = frameworkIdsFromURLStr
|
||||
.split(",")
|
||||
.filter((fId) => FRAMEWORKS.find((framework) => framework.id === fId));
|
||||
if (frameworkIdsFromURL.length > 0) {
|
||||
frameworkIdsSelectedOnInit = frameworkIdsFromURL;
|
||||
} else {
|
||||
removeSearchParamKeyFromURL(frameworkIdsFromURLKey);
|
||||
}
|
||||
}
|
||||
|
||||
if (frameworkIdsSelectedOnInit.length === 0) {
|
||||
const frameworkIdsFromStorage = frameworkIdsStorage.getJSON();
|
||||
if (frameworkIdsFromStorage?.length > 0) {
|
||||
frameworkIdsSelectedOnInit = frameworkIdsFromStorage.map((x) =>
|
||||
x === "svelte" ? "svelte4" : x
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (frameworkIdsSelectedOnInit.length === 0) {
|
||||
frameworkIdsSelectedOnInit = ["svelte4", "react"];
|
||||
}
|
||||
|
||||
frameworkIdsSelected = new Set(frameworkIdsSelectedOnInit);
|
||||
frameworkIdsSelectedStorageInitialized = true;
|
||||
});
|
||||
|
||||
function saveFrameworkIdsSelectedOnStorage() {
|
||||
frameworkIdsStorage.setJSON([...frameworkIdsSelected]);
|
||||
removeSearchParamKeyFromURL(frameworkIdsFromURLKey);
|
||||
}
|
||||
|
||||
function toggleFrameworkId(frameworkId) {
|
||||
if (frameworkIdsSelected.has(frameworkId)) {
|
||||
frameworkIdsSelected.delete(frameworkId);
|
||||
} else {
|
||||
frameworkIdsSelected.add(frameworkId);
|
||||
}
|
||||
frameworkIdsSelected = frameworkIdsSelected;
|
||||
saveFrameworkIdsSelectedOnStorage();
|
||||
}
|
||||
|
||||
$: {
|
||||
async function importFrameworkSnippets(frameworkIds) {
|
||||
for (const frameworkId of frameworkIds) {
|
||||
if (!snippetsByFrameworkId.has(frameworkId)) {
|
||||
const frameworkSnippets = (
|
||||
await snippetsImporterByFrameworkId[frameworkId]()
|
||||
).default;
|
||||
snippetsByFrameworkId.set(frameworkId, frameworkSnippets);
|
||||
}
|
||||
}
|
||||
|
||||
snippetsByFrameworkId = snippetsByFrameworkId;
|
||||
}
|
||||
|
||||
importFrameworkSnippets([...frameworkIdsSelected]);
|
||||
}
|
||||
|
||||
const MAX_FRAMEWORK_NB_INITIAL_DISPLAYED = 10;
|
||||
|
||||
const FRAMEWORKS_INITIAL_DISPLAYED = FRAMEWORKS.slice(
|
||||
0,
|
||||
MAX_FRAMEWORK_NB_INITIAL_DISPLAYED
|
||||
);
|
||||
|
||||
const FRAMEWORKS_MORE = FRAMEWORKS.slice(MAX_FRAMEWORK_NB_INITIAL_DISPLAYED);
|
||||
|
||||
$: frameworksSelected = [...frameworkIdsSelected].map((id) =>
|
||||
FRAMEWORKS.find((f) => f.id === id)
|
||||
);
|
||||
|
||||
$: frameworksNotSelected = FRAMEWORKS_INITIAL_DISPLAYED.filter(
|
||||
(f) => !frameworkIdsSelected.has(f.id)
|
||||
);
|
||||
|
||||
$: frameworksMoreNotSelected = FRAMEWORKS_MORE.filter(
|
||||
(f) => !frameworkIdsSelected.has(f.id)
|
||||
);
|
||||
|
||||
let showBonusFrameworks = false;
|
||||
import { Router } from "svelte-router-spa";
|
||||
import Index from "./Index.svelte";
|
||||
const routes = [
|
||||
{
|
||||
name: "/",
|
||||
component: Index,
|
||||
},
|
||||
{ name: "/compare/:versus", component: Index },
|
||||
{
|
||||
name: "404",
|
||||
path: "404",
|
||||
component: Index,
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<AppNotificationCenter />
|
||||
|
||||
<Header {frameworksSelected} />
|
||||
|
||||
<div class="flex border-b border-gray-700">
|
||||
<Aside />
|
||||
<div class="pb-8 w-10 grow">
|
||||
<div
|
||||
class="flex px-6 lg:px-20 py-2 sticky top-0 z-20 w-full backdrop-blur bg-gray-900/80 border-b border-gray-700 whitespace-nowrap overflow-x-auto"
|
||||
>
|
||||
{#each [...frameworksSelected, ...frameworksNotSelected] as framework (framework.id)}
|
||||
<button
|
||||
title={`Display ${framework.title}`}
|
||||
class={c(
|
||||
"text-sm flex-shrink-0 rounded border border-gray-700 px-3 py-1 border-opacity-50 bg-gray-900 hover:bg-gray-800 transition-all mr-2",
|
||||
frameworkIdsSelected.has(framework.id)
|
||||
? "border-blue-500"
|
||||
: "opacity-70"
|
||||
)}
|
||||
on:click={() => toggleFrameworkId(framework.id)}
|
||||
>
|
||||
<FrameworkLabel id={framework.id} size={15} />
|
||||
</button>
|
||||
{/each}
|
||||
{#if showBonusFrameworks}
|
||||
{#each frameworksMoreNotSelected as framework (framework.id)}
|
||||
<button
|
||||
title={`Display ${framework.title}`}
|
||||
class={c(
|
||||
"text-sm flex-shrink-0 rounded border border-gray-700 px-3 py-1 border-opacity-50 bg-gray-900 hover:bg-gray-800 transition-all mr-2",
|
||||
frameworkIdsSelected.has(framework.id)
|
||||
? "border-blue-500"
|
||||
: "opacity-70"
|
||||
)}
|
||||
on:click={() => toggleFrameworkId(framework.id)}
|
||||
>
|
||||
<FrameworkLabel id={framework.id} size={15} />
|
||||
</button>
|
||||
{/each}
|
||||
{:else if frameworksMoreNotSelected.length > 0}
|
||||
<button
|
||||
title="more"
|
||||
class="opacity-70 text-sm flex-shrink-0 rounded border border-gray-700 px-3 py-1 border-opacity-50 bg-gray-900 hover:bg-gray-800 transition-all mr-2"
|
||||
on:click={() => {
|
||||
showBonusFrameworks = !showBonusFrameworks;
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="size-4"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M6.75 12a.75.75 0 11-1.5 0 .75.75 0 011.5 0zM12.75 12a.75.75 0 11-1.5 0 .75.75 0 011.5 0zM18.75 12a.75.75 0 11-1.5 0 .75.75 0 011.5 0z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<main class="relative pt-10">
|
||||
<div>
|
||||
{#if frameworkIdsSelected.size === 0}
|
||||
<div class="space-y-4">
|
||||
<div class="flex justify-center">
|
||||
<ArrowUpIcon class="size-6 animate-bounce" />
|
||||
</div>
|
||||
<div class="flex justify-center">
|
||||
<p
|
||||
class="text-lg opacity-80 flex items-center text-center space-x-3"
|
||||
>
|
||||
<img src="/popper.svg" alt="logo" class="size-6" />
|
||||
<span>
|
||||
Please select a framework to view framework's snippets
|
||||
</span>
|
||||
<img src="/popper.svg" alt="logo" class="size-6" />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div
|
||||
class="max-w-full prose prose-sm prose-invert prose-h1:font-semibold prose-h2:font-medium prose-h3:font-medium prose-h1:scroll-mt-[5rem] prose-pre:mt-0 prose-h2:scroll-mt-[5rem]"
|
||||
>
|
||||
{#each sections as section}
|
||||
<div class="px-6 md:px-14 lg:px-20 max-w-full">
|
||||
<h1 id={section.sectionId} class="header-anchor">
|
||||
{section.title}
|
||||
<a
|
||||
href={"#" + section.sectionId}
|
||||
aria-hidden="true"
|
||||
tabindex="-1"
|
||||
>
|
||||
#
|
||||
</a>
|
||||
</h1>
|
||||
|
||||
{#each snippets.filter((s) => s.sectionId === section.sectionId) as snippet}
|
||||
<div
|
||||
id={section.sectionId + "." + snippet.snippetId}
|
||||
data-snippet-id={section.sectionId +
|
||||
"." +
|
||||
snippet.snippetId}
|
||||
>
|
||||
<h2
|
||||
class="header-anchor sticky py-2 top-[2.9531rem] z-10 bg-[var(--bg-color)]"
|
||||
>
|
||||
{snippet.title}
|
||||
<a
|
||||
href={"#" + snippet.snippetId}
|
||||
aria-hidden="true"
|
||||
tabindex="-1"
|
||||
>
|
||||
#
|
||||
</a>
|
||||
</h2>
|
||||
{#if frameworkIdsSelectedStorageInitialized}
|
||||
<div
|
||||
class="grid grid-cols-1 2xl:grid-cols-2 gap-x-10"
|
||||
style="margin-top: 1rem;"
|
||||
>
|
||||
{#each [...frameworkIdsSelected] as frameworkId (frameworkId)}
|
||||
{@const framework = FRAMEWORKS.find(
|
||||
(f) => f.id === frameworkId
|
||||
)}
|
||||
{@const frameworkSnippet = snippetsByFrameworkId
|
||||
.get(frameworkId)
|
||||
?.find((s) => s.snippetId === snippet.snippetId)}
|
||||
{#if frameworkSnippet}
|
||||
<div style:margin-top="0rem" style:order="0">
|
||||
<div
|
||||
class="flex justify-between items-center space-x-3"
|
||||
>
|
||||
<h3
|
||||
style="margin-top: 0rem; margin-bottom: 0rem;"
|
||||
>
|
||||
<FrameworkLabel id={framework.id} />
|
||||
</h3>
|
||||
<div class="flex items-center space-x-3">
|
||||
{#if frameworkSnippet.playgroundURL}
|
||||
<a
|
||||
href={frameworkSnippet.playgroundURL}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<button
|
||||
class="opacity-50 hover:opacity-100 bg-gray-800 hover:bg-gray-700 py-1 px-1.5 rounded transition-all"
|
||||
title={`Open playground for ${framework.title}`}
|
||||
aria-label={`Open playground for ${framework.title}`}
|
||||
>
|
||||
<PlayIcon class="h-4 w-4" />
|
||||
</button>
|
||||
</a>
|
||||
{/if}
|
||||
<a
|
||||
href={frameworkSnippet.snippetEditHref}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<button
|
||||
class="opacity-50 hover:opacity-100 bg-gray-800 hover:bg-gray-700 py-1 px-1.5 rounded transition-all"
|
||||
title="Edit on Github"
|
||||
aria-label="Edit on Github"
|
||||
>
|
||||
<PencilIcon class="h-4 w-4" />
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
{#if frameworkSnippet.markdownFiles.length > 0}
|
||||
<div class="space-y-2">
|
||||
{#each frameworkSnippet.markdownFiles as markdownFile}
|
||||
<div>
|
||||
{@html markdownFile.contentHtml}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{:else if frameworkSnippet.files.length > 0}
|
||||
<CodeEditor files={frameworkSnippet.files} />
|
||||
{:else}
|
||||
<div
|
||||
class="bg-gray-800 text-white rounded-md mx-auto"
|
||||
>
|
||||
<div class="text-center py-8 px-4 sm:px-6">
|
||||
<div>
|
||||
<span
|
||||
class="block text-2xl tracking-tight font-bold"
|
||||
>
|
||||
Missing snippet
|
||||
</span>
|
||||
<span
|
||||
class="block text-lg mt-1 font-semibold space-x-1"
|
||||
>
|
||||
<span>
|
||||
Help us to improve Component Party
|
||||
</span>
|
||||
<img
|
||||
src="/popper.svg"
|
||||
alt="logo"
|
||||
class="size-5 m-0 inline-block"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="mt-6 flex justify-center">
|
||||
<div
|
||||
class="inline-flex rounded-md shadow"
|
||||
>
|
||||
<a
|
||||
class="inline-flex space-x-2 items-center justify-center px-4 py-2 border border-transparent text-base font-medium rounded-md text-white bg-[#161b22] hover:bg-[#161b22]/80 no-underline"
|
||||
href={frameworkSnippet.snippetEditHref}
|
||||
>
|
||||
<button
|
||||
class="flex items-center space-x-3"
|
||||
>
|
||||
<span>Contribute on Github</span>
|
||||
<GithubIcon class="h-5 w-5" />
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.header-anchor > a {
|
||||
float: left;
|
||||
margin-left: -0.87em;
|
||||
padding-right: 0.23em;
|
||||
font-weight: 500;
|
||||
transition:
|
||||
color 0.25s,
|
||||
opacity 0.25s;
|
||||
opacity: 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.header-anchor:hover > a {
|
||||
opacity: 100;
|
||||
}
|
||||
</style>
|
||||
<Router {routes} />
|
||||
|
||||
453
src/Index.svelte
Normal file
453
src/Index.svelte
Normal file
@@ -0,0 +1,453 @@
|
||||
<script>
|
||||
import FRAMEWORKS, { matchFrameworkId } from "../frameworks.mjs";
|
||||
import c from "classnames";
|
||||
import FrameworkLabel from "./components/FrameworkLabel.svelte";
|
||||
import { sections, snippets } from "./generatedContent/tree.js";
|
||||
import snippetsImporterByFrameworkId from "./generatedContent/framework/index.js";
|
||||
import { PlayIcon, PencilIcon, ArrowUpIcon } from "heroiconsvelte/24/outline";
|
||||
import CodeEditor from "./components/CodeEditor.svelte";
|
||||
import AppNotificationCenter from "./components/AppNotificationCenter.svelte";
|
||||
import createLocaleStorage from "./lib/createLocaleStorage.js";
|
||||
import { onMount } from "svelte";
|
||||
import Header from "./components/Header.svelte";
|
||||
import Aside from "./components/Aside.svelte";
|
||||
import GithubIcon from "./components/GithubIcon.svelte";
|
||||
import { navigateTo } from "svelte-router-spa";
|
||||
|
||||
export let currentRoute;
|
||||
|
||||
const frameworkIdsStorage = createLocaleStorage("framework_display");
|
||||
|
||||
function removeSearchParamKeyFromURL(k) {
|
||||
// Get the current search params as an object
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
|
||||
if (!searchParams.has(k)) {
|
||||
// The key doesn't exist, so don't do anything
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove the parameter you want to remove
|
||||
searchParams.delete(k);
|
||||
|
||||
let newUrl = window.location.pathname;
|
||||
if (searchParams.toString().length > 0) {
|
||||
// There are still search params, so include the `?` character
|
||||
newUrl += `?${searchParams}`;
|
||||
}
|
||||
|
||||
// Update the URL without reloading the page
|
||||
history.replaceState({}, "", newUrl);
|
||||
}
|
||||
|
||||
const frameworkIdsFromURLKey = "f";
|
||||
let frameworkIdsSelected = new Set();
|
||||
let snippetsByFrameworkId = new Map();
|
||||
let frameworkIdsSelectedInitialized = false;
|
||||
let isVersusFrameworks = false;
|
||||
let onMountCallbacks = new Set();
|
||||
let isMounted = false;
|
||||
|
||||
// -- on route change --
|
||||
$: {
|
||||
window.scrollTo(0, 0);
|
||||
isVersusFrameworks = false;
|
||||
if (currentRoute.name === "/") {
|
||||
if (isMounted) {
|
||||
handleInitialFrameworkIdsSelectedFromStorage();
|
||||
} else {
|
||||
onMountCallbacks.add(handleInitialFrameworkIdsSelectedFromStorage);
|
||||
}
|
||||
} else if (currentRoute.namedParams?.versus) {
|
||||
const versusFrameworks = handleVersus(currentRoute.namedParams.versus);
|
||||
if (versusFrameworks) {
|
||||
isVersusFrameworks = true;
|
||||
frameworkIdsSelected = new Set(versusFrameworks.map((f) => f.id));
|
||||
frameworkIdsSelectedInitialized = true;
|
||||
} else {
|
||||
navigateTo("/");
|
||||
}
|
||||
} else {
|
||||
navigateTo("/");
|
||||
}
|
||||
}
|
||||
|
||||
function handleInitialFrameworkIdsSelectedFromStorage() {
|
||||
let frameworkIdsSelectedOnInit = [];
|
||||
|
||||
const url = new URL(window.location.href);
|
||||
|
||||
const frameworkIdsFromURLStr = url.searchParams.get(frameworkIdsFromURLKey);
|
||||
|
||||
if (frameworkIdsFromURLStr) {
|
||||
const frameworkIdsFromURL = frameworkIdsFromURLStr
|
||||
.split(",")
|
||||
.filter(matchFrameworkId);
|
||||
if (frameworkIdsFromURL.length > 0) {
|
||||
frameworkIdsSelectedOnInit = frameworkIdsFromURL;
|
||||
} else {
|
||||
removeSearchParamKeyFromURL(frameworkIdsFromURLKey);
|
||||
}
|
||||
}
|
||||
|
||||
if (frameworkIdsSelectedOnInit.length === 0) {
|
||||
const frameworkIdsFromStorage = frameworkIdsStorage.getJSON();
|
||||
if (frameworkIdsFromStorage?.length > 0) {
|
||||
frameworkIdsSelectedOnInit = frameworkIdsFromStorage.map((x) =>
|
||||
x === "svelte" ? "svelte4" : x
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (frameworkIdsSelectedOnInit.length === 0) {
|
||||
frameworkIdsSelectedOnInit = ["react", "svelte4"];
|
||||
}
|
||||
|
||||
frameworkIdsSelected = new Set(frameworkIdsSelectedOnInit);
|
||||
frameworkIdsSelectedInitialized = true;
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
isMounted = true;
|
||||
for (const callback of onMountCallbacks) {
|
||||
callback();
|
||||
}
|
||||
onMountCallbacks.clear();
|
||||
onMountCallbacks = onMountCallbacks;
|
||||
});
|
||||
|
||||
function saveFrameworkIdsSelectedOnStorage() {
|
||||
frameworkIdsStorage.setJSON([...frameworkIdsSelected]);
|
||||
removeSearchParamKeyFromURL(frameworkIdsFromURLKey);
|
||||
}
|
||||
|
||||
function toggleFrameworkId(frameworkId) {
|
||||
if (frameworkIdsSelected.has(frameworkId)) {
|
||||
frameworkIdsSelected.delete(frameworkId);
|
||||
} else {
|
||||
frameworkIdsSelected.add(frameworkId);
|
||||
}
|
||||
frameworkIdsSelected = frameworkIdsSelected;
|
||||
saveFrameworkIdsSelectedOnStorage();
|
||||
}
|
||||
|
||||
$: {
|
||||
async function importFrameworkSnippets(frameworkIds) {
|
||||
for (const frameworkId of frameworkIds) {
|
||||
if (!snippetsByFrameworkId.has(frameworkId)) {
|
||||
const frameworkSnippets = (
|
||||
await snippetsImporterByFrameworkId[frameworkId]()
|
||||
).default;
|
||||
snippetsByFrameworkId.set(frameworkId, frameworkSnippets);
|
||||
}
|
||||
}
|
||||
|
||||
snippetsByFrameworkId = snippetsByFrameworkId;
|
||||
}
|
||||
|
||||
importFrameworkSnippets([...frameworkIdsSelected]);
|
||||
}
|
||||
|
||||
const MAX_FRAMEWORK_NB_INITIAL_DISPLAYED = 10;
|
||||
|
||||
const FRAMEWORKS_INITIAL_DISPLAYED = FRAMEWORKS.slice(
|
||||
0,
|
||||
MAX_FRAMEWORK_NB_INITIAL_DISPLAYED
|
||||
);
|
||||
|
||||
const FRAMEWORKS_MORE = FRAMEWORKS.slice(MAX_FRAMEWORK_NB_INITIAL_DISPLAYED);
|
||||
|
||||
$: frameworksSelected = [...frameworkIdsSelected].map(matchFrameworkId);
|
||||
|
||||
$: frameworksNotSelected = FRAMEWORKS_INITIAL_DISPLAYED.filter(
|
||||
(f) => !frameworkIdsSelected.has(f.id)
|
||||
);
|
||||
|
||||
$: frameworksMoreNotSelected = FRAMEWORKS_MORE.filter(
|
||||
(f) => !frameworkIdsSelected.has(f.id)
|
||||
);
|
||||
|
||||
let showBonusFrameworks = false;
|
||||
|
||||
function handleVersus(versus) {
|
||||
const fids = versus.split("-vs-");
|
||||
|
||||
if (fids.length !== 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const frameworks = fids.map(matchFrameworkId);
|
||||
|
||||
if (frameworks.some((f) => !f)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return frameworks;
|
||||
}
|
||||
</script>
|
||||
|
||||
<AppNotificationCenter />
|
||||
|
||||
<Header {frameworksSelected} />
|
||||
|
||||
<div class="flex border-b border-gray-700">
|
||||
<Aside />
|
||||
<div class="pb-8 w-10 grow">
|
||||
<div
|
||||
class="flex px-6 lg:px-20 py-2 sticky top-0 z-20 w-full backdrop-blur bg-gray-900/80 border-b border-gray-700 whitespace-nowrap overflow-x-auto"
|
||||
>
|
||||
{#each [...frameworksSelected, ...frameworksNotSelected] as framework (framework.id)}
|
||||
<button
|
||||
title={`Display ${framework.title}`}
|
||||
class={c(
|
||||
"text-sm flex-shrink-0 rounded border border-gray-700 px-3 py-1 border-opacity-50 bg-gray-900 hover:bg-gray-800 transition-all mr-2",
|
||||
frameworkIdsSelected.has(framework.id)
|
||||
? "border-blue-500"
|
||||
: "opacity-70"
|
||||
)}
|
||||
on:click={() => {
|
||||
toggleFrameworkId(framework.id);
|
||||
if (isVersusFrameworks && currentRoute.name !== "/") {
|
||||
navigateTo("/");
|
||||
}
|
||||
}}
|
||||
>
|
||||
<FrameworkLabel id={framework.id} size={15} />
|
||||
</button>
|
||||
{/each}
|
||||
{#if showBonusFrameworks}
|
||||
{#each frameworksMoreNotSelected as framework (framework.id)}
|
||||
<button
|
||||
title={`Display ${framework.title}`}
|
||||
class={c(
|
||||
"text-sm flex-shrink-0 rounded border border-gray-700 px-3 py-1 border-opacity-50 bg-gray-900 hover:bg-gray-800 transition-all mr-2",
|
||||
frameworkIdsSelected.has(framework.id)
|
||||
? "border-blue-500"
|
||||
: "opacity-70"
|
||||
)}
|
||||
on:click={() => toggleFrameworkId(framework.id)}
|
||||
>
|
||||
<FrameworkLabel id={framework.id} size={15} />
|
||||
</button>
|
||||
{/each}
|
||||
{:else if frameworksMoreNotSelected.length > 0}
|
||||
<button
|
||||
title="more"
|
||||
class="opacity-70 text-sm flex-shrink-0 rounded border border-gray-700 px-3 py-1 border-opacity-50 bg-gray-900 hover:bg-gray-800 transition-all mr-2"
|
||||
on:click={() => {
|
||||
showBonusFrameworks = !showBonusFrameworks;
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="size-4"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M6.75 12a.75.75 0 11-1.5 0 .75.75 0 011.5 0zM12.75 12a.75.75 0 11-1.5 0 .75.75 0 011.5 0zM18.75 12a.75.75 0 11-1.5 0 .75.75 0 011.5 0z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<main class="relative pt-10">
|
||||
<div>
|
||||
{#if frameworkIdsSelected.size === 0}
|
||||
<div class="space-y-4">
|
||||
<div class="flex justify-center">
|
||||
<ArrowUpIcon class="size-6 animate-bounce" />
|
||||
</div>
|
||||
<div class="flex justify-center">
|
||||
<p
|
||||
class="text-lg opacity-80 flex items-center text-center space-x-3"
|
||||
>
|
||||
<img src="/popper.svg" alt="logo" class="size-6" />
|
||||
<span>
|
||||
Please select a framework to view framework's snippets
|
||||
</span>
|
||||
<img src="/popper.svg" alt="logo" class="size-6" />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div
|
||||
class="max-w-full prose prose-sm prose-invert prose-h1:font-semibold prose-h2:font-medium prose-h3:font-medium prose-h1:scroll-mt-[5rem] prose-pre:mt-0 prose-h2:scroll-mt-[5rem]"
|
||||
>
|
||||
{#each sections as section}
|
||||
<div class="px-6 md:px-14 lg:px-20 max-w-full">
|
||||
<h1 id={section.sectionId} class="header-anchor">
|
||||
{section.title}
|
||||
<a
|
||||
href={"#" + section.sectionId}
|
||||
aria-hidden="true"
|
||||
tabindex="-1"
|
||||
>
|
||||
#
|
||||
</a>
|
||||
</h1>
|
||||
|
||||
{#each snippets.filter((s) => s.sectionId === section.sectionId) as snippet}
|
||||
<div
|
||||
id={section.sectionId + "." + snippet.snippetId}
|
||||
data-snippet-id={section.sectionId +
|
||||
"." +
|
||||
snippet.snippetId}
|
||||
>
|
||||
<h2
|
||||
class="header-anchor sticky py-2 top-[2.9531rem] z-10 bg-[var(--bg-color)]"
|
||||
>
|
||||
{snippet.title}
|
||||
<a
|
||||
href={"#" + snippet.snippetId}
|
||||
aria-hidden="true"
|
||||
tabindex="-1"
|
||||
>
|
||||
#
|
||||
</a>
|
||||
</h2>
|
||||
{#if frameworkIdsSelectedInitialized}
|
||||
<div
|
||||
class="grid grid-cols-1 2xl:grid-cols-2 gap-x-10"
|
||||
style="margin-top: 1rem;"
|
||||
>
|
||||
{#each [...frameworkIdsSelected] as frameworkId (frameworkId)}
|
||||
{@const framework = matchFrameworkId(frameworkId)}
|
||||
{@const frameworkSnippet = snippetsByFrameworkId
|
||||
.get(frameworkId)
|
||||
?.find((s) => s.snippetId === snippet.snippetId)}
|
||||
{#if frameworkSnippet}
|
||||
<div style:margin-top="0rem" style:order="0">
|
||||
<div
|
||||
class="flex justify-between items-center space-x-3"
|
||||
>
|
||||
<h3
|
||||
style="margin-top: 0rem; margin-bottom: 0rem;"
|
||||
>
|
||||
<FrameworkLabel id={framework.id} />
|
||||
</h3>
|
||||
<div class="flex items-center space-x-3">
|
||||
{#if frameworkSnippet.playgroundURL}
|
||||
<a
|
||||
href={frameworkSnippet.playgroundURL}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<button
|
||||
class="opacity-50 hover:opacity-100 bg-gray-800 hover:bg-gray-700 py-1 px-1.5 rounded transition-all"
|
||||
title={`Open playground for ${framework.title}`}
|
||||
aria-label={`Open playground for ${framework.title}`}
|
||||
>
|
||||
<PlayIcon class="h-4 w-4" />
|
||||
</button>
|
||||
</a>
|
||||
{/if}
|
||||
<a
|
||||
href={frameworkSnippet.snippetEditHref}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<button
|
||||
class="opacity-50 hover:opacity-100 bg-gray-800 hover:bg-gray-700 py-1 px-1.5 rounded transition-all"
|
||||
title="Edit on Github"
|
||||
aria-label="Edit on Github"
|
||||
>
|
||||
<PencilIcon class="h-4 w-4" />
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
{#if frameworkSnippet.markdownFiles.length > 0}
|
||||
<div class="space-y-2">
|
||||
{#each frameworkSnippet.markdownFiles as markdownFile}
|
||||
<div>
|
||||
{@html markdownFile.contentHtml}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{:else if frameworkSnippet.files.length > 0}
|
||||
<CodeEditor files={frameworkSnippet.files} />
|
||||
{:else}
|
||||
<div
|
||||
class="bg-gray-800 text-white rounded-md mx-auto"
|
||||
>
|
||||
<div class="text-center py-8 px-4 sm:px-6">
|
||||
<div>
|
||||
<span
|
||||
class="block text-2xl tracking-tight font-bold"
|
||||
>
|
||||
Missing snippet
|
||||
</span>
|
||||
<span
|
||||
class="block text-lg mt-1 font-semibold space-x-1"
|
||||
>
|
||||
<span>
|
||||
Help us to improve Component Party
|
||||
</span>
|
||||
<img
|
||||
src="/popper.svg"
|
||||
alt="logo"
|
||||
class="size-5 m-0 inline-block"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="mt-6 flex justify-center">
|
||||
<div
|
||||
class="inline-flex rounded-md shadow"
|
||||
>
|
||||
<a
|
||||
class="inline-flex space-x-2 items-center justify-center px-4 py-2 border border-transparent text-base font-medium rounded-md text-white bg-[#161b22] hover:bg-[#161b22]/80 no-underline"
|
||||
href={frameworkSnippet.snippetEditHref}
|
||||
>
|
||||
<button
|
||||
class="flex items-center space-x-3"
|
||||
>
|
||||
<span>Contribute on Github</span>
|
||||
<GithubIcon class="h-5 w-5" />
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.header-anchor > a {
|
||||
float: left;
|
||||
margin-left: -0.87em;
|
||||
padding-right: 0.23em;
|
||||
font-weight: 500;
|
||||
transition:
|
||||
color 0.25s,
|
||||
opacity 0.25s;
|
||||
opacity: 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.header-anchor:hover > a {
|
||||
opacity: 100;
|
||||
}
|
||||
</style>
|
||||
@@ -7,6 +7,8 @@ import { Eta } from "eta";
|
||||
import FRAMEWORKS from "./frameworks.mjs";
|
||||
import pluginGenerateFrameworkContent from "./build/generateContentVitePlugin.js";
|
||||
|
||||
// @TODO: sitemap
|
||||
|
||||
const footerNavigation = [
|
||||
{
|
||||
title: "Most Popular Frameworks",
|
||||
@@ -33,24 +35,24 @@ const footerNavigation = [
|
||||
{
|
||||
title: "Comparing Legacy version & Current Version",
|
||||
links: [
|
||||
{ name: "Vue 2 vs. Vue 3", url: "/compare/vue-2-vs-vue-3" },
|
||||
{ name: "Vue 2 vs. Vue 3", url: "/compare/vue2-vs-vue3" },
|
||||
{
|
||||
name: "Aurelia 1 vs. Aurelia 2",
|
||||
url: "/compare/aurelia-1-vs-aurelia-2",
|
||||
url: "/compare/aurelia1-vs-aurelia2",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Comparing Current Version & Upcoming Version",
|
||||
links: [
|
||||
{ name: "Svelte 4 vs. Svelte 5", url: "/compare/svelte-4-vs-svelte-5" },
|
||||
{ name: "Svelte 4 vs. Svelte 5", url: "/compare/svelte4-vs-svelte5" },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const footerLinks = footerNavigation.map((n) => n.links).flat();
|
||||
|
||||
const sharedTemplateData = {
|
||||
const templateDataDefaults = {
|
||||
title: "Component Party",
|
||||
url: "https://component-party.dev/",
|
||||
description: `Web component JS frameworks overview by their syntax and features: ${FRAMEWORKS.map((f) => f.title).join(", ")}`,
|
||||
@@ -67,14 +69,14 @@ export default defineConfig({
|
||||
outputPath: `${link.url}.html`,
|
||||
template: "dist/index.html",
|
||||
templateData: {
|
||||
...sharedTemplateData,
|
||||
title: `${link.name} - ${sharedTemplateData.title}`,
|
||||
...templateDataDefaults,
|
||||
title: `${link.name} - ${templateDataDefaults.title}`,
|
||||
},
|
||||
})),
|
||||
{
|
||||
outputPath: "index.html",
|
||||
template: "dist/index.html",
|
||||
templateData: sharedTemplateData,
|
||||
templateData: templateDataDefaults,
|
||||
},
|
||||
]),
|
||||
],
|
||||
@@ -119,7 +121,11 @@ async function generateHtmlPagesPlugin(pages) {
|
||||
const matchedPage = pages.find(
|
||||
(page) => ctx.originalUrl === filePathToUrl(page.outputPath)
|
||||
);
|
||||
html = htmlTransform.render(html, matchedPage.templateData);
|
||||
if (matchedPage) {
|
||||
html = htmlTransform.render(html, matchedPage.templateData);
|
||||
} else {
|
||||
html = htmlTransform.render(html, templateDataDefaults);
|
||||
}
|
||||
}
|
||||
return html;
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user