diff --git a/docs/assets/config/themes.json b/docs/assets/config/themes.json new file mode 100644 index 0000000..eb8eeb3 --- /dev/null +++ b/docs/assets/config/themes.json @@ -0,0 +1,24 @@ +{ + "defaultItems": [ + { + "name": "fog", + "owner": "wonder-light", + "intr": "静态博客主题,不适合追求简洁的博主使用", + "secr": "https://github.com/user-attachments/assets/f6e63470-f264-441e-b59f-3534f193ea00", + "prev": "https://blog.nianian.cn", + "repo": "https://github.com/wonder-light/glidea-theme-fog", + "star": 1 + } + ], + "githubItems": [ + { + "name": "fog", + "owner": "wonder-light", + "intr": "静态博客主题,不适合追求简洁的博主使用", + "secr": "https://github.com/user-attachments/assets/f6e63470-f264-441e-b59f-3534f193ea00", + "prev": "https://blog.nianian.cn", + "repo": "https://github.com/wonder-light/glidea-theme-fog", + "star": 0 + } + ] +} \ No newline at end of file diff --git a/docs/assets/css/main.css b/docs/assets/css/main.css index 0a77876..10d5f27 100644 --- a/docs/assets/css/main.css +++ b/docs/assets/css/main.css @@ -1,7 +1,13 @@ +/* #ffd100 */ + :root { --app-name-img-width: 80px; } +.jc-center { + justify-content: center; +} + .p-big { font-size: 1.4rem; font-weight: 700; @@ -49,7 +55,7 @@ font-size: 1.05rem; letter-spacing: 0.1rem; margin: 0.5rem 1rem; - padding: 0.75em 2rem; + padding: 0.5em 1rem; text-decoration: none; transition: 0.15s; } @@ -65,6 +71,11 @@ opacity: 0.8; } +.a-button .icon, +.a-button-cover .icon { + color: currentColor; +} + /* 没有元素时隐藏侧边栏 */ .b-main-hide button.sidebar-toggle { display: none !important; @@ -135,6 +146,37 @@ a.app-name-link img { margin-right: 1rem; } -.theme-icon img{ +.theme-icon img { width: 1rem; } + +.left-segm { + display: flex; + align-items: center; + justify-content: flex-end; +} + +.left-segm .el-segmented { + --el-segmented-item-selected-color: var(--el-text-color-primary); + --el-segmented-item-selected-bg-color: var(--theme-color, #42b983); + --el-border-radius-base: 16px; +} + +.left-segm .el-segmented__item { + padding: 0.5rem 1rem; +} + +.theme-list { + display: flex; + flex-wrap: wrap; +} + +.theme-list .theme-card { + width: 100%; +} + +@media screen and (min-width: 768px) { + .theme-list .theme-card { + width: 50%; + } +} diff --git a/docs/assets/images/clothes-line.svg b/docs/assets/images/clothes-line.svg new file mode 100644 index 0000000..6faddde --- /dev/null +++ b/docs/assets/images/clothes-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/assets/images/right-arrow.svg b/docs/assets/images/right-arrow.svg new file mode 100644 index 0000000..085c1f8 --- /dev/null +++ b/docs/assets/images/right-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/assets/js/discussion.js b/docs/assets/js/discussion.js new file mode 100644 index 0000000..3f64901 --- /dev/null +++ b/docs/assets/js/discussion.js @@ -0,0 +1,3 @@ +const { execDiscussion } = require("./update"); + +execDiscussion(); \ No newline at end of file diff --git a/docs/assets/js/main.js b/docs/assets/js/main.js index 5608932..84337ea 100644 --- a/docs/assets/js/main.js +++ b/docs/assets/js/main.js @@ -3,9 +3,9 @@ const themeCard = { template: `
- +
-
{{name}}{{foo}}
+
{{name}}
预览 @@ -25,7 +25,64 @@ const themeCard = { repo: String, // 仓库地址 }, data() { - return {} + return {}; + }, +}; + +// 主题列表 +const themeList = { + template: ` +
+ +
+ +
+
+ +
+
+ +
+
+
+ {{ loadTip }} +
+
+
+ `, + inject: ["defaultItems", "githubItems"], + props: { + label: String, + shared: String, + }, + data() { + return { + currentOption: this.label, + options: [this.label, "Github"], + hasMoreData: false, + }; + }, + computed: { + isGithub() { + return this.currentOption == "Github"; + }, + getItems() { + return this.isGithub ? this.githubItems : this.defaultItems; + }, + }, + created() { + fetch("/assets/config/themes.json") + .then((response) => response.json()) + .then((data) => { + this.githubItems = data.githubItems; + this.defaultItems = data.defaultItems; + }); }, }; @@ -81,12 +138,28 @@ window.$docsify = { // vue 组件 vueComponents: { "theme-card": themeCard, + "theme-list": themeList, + ElSegmented: ElementPlus.ElSegmented, + ElEmpty: ElementPlus.ElEmpty, }, // vue 全局选项 vueGlobalOptions: { data() { return { - count: 0, + defaultItems: [], + githubItems: [], + }; + }, + provide() { + return { + defaultItems: Vue.computed({ + get: () => this.defaultItems, + set: (value) => (this.defaultItems = value), + }), + githubItems: Vue.computed({ + get: () => this.githubItems, + set: (value) => (this.githubItems = value), + }), }; }, }, diff --git a/docs/assets/js/update.js b/docs/assets/js/update.js new file mode 100644 index 0000000..a809fab --- /dev/null +++ b/docs/assets/js/update.js @@ -0,0 +1,220 @@ +// 在 node.js 执行 +const fs = require("fs"); +const path = require("path"); + +const configPath = path.normalize(path.join(__dirname, "../config/themes.json")); +// Github 令牌, 减缓 Github 的限速限制 +const auth = ""; + +// 配置 +let config = JSON.parse(fs.readFileSync(configPath, { encoding: "utf-8" })); +if (!config) config = {}; + +function sleep(delaytime = 1000) { + return new Promise((resolve) => setTimeout(resolve, delaytime)); +} + +/** + * 更新主题的函数 + * @param {string} query 查询 + * @param {string} auth 授权 + * @param {(result: any) => ({totalCount: number, pageInfo: object, nodes: []})} format 返回格式化的数据 + * @param {(data: any) => Promise<{name: string, owner: string, intr: string, secr: string, prev: string, repo: string}|null>} handle 处理数据 + * @param {string|null|undefined} startCursor + * @returns {Promise} + */ +async function updateTheme(query, auth, format, handle, startCursor) { + let myHeaders = new Headers(); + myHeaders.append("Authorization", `Bearer ${auth}`); + myHeaders.append("Content-Type", "application/json"); + + let graphql = JSON.stringify({ + query: query, + variables: { + startCursor: !startCursor ? "" : startCursor, + }, + }); + + let requestOptions = { + method: "POST", + headers: myHeaders, + body: graphql, + }; + + let items = []; + + // 获取数据 + let data = await fetch("https://api.github.com/graphql", requestOptions) + .then((response) => response.json()) + .then((result) => format(result)) + .catch((error) => ({})); + + // 没有则返回 + if (!data.nodes?.length) { + return items; + } + + // 添加 + let nodes = []; + for (const item of data.nodes) { + try { + let value = await handle(item); + if (value) { + nodes.push(value); + } + } catch (e) {} + } + + items.push(...nodes); + + // 下一页 + if (data.pageInfo.hasNextPage) { + await sleep(); + let values = await updateTheme(query, auth, format, handle, data.pageInfo.hasNextPage); + items.push(...values); + } + + return items; +} + +// 从 Github 中搜索对应 topic 的仓库 +async function updateRepoTheme() { + let query = ` + query($startCursor: String) { + topic(name: "glidea-theme") { + repositories(first: 30, visibility: PUBLIC, after: $startCursor) { + totalCount + pageInfo { + startCursor + endCursor + hasNextPage + hasPreviousPage + } + nodes { + name + owner { + login + } + refs(first: 1, refPrefix: "refs/heads/") { + nodes { + name + } + } + description + url + homepageUrl + openGraphImageUrl + stargazerCount + createdAt + pushedAt + } + } + } + } + `; + let format = (result) => ({ + totalCount: result.data.topic.repositories.totalCount, + pageInfo: result.data.topic.repositories.pageInfo, + nodes: result.data.topic.repositories.nodes, + }); + let handle = async (node) => { + // 获取 README.md + let url = `https://raw.githubusercontent.com/${node.owner.login}/${node.name}/refs/heads/${node.refs.nodes[0].name}/README.md`; + let text = await fetch(url).then((result) => result.text()); + // 设置数据 + let secr = text.match(/\[screenshots\]\:(.*)/)?.[1]; + if (!secr) secr = ""; + let prev = text.match(/\[preview\]\:(.*)/)?.[1]; + if (!prev) prev = !node.homepageUrl ? node.url : node.homepageUrl; + let intr = text.match(/\[introduce\]\:(.*)/)?.[1]; + if (!intr) intr = ""; + + return { + name: node.name.replace("glidea-theme-", ""), + owner: node.owner.login, + intr: intr, + secr: secr, + prev: prev, + repo: node.url, + star: node.stargazerCount, + }; + }; + return await updateTheme(query, auth, format, handle, null); +} + +// 从讨论区中搜索 +async function updateDiscussionTheme() { + let query = ` + query($startCursor: String) { + repository(owner: "wonder-light", name: "glidea") { + discussion(number: 3) { + comments(first: 40, after: $startCursor) { + totalCount + pageInfo { + startCursor + endCursor + hasNextPage + hasPreviousPage + } + nodes { + author { + login + } + body + upvoteCount + createdAt + updatedAt + } + } + } + } + } + `; + let format = (result) => ({ + totalCount: result.data.repository.discussion.comments.totalCount, + pageInfo: result.data.repository.discussion.comments.pageInfo, + nodes: result.data.repository.discussion.comments.nodes, + }); + let handle = async (node) => { + let text = node.body; + // 设置数据 + let name = text.match(/\[theme\]\:(.*)/)?.[1]; + if (!name) name = ""; + let intr = text.match(/\[introduce\]\:(.*)/)?.[1]; + if (!intr) intr = ""; + let prev = text.match(/\[preview\]\:(.*)/)?.[1]; + if (!prev) prev = !node.homepageUrl ? node.url : node.homepageUrl; + let repo = text.match(/\[repository\]\:(.*)/)?.[1]; + if (!repo) repo = ""; + let secr = text.match(/\[screenshots\]\:(.*)/)?.[1]; + if (!secr) secr = ""; + + if (!name && !repo) return null; + + return { + name: name, + owner: node.author.login, + intr: intr, + secr: secr, + prev: prev, + repo: repo, + star: node.upvoteCount, + }; + }; + return await updateTheme(query, auth, format, handle, null); +} + +async function execRepo() { + config.githubItems = await updateRepoTheme(); + fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); +} + +async function execDiscussion() { + config.defaultItems = await updateDiscussionTheme(); + fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); +} + +// execRepo(); + +exports.execRepo = execRepo; +exports.execDiscussion = execDiscussion; diff --git a/docs/index.html b/docs/index.html index 173e433..29825e2 100644 --- a/docs/index.html +++ b/docs/index.html @@ -8,34 +8,37 @@ - + +
+ + + + - + - + - + - + - + - - - - - - - + + + + + \ No newline at end of file diff --git a/docs/zh-cn/docs/_sidebar.md b/docs/zh-cn/docs/_sidebar.md index 474f825..e69989e 100644 --- a/docs/zh-cn/docs/_sidebar.md +++ b/docs/zh-cn/docs/_sidebar.md @@ -8,6 +8,7 @@ * [结构](zh-cn/docs/theme/struct.md) * [变量](zh-cn/docs/theme/var.md) * [自定义](zh-cn/docs/theme/custom.md) + * [分享](zh-cn/docs/theme/shared.md) * 指南 * [安装](zh-cn/docs/guide/install.md) * [常见问题](zh-cn/docs/guide/faq.md) diff --git a/docs/zh-cn/docs/theme/shared.md b/docs/zh-cn/docs/theme/shared.md new file mode 100644 index 0000000..73d04d7 --- /dev/null +++ b/docs/zh-cn/docs/theme/shared.md @@ -0,0 +1 @@ +# 分享主题 diff --git a/docs/zh-cn/themes/README.md b/docs/zh-cn/themes/README.md index 1092046..6fb6933 100644 --- a/docs/zh-cn/themes/README.md +++ b/docs/zh-cn/themes/README.md @@ -1,5 +1,5 @@ # 主题
- +
\ No newline at end of file diff --git a/docs/zh-cn/themes/_sidebar.md b/docs/zh-cn/themes/_sidebar.md new file mode 100644 index 0000000..e8d7141 --- /dev/null +++ b/docs/zh-cn/themes/_sidebar.md @@ -0,0 +1 @@ + \ No newline at end of file