mirror of
https://github.com/one-among-us/data.git
synced 2024-11-10 13:24:50 +08:00
commit
45fd335c0a
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
|
name: Generator
|
||||||
|
|
||||||
# Controls when the workflow will run
|
|
||||||
on:
|
on:
|
||||||
# Triggers the workflow on push or pull request events but only for the main branch
|
|
||||||
push:
|
push:
|
||||||
branches: [ main ]
|
branches: [ main ]
|
||||||
|
|
||||||
# Allows you to run this workflow manually from the Actions tab
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
|
||||||
jobs:
|
jobs:
|
||||||
# This workflow contains a single job called "build"
|
|
||||||
build:
|
build:
|
||||||
# The type of runner that the job will run on
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- name: Checkout
|
||||||
- uses: actions/setup-python@v2
|
uses: actions/checkout@v2
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
python-version: "3.9"
|
node-version: 16.x
|
||||||
|
- name: Cache node_modules
|
||||||
- name: "Install dependencies"
|
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: |
|
run: |
|
||||||
set -xe
|
git config --global user.name $(git show -s --format='%an' HEAD)
|
||||||
python -VV
|
git config --global user.email $(git show -s --format='%ae' HEAD)
|
||||||
python -m pip install json5
|
|
||||||
|
|
||||||
- name: "Run generator"
|
cd dist
|
||||||
run: "python generator.py"
|
git init
|
||||||
|
git add .
|
||||||
- uses: EndBug/add-and-commit@v7
|
git commit -m "Build on $(date '+%Y-%m-%d %H:%M:%S')"
|
||||||
with:
|
git branch -m gh-pages
|
||||||
# Determines the way the action fills missing author name and email. Three options are available:
|
git remote add origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
|
||||||
# - github_actor -> UserName <UserName@users.noreply.github.com>
|
git push -f origin gh-pages
|
||||||
# - 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'
|
|
||||||
|
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/inspectionProfiles/Project_Default.xml
|
||||||
.idea/misc.xml
|
.idea/misc.xml
|
||||||
|
@ -16,5 +16,7 @@
|
|||||||
* `photos`: Photo directory
|
* `photos`: Photo directory
|
||||||
* `comments`: List of comments made by other users in the format of `yyyy-mm-dd-{name}-{id}.txt`
|
* `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
|
* Branch `gh-pages`: Data that's automatically generated by Github Actions
|
||||||
* `people-list.json5`: A list of all people currently in the repository
|
* `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),供大家无偿下载和欣赏。在这里挑选的几幅画作,可以让大家管窥阿蛍的绘画风格。
|
靠画作赞赏获得的收入是他的一部分经济来源。即使不幸确诊了升结肠印戒细胞癌,阿蛍也没有放下 ta 的画笔。后来,阿蛍把大部分画作的电子档上传到了 ta 的[Telegram频道](https://t.me/joinchat/65vSQ6ELb3YxN2I9),供大家无偿下载和欣赏。在这里挑选的几幅画作,可以让大家管窥阿蛍的绘画风格。
|
||||||
|
|
||||||
<PhotoScroll photos="[
|
<PhotoScroll photos={[
|
||||||
'${path}/photos/IMG_1308.JPG',
|
'${path}/photos/IMG_1308.JPG',
|
||||||
'${path}/photos/img002.jpg',
|
'${path}/photos/img002.jpg',
|
||||||
'${path}/photos/img051.jpg',
|
'${path}/photos/img051.jpg',
|
||||||
@ -15,7 +15,7 @@
|
|||||||
'${path}/photos/img252.jpg',
|
'${path}/photos/img252.jpg',
|
||||||
'${path}/photos/img253.jpg',
|
'${path}/photos/img253.jpg',
|
||||||
'${path}/photos/img370.jpg',
|
'${path}/photos/img370.jpg',
|
||||||
]" />
|
]} />
|
||||||
|
|
||||||
但这个世界就是这么不公平,阿蛍的病情持续恶化,并且一直没有找到合适的靶向药物。在 2021 年夏天,阿蛍被确诊为骨转移 IV 期。不过,即使承受着剧烈的疼痛,阿蛍仍然在关心和爱护着每一个安慰 ta 的推友,尽量不让我们担心。
|
但这个世界就是这么不公平,阿蛍的病情持续恶化,并且一直没有找到合适的靶向药物。在 2021 年夏天,阿蛍被确诊为骨转移 IV 期。不过,即使承受着剧烈的疼痛,阿蛍仍然在关心和爱护着每一个安慰 ta 的推友,尽量不让我们担心。
|
||||||
|
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
存存是一个可爱的小姑娘,因此人缘也超级好,每一个见到存存的人都会被她的热情和开朗所打动。虽然存存患有双相以及其他的基础疾病,身体不是很好,经常生病[住院](https://twitter.com/donotexist_A/status/1383379769903910915?s=20),要吃很多药,但她和医生、病友的关系总是很好。同病房的美术生哥哥帮存存画过一张自画像。
|
存存是一个可爱的小姑娘,因此人缘也超级好,每一个见到存存的人都会被她的热情和开朗所打动。虽然存存患有双相以及其他的基础疾病,身体不是很好,经常生病[住院](https://twitter.com/donotexist_A/status/1383379769903910915?s=20),要吃很多药,但她和医生、病友的关系总是很好。同病房的美术生哥哥帮存存画过一张自画像。
|
||||||
|
|
||||||
<PhotoScroll photos="[
|
<PhotoScroll photos={[
|
||||||
'${path}/photos/portrait.jpg',
|
'${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