@umami/shiso 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/.eslintrc.json +11 -0
  2. package/.prettierrc.json +7 -0
  3. package/LICENSE +21 -0
  4. package/README.md +7 -0
  5. package/dist/index.css +158 -0
  6. package/dist/index.d.ts +95 -0
  7. package/dist/index.js +335 -0
  8. package/dist/index.mjs +302 -0
  9. package/dts.mjs +8 -0
  10. package/esbuild.mjs +36 -0
  11. package/next.config.ts +15 -0
  12. package/package.json +83 -0
  13. package/public/leaf.png +0 -0
  14. package/public/leaf.svg +1 -0
  15. package/src/app/Footer.tsx +14 -0
  16. package/src/app/Header.tsx +14 -0
  17. package/src/app/blog/[[...id]]/page.tsx +8 -0
  18. package/src/app/docs/[[...id]]/page.tsx +8 -0
  19. package/src/app/layout.tsx +41 -0
  20. package/src/app/page.tsx +25 -0
  21. package/src/assets/leaf.svg +1 -0
  22. package/src/components/Footer.module.css +0 -0
  23. package/src/components/Footer.tsx +1 -0
  24. package/src/components/Header.module.css +0 -0
  25. package/src/components/Header.tsx +0 -0
  26. package/src/components/Markdown.tsx +21 -0
  27. package/src/components/Shiso.tsx +19 -0
  28. package/src/components/blog/Blog.module.css +0 -0
  29. package/src/components/blog/Blog.tsx +21 -0
  30. package/src/components/docs/Callout.module.css +6 -0
  31. package/src/components/docs/Callout.tsx +18 -0
  32. package/src/components/docs/CodeBlock.module.css +37 -0
  33. package/src/components/docs/CodeBlock.tsx +30 -0
  34. package/src/components/docs/ContentArea.module.css +63 -0
  35. package/src/components/docs/ContentArea.tsx +27 -0
  36. package/src/components/docs/Docs.tsx +50 -0
  37. package/src/components/docs/Note.tsx +5 -0
  38. package/src/components/docs/PageLinks.module.css +49 -0
  39. package/src/components/docs/PageLinks.tsx +49 -0
  40. package/src/components/docs/SideNav.module.css +32 -0
  41. package/src/components/docs/SideNav.tsx +46 -0
  42. package/src/components/docs/TopNav.tsx +25 -0
  43. package/src/components/icons/Leaf.tsx +15 -0
  44. package/src/components/icons/index.ts +1 -0
  45. package/src/components/index.ts +8 -0
  46. package/src/content/blog/index.mdx +5 -0
  47. package/src/content/docs/components/index.mdx +1 -0
  48. package/src/content/docs/components.mdx +5 -0
  49. package/src/content/docs/configuration.mdx +81 -0
  50. package/src/content/docs/index.mdx +11 -0
  51. package/src/content/docs/installation.mdx +38 -0
  52. package/src/content/docs/writing-content.mdx +95 -0
  53. package/src/declarations.d.ts +3 -0
  54. package/src/index.ts +5 -0
  55. package/src/lib/content.ts +61 -0
  56. package/src/lib/next.tsx +46 -0
  57. package/src/lib/types.ts +10 -0
  58. package/src/shiso.config.json +59 -0
  59. package/tsconfig.build.json +24 -0
  60. package/tsconfig.json +41 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,302 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
