Compare commits
93 Commits
@portaljs/
...
feature/se
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d367deaea3 | ||
|
|
3e9eadcc69 | ||
|
|
da226ef205 | ||
|
|
a37a31f89a | ||
|
|
03c27df800 | ||
|
|
d198130038 | ||
|
|
06209877ea | ||
|
|
822a3ce5ec | ||
|
|
1f06c67d13 | ||
|
|
9dea140859 | ||
|
|
d5899b22ab | ||
|
|
dc895ed277 | ||
|
|
7315df8a86 | ||
|
|
349f5bea66 | ||
|
|
6aef860a81 | ||
|
|
e908cb9344 | ||
|
|
1a22e54d5b | ||
|
|
172b4b71d4 | ||
|
|
3873852567 | ||
|
|
5e349855a2 | ||
|
|
40bd9e0311 | ||
|
|
b437b58d06 | ||
|
|
c3137ba1cb | ||
|
|
2e13c1b738 | ||
|
|
122870a23e | ||
|
|
4e282e0d86 | ||
|
|
6020f76adb | ||
|
|
f3c2a2ffa7 | ||
|
|
11659a838b | ||
|
|
58b7b4e753 | ||
|
|
7cf8c31e53 | ||
|
|
df000b9e8f | ||
|
|
77e9f58899 | ||
|
|
0737aaafb2 | ||
|
|
d798f402f6 | ||
|
|
80c6221a05 | ||
|
|
f04b86dda4 | ||
|
|
0fd3ee9912 | ||
|
|
cb0b9b1f14 | ||
|
|
9ee4376abf | ||
|
|
5a0ddd91ce | ||
|
|
d097bc765b | ||
|
|
b283fc1e99 | ||
|
|
0511e00d83 | ||
|
|
c8afa775d4 | ||
|
|
7ba9b5157e | ||
|
|
6c2a1ea125 | ||
|
|
343faf72cf | ||
|
|
1eb3f7367b | ||
|
|
8cdf54397f | ||
|
|
fb94cb9ce9 | ||
|
|
4595cd2231 | ||
|
|
aa2c8aac04 | ||
|
|
f2e5459297 | ||
|
|
e111adfe73 | ||
|
|
492c21ca4e | ||
|
|
0581357df8 | ||
|
|
15ceeec035 | ||
|
|
1caabcf6b4 | ||
|
|
b548dfd113 | ||
|
|
c5ee257d48 | ||
|
|
8d83f3a900 | ||
|
|
add2f6d0f3 | ||
|
|
dfab6aa318 | ||
|
|
f96fb562fe | ||
|
|
c4bf5bd054 | ||
|
|
c706575ae4 | ||
|
|
ed8de380a9 | ||
|
|
33521916d6 | ||
|
|
04206457a4 | ||
|
|
8a5acb7012 | ||
|
|
32493a2014 | ||
|
|
b34220cac7 | ||
|
|
44b37e27d9 | ||
|
|
6d3e571151 | ||
|
|
0e997f71e5 | ||
|
|
4a41d517ee | ||
|
|
c79b69ffe6 | ||
|
|
2ad6551a44 | ||
|
|
5de9888c02 | ||
|
|
5a517d714a | ||
|
|
746c77de11 | ||
|
|
9e256b9bf1 | ||
|
|
4bfcd4373b | ||
|
|
6649f78459 | ||
|
|
6f0da8c3a3 | ||
|
|
5b1238cc27 | ||
|
|
17803f1f5d | ||
|
|
81f50bb9a2 | ||
|
|
f1aee6a93e | ||
|
|
053005d784 | ||
|
|
095eba606e | ||
|
|
1097b5077d |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,6 +4,7 @@
|
||||
dist
|
||||
tmp
|
||||
/out-tsc
|
||||
**/*.tgz
|
||||
|
||||
# dependencies
|
||||
node_modules
|
||||
|
||||
160
examples/ckan-ssg/package-lock.json
generated
160
examples/ckan-ssg/package-lock.json
generated
@@ -10,6 +10,7 @@
|
||||
"dependencies": {
|
||||
"@heroicons/react": "^2.0.17",
|
||||
"@portaljs/ckan": "^0.0.2",
|
||||
"@portaljs/remark-wiki-link": "^1.0.4",
|
||||
"next": "13.3.1",
|
||||
"next-seo": "^6.0.0",
|
||||
"octokit": "^2.0.14",
|
||||
@@ -35,7 +36,6 @@
|
||||
"version": "7.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz",
|
||||
"integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.13.11"
|
||||
},
|
||||
@@ -732,6 +732,16 @@
|
||||
"react-dom": "^18.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@portaljs/remark-wiki-link": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@portaljs/remark-wiki-link/-/remark-wiki-link-1.0.4.tgz",
|
||||
"integrity": "sha512-cp6vlssDAPawcBI0vUPRpcPdORql3RbK1Q+t1LuRvMQ+yiRb+9DnSPBUviDXKqwsBMOOXP/ePAdYohaeXGt0lQ==",
|
||||
"dependencies": {
|
||||
"mdast-util-to-markdown": "^1.5.0",
|
||||
"mdast-util-wiki-link": "^0.0.2",
|
||||
"micromark-util-symbol": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@rushstack/eslint-patch": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz",
|
||||
@@ -1420,6 +1430,24 @@
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/character-entities-legacy": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz",
|
||||
"integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/character-reference-invalid": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz",
|
||||
"integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||
@@ -2888,6 +2916,28 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/is-alphabetical": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
|
||||
"integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/is-alphanumerical": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
|
||||
"integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
|
||||
"dependencies": {
|
||||
"is-alphabetical": "^1.0.0",
|
||||
"is-decimal": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/is-arguments": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
|
||||
@@ -3019,6 +3069,15 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-decimal": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz",
|
||||
"integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/is-docker": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
|
||||
@@ -3055,6 +3114,15 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-hexadecimal": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
|
||||
"integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/is-map": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
|
||||
@@ -3727,6 +3795,59 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-wiki-link": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/mdast-util-wiki-link/-/mdast-util-wiki-link-0.0.2.tgz",
|
||||
"integrity": "sha512-lSsR10/dPuYIxzjGZIGA4oYzsnEnqcsD6DTXL0pqdbBzNB9teKVZB2aIzZcUsdg31v/NoHOstkVwzbN6VrQLtw==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.1",
|
||||
"mdast-util-to-markdown": "^0.6.5"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-wiki-link/node_modules/longest-streak": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz",
|
||||
"integrity": "sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-wiki-link/node_modules/mdast-util-to-markdown": {
|
||||
"version": "0.6.5",
|
||||
"resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz",
|
||||
"integrity": "sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ==",
|
||||
"dependencies": {
|
||||
"@types/unist": "^2.0.0",
|
||||
"longest-streak": "^2.0.0",
|
||||
"mdast-util-to-string": "^2.0.0",
|
||||
"parse-entities": "^2.0.0",
|
||||
"repeat-string": "^1.0.0",
|
||||
"zwitch": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-wiki-link/node_modules/mdast-util-to-string": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz",
|
||||
"integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-wiki-link/node_modules/zwitch": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz",
|
||||
"integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/merge2": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||
@@ -4714,6 +4835,32 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/parse-entities": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz",
|
||||
"integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==",
|
||||
"dependencies": {
|
||||
"character-entities": "^1.0.0",
|
||||
"character-entities-legacy": "^1.0.0",
|
||||
"character-reference-invalid": "^1.0.0",
|
||||
"is-alphanumerical": "^1.0.0",
|
||||
"is-decimal": "^1.0.0",
|
||||
"is-hexadecimal": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/parse-entities/node_modules/character-entities": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz",
|
||||
"integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
@@ -5083,8 +5230,7 @@
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.13.11",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
|
||||
},
|
||||
"node_modules/regexp.prototype.flags": {
|
||||
"version": "1.5.0",
|
||||
@@ -5147,6 +5293,14 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/repeat-string": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
|
||||
"integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.2",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"dependencies": {
|
||||
"@heroicons/react": "^2.0.17",
|
||||
"@portaljs/ckan": "^0.0.2",
|
||||
"@portaljs/remark-wiki-link": "^1.0.4",
|
||||
"next": "13.3.1",
|
||||
"next-seo": "^6.0.0",
|
||||
"octokit": "^2.0.14",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { MDXRemote } from 'next-mdx-remote';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { Mermaid } from '@flowershow/core';
|
||||
import { Mermaid } from '@portaljs/core';
|
||||
|
||||
// Custom components/renderers to pass to MDX.
|
||||
// Since the MDX files aren't loaded by webpack, they have no knowledge of how
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import matter from "gray-matter";
|
||||
import mdxmermaid from "mdx-mermaid";
|
||||
import { h } from "hastscript";
|
||||
import remarkCallouts from "@flowershow/remark-callouts";
|
||||
import remarkEmbed from "@flowershow/remark-embed";
|
||||
import remarkCallouts from "@portaljs/remark-callouts";
|
||||
import remarkEmbed from "@portaljs/remark-embed";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import remarkMath from "remark-math";
|
||||
import remarkSmartypants from "remark-smartypants";
|
||||
import remarkToc from "remark-toc";
|
||||
import remarkWikiLink from "@flowershow/remark-wiki-link";
|
||||
import remarkWikiLink from "@portaljs/remark-wiki-link";
|
||||
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
||||
import rehypeKatex from "rehype-katex";
|
||||
import rehypeSlug from "rehype-slug";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MarkdownDB } from "@flowershow/markdowndb";
|
||||
import { MarkdownDB } from "mddb";
|
||||
|
||||
const dbPath = "markdown.db";
|
||||
|
||||
|
||||
1099
examples/ckan/package-lock.json
generated
1099
examples/ckan/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -11,14 +11,14 @@
|
||||
"mddb": "mddb ./content"
|
||||
},
|
||||
"dependencies": {
|
||||
"@flowershow/core": "^0.4.13",
|
||||
"@flowershow/markdowndb": "^0.1.5",
|
||||
"@flowershow/remark-callouts": "^1.0.0",
|
||||
"@flowershow/remark-embed": "^1.0.0",
|
||||
"@githubocto/flat-ui": "^0.14.1",
|
||||
"@heroicons/react": "^2.0.18",
|
||||
"@portaljs/ckan": "^0.0.2",
|
||||
"@portaljs/components": "0.1.6",
|
||||
"@portaljs/core": "^1.0.5",
|
||||
"@portaljs/remark-callouts": "^1.0.5",
|
||||
"@portaljs/remark-embed": "^1.0.4",
|
||||
"@portaljs/remark-wiki-link": "^1.0.4",
|
||||
"@tailwindcss/typography": "^0.5.9",
|
||||
"@types/node": "20.2.3",
|
||||
"@types/react": "18.2.6",
|
||||
@@ -27,6 +27,7 @@
|
||||
"eslint": "8.41.0",
|
||||
"eslint-config-next": "13.4.3",
|
||||
"isomorphic-unfetch": "^4.0.2",
|
||||
"mddb": "^0.1.9",
|
||||
"next": "13.4.3",
|
||||
"next-mdx-remote": "^4.4.1",
|
||||
"papaparse": "^5.4.1",
|
||||
|
||||
@@ -40,16 +40,25 @@ export default function Home({
|
||||
});
|
||||
|
||||
return (
|
||||
<main className="flex min-h-screen flex-col items-center p-24 bg-zinc-900">
|
||||
<DatasetSearchForm
|
||||
options={options}
|
||||
setOptions={setOptions}
|
||||
groups={groups}
|
||||
orgs={orgs}
|
||||
/>
|
||||
<div className="bg-white p-8 my-4 rounded-lg">
|
||||
<ListOfDatasets options={options} setOptions={setOptions} ckan={ckan} />{' '}
|
||||
</div>
|
||||
</main>
|
||||
<div>
|
||||
<main className="py-12 bg-zinc-900">
|
||||
<DatasetSearchForm
|
||||
options={options}
|
||||
setOptions={setOptions}
|
||||
groups={groups}
|
||||
orgs={orgs}
|
||||
/>
|
||||
<div
|
||||
className="bg-white p-8 mx-auto my-4 rounded-lg"
|
||||
style={{ width: 'min(1100px, 95vw)' }}
|
||||
>
|
||||
<ListOfDatasets
|
||||
options={options}
|
||||
setOptions={setOptions}
|
||||
ckan={ckan}
|
||||
/>{' '}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@import "@flowershow/remark-callouts/styles.css";
|
||||
@import "@portaljs/remark-callouts/styles.css";
|
||||
|
||||
/* mathjax */
|
||||
.math-inline > mjx-container > svg {
|
||||
|
||||
1069
examples/fivethirtyeight/package-lock.json
generated
1069
examples/fivethirtyeight/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -9,10 +9,11 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@flowershow/core": "^0.4.13",
|
||||
"@headlessui/react": "^1.7.14",
|
||||
"@heroicons/react": "^2.0.18",
|
||||
"@portaljs/components": "^0.1.8",
|
||||
"@portaljs/core": "^1.0.5",
|
||||
"@portaljs/remark-wiki-link": "^1.0.4",
|
||||
"@tailwindcss/typography": "^0.5.9",
|
||||
"@types/node": "20.1.1",
|
||||
"@types/react": "18.2.6",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import '@/styles/globals.css';
|
||||
import '@portaljs/components/styles.css';
|
||||
import { useEffect } from 'react';
|
||||
import { pageview } from '@flowershow/core';
|
||||
import { pageview } from '@portaljs/core';
|
||||
import Script from 'next/script';
|
||||
import Head from 'next/head';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { MDXRemote } from 'next-mdx-remote';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { Mermaid } from '@flowershow/core';
|
||||
import { Mermaid } from '@portaljs/core';
|
||||
|
||||
// Custom components/renderers to pass to MDX.
|
||||
// Since the MDX files aren't loaded by webpack, they have no knowledge of how
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import matter from "gray-matter";
|
||||
import mdxmermaid from "mdx-mermaid";
|
||||
import { h } from "hastscript";
|
||||
import remarkCallouts from "@flowershow/remark-callouts";
|
||||
import remarkEmbed from "@flowershow/remark-embed";
|
||||
import remarkCallouts from "@portaljs/remark-callouts";
|
||||
import remarkEmbed from "@portaljs/remark-embed";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import remarkMath from "remark-math";
|
||||
import remarkSmartypants from "remark-smartypants";
|
||||
import remarkToc from "remark-toc";
|
||||
import remarkWikiLink from "@flowershow/remark-wiki-link";
|
||||
import remarkWikiLink from "@portaljs/remark-wiki-link";
|
||||
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
||||
import rehypeKatex from "rehype-katex";
|
||||
import rehypeSlug from "rehype-slug";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MarkdownDB } from "@flowershow/markdowndb";
|
||||
import { MarkdownDB } from "mddb";
|
||||
|
||||
const dbPath = "markdown.db";
|
||||
|
||||
|
||||
586
examples/github-backed-catalog/package-lock.json
generated
586
examples/github-backed-catalog/package-lock.json
generated
@@ -8,16 +8,17 @@
|
||||
"name": "my-app",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@flowershow/core": "^0.4.13",
|
||||
"@flowershow/markdowndb": "^0.1.5",
|
||||
"@flowershow/remark-callouts": "^1.0.0",
|
||||
"@flowershow/remark-embed": "^1.0.0",
|
||||
"@portaljs/components": "^0.1.6",
|
||||
"@portaljs/core": "^1.0.5",
|
||||
"@portaljs/remark-callouts": "^1.0.5",
|
||||
"@portaljs/remark-embed": "^1.0.4",
|
||||
"@portaljs/remark-wiki-link": "^1.0.4",
|
||||
"@types/node": "18.16.0",
|
||||
"@types/react": "18.0.38",
|
||||
"@types/react-dom": "18.0.11",
|
||||
"eslint": "8.39.0",
|
||||
"eslint-config-next": "13.3.1",
|
||||
"mddb": "^0.1.9",
|
||||
"next": "13.4.3",
|
||||
"next-mdx-remote": "^4.4.1",
|
||||
"next-seo": "^6.0.0",
|
||||
@@ -45,19 +46,31 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/autocomplete-core": {
|
||||
"version": "1.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.8.2.tgz",
|
||||
"integrity": "sha512-mTeshsyFhAqw/ebqNsQpMtbnjr+qVOSKXArEj4K0d7sqc8It1XD0gkASwecm9mF/jlOQ4Z9RNg1HbdA8JPdRwQ==",
|
||||
"version": "1.9.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.2.tgz",
|
||||
"integrity": "sha512-hkG80c9kx9ClVAEcUJbTd2ziVC713x9Bji9Ty4XJfKXlxlsx3iXsoNhAwfeR4ulzIUg7OE5gez0UU1zVDdG7kg==",
|
||||
"dependencies": {
|
||||
"@algolia/autocomplete-shared": "1.8.2"
|
||||
"@algolia/autocomplete-plugin-algolia-insights": "1.9.2",
|
||||
"@algolia/autocomplete-shared": "1.9.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/autocomplete-plugin-algolia-insights": {
|
||||
"version": "1.9.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.2.tgz",
|
||||
"integrity": "sha512-2LVsf4W66hVHQ3Ua/8k15oPlxjELCztbAkQm/hP42Sw+GLkHAdY1vaVRYziaWq64+Oljfg6FKkZHCdgXH+CGIA==",
|
||||
"dependencies": {
|
||||
"@algolia/autocomplete-shared": "1.9.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"search-insights": ">= 1 < 3"
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/autocomplete-preset-algolia": {
|
||||
"version": "1.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.8.2.tgz",
|
||||
"integrity": "sha512-J0oTx4me6ZM9kIKPuL3lyU3aB8DEvpVvR6xWmHVROx5rOYJGQcZsdG4ozxwcOyiiu3qxMkIbzntnV1S1VWD8yA==",
|
||||
"version": "1.9.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.2.tgz",
|
||||
"integrity": "sha512-pqgIm2GNqtCT59Y1ICctIPrYTi34+wNPiNWEclD/yDzp5uDUUsyGe5XrUjCNyQRTKonAlmYxoaEHOn8FWgmBHA==",
|
||||
"dependencies": {
|
||||
"@algolia/autocomplete-shared": "1.8.2"
|
||||
"@algolia/autocomplete-shared": "1.9.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@algolia/client-search": ">= 4.9.1 < 6",
|
||||
@@ -65,123 +78,127 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/autocomplete-shared": {
|
||||
"version": "1.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.8.2.tgz",
|
||||
"integrity": "sha512-b6Z/X4MczChMcfhk6kfRmBzPgjoPzuS9KGR4AFsiLulLNRAAqhP+xZTKtMnZGhLuc61I20d5WqlId02AZvcO6g=="
|
||||
"version": "1.9.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.2.tgz",
|
||||
"integrity": "sha512-XxX6YDn+7LG+SmdpXEOnj7fc3TjiVpQ0CbGhjLwrd2tYr6LVY2D4Iiu/iuYJ4shvVDWWnpwArSk0uIWC/8OPUA==",
|
||||
"peerDependencies": {
|
||||
"@algolia/client-search": ">= 4.9.1 < 6",
|
||||
"algoliasearch": ">= 4.9.1 < 6"
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/cache-browser-local-storage": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.17.1.tgz",
|
||||
"integrity": "sha512-e91Jpu93X3t3mVdQwF3ZDjSFMFIfzSc+I76G4EX8nl9RYXgqcjframoL05VTjcD2YCsI18RIHAWVCBoCXVZnrw==",
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.17.2.tgz",
|
||||
"integrity": "sha512-ZkVN7K/JE+qMQbpR6h3gQOGR6yCJpmucSBCmH5YDxnrYbp2CbrVCu0Nr+FGVoWzMJNznj1waShkfQ9awERulLw==",
|
||||
"dependencies": {
|
||||
"@algolia/cache-common": "4.17.1"
|
||||
"@algolia/cache-common": "4.17.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/cache-common": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.17.1.tgz",
|
||||
"integrity": "sha512-fvi1WT8aSiGAKrcTw8Qg3RYgcwW8GZMHcqEm4AyDBEy72JZlFBSY80cTQ75MslINjCHXLDT+9EN8AGI9WVY7uA=="
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.17.2.tgz",
|
||||
"integrity": "sha512-fojbhYIS8ovfYs6hwZpy1O4mBfVRxNgAaZRqsdVQd54hU4MxYDYFCxagYX28lOBz7btcDHld6BMoWXvjzkx6iQ=="
|
||||
},
|
||||
"node_modules/@algolia/cache-in-memory": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.17.1.tgz",
|
||||
"integrity": "sha512-NbBt6eBWlsXc5geSpfPRC5dkIB/0Ptthw8r0yM5Z7D3sPlYdnTZSO9y9XWXIptRMwmZe4cM8iBMN8y0tzbcBkA==",
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.17.2.tgz",
|
||||
"integrity": "sha512-UYQcMzPurNi+cPYkuPemTZkjKAjdgAS1hagC5irujKbrYnN4yscK4TkOI5tX+O8/KegtJt3kOK07OIrJ2QDAAw==",
|
||||
"dependencies": {
|
||||
"@algolia/cache-common": "4.17.1"
|
||||
"@algolia/cache-common": "4.17.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/client-account": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.17.1.tgz",
|
||||
"integrity": "sha512-3rL/6ofJvyL+q8TiWM3qoM9tig+SY4gB1Vbsj+UeJPnJm8Khm+7OS+r+mFraqR6pTehYqN8yGYoE7x4diEn4aA==",
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.17.2.tgz",
|
||||
"integrity": "sha512-doSk89pBPDpDyKJSHFADIGa2XSGrBCj3QwPvqtRJXDADpN+OjW+eTR8r4hEs/7X4GGfjfAOAES8JgDx+fZntYw==",
|
||||
"dependencies": {
|
||||
"@algolia/client-common": "4.17.1",
|
||||
"@algolia/client-search": "4.17.1",
|
||||
"@algolia/transporter": "4.17.1"
|
||||
"@algolia/client-common": "4.17.2",
|
||||
"@algolia/client-search": "4.17.2",
|
||||
"@algolia/transporter": "4.17.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/client-analytics": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.17.1.tgz",
|
||||
"integrity": "sha512-Bepr2w249vODqeBtM7i++tPmUsQ9B81aupUGbDWmjA/FX+jzQqOdhW8w1CFO5kWViNKTbz2WBIJ9U3x8hOa4bA==",
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.17.2.tgz",
|
||||
"integrity": "sha512-V+DcXbOtD/hKwAR3qGQrtlrJ3q2f9OKfx843q744o4m3xHv5ueCAvGXB1znPsdaUrVDNAImcgEgqwI9x7EJbDw==",
|
||||
"dependencies": {
|
||||
"@algolia/client-common": "4.17.1",
|
||||
"@algolia/client-search": "4.17.1",
|
||||
"@algolia/requester-common": "4.17.1",
|
||||
"@algolia/transporter": "4.17.1"
|
||||
"@algolia/client-common": "4.17.2",
|
||||
"@algolia/client-search": "4.17.2",
|
||||
"@algolia/requester-common": "4.17.2",
|
||||
"@algolia/transporter": "4.17.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/client-common": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.17.1.tgz",
|
||||
"integrity": "sha512-+r7kg4EgbFnGsDnoGSVNtXZO8xvZ0vzf1WAOV7sqV9PMf1bp6cpJP/3IuPrSk4t5w2KVl+pC8jfTM7HcFlfBEQ==",
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.17.2.tgz",
|
||||
"integrity": "sha512-gKBUnjxi0ukJYIJxVREYGt1Dmj1B3RBYbfGWi0dIPp1BC1VvQm+BOuNwsIwmq/x3MPO+sGuK978eKiP3tZDvag==",
|
||||
"dependencies": {
|
||||
"@algolia/requester-common": "4.17.1",
|
||||
"@algolia/transporter": "4.17.1"
|
||||
"@algolia/requester-common": "4.17.2",
|
||||
"@algolia/transporter": "4.17.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/client-personalization": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.17.1.tgz",
|
||||
"integrity": "sha512-gJku9DG/THJpfsSlG/az0a3QIn+VVff9kKh8PG8+7ZfxOHS+C+Y5YSeZVsC+c2cfoKLPo3CuHIiJ/p86erR3bA==",
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.17.2.tgz",
|
||||
"integrity": "sha512-wc4UgOWxSYWz5wpuelNmlt895jA9twjZWM2ms17Ws8qCvBHF7OVGdMGgbysPB8790YnfvvDnSsWOv3CEj26Eow==",
|
||||
"dependencies": {
|
||||
"@algolia/client-common": "4.17.1",
|
||||
"@algolia/requester-common": "4.17.1",
|
||||
"@algolia/transporter": "4.17.1"
|
||||
"@algolia/client-common": "4.17.2",
|
||||
"@algolia/requester-common": "4.17.2",
|
||||
"@algolia/transporter": "4.17.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/client-search": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.17.1.tgz",
|
||||
"integrity": "sha512-Q5YfT5gVkx60PZDQBqp/zH9aUbBdC7HVvxupiHUgnCKqRQsRZjOhLest7AI6FahepuZLBZS62COrO7v+JvKY7w==",
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.17.2.tgz",
|
||||
"integrity": "sha512-FUjIs+gRe0upJC++uVs4sdxMw15JxfkT86Gr/kqVwi9kcqaZhXntSbW/Fw959bIYXczjmeVQsilYvBWW4YvSZA==",
|
||||
"dependencies": {
|
||||
"@algolia/client-common": "4.17.1",
|
||||
"@algolia/requester-common": "4.17.1",
|
||||
"@algolia/transporter": "4.17.1"
|
||||
"@algolia/client-common": "4.17.2",
|
||||
"@algolia/requester-common": "4.17.2",
|
||||
"@algolia/transporter": "4.17.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/logger-common": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.17.1.tgz",
|
||||
"integrity": "sha512-Us28Ot+fLEmX9M96sa65VZ8EyEEzhYPxfhV9aQyKDjfXbUdJlJxKt6wZpoEg9RAPSdO8IjK9nmuW2P8au3rRsg=="
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.17.2.tgz",
|
||||
"integrity": "sha512-EfXuweUE+1HiSMsQidaDWA5Lv4NnStYIlh7PO5pLkI+sdhbMX0e5AO5nUAMIFM1VkEANes70RA8fzhP6OqCqQQ=="
|
||||
},
|
||||
"node_modules/@algolia/logger-console": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.17.1.tgz",
|
||||
"integrity": "sha512-iKGQTpOjHiE64W3JIOu6dmDvn+AfYIElI9jf/Nt6umRPmP/JI9rK+OHUoW4pKrBtdG0DPd62ppeNXzSnLxY6/g==",
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.17.2.tgz",
|
||||
"integrity": "sha512-JuG8HGVlJ+l/UEDK4h2Y8q/IEmRjQz1J0aS9tf6GPNbGYiSvMr1DDdZ+hqV3bb1XE6wU8Ypex56HisWMSpnG0A==",
|
||||
"dependencies": {
|
||||
"@algolia/logger-common": "4.17.1"
|
||||
"@algolia/logger-common": "4.17.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/requester-browser-xhr": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.17.1.tgz",
|
||||
"integrity": "sha512-W5mGfGDsyfVR+r4pUFrYLGBEM18gs38+GNt5PE5uPULy4uVTSnnVSkJkWeRkmLBk9zEZ/Nld8m4zavK6dtEuYg==",
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.17.2.tgz",
|
||||
"integrity": "sha512-FKI2lYWwksALfRt2OETFmGb5+P7WVc4py2Ai3H7k8FSfTLwVvs9WVVmtlx6oANQ8RFEK4B85h8DQJTJ29TDfmA==",
|
||||
"dependencies": {
|
||||
"@algolia/requester-common": "4.17.1"
|
||||
"@algolia/requester-common": "4.17.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/requester-common": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.17.1.tgz",
|
||||
"integrity": "sha512-HggXdjvVFQR0I5l7hM5WdHgQ1tqcRWeyXZz8apQ7zPWZhirmY2E9D6LVhDh/UnWQNEm7nBtM+eMFONJ3bZccIQ=="
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.17.2.tgz",
|
||||
"integrity": "sha512-Rfim23ztAhYpE9qm+KCfCRo+YLJCjiiTG+IpDdzUjMpYPhUtirQT0A35YEd/gKn86YNyydxS9w8iRSjwKh+L0A=="
|
||||
},
|
||||
"node_modules/@algolia/requester-node-http": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.17.1.tgz",
|
||||
"integrity": "sha512-NzFWecXT6d0PPsQY9L+/qoK2deF74OLcpvqCH+Vh3mh+QzPsFafcBExdguAjZsAWDn1R6JEeFW7/fo/p0SE57w==",
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.17.2.tgz",
|
||||
"integrity": "sha512-E0b0kyCDMvUIhQmDNd/mH4fsKJdEEX6PkMKrYJjzm6moo+rP22tqpq4Rfe7DZD8OB6/LsDD3zs3Kvd+L+M5wwQ==",
|
||||
"dependencies": {
|
||||
"@algolia/requester-common": "4.17.1"
|
||||
"@algolia/requester-common": "4.17.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/transporter": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.17.1.tgz",
|
||||
"integrity": "sha512-ZM+qhX47Vh46mWH8/U9ihvy98HdTYpYQDSlqBD7IbiUbbyoCMke+qmdSX2MGhR2FCcXBSxejsJKKVAfbpaLVgg==",
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.17.2.tgz",
|
||||
"integrity": "sha512-m8pXlz5OnNzjD1rcw+duCN4jG4yEzkJBsvKYMoN22Oq6rQwy1AY5muZ+IQUs4dL+A364CYkRMLRWhvXpCZ1x+g==",
|
||||
"dependencies": {
|
||||
"@algolia/cache-common": "4.17.1",
|
||||
"@algolia/logger-common": "4.17.1",
|
||||
"@algolia/requester-common": "4.17.1"
|
||||
"@algolia/cache-common": "4.17.2",
|
||||
"@algolia/logger-common": "4.17.2",
|
||||
"@algolia/requester-common": "4.17.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
@@ -353,18 +370,18 @@
|
||||
"integrity": "sha512-Tbsj02wXCbqGmzdnXNk0SOF19ChhRU70BsroIi4Pm6Ehp56in6vch94mfbdQ17DozxkL3BAVjbZ4Qc1a0HFRAg=="
|
||||
},
|
||||
"node_modules/@docsearch/css": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.4.0.tgz",
|
||||
"integrity": "sha512-Hg8Xfma+rFwRi6Y/pfei4FJoQ1hdVURmmNs/XPoMTCPAImU+d5yxj+M+qdLtNjWRpfWziU4dQcqY94xgFBn2dg=="
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.5.0.tgz",
|
||||
"integrity": "sha512-Ob5FQLubplcBNihAVtriR59FRBeP8u69F6mu4L4yIr60KfsPc10bOV0DoPErJw0zF9IBN2cNLW9qdmt8zWPxyg=="
|
||||
},
|
||||
"node_modules/@docsearch/react": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.4.0.tgz",
|
||||
"integrity": "sha512-ufrp5879XYGojgS30ZAp8H4qIMbahRHB9M85VDBP36Xgz5QjYM54i1URKj5e219F7gqTtOivfztFTij6itc0MQ==",
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.5.0.tgz",
|
||||
"integrity": "sha512-3IG8mmSMzSHNGy2S1VuPyYU9tFCxFpj5Ov8SYwsSHM4yMvFsaO9oFxXocA5lSenliIELhuOuS5+BdxHa/Qlf2A==",
|
||||
"dependencies": {
|
||||
"@algolia/autocomplete-core": "1.8.2",
|
||||
"@algolia/autocomplete-preset-algolia": "1.8.2",
|
||||
"@docsearch/css": "3.4.0",
|
||||
"@algolia/autocomplete-core": "1.9.2",
|
||||
"@algolia/autocomplete-preset-algolia": "1.9.2",
|
||||
"@docsearch/css": "3.5.0",
|
||||
"algoliasearch": "^4.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -573,16 +590,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/core": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.6.tgz",
|
||||
"integrity": "sha512-EvYTiXet5XqweYGClEmpu3BoxmsQ4hkj3QaYA6qEnigCWffTP3vNRwBReTdrwDwo7OoJ3wM8Uoe9Uk4n+d4hfg=="
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.3.0.tgz",
|
||||
"integrity": "sha512-vX1WVAdPjZg9DkDkC+zEx/tKtnST6/qcNpwcjeBgco3XRNHz5PUA+ivi/yr6G3o0kMR60uKBJcfOdfzOFI7PMQ=="
|
||||
},
|
||||
"node_modules/@floating-ui/dom": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.2.8.tgz",
|
||||
"integrity": "sha512-XLwhYV90MxiHDq6S0rzFZj00fnDM+A1R9jhSioZoMsa7G0Q0i+Q4x40ajR8FHSdYDE1bgjG45mIWe6jtv9UPmg==",
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.3.0.tgz",
|
||||
"integrity": "sha512-qIAwejE3r6NeA107u4ELDKkH8+VtgRKdXqtSPaKflL2S2V+doyN+Wt9s5oHKXPDo4E8TaVXaHT3+6BbagH31xw==",
|
||||
"dependencies": {
|
||||
"@floating-ui/core": "^1.2.6"
|
||||
"@floating-ui/core": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/react-dom": {
|
||||
@@ -612,103 +629,6 @@
|
||||
"react-dom": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@flowershow/core": {
|
||||
"version": "0.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@flowershow/core/-/core-0.4.13.tgz",
|
||||
"integrity": "sha512-UeDb70pjUGgILUXGQKFkytKL9ilwsTIM3jYsNNi55PKHXAaHEQA480Y+m2yNPgC5SzFlGj0FIP/zhH0JfBdNiw==",
|
||||
"dependencies": {
|
||||
"@docsearch/react": "^3.3.3",
|
||||
"@floating-ui/react-dom": "^1.3.0",
|
||||
"@floating-ui/react-dom-interactions": "^0.13.3",
|
||||
"@giscus/react": "^2.2.6",
|
||||
"@headlessui/react": "^1.7.12",
|
||||
"clsx": "^1.2.1",
|
||||
"disqus-react": "^1.1.5",
|
||||
"framer-motion": "^10.0.1",
|
||||
"kbar": "0.1.0-beta.40",
|
||||
"mdx-mermaid": "2.0.0-rc7",
|
||||
"mermaid": "10.0.1-rc.2",
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"next": "^13.2.1",
|
||||
"next-themes": "^0.2.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@flowershow/core/node_modules/dagre-d3-es": {
|
||||
"version": "7.0.8",
|
||||
"resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.8.tgz",
|
||||
"integrity": "sha512-eykdoYQ4FwCJinEYS0gPL2f2w+BPbSLvnQSJ3Ye1vAoPjdkq6xIMKBv+UkICd3qZE26wBKIn3p+6n0QC7R1LyA==",
|
||||
"dependencies": {
|
||||
"d3": "^7.8.2",
|
||||
"lodash-es": "^4.17.21"
|
||||
}
|
||||
},
|
||||
"node_modules/@flowershow/core/node_modules/dompurify": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.3.tgz",
|
||||
"integrity": "sha512-q6QaLcakcRjebxjg8/+NP+h0rPfatOgOzc46Fst9VAA3jF2ApfKBNKMzdP4DYTqtUMXSCd5pRS/8Po/OmoCHZQ=="
|
||||
},
|
||||
"node_modules/@flowershow/core/node_modules/mermaid": {
|
||||
"version": "10.0.1-rc.2",
|
||||
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.0.1-rc.2.tgz",
|
||||
"integrity": "sha512-THnhraO9F6pQZY9Nv91QuWv35QdmZy/UW2FpadRN/1cLuqCyihNKIEOxuVLEPrgtFawt2nL+BpUoJKC4div3UQ==",
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "^6.0.0",
|
||||
"cytoscape": "^3.23.0",
|
||||
"cytoscape-cose-bilkent": "^4.1.0",
|
||||
"cytoscape-fcose": "^2.1.0",
|
||||
"d3": "^7.4.0",
|
||||
"dagre-d3-es": "7.0.8",
|
||||
"dompurify": "2.4.3",
|
||||
"elkjs": "^0.8.2",
|
||||
"khroma": "^2.0.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"moment-mini": "^2.29.4",
|
||||
"non-layered-tidy-tree-layout": "^2.0.2",
|
||||
"stylis": "^4.1.2",
|
||||
"ts-dedent": "^2.2.0",
|
||||
"uuid": "^9.0.0",
|
||||
"web-worker": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@flowershow/markdowndb": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@flowershow/markdowndb/-/markdowndb-0.1.5.tgz",
|
||||
"integrity": "sha512-AfmkvgitNb7z150bTcCn/1lqwUhPRD3IhCbIwYxE5IXtL57+WwewJUNOU3SOKXNWg6eDVlfEq0H2GICSLAC4bw==",
|
||||
"dependencies": {
|
||||
"@flowershow/remark-wiki-link": "^1.1.2",
|
||||
"gray-matter": "^4.0.3",
|
||||
"knex": "^2.4.2",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"remark-parse": "^10.0.1",
|
||||
"sqlite3": "^5.1.6",
|
||||
"unist-util-select": "^4.0.3"
|
||||
},
|
||||
"bin": {
|
||||
"mddb": "src/bin/index.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@flowershow/remark-callouts": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@flowershow/remark-callouts/-/remark-callouts-1.0.0.tgz",
|
||||
"integrity": "sha512-zzHDpw1bswTTf+cbhNh2Bogf4ghpIcxAypFxYZxZ/afeGdN3NNSQwnamL8StY9uu6aQ/miq4Egbuof3xk2ksWA==",
|
||||
"dependencies": {
|
||||
"mdast-util-from-markdown": "^1.2.0",
|
||||
"svg-parser": "^2.0.4",
|
||||
"unist-util-visit": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@flowershow/remark-embed": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@flowershow/remark-embed/-/remark-embed-1.0.0.tgz",
|
||||
"integrity": "sha512-tADovIrhbmNWJj72C+pgT921+BuApmO6xxKU3HlWciRHkD6S4KqsikLjsopalK+VJmqluoHhhST0kf0S6xUKIA==",
|
||||
"dependencies": {
|
||||
"unist-util-visit": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@flowershow/remark-wiki-link": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@flowershow/remark-wiki-link/-/remark-wiki-link-1.2.0.tgz",
|
||||
@@ -1701,9 +1621,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@headlessui/react": {
|
||||
"version": "1.7.14",
|
||||
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.14.tgz",
|
||||
"integrity": "sha512-znzdq9PG8rkwcu9oQ2FwIy0ZFtP9Z7ycS+BAqJ3R5EIqC/0bJGvhT7193rFf+45i9nnPsYvCQVW4V/bB9Xc+gA==",
|
||||
"version": "1.7.15",
|
||||
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.15.tgz",
|
||||
"integrity": "sha512-OTO0XtoRQ6JPB1cKNFYBZv2Q0JMqMGNhYP1CjPvcJvjz8YGokz8oAj89HIYZGN0gZzn/4kk9iUpmMF4Q21Gsqw==",
|
||||
"dependencies": {
|
||||
"client-only": "^0.0.1"
|
||||
},
|
||||
@@ -1807,9 +1727,9 @@
|
||||
"integrity": "sha512-kXOeFbfCm4fFf2A3WwVEeQj55tMZa8c8/f9AKHMobQMkzNUfUj+antR3fRPaZJawsa1aZiP/Da3ndpZrwEe4rQ=="
|
||||
},
|
||||
"node_modules/@lit/reactive-element": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.1.tgz",
|
||||
"integrity": "sha512-va15kYZr7KZNNPZdxONGQzpUr+4sxVu7V/VG7a8mRfPPXUyhEYj5RzXCQmGrlP3tAh0L3HHm5AjBMFYRqlM9SA==",
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.2.tgz",
|
||||
"integrity": "sha512-rDfl+QnCYjuIGf5xI2sVJWdYIi56CTCwWa+nidKYX6oIuBYwUbT/vX4qbUDlHiZKJ/3FRNQ/tWJui44p6/stSA==",
|
||||
"dependencies": {
|
||||
"@lit-labs/ssr-dom-shim": "^1.0.0"
|
||||
}
|
||||
@@ -2444,6 +2364,60 @@
|
||||
"react-dom": "^18.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@portaljs/core": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@portaljs/core/-/core-1.0.5.tgz",
|
||||
"integrity": "sha512-HJ3eYjyKL7wrPlBwcEHzNd/SW2PwLu49nAsRTz8r7tgyRINDVkHTLVjZ5V6jCSYtuX7LSlxk0WMIZ9aDOocXDA==",
|
||||
"dependencies": {
|
||||
"@docsearch/react": "^3.3.3",
|
||||
"@floating-ui/react-dom": "^1.3.0",
|
||||
"@floating-ui/react-dom-interactions": "^0.13.3",
|
||||
"@giscus/react": "^2.2.6",
|
||||
"@headlessui/react": "^1.7.12",
|
||||
"clsx": "^1.2.1",
|
||||
"core-js": "^3.30.2",
|
||||
"disqus-react": "^1.1.5",
|
||||
"framer-motion": "^10.0.1",
|
||||
"kbar": "0.1.0-beta.40",
|
||||
"mermaid": "^10.2.2",
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"mdx-mermaid": "2.0.0-rc7",
|
||||
"next": "^13.2.1",
|
||||
"next-themes": "^0.2.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@portaljs/remark-callouts": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@portaljs/remark-callouts/-/remark-callouts-1.0.5.tgz",
|
||||
"integrity": "sha512-KMjr44isEvQzpNBBCP3s5/3TCmI/ce4xRvbOk6h9xicVZqE6BPTH9rhfOGvop9cchyAWgj9gmJXhQk+Bd+t5bg==",
|
||||
"dependencies": {
|
||||
"mdast-util-from-markdown": "^1.2.0",
|
||||
"svg-parser": "^2.0.4",
|
||||
"unist-util-visit": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@portaljs/remark-embed": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@portaljs/remark-embed/-/remark-embed-1.0.4.tgz",
|
||||
"integrity": "sha512-BvRMC1iBd5M93u9WS0mvunHoBMWgQQTCR7RdqSS9sRav5pqquiNG7il12Yza4vFpFBXwLkzEG0NwIVXzzutT8w==",
|
||||
"dependencies": {
|
||||
"unist-util-visit": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@portaljs/remark-wiki-link": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@portaljs/remark-wiki-link/-/remark-wiki-link-1.0.4.tgz",
|
||||
"integrity": "sha512-cp6vlssDAPawcBI0vUPRpcPdORql3RbK1Q+t1LuRvMQ+yiRb+9DnSPBUviDXKqwsBMOOXP/ePAdYohaeXGt0lQ==",
|
||||
"dependencies": {
|
||||
"mdast-util-to-markdown": "^1.5.0",
|
||||
"mdast-util-wiki-link": "^0.0.2",
|
||||
"micromark-util-symbol": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@primer/octicons-react": {
|
||||
"version": "12.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@primer/octicons-react/-/octicons-react-12.1.0.tgz",
|
||||
@@ -2474,27 +2448,43 @@
|
||||
"integrity": "sha512-Z8R0kdAZui8eYTuGY5oQUA0SU4jYq43m4bZW6Dw0B35fUp+U3r+pCrkj0EADJAPv1UaKNskSv/lrfRdC7719Rg=="
|
||||
},
|
||||
"node_modules/@radix-ui/react-compose-refs": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.0.tgz",
|
||||
"integrity": "sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA==",
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz",
|
||||
"integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-portal": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.2.tgz",
|
||||
"integrity": "sha512-swu32idoCW7KA2VEiUZGBSu9nB6qwGdV6k6HYhUoOo3M1FFpD+VgLzUqtt3mwL1ssz7r2x8MggpLSQach2Xy/Q==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.3.tgz",
|
||||
"integrity": "sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-primitive": "1.0.2"
|
||||
"@radix-ui/react-primitive": "1.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-presence": {
|
||||
@@ -2517,28 +2507,44 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-primitive": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.2.tgz",
|
||||
"integrity": "sha512-zY6G5Qq4R8diFPNwtyoLRZBxzu1Z+SXMlfYpChN7Dv8gvmx9X3qhDqiLWvKseKVJMuedFeU/Sa0Sy/Ia+t06Dw==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz",
|
||||
"integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-slot": "1.0.1"
|
||||
"@radix-ui/react-slot": "1.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.1.tgz",
|
||||
"integrity": "sha512-avutXAFL1ehGvAXtPquu0YK5oz6ctS474iM3vNGQIkswrVhdrS52e3uoMQBzZhNRAIE0jBnUyXWNmSjGHhCFcw==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
||||
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-compose-refs": "1.0.0"
|
||||
"@radix-ui/react-compose-refs": "1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/rect": {
|
||||
@@ -2862,6 +2868,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz",
|
||||
"integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
@@ -3078,24 +3085,24 @@
|
||||
}
|
||||
},
|
||||
"node_modules/algoliasearch": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.17.1.tgz",
|
||||
"integrity": "sha512-4GDQ1RhP2qUR3x8PevFRbEdqZqIARNViZYjgTJmA1T7wRNtFA3W4Aqc/RsODqa1J8IO/QDla5x4tWuUS8NV8wA==",
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.17.2.tgz",
|
||||
"integrity": "sha512-VFu43JJNYIW74awp7oeQcQsPcxOhd8psqBDTfyNO2Zt6L1NqnNMTVnaIdQ+8dtKqUDBqQZp0szPxECvX8CK2Fg==",
|
||||
"dependencies": {
|
||||
"@algolia/cache-browser-local-storage": "4.17.1",
|
||||
"@algolia/cache-common": "4.17.1",
|
||||
"@algolia/cache-in-memory": "4.17.1",
|
||||
"@algolia/client-account": "4.17.1",
|
||||
"@algolia/client-analytics": "4.17.1",
|
||||
"@algolia/client-common": "4.17.1",
|
||||
"@algolia/client-personalization": "4.17.1",
|
||||
"@algolia/client-search": "4.17.1",
|
||||
"@algolia/logger-common": "4.17.1",
|
||||
"@algolia/logger-console": "4.17.1",
|
||||
"@algolia/requester-browser-xhr": "4.17.1",
|
||||
"@algolia/requester-common": "4.17.1",
|
||||
"@algolia/requester-node-http": "4.17.1",
|
||||
"@algolia/transporter": "4.17.1"
|
||||
"@algolia/cache-browser-local-storage": "4.17.2",
|
||||
"@algolia/cache-common": "4.17.2",
|
||||
"@algolia/cache-in-memory": "4.17.2",
|
||||
"@algolia/client-account": "4.17.2",
|
||||
"@algolia/client-analytics": "4.17.2",
|
||||
"@algolia/client-common": "4.17.2",
|
||||
"@algolia/client-personalization": "4.17.2",
|
||||
"@algolia/client-search": "4.17.2",
|
||||
"@algolia/logger-common": "4.17.2",
|
||||
"@algolia/logger-console": "4.17.2",
|
||||
"@algolia/requester-browser-xhr": "4.17.2",
|
||||
"@algolia/requester-common": "4.17.2",
|
||||
"@algolia/requester-node-http": "4.17.2",
|
||||
"@algolia/transporter": "4.17.2"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
@@ -3402,7 +3409,8 @@
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/before-after-hook": {
|
||||
"version": "2.2.3",
|
||||
@@ -3430,6 +3438,7 @@
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"buffer": "^5.5.0",
|
||||
"inherits": "^2.0.4",
|
||||
@@ -3532,6 +3541,7 @@
|
||||
}
|
||||
],
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.1.13"
|
||||
@@ -3542,6 +3552,7 @@
|
||||
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
||||
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
@@ -3905,6 +3916,16 @@
|
||||
"toggle-selection": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/core-js": {
|
||||
"version": "3.31.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.31.0.tgz",
|
||||
"integrity": "sha512-NIp2TQSGfR6ba5aalZD+ZQ1fSxGhDo/s1w0nx3RYzf2pnJxt7YynxFlFScP6eV7+GZsKO95NSjGxyJsU3DZgeQ==",
|
||||
"hasInstallScript": true,
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/core-js"
|
||||
}
|
||||
},
|
||||
"node_modules/cose-base": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz",
|
||||
@@ -3933,6 +3954,7 @@
|
||||
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
|
||||
"integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"node-fetch": "2.6.7"
|
||||
}
|
||||
@@ -3942,6 +3964,7 @@
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
@@ -4080,9 +4103,9 @@
|
||||
"integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg=="
|
||||
},
|
||||
"node_modules/d3": {
|
||||
"version": "7.8.4",
|
||||
"resolved": "https://registry.npmjs.org/d3/-/d3-7.8.4.tgz",
|
||||
"integrity": "sha512-q2WHStdhiBtD8DMmhDPyJmXUxr6VWRngKyiJ5EfXMxPw+tqT6BhNjhJZ4w3BHsNm3QoVfZLY8Orq/qPFczwKRA==",
|
||||
"version": "7.8.5",
|
||||
"resolved": "https://registry.npmjs.org/d3/-/d3-7.8.5.tgz",
|
||||
"integrity": "sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==",
|
||||
"dependencies": {
|
||||
"d3-array": "3",
|
||||
"d3-axis": "3",
|
||||
@@ -4489,7 +4512,6 @@
|
||||
"version": "7.0.10",
|
||||
"resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.10.tgz",
|
||||
"integrity": "sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"d3": "^7.8.2",
|
||||
"lodash-es": "^4.17.21"
|
||||
@@ -4516,10 +4538,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.7",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz",
|
||||
"integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==",
|
||||
"peer": true
|
||||
"version": "1.11.8",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.8.tgz",
|
||||
"integrity": "sha512-LcgxzFoWMEPO7ggRv1Y2N31hUf2R0Vj7fuy/m+Bg1K8rr+KAs1AEy4y9jd5DXe8pbHgX+srkHNS7TH6Q6ZhYeQ=="
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
@@ -4685,7 +4706,8 @@
|
||||
"version": "0.0.1045489",
|
||||
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1045489.tgz",
|
||||
"integrity": "sha512-D+PTmWulkuQW4D1NTiCRCFxF7pQPn0hgp4YyX4wAQ6xYXKOadSWPR3ENGDQ47MW/Ewc9v2rpC/UEEGahgBYpSQ==",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/didyoumean": {
|
||||
"version": "1.2.2",
|
||||
@@ -4739,8 +4761,7 @@
|
||||
"node_modules/dompurify": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.3.tgz",
|
||||
"integrity": "sha512-axQ9zieHLnAnHh0sfAamKYiqXMJAVwu+LM/alQ7WDagoWessyWvMSFyW65CqF3owufNu8HBcE4cM2Vflu7YWcQ==",
|
||||
"peer": true
|
||||
"integrity": "sha512-axQ9zieHLnAnHh0sfAamKYiqXMJAVwu+LM/alQ7WDagoWessyWvMSFyW65CqF3owufNu8HBcE4cM2Vflu7YWcQ=="
|
||||
},
|
||||
"node_modules/downshift": {
|
||||
"version": "6.1.12",
|
||||
@@ -4807,6 +4828,7 @@
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
@@ -5521,6 +5543,7 @@
|
||||
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
|
||||
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"debug": "^4.1.1",
|
||||
"get-stream": "^5.1.0",
|
||||
@@ -5615,6 +5638,7 @@
|
||||
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
|
||||
"integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"pend": "~1.2.0"
|
||||
}
|
||||
@@ -5749,7 +5773,8 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/fs-extra": {
|
||||
"version": "10.1.0",
|
||||
@@ -5884,6 +5909,7 @@
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
|
||||
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"pump": "^3.0.0"
|
||||
},
|
||||
@@ -6456,7 +6482,8 @@
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.2.4",
|
||||
@@ -7350,9 +7377,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/lit": {
|
||||
"version": "2.7.4",
|
||||
"resolved": "https://registry.npmjs.org/lit/-/lit-2.7.4.tgz",
|
||||
"integrity": "sha512-cgD7xrZoYr21mbrkZIuIrj98YTMw/snJPg52deWVV4A8icLyNHI3bF70xsJeAgwTuiq5Kkd+ZR8gybSJDCPB7g==",
|
||||
"version": "2.7.5",
|
||||
"resolved": "https://registry.npmjs.org/lit/-/lit-2.7.5.tgz",
|
||||
"integrity": "sha512-i/cH7Ye6nBDUASMnfwcictBnsTN91+aBjXoTHF2xARghXScKxpD4F4WYI+VLXg9lqbMinDfvoI7VnZXjyHgdfQ==",
|
||||
"dependencies": {
|
||||
"@lit/reactive-element": "^1.6.0",
|
||||
"lit-element": "^3.3.0",
|
||||
@@ -7993,6 +8020,23 @@
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/mddb": {
|
||||
"version": "0.1.9",
|
||||
"resolved": "https://registry.npmjs.org/mddb/-/mddb-0.1.9.tgz",
|
||||
"integrity": "sha512-d3B5zArnWDqKN1Blq6hGtfr3HTHUKK/GS95b4OZqcyDPvUP4JnYuWHDjyoJ0tSgDKH6ybB6WdnnI3tcHQvRTyw==",
|
||||
"dependencies": {
|
||||
"@flowershow/remark-wiki-link": "^1.1.2",
|
||||
"gray-matter": "^4.0.3",
|
||||
"knex": "^2.4.2",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"remark-parse": "^10.0.1",
|
||||
"sqlite3": "^5.1.6",
|
||||
"unist-util-select": "^4.0.3"
|
||||
},
|
||||
"bin": {
|
||||
"mddb": "dist/src/bin/index.js"
|
||||
}
|
||||
},
|
||||
"node_modules/mdn-data": {
|
||||
"version": "2.0.14",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
|
||||
@@ -8002,6 +8046,7 @@
|
||||
"version": "2.0.0-rc7",
|
||||
"resolved": "https://registry.npmjs.org/mdx-mermaid/-/mdx-mermaid-2.0.0-rc7.tgz",
|
||||
"integrity": "sha512-AMy3138EsvcGwE4cGqUVytj4mLpJ3TJ2nek82+67Qi4GSOXoelAqmQudHSk26IsP091c3qX4d/4wi9CqLwFl9Q==",
|
||||
"peer": true,
|
||||
"optionalDependencies": {
|
||||
"estree-util-to-js": "^1.1.0",
|
||||
"estree-util-visit": "^1.2.0",
|
||||
@@ -8032,10 +8077,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/mermaid": {
|
||||
"version": "10.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.2.0.tgz",
|
||||
"integrity": "sha512-mYKXlH9ngKdMsJ87VYMdlDZXS+MXDAGKPf3XzDf2vvAPnmRoFm7GFebemOAOWYI1bWSECDyoWTGwesWe6mW1Cw==",
|
||||
"peer": true,
|
||||
"version": "10.2.3",
|
||||
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.2.3.tgz",
|
||||
"integrity": "sha512-cMVE5s9PlQvOwfORkyVpr5beMsLdInrycAosdr+tpZ0WFjG4RJ/bUHST7aTgHNJbujHkdBRAm+N50P3puQOfPw==",
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "^6.0.2",
|
||||
"cytoscape": "^3.23.0",
|
||||
@@ -8899,7 +8943,8 @@
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
|
||||
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/modern-normalize": {
|
||||
"version": "1.1.0",
|
||||
@@ -8912,11 +8957,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/moment-mini": {
|
||||
"version": "2.29.4",
|
||||
"resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.29.4.tgz",
|
||||
"integrity": "sha512-uhXpYwHFeiTbY9KSgPPRoo1nt8OxNVdMVoTBYHfSEKeRkIkwGpO+gERmhuhBtzfaeOyTkykSrm2+noJBgqt3Hg=="
|
||||
},
|
||||
"node_modules/mri": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
||||
@@ -9641,7 +9681,8 @@
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
|
||||
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/periscopic": {
|
||||
"version": "3.1.0",
|
||||
@@ -9850,6 +9891,7 @@
|
||||
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
||||
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
@@ -9896,13 +9938,15 @@
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/pump": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
@@ -9923,6 +9967,7 @@
|
||||
"deprecated": "< 19.4.0 is no longer supported",
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"https-proxy-agent": "5.0.1",
|
||||
"progress": "2.0.3",
|
||||
@@ -9938,6 +9983,7 @@
|
||||
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-18.2.1.tgz",
|
||||
"integrity": "sha512-MRtTAZfQTluz3U2oU/X2VqVWPcR1+94nbA2V6ZrSZRVEwLqZ8eclZ551qGFQD/vD2PYqHJwWOW/fpC721uznVw==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"cross-fetch": "3.1.5",
|
||||
"debug": "4.3.4",
|
||||
@@ -10804,6 +10850,15 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/search-insights": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.6.0.tgz",
|
||||
"integrity": "sha512-vU2/fJ+h/Mkm/DJOe+EaM5cafJv/1rRTZpGJTuFPf/Q5LjzgMDsqPdSaZsAe+GAWHHsfsu+rQSAn6c8IGtBEVw==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/section-matter": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
|
||||
@@ -11403,6 +11458,7 @@
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
|
||||
"integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"chownr": "^1.1.1",
|
||||
"mkdirp-classic": "^0.5.2",
|
||||
@@ -11414,13 +11470,15 @@
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
||||
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/tar-stream": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
||||
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"bl": "^4.0.3",
|
||||
"end-of-stream": "^1.4.1",
|
||||
@@ -11484,7 +11542,8 @@
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/tildify": {
|
||||
"version": "2.0.0",
|
||||
@@ -11867,6 +11926,7 @@
|
||||
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
|
||||
"integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"buffer": "^5.2.1",
|
||||
"through": "^2.3.8"
|
||||
@@ -12880,6 +12940,7 @@
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz",
|
||||
"integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
@@ -12955,6 +13016,7 @@
|
||||
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
|
||||
"integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"buffer-crc32": "~0.2.3",
|
||||
"fd-slicer": "~1.1.0"
|
||||
|
||||
@@ -10,16 +10,17 @@
|
||||
"prettier": "prettier --write ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@flowershow/core": "^0.4.13",
|
||||
"@flowershow/markdowndb": "^0.1.5",
|
||||
"@flowershow/remark-callouts": "^1.0.0",
|
||||
"@flowershow/remark-embed": "^1.0.0",
|
||||
"@portaljs/components": "^0.1.6",
|
||||
"@portaljs/core": "^1.0.5",
|
||||
"@portaljs/remark-callouts": "^1.0.5",
|
||||
"@portaljs/remark-embed": "^1.0.4",
|
||||
"@portaljs/remark-wiki-link": "^1.0.4",
|
||||
"@types/node": "18.16.0",
|
||||
"@types/react": "18.0.38",
|
||||
"@types/react-dom": "18.0.11",
|
||||
"eslint": "8.39.0",
|
||||
"eslint-config-next": "13.3.1",
|
||||
"mddb": "^0.1.9",
|
||||
"next": "13.4.3",
|
||||
"next-mdx-remote": "^4.4.1",
|
||||
"next-seo": "^6.0.0",
|
||||
|
||||
@@ -79,7 +79,7 @@ pre {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@import "@flowershow/remark-callouts/styles.css";
|
||||
@import "@portaljs/remark-callouts/styles.css";
|
||||
|
||||
/* mathjax */
|
||||
.math-inline > mjx-container > svg {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { MDXRemote } from 'next-mdx-remote';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { Mermaid } from '@flowershow/core';
|
||||
import { Mermaid } from '@portaljs/core';
|
||||
|
||||
// Custom components/renderers to pass to MDX.
|
||||
// Since the MDX files aren't loaded by webpack, they have no knowledge of how
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import matter from "gray-matter";
|
||||
import mdxmermaid from "mdx-mermaid";
|
||||
import { h } from "hastscript";
|
||||
import remarkCallouts from "@flowershow/remark-callouts";
|
||||
import remarkEmbed from "@flowershow/remark-embed";
|
||||
import remarkCallouts from "@portaljs/remark-callouts";
|
||||
import remarkEmbed from "@portaljs/remark-embed";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import remarkMath from "remark-math";
|
||||
import remarkSmartypants from "remark-smartypants";
|
||||
import remarkToc from "remark-toc";
|
||||
import remarkWikiLink from "@flowershow/remark-wiki-link";
|
||||
import remarkWikiLink from "@portaljs/remark-wiki-link";
|
||||
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
||||
import rehypeKatex from "rehype-katex";
|
||||
import rehypeSlug from "rehype-slug";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MarkdownDB } from "@flowershow/markdowndb";
|
||||
import { MarkdownDB } from "mddb";
|
||||
|
||||
const dbPath = "markdown.db";
|
||||
|
||||
|
||||
5
examples/learn/next.config.js
Normal file
5
examples/learn/next.config.js
Normal file
@@ -0,0 +1,5 @@
|
||||
const nextConfig = {
|
||||
swcMinify: false
|
||||
}
|
||||
|
||||
module.exports = nextConfig
|
||||
1969
examples/learn/package-lock.json
generated
1969
examples/learn/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -12,17 +12,28 @@
|
||||
"mddb": "mddb ./content"
|
||||
},
|
||||
"dependencies": {
|
||||
"@flowershow/core": "^0.4.10",
|
||||
"@flowershow/markdowndb": "^0.1.1",
|
||||
"@flowershow/remark-callouts": "^1.0.0",
|
||||
"@flowershow/remark-embed": "^1.0.0",
|
||||
"@flowershow/remark-wiki-link": "^1.1.2",
|
||||
"@githubocto/flat-ui": "^0.14.1",
|
||||
"@heroicons/react": "^2.0.17",
|
||||
"@opentelemetry/api": "^1.4.0",
|
||||
"@portaljs/components": "^0.1.8",
|
||||
"@portaljs/core": "^1.0.5",
|
||||
"@portaljs/remark-callouts": "^1.0.5",
|
||||
"@portaljs/remark-embed": "^1.0.4",
|
||||
"@portaljs/remark-wiki-link": "^1.0.4",
|
||||
"@tanstack/react-table": "^8.8.5",
|
||||
"flexsearch": "0.7.21",
|
||||
"gray-matter": "^4.0.3",
|
||||
"hastscript": "^7.2.0",
|
||||
"mddb": "^0.1.9",
|
||||
"mdx-mermaid": "2.0.0-rc7",
|
||||
"next": "13.2.1",
|
||||
"next-mdx-remote": "^4.4.1",
|
||||
"papaparse": "^5.4.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-hook-form": "^7.43.9",
|
||||
"react-query": "^3.39.3",
|
||||
"react-vega": "^7.6.0",
|
||||
"rehype-autolink-headings": "^6.1.1",
|
||||
"rehype-katex": "^6.0.3",
|
||||
"rehype-prism-plus": "^1.5.1",
|
||||
@@ -32,17 +43,6 @@
|
||||
"remark-smartypants": "^2.0.0",
|
||||
"remark-toc": "^8.0.1",
|
||||
"typescript": "5.0.4",
|
||||
"@githubocto/flat-ui": "^0.14.1",
|
||||
"@heroicons/react": "^2.0.17",
|
||||
"@tanstack/react-table": "^8.8.5",
|
||||
"flexsearch": "0.7.21",
|
||||
"next-mdx-remote": "^4.4.1",
|
||||
"papaparse": "^5.4.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-hook-form": "^7.43.9",
|
||||
"react-query": "^3.39.3",
|
||||
"react-vega": "^7.6.0",
|
||||
"vega": "5.25.0",
|
||||
"vega-lite": "5.1.0"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@import "@flowershow/remark-callouts/styles.css";
|
||||
@import "@portaljs/remark-callouts/styles.css";
|
||||
|
||||
.w-5 {
|
||||
width: 1.25rem
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
import { MDXRemote } from 'next-mdx-remote';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { Mermaid } from '@flowershow/core';
|
||||
import { Mermaid } from '@portaljs/core';
|
||||
|
||||
// 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 = {
|
||||
Table: dynamic(() => import('@portaljs/components').then(mod => mod.Table)),
|
||||
Catalog: dynamic(() => import('@portaljs/components').then(mod => mod.Catalog)),
|
||||
Table: dynamic(() => import('@portaljs/components').then((mod) => mod.Table)),
|
||||
Catalog: dynamic(() =>
|
||||
import('@portaljs/components').then((mod) => mod.Catalog)
|
||||
),
|
||||
mermaid: Mermaid,
|
||||
Vega: dynamic(() => import('@portaljs/components').then(mod => mod.Vega)),
|
||||
VegaLite: dynamic(() => import('@portaljs/components').then(mod => mod.VegaLite)),
|
||||
LineChart: dynamic(() => import('@portaljs/components').then(mod => mod.LineChart)),
|
||||
FlatUiTable: dynamic(() => import('@portaljs/components').then(mod => mod.FlatUiTable)),
|
||||
Vega: dynamic(() => import('@portaljs/components').then((mod) => mod.Vega)),
|
||||
VegaLite: dynamic(() =>
|
||||
import('@portaljs/components').then((mod) => mod.VegaLite)
|
||||
),
|
||||
LineChart: dynamic(() =>
|
||||
import('@portaljs/components').then((mod) => mod.LineChart)
|
||||
),
|
||||
FlatUiTable: dynamic(() =>
|
||||
import('@portaljs/components').then((mod) => mod.FlatUiTable)
|
||||
),
|
||||
} as any;
|
||||
|
||||
export default function DRD({ source }: { source: any }) {
|
||||
|
||||
@@ -16,6 +16,8 @@ We welcome contributions from anyone who is interested in improving OpenSpending
|
||||
|
||||
The main platform for communication and collaboration for OpenSpending is Github, if you want to interact with us you can o so by submitting an issue.
|
||||
|
||||
**Repo for issues:** [https://github.com/os-data/registry/issues](https://github.com/os-data/registry/issues)
|
||||
|
||||
If you want to submit a dataset for evaluation and inclusion in OpenSpending, you will need to create an issue on Github using this template:
|
||||
|
||||
```markdown
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
---
|
||||
title: Frankfurt is Investing in Education, and Your City Should Too
|
||||
date: 06/12/2023
|
||||
authors: ['Michael Polidori']
|
||||
---
|
||||
|
||||
_Note: The currency in this post has been converted to USD using an average exchange rate of 1 EUR = 1.20 USD._
|
||||
|
||||
Between 2008 and 2016, the population of Frankfurt, Germany grew from approximately 670k to 740k[^1], while
|
||||
its spending on education climbed from \$465 million to a staggering \$814 million, a 75% increase. That's a
|
||||
significant surge, bumping education to around 20% of the total budget, only second to social issues.
|
||||
|
||||
The stacked bar chart below (using the [City of Frankfurt Expenditure dataset](https://www.openspending.org/@os-data/city-of-frankfurt-expenditure))
|
||||
helps to bring this data to life. It maps out the city's annual spending across various areas. As you can see,
|
||||
the education slice has grown noticeably over the years, indicating Frankfurt's intention to prioritize this space.
|
||||
The city's commitment to education is abundantly clear.
|
||||
|
||||
<VegaLite
|
||||
spec={{
|
||||
$schema: 'https://vega.github.io/schema/vega-lite/v5.json',
|
||||
data: {
|
||||
url: 'https://storage.openspending.org/city-of-frankfurt-expenditure/frankfurt-sums.csv',
|
||||
},
|
||||
transform: [
|
||||
{
|
||||
calculate: "format(datum.amount / 1e6 * 1.20, '$,.1f') + 'M'",
|
||||
as: 'formattedAmountMillion',
|
||||
},
|
||||
{ calculate: 'datum.amount / 1e9 * 1.20', as: 'amountBillion' },
|
||||
],
|
||||
mark: 'bar',
|
||||
width: 350,
|
||||
height: 400,
|
||||
encoding: {
|
||||
x: {
|
||||
field: 'date',
|
||||
type: 'ordinal',
|
||||
title: 'Year',
|
||||
},
|
||||
y: {
|
||||
field: 'amount',
|
||||
type: 'quantitative',
|
||||
title: 'Spending (USD in billions)',
|
||||
axis: {
|
||||
format: '~s',
|
||||
labelExpr: "format(datum.value / 1e9 * 1.20, '$,.0f') + 'B'",
|
||||
},
|
||||
},
|
||||
color: {
|
||||
field: 'label',
|
||||
type: 'nominal',
|
||||
title: 'Area',
|
||||
scale: {
|
||||
domain: [
|
||||
'Building supervision and monument protection',
|
||||
'Business development agency',
|
||||
'Central finance economy',
|
||||
'Central services',
|
||||
'Culture, leisure and sport',
|
||||
'Education',
|
||||
'Elections and superordinate matters',
|
||||
'Environment',
|
||||
'Finance',
|
||||
'Fire protection and emergency services',
|
||||
'Geoinformation and property regulations',
|
||||
'Head of the city administration',
|
||||
'Health',
|
||||
'Local transport and public transport',
|
||||
'Order and security',
|
||||
'Personnel and organization',
|
||||
'Property and building management',
|
||||
'Reside',
|
||||
'Revision and law',
|
||||
'Social issue',
|
||||
'Town planning',
|
||||
],
|
||||
range: [
|
||||
'#EF5350',
|
||||
'#F06292',
|
||||
'#BA68C8',
|
||||
'#9575CD',
|
||||
'#7986CB',
|
||||
'#64B5F6',
|
||||
'#4FC3F7',
|
||||
'#4DD0E1',
|
||||
'#4DB6AC',
|
||||
'#81C784',
|
||||
'#AED581',
|
||||
'#DCE775',
|
||||
'#FFF176',
|
||||
'#FFD54F',
|
||||
'#FFB74D',
|
||||
'#FF8A65',
|
||||
'#A1887F',
|
||||
'#90A4AE',
|
||||
'#78909C',
|
||||
'#546E7A',
|
||||
'#455A64',
|
||||
],
|
||||
},
|
||||
},
|
||||
tooltip: [
|
||||
{ field: 'label', type: 'nominal', title: 'Area' },
|
||||
{
|
||||
field: 'formattedAmountMillion',
|
||||
type: 'ordinal',
|
||||
title: 'Spending (USD in millions)',
|
||||
},
|
||||
{ field: 'date', type: 'ordinal', title: 'Year' },
|
||||
],
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
Now, let's look at a line chart that traces only the trajectory of education spending through these eight
|
||||
years (using the same dataset). It's not just a line; it's a testament to Frankfurt's growing conviction that investing in education is
|
||||
the key to a prosperous future.
|
||||
|
||||
<VegaLite
|
||||
spec={{
|
||||
$schema: 'https://vega.github.io/schema/vega-lite/v5.json',
|
||||
description: 'Frankfurt Education Spending.',
|
||||
data: {
|
||||
url: 'https://storage.openspending.org/city-of-frankfurt-expenditure/frankfurt-sums.csv',
|
||||
},
|
||||
transform: [
|
||||
{ filter: "datum.label==='Education'" },
|
||||
{
|
||||
calculate: "format(datum.amount / 1e6 * 1.20, '$,.1f') + 'M'",
|
||||
as: 'formattedAmountMillion',
|
||||
},
|
||||
],
|
||||
mark: {
|
||||
type: 'area',
|
||||
line: true,
|
||||
point: true,
|
||||
},
|
||||
width: 400,
|
||||
height: 400,
|
||||
encoding: {
|
||||
x: {
|
||||
field: 'date',
|
||||
type: 'ordinal',
|
||||
title: 'Year',
|
||||
},
|
||||
y: {
|
||||
field: 'amount',
|
||||
type: 'quantitative',
|
||||
title: 'Spending (USD in millions)',
|
||||
axis: {
|
||||
format: '~s',
|
||||
labelExpr: "format(datum.value / 1e6 * 1.20, '$,.0f') + 'M'",
|
||||
},
|
||||
},
|
||||
color: {
|
||||
title: '',
|
||||
field: 'label',
|
||||
scale: {
|
||||
domain: ['Education'],
|
||||
range: ['#64b5f6'],
|
||||
},
|
||||
},
|
||||
tooltip: [
|
||||
{ field: 'label', type: 'nominal', title: 'Area' },
|
||||
{
|
||||
field: 'formattedAmountMillion',
|
||||
type: 'ordinal',
|
||||
title: 'Spending (USD in millions)',
|
||||
},
|
||||
{ field: 'date', type: 'ordinal', title: 'Year' },
|
||||
],
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
Despite Frankfurt's population experiencing an increase of less than 100k during this period, the significant
|
||||
investment in education tells a different story. It sends a clear message: education isn't merely a line item
|
||||
in their budget—it's their future.
|
||||
|
||||
During this period, it's likely that schools underwent major overhauls, more teachers got hired, new educational
|
||||
programs launched, etc., to give every child in Frankfurt a chance to have an impactful and quality education.
|
||||
|
||||
The beauty of good data is that it's not just numbers—it's narratives. And the narrative here is that Frankfurt
|
||||
is leveraging the power of long-term investment in education for a better, brighter future. This investment in
|
||||
education is not just about the dollars and cents. It's about recognizing the value of quality education to drive
|
||||
social and economic progress.
|
||||
|
||||
Frankfurt is a city that's recognized the power of education, and it's using that power to redefine its future.
|
||||
One can only hope that more cities follow suit.
|
||||
|
||||
[^1]: https://worldpopulationreview.com/world-cities/frankfurt-population
|
||||
284
examples/openspending/content/stories/moers-anomaly-2016.mdx
Normal file
284
examples/openspending/content/stories/moers-anomaly-2016.mdx
Normal file
@@ -0,0 +1,284 @@
|
||||
---
|
||||
title: An Exploration of Moers' 2016 Budget Anomaly
|
||||
date: 06/13/2023
|
||||
---
|
||||
|
||||
_Note: The currency in this post has been converted to USD using an average exchange rate of 1 EUR = 1.20 USD.
|
||||
Additionally, the text values for account groups have been loosely translated to English. You can find the
|
||||
original dataset here: [Moers budget dataset](https://www.openspending.org/@os-data/moers-all)_
|
||||
|
||||
In the fiscal landscape of Moers, Germany, 2016 stands out as an anomaly. An examination of the budget allocations
|
||||
for this particular year shows a significant surge in spending across various areas. After this anomalous
|
||||
spike, spending patterns then seemed to resume their previous trajectory of a slow, steady climb in the
|
||||
following years. While it's tempting to dismiss this as an irregularity, it's worth exploring the potential
|
||||
underlying causes of this fiscal fluctuation.
|
||||
|
||||
<VegaLite
|
||||
spec={{
|
||||
$schema: 'https://vega.github.io/schema/vega-lite/v5.json',
|
||||
title: 'Spending by Account Group',
|
||||
description: 'Spending by Account Group',
|
||||
data: {
|
||||
url: 'https://storage.openspending.org/moers-all/moers-sums.csv',
|
||||
},
|
||||
transform: [
|
||||
{
|
||||
calculate: "format(datum.amount / 1e6 * 1.20, '$,.1f') + 'M'",
|
||||
as: 'formattedAmountMillion',
|
||||
},
|
||||
{ calculate: 'datum.amount / 1e9 * 1.20', as: 'amountBillion' },
|
||||
],
|
||||
mark: 'bar',
|
||||
height: 400,
|
||||
width: 350,
|
||||
encoding: {
|
||||
x: {
|
||||
field: 'date',
|
||||
type: 'temporal',
|
||||
timeUnit: 'utcyear',
|
||||
title: 'Year',
|
||||
},
|
||||
y: {
|
||||
field: 'amount',
|
||||
type: 'quantitative',
|
||||
title: 'Spending (USD in millions)',
|
||||
axis: {
|
||||
format: '~s',
|
||||
labelExpr: "format(datum.value / 1e6 * 1.20, '$,.0f') + 'M'",
|
||||
},
|
||||
},
|
||||
color: {
|
||||
field: 'account group',
|
||||
type: 'nominal',
|
||||
title: 'Account Group',
|
||||
scale: {
|
||||
domain: [
|
||||
'Activated Own Work',
|
||||
'Balance Expenses',
|
||||
'Care Expenses',
|
||||
'Donations And General Levies',
|
||||
'Expenses For Material And Services',
|
||||
'Extraordinary Expenses',
|
||||
'Extraordinary Income',
|
||||
'Other Ordinary Expenses',
|
||||
'Other Ordinary Income',
|
||||
'Other Transfer Income',
|
||||
'Personnel Expenses',
|
||||
'Private Law Performance Fees',
|
||||
'Public-Service Performance Fees',
|
||||
'Taxes And Similar Charges',
|
||||
'Transfer Expenses',
|
||||
],
|
||||
range: [
|
||||
'#EF5350',
|
||||
'#F06292',
|
||||
'#BA68C8',
|
||||
'#9575CD',
|
||||
'#7986CB',
|
||||
'#64B5F6',
|
||||
'#4FC3F7',
|
||||
'#4DD0E1',
|
||||
'#4DB6AC',
|
||||
'#81C784',
|
||||
'#AED581',
|
||||
'#DCE775',
|
||||
'#FFF176',
|
||||
'#FFD54F',
|
||||
'#FFB74D',
|
||||
],
|
||||
},
|
||||
},
|
||||
tooltip: [
|
||||
{ field: 'account group', type: 'nominal', title: 'Account Group' },
|
||||
{
|
||||
field: 'formattedAmountMillion',
|
||||
type: 'ordinal',
|
||||
title: 'Spending (USD)',
|
||||
},
|
||||
{ field: 'date', type: 'temporal', title: 'Year', format: '%Y' }
|
||||
],
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
## Why?
|
||||
|
||||
One possible explanation could be the global refugee crisis that was unfolding around this time, particularly
|
||||
in Germany. While we can't assert this connection definitively due to the lack of specific data, it's an angle
|
||||
worth examining to better understand the budget anomaly of 2016.
|
||||
|
||||
For instance, the "Donations and General Levies" account group saw a distinct increase in 2016. This could be
|
||||
reflective of Moers' attempts to provide immediate support to incoming refugees, although we can only speculate
|
||||
at this point.
|
||||
|
||||
<VegaLite
|
||||
spec={{
|
||||
$schema: 'https://vega.github.io/schema/vega-lite/v5.json',
|
||||
title: 'Donations and General Levies',
|
||||
description: 'Donations and General Levies',
|
||||
data: {
|
||||
url: 'https://storage.openspending.org/moers-all/moers-sums.csv',
|
||||
},
|
||||
transform: [
|
||||
{ filter: "datum['account group']==='Donations And General Levies'" },
|
||||
{
|
||||
calculate: "format(datum.amount / 1e6 * 1.20, '$,.1f') + 'M'",
|
||||
as: 'formattedAmountMillion',
|
||||
},
|
||||
],
|
||||
mark: {
|
||||
type: 'area',
|
||||
line: true,
|
||||
point: true,
|
||||
},
|
||||
width: 400,
|
||||
height: 400,
|
||||
encoding: {
|
||||
x: {
|
||||
field: 'date',
|
||||
type: 'temporal',
|
||||
timeUnit: 'utcyear',
|
||||
title: 'Year',
|
||||
},
|
||||
y: {
|
||||
field: 'amount',
|
||||
type: 'quantitative',
|
||||
title: 'Spending (USD in millions)',
|
||||
axis: {
|
||||
format: '~s',
|
||||
labelExpr: "format(datum.value / 1e6 * 1.20, '$,.0f') + 'M'",
|
||||
},
|
||||
},
|
||||
color: {
|
||||
title: 'Account Group',
|
||||
field: 'account group',
|
||||
scale: {
|
||||
domain: ['Donations And General Levies'],
|
||||
range: ['#9575CD'],
|
||||
},
|
||||
},
|
||||
tooltip: [
|
||||
{ field: 'account group', type: 'nominal', title: 'Area' },
|
||||
{
|
||||
field: 'formattedAmountMillion',
|
||||
type: 'ordinal',
|
||||
title: 'Spending (USD in millions)',
|
||||
},
|
||||
{ field: 'date', type: 'temporal', title: 'Year', format: '%Y' }
|
||||
],
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
Similarly, "Expenses for Material and Services" also experienced an upswing. This could suggest
|
||||
that the town was working to establish necessary infrastructure and resources for the newcomers. It's plausible
|
||||
that procurement of essential supplies and services to aid the refugees was a factor contributing to this budget
|
||||
increase.
|
||||
|
||||
The rise in "Personnel Expenses" may suggest an expansion of the town's workforce during this period. Additional
|
||||
staffing in areas like interpretation, social work, healthcare, and administration would be necessary to handle
|
||||
the influx of refugees.
|
||||
|
||||
The two account groups that experienced the most substantial raw monetary increases were "Taxes and Similar Charges"
|
||||
and "Transfer Expenses". Both these categories more than doubled in size during the year, a significant surge
|
||||
especially considering their already high baseline spending. This could be for a variety of reasons.
|
||||
|
||||
For "Taxes and Similar Charges", the hike could indicate the town adjusting local taxation to meet the additional
|
||||
expenditures, or it could reflect an increase in income from other sources falling under this group. The influx
|
||||
of refugees and the resulting uptick in economic activity may have also led to a rise in the collection of certain
|
||||
local taxes or fees.
|
||||
|
||||
Concurrently, the "Transfer Expenses" spike could be an indication of heightened social welfare payments, costs
|
||||
associated with refugee integration, and funds transferred to other entities managing the crisis. These financial
|
||||
escalations are a testament to the extensive and multifaceted financial impact the refugee crisis had on the town's
|
||||
budget.
|
||||
|
||||
<VegaLite
|
||||
spec={{
|
||||
$schema: 'https://vega.github.io/schema/vega-lite/v5.json',
|
||||
title: 'Largest Spending by Account Group',
|
||||
description: 'Largest Spending by Account Group',
|
||||
data: {
|
||||
url: 'https://storage.openspending.org/moers-all/moers-sums.csv',
|
||||
},
|
||||
transform: [
|
||||
{
|
||||
filter: {
|
||||
field: 'account group',
|
||||
oneOf: [
|
||||
'Donations And General Levies',
|
||||
'Expenses For Material And Services',
|
||||
'Personnel Expenses',
|
||||
'Taxes And Similar Charges',
|
||||
'Transfer Expenses'
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
calculate: "format(datum.amount / 1e6 * 1.20, '$,.1f') + 'M'",
|
||||
as: 'formattedAmountMillion',
|
||||
}
|
||||
],
|
||||
mark: {
|
||||
type: 'line',
|
||||
point: true,
|
||||
},
|
||||
width: 400,
|
||||
height: 400,
|
||||
encoding: {
|
||||
x: {
|
||||
field: 'date',
|
||||
type: 'temporal',
|
||||
timeUnit: 'utcyear',
|
||||
title: 'Year'
|
||||
},
|
||||
y: {
|
||||
field: 'amount',
|
||||
type: 'quantitative',
|
||||
title: 'Spending (USD in millions)',
|
||||
axis: {
|
||||
format: '~s',
|
||||
labelExpr: "format(datum.value / 1e6 * 1.20, '$,.0f') + 'M'",
|
||||
}
|
||||
},
|
||||
color: {
|
||||
field: 'account group',
|
||||
type: 'nominal',
|
||||
title: 'Account Group',
|
||||
scale: {
|
||||
domain: [
|
||||
'Donations And General Levies',
|
||||
'Expenses For Material And Services',
|
||||
'Personnel Expenses',
|
||||
'Taxes And Similar Charges',
|
||||
'Transfer Expenses'
|
||||
],
|
||||
range: [
|
||||
'#9575CD',
|
||||
'#7986CB',
|
||||
'#AED581',
|
||||
'#FFD54F',
|
||||
'#FFB74D'
|
||||
],
|
||||
},
|
||||
},
|
||||
tooltip: [
|
||||
{ field: 'account group', type: 'nominal', title: 'Area' },
|
||||
{
|
||||
field: 'formattedAmountMillion',
|
||||
type: 'ordinal',
|
||||
title: 'Spending (USD in millions)',
|
||||
},
|
||||
{ field: 'date', type: 'temporal', title: 'Year', format: '%Y' }
|
||||
],
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
By 2017, these budget items returned to their pre-2016 levels, which may suggest that the town had successfully
|
||||
adapted to the new circumstances, perhaps by implementing more cost-effective strategies.
|
||||
|
||||
While this exploration offers a compelling perspective, it's important to note that these are theories derived
|
||||
from the available budget data and the concurrent global events of the time. It underscores how global crises,
|
||||
like the refugee crisis, may potentially impact not just national budgets, but also the fiscal management of
|
||||
smaller towns like Moers.
|
||||
@@ -0,0 +1,105 @@
|
||||
---
|
||||
title: Where does Berlin spend its ERDF benefits?
|
||||
date: 2023-06-12
|
||||
authors: ['João Demenech']
|
||||
---
|
||||
|
||||
In this data-driven story, let's analyze how the city of Berlin benefited from ERDF from 2008 to 2015.
|
||||
|
||||
## What is ERDF?
|
||||
|
||||
If you're not familiar with ERDF, it's the European Regional Development Fund. According to its [official website](https://ec.europa.eu/regional_policy/funding/erdf_en):
|
||||
|
||||
> The European Regional Development Fund (ERDF) aims to strengthen economic, social, and territorial cohesion in the European Union by correcting imbalances between its regions. In 2021-2027 it will enable investments in a smarter, greener, more connected, and more social Europe that is closer to its citizens.
|
||||
|
||||
## A look into the data
|
||||
|
||||
The dataset that will be used is this one: https://www.openspending.org/@os-data/de3-berlin-2007-2013-erdf (if you're looking for ERDF data for other cities/regions, take a look at the data catalog).
|
||||
|
||||
Here's a sample of this data:
|
||||
|
||||
<FlatUiTable url="https://storage.openspending.org/de3-berlin-2007-2013-erdf/concat.csv" />
|
||||
|
||||
Note that we will only use the rows where the "amount_kind" column is set to "total_amount".
|
||||
|
||||
## How has the total amount changed over the years?
|
||||
|
||||
The line chart below shows the sum of the total amount of EUR that was approved for each year:
|
||||
|
||||
<LineChart data="https://storage.openspending.org/de3-berlin-2007-2013-erdf/berlin-erdf-2007-2013-total-amount-apporved-per-year.csv" xAxis="approval_year" yAxis="total_amount" />
|
||||
|
||||
As you can see, the total increased significantly from 2007 to 2010, later fluctuating between €7 million and €9 million per year.
|
||||
|
||||
## Who were the top beneficiaries for each year?
|
||||
|
||||
Now, let's try to understand who were the top beneficiaries each year. To do that, let's filter the data to show only the two top beneficiaries for each year:
|
||||
|
||||
<FlatUiTable url="https://storage.openspending.org/de3-berlin-2007-2013-erdf/berlin-erdf-2007-2013-total-amount-approved-per-year-per-beneficiary--top-2.csv" />
|
||||
|
||||
Since there are many years in this range, let's split this analysis into two ranges: one for 2008-2010 and the other for 2011-2015.
|
||||
|
||||
<VegaLite spec={{
|
||||
"data": { "url": "https://storage.openspending.org/de3-berlin-2007-2013-erdf/berlin-erdf-2007-2013-total-amount-approved-per-year-per-beneficiary--top-2.csv"},
|
||||
"transform": [
|
||||
{"filter": "datum.approval_year <= 2010"},
|
||||
],
|
||||
"title": "Total Amount (EUR) x Approval Year (2007-2010)",
|
||||
"width": "container",
|
||||
"mark": {"type": "bar", "tooltip": true },
|
||||
"encoding": {
|
||||
"y": {
|
||||
"aggregate": "sum",
|
||||
"field": "total_amount",
|
||||
"title": "Total Amount (EUR)",
|
||||
"stack": null
|
||||
},
|
||||
"x": {"field": "approval_year", "title": "Approval Year"},
|
||||
"color": {
|
||||
"type": "nominal",
|
||||
"field": "beneficiary_name",
|
||||
}
|
||||
}
|
||||
}} />
|
||||
|
||||
<VegaLite spec={{
|
||||
"title": "Total Amount (EUR) x Approval Year (2011-2013)",
|
||||
"data": { "url": "https://storage.openspending.org/de3-berlin-2007-2013-erdf/berlin-erdf-2007-2013-total-amount-approved-per-year-per-beneficiary--top-2.csv"},
|
||||
"transform": [
|
||||
{"filter": "datum.approval_year > 2010"},
|
||||
],
|
||||
"width": "container",
|
||||
"mark": {"type": "bar", "tooltip": true },
|
||||
"encoding": {
|
||||
"y": {
|
||||
"aggregate": "sum",
|
||||
"field": "total_amount",
|
||||
"title": "Total Amount (EUR)",
|
||||
"stack": null
|
||||
},
|
||||
"x": {"field": "approval_year", "title": "Approval Year"},
|
||||
"color": {
|
||||
"type": "nominal",
|
||||
"field": "beneficiary_name",
|
||||
}
|
||||
}
|
||||
}} />
|
||||
|
||||
It's easy to spot some repeating colors. Now, let's see to which sector the top beneficiaries belong to:
|
||||
|
||||
<Table csv="
|
||||
Beneficiary,Sector
|
||||
D & B,Education
|
||||
Stiftung Sozialpädagogisches Institut Berlin (SPI),Education/Social work
|
||||
IB e.V.,Social work
|
||||
gsub-Projektegesellschaft mbH,Consulting
|
||||
BBW Berufsvorbereitungs-u.Ausbildungsgesellschaft,Education
|
||||
Arbeit und Bildung e.V.,Consulting
|
||||
Gesellschaft für soziale Unternehmensberatung GSUB,Consulting
|
||||
SPI Consult GmbH,Consulting
|
||||
Beuth Hochschule für Technik Berlin,Education
|
||||
TU Berlin, Fakultät II,Education
|
||||
Hochschule für Technik und Wirtschaft Berlin,Education
|
||||
WeTeK gGmbH,Education
|
||||
" />
|
||||
|
||||
Based on the sectors of the top beneficiaries, it's clear that education and professional training have been a major focus of ERDF investment in Berlin during that period of time.
|
||||
@@ -2,7 +2,7 @@
|
||||
import { remark } from "remark";
|
||||
import stripMarkdown, { Options } from "strip-markdown";
|
||||
|
||||
import { defaultConfig as siteConfig } from '@flowershow/core'
|
||||
import { defaultConfig as siteConfig } from '@portaljs/core'
|
||||
|
||||
// TODO return type
|
||||
const sluggify = (urlPath: string) => {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import matter from "gray-matter";
|
||||
import mdxmermaid from "mdx-mermaid";
|
||||
import { h } from "hastscript";
|
||||
import remarkCallouts from "@flowershow/remark-callouts";
|
||||
import remarkEmbed from "@flowershow/remark-embed";
|
||||
import remarkCallouts from "@portaljs/remark-callouts";
|
||||
import remarkEmbed from "@portaljs/remark-embed";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import remarkMath from "remark-math";
|
||||
import remarkSmartypants from "remark-smartypants";
|
||||
import remarkToc from "remark-toc";
|
||||
import remarkWikiLink from "@flowershow/remark-wiki-link";
|
||||
import remarkWikiLink from "@portaljs/remark-wiki-link";
|
||||
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
||||
import rehypeKatex from "rehype-katex";
|
||||
import rehypeSlug from "rehype-slug";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MarkdownDB } from "@flowershow/markdowndb";
|
||||
import { MarkdownDB } from "mddb";
|
||||
// import config from "./markdowndb.config.js";
|
||||
|
||||
// TODO get this path from markdowndb.config.js or something
|
||||
|
||||
4124
examples/openspending/package-lock.json
generated
4124
examples/openspending/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -12,53 +12,55 @@
|
||||
"test": "vitest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@octokit/plugin-throttling": "^5.2.2",
|
||||
"@types/flexsearch": "^0.7.3",
|
||||
"@vitejs/plugin-react": "^4.0.0",
|
||||
"clsx": "^1.2.1",
|
||||
"datapackage": "^1.1.10",
|
||||
"flexsearch": "0.7.21",
|
||||
"next-seo": "^6.0.0",
|
||||
"octokit": "^2.0.14",
|
||||
"prettier": "^2.8.8",
|
||||
"react-hook-form": "^7.43.9",
|
||||
"react-markdown": "^8.0.7",
|
||||
"react-timeago": "^7.1.0",
|
||||
"rehype-raw": "^6.1.1",
|
||||
"remark": "^14.0.3",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"strip-markdown": "^5.0.1",
|
||||
"@flowershow/core": "^0.4.13",
|
||||
"@flowershow/markdowndb": "^0.1.5",
|
||||
"@flowershow/remark-callouts": "^1.0.0",
|
||||
"@flowershow/remark-embed": "^1.0.0",
|
||||
"@flowershow/markdowndb": "^0.1.8",
|
||||
"@githubocto/flat-ui": "^0.14.1",
|
||||
"@headlessui/react": "^1.7.14",
|
||||
"@heroicons/react": "^2.0.18",
|
||||
"@octokit/plugin-throttling": "^5.2.2",
|
||||
"@portaljs/ckan": "^0.0.2",
|
||||
"@portaljs/components": "^0.1.8",
|
||||
"@portaljs/components": "0.1.12",
|
||||
"@portaljs/core": "^1.0.5",
|
||||
"@portaljs/remark-callouts": "^1.0.5",
|
||||
"@portaljs/remark-embed": "^1.0.4",
|
||||
"@portaljs/remark-wiki-link": "^1.0.4",
|
||||
"@tailwindcss/typography": "^0.5.9",
|
||||
"@types/flexsearch": "^0.7.3",
|
||||
"@types/node": "20.2.3",
|
||||
"@types/react": "18.2.6",
|
||||
"@types/react-dom": "18.2.4",
|
||||
"@vitejs/plugin-react": "^4.0.0",
|
||||
"autoprefixer": "10.4.14",
|
||||
"clsx": "^1.2.1",
|
||||
"datapackage": "^1.1.10",
|
||||
"eslint": "8.41.0",
|
||||
"eslint-config-next": "13.4.3",
|
||||
"flexsearch": "0.7.21",
|
||||
"isomorphic-unfetch": "^4.0.2",
|
||||
"mddb": "^0.1.9",
|
||||
"next": "13.4.3",
|
||||
"next-mdx-remote": "^4.4.1",
|
||||
"next-seo": "^6.0.0",
|
||||
"octokit": "^2.0.14",
|
||||
"papaparse": "^5.4.1",
|
||||
"postcss": "8.4.23",
|
||||
"prettier": "^2.8.8",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-hook-form": "^7.43.9",
|
||||
"react-markdown": "^8.0.7",
|
||||
"react-query": "^3.39.3",
|
||||
"react-timeago": "^7.1.0",
|
||||
"rehype-autolink-headings": "^6.1.1",
|
||||
"rehype-katex": "^6.0.3",
|
||||
"rehype-prism-plus": "^1.5.1",
|
||||
"rehype-raw": "^6.1.1",
|
||||
"rehype-slug": "^5.1.0",
|
||||
"remark": "^14.0.3",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"remark-math": "^5.1.1",
|
||||
"remark-smartypants": "^2.0.0",
|
||||
"remark-toc": "^8.0.1",
|
||||
"strip-markdown": "^5.0.1",
|
||||
"tailwindcss": "3.3.2",
|
||||
"typescript": "5.0.4"
|
||||
},
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { AppProps } from 'next/app';
|
||||
import '@portaljs/components/styles.css';
|
||||
import './styles.css';
|
||||
import { NextSeo } from 'next-seo';
|
||||
|
||||
@@ -13,7 +14,7 @@ import {
|
||||
ThemeProvider,
|
||||
NavItem,
|
||||
NavGroup,
|
||||
} from '@flowershow/core';
|
||||
} from '@portaljs/core';
|
||||
|
||||
export interface CustomAppProps {
|
||||
meta: {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from 'fs';
|
||||
import React from 'react';
|
||||
import { GetStaticProps } from 'next';
|
||||
import { BlogsList, SimpleLayout } from '@flowershow/core';
|
||||
import { BlogsList, SimpleLayout } from '@portaljs/core';
|
||||
import clientPromise from '../lib/mddb';
|
||||
import type { CustomAppProps } from './_app';
|
||||
import Layout from '@/components/_shared/Layout';
|
||||
|
||||
@@ -4,7 +4,12 @@ import { GetStaticProps } from 'next';
|
||||
import Layout from '../../components/_shared/Layout';
|
||||
import { formatDate } from '@/utils/formatDate';
|
||||
import parse from '../../lib/markdown';
|
||||
import DataRichDocument from '../../components/DataRichDocument';
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
const DataRichDocument = dynamic(
|
||||
() => import('../../components/DataRichDocument'),
|
||||
{ ssr: false }
|
||||
);
|
||||
|
||||
export default function Page({ source, meta }) {
|
||||
return (
|
||||
@@ -46,7 +51,10 @@ export const getStaticProps: GetStaticProps = async ({ params }) => {
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const mddb = await clientPromise;
|
||||
let allDocuments = await mddb.getFiles({ extensions: ['mdx'], folder: 'stories' });
|
||||
let allDocuments = await mddb.getFiles({
|
||||
extensions: ['mdx'],
|
||||
folder: 'stories',
|
||||
});
|
||||
|
||||
const paths = allDocuments
|
||||
.filter((page) => page.metadata?.isDraft !== true)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from 'fs';
|
||||
import React from 'react';
|
||||
import { GetStaticProps } from 'next';
|
||||
import { BlogsList, SimpleLayout } from '@flowershow/core';
|
||||
import { BlogsList, SimpleLayout } from '@portaljs/core';
|
||||
import clientPromise from '../../lib/mddb';
|
||||
import type { CustomAppProps } from '../_app';
|
||||
import Layout from '@/components/_shared/Layout';
|
||||
|
||||
@@ -86,7 +86,7 @@ pre {
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@import "@flowershow/remark-callouts/styles.css";
|
||||
@import "@portaljs/remark-callouts/styles.css";
|
||||
|
||||
.w-5 {
|
||||
width: 1.25rem
|
||||
|
||||
@@ -4,8 +4,8 @@ module.exports = {
|
||||
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./node_modules/@flowershow/core/dist/*.js",
|
||||
"./node_modules/@flowershow/core/*.js",
|
||||
"./node_modules/@portaljs/core/dist/*.js",
|
||||
"./node_modules/@portaljs/core/*.js",
|
||||
],
|
||||
darkMode: "class",
|
||||
theme: {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import matter from "gray-matter";
|
||||
import mdxmermaid from "mdx-mermaid";
|
||||
import { h } from "hastscript";
|
||||
import remarkCallouts from "@flowershow/remark-callouts";
|
||||
import remarkEmbed from "@flowershow/remark-embed";
|
||||
import remarkCallouts from "@portaljs/remark-callouts";
|
||||
import remarkEmbed from "@portaljs/remark-embed";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import remarkMath from "remark-math";
|
||||
import remarkSmartypants from "remark-smartypants";
|
||||
import remarkToc from "remark-toc";
|
||||
import remarkWikiLink from "@flowershow/remark-wiki-link";
|
||||
import remarkWikiLink from "@portaljs/remark-wiki-link";
|
||||
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
||||
import rehypeKatex from "rehype-katex";
|
||||
import rehypeSlug from "rehype-slug";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MarkdownDB } from "@flowershow/markdowndb";
|
||||
import { MarkdownDB } from "mddb";
|
||||
|
||||
const dbPath = "markdown.db";
|
||||
|
||||
|
||||
1252
examples/turing/package-lock.json
generated
1252
examples/turing/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -12,11 +12,6 @@
|
||||
},
|
||||
"browserslist": "defaults, not ie <= 11",
|
||||
"dependencies": {
|
||||
"@flowershow/core": "^0.4.10",
|
||||
"@flowershow/markdowndb": "^0.1.1",
|
||||
"@flowershow/remark-callouts": "^1.0.0",
|
||||
"@flowershow/remark-embed": "^1.0.0",
|
||||
"@flowershow/remark-wiki-link": "^1.1.2",
|
||||
"@headlessui/react": "^1.7.13",
|
||||
"@heroicons/react": "^2.0.17",
|
||||
"@mapbox/rehype-prism": "^0.8.0",
|
||||
@@ -24,6 +19,10 @@
|
||||
"@mdx-js/react": "^2.1.5",
|
||||
"@next/mdx": "^13.0.2",
|
||||
"@opentelemetry/api": "^1.4.0",
|
||||
"@portaljs/core": "^1.0.5",
|
||||
"@portaljs/remark-callouts": "^1.0.5",
|
||||
"@portaljs/remark-embed": "^1.0.4",
|
||||
"@portaljs/remark-wiki-link": "^1.0.4",
|
||||
"@tailwindcss/forms": "^0.5.3",
|
||||
"@tailwindcss/typography": "^0.5.4",
|
||||
"@tanstack/react-table": "^8.8.5",
|
||||
@@ -35,6 +34,7 @@
|
||||
"focus-visible": "^5.2.0",
|
||||
"gray-matter": "^4.0.3",
|
||||
"hastscript": "^7.2.0",
|
||||
"mddb": "^0.1.9",
|
||||
"mdx-mermaid": "^2.0.0-rc7",
|
||||
"mermaid": "^10.1.0",
|
||||
"next": "13.2.1",
|
||||
@@ -60,12 +60,12 @@
|
||||
"tailwindcss": "^3.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "18.16.0",
|
||||
"@types/react": "18.2.0",
|
||||
"@types/react-dom": "18.2.0",
|
||||
"eslint": "8.26.0",
|
||||
"eslint-config-next": "13.0.2",
|
||||
"prettier": "^2.8.7",
|
||||
"prettier-plugin-tailwindcss": "^0.2.6",
|
||||
"@types/node": "18.16.0",
|
||||
"@types/react": "18.2.0",
|
||||
"@types/react-dom": "18.2.0"
|
||||
"prettier-plugin-tailwindcss": "^0.2.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { MDXRemote } from 'next-mdx-remote'
|
||||
import { Card } from '../components/Card'
|
||||
import Head from 'next/head'
|
||||
import parse from '../lib/markdown'
|
||||
import { Mermaid } from '@flowershow/core';
|
||||
import { Mermaid } from '@portaljs/core';
|
||||
|
||||
export const getStaticProps = async ({ params }) => {
|
||||
const urlPath = params.slug ? params.slug.join('/') : ''
|
||||
|
||||
1720
package-lock.json
generated
1720
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "portaljs",
|
||||
"workspaces": ["./packages/*"],
|
||||
"workspaces": [
|
||||
"./packages/*"
|
||||
],
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"changeset": "changeset",
|
||||
"prerelease": "nx run-many --targets=lint,test,build --projects=tag:test",
|
||||
"release": "changeset publish"
|
||||
},
|
||||
"private": true,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'tailwindcss/tailwind.css'
|
||||
import '../src/index.css'
|
||||
|
||||
|
||||
import type { Preview } from '@storybook/react';
|
||||
|
||||
const preview: Preview = {
|
||||
|
||||
@@ -1,5 +1,31 @@
|
||||
# @portaljs/components
|
||||
|
||||
## 0.3.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#980](https://github.com/datopian/portaljs/pull/980) [`38738525`](https://github.com/datopian/portaljs/commit/3873852567b1aab4827a716bd588bd5de3223e2b) Thanks [@demenech](https://github.com/demenech)! - Fix missing CSS styles for PDF component
|
||||
|
||||
## 0.3.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [`2e13c1b7`](https://github.com/datopian/portaljs/commit/2e13c1b738ddac91a9419f5c0484406328bd1cd3) Thanks [@demenech](https://github.com/demenech)! - PDF and Excel components
|
||||
|
||||
- [#973](https://github.com/datopian/portaljs/pull/973) [`f3c2a2ff`](https://github.com/datopian/portaljs/commit/f3c2a2ffa7dcf9693bd25318c719ce58d27070b8) Thanks [@demenech](https://github.com/demenech)! - Implement <Excel /> component
|
||||
|
||||
## 0.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [`80c6221a`](https://github.com/datopian/portaljs/commit/80c6221a05733f8c1dd0431bed4d72b1f9d7d636) Thanks [@luccasmmg](https://github.com/luccasmmg)! - Added the OpenLayers and the Map(Leaflet based) component
|
||||
|
||||
## 0.1.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#960](https://github.com/datopian/portaljs/pull/960) [`add2f6d0`](https://github.com/datopian/portaljs/commit/add2f6d0f372434eb996d59d6faf5cd06530c932) Thanks [@demenech](https://github.com/demenech)! - Fix width of the <LineChart /> component
|
||||
|
||||
## 0.1.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@portaljs/components",
|
||||
"version": "0.1.11",
|
||||
"version": "0.3.1",
|
||||
"type": "module",
|
||||
"description": "https://portaljs.org",
|
||||
"keywords": [
|
||||
@@ -12,12 +12,14 @@
|
||||
],
|
||||
"scripts": {
|
||||
"dev": "npm run storybook",
|
||||
"build": "tsc && vite build && npm run build-tailwind",
|
||||
"example": "vite",
|
||||
"build": "tsc && vite build && npm run build-tailwind && npm run fix-leaflet",
|
||||
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||
"storybook": "storybook dev -p 6006",
|
||||
"build-storybook": "storybook build",
|
||||
"build-tailwind": "NODE_ENV=production npx tailwindcss -o ./dist/styles.css --minify",
|
||||
"prepare": "npm run build"
|
||||
"build-tailwind": "NODE_ENV=production npx tailwindcss --postcss -c tailwind.config.js -i src/index.css -o ./dist/style.css --minify",
|
||||
"prepare": "npm run build",
|
||||
"fix-leaflet": "node ./scripts/fix-leaflet.cjs"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.2.0",
|
||||
@@ -26,19 +28,29 @@
|
||||
"dependencies": {
|
||||
"@githubocto/flat-ui": "^0.14.1",
|
||||
"@heroicons/react": "^2.0.17",
|
||||
"@planet/maps": "^8.1.0",
|
||||
"@tanstack/react-table": "^8.8.5",
|
||||
"ag-grid-react": "^30.0.4",
|
||||
"chroma-js": "^2.4.2",
|
||||
"flexsearch": "0.7.21",
|
||||
"leaflet": "^1.9.4",
|
||||
"next-mdx-remote": "^4.4.1",
|
||||
"ol": "^7.4.0",
|
||||
"papaparse": "^5.4.1",
|
||||
"postcss-url": "^10.1.3",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-hook-form": "^7.43.9",
|
||||
"react-leaflet": "^4.2.1",
|
||||
"react-query": "^3.39.3",
|
||||
"react-vega": "^7.6.0",
|
||||
"rollup-plugin-re": "^1.0.7",
|
||||
"vega": "5.25.0",
|
||||
"vega-lite": "5.1.0",
|
||||
"vitest": "^0.31.4"
|
||||
"vitest": "^0.31.4",
|
||||
"@react-pdf-viewer/core": "3.6.0",
|
||||
"@react-pdf-viewer/default-layout": "3.6.0",
|
||||
"pdfjs-dist": "2.15.349",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/addon-essentials": "^7.0.7",
|
||||
@@ -48,13 +60,16 @@
|
||||
"@storybook/react": "^7.0.7",
|
||||
"@storybook/react-vite": "^7.0.7",
|
||||
"@storybook/testing-library": "^0.0.14-next.2",
|
||||
"@swc/core": "^1.3.68",
|
||||
"@types/flexsearch": "^0.7.3",
|
||||
"@types/leaflet": "^1.9.3",
|
||||
"@types/papaparse": "^5.3.7",
|
||||
"@types/react": "^18.0.28",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"@typescript-eslint/eslint-plugin": "^5.57.1",
|
||||
"@typescript-eslint/parser": "^5.57.1",
|
||||
"@vitejs/plugin-react": "^4.0.0",
|
||||
"@vitejs/plugin-react-swc": "^3.3.2",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"eslint": "^8.38.0",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
@@ -62,12 +77,15 @@
|
||||
"eslint-plugin-storybook": "^0.6.11",
|
||||
"json": "^11.0.0",
|
||||
"postcss": "^8.4.23",
|
||||
"postcss-import": "^15.1.0",
|
||||
"postcss-import-url": "^7.2.0",
|
||||
"prop-types": "^15.8.1",
|
||||
"storybook": "^7.0.7",
|
||||
"tailwindcss": "^3.3.2",
|
||||
"typescript": "^5.0.2",
|
||||
"vite": "^4.3.2",
|
||||
"vite-plugin-dts": "^2.3.0"
|
||||
"vite-plugin-dts": "^2.3.0",
|
||||
"vite-plugin-swc-only": "^0.1.18"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
@@ -81,7 +99,7 @@
|
||||
"require": "./dist/components.umd.js"
|
||||
},
|
||||
"./styles.css": {
|
||||
"import": "./dist/styles.css"
|
||||
"import": "./dist/style.css"
|
||||
}
|
||||
},
|
||||
"publishConfig": {
|
||||
|
||||
BIN
packages/components/portaljs-components-0.1.12.tgz
Normal file
BIN
packages/components/portaljs-components-0.1.12.tgz
Normal file
Binary file not shown.
@@ -1,6 +1,10 @@
|
||||
console.log('PostCSS');
|
||||
|
||||
export default {
|
||||
plugins: {
|
||||
'postcss-import': {},
|
||||
'postcss-url': { url: 'inline' },
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
6
packages/components/scripts/fix-leaflet.cjs
Normal file
6
packages/components/scripts/fix-leaflet.cjs
Normal file
@@ -0,0 +1,6 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const leafletPath = path.join(require.resolve('leaflet'), '../')
|
||||
|
||||
fs.cpSync(`${leafletPath}images`,'./dist/images', { recursive: true });
|
||||
99
packages/components/src/components/Excel.tsx
Normal file
99
packages/components/src/components/Excel.tsx
Normal file
@@ -0,0 +1,99 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import LoadingSpinner from './LoadingSpinner';
|
||||
import { read, utils } from 'xlsx';
|
||||
import { AgGridReact } from 'ag-grid-react';
|
||||
import 'ag-grid-community/styles/ag-grid.css';
|
||||
import 'ag-grid-community/styles/ag-theme-alpine.css';
|
||||
|
||||
export type ExcelProps = {
|
||||
url: string;
|
||||
};
|
||||
|
||||
export function Excel({ url }: ExcelProps) {
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [activeSheetName, setActiveSheetName] = useState<string>();
|
||||
const [workbook, setWorkbook] = useState<any>();
|
||||
const [rows, setRows] = useState<any>();
|
||||
const [cols, setCols] = useState<any>();
|
||||
|
||||
const loadSpreadsheet = (wb: any, name: string) => {
|
||||
setActiveSheetName(name);
|
||||
const ws = wb.Sheets[name];
|
||||
|
||||
const range = utils.decode_range(ws['!ref'] || 'A1');
|
||||
const columns = Array.from({ length: range.e.c + 1 }, (_, i) => ({
|
||||
field: utils.encode_col(i),
|
||||
}));
|
||||
|
||||
const rowsAr = utils.sheet_to_json(ws, { header: 1 });
|
||||
const rows = rowsAr.map((row) => {
|
||||
const obj = {};
|
||||
columns.forEach((col, i) => {
|
||||
obj[col.field] = row[i];
|
||||
});
|
||||
return obj;
|
||||
});
|
||||
|
||||
setRows(rows);
|
||||
setCols(columns);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setIsLoading(true);
|
||||
|
||||
fetch(url)
|
||||
.then((res) => res.arrayBuffer())
|
||||
.then((f) => {
|
||||
const wb = read(f);
|
||||
setWorkbook(wb);
|
||||
loadSpreadsheet(wb, wb.SheetNames[0]);
|
||||
setIsLoading(false);
|
||||
});
|
||||
}, [url]);
|
||||
|
||||
return isLoading ? (
|
||||
<div className="w-full flex items-center justify-center w-[600px] h-[300px]">
|
||||
<LoadingSpinner />
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{cols && rows && (
|
||||
<div>
|
||||
<div
|
||||
className="ag-theme-alpine"
|
||||
style={{ height: 400, width: '100%' }}
|
||||
>
|
||||
<AgGridReact
|
||||
rowData={rows}
|
||||
columnDefs={cols}
|
||||
defaultColDef={{
|
||||
resizable: true,
|
||||
minWidth: 200,
|
||||
flex: 1,
|
||||
sortable: true,
|
||||
filter: true,
|
||||
}}
|
||||
></AgGridReact>
|
||||
</div>
|
||||
<div className="border-t">
|
||||
{workbook.SheetNames.map((name: string, idx: number) => {
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
key={idx}
|
||||
className={`text-sm px-3 pb-2 pt-4 border-b border-l border-r ${
|
||||
name == activeSheetName ? 'font-semibold' : ''
|
||||
}`}
|
||||
onClick={() => loadSpreadsheet(workbook, name)}
|
||||
>
|
||||
{name}
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -35,7 +35,7 @@ export function LineChart({
|
||||
const spec = {
|
||||
$schema: 'https://vega.github.io/schema/vega-lite/v5.json',
|
||||
title,
|
||||
width: 600,
|
||||
width: 'container',
|
||||
height: 300,
|
||||
mark: {
|
||||
type: 'line',
|
||||
|
||||
233
packages/components/src/components/Map.tsx
Normal file
233
packages/components/src/components/Map.tsx
Normal file
@@ -0,0 +1,233 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import LoadingSpinner from './LoadingSpinner';
|
||||
import loadData from '../lib/loadData';
|
||||
import chroma from 'chroma-js';
|
||||
import {
|
||||
MapContainer,
|
||||
TileLayer,
|
||||
GeoJSON as GeoJSONLayer,
|
||||
LayersControl,
|
||||
} from 'react-leaflet';
|
||||
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import * as L from 'leaflet';
|
||||
|
||||
export type MapProps = {
|
||||
layers: {
|
||||
data: string | GeoJSON.GeoJSON;
|
||||
name: string;
|
||||
colorScale?: {
|
||||
starting: string;
|
||||
ending: string;
|
||||
};
|
||||
tooltip?:
|
||||
| {
|
||||
propNames: string[];
|
||||
}
|
||||
| boolean;
|
||||
_id?: number;
|
||||
}[];
|
||||
title?: string;
|
||||
center?: { latitude: number | undefined; longitude: number | undefined };
|
||||
zoom?: number;
|
||||
};
|
||||
|
||||
export function Map({
|
||||
layers = [
|
||||
{
|
||||
data: null,
|
||||
name: null,
|
||||
colorScale: { starting: 'blue', ending: 'red' },
|
||||
tooltip: true,
|
||||
},
|
||||
],
|
||||
center = { latitude: 45, longitude: 45 },
|
||||
zoom = 2,
|
||||
title = '',
|
||||
}: MapProps) {
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [layersData, setLayersData] = useState<any>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const loadDataPromises = layers.map(async (layer) => {
|
||||
let layerData: any;
|
||||
|
||||
if (typeof layer.data === 'string') {
|
||||
// If "data" is string, assume it's a URL
|
||||
setIsLoading(true);
|
||||
layerData = await loadData(layer.data).then((res: any) => {
|
||||
return JSON.parse(res);
|
||||
});
|
||||
} else {
|
||||
// Else, expect raw GeoJSON
|
||||
layerData = layer.data;
|
||||
}
|
||||
|
||||
if (layer.colorScale) {
|
||||
const colorScaleAr = chroma
|
||||
.scale([layer.colorScale.starting, layer.colorScale.ending])
|
||||
.mode('lch')
|
||||
.colors(layerData.features.length);
|
||||
|
||||
layerData.features.forEach((feature, i) => {
|
||||
// Only style if the feature doesn't have a color prop
|
||||
if (feature.color === undefined) {
|
||||
feature.color = colorScaleAr[i];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return { name: layer.name, data: layerData };
|
||||
});
|
||||
|
||||
Promise.all(loadDataPromises).then((values) => {
|
||||
setLayersData(values);
|
||||
setIsLoading(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return isLoading ? (
|
||||
<div className="w-full flex items-center justify-center w-[600px] h-[300px]">
|
||||
<LoadingSpinner />
|
||||
</div>
|
||||
) : (
|
||||
<MapContainer
|
||||
center={[center.latitude, center.longitude]}
|
||||
zoom={zoom}
|
||||
scrollWheelZoom={false}
|
||||
className="h-80 w-full"
|
||||
// @ts-ignore
|
||||
whenReady={(map: any) => {
|
||||
// Enable zoom using scroll wheel
|
||||
map.target.scrollWheelZoom.enable();
|
||||
|
||||
// Create the title box
|
||||
var info = new L.Control() as any;
|
||||
|
||||
info.onAdd = function () {
|
||||
this._div = L.DomUtil.create('div', 'info');
|
||||
this.update();
|
||||
return this._div;
|
||||
};
|
||||
|
||||
info.update = function () {
|
||||
this._div.innerHTML = `<h4 style="font-weight: 600; background: #f9f9f9; padding: 5px; border-radius: 5px; color: #464646;">${title}</h4>`;
|
||||
};
|
||||
|
||||
if (title) info.addTo(map.target);
|
||||
}}
|
||||
>
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
/>
|
||||
<LayersControl position="bottomright">
|
||||
{layers.map((layer) => {
|
||||
const data = layersData.find(
|
||||
(layerData) => layerData.name === layer.name
|
||||
)?.data;
|
||||
|
||||
return (
|
||||
data && (
|
||||
<LayersControl.Overlay key={layer.name} checked name={layer.name}>
|
||||
<GeoJSONLayer
|
||||
data={data}
|
||||
// @ts-ignore
|
||||
pointToLayer={(feature, latlng) => {
|
||||
// This resolver an issue in which the bundled map was
|
||||
// not finding the images
|
||||
const leafletBase =
|
||||
'https://unpkg.com/leaflet@1.9.4/dist/images/';
|
||||
|
||||
const icon = new L.Icon({
|
||||
iconUrl: leafletBase + 'marker-icon.png',
|
||||
iconRetinaUrl: leafletBase + 'marker-icon-2x.png',
|
||||
shadowUrl: leafletBase + 'marker-shadow.png',
|
||||
iconSize: [25, 41],
|
||||
iconAnchor: [12, 41],
|
||||
popupAnchor: [1, -34],
|
||||
tooltipAnchor: [16, -28],
|
||||
shadowSize: [41, 41],
|
||||
});
|
||||
|
||||
const iconMarker = L.marker(latlng, { icon });
|
||||
return iconMarker;
|
||||
}}
|
||||
style={(geoJsonFeature: any) => {
|
||||
// Set the fill color of each feature when appliable
|
||||
if (
|
||||
!['Point', 'MultiPoint'].includes(geoJsonFeature.type)
|
||||
) {
|
||||
return { color: geoJsonFeature?.color };
|
||||
}
|
||||
}}
|
||||
eventHandlers={{
|
||||
add: (e) => {
|
||||
const featureGroup = e.target;
|
||||
const tooltip = layer.tooltip;
|
||||
|
||||
featureGroup.eachLayer((featureLayer) => {
|
||||
const feature = featureLayer.feature;
|
||||
const geometryType = feature.geometry.type;
|
||||
|
||||
if (tooltip) {
|
||||
const featurePropNames = Object.keys(
|
||||
feature.properties
|
||||
);
|
||||
let includedFeaturePropNames;
|
||||
|
||||
if (tooltip === true) {
|
||||
includedFeaturePropNames = featurePropNames;
|
||||
} else {
|
||||
includedFeaturePropNames = tooltip.propNames.filter(
|
||||
(name) => featurePropNames.includes(name)
|
||||
);
|
||||
}
|
||||
|
||||
if (includedFeaturePropNames) {
|
||||
const tooltipContent = includedFeaturePropNames
|
||||
.map(
|
||||
(name) =>
|
||||
`<b>${name}:</b> ${feature.properties[name]}`
|
||||
)
|
||||
.join('<br />');
|
||||
|
||||
featureLayer.bindTooltip(tooltipContent, {
|
||||
direction: 'center',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
featureLayer.on({
|
||||
mouseover: (event) => {
|
||||
if (
|
||||
['Polygon', 'MultiPolygon'].includes(geometryType)
|
||||
) {
|
||||
event.target.setStyle({
|
||||
fillOpacity: 0.5,
|
||||
});
|
||||
}
|
||||
},
|
||||
mouseout: (event) => {
|
||||
if (
|
||||
['Polygon', 'MultiPolygon'].includes(geometryType)
|
||||
) {
|
||||
event.target.setStyle({
|
||||
fillOpacity: 0.2,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
}}
|
||||
/>
|
||||
;
|
||||
</LayersControl.Overlay>
|
||||
)
|
||||
);
|
||||
})}
|
||||
</LayersControl>
|
||||
</MapContainer>
|
||||
);
|
||||
}
|
||||
84
packages/components/src/components/OpenLayers/Controls.jsx
Normal file
84
packages/components/src/components/OpenLayers/Controls.jsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
export const Controls = ({ children }) => {
|
||||
return <div>{children}</div>;
|
||||
};
|
||||
|
||||
import { FullScreen, Zoom } from 'ol/control';
|
||||
import { MapContext } from './Map';
|
||||
|
||||
export const FullScreenControl = () => {
|
||||
const { map } = useContext(MapContext);
|
||||
useEffect(() => {
|
||||
if (!map) return;
|
||||
let fullScreenControl = new FullScreen({
|
||||
className: 'ml-1 flex flex-col w-8 items-center mt-2',
|
||||
activeClassName:
|
||||
'w-full inline-flex justify-center items-center rounded-t-md bg-white px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10 text-sm',
|
||||
inactiveClassName:
|
||||
'inline-flex w-full justify-center items-center rounded-t-md bg-white px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10 text-sm',
|
||||
});
|
||||
let zoomControl = new Zoom({
|
||||
className: 'ml-1 flex flex-col w-8 items-center',
|
||||
zoomInClassName:
|
||||
'inline-flex w-full justify-center items-center bg-white px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10 text-sm',
|
||||
zoomOutClassName:
|
||||
'inline-flex w-full justify-center items-center rounded-b-md bg-white px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10 text-sm',
|
||||
});
|
||||
map.controls.push(fullScreenControl);
|
||||
map.controls.push(zoomControl);
|
||||
|
||||
return () => {
|
||||
map.controls.remove(zoomControl);
|
||||
map.controls.remove(fullScreenControl);
|
||||
};
|
||||
}, [map]);
|
||||
return null;
|
||||
};
|
||||
|
||||
//build a list of checkboxes in react
|
||||
|
||||
export const ListOfCheckboxes = ({ layers, shownLayers, setShownLayers }) => {
|
||||
//layers is an array of url and name
|
||||
function addLayer(layer) {
|
||||
setShownLayers([...shownLayers, layer.url]);
|
||||
}
|
||||
|
||||
function removeLayer(layer) {
|
||||
setShownLayers(shownLayers.filter((l) => l !== layer.url));
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3 className="mb-4 font-semibold text-gray-900 ">Layers</h3>
|
||||
<ul className="w-48 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg ">
|
||||
{layers.map((layer, index) => (
|
||||
<li
|
||||
key={index}
|
||||
className="w-full border-b border-gray-200 rounded-t-lg "
|
||||
>
|
||||
<div className="flex items-center pl-3">
|
||||
<input
|
||||
id={layer.name}
|
||||
type="checkbox"
|
||||
defaultChecked={shownLayers.includes(layer.url)}
|
||||
onClick={() =>
|
||||
shownLayers.includes(layer.url)
|
||||
? removeLayer(layer)
|
||||
: addLayer(layer)
|
||||
}
|
||||
value={true}
|
||||
className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 focus:ring-2 "
|
||||
></input>
|
||||
<label
|
||||
htmlFor={layer.name}
|
||||
className="w-full py-3 ml-2 text-sm font-medium text-gray-90"
|
||||
>
|
||||
{layer.name}
|
||||
</label>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import HeatMap from 'ol/layer/Heatmap';
|
||||
import { MapContext } from './Map';
|
||||
const HeatMapLayer = ({ source, style, zIndex = 0 }) => {
|
||||
const { map } = useContext(MapContext);
|
||||
const [heatMapLayer, setHeatMapLayer] = useState(null);
|
||||
useEffect(() => {
|
||||
if (!map) return;
|
||||
let heatMapLayer = new HeatMap({
|
||||
source,
|
||||
style,
|
||||
blur: parseInt(5, 10),
|
||||
radius: parseInt(5, 10),
|
||||
});
|
||||
map.addLayer(heatMapLayer);
|
||||
setHeatMapLayer(heatMapLayer);
|
||||
heatMapLayer.setZIndex(zIndex);
|
||||
return () => {
|
||||
if (map) {
|
||||
map.removeLayer(heatMapLayer);
|
||||
}
|
||||
};
|
||||
}, [map]);
|
||||
useEffect(() => {
|
||||
heatMapLayer && heatMapLayer.setZIndex(zIndex);
|
||||
}, [zIndex]);
|
||||
return null;
|
||||
};
|
||||
export default HeatMapLayer;
|
||||
4
packages/components/src/components/OpenLayers/Layers.jsx
Normal file
4
packages/components/src/components/OpenLayers/Layers.jsx
Normal file
@@ -0,0 +1,4 @@
|
||||
import React from 'react';
|
||||
export const Layers = ({ children }) => {
|
||||
return <div>{children}</div>;
|
||||
};
|
||||
50
packages/components/src/components/OpenLayers/Map.jsx
Normal file
50
packages/components/src/components/OpenLayers/Map.jsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import React, { useRef, useState, useEffect } from 'react';
|
||||
import * as ol from 'ol';
|
||||
|
||||
export const MapContext = new React.createContext();
|
||||
|
||||
const Map = ({ children, zoom, center, setSelected }) => {
|
||||
const mapRef = useRef();
|
||||
const [map, setMap] = useState(null);
|
||||
// on component mount
|
||||
useEffect(() => {
|
||||
let options = {
|
||||
view: new ol.View({ zoom, center }),
|
||||
layers: [],
|
||||
controls: [],
|
||||
overlays: [],
|
||||
};
|
||||
let mapObject = new ol.Map(options);
|
||||
mapObject.setTarget(mapRef.current);
|
||||
setMap(mapObject);
|
||||
return () => mapObject.setTarget(undefined);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (map) {
|
||||
if (setSelected !== null) {
|
||||
let selected = null;
|
||||
map.on('pointermove', function (e) {
|
||||
map.forEachFeatureAtPixel(e.pixel, function (f) {
|
||||
selected = f;
|
||||
return true;
|
||||
});
|
||||
if (selected) {
|
||||
setSelected(selected);
|
||||
} else {
|
||||
setSelected(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [map]);
|
||||
return (
|
||||
<MapContext.Provider value={{ map }}>
|
||||
<div ref={mapRef} className="w-full" style={{height: '500px'}}>
|
||||
{children}
|
||||
</div>
|
||||
</MapContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default Map;
|
||||
136
packages/components/src/components/OpenLayers/OpenLayers.tsx
Normal file
136
packages/components/src/components/OpenLayers/OpenLayers.tsx
Normal file
@@ -0,0 +1,136 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import Map from './Map';
|
||||
import { Layers } from './Layers';
|
||||
import { Fill, Icon, Style } from 'ol/style';
|
||||
import * as olSource from 'ol/source';
|
||||
import TileLayer from './TileLayer';
|
||||
import { fromLonLat } from 'ol/proj';
|
||||
import VectorLayer from './VectorLayer';
|
||||
import { Vector as VectorSource } from 'ol/source';
|
||||
import GeoJSON from 'ol/format/GeoJSON';
|
||||
import KML from 'ol/format/KML';
|
||||
import { colors } from './colors';
|
||||
import { FullScreenControl, Controls, ListOfCheckboxes } from './Controls';
|
||||
import HeatMapLayer from './HeatMapLayer';
|
||||
|
||||
function osm() {
|
||||
return new olSource.OSM();
|
||||
}
|
||||
|
||||
const formats = {
|
||||
geojson: new GeoJSON(),
|
||||
kml: new KML(),
|
||||
};
|
||||
|
||||
interface OpenLayersProps {
|
||||
layers: {
|
||||
url: string;
|
||||
name?: string;
|
||||
format?: string;
|
||||
heatmap?: boolean;
|
||||
}[];
|
||||
center?: [number, number];
|
||||
zoom?: number;
|
||||
popup?: (selected: any) => JSX.Element;
|
||||
}
|
||||
|
||||
export default function OpenLayers({
|
||||
layers,
|
||||
center = [0, 0],
|
||||
zoom = 1,
|
||||
popup,
|
||||
}: OpenLayersProps) {
|
||||
const [shownLayers, setShownLayers] = useState(
|
||||
layers.map((layer) => layer.url)
|
||||
);
|
||||
const [selected, setSelected] = useState(null);
|
||||
const [style, setStyle] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
const style = new Style({
|
||||
fill: new Fill({
|
||||
color: '#eeeeee',
|
||||
}),
|
||||
image: new Icon({
|
||||
anchor: [0.5, 46],
|
||||
anchorXUnits: 'fraction',
|
||||
anchorYUnits: 'pixels',
|
||||
width: 18,
|
||||
height: 28,
|
||||
src: 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Google_Maps_icon_%282020%29.svg/418px-Google_Maps_icon_%282020%29.svg.png?20200218211225',
|
||||
}),
|
||||
});
|
||||
setStyle(style);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<Map
|
||||
center={fromLonLat(center)}
|
||||
zoom={zoom}
|
||||
setSelected={popup ? setSelected : null}
|
||||
>
|
||||
<Layers>
|
||||
<TileLayer source={osm()} zIndex={0} />
|
||||
{layers.map((layer, index) =>
|
||||
!layer.heatmap ? (
|
||||
<VectorLayer
|
||||
key={index}
|
||||
zIndex={shownLayers.includes(layer.url) ? 1 : -1}
|
||||
source={
|
||||
new VectorSource({
|
||||
url: layer.url,
|
||||
format: layer.format
|
||||
? formats[layer.format]
|
||||
: new GeoJSON(),
|
||||
})
|
||||
}
|
||||
style={function (feature) {
|
||||
const id = feature.getId();
|
||||
const color = feature.get('COLOR') || colors[id % 1302].hex;
|
||||
style.getFill().setColor(color);
|
||||
return style;
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<HeatMapLayer
|
||||
key={index}
|
||||
zIndex={shownLayers.includes(layer.url) ? 1 : -1}
|
||||
source={
|
||||
new VectorSource({
|
||||
url: layer.url,
|
||||
format: layer.format
|
||||
? formats[layer.format]
|
||||
: new GeoJSON(),
|
||||
})
|
||||
}
|
||||
style={function (feature) {
|
||||
const color =
|
||||
feature.get('COLOR') || colors[feature.ol_uid % 1302].hex;
|
||||
style.getFill().setColor(color);
|
||||
return style;
|
||||
}}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</Layers>
|
||||
{/* add a floating pane that will output the ListOfCheckboxes component using tailwind*/}
|
||||
<div className="absolute bottom-0 right-0 m-4 p-4 z-50 bg-white rounded-lg shadow-xl">
|
||||
<ListOfCheckboxes
|
||||
layers={layers}
|
||||
shownLayers={shownLayers}
|
||||
setShownLayers={setShownLayers}
|
||||
/>
|
||||
</div>
|
||||
{popup && selected && (
|
||||
<div className="absolute bottom-0 left-0 m-4 p-4 z-50 bg-white rounded-lg shadow-xl">
|
||||
{popup(selected)}
|
||||
</div>
|
||||
)}
|
||||
<Controls>
|
||||
<FullScreenControl />
|
||||
</Controls>
|
||||
</Map>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
23
packages/components/src/components/OpenLayers/TileLayer.jsx
Normal file
23
packages/components/src/components/OpenLayers/TileLayer.jsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { useContext, useEffect } from 'react';
|
||||
import OLTileLayer from 'ol/layer/Tile';
|
||||
import { MapContext } from './Map';
|
||||
const TileLayer = ({ source, zIndex = 0 }) => {
|
||||
const { map } = useContext(MapContext);
|
||||
useEffect(() => {
|
||||
if (!map) return;
|
||||
|
||||
let tileLayer = new OLTileLayer({
|
||||
source,
|
||||
zIndex,
|
||||
});
|
||||
map.addLayer(tileLayer);
|
||||
tileLayer.setZIndex(zIndex);
|
||||
return () => {
|
||||
if (map) {
|
||||
map.removeLayer(tileLayer);
|
||||
}
|
||||
};
|
||||
}, [map]);
|
||||
return null;
|
||||
};
|
||||
export default TileLayer;
|
||||
@@ -0,0 +1,33 @@
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import OLVectorLayer from 'ol/layer/Vector';
|
||||
import { MapContext } from './Map';
|
||||
const VectorLayer = ({ source, style, zIndex = 0 }) => {
|
||||
const { map } = useContext(MapContext);
|
||||
const [vectorLayer, setVectorLayer] = useState(null);
|
||||
useEffect(() => {
|
||||
if (!map) return;
|
||||
let vectorLayer = new OLVectorLayer({
|
||||
source,
|
||||
style,
|
||||
});
|
||||
const vectorSource = vectorLayer.getSource();
|
||||
vectorSource.on('featuresloadend', function () {
|
||||
vectorSource.getFeatures().forEach((feature, index) => {
|
||||
feature.setId(index);
|
||||
});
|
||||
});
|
||||
map.addLayer(vectorLayer);
|
||||
setVectorLayer(vectorLayer);
|
||||
vectorLayer.setZIndex(zIndex);
|
||||
return () => {
|
||||
if (map) {
|
||||
map.removeLayer(vectorLayer);
|
||||
}
|
||||
};
|
||||
}, [map]);
|
||||
useEffect(() => {
|
||||
vectorLayer && vectorLayer.setZIndex(zIndex);
|
||||
}, [zIndex]);
|
||||
return null;
|
||||
};
|
||||
export default VectorLayer;
|
||||
5210
packages/components/src/components/OpenLayers/colors.js
Normal file
5210
packages/components/src/components/OpenLayers/colors.js
Normal file
File diff suppressed because it is too large
Load Diff
32
packages/components/src/components/PdfViewer.tsx
Normal file
32
packages/components/src/components/PdfViewer.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
// Core viewer
|
||||
import { Viewer, Worker, SpecialZoomLevel } from '@react-pdf-viewer/core';
|
||||
import { defaultLayoutPlugin } from '@react-pdf-viewer/default-layout';
|
||||
|
||||
// Import styles
|
||||
import '@react-pdf-viewer/core/lib/styles/index.css';
|
||||
import '@react-pdf-viewer/default-layout/lib/styles/index.css';
|
||||
|
||||
export interface PdfViewerProps {
|
||||
url: string;
|
||||
layout: boolean;
|
||||
parentClassName?: string;
|
||||
}
|
||||
|
||||
export function PdfViewer({
|
||||
url,
|
||||
layout = false,
|
||||
parentClassName,
|
||||
}: PdfViewerProps) {
|
||||
const defaultLayoutPluginInstance = defaultLayoutPlugin();
|
||||
return (
|
||||
<Worker workerUrl="https://unpkg.com/pdfjs-dist@2.15.349/build/pdf.worker.js">
|
||||
<div className={parentClassName}>
|
||||
<Viewer
|
||||
defaultScale={SpecialZoomLevel.PageWidth}
|
||||
fileUrl={url}
|
||||
plugins={layout ? [defaultLayoutPluginInstance] : []}
|
||||
/>
|
||||
</div>
|
||||
</Worker>
|
||||
);
|
||||
}
|
||||
6
packages/components/src/include.css
Normal file
6
packages/components/src/include.css
Normal file
@@ -0,0 +1,6 @@
|
||||
/* Temporary fix for a size issue with FlatUiTable loading indicator on Firefox */
|
||||
@layer base {
|
||||
svg[tw^='animate-pulse w-12'] {
|
||||
max-width: 100px;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
/* Temporary fix for a size issue with FlatUiTable loading indicator on Firefox */
|
||||
@layer base {
|
||||
svg[tw^='animate-pulse w-12'] {
|
||||
max-width: 100px;
|
||||
}
|
||||
}
|
||||
@import "tailwindcss/base";
|
||||
@import "tailwindcss/components";
|
||||
@import "include";
|
||||
@import "leaflet";
|
||||
@import '@react-pdf-viewer/core/lib/styles/index.css';
|
||||
@import '@react-pdf-viewer/default-layout/lib/styles/index.css';
|
||||
@import 'ag-grid-community/styles/ag-grid.css';
|
||||
@import 'ag-grid-community/styles/ag-theme-alpine.css';
|
||||
@import "tailwindcss/utilities";
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
export * from "./components/Table";
|
||||
export * from "./components/Catalog";
|
||||
export * from "./components/LineChart";
|
||||
export * from "./components/Vega";
|
||||
export * from "./components/VegaLite";
|
||||
export * from "./components/FlatUiTable";
|
||||
export * from './components/Table';
|
||||
export * from './components/Catalog';
|
||||
export * from './components/LineChart';
|
||||
export * from './components/Vega';
|
||||
export * from './components/VegaLite';
|
||||
export * from './components/FlatUiTable';
|
||||
export * from './components/OpenLayers/OpenLayers';
|
||||
export * from './components/Map';
|
||||
export * from './components/PdfViewer';
|
||||
export * from "./components/Excel";
|
||||
|
||||
171
packages/components/src/types/GeoJSON.tsx
Normal file
171
packages/components/src/types/GeoJSON.tsx
Normal file
@@ -0,0 +1,171 @@
|
||||
/**
|
||||
* Typescript types for the GeoJSON RFC7946 specification. This is not fully RFC-compliant due to lack of support for
|
||||
* ranged number data types.
|
||||
*
|
||||
* See https://tools.ietf.org/html/rfc7946
|
||||
*/
|
||||
export declare namespace GeoJSON {
|
||||
/**
|
||||
* Inside this document, the term "geometry type" refers to seven case-sensitive strings: "Point", "MultiPoint",
|
||||
* "LineString", "MultiLineString", "Polygon", "MultiPolygon", and "GeometryCollection".
|
||||
*/
|
||||
export type Geometry = Point | MultiPoint | LineString | MultiLineString | Polygon | MultiPolygon
|
||||
| GeometryCollection;
|
||||
export type GeometryType = Geometry["type"];
|
||||
|
||||
/**
|
||||
* ...the term "GeoJSON types" refers to nine case-sensitive strings: "Feature", "FeatureCollection", and the
|
||||
* geometry types listed above.
|
||||
*/
|
||||
export type GeoJson = Geometry | Feature | FeatureCollection;
|
||||
export type GeoJsonType = GeoJson["type"];
|
||||
|
||||
// types
|
||||
|
||||
/**
|
||||
* A position is an array of numbers. There MUST be two or more elements. The first two elements are longitude and
|
||||
* latitude, or easting and northing, precisely in that order and using decimal numbers. Altitude or elevation MAY
|
||||
* be included as an optional third element.
|
||||
*
|
||||
* Implementations SHOULD NOT extend positions beyond three elements because the semantics of extra elements are
|
||||
* unspecified and ambiguous.
|
||||
*/
|
||||
export type Position = [longitude: number, latitude: number, elevation?: number]
|
||||
|
||||
export type Record = { [key in string | number]: unknown };
|
||||
|
||||
/**
|
||||
* Properties inherit to all GeoJSON types
|
||||
*/
|
||||
export interface GeometryBase extends Record {
|
||||
/**
|
||||
* A GeoJSON object MAY have a member named "bbox" to include information on the coordinate range for its
|
||||
* Geometries, Features, or FeatureCollections. The value of the bbox member MUST be an array of length 2*n
|
||||
* where n is the number of dimensions represented in the contained geometries, with all axes of the most
|
||||
* southwesterly point followed by all axes of the more northeasterly point. The axes order of a bbox follows
|
||||
* the axes order of geometries.
|
||||
*/
|
||||
bbox?: number[];
|
||||
|
||||
/**
|
||||
* A GeoJSON object MAY have other members.
|
||||
*
|
||||
* Members not described in this specification ("foreign members") MAY be used in a GeoJSON document. Note that
|
||||
* support for foreign members can vary across implementations, and no normative processing model for foreign
|
||||
* members is defined.
|
||||
*/
|
||||
}
|
||||
|
||||
// geometry types
|
||||
|
||||
export interface Point extends GeometryBase {
|
||||
type: "Point";
|
||||
/**
|
||||
* For type "Point", the "coordinates" member is a single position.
|
||||
*/
|
||||
coordinates: Position;
|
||||
}
|
||||
|
||||
export interface MultiPoint extends GeometryBase {
|
||||
type: "MultiPoint";
|
||||
/**
|
||||
* For type "MultiPoint", the "coordinates" member is an array of positions.
|
||||
*/
|
||||
coordinates: Position[];
|
||||
}
|
||||
|
||||
export interface LineString extends GeometryBase {
|
||||
type: "LineString";
|
||||
/**
|
||||
* For type "LineString", the "coordinates" member is an array of two or more positions.
|
||||
*/
|
||||
coordinates: { 0: Position, 1: Position } & Position[]
|
||||
}
|
||||
|
||||
export interface MultiLineString extends GeometryBase {
|
||||
type: "MultiLineString";
|
||||
/**
|
||||
* For type "MultiLineString", the "coordinates" member is an array of LineString coordinate arrays.
|
||||
*/
|
||||
coordinates: LineString["coordinates"][];
|
||||
}
|
||||
|
||||
/**
|
||||
* To specify a constraint specific to Polygons, it is useful to introduce the concept of a linear ring:
|
||||
* - A linear ring is a closed LineString with four or more positions.
|
||||
* - The first and last positions are equivalent, and they MUST contain identical values; their representation
|
||||
* SHOULD also be identical.
|
||||
* - A linear ring is the boundary of a surface or the boundary of a hole in a surface.
|
||||
* - A linear ring MUST follow the right-hand rule with respect to the area it bounds, i.e., exterior rings are
|
||||
* counterclockwise, and holes are clockwise.
|
||||
*/
|
||||
export type LinearRing = { 0: Position, 1: Position, 2: Position, 3: Position } & Position[];
|
||||
|
||||
export interface Polygon extends GeometryBase {
|
||||
type: "Polygon";
|
||||
/**
|
||||
* For type "Polygon", the "coordinates" member MUST be an array of linear ring coordinate arrays.
|
||||
*
|
||||
* For Polygons with more than one of these rings, the first MUST be the exterior ring, and any others MUST be
|
||||
* interior rings. The exterior ring bounds the surface, and the interior rings (if present) bound holes within
|
||||
* the surface.
|
||||
*/
|
||||
coordinates: LinearRing[];
|
||||
}
|
||||
|
||||
export interface MultiPolygon extends GeometryBase {
|
||||
type: "MultiPolygon";
|
||||
/**
|
||||
* For type "MultiPolygon", the "coordinates" member is an array of Polygon coordinate arrays.
|
||||
*/
|
||||
coordinates: Polygon["coordinates"][];
|
||||
}
|
||||
|
||||
export interface GeometryCollection {
|
||||
/**
|
||||
* A GeoJSON object with type "GeometryCollection" is a Geometry object.
|
||||
*/
|
||||
type: "GeometryCollection";
|
||||
/**
|
||||
* A GeometryCollection has a member with the name "geometries". The value of "geometries" is an array. Each
|
||||
* element of this array is a GeoJSON Geometry object. It is possible for this array to be empty.
|
||||
*/
|
||||
geometries: Geometry[];
|
||||
}
|
||||
|
||||
// GeoJSON types
|
||||
|
||||
export interface Feature {
|
||||
/**
|
||||
* A Feature object has a "type" member with the value "Feature".
|
||||
*/
|
||||
type: "Feature";
|
||||
/**
|
||||
* If a Feature has a commonly used identifier, that identifier SHOULD be included as a member of the Feature object
|
||||
* with the name "id", and the value of this member is either a JSON string or number.
|
||||
*/
|
||||
id?: string | number;
|
||||
/**
|
||||
* A Feature object has a member with the name "geometry". The value of the geometry member SHALL be either a
|
||||
* Geometry object as defined above or, in the case that the Feature is unlocated, a JSON null value.
|
||||
*/
|
||||
geometry: Geometry | null;
|
||||
/**
|
||||
* A Feature object has a member with the name "properties". The value of the properties member is an object
|
||||
* (any JSON object or a JSON null value).
|
||||
*/
|
||||
properties: Record | null;
|
||||
}
|
||||
|
||||
export interface FeatureCollection {
|
||||
/**
|
||||
* A GeoJSON object with the type "FeatureCollection" is a FeatureCollection object.
|
||||
*/
|
||||
type: "FeatureCollection";
|
||||
/**
|
||||
* A FeatureCollection object has a member with the name "features". The value of "features" is a JSON array. Each
|
||||
* element of the array is a Feature object as defined above. It is possible for this array to be empty.
|
||||
*/
|
||||
features: Feature[];
|
||||
}
|
||||
}
|
||||
34
packages/components/stories/Excel.stories.ts
Normal file
34
packages/components/stories/Excel.stories.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { Excel, ExcelProps } from '../src/components/Excel';
|
||||
|
||||
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction
|
||||
const meta: Meta = {
|
||||
title: 'Components/Excel',
|
||||
component: Excel,
|
||||
tags: ['autodocs'],
|
||||
argTypes: {
|
||||
url: {
|
||||
description:
|
||||
'Url of the file to be displayed e.g.: "https://url.to/data.csv"',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<ExcelProps>;
|
||||
|
||||
export const SingleSheet: Story = {
|
||||
name: 'Excel file with just one sheet',
|
||||
args: {
|
||||
url: 'https://sheetjs.com/pres.xlsx',
|
||||
},
|
||||
};
|
||||
|
||||
export const MultipleSheet: Story = {
|
||||
name: 'Excel file with multiple sheets',
|
||||
args: {
|
||||
url: 'https://storage.portaljs.org/IC-Gantt-Chart-Project-Template-8857.xlsx',
|
||||
},
|
||||
};
|
||||
91
packages/components/stories/Map.stories.ts
Normal file
91
packages/components/stories/Map.stories.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { Map, MapProps } from '../src/components/Map';
|
||||
|
||||
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction
|
||||
const meta: Meta = {
|
||||
title: 'Components/Map',
|
||||
component: Map,
|
||||
tags: ['autodocs'],
|
||||
argTypes: {
|
||||
layers: {
|
||||
description:
|
||||
'Data to be displayed.\n\n GeoJSON Object \n\nOR\n\n URL to GeoJSON Object',
|
||||
},
|
||||
title: {
|
||||
description: 'Title to display on the map. Optional.',
|
||||
},
|
||||
center: {
|
||||
description: 'Initial coordinates of the center of the map',
|
||||
},
|
||||
zoom: {
|
||||
description: 'Zoom level',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<MapProps>;
|
||||
|
||||
// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
|
||||
export const GeoJSONPolygons: Story = {
|
||||
name: 'GeoJSON polygons map',
|
||||
args: {
|
||||
layers: [
|
||||
{
|
||||
data: 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_geography_marine_polys.geojson',
|
||||
name: 'Polygons',
|
||||
tooltip: { propNames: ['name'] },
|
||||
colorScale: {
|
||||
starting: '#ff0000',
|
||||
ending: '#00ff00',
|
||||
},
|
||||
},
|
||||
],
|
||||
title: 'Seas and Oceans Map',
|
||||
center: { latitude: 45, longitude: 0 },
|
||||
zoom: 2,
|
||||
},
|
||||
};
|
||||
|
||||
export const GeoJSONPoints: Story = {
|
||||
name: 'GeoJSON points map',
|
||||
args: {
|
||||
layers: [
|
||||
{
|
||||
data: 'https://opendata.arcgis.com/datasets/9c58741995174fbcb017cf46c8a42f4b_25.geojson',
|
||||
name: 'Points',
|
||||
tooltip: { propNames: ['Location'] },
|
||||
},
|
||||
],
|
||||
title: 'Roads in York',
|
||||
center: { latitude: 53.9614, longitude: -1.0739 },
|
||||
zoom: 12,
|
||||
},
|
||||
};
|
||||
|
||||
export const GeoJSONMultipleLayers: Story = {
|
||||
name: 'GeoJSON polygons and points map',
|
||||
args: {
|
||||
layers: [
|
||||
{
|
||||
data: 'https://opendata.arcgis.com/datasets/9c58741995174fbcb017cf46c8a42f4b_25.geojson',
|
||||
name: 'Points',
|
||||
tooltip: true,
|
||||
},
|
||||
{
|
||||
data: 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_geography_marine_polys.geojson',
|
||||
name: 'Polygons',
|
||||
tooltip: true,
|
||||
colorScale: {
|
||||
starting: '#ff0000',
|
||||
ending: '#00ff00',
|
||||
},
|
||||
},
|
||||
],
|
||||
title: 'Polygons and points',
|
||||
center: { latitude: 45, longitude: 0 },
|
||||
zoom: 2,
|
||||
},
|
||||
};
|
||||
136
packages/components/stories/OpenLayers.stories.tsx
Normal file
136
packages/components/stories/OpenLayers.stories.tsx
Normal file
@@ -0,0 +1,136 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import React from 'react';
|
||||
import OpenLayers from '../src/components/OpenLayers/OpenLayers';
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Components/OpenLayers',
|
||||
component: OpenLayers,
|
||||
argTypes: {
|
||||
layers: {
|
||||
description: 'Layers to be added to the map',
|
||||
control: {
|
||||
type: 'array',
|
||||
},
|
||||
},
|
||||
center: {
|
||||
description: 'Center of the map',
|
||||
defaultValue: [0, 0],
|
||||
control: {
|
||||
type: 'array',
|
||||
},
|
||||
},
|
||||
zoom: {
|
||||
description: 'Zoom level of the map',
|
||||
defaultValue: 1,
|
||||
control: {
|
||||
type: 'number',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<any>;
|
||||
|
||||
export const Secondary: Story = {
|
||||
name: 'Map with OpenLayers',
|
||||
args: {
|
||||
layers: [
|
||||
{
|
||||
url: 'https://openlayers.org/data/vector/ecoregions.json',
|
||||
name: 'Ecoregions',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export const Primary: Story = {
|
||||
name: 'Map with OpenLayers 2',
|
||||
args: {
|
||||
layers: [
|
||||
{
|
||||
url: 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_geography_marine_polys.geojson',
|
||||
name: 'Marine regions',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export const MapWithPopover: Story = {
|
||||
name: 'Map with popup',
|
||||
args: {
|
||||
layers: [
|
||||
{
|
||||
url: 'https://openlayers.org/data/vector/ecoregions.json',
|
||||
name: 'Ecoregions',
|
||||
},
|
||||
],
|
||||
popup: (feature: any) => {
|
||||
return (
|
||||
<div className="flex flex-col gap-y-1" style={{ color: 'red' }}>
|
||||
<span className="font-bold">Biome name</span>
|
||||
<span className="text-sm">{feature.values_.BIOME_NAME}</span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Third: Story = {
|
||||
name: 'Map with two layers',
|
||||
args: {
|
||||
layers: [
|
||||
{
|
||||
url: 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_geography_marine_polys.geojson',
|
||||
name: 'Marine regions',
|
||||
},
|
||||
{
|
||||
url: 'https://openlayers.org/data/vector/ecoregions.json',
|
||||
name: 'Ecoregions',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export const CustomCenter: Story = {
|
||||
name: 'Map with custom center and zoom',
|
||||
args: {
|
||||
layers: [
|
||||
{
|
||||
url: 'https://openlayers.org/data/vector/ecoregions.json',
|
||||
name: 'Ecoregions',
|
||||
},
|
||||
],
|
||||
center: [-15, 20],
|
||||
zoom: 4,
|
||||
},
|
||||
};
|
||||
|
||||
export const PointsOnMap: Story = {
|
||||
name: 'Map with points on',
|
||||
args: {
|
||||
layers: [
|
||||
{
|
||||
url: 'https://opendata.arcgis.com/datasets/9c58741995174fbcb017cf46c8a42f4b_25.geojson',
|
||||
name: 'E-Scooter Parking Bays',
|
||||
},
|
||||
],
|
||||
center: [-1.055429957881787, 53.963900188025301],
|
||||
zoom: 12,
|
||||
},
|
||||
};
|
||||
|
||||
export const KMLFile: Story = {
|
||||
name: 'Map with KML File',
|
||||
args: {
|
||||
layers: [
|
||||
{
|
||||
url: 'https://openlayers.org/en/latest/examples/data/kml/2012_Earthquakes_Mag5.kml',
|
||||
name: '2012 Earthquakes M5+',
|
||||
format: 'kml',
|
||||
heatmap: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
50
packages/components/stories/PdfViewer.stories.ts
Normal file
50
packages/components/stories/PdfViewer.stories.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { PdfViewer, PdfViewerProps } from '../src/components/PdfViewer';
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Components/PdfViewer',
|
||||
component: PdfViewer,
|
||||
tags: ['autodocs'],
|
||||
argTypes: {
|
||||
url: {
|
||||
description: 'URL to PDF file',
|
||||
},
|
||||
parentClassName: {
|
||||
description: 'Classname for the parent div of the pdf viewer',
|
||||
},
|
||||
layour: {
|
||||
description:
|
||||
'Set to true if you want to have a layout with zoom level, page count, printing button etc',
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<PdfViewerProps>;
|
||||
|
||||
export const PdfViewerStory: Story = {
|
||||
name: 'PdfViewer',
|
||||
args: {
|
||||
url: 'https://cdn.filestackcontent.com/wcrjf9qPTCKXV3hMXDwK',
|
||||
},
|
||||
};
|
||||
|
||||
export const PdfViewerStoryWithLayout: Story = {
|
||||
name: 'PdfViewer with the default layout',
|
||||
args: {
|
||||
url: 'https://cdn.filestackcontent.com/wcrjf9qPTCKXV3hMXDwK',
|
||||
layout: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const PdfViewerStoryWithHeight: Story = {
|
||||
name: 'PdfViewer with a custom height',
|
||||
args: {
|
||||
url: 'https://cdn.filestackcontent.com/wcrjf9qPTCKXV3hMXDwK',
|
||||
parentClassName: 'h-96',
|
||||
layout: true,
|
||||
},
|
||||
};
|
||||
@@ -1,8 +1,10 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
content: [
|
||||
'./index.html',
|
||||
'./src/**/*.{js,ts,jsx,tsx}',
|
||||
'./stories/*.{js,ts,jsx,tsx}',
|
||||
],
|
||||
theme: {},
|
||||
plugins: [],
|
||||
};
|
||||
|
||||
@@ -1,29 +1,14 @@
|
||||
import react from '@vitejs/plugin-react'
|
||||
import path from 'node:path'
|
||||
import { defineConfig } from 'vitest/config'
|
||||
import dts from 'vite-plugin-dts'
|
||||
import tailwindcss from 'tailwindcss'
|
||||
import { UserConfigExport } from 'vite'
|
||||
import replace from "rollup-plugin-re"
|
||||
import react from '@vitejs/plugin-react';
|
||||
import path from 'node:path';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
import dts from 'vite-plugin-dts';
|
||||
import tailwindcss from 'tailwindcss';
|
||||
import { UserConfigExport } from 'vite';
|
||||
|
||||
const app = async (): Promise<UserConfigExport> => {
|
||||
return defineConfig({
|
||||
plugins: [
|
||||
react(),
|
||||
replace({
|
||||
patterns: [
|
||||
{
|
||||
match: /js-sha256/,
|
||||
test: `eval("require('crypto')")`,
|
||||
replace: `require('crypto')`,
|
||||
},
|
||||
{
|
||||
match: /js-sha256/,
|
||||
test: `eval("require('buffer').Buffer")`,
|
||||
replace: `require('buffer').Buffer`,
|
||||
},
|
||||
],
|
||||
}),
|
||||
dts({
|
||||
insertTypesEntry: true,
|
||||
}),
|
||||
@@ -34,6 +19,7 @@ const app = async (): Promise<UserConfigExport> => {
|
||||
},
|
||||
},
|
||||
build: {
|
||||
target: 'es2020',
|
||||
lib: {
|
||||
entry: path.resolve(__dirname, 'src/index.ts'),
|
||||
name: 'components',
|
||||
@@ -41,12 +27,27 @@ const app = async (): Promise<UserConfigExport> => {
|
||||
fileName: (format) => `components.${format}.js`,
|
||||
},
|
||||
rollupOptions: {
|
||||
external: ['react', 'react-dom', 'tailwindcss', 'vega-lite', 'vega', 'react-vega'],
|
||||
external: [
|
||||
'react',
|
||||
'ol-mapbox-style',
|
||||
'react-dom',
|
||||
'tailwindcss',
|
||||
'vega-lite',
|
||||
'vega',
|
||||
'react-vega',
|
||||
'ol',
|
||||
'leaflet',
|
||||
],
|
||||
output: {
|
||||
manualChunks: undefined,
|
||||
globals: {
|
||||
react: 'React',
|
||||
ol: 'ol',
|
||||
'ol-mapbox-style': 'ol-mapbox-style',
|
||||
'react-vega': 'react-vega',
|
||||
'react-dom': 'ReactDOM',
|
||||
tailwindcss: 'tailwindcss',
|
||||
leaflet: 'leaflet',
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -55,7 +56,7 @@ const app = async (): Promise<UserConfigExport> => {
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
},
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
// https://vitejs.dev/config/
|
||||
export default app
|
||||
export default app;
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
// vite.config.ts
|
||||
import react from "file:///home/urutu-branco/Projetos/portaljs/node_modules/@vitejs/plugin-react-swc/index.mjs";
|
||||
import path from "node:path";
|
||||
import { defineConfig } from "file:///home/urutu-branco/Projetos/portaljs/node_modules/vitest/dist/config.js";
|
||||
import dts from "file:///home/urutu-branco/Projetos/portaljs/node_modules/vite-plugin-dts/dist/index.mjs";
|
||||
import tailwindcss from "file:///home/urutu-branco/Projetos/portaljs/node_modules/tailwindcss/lib/index.js";
|
||||
var __vite_injected_original_dirname = "/home/urutu-branco/Projetos/portaljs/packages/components";
|
||||
var app = async () => {
|
||||
return defineConfig({
|
||||
plugins: [
|
||||
react(),
|
||||
dts({
|
||||
insertTypesEntry: true
|
||||
})
|
||||
],
|
||||
css: {
|
||||
postcss: {
|
||||
plugins: [tailwindcss]
|
||||
}
|
||||
},
|
||||
build: {
|
||||
target: "es2020",
|
||||
lib: {
|
||||
entry: path.resolve(__vite_injected_original_dirname, "src/index.ts"),
|
||||
name: "components",
|
||||
formats: ["es", "umd"],
|
||||
fileName: (format) => `components.${format}.js`
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [
|
||||
"react",
|
||||
"ol-mapbox-style",
|
||||
"react-dom",
|
||||
"tailwindcss",
|
||||
"vega-lite",
|
||||
"vega",
|
||||
"react-vega",
|
||||
"ol",
|
||||
"ol/dom.js"
|
||||
],
|
||||
output: {
|
||||
manualChunks: void 0,
|
||||
globals: {
|
||||
react: "React",
|
||||
ol: "ol",
|
||||
"ol/dom.js": "ol/dom.js",
|
||||
"react-vega": "react-vega",
|
||||
"react-dom": "ReactDOM",
|
||||
tailwindcss: "tailwindcss"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
test: {
|
||||
globals: true,
|
||||
environment: "jsdom"
|
||||
}
|
||||
});
|
||||
};
|
||||
var vite_config_default = app;
|
||||
export {
|
||||
vite_config_default as default
|
||||
};
|
||||
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCIvaG9tZS91cnV0dS1icmFuY28vUHJvamV0b3MvcG9ydGFsanMvcGFja2FnZXMvY29tcG9uZW50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL2hvbWUvdXJ1dHUtYnJhbmNvL1Byb2pldG9zL3BvcnRhbGpzL3BhY2thZ2VzL2NvbXBvbmVudHMvdml0ZS5jb25maWcudHNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL2hvbWUvdXJ1dHUtYnJhbmNvL1Byb2pldG9zL3BvcnRhbGpzL3BhY2thZ2VzL2NvbXBvbmVudHMvdml0ZS5jb25maWcudHNcIjtpbXBvcnQgcmVhY3QgZnJvbSAnQHZpdGVqcy9wbHVnaW4tcmVhY3Qtc3djJztcbmltcG9ydCBwYXRoIGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgeyBkZWZpbmVDb25maWcgfSBmcm9tICd2aXRlc3QvY29uZmlnJztcbmltcG9ydCBkdHMgZnJvbSAndml0ZS1wbHVnaW4tZHRzJztcbmltcG9ydCB0YWlsd2luZGNzcyBmcm9tICd0YWlsd2luZGNzcyc7XG5pbXBvcnQgeyBVc2VyQ29uZmlnRXhwb3J0IH0gZnJvbSAndml0ZSc7XG5pbXBvcnQgcmVwbGFjZSBmcm9tICdyb2xsdXAtcGx1Z2luLXJlJztcblxuY29uc3QgYXBwID0gYXN5bmMgKCk6IFByb21pc2U8VXNlckNvbmZpZ0V4cG9ydD4gPT4ge1xuICByZXR1cm4gZGVmaW5lQ29uZmlnKHtcbiAgICBwbHVnaW5zOiBbXG4gICAgICByZWFjdCgpLFxuICAgICAgZHRzKHtcbiAgICAgICAgaW5zZXJ0VHlwZXNFbnRyeTogdHJ1ZSxcbiAgICAgIH0pLFxuICAgIF0sXG4gICAgY3NzOiB7XG4gICAgICBwb3N0Y3NzOiB7XG4gICAgICAgIHBsdWdpbnM6IFt0YWlsd2luZGNzc10sXG4gICAgICB9LFxuICAgIH0sXG4gICAgYnVpbGQ6IHtcbiAgICAgIHRhcmdldDogJ2VzMjAyMCcsXG4gICAgICBsaWI6IHtcbiAgICAgICAgZW50cnk6IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICdzcmMvaW5kZXgudHMnKSxcbiAgICAgICAgbmFtZTogJ2NvbXBvbmVudHMnLFxuICAgICAgICBmb3JtYXRzOiBbJ2VzJywgJ3VtZCddLFxuICAgICAgICBmaWxlTmFtZTogKGZvcm1hdCkgPT4gYGNvbXBvbmVudHMuJHtmb3JtYXR9LmpzYCxcbiAgICAgIH0sXG4gICAgICByb2xsdXBPcHRpb25zOiB7XG4gICAgICAgIGV4dGVybmFsOiBbXG4gICAgICAgICAgJ3JlYWN0JyxcbiAgICAgICAgICAnb2wtbWFwYm94LXN0eWxlJyxcbiAgICAgICAgICAncmVhY3QtZG9tJyxcbiAgICAgICAgICAndGFpbHdpbmRjc3MnLFxuICAgICAgICAgICd2ZWdhLWxpdGUnLFxuICAgICAgICAgICd2ZWdhJyxcbiAgICAgICAgICAncmVhY3QtdmVnYScsXG4gICAgICAgICAgJ29sJyxcbiAgICAgICAgICAnb2wvZG9tLmpzJyxcbiAgICAgICAgXSxcbiAgICAgICAgb3V0cHV0OiB7XG4gICAgICAgICAgbWFudWFsQ2h1bmtzOiB1bmRlZmluZWQsXG4gICAgICAgICAgZ2xvYmFsczoge1xuICAgICAgICAgICAgcmVhY3Q6ICdSZWFjdCcsXG4gICAgICAgICAgICBvbDogJ29sJyxcbiAgICAgICAgICAgICdvbC9kb20uanMnOiAnb2wvZG9tLmpzJyxcbiAgICAgICAgICAgICdyZWFjdC12ZWdhJzogJ3JlYWN0LXZlZ2EnLFxuICAgICAgICAgICAgJ3JlYWN0LWRvbSc6ICdSZWFjdERPTScsXG4gICAgICAgICAgICB0YWlsd2luZGNzczogJ3RhaWx3aW5kY3NzJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICAgIHRlc3Q6IHtcbiAgICAgIGdsb2JhbHM6IHRydWUsXG4gICAgICBlbnZpcm9ubWVudDogJ2pzZG9tJyxcbiAgICB9LFxuICB9KTtcbn07XG4vLyBodHRwczovL3ZpdGVqcy5kZXYvY29uZmlnL1xuZXhwb3J0IGRlZmF1bHQgYXBwO1xuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUEwVixPQUFPLFdBQVc7QUFDNVcsT0FBTyxVQUFVO0FBQ2pCLFNBQVMsb0JBQW9CO0FBQzdCLE9BQU8sU0FBUztBQUNoQixPQUFPLGlCQUFpQjtBQUp4QixJQUFNLG1DQUFtQztBQVF6QyxJQUFNLE1BQU0sWUFBdUM7QUFDakQsU0FBTyxhQUFhO0FBQUEsSUFDbEIsU0FBUztBQUFBLE1BQ1AsTUFBTTtBQUFBLE1BQ04sSUFBSTtBQUFBLFFBQ0Ysa0JBQWtCO0FBQUEsTUFDcEIsQ0FBQztBQUFBLElBQ0g7QUFBQSxJQUNBLEtBQUs7QUFBQSxNQUNILFNBQVM7QUFBQSxRQUNQLFNBQVMsQ0FBQyxXQUFXO0FBQUEsTUFDdkI7QUFBQSxJQUNGO0FBQUEsSUFDQSxPQUFPO0FBQUEsTUFDTCxRQUFRO0FBQUEsTUFDUixLQUFLO0FBQUEsUUFDSCxPQUFPLEtBQUssUUFBUSxrQ0FBVyxjQUFjO0FBQUEsUUFDN0MsTUFBTTtBQUFBLFFBQ04sU0FBUyxDQUFDLE1BQU0sS0FBSztBQUFBLFFBQ3JCLFVBQVUsQ0FBQyxXQUFXLGNBQWM7QUFBQSxNQUN0QztBQUFBLE1BQ0EsZUFBZTtBQUFBLFFBQ2IsVUFBVTtBQUFBLFVBQ1I7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFBQSxRQUNBLFFBQVE7QUFBQSxVQUNOLGNBQWM7QUFBQSxVQUNkLFNBQVM7QUFBQSxZQUNQLE9BQU87QUFBQSxZQUNQLElBQUk7QUFBQSxZQUNKLGFBQWE7QUFBQSxZQUNiLGNBQWM7QUFBQSxZQUNkLGFBQWE7QUFBQSxZQUNiLGFBQWE7QUFBQSxVQUNmO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFBQSxJQUNGO0FBQUEsSUFDQSxNQUFNO0FBQUEsTUFDSixTQUFTO0FBQUEsTUFDVCxhQUFhO0FBQUEsSUFDZjtBQUFBLEVBQ0YsQ0FBQztBQUNIO0FBRUEsSUFBTyxzQkFBUTsiLAogICJuYW1lcyI6IFtdCn0K
|
||||
@@ -1,5 +1,17 @@
|
||||
# @portaljs/core
|
||||
|
||||
## 1.0.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#958](https://github.com/datopian/portaljs/pull/958) [`c4bf5bd0`](https://github.com/datopian/portaljs/commit/c4bf5bd05401982125750e61a27ed31f9bb14a4d) Thanks [@olayway](https://github.com/olayway)! - Add basic Hero component.
|
||||
|
||||
## 1.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [`6f0da8c3`](https://github.com/datopian/portaljs/commit/6f0da8c3a3cde4dc7512c6529eb662de6f4fe56a) Thanks [@olayway](https://github.com/olayway)! - Fix public API (`exports`, `types`, and `main` fields in `package.json`).
|
||||
|
||||
## 1.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@portaljs/core",
|
||||
"version": "1.0.4",
|
||||
"version": "1.0.6",
|
||||
"description": "Core Portal.JS components, configs and utils.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -23,7 +23,14 @@
|
||||
"dist"
|
||||
],
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
"types": "./dist/src/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/src/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@docsearch/react": "^3.3.3",
|
||||
"@floating-ui/react-dom": "^1.3.0",
|
||||
|
||||
90
packages/core/src/ui/Hero/Hero.tsx
Normal file
90
packages/core/src/ui/Hero/Hero.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
interface Button {
|
||||
title: string;
|
||||
href: string;
|
||||
type: 'filled' | 'text'
|
||||
}
|
||||
|
||||
export interface HeroProps {
|
||||
title: string;
|
||||
subtitle?: string;
|
||||
announcement?: {
|
||||
title: string;
|
||||
href?: string;
|
||||
};
|
||||
buttons?: Array<Button>
|
||||
}
|
||||
|
||||
const buttonStyle = {
|
||||
'filled': "rounded-md bg-secondary px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-secondary/90 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",
|
||||
'text': "text-sm font-semibold leading-6"
|
||||
}
|
||||
|
||||
|
||||
export const Hero: React.FC<HeroProps> = ({ title, subtitle, announcement, buttons }) => {
|
||||
|
||||
return (
|
||||
<div className="text-primary dark:text-primary-dark">
|
||||
<div className="relative isolate px-6 pt-14 lg:px-8">
|
||||
{/* <div
|
||||
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div
|
||||
className="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#38bdf8] to-[#89a8fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
|
||||
style={{
|
||||
clipPath:
|
||||
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
|
||||
}}
|
||||
/>
|
||||
</div> */}
|
||||
<div className="mx-auto max-w-2xl py-16 sm:py-32 lg:py-40">
|
||||
{announcement && (
|
||||
<div className="hidden sm:mb-8 sm:flex sm:justify-center">
|
||||
<div className="relative rounded-full px-3 py-1 text-sm leading-6 ring-1 ring-primary/20 hover:ring-primary/30 dark:ring-primary-dark/30 dark:hover:ring-primary-dark/40">
|
||||
{announcement.title}{' '}
|
||||
<a href="#" className="font-semibold text-secondary">
|
||||
<span className="absolute inset-0" aria-hidden="true" />
|
||||
Read more <span aria-hidden="true">→</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="text-center">
|
||||
<h1 className="text-4xl font-bold tracking-tight sm:text-6xl">
|
||||
{title}
|
||||
</h1>
|
||||
{subtitle && (
|
||||
<p className="mt-6 text-lg leading-8 text-primary/90 dark:text-primary-dark/80">
|
||||
{subtitle}
|
||||
</p>
|
||||
)}
|
||||
{buttons && buttons.length && (
|
||||
<div className="mt-10 flex items-center justify-center gap-x-6">
|
||||
{buttons.map((b) => (
|
||||
<a
|
||||
href={b.href}
|
||||
className={buttonStyle[b.type]}
|
||||
>
|
||||
{b.title}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* <div
|
||||
className="absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-30rem)]"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div
|
||||
className="relative left-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#89a8fc] to-[#38bdf8] opacity-30 sm:left-[calc(50%+36rem)] sm:w-[72.1875rem]"
|
||||
style={{
|
||||
clipPath:
|
||||
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
|
||||
}}
|
||||
/>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
1
packages/core/src/ui/Hero/index.ts
Normal file
1
packages/core/src/ui/Hero/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { Hero } from "./Hero"
|
||||
@@ -18,5 +18,5 @@ export { BlogLayout } from "./BlogLayout";
|
||||
export { Mermaid } from "./Mermaid";
|
||||
export { SiteToc, NavItem, NavGroup } from "./SiteToc";
|
||||
export { Comments, CommentsConfig } from "./Comments";
|
||||
|
||||
export { AuthorConfig } from "./types";
|
||||
export { Hero } from "./Hero";
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @portaljs/remark-callouts
|
||||
|
||||
## 1.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [`6f0da8c3`](https://github.com/datopian/portaljs/commit/6f0da8c3a3cde4dc7512c6529eb662de6f4fe56a) Thanks [@olayway](https://github.com/olayway)! - Fix public API (`exports`, `types`, and `main` fields in `package.json`).
|
||||
|
||||
## 1.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@portaljs/remark-callouts",
|
||||
"version": "1.0.4",
|
||||
"version": "1.0.5",
|
||||
"description": "Remark plugin to add support for blockquote-based admonitions/callouts",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -36,9 +36,12 @@
|
||||
"unist-util-visit": "^4.1.0"
|
||||
},
|
||||
"type": "module",
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.js",
|
||||
"types": "./dist/src/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"types": "./dist/src/index.d.ts",
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.cjs"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @portaljs/remark-embed
|
||||
|
||||
## 1.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [`6f0da8c3`](https://github.com/datopian/portaljs/commit/6f0da8c3a3cde4dc7512c6529eb662de6f4fe56a) Thanks [@olayway](https://github.com/olayway)! - Fix public API (`exports`, `types`, and `main` fields in `package.json`).
|
||||
|
||||
## 1.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@portaljs/remark-embed",
|
||||
"version": "1.0.3",
|
||||
"version": "1.0.4",
|
||||
"description": "Converts youtube link in mdx to an iframe embed",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -32,9 +32,12 @@
|
||||
"unist-util-visit": "^4.1.1"
|
||||
},
|
||||
"type": "module",
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.js",
|
||||
"types": "./dist/src/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"types": "./dist/src/index.d.ts",
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.cjs"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @portaljs/remark-wiki-link
|
||||
|
||||
## 1.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [`6f0da8c3`](https://github.com/datopian/portaljs/commit/6f0da8c3a3cde4dc7512c6529eb662de6f4fe56a) Thanks [@olayway](https://github.com/olayway)! - Fix public API (`exports`, `types`, and `main` fields in `package.json`).
|
||||
|
||||
## 1.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@portaljs/remark-wiki-link",
|
||||
"version": "1.0.3",
|
||||
"version": "1.0.4",
|
||||
"description": "Parse and render wiki-style links in markdown especially Obsidian style links.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -35,9 +35,12 @@
|
||||
"micromark-util-symbol": "^1.0.1"
|
||||
},
|
||||
"type": "module",
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.js",
|
||||
"types": "./dist/src/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"types": "./dist/src/index.d.ts",
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.cjs"
|
||||
}
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
"compilerOptions": {
|
||||
"types": ["node"],
|
||||
"outDir": "dist",
|
||||
"forceConsistentCasingInFileNames": true
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"declaration": true
|
||||
},
|
||||
"exclude": ["**/*.spec.ts"],
|
||||
"include": ["**/*.ts", "**/*.js"]
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
|
||||
5
site/.gitignore
vendored
5
site/.gitignore
vendored
@@ -35,3 +35,8 @@ yarn-error.log*
|
||||
|
||||
# markdowndb
|
||||
markdown.db
|
||||
|
||||
# seo
|
||||
robots.txt
|
||||
sitemap-0.xml
|
||||
sitemap.xml
|
||||
|
||||
@@ -58,7 +58,7 @@ export default function Features() {
|
||||
>
|
||||
<div className="absolute -inset-px rounded-xl border-2 border-transparent opacity-0 [background:linear-gradient(var(--quick-links-hover-bg,theme(colors.sky.50)),var(--quick-links-hover-bg,theme(colors.sky.50)))_padding-box,linear-gradient(to_top,theme(colors.blue.300),theme(colors.blue.400),theme(colors.blue.500))_border-box] group-hover:opacity-100 dark:[--quick-links-hover-bg:theme(colors.slate.800)]" />
|
||||
<div className="relative overflow-hidden rounded-xl p-6">
|
||||
<img src={feature.icon} alt="" className="h-24 w-auto" />
|
||||
<img src={feature.icon} alt={feature.title} className="h-24 w-auto" />
|
||||
<h2 className="mt-4 font-display text-base text-primary dark:text-primary-dark">
|
||||
<span className="absolute -inset-px rounded-xl" />
|
||||
{feature.title}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useRef } from 'react';
|
||||
import ButtonLink from './ButtonLink';
|
||||
import NewsletterForm from './NewsletterForm';
|
||||
import Image from 'next/image';
|
||||
import DatahubExampleImg from "@/public/images/showcases/datahub.png"
|
||||
import DatahubExampleImg from '@/public/images/showcases/datahub.webp';
|
||||
|
||||
const codeLanguage = 'javascript';
|
||||
const code = `export default {
|
||||
@@ -41,7 +41,7 @@ export function Hero() {
|
||||
{/* Commented code on line 37, 39 and 113 will reenable the two columns hero */}
|
||||
<div className="mx-auto grid max-w-2xl grid-cols-1 gap-y-16 gap-x-8 px-4 lg:max-w-8xl lg:grid-cols-2 lg:px-8 xl:gap-x-16 xl:px-12">
|
||||
<div className="relative mb-10 lg:mb-0 md:text-center lg:text-left">
|
||||
<div role="heading">
|
||||
<div>
|
||||
<h1 className="inline bg-gradient-to-r from-blue-500 via-blue-300 to-blue-500 bg-clip-text text-5xl tracking-tight text-transparent">
|
||||
The JavaScript framework for data portals
|
||||
</h1>
|
||||
@@ -72,9 +72,11 @@ export function Hero() {
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<img
|
||||
<Image
|
||||
src="/images/datopian_logo.png"
|
||||
alt="Datopian"
|
||||
width={24}
|
||||
height={20}
|
||||
className="mx-2 mb-1 h-6 inline bg-black rounded-full"
|
||||
/>
|
||||
<span>Datopian</span>
|
||||
@@ -85,7 +87,12 @@ export function Hero() {
|
||||
<div className="relative rounded-2xl bg-[#0A101F]/80 ring-1 ring-white/10 backdrop-blur">
|
||||
<div className="absolute -top-px left-20 right-11 h-px bg-gradient-to-r from-sky-300/0 via-sky-300/70 to-sky-300/0" />
|
||||
<div className="absolute -bottom-px left-11 right-20 h-px bg-gradient-to-r from-blue-400/0 via-blue-400 to-blue-400/0" />
|
||||
<Image src={DatahubExampleImg} alt="opendata.datahub.io" />
|
||||
<Image
|
||||
height={400}
|
||||
width={600}
|
||||
src={DatahubExampleImg}
|
||||
alt="opendata.datahub.io"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
65
site/components/JSONLD.tsx
Normal file
65
site/components/JSONLD.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
import { ArticleJsonLd } from 'next-seo';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function JSONLD({
|
||||
meta,
|
||||
source,
|
||||
}: {
|
||||
meta: any;
|
||||
source: string;
|
||||
}): JSX.Element {
|
||||
if (!source) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://portaljs.org';
|
||||
const pageUrl = `${baseUrl}/${meta.urlPath}`;
|
||||
|
||||
const imageMatches = source.match(
|
||||
/(?<=src: ")(.*)\.((png)|(jpg)|(jpeg))(?=")/g
|
||||
);
|
||||
let images = [];
|
||||
if (imageMatches) {
|
||||
images = [...imageMatches];
|
||||
images = images.map((img) =>
|
||||
img.startsWith('http')
|
||||
? img
|
||||
: `${baseUrl}${img.startsWith('/') ? '' : '/'}${img}`
|
||||
);
|
||||
}
|
||||
|
||||
let Component: JSX.Element;
|
||||
|
||||
const isBlog: boolean =
|
||||
/^blog\/.*/.test(meta.urlPath) || meta.filetype === 'blog';
|
||||
const isDoc: boolean = /^((docs)|(howtos\/)|(guide\/)).*/.test(meta.urlPath);
|
||||
|
||||
if (isBlog) {
|
||||
Component = (
|
||||
<ArticleJsonLd
|
||||
type="BlogPosting"
|
||||
url={pageUrl}
|
||||
title={meta.title}
|
||||
datePublished={meta.date}
|
||||
dateModified={meta.date}
|
||||
authorName={meta.authors.length ? meta.authors[0].name : 'PortalJS'}
|
||||
description={meta.description}
|
||||
images={images}
|
||||
/>
|
||||
);
|
||||
} else if (isDoc) {
|
||||
Component = (
|
||||
<ArticleJsonLd
|
||||
url={pageUrl}
|
||||
title={meta.title}
|
||||
images={images}
|
||||
datePublished={meta.date}
|
||||
dateModified={meta.date}
|
||||
authorName={meta.authors.length ? meta.authors[0].name : 'PortalJS'}
|
||||
description={meta.description}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return Component;
|
||||
}
|
||||
@@ -54,12 +54,14 @@ function useTableOfContents(tableOfContents) {
|
||||
export default function Layout({
|
||||
children,
|
||||
title,
|
||||
description,
|
||||
tableOfContents = [],
|
||||
isHomePage = false,
|
||||
sidebarTree = [],
|
||||
}: {
|
||||
children;
|
||||
title?: string;
|
||||
description?: string;
|
||||
tableOfContents?;
|
||||
urlPath?: string;
|
||||
sidebarTree?: [];
|
||||
@@ -82,7 +84,7 @@ export default function Layout({
|
||||
|
||||
return (
|
||||
<>
|
||||
{title && <NextSeo title={title} />}
|
||||
{title && <NextSeo title={title} description={description} />}
|
||||
<Nav />
|
||||
<div className="mx-auto p-6 bg-background dark:bg-background-dark">
|
||||
{isHomePage && <Hero />}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import { MDXRemote } from 'next-mdx-remote';
|
||||
import { NextSeo } from 'next-seo';
|
||||
import layouts from 'layouts';
|
||||
import DocsPagination from './DocsPagination';
|
||||
import { NextSeo } from 'next-seo';
|
||||
import { Hero } from "@portaljs/core";
|
||||
|
||||
export default function MDXPage({ source, frontMatter }) {
|
||||
const Layout = ({ children }) => {
|
||||
const layoutName = frontMatter?.layout || 'default';
|
||||
const LayoutComponent = layouts[layoutName];
|
||||
const Layout = ({ children }) => {
|
||||
const layoutName = frontMatter?.layout || 'default';
|
||||
const LayoutComponent = layouts[layoutName];
|
||||
|
||||
return <LayoutComponent {...frontMatter}>{children}</LayoutComponent>;
|
||||
};
|
||||
return <LayoutComponent {...frontMatter}>{children}</LayoutComponent>;
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<MDXRemote {...source} components={{ DocsPagination, NextSeo }} />
|
||||
</Layout>
|
||||
);
|
||||
return (
|
||||
<Layout>
|
||||
<MDXRemote {...source} components={{ DocsPagination, NextSeo, Hero }} />
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export default function NavItem({ item }) {
|
||||
};
|
||||
|
||||
return (
|
||||
<Menu as="div" className="relative">
|
||||
<Menu as="div" role="menu" className="relative">
|
||||
<Menu.Item>
|
||||
{Object.prototype.hasOwnProperty.call(item, 'href') ? (
|
||||
<Link
|
||||
|
||||
@@ -3,10 +3,6 @@ import Script from 'next/script';
|
||||
export default function NewsletterForm() {
|
||||
return (
|
||||
<div>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://sibforms.com/forms/end-form/build/sib-styles.css"
|
||||
/>
|
||||
<div
|
||||
id="sib-form-container"
|
||||
className="mt-8 sm:mx-auto sm:text-center lg:text-left lg:mx-0"
|
||||
@@ -119,6 +115,7 @@ export default function NewsletterForm() {
|
||||
}}
|
||||
/>
|
||||
<Script
|
||||
strategy="worker"
|
||||
id="newsletter-submit-form"
|
||||
src="https://sibforms.com/forms/end-form/build/main.js"
|
||||
/>
|
||||
|
||||
@@ -5,26 +5,26 @@ const items = [
|
||||
{
|
||||
title: 'Open Data Northern Ireland',
|
||||
href: 'https://www.opendatani.gov.uk/',
|
||||
image: '/images/showcases/odni.png',
|
||||
image: '/images/showcases/odni.webp',
|
||||
description: 'Government Open Data Portal',
|
||||
},
|
||||
{
|
||||
title: 'Birmingham City Observatory',
|
||||
href: 'https://www.cityobservatory.birmingham.gov.uk/',
|
||||
image: '/images/showcases/birmingham.png',
|
||||
image: '/images/showcases/birmingham.webp',
|
||||
description: 'Government Open Data Portal',
|
||||
},
|
||||
{
|
||||
title: 'UAE Open Data',
|
||||
href: 'https://opendata.fcsc.gov.ae/',
|
||||
image: '/images/showcases/uae.png',
|
||||
image: '/images/showcases/uae.webp',
|
||||
description: 'Government Open Data Portal',
|
||||
sourceUrl: 'https://github.com/FCSCOpendata/frontend',
|
||||
},
|
||||
{
|
||||
title: 'Datahub Open Data',
|
||||
href: 'https://opendata.datahub.io/',
|
||||
image: '/images/showcases/datahub.png',
|
||||
image: '/images/showcases/datahub.webp',
|
||||
description: 'Demo Data Portal by DataHub',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { defaultConfig } from "@flowershow/core";
|
||||
import { defaultConfig } from "@portaljs/core";
|
||||
import userConfig from "../content/config";
|
||||
|
||||
export const siteConfig: any = {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user