@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.
- package/.eslintrc.json +11 -0
- package/.prettierrc.json +7 -0
- package/LICENSE +21 -0
- package/README.md +7 -0
- package/dist/index.css +158 -0
- package/dist/index.d.ts +95 -0
- package/dist/index.js +335 -0
- package/dist/index.mjs +302 -0
- package/dts.mjs +8 -0
- package/esbuild.mjs +36 -0
- package/next.config.ts +15 -0
- package/package.json +83 -0
- package/public/leaf.png +0 -0
- package/public/leaf.svg +1 -0
- package/src/app/Footer.tsx +14 -0
- package/src/app/Header.tsx +14 -0
- package/src/app/blog/[[...id]]/page.tsx +8 -0
- package/src/app/docs/[[...id]]/page.tsx +8 -0
- package/src/app/layout.tsx +41 -0
- package/src/app/page.tsx +25 -0
- package/src/assets/leaf.svg +1 -0
- package/src/components/Footer.module.css +0 -0
- package/src/components/Footer.tsx +1 -0
- package/src/components/Header.module.css +0 -0
- package/src/components/Header.tsx +0 -0
- package/src/components/Markdown.tsx +21 -0
- package/src/components/Shiso.tsx +19 -0
- package/src/components/blog/Blog.module.css +0 -0
- package/src/components/blog/Blog.tsx +21 -0
- package/src/components/docs/Callout.module.css +6 -0
- package/src/components/docs/Callout.tsx +18 -0
- package/src/components/docs/CodeBlock.module.css +37 -0
- package/src/components/docs/CodeBlock.tsx +30 -0
- package/src/components/docs/ContentArea.module.css +63 -0
- package/src/components/docs/ContentArea.tsx +27 -0
- package/src/components/docs/Docs.tsx +50 -0
- package/src/components/docs/Note.tsx +5 -0
- package/src/components/docs/PageLinks.module.css +49 -0
- package/src/components/docs/PageLinks.tsx +49 -0
- package/src/components/docs/SideNav.module.css +32 -0
- package/src/components/docs/SideNav.tsx +46 -0
- package/src/components/docs/TopNav.tsx +25 -0
- package/src/components/icons/Leaf.tsx +15 -0
- package/src/components/icons/index.ts +1 -0
- package/src/components/index.ts +8 -0
- package/src/content/blog/index.mdx +5 -0
- package/src/content/docs/components/index.mdx +1 -0
- package/src/content/docs/components.mdx +5 -0
- package/src/content/docs/configuration.mdx +81 -0
- package/src/content/docs/index.mdx +11 -0
- package/src/content/docs/installation.mdx +38 -0
- package/src/content/docs/writing-content.mdx +95 -0
- package/src/declarations.d.ts +3 -0
- package/src/index.ts +5 -0
- package/src/lib/content.ts +61 -0
- package/src/lib/next.tsx +46 -0
- package/src/lib/types.ts +10 -0
- package/src/shiso.config.json +59 -0
- package/tsconfig.build.json +24 -0
- 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
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
|
+
}
|
package/public/leaf.png
ADDED
|
Binary file
|
package/public/leaf.svg
ADDED
|
@@ -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,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
|
+
}
|
package/src/app/page.tsx
ADDED
|
@@ -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
|
+
}
|