7
+ // css-modules:E:\dev\umami-shiso\src\components\blog\Blog.module.css
8
+ var Blog_default = {};
9
+
10
+ // src/components/Markdown.tsx
11
+ import { MDXRemote } from "next-mdx-remote/rsc";
12
+ import remarkGfm from "remark-gfm";
13
+ import rehypeHighlight from "rehype-highlight";
14
+ import Link from "next/link";
15
+
16
+ // src/components/docs/CodeBlock.tsx
17
+ import { useState, useRef } from "react";
18
+ import { Icon, Icons } from "@umami/react-zen";
19
+
20
+ // css-modules:E:\dev\umami-shiso\src\components\docs\CodeBlock.module.css
21
+ var CodeBlock_default = { "container": "CodeBlock_container__ZWQ3M", "button": "CodeBlock_button__YzlkO", "copy": "CodeBlock_copy__MGRjZ", "check": "CodeBlock_check__YTZlN" };
22
+
23
+ // src/components/docs/CodeBlock.tsx
24
+ import { jsx, jsxs } from "react/jsx-runtime";
25
+ function CodeBlock(props) {
26
+ const textInput = useRef(null);
27
+ const [copied, setCopied] = useState(false);
28
+ const handleCopy = () => {
29
+ setCopied(true);
30
+ navigator?.clipboard?.writeText(textInput?.current?.textContent);
31
+ setTimeout(() => {
32
+ setCopied(false);
33
+ }, 1e3);
34
+ };
35
+ return /* @__PURE__ */ jsxs("pre", { ref: textInput, className: CodeBlock_default.container, children: [
36
+ props.children,
37
+ /* @__PURE__ */ jsx("button", { "aria-label": "Copy code", className: CodeBlock_default.button, onClick: handleCopy, children: /* @__PURE__ */ jsx(Icon, { size: "sm", className: copied ? CodeBlock_default.check : CodeBlock_default.copy, children: copied ? /* @__PURE__ */ jsx(Icons.Check, {}) : /* @__PURE__ */ jsx(Icons.Copy, {}) }) })
38
+ ] });
39
+ }
40
+
41
+ // src/components/Markdown.tsx
42
+ import { jsx as jsx2 } from "react/jsx-runtime";
43
+ var options = {
44
+ mdxOptions: {
45
+ remarkPlugins: [remarkGfm],
46
+ rehypePlugins: [rehypeHighlight]
47
+ }
48
+ };
49
+ var components = {
50
+ a: (props) => /* @__PURE__ */ jsx2(Link, { ...props }),
51
+ pre: CodeBlock
52
+ };
53
+ function Markdown({ children }) {
54
+ return /* @__PURE__ */ jsx2(MDXRemote, { source: children, components, options });
55
+ }
56
+
57
+ // src/components/blog/Blog.tsx
58
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
59
+ function Blog({ content }) {
60
+ return /* @__PURE__ */ jsx3("div", { className: Blog_default.blog, children: /* @__PURE__ */ jsx3("div", { className: Blog_default.main, children: /* @__PURE__ */ jsxs2("div", { className: Blog_default.content, children: [
61
+ /* @__PURE__ */ jsx3("h1", { children: content?.meta?.title }),
62
+ /* @__PURE__ */ jsx3("p", { className: Blog_default.description, children: content?.meta?.description }),
63
+ /* @__PURE__ */ jsx3(Markdown, { children: content?.body })
64
+ ] }) }) });
65
+ }
66
+
67
+ // src/components/docs/Docs.tsx
68
+ import { Grid, Box as Box3, Heading as Heading2 } from "@umami/react-zen";
69
+
70
+ // src/components/docs/PageLinks.tsx
71
+ import { useEffect, useState as useState2 } from "react";
72
+ import { Column, Text } from "@umami/react-zen";
73
+ import classNames from "classnames";
74
+
75
+ // css-modules:E:\dev\umami-shiso\src\components\docs\PageLinks.module.css
76
+ var PageLinks_default = { "title": "PageLinks_title__NDFiN", "links": "PageLinks_links__NDRmO", "indent-1": "PageLinks_indent-1__ODFiY", "indent-2": "PageLinks_indent-2__OTFkY", "indent-3": "PageLinks_indent-3__ZGM3O", "indent-4": "PageLinks_indent-4__Y2U0M", "indent-5": "PageLinks_indent-5__MzUwM", "indent-6": "PageLinks_indent-6__ZTQ4M", "selected": "PageLinks_selected__MDVlN" };
77
+
78
+ // src/components/docs/PageLinks.tsx
79
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
80
+ function PageLinks({ items, offset = 0 }) {
81
+ const [hash, setHash] = useState2(items?.[0]?.id);
82
+ useEffect(() => {
83
+ const callback = () => {
84
+ const x = [...items].reverse().find(({ id }) => {
85
+ const rect = document.getElementById(id)?.getBoundingClientRect();
86
+ return rect && rect.top <= offset;
87
+ });
88
+ if (x) setHash(x.id);
89
+ };
90
+ window.addEventListener("scroll", callback, false);
91
+ return () => {
92
+ window.removeEventListener("scroll", callback, false);
93
+ };
94
+ }, []);
95
+ if (!items?.length) {
96
+ return null;
97
+ }
98
+ return /* @__PURE__ */ jsxs3(Column, { gap: "3", minWidth: "240px", className: PageLinks_default.links, children: [
99
+ /* @__PURE__ */ jsx4(Text, { size: "2", weight: "bold", children: "On this page" }),
100
+ items.map(({ name, id, size }) => {
101
+ return /* @__PURE__ */ jsx4(
102
+ "a",
103
+ {
104
+ href: `#${id}`,
105
+ className: classNames(PageLinks_default[`indent-${size}`], { [PageLinks_default.selected]: hash === id }),
106
+ children: name
107
+ },
108
+ id
109
+ );
110
+ })
111
+ ] });
112
+ }
113
+
114
+ // src/components/docs/SideNav.tsx
115
+ import { Box, List, ListItem, ListSection } from "@umami/react-zen";
116
+ import classNames2 from "classnames";
117
+ import { usePathname } from "next/navigation";
118
+ import Link2 from "next/link";
119
+
120
+ // css-modules:E:\dev\umami-shiso\src\components\docs\SideNav.module.css
121
+ var SideNav_default = { "nav": "SideNav_nav__NmRlZ", "item": "SideNav_item__ZmExN", "selected": "SideNav_selected__Y2U0Y", "items": "SideNav_items__MWIxZ" };
122
+
123
+ // src/components/docs/SideNav.tsx
124
+ import { jsx as jsx5 } from "react/jsx-runtime";
125
+ function SideNav({ tabs, navigation }) {
126
+ const pathname = usePathname();
127
+ const tab = tabs.find(({ url, id }) => id !== "docs" ? pathname.startsWith(url) : false);
128
+ const menu = navigation[tab?.id || "docs"];
129
+ return /* @__PURE__ */ jsx5(Box, { className: SideNav_default.nav, children: /* @__PURE__ */ jsx5(List, { items: navigation, children: menu.map(({ group, pages }) => {
130
+ return /* @__PURE__ */ jsx5(ListSection, { title: group, className: SideNav_default.items, children: pages.map(({ label: text, url }, index) => {
131
+ return /* @__PURE__ */ jsx5(
132
+ ListItem,
133
+ {
134
+ className: classNames2(SideNav_default.item, {
135
+ [SideNav_default.selected]: url === pathname
136
+ }),
137
+ children: /* @__PURE__ */ jsx5(Link2, { href: url, prefetch: false, children: text })
138
+ },
139
+ index
140
+ );
141
+ }) }, group);
142
+ }) }) });
143
+ }
144
+
145
+ // src/components/docs/TopNav.tsx
146
+ import Link3 from "next/link";
147
+ import { usePathname as usePathname2 } from "next/navigation";
148
+ import { Tabs, TabList, Tab } from "@umami/react-zen";
149
+ import { jsx as jsx6 } from "react/jsx-runtime";
150
+ function TopNav({ tabs }) {
151
+ const pathname = usePathname2();
152
+ const tab = tabs.find(({ id, url }) => id !== "docs" ? pathname.startsWith(url) : false);
153
+ const selected = tab?.id || "docs";
154
+ return /* @__PURE__ */ jsx6(Tabs, { selectedKey: selected, children: /* @__PURE__ */ jsx6(TabList, { items: tabs, children: ({ id, label, url }) => {
155
+ return /* @__PURE__ */ jsx6(Tab, { id, children: /* @__PURE__ */ jsx6(Link3, { href: url, children: label }) });
156
+ } }) });
157
+ }
158
+
159
+ // src/components/docs/ContentArea.tsx
160
+ import { Heading, Box as Box2, Text as Text2 } from "@umami/react-zen";
161
+
162
+ // css-modules:E:\dev\umami-shiso\src\components\docs\ContentArea.module.css
163
+ var ContentArea_default = { "content": "ContentArea_content__YzBjN" };
164
+
165
+ // src/components/docs/ContentArea.tsx
166
+ import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
167
+ function ContentArea({ title, description, group, body }) {
168
+ return /* @__PURE__ */ jsxs4(Box2, { flexGrow: 1, children: [
169
+ /* @__PURE__ */ jsx7(Text2, { color: "primary", weight: "bold", children: group }),
170
+ /* @__PURE__ */ jsx7(Heading, { size: "8", as: "h1", children: title }),
171
+ /* @__PURE__ */ jsx7(Text2, { type: "muted", children: description }),
172
+ /* @__PURE__ */ jsx7(Box2, { className: ContentArea_default.content, children: /* @__PURE__ */ jsx7(Markdown, { children: body }) })
173
+ ] });
174
+ }
175
+
176
+ // src/components/docs/Docs.tsx
177
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
178
+ function Docs({ content, config }) {
179
+ if (!content) {
180
+ return /* @__PURE__ */ jsx8(Heading2, { size: "6", children: "Page not found" });
181
+ }
182
+ const { tabs, navigation } = config?.docs || {};
183
+ content.group = Object.keys(navigation).reduce((name, key) => {
184
+ if (!name) {
185
+ return navigation[key]?.find((section) => {
186
+ return section.pages.find(
187
+ (page) => page.url === `/docs/${content.id}` || page.url === `/docs` && content.id === "index"
188
+ );
189
+ })?.group;
190
+ }
191
+ return name;
192
+ }, null);
193
+ console.log({ config, tabs, content });
194
+ return /* @__PURE__ */ jsxs5(Box3, { flexGrow: "1", children: [
195
+ tabs && /* @__PURE__ */ jsx8(TopNav, { tabs }),
196
+ /* @__PURE__ */ jsxs5(Grid, { gap: "6", columns: "240px 1fr 240px", children: [
197
+ /* @__PURE__ */ jsx8(SideNav, { tabs, navigation }),
198
+ /* @__PURE__ */ jsx8(
199
+ ContentArea,
200
+ {
201
+ title: content?.meta?.title,
202
+ body: content?.body,
203
+ group: content?.group,
204
+ description: content?.meta?.description
205
+ }
206
+ ),
207
+ /* @__PURE__ */ jsx8(PageLinks, { items: content?.anchors, offset: 150 })
208
+ ] })
209
+ ] });
210
+ }
211
+
212
+ // src/lib/next.tsx
213
+ var next_exports = {};
214
+ __export(next_exports, {
215
+ default: () => next_default
216
+ });
217
+ import path2 from "node:path";
218
+
219
+ // src/lib/content.ts
220
+ import { cache } from "react";
221
+ import matter from "gray-matter";
222
+ import recursive from "recursive-readdir";
223
+ import { firstBy } from "thenby";
224
+ import fs from "node:fs/promises";
225
+ import path from "node:path";
226
+ var getFiles = cache(async (folder) => {
227
+ const dir = path.resolve(folder);
228
+ const files = await recursive(dir);
229
+ return Promise.all(
230
+ files.filter((file) => path.extname(file) === ".mdx").map(async (file) => {
231
+ const postContent = await fs.readFile(file, "utf8");
232
+ const { data, content } = matter(postContent);
233
+ const id = file.replace(".mdx", "").replace(dir, "").replace(/\\/g, "/").replace(/^\//, "");
234
+ const anchors = [];
235
+ const body = content.split("\n").map((line) => {
236
+ const match = line.match(/(#+)\s+(.*)/);
237
+ if (match) {
238
+ const [, num, name] = match;
239
+ const id2 = name.toLowerCase().replace(/\s+/g, "-");
240
+ const size = num.length;
241
+ anchors.push({ name, id: id2, size });
242
+ return `<h${size} id="${id2}">${name.replace(/\{|\}/g, "")}</h${size}>`;
243
+ }
244
+ return line;
245
+ }).join("\n");
246
+ return {
247
+ meta: data,
248
+ id,
249
+ body,
250
+ anchors
251
+ };
252
+ })
253
+ ).then((posts) => posts.sort(firstBy("date", "desc")));
254
+ });
255
+ async function getFile(id, folder) {
256
+ const files = await getFiles(folder);
257
+ return files.find((file) => file?.id === id);
258
+ }
259
+ async function getContent(params, folder) {
260
+ const { id = [] } = params;
261
+ const name = id?.length ? id.join("/") : "index";
262
+ return getFile(name, folder);
263
+ }
264
+
265
+ // src/lib/next.tsx
266
+ import { jsx as jsx9 } from "react/jsx-runtime";
267
+ var DEFAULT_CONTENT_DIR = "./src/content";
268
+ var components2 = {
269
+ docs: Docs,
270
+ blog: Blog
271
+ };
272
+ var next_default = (config) => {
273
+ const { contentDir = DEFAULT_CONTENT_DIR } = config || {};
274
+ const getMetadata = ({ title }) => {
275
+ return async ({ params }) => {
276
+ const content = await getContent(await params, contentDir);
277
+ return {
278
+ title: {
279
+ absolute: `${content?.meta?.title} \u2013 ${title}`,
280
+ default: title
281
+ }
282
+ };
283
+ };
284
+ };
285
+ const renderPage = ({ type }) => {
286
+ const folder = path2.resolve(process.cwd(), contentDir, type);
287
+ return async ({ params }) => {
288
+ const content = await getContent(await params, folder);
289
+ const Component = components2[type];
290
+ return Component && /* @__PURE__ */ jsx9(Component, { content, config });
291
+ };
292
+ };
293
+ return {
294
+ getMetadata,
295
+ renderPage
296
+ };
297
+ };
298
+ export {
299
+ Blog,
300
+ Docs,
301
+ next_exports as next
302
+ };
package/dts.mjs ADDED
@@ -0,0 +1,8 @@
1
+ import dts from 'dts-bundle';
2
+ import path from 'node:path';
3
+
4
+ dts.bundle({
5
+ name: '@umami/shiso',
6
+ main: path.resolve('./types/components/index.d.ts'),
7
+ out: path.resolve('./dist/index.d.ts'),
8
+ });
package/esbuild.mjs ADDED
@@ -0,0 +1,36 @@
1
+ import esbuild from 'esbuild';
2
+ import cssModules from '@umami/esbuild-plugin-css-modules';
3
+ import pkg from './package.json' with { type: 'json' };
4
+
5
+ const { dependencies } = pkg;
6
+
7
+ const config = {
8
+ entryPoints: ['src/index.ts'],
9
+ bundle: true,
10
+ external: Object.keys(dependencies),
11
+ jsx: 'automatic',
12
+ platform: 'node',
13
+ plugins: [cssModules()],
14
+ };
15
+
16
+ esbuild
17
+ .build({
18
+ ...config,
19
+ outfile: 'dist/index.js',
20
+ format: 'cjs',
21
+ })
22
+ .catch(e => {
23
+ console.error(e);
24
+ process.exit(1);
25
+ });
26
+
27
+ esbuild
28
+ .build({
29
+ ...config,
30
+ outfile: 'dist/index.mjs',
31
+ format: 'esm',
32
+ })
33
+ .catch(e => {
34
+ console.error(e);
35
+ process.exit(1);
36
+ });
package/next.config.ts ADDED
@@ -0,0 +1,15 @@
1
+ import type { NextConfig } from 'next';
2
+
3
+ const nextConfig: NextConfig = {
4
+ pageExtensions: ['ts', 'tsx', 'js', 'jsx', 'md', 'mdx'],
5
+ reactStrictMode: false,
6
+ output: 'standalone',
7
+ eslint: {
8
+ ignoreDuringBuilds: true,
9
+ },
10
+ typescript: {
11
+ ignoreBuildErrors: true,
12
+ },
13
+ };
14
+
15
+ export default nextConfig;
package/package.json ADDED
@@ -0,0 +1,83 @@
1
+ {
2
+ "name": "@umami/shiso",
3
+ "version": "0.1.0",
4
+ "description": "A content layer for Next.js",
5
+ "homepage": "https://umami.is/shiso",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/umami-software/shiso.git"
9
+ },
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "main": "dist/index.js",
14
+ "module": "dist/index.mjs",
15
+ "types": "dist/index.d.ts",
16
+ "scripts": {
17
+ "dev": "next dev --port 3100",
18
+ "build": "next build",
19
+ "start": "next start",
20
+ "lint": "next lint",
21
+ "icons": "svgr ./src/assets --out-dir ./src/components/icons --typescript",
22
+ "types": "tsc -p tsconfig.build.json",
23
+ "esbuild": "node esbuild.mjs",
24
+ "dts": "node dts.mjs",
25
+ "bundle": "npm-run-all types dts esbuild"
26
+ },
27
+ "lint-staged": {
28
+ "**/*.{js,jsx,ts,tsx}": [
29
+ "prettier --write",
30
+ "eslint"
31
+ ],
32
+ "**/*.css": [
33
+ "stylelint --fix",
34
+ "prettier --write"
35
+ ],
36
+ "**/*.json": [
37
+ "prettier --write"
38
+ ]
39
+ },
40
+ "dependencies": {
41
+ "@mdx-js/loader": "^3.0.0",
42
+ "@mdx-js/react": "^3.0.0",
43
+ "@umami/react-zen": "^0.27.0",
44
+ "classnames": "^2.5.1",
45
+ "glob": "^10.3.10",
46
+ "gray-matter": "^4.0.3",
47
+ "highlight.js": "^11.11.0",
48
+ "next": "15.1.0",
49
+ "next-mdx-remote": "^5.0.0",
50
+ "react": "19.0.0",
51
+ "react-dom": "19.0.0",
52
+ "recursive-readdir": "^2.2.3",
53
+ "rehype-highlight": "^7.0.1",
54
+ "remark-gfm": "^4.0.0",
55
+ "thenby": "^1.3.4"
56
+ },
57
+ "devDependencies": {
58
+ "@svgr/cli": "^8.1.0",
59
+ "@types/css-modules": "^1.0.5",
60
+ "@types/mdx": "^2.0.11",
61
+ "@types/node": "^22.10.2",
62
+ "@types/react": "^19.0.2",
63
+ "@types/react-dom": "^19.0.2",
64
+ "@umami/esbuild-plugin-css-modules": "^0.4.0",
65
+ "dts-bundle": "^0.7.3",
66
+ "esbuild": "^0.24.0",
67
+ "esbuild-plugin-css-modules": "^0.3.0",
68
+ "eslint": "^8",
69
+ "eslint-config-next": "15.0.2",
70
+ "eslint-config-prettier": "^9.1.0",
71
+ "eslint-import-resolver-alias": "^1.1.2",
72
+ "eslint-plugin-import": "^2.29.1",
73
+ "eslint-plugin-prettier": "^5.1.3",
74
+ "husky": "^9.1.1",
75
+ "lint-staged": "^15.2.7",
76
+ "npm-run-all": "^4.1.5",
77
+ "prettier": "^3.2.5",
78
+ "stylelint": "^15.10.1",
79
+ "stylelint-config-prettier": "^9.0.5",
80
+ "stylelint-config-recommended": "^14.0.1",
81
+ "typescript": "^5"
82
+ }
83
+ }
Binary file
@@ -0,0 +1 @@
1
+ <svg id="Glyph_Icon" height="512" viewBox="0 0 64 64" width="512" xmlns="http://www.w3.org/2000/svg" data-name="Glyph Icon"><path d="m55.221 10.79c-.555-.242-1.182-.085-1.564.39-4.738 5.882-18.607 6.77-22.746 6.903-1.002.032-2.035.155-3.067.366-20.567 4.187-20.255 19.314-19.671 23.85.097.75.601 1.362 1.315 1.599.708.236 1.469.045 1.988-.492 2.403-2.49 7.671-6.969 15.952-8.985 3.422-.833 6.668-2.36 9.557-4.111-3.375 2.564-7.731 5.332-13.243 7.92-5.526 2.596-9.586 7.096-11.075 8.909-.339.413-.493.953-.423 1.483.072.536.368 1.023.812 1.338 1.414 1.004 3.099 1.813 5.006 2.408 2.053.638 4.168.954 6.286.954 4.28 0 8.564-1.287 12.329-3.782 14.464-9.588 18.439-31.031 19.312-37.373.082-.588-.227-1.141-.768-1.377z"/></svg>
@@ -0,0 +1,14 @@
1
+ import { Box, Text } from '@umami/react-zen';
2
+
3
+ export function Footer() {
4
+ return (
5
+ <Box as="footer" paddingY="8">
6
+ <Text align="center" as="div">
7
+ Built by{' '}
8
+ <a href="https://umami.is">
9
+ <strong>umami</strong>
10
+ </a>
11
+ </Text>
12
+ </Box>
13
+ );
14
+ }
@@ -0,0 +1,14 @@
1
+ import { Row, Text } from '@umami/react-zen';
2
+ import Link from 'next/link';
3
+
4
+ export function Header() {
5
+ return (
6
+ <Row paddingY="5" gap="5" alignItems="center">
7
+ <Text size="5" weight="bold" spacing="1" asChild>
8
+ <Link href="/">shiso</Link>
9
+ </Text>
10
+ <Link href="/docs">docs</Link>
11
+ <Link href="/blog">blog</Link>
12
+ </Row>
13
+ );
14
+ }
@@ -0,0 +1,8 @@
1
+ import shiso from '@/lib/next';
2
+ import config from '@/shiso.config.json';
3
+
4
+ const { getMetadata, renderPage } = shiso(config);
5
+
6
+ export const generateMetadata = getMetadata({ title: 'SHISO' });
7
+
8
+ export default renderPage({ type: 'blog' });
@@ -0,0 +1,8 @@
1
+ import shiso from '@/lib/next';
2
+ import config from '@/shiso.config.json';
3
+
4
+ const { getMetadata, renderPage } = shiso(config);
5
+
6
+ export const generateMetadata = getMetadata({ title: 'SHISO' });
7
+
8
+ export default renderPage({ type: 'docs' });
@@ -0,0 +1,41 @@
1
+ import { ReactNode, Suspense } from 'react';
2
+ import type { Metadata } from 'next';
3
+ import { Inter } from 'next/font/google';
4
+ import { Container, Column } from '@umami/react-zen';
5
+ import { Header } from './Header';
6
+ import { Footer } from './Footer';
7
+ import '@umami/react-zen/dist/styles.css';
8
+ import 'highlight.js/styles/github-dark.css';
9
+
10
+ const inter = Inter({ subsets: ['latin'] });
11
+
12
+ export const metadata: Metadata = {
13
+ title: 'Shiso',
14
+ description: 'MDX powered content',
15
+ };
16
+
17
+ export default function RootLayout({
18
+ children,
19
+ }: Readonly<{
20
+ children: ReactNode;
21
+ }>) {
22
+ return (
23
+ <html lang="en">
24
+ <head>
25
+ <title>shiso</title>
26
+ <link rel="icon" type="image/png" href="/leaf.png" />
27
+ </head>
28
+ <body className={inter.className}>
29
+ <Suspense>
30
+ <Container>
31
+ <Column height="100vh" className="ohhyeaaaaa">
32
+ <Header />
33
+ {children}
34
+ <Footer />
35
+ </Column>
36
+ </Container>
37
+ </Suspense>
38
+ </body>
39
+ </html>
40
+ );
41
+ }
@@ -0,0 +1,25 @@
1
+ import { Heading, Text, Row, Column, Icon, Button } from '@umami/react-zen';
2
+ import Link from 'next/link';
3
+ import Leaf from '@/components/icons/Leaf';
4
+
5
+ export default function Home() {
6
+ return (
7
+ <Column gap="3" style={{ margin: '0 auto' }} flexGrow={1}>
8
+ <Heading size="5">shiso</Heading>
9
+ <Icon size="lg">
10
+ <Leaf />
11
+ </Icon>
12
+ <Text as="p" type="muted">
13
+ Publish content using MDX.
14
+ </Text>
15
+ <Row gap="3">
16
+ <Button variant="primary" asChild>
17
+ <Link href="/docs">Get started</Link>
18
+ </Button>
19
+ <Button asChild>
20
+ <Link href="https://github.com/umami-software/shiso">View code</Link>
21
+ </Button>
22
+ </Row>
23
+ </Column>
24
+ );
25
+ }
@@ -0,0 +1 @@
1
+ <svg id="Glyph_Icon" height="512" viewBox="0 0 64 64" width="512" xmlns="http://www.w3.org/2000/svg" data-name="Glyph Icon"><path d="m55.221 10.79c-.555-.242-1.182-.085-1.564.39-4.738 5.882-18.607 6.77-22.746 6.903-1.002.032-2.035.155-3.067.366-20.567 4.187-20.255 19.314-19.671 23.85.097.75.601 1.362 1.315 1.599.708.236 1.469.045 1.988-.492 2.403-2.49 7.671-6.969 15.952-8.985 3.422-.833 6.668-2.36 9.557-4.111-3.375 2.564-7.731 5.332-13.243 7.92-5.526 2.596-9.586 7.096-11.075 8.909-.339.413-.493.953-.423 1.483.072.536.368 1.023.812 1.338 1.414 1.004 3.099 1.813 5.006 2.408 2.053.638 4.168.954 6.286.954 4.28 0 8.564-1.287 12.329-3.782 14.464-9.588 18.439-31.031 19.312-37.373.082-.588-.227-1.141-.768-1.377z"/></svg>
File without changes
@@ -0,0 +1 @@
1
+ export default function Footer() {}
File without changes
File without changes
@@ -0,0 +1,21 @@
1
+ import { MDXRemote } from 'next-mdx-remote/rsc';
2
+ import remarkGfm from 'remark-gfm';
3
+ import rehypeHighlight from 'rehype-highlight';
4
+ import Link, { LinkProps } from 'next/link';
5
+ import { CodeBlock } from '@/components/docs/CodeBlock';
6
+
7
+ const options = {
8
+ mdxOptions: {
9
+ remarkPlugins: [remarkGfm],
10
+ rehypePlugins: [rehypeHighlight],
11
+ },
12
+ };
13
+
14
+ const components = {
15
+ a: (props: any) => <Link {...(props as LinkProps)} />,
16
+ pre: CodeBlock,
17
+ };
18
+
19
+ export default function Markdown({ children }) {
20
+ return <MDXRemote source={children as any} components={components} options={options} />;
21
+ }
@@ -0,0 +1,19 @@
1
+ 'use client';
2
+ import { ReactNode, createContext } from 'react';
3
+
4
+ export interface ShisoConfig {
5
+ contentDir: string;
6
+ docs?: { [key: string]: any };
7
+ blog?: { [key: string]: any };
8
+ }
9
+
10
+ export interface ShisoProps {
11
+ config: ShisoConfig;
12
+ children: ReactNode;
13
+ }
14
+
15
+ export const ShisoContext = createContext({ config: {} as ShisoConfig });
16
+
17
+ export function Shiso({ config, children }: ShisoProps) {
18
+ return <ShisoContext.Provider value={{ config }}>{children}</ShisoContext.Provider>;
19
+ }
File without changes
@@ -0,0 +1,21 @@
1
+ import styles from './Blog.module.css';
2
+ import Markdown from '../Markdown';
3
+
4
+ export interface BlogProps {
5
+ content: any;
6
+ config: any;
7
+ }
8
+
9
+ export function Blog({ content }: BlogProps) {
10
+ return (
11
+ <div className={styles.blog}>
12
+ <div className={styles.main}>
13
+ <div className={styles.content}>
14
+ <h1>{content?.meta?.title}</h1>
15
+ <p className={styles.description}>{content?.meta?.description}</p>
16
+ <Markdown>{content?.body}</Markdown>
17
+ </div>
18
+ </div>
19
+ </div>
20
+ );
21
+ }
@@ -0,0 +1,6 @@
1
+ .callout {
2
+ display: flex;
3
+ align-items: center;
4
+ gap: 10px;
5
+ padding: 8px 16px;
6
+ }