mirror of
https://github.com/one-among-us/data.git
synced 2024-11-22 03:04:51 +08:00
[U] Migrate to MDX
This commit is contained in:
parent
46e8bf3e8b
commit
92e43b18b0
59
.github/workflows/generator.yml
vendored
59
.github/workflows/generator.yml
vendored
@ -1,47 +1,42 @@
|
||||
# This is a basic workflow to help you get started with Actions
|
||||
|
||||
name: Generator
|
||||
|
||||
# Controls when the workflow will run
|
||||
on:
|
||||
# Triggers the workflow on push or pull request events but only for the main branch
|
||||
push:
|
||||
branches: [ main ]
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
# This workflow contains a single job called "build"
|
||||
build:
|
||||
# The type of runner that the job will run on
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
python-version: "3.9"
|
||||
|
||||
- name: "Install dependencies"
|
||||
node-version: 16.x
|
||||
- name: Cache node_modules
|
||||
uses: actions/cache@v2
|
||||
id: cache
|
||||
with:
|
||||
path: node_modules
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: ${{ runner.os }}-node-
|
||||
- name: Install Dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: yarn install --production --frozen-lockfile
|
||||
- name: Build
|
||||
run: yarn build
|
||||
- name: Deploy
|
||||
run: |
|
||||
set -xe
|
||||
python -VV
|
||||
python -m pip install json5
|
||||
git config --global user.name $(git show -s --format='%an' HEAD)
|
||||
git config --global user.email $(git show -s --format='%ae' HEAD)
|
||||
|
||||
- name: "Run generator"
|
||||
run: "python generator.py"
|
||||
|
||||
- uses: EndBug/add-and-commit@v7
|
||||
with:
|
||||
# Determines the way the action fills missing author name and email. Three options are available:
|
||||
# - github_actor -> UserName <UserName@users.noreply.github.com>
|
||||
# - user_info -> Your Display Name <your-actual@email.com>
|
||||
# - github_actions -> github-actions <email associated with the github logo>
|
||||
# Default: github_actor
|
||||
default_author: github_actions
|
||||
|
||||
# The message for the commit.
|
||||
# Default: 'Commit from GitHub Actions (name of the workflow)'
|
||||
message: '[U] Generate json'
|
||||
cd dist
|
||||
git init
|
||||
git add .
|
||||
git commit -m "Build on $(date '+%Y-%m-%d %H:%M:%S')"
|
||||
git branch -m gh-pages
|
||||
git remote add origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
|
||||
git push -f origin gh-pages
|
||||
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,3 +1,9 @@
|
||||
/dist
|
||||
|
||||
/node_modules
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
.idea/inspectionProfiles/Project_Default.xml
|
||||
.idea/misc.xml
|
||||
|
@ -16,5 +16,7 @@
|
||||
* `photos`: Photo directory
|
||||
* `comments`: List of comments made by other users in the format of `yyyy-mm-dd-{name}-{id}.txt`
|
||||
|
||||
* Directory `/generated`: Data that's automatically generated by Github Actions
|
||||
* `people-list.json5`: A list of all people currently in the repository
|
||||
* Branch `gh-pages`: Data that's automatically generated by Github Actions
|
||||
* `people-list.json`: A list of all people currently in the repository
|
||||
* Directory `/people/<userid>/`: Built data for a specific person
|
||||
* `page.js`: `page.md` built with MDX
|
||||
|
@ -1,26 +0,0 @@
|
||||
[
|
||||
{
|
||||
path: "Uekawakuyuurei",
|
||||
id: "Uekawakuyuurei",
|
||||
name: "蛍",
|
||||
profileUrl: "${path}/photos/profile.jpg",
|
||||
},
|
||||
{
|
||||
path: "gaoyanger",
|
||||
id: "gaoyanger",
|
||||
name: "羔羊",
|
||||
profileUrl: "${path}/photos/profile.jpg",
|
||||
},
|
||||
{
|
||||
path: "GLaDOSister",
|
||||
id: "GLaDOSister",
|
||||
name: "倉山静葉",
|
||||
profileUrl: "${path}/photos/profile.jpg",
|
||||
},
|
||||
{
|
||||
path: "donotexist_A",
|
||||
id: "donotexist_A",
|
||||
name: "不存在",
|
||||
profileUrl: "${path}/photos/profile.jpg",
|
||||
},
|
||||
]
|
16
generator.py
16
generator.py
@ -1,16 +0,0 @@
|
||||
import io
|
||||
import os, json5
|
||||
from pathlib import Path
|
||||
|
||||
if __name__ == '__main__':
|
||||
output = []
|
||||
for p in os.listdir("people/"):
|
||||
info_path = f'people/{p}/info.json5'
|
||||
if os.path.isfile(info_path):
|
||||
with io.open(info_path, 'r', encoding='utf-8') as f:
|
||||
o = json5.load(f)
|
||||
output.append({'path': p, 'id': o['id'], 'name': o['name'], 'profileUrl': o['profileUrl']})
|
||||
|
||||
Path("generated").mkdir(parents=True, exist_ok=True)
|
||||
with io.open('generated/people-list.json5', 'w', encoding='utf-8') as f:
|
||||
f.write(json5.dumps(output, indent=2, ensure_ascii=False))
|
26
package.json
Normal file
26
package.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "our-data",
|
||||
"version": "1.0.0",
|
||||
"description": "Data for https://one-among.us",
|
||||
"main": "scripts/build.ts",
|
||||
"repository": "https://github.com/hykilpikonna/our-data",
|
||||
"author": "Hykilpikonna <me@hydev.org>",
|
||||
"license": "UNLICENSED",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "node --loader ts-node/esm/transpile-only scripts/build.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mdx-js/mdx": "^2.1.0",
|
||||
"@swc/core": "^1.2.159",
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
"@types/node": "^16",
|
||||
"esbuild": "^0.14.27",
|
||||
"fs-extra": "^10.0.1",
|
||||
"json5": "^2.2.0",
|
||||
"ts-node": "^10.7.0",
|
||||
"typescript": "^4.6.2",
|
||||
"xdm": "^3.4.0"
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
|
||||
靠画作赞赏获得的收入是他的一部分经济来源。即使不幸确诊了升结肠印戒细胞癌,阿蛍也没有放下 ta 的画笔。后来,阿蛍把大部分画作的电子档上传到了 ta 的[Telegram频道](https://t.me/joinchat/65vSQ6ELb3YxN2I9),供大家无偿下载和欣赏。在这里挑选的几幅画作,可以让大家管窥阿蛍的绘画风格。
|
||||
|
||||
<PhotoScroll photos="[
|
||||
<PhotoScroll photos={[
|
||||
'${path}/photos/IMG_1308.JPG',
|
||||
'${path}/photos/img002.jpg',
|
||||
'${path}/photos/img051.jpg',
|
||||
@ -15,7 +15,7 @@
|
||||
'${path}/photos/img252.jpg',
|
||||
'${path}/photos/img253.jpg',
|
||||
'${path}/photos/img370.jpg',
|
||||
]" />
|
||||
]} />
|
||||
|
||||
但这个世界就是这么不公平,阿蛍的病情持续恶化,并且一直没有找到合适的靶向药物。在 2021 年夏天,阿蛍被确诊为骨转移 IV 期。不过,即使承受着剧烈的疼痛,阿蛍仍然在关心和爱护着每一个安慰 ta 的推友,尽量不让我们担心。
|
||||
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
存存是一个可爱的小姑娘,因此人缘也超级好,每一个见到存存的人都会被她的热情和开朗所打动。虽然存存患有双相以及其他的基础疾病,身体不是很好,经常生病[住院](https://twitter.com/donotexist_A/status/1383379769903910915?s=20),要吃很多药,但她和医生、病友的关系总是很好。同病房的美术生哥哥帮存存画过一张自画像。
|
||||
|
||||
<PhotoScroll photos="[
|
||||
<PhotoScroll photos={[
|
||||
'${path}/photos/portrait.jpg',
|
||||
]" />
|
||||
]} />
|
||||
|
||||
因为存存常梳的发型有点像《动物森友会》里的西施惠,性格也跟西施惠一样可爱,所以有的时候我们也会叫她西施惠。可是存存自己好像有时候不喜欢我们这样叫。
|
||||
|
||||
|
89
scripts/build.ts
Normal file
89
scripts/build.ts
Normal file
@ -0,0 +1,89 @@
|
||||
import url from "url";
|
||||
import path from "path";
|
||||
import fs from "fs-extra";
|
||||
|
||||
import json5 from "json5";
|
||||
|
||||
import { renderMdx } from "./mdx.ts";
|
||||
|
||||
const PUBLIC_DIR = "public";
|
||||
|
||||
const PEOPLE_DIR = "people";
|
||||
const PEOPLE_INFO_FILENAME = "info.json5";
|
||||
const PEOPLE_PAGE_FILE = "page.md";
|
||||
|
||||
const DIST_DIR = "dist";
|
||||
const DIST_PEOPLE_LIST = "people-list.json";
|
||||
const DIST_PEOPLE_INFO_FILENAME = "info.json";
|
||||
const DIST_PEOPLE_PAGE_FILE = "page.js";
|
||||
|
||||
const projectRoot = path.dirname(path.dirname(url.fileURLToPath(import.meta.url)));
|
||||
const peopleDir = path.join(projectRoot, PEOPLE_DIR);
|
||||
const people = fs.readdirSync(peopleDir).map(person => ({
|
||||
dirname: person,
|
||||
srcPath: path.join(peopleDir, person),
|
||||
distPath: path.join(projectRoot, DIST_DIR, PEOPLE_DIR, person)
|
||||
}));
|
||||
|
||||
// Transform `info.json5` to `info.json`.
|
||||
// Extract metadata from `people/${dirname}/info.json5` to `dist/people-list.json`.
|
||||
function buildPeopleInfoAndList() {
|
||||
const PEOPLE_LIST_KEYS = ["id", "name", "profileUrl"] as const;
|
||||
|
||||
type PeopleMeta = Record<"path" | typeof PEOPLE_LIST_KEYS[number], unknown>;
|
||||
const peopleList: PeopleMeta[] = [];
|
||||
|
||||
for (const { dirname, srcPath, distPath } of people) {
|
||||
const infoFile = fs.readFileSync(path.join(srcPath, PEOPLE_INFO_FILENAME), "utf-8");
|
||||
const info = json5.parse(infoFile);
|
||||
|
||||
const peopleMeta = {
|
||||
path: dirname,
|
||||
...Object.fromEntries(PEOPLE_LIST_KEYS.map(key => [key, info[key]]))
|
||||
} as PeopleMeta;
|
||||
|
||||
peopleList.push(peopleMeta);
|
||||
|
||||
fs.ensureDirSync(distPath);
|
||||
fs.writeFileSync(path.join(distPath, DIST_PEOPLE_INFO_FILENAME), JSON.stringify(info));
|
||||
}
|
||||
|
||||
fs.writeFileSync(path.join(projectRoot, DIST_DIR, DIST_PEOPLE_LIST), JSON.stringify(peopleList));
|
||||
}
|
||||
|
||||
// Render `people/${dirname}/page.md` to `dist/people/${dirname}/page.js`.
|
||||
function buildPeoplePages() {
|
||||
for (const { srcPath, distPath } of people) {
|
||||
const markdown = fs.readFileSync(path.join(srcPath, PEOPLE_PAGE_FILE), "utf-8");
|
||||
const result = renderMdx(markdown);
|
||||
|
||||
fs.ensureDirSync(distPath);
|
||||
fs.writeFileSync(path.join(distPath, DIST_PEOPLE_PAGE_FILE), result);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy `people/${dirname}/comments` and `photos` to `dist/people/${dirname}/`.
|
||||
function copyPeopleAssets() {
|
||||
const PEOPLE_ASSETS = ["comments", "photos"];
|
||||
|
||||
for (const { srcPath, distPath } of people) {
|
||||
fs.ensureDirSync(distPath);
|
||||
|
||||
for (const assetDirname of PEOPLE_ASSETS) {
|
||||
const assetSrcPath = path.join(srcPath, assetDirname);
|
||||
if (fs.pathExistsSync(assetSrcPath)) {
|
||||
fs.copySync(assetSrcPath, path.join(distPath, assetDirname));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy files `public` to dist.
|
||||
function copyPublic() {
|
||||
fs.copySync(path.join(projectRoot, PUBLIC_DIR), path.join(projectRoot, DIST_DIR));
|
||||
}
|
||||
|
||||
buildPeopleInfoAndList();
|
||||
buildPeoplePages();
|
||||
copyPeopleAssets();
|
||||
copyPublic();
|
24
scripts/mdx.ts
Normal file
24
scripts/mdx.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import * as mdx from "xdm";
|
||||
import * as swc from "@swc/core";
|
||||
|
||||
export function renderMdx(markdown: string): string {
|
||||
const esmCode = mdx.compileSync(markdown, {
|
||||
jsxRuntime: "classic",
|
||||
pragma: "Vue.h",
|
||||
pragmaFrag: "Vue.Fragment",
|
||||
pragmaImportSource: "vue"
|
||||
}).value.toString("utf-8");
|
||||
|
||||
const codeRemovedImport = esmCode.replace(/^import .*$/m, "");
|
||||
|
||||
return swc.transformSync(codeRemovedImport, {
|
||||
jsc: {
|
||||
parser: {
|
||||
syntax: "ecmascript"
|
||||
},
|
||||
loose: true,
|
||||
},
|
||||
minify: true,
|
||||
module: { type: "commonjs" },
|
||||
}).code;
|
||||
}
|
26
tsconfig.json
Normal file
26
tsconfig.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2021",
|
||||
"lib": [
|
||||
"ES2021"
|
||||
],
|
||||
"skipLibCheck": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"moduleResolution": "Node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"strict": false,
|
||||
"module": "ES2020",
|
||||
"strictBindCallApply": true,
|
||||
"baseUrl": "./",
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"include": [
|
||||
"scripts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist"
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user