Skip to content

Commit 289a92b

Browse files
committed
[add] Lark Wiki pages
[optimize] update Upstream packages
1 parent 566646d commit 289a92b

7 files changed

Lines changed: 408 additions & 270 deletions

File tree

.env

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
NEXT_PUBLIC_SITE_NAME = 开源市集
22
NEXT_PUBLIC_SITE_SUMMARY =
33
NEXT_PUBLIC_LOGO = https://github.com/Open-Source-Bazaar.png
4+
5+
NEXT_PUBLIC_LARK_API_HOST = https://open.feishu.cn/open-apis/
6+
NEXT_PUBLIC_LARK_APP_ID = cli_a8094a652022900d
7+
NEXT_PUBLIC_LARK_WIKI_URL = https://open-source-bazaar.feishu.cn/wiki/space/7052192153363054596

models/Wiki.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,26 @@
11
import { Content, ContentModel } from 'mobx-github';
2+
import { DocumentModel, WikiNodeModel } from 'mobx-lark';
23
import { DataObject } from 'mobx-restful';
34

5+
import { lark } from '../pages/api/Lark/core';
46
import './Base';
7+
import { LarkWikiDomain, LarkWikiId } from './configuration';
58

69
export interface XContent extends Content {
710
meta?: DataObject;
811
children?: XContent[];
912
}
1013

1114
export const policyContentStore = new ContentModel('fpsig', 'open-source-policy');
15+
16+
export class MyWikiNodeModel extends WikiNodeModel {
17+
client = lark.client;
18+
}
19+
20+
export const wikiStore = new MyWikiNodeModel(LarkWikiDomain, LarkWikiId);
21+
22+
export class MyDocumentModel extends DocumentModel {
23+
client = lark.client;
24+
}
25+
26+
export const documentStore = new MyDocumentModel(LarkWikiDomain);

models/configuration.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,7 @@ export const LarkAppMeta = {
2727
id: process.env.NEXT_PUBLIC_LARK_APP_ID!,
2828
secret: process.env.LARK_APP_SECRET!,
2929
};
30+
const { hostname, pathname } = new URL(process.env.NEXT_PUBLIC_LARK_WIKI_URL!);
31+
32+
export const LarkWikiDomain = hostname;
33+
export const LarkWikiId = pathname.split('/').pop()!;

package.json

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"private": true,
66
"scripts": {
77
"prepare": "husky",
8+
"install": "pnpx git-utility download https://github.com/Open-Source-Bazaar/key-vault main Open-Source-Bazaar.github.io || true",
89
"dev": "next dev",
910
"build": "next build",
1011
"start": "next start",
@@ -13,8 +14,8 @@
1314
},
1415
"dependencies": {
1516
"@koa/router": "^14.0.0",
16-
"@mdx-js/loader": "^3.1.0",
17-
"@mdx-js/react": "^3.1.0",
17+
"@mdx-js/loader": "^3.1.1",
18+
"@mdx-js/react": "^3.1.1",
1819
"@next/mdx": "^15.5.2",
1920
"core-js": "^3.45.1",
2021
"file-type": "^21.0.0",
@@ -27,7 +28,7 @@
2728
"mobx": "^6.13.7",
2829
"mobx-github": "^0.4.0",
2930
"mobx-i18n": "^0.7.1",
30-
"mobx-lark": "^2.4.0",
31+
"mobx-lark": "^2.4.1",
3132
"mobx-react": "^9.2.0",
3233
"mobx-react-helper": "^0.5.1",
3334
"mobx-restful": "^2.1.0",
@@ -47,11 +48,11 @@
4748
"@babel/plugin-proposal-decorators": "^7.28.0",
4849
"@babel/plugin-transform-typescript": "^7.28.0",
4950
"@babel/preset-react": "^7.27.1",
50-
"@cspell/eslint-plugin": "^9.2.0",
51+
"@cspell/eslint-plugin": "^9.2.1",
5152
"@eslint/js": "^9.34.0",
5253
"@next/eslint-plugin-next": "^15.5.2",
5354
"@softonus/prettier-plugin-duplicate-remover": "^1.1.2",
54-
"@stylistic/eslint-plugin": "^5.2.3",
55+
"@stylistic/eslint-plugin": "^5.3.1",
5556
"@types/eslint-config-prettier": "^6.11.3",
5657
"@types/koa": "^3.0.0",
5758
"@types/koa__router": "^12.0.4",
@@ -69,13 +70,13 @@
6970
"jiti": "^2.5.1",
7071
"less": "^4.4.1",
7172
"less-loader": "^12.3.0",
72-
"lint-staged": "^16.1.5",
73+
"lint-staged": "^16.1.6",
7374
"next-with-less": "^3.0.1",
7475
"prettier": "^3.6.2",
7576
"prettier-plugin-css-order": "^2.1.2",
7677
"sass": "^1.91.0",
7778
"typescript": "~5.9.2",
78-
"typescript-eslint": "^8.41.0"
79+
"typescript-eslint": "^8.42.0"
7980
},
8081
"resolutions": {
8182
"next": "$next"

pages/wiki/[node_token].tsx

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { Block, renderBlocks, WikiNode } from 'mobx-lark';
2+
import { GetStaticPaths, GetStaticProps } from 'next';
3+
import { FC } from 'react';
4+
import { Container } from 'react-bootstrap';
5+
import { Minute, Second } from 'web-utility';
6+
7+
import { PageHead } from '../../components/Layout/PageHead';
8+
import { documentStore, wikiStore } from '../../models/Wiki';
9+
import { lark } from '../api/Lark/core';
10+
11+
export const getStaticPaths: GetStaticPaths = async () => {
12+
await lark.getAccessToken();
13+
14+
const nodes = await wikiStore.getAll();
15+
16+
return {
17+
paths: nodes.map(({ node_token }) => ({ params: { node_token } })),
18+
fallback: 'blocking',
19+
};
20+
};
21+
22+
export const getStaticProps: GetStaticProps = async ({ params }) => {
23+
await lark.getAccessToken();
24+
25+
const node = await wikiStore.getOne(params!.node_token as string);
26+
27+
if (node?.obj_type !== 'docx') return { notFound: true };
28+
29+
try {
30+
const blocks = await documentStore.getOneBlocks(
31+
node.obj_token,
32+
token => `/api/Lark/file/${token}/placeholder`,
33+
);
34+
35+
return { props: { node, blocks } };
36+
} catch (error) {
37+
console.error(error);
38+
39+
return { notFound: true, revalidate: Minute / Second };
40+
}
41+
};
42+
43+
interface WikiDocumentPageProps {
44+
node: WikiNode;
45+
blocks: Block<any, any, any>[];
46+
}
47+
48+
const WikiDocumentPage: FC<WikiDocumentPageProps> = ({ node, blocks }) => (
49+
<Container>
50+
<PageHead title={node.title} />
51+
52+
{renderBlocks(blocks)}
53+
</Container>
54+
);
55+
56+
export default WikiDocumentPage;

pages/wiki/index.tsx

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { WikiNode } from 'mobx-lark';
2+
import { observer } from 'mobx-react';
3+
import { GetStaticProps } from 'next';
4+
import { FC, useContext } from 'react';
5+
import { Container } from 'react-bootstrap';
6+
import { treeFrom } from 'web-utility';
7+
8+
import { PageHead } from '../../components/Layout/PageHead';
9+
import { I18nContext } from '../../models/Translation';
10+
import { wikiStore } from '../../models/Wiki';
11+
import { lark } from '../api/Lark/core';
12+
13+
export const getStaticProps: GetStaticProps = async () => {
14+
await lark.getAccessToken();
15+
16+
const nodes = await wikiStore.getAll();
17+
18+
return { props: { nodes } };
19+
};
20+
21+
interface XWikiNode extends WikiNode {
22+
// eslint-disable-next-line no-restricted-syntax
23+
children?: XWikiNode[];
24+
}
25+
26+
const renderTree = (children?: XWikiNode[]) =>
27+
children && (
28+
<ol>
29+
{children.map(({ node_token, title, children }) => (
30+
<li key={node_token}>
31+
<a href={`/wiki/${node_token}`}>{title}</a>
32+
33+
{renderTree(children)}
34+
</li>
35+
))}
36+
</ol>
37+
);
38+
39+
const WikiIndexPage: FC<{ nodes: XWikiNode[] }> = observer(({ nodes }) => {
40+
const { t } = useContext(I18nContext);
41+
42+
return (
43+
<Container>
44+
<PageHead title={t('wiki')} />
45+
46+
<h1>{t('wiki')}</h1>
47+
48+
{renderTree(treeFrom(nodes, 'node_token', 'parent_node_token', 'children'))}
49+
</Container>
50+
);
51+
});
52+
53+
export default WikiIndexPage;

0 commit comments

Comments
 (0)