From 134101e0c19bb1e175440ca3aca1b4e335739031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=A7=E6=B5=AA?= Date: Wed, 5 Aug 2020 10:23:09 +0800 Subject: [PATCH] feat: add issue comment with Preview in Playground (#45) --- .github/workflows/issue-pr.yaml | 4 +- .github/workflows/labeling.yaml | 5 +- .github/workflows/toggle-pr-with-issue.yaml | 5 +- actions/types.d.ts | 7 --- pnpm-lock.yaml | 50 ++++++++-------- pnpm-workspace.yaml | 2 +- {actions => scripts/actions}/issue-pr.ts | 34 ++++++++--- {actions => scripts/actions}/labeling.ts | 2 +- {actions => scripts/actions}/loader.ts | 0 .../actions}/toggle-pr-with-issue.ts | 2 +- scripts/actions/utils/formatToCode.ts | 24 ++++++++ scripts/actions/utils/toCommentBlock.ts | 9 +++ scripts/actions/utils/toDivider.ts | 3 + scripts/actions/utils/toFooter.ts | 11 ++++ scripts/actions/utils/toInfoHeader.ts | 11 ++++ scripts/actions/utils/toLinks.ts | 8 +++ scripts/build.ts | 59 ++----------------- scripts/locales/en.json | 1 + scripts/locales/zh-CN.json | 1 + {actions => scripts}/package.json | 10 +++- scripts/readme.ts | 6 +- scripts/tsconfig.json | 16 +++++ scripts/types.ts | 7 +++ tsconfig.base.json | 1 + 24 files changed, 169 insertions(+), 109 deletions(-) delete mode 100644 actions/types.d.ts rename {actions => scripts/actions}/issue-pr.ts (86%) rename {actions => scripts/actions}/labeling.ts (96%) rename {actions => scripts/actions}/loader.ts (100%) rename {actions => scripts/actions}/toggle-pr-with-issue.ts (97%) create mode 100644 scripts/actions/utils/formatToCode.ts create mode 100644 scripts/actions/utils/toCommentBlock.ts create mode 100644 scripts/actions/utils/toDivider.ts create mode 100644 scripts/actions/utils/toFooter.ts create mode 100644 scripts/actions/utils/toInfoHeader.ts create mode 100644 scripts/actions/utils/toLinks.ts rename {actions => scripts}/package.json (71%) create mode 100644 scripts/tsconfig.json diff --git a/.github/workflows/issue-pr.yaml b/.github/workflows/issue-pr.yaml index 5e73a7099..0f110eaeb 100644 --- a/.github/workflows/issue-pr.yaml +++ b/.github/workflows/issue-pr.yaml @@ -9,5 +9,5 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - run: cd actions && npm i --only=production - - run: cd actions && node -r esm -r esbuild-register ./loader.ts ${{github.token}} issue-pr \ No newline at end of file + - run: cd scripts && npm i --only=production + - run: cd scripts/actions && node -r esm -r esbuild-register ./loader.ts ${{github.token}} issue-pr diff --git a/.github/workflows/labeling.yaml b/.github/workflows/labeling.yaml index 3eff37958..2d853e2fd 100644 --- a/.github/workflows/labeling.yaml +++ b/.github/workflows/labeling.yaml @@ -9,5 +9,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - run: cd actions && npm i --only=production - - run: cd actions && node -r esm -r esbuild-register ./loader.ts ${{github.token}} labeling + - run: cd scripts && npm i --only=production + - run: cd scripts/actions && node -r esm -r esbuild-register ./loader.ts ${{github.token}} labeling + diff --git a/.github/workflows/toggle-pr-with-issue.yaml b/.github/workflows/toggle-pr-with-issue.yaml index 11c2fdcea..2bee9f7a2 100644 --- a/.github/workflows/toggle-pr-with-issue.yaml +++ b/.github/workflows/toggle-pr-with-issue.yaml @@ -9,5 +9,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - run: cd actions && npm i --only=production - - run: cd actions && node -r esm -r esbuild-register ./loader.ts ${{github.token}} toggle-pr-with-issue + - run: cd scripts && npm i --only=production + - run: cd scripts/actions && node -r esm -r esbuild-register ./loader.ts ${{github.token}} toggle-pr-with-issue + diff --git a/actions/types.d.ts b/actions/types.d.ts deleted file mode 100644 index b347d7075..000000000 --- a/actions/types.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { getOctokit, context } from '@actions/github' -import type Core from '@actions/core' -import type IO from '@actions/io' - -export type Github = ReturnType -export type Context = typeof context -export type Action = (github: Github, context: Context, core: typeof Core, io: typeof IO) => Promise diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b19f4ec67..119bf15e9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -43,7 +43,7 @@ importers: ts-node: ^8.10.2 typescript: ^4.0.0-beta utility-types: ^3.10.0 - actions: + scripts: dependencies: '@actions/core': 1.2.4 '@actions/github': 4.0.0 @@ -52,11 +52,15 @@ importers: esbuild: 0.6.16 esbuild-register: 1.0.2_esbuild@0.6.16 esm: 3.2.25 + fast-glob: 3.2.4 + fs-extra: 9.0.1 js-yaml: 3.14.0 limax: 2.1.0 + lz-string: 1.4.4 devDependencies: '@octokit/types': 5.2.0 '@types/js-yaml': 3.12.5 + '@types/lz-string': 1.3.34 specifiers: '@actions/core': ^1.2.4 '@actions/github': ^4.0.0 @@ -64,11 +68,15 @@ importers: '@octokit/types': ^5.2.0 '@type-challenges/octokit-create-pull-request': ^0.1.8 '@types/js-yaml': ^3.12.5 + '@types/lz-string': ^1.3.34 esbuild: ^0.6.16 esbuild-register: ^1.0.2 esm: ^3.2.25 + fast-glob: ^3.2.4 + fs-extra: ^9.0.1 js-yaml: ^3.14.0 limax: ^2.1.0 + lz-string: ^1.4.4 utils: devDependencies: typescript: 3.9.7 @@ -77,6 +85,7 @@ importers: lockfileVersion: 5.1 packages: /@actions/core/1.2.4: + dev: false resolution: integrity: sha512-YJCEq8BE3CdN8+7HPZ/4DxJjk/OkZV2FFIf+DlZTC/4iBlzYCD5yjRR6eiOS5llO11zbRltIRuKAjMKaWTE6cg== /@actions/github/4.0.0: @@ -85,11 +94,13 @@ packages: '@octokit/core': 3.1.1 '@octokit/plugin-paginate-rest': 2.3.0 '@octokit/plugin-rest-endpoint-methods': 4.1.2 + dev: false resolution: integrity: sha512-Ej/Y2E+VV6sR9X7pWL5F3VgEWrABaT292DRqRU6R4hnQjPtC/zD3nagxVdXWiRQvYDh8kHXo7IDmG42eJ/dOMA== /@actions/http-client/1.0.8: dependencies: tunnel: 0.0.6 + dev: false resolution: integrity: sha512-G4JjJ6f9Hb3Zvejj+ewLLKLf99ZC+9v+yCxoYf9vSyH+WkzPLB2LuUtRMGNkooMqdugGBFStIKXOuvH1W+EctA== /@actions/io/1.0.2: @@ -210,13 +221,11 @@ packages: dependencies: '@nodelib/fs.stat': 2.0.3 run-parallel: 1.1.9 - dev: true engines: node: '>= 8' resolution: integrity: sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== /@nodelib/fs.stat/2.0.3: - dev: true engines: node: '>= 8' resolution: @@ -225,7 +234,6 @@ packages: dependencies: '@nodelib/fs.scandir': 2.1.3 fastq: 1.8.0 - dev: true engines: node: '>= 8' resolution: @@ -233,6 +241,7 @@ packages: /@octokit/auth-token/2.4.2: dependencies: '@octokit/types': 5.2.0 + dev: false resolution: integrity: sha512-jE/lE/IKIz2v1+/P0u4fJqv0kYwXOTujKemJMFr6FeopsxlIK3+wKDCJGnysg81XID5TgZQbIfuJ5J0lnTiuyQ== /@octokit/core/3.1.1: @@ -243,6 +252,7 @@ packages: '@octokit/types': 5.2.0 before-after-hook: 2.1.0 universal-user-agent: 6.0.0 + dev: false resolution: integrity: sha512-cQ2HGrtyNJ1IBxpTP1U5m/FkMAJvgw7d2j1q3c9P0XUuYilEgF6e4naTpsgm4iVcQeOnccZlw7XHRIUBy0ymcg== /@octokit/endpoint/6.0.5: @@ -250,6 +260,7 @@ packages: '@octokit/types': 5.2.0 is-plain-object: 4.1.1 universal-user-agent: 6.0.0 + dev: false resolution: integrity: sha512-70K5u6zd45ItOny6aHQAsea8HHQjlQq85yqOMe+Aj8dkhN2qSJ9T+Q3YjUjEYfPRBcuUWNgMn62DQnP/4LAIiQ== /@octokit/graphql/4.5.3: @@ -257,17 +268,20 @@ packages: '@octokit/request': 5.4.7 '@octokit/types': 5.2.0 universal-user-agent: 6.0.0 + dev: false resolution: integrity: sha512-JyYvi3j2tOb5ofASEpcg1Advs07H+Ag+I+ez7buuZfNVAmh1IYcDTuxd4gnYH8S2PSGu+f5IdDGxMmkK+5zsdA== /@octokit/plugin-paginate-rest/2.3.0: dependencies: '@octokit/types': 5.2.0 + dev: false resolution: integrity: sha512-Ye2ZJreP0ZlqJQz8fz+hXvrEAEYK4ay7br1eDpWzr6j76VXs/gKqxFcH8qRzkB3fo/2xh4Vy9VtGii4ZDc9qlA== /@octokit/plugin-rest-endpoint-methods/4.1.2: dependencies: '@octokit/types': 5.2.0 deprecation: 2.3.1 + dev: false resolution: integrity: sha512-PTI7wpbGEZ2IR87TVh+TNWaLcgX/RsZQalFbQCq8XxYUrQ36RHyERrHSNXFy5gkWpspUAOYRSV707JJv6BhqJA== /@octokit/request-error/2.0.2: @@ -275,6 +289,7 @@ packages: '@octokit/types': 5.2.0 deprecation: 2.3.1 once: 1.4.0 + dev: false resolution: integrity: sha512-2BrmnvVSV1MXQvEkrb9zwzP0wXFNbPJij922kYBTLIlIafukrGOb+ABBT2+c6wZiuyWDH1K1zmjGQ0toN/wMWw== /@octokit/request/5.4.7: @@ -287,6 +302,7 @@ packages: node-fetch: 2.6.0 once: 1.4.0 universal-user-agent: 6.0.0 + dev: false resolution: integrity: sha512-FN22xUDP0i0uF38YMbOfx6TotpcENP5W8yJM1e/LieGXn6IoRxDMnBf7tx5RKSW4xuUZ/1P04NFZy5iY3Rax1A== /@octokit/types/5.2.0: @@ -648,7 +664,6 @@ packages: resolution: integrity: sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== /at-least-node/1.0.0: - dev: true engines: node: '>= 4.0.0' resolution: @@ -673,6 +688,7 @@ packages: resolution: integrity: sha1-ibTRmasr7kneFk6gK4nORi1xt2c= /before-after-hook/2.1.0: + dev: false resolution: integrity: sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A== /brace-expansion/1.1.11: @@ -684,7 +700,6 @@ packages: /braces/3.0.2: dependencies: fill-range: 7.0.1 - dev: true engines: node: '>=8' resolution: @@ -868,6 +883,7 @@ packages: resolution: integrity: sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= /deprecation/2.3.1: + dev: false resolution: integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== /detect-libc/1.0.3: @@ -1251,7 +1267,6 @@ packages: merge2: 1.4.1 micromatch: 4.0.2 picomatch: 2.2.2 - dev: true engines: node: '>=8' resolution: @@ -1267,7 +1282,6 @@ packages: /fastq/1.8.0: dependencies: reusify: 1.0.4 - dev: true resolution: integrity: sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q== /file-entry-cache/5.0.1: @@ -1281,7 +1295,6 @@ packages: /fill-range/7.0.1: dependencies: to-regex-range: 5.0.1 - dev: true engines: node: '>=8' resolution: @@ -1351,7 +1364,6 @@ packages: graceful-fs: 4.2.4 jsonfile: 6.0.1 universalify: 1.0.0 - dev: true engines: node: '>=10' resolution: @@ -1400,7 +1412,6 @@ packages: /glob-parent/5.1.1: dependencies: is-glob: 4.0.1 - dev: true engines: node: '>= 6' resolution: @@ -1430,7 +1441,6 @@ packages: resolution: integrity: sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== /graceful-fs/4.2.4: - dev: true resolution: integrity: sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== /has-flag/3.0.0: @@ -1575,7 +1585,6 @@ packages: resolution: integrity: sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== /is-extglob/2.1.1: - dev: true engines: node: '>=0.10.0' resolution: @@ -1598,18 +1607,17 @@ packages: /is-glob/4.0.1: dependencies: is-extglob: 2.1.1 - dev: true engines: node: '>=0.10.0' resolution: integrity: sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== /is-number/7.0.0: - dev: true engines: node: '>=0.12.0' resolution: integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== /is-plain-object/4.1.1: + dev: false engines: node: '>=0.10.0' resolution: @@ -1695,7 +1703,6 @@ packages: /jsonfile/6.0.1: dependencies: universalify: 1.0.0 - dev: true optionalDependencies: graceful-fs: 4.2.4 resolution: @@ -1768,7 +1775,6 @@ packages: resolution: integrity: sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== /lz-string/1.4.4: - dev: true hasBin: true resolution: integrity: sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY= @@ -1785,7 +1791,6 @@ packages: resolution: integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== /merge2/1.4.1: - dev: true engines: node: '>= 8' resolution: @@ -1794,7 +1799,6 @@ packages: dependencies: braces: 3.0.2 picomatch: 2.2.2 - dev: true engines: node: '>=8' resolution: @@ -1861,6 +1865,7 @@ packages: resolution: integrity: sha512-o/qITSDR0JCyCKEQ1/1bnUXMmznxabbwi/Y4WwJElf+evwJNFNwIDMCCt5IigFVxgeGBJESLohGtIS9gEzo1fA== /node-fetch/2.6.0: + dev: false engines: node: 4.x || >=6.0.0 resolution: @@ -2163,7 +2168,6 @@ packages: resolution: integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== /picomatch/2.2.2: - dev: true engines: node: '>=8.6' resolution: @@ -2341,7 +2345,6 @@ packages: resolution: integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== /reusify/1.0.4: - dev: true engines: iojs: '>=1.0.0' node: '>=0.10.0' @@ -2390,7 +2393,6 @@ packages: resolution: integrity: sha512-2a4Mch4f0W2lEvkPuxtz0GfrtfgLj9bdd/oC9L3LozGOCnmLqO7ivMfKbCJoRgqWIU2UqAcbxRFSwmIKx+uStA== /run-parallel/1.1.9: - dev: true resolution: integrity: sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== /safe-buffer/5.1.2: @@ -2673,7 +2675,6 @@ packages: /to-regex-range/5.0.1: dependencies: is-number: 7.0.0 - dev: true engines: node: '>=8.0' resolution: @@ -2723,6 +2724,7 @@ packages: resolution: integrity: sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== /tunnel/0.0.6: + dev: false engines: node: '>=0.6.11 <=0.7.0 || >=0.7.3' resolution: @@ -2762,6 +2764,7 @@ packages: resolution: integrity: sha512-d3s/CogGtB2uPZ2Z8ts6eoUxxyB9PH3R27/UrzvpthuOvpCg4FWWnBbBiqJ0K4eu6eTlgmLiqQkh2dquReJweA== /universal-user-agent/6.0.0: + dev: false resolution: integrity: sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== /universalify/0.1.2: @@ -2771,7 +2774,6 @@ packages: resolution: integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== /universalify/1.0.0: - dev: true engines: node: '>= 10.0.0' resolution: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 1f6749141..52d921bef 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,3 @@ packages: - utils - - actions \ No newline at end of file + - scripts diff --git a/actions/issue-pr.ts b/scripts/actions/issue-pr.ts similarity index 86% rename from actions/issue-pr.ts rename to scripts/actions/issue-pr.ts index b8751583f..b26281740 100644 --- a/actions/issue-pr.ts +++ b/scripts/actions/issue-pr.ts @@ -1,7 +1,11 @@ import YAML from 'js-yaml' import slug from 'limax' import { PushCommit } from '@type-challenges/octokit-create-pull-request' -import type { Action, Github, Context } from './types' +import { Action, Context, Github } from '../types' +import { t } from '../locales' +import { toPlaygroundUrl } from '../toUrl' +import { toBadgeLink } from '../readme' +import { formatToCode } from './utils/formatToCode' const Messages = { en: { @@ -44,7 +48,7 @@ const action: Action = async(github, context, core) => { const tests = getCodeBlock(body, Messages[locale].tests, 'ts') const question = getCommentRange(body, 'question') - let info: any = {} + let info: any try { info = YAML.safeLoad(infoRaw || '') @@ -121,15 +125,31 @@ const action: Action = async(github, context, core) => { fresh: !existing_pull, }) + const playgroundURL = toPlaygroundUrl(formatToCode({ + no, + difficulty: info.difficulty, + path: '', + info, + template, + tests, + readme: { + [locale]: question, + }, + }, locale)) + + const playgroundBadge = toBadgeLink(playgroundURL, '', t(locale, 'badge.preview-playground'), '3178c6', '?logo=typescript') + const createMessageBody = (prNumber: number) => + `${Messages[locale].issue_update_reply.replace('{0}', prNumber.toString()) + }\n\n${ + getTimestampBadge()} ${playgroundBadge}` + if (existing_pull) { core.info('-----Pull Request Existed-----') core.info(JSON.stringify(existing_pull, null, 2)) await updateComment( github, context, - `${Messages[locale].issue_update_reply.replace('{0}', existing_pull.number.toString()) - }\n\n${ - getTimestampBadge()}`, + createMessageBody(existing_pull.number), ) } else { @@ -151,9 +171,7 @@ const action: Action = async(github, context, core) => { await updateComment( github, context, - `${Messages[locale].issue_reply.replace('{0}', pr.number.toString()) - }\n\n${ - getTimestampBadge()}`, + createMessageBody(pr.number), ) } } diff --git a/actions/labeling.ts b/scripts/actions/labeling.ts similarity index 96% rename from actions/labeling.ts rename to scripts/actions/labeling.ts index 74d2e71ab..ce2d726bf 100644 --- a/actions/labeling.ts +++ b/scripts/actions/labeling.ts @@ -1,4 +1,4 @@ -import type { Action } from './types' +import { Action } from '../types' const action: Action = async(github, context, core) => { const payload = context.payload diff --git a/actions/loader.ts b/scripts/actions/loader.ts similarity index 100% rename from actions/loader.ts rename to scripts/actions/loader.ts diff --git a/actions/toggle-pr-with-issue.ts b/scripts/actions/toggle-pr-with-issue.ts similarity index 97% rename from actions/toggle-pr-with-issue.ts rename to scripts/actions/toggle-pr-with-issue.ts index af11a472b..b537493fb 100644 --- a/actions/toggle-pr-with-issue.ts +++ b/scripts/actions/toggle-pr-with-issue.ts @@ -1,4 +1,4 @@ -import { Action } from './types' +import { Action } from '../types' const action: Action = async(github, context, core) => { const payload = context.payload || {} diff --git a/scripts/actions/utils/formatToCode.ts b/scripts/actions/utils/formatToCode.ts new file mode 100644 index 000000000..0bb869589 --- /dev/null +++ b/scripts/actions/utils/formatToCode.ts @@ -0,0 +1,24 @@ +import { Quiz } from '../../types' +import { defaultLocale, SupportedLocale, t } from '../../locales' +import { toCommentBlock } from './toCommentBlock' +import { toInfoHeader } from './toInfoHeader' +import { toLinks } from './toLinks' +import { toDivider } from './toDivider' +import { toFooter } from './toFooter' + +export const formatToCode = (quiz: Quiz, locale: SupportedLocale) => { + return `${toCommentBlock( + toInfoHeader(quiz, locale) + + (quiz.readme[locale] || quiz.readme[defaultLocale]) + + toLinks(quiz, locale), + ) + + toDivider(t(locale, 'divider.code-start')) + }\n${ + (quiz.template || '').trim() + }\n\n${ + toDivider(t(locale, 'divider.test-cases')) + }${quiz.tests || '' + }\n\n${ + toDivider(t(locale, 'divider.further-steps')) + }${toCommentBlock(toFooter(quiz, locale))}` +} diff --git a/scripts/actions/utils/toCommentBlock.ts b/scripts/actions/utils/toCommentBlock.ts new file mode 100644 index 000000000..7f9800df6 --- /dev/null +++ b/scripts/actions/utils/toCommentBlock.ts @@ -0,0 +1,9 @@ +export const toCommentBlock = function(text: string) { + return `/*\n${ + text + .trim() + .split('\n') + .map(i => ` ${i}`) + .join('\n') + }\n*/\n\n` +} diff --git a/scripts/actions/utils/toDivider.ts b/scripts/actions/utils/toDivider.ts new file mode 100644 index 000000000..18709ebbb --- /dev/null +++ b/scripts/actions/utils/toDivider.ts @@ -0,0 +1,3 @@ +export const toDivider = function(text: string) { + return `\n/* _____________ ${text} _____________ */\n` +} diff --git a/scripts/actions/utils/toFooter.ts b/scripts/actions/utils/toFooter.ts new file mode 100644 index 000000000..27b358563 --- /dev/null +++ b/scripts/actions/utils/toFooter.ts @@ -0,0 +1,11 @@ +import { Quiz } from '../../types' + +import { SupportedLocale, t } from '../../locales' +import { toAnswerShort, toHomepageShort, toSolutionsShort } from '../../toUrl' + +export const toFooter = function(quiz: Quiz, locale: SupportedLocale) { + return '\n\n' + + `> ${t(locale, 'link.share-solutions')}${toAnswerShort(quiz.no, locale)}\n` + + `> ${t(locale, 'link.checkout-solutions')}${toSolutionsShort(quiz.no)}\n` + + `> ${t(locale, 'link.more-challenges')}${toHomepageShort(locale)}\n` +} diff --git a/scripts/actions/utils/toInfoHeader.ts b/scripts/actions/utils/toInfoHeader.ts new file mode 100644 index 000000000..09e332dd6 --- /dev/null +++ b/scripts/actions/utils/toInfoHeader.ts @@ -0,0 +1,11 @@ +import { Quiz } from '../../types' +import { SupportedLocale, t } from '../../locales' +import { resolveInfo } from '../../loader' + +export const toInfoHeader = function toInfoHeader(quiz: Quiz, locale: SupportedLocale) { + const info = resolveInfo(quiz, locale) + return `${quiz.no} - ${info.title || ''}\n` + + '-------\n' + + `by ${info.author?.name} (@${info?.author?.github}) #${t(locale, `difficulty.${quiz.difficulty}`)} ${info?.tags?.map(i => `#${i}`).join(' ') || ''}\n\n` + + `### ${t(locale, 'title.question')}\n\n` +} diff --git a/scripts/actions/utils/toLinks.ts b/scripts/actions/utils/toLinks.ts new file mode 100644 index 000000000..25e0e44da --- /dev/null +++ b/scripts/actions/utils/toLinks.ts @@ -0,0 +1,8 @@ +import { Quiz } from '../../types' +import { SupportedLocale, t } from '../../locales' +import { toReadmeShort } from '../../toUrl' + +export function toLinks(quiz: Quiz, locale: SupportedLocale) { + return '\n\n' + + `> ${t(locale, 'link.view-on-github')}${toReadmeShort(quiz.no, locale)}` +} diff --git a/scripts/build.ts b/scripts/build.ts index 390ab6593..6f98f5205 100644 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -1,43 +1,9 @@ import path from 'path' import fs from 'fs-extra' import { loadQuizes, resolveInfo } from './loader' -import { toPlaygroundUrl, toSolutionsShort, REPO, toSolutionsFull, toQuizREADME, toAnswerShort, toShareAnswerFull, toReadmeShort, toHomepageShort } from './toUrl' -import { Quiz } from './types' -import { supportedLocales, defaultLocale, t, SupportedLocale } from './locales' - -function toCommentBlock(text: string) { - return `/*\n${ - text - .trim() - .split('\n') - .map(i => ` ${i}`) - .join('\n') - }\n*/\n\n` -} - -function toDivier(text: string) { - return `\n/* _____________ ${text} _____________ */\n` -} - -function toInfoHeader(quiz: Quiz, locale: SupportedLocale) { - const info = resolveInfo(quiz, locale) - return `${quiz.no} - ${info.title || ''}\n` - + '-------\n' - + `by ${info.author?.name} (@${info?.author?.github}) #${t(locale, `difficulty.${quiz.difficulty}`)} ${info?.tags?.map(i => `#${i}`).join(' ') || ''}\n\n` - + `### ${t(locale, 'title.question')}\n\n` -} - -function toLinks(quiz: Quiz, locale: SupportedLocale) { - return '\n\n' - + `> ${t(locale, 'link.view-on-github')}${toReadmeShort(quiz.no, locale)}` -} - -function toFooter(quiz: Quiz, locale: SupportedLocale) { - return '\n\n' - + `> ${t(locale, 'link.share-solutions')}${toAnswerShort(quiz.no, locale)}\n` - + `> ${t(locale, 'link.checkout-solutions')}${toSolutionsShort(quiz.no)}\n` - + `> ${t(locale, 'link.more-challenges')}${toHomepageShort(locale)}\n` -} +import { REPO, toPlaygroundUrl, toQuizREADME, toShareAnswerFull, toSolutionsFull } from './toUrl' +import { defaultLocale, supportedLocales } from './locales' +import { formatToCode } from './actions/utils/formatToCode' export async function build() { const quizes = await loadQuizes() @@ -53,24 +19,7 @@ export async function build() { for (const locale of supportedLocales) { const info = resolveInfo(quiz, locale) - /* eslint-disable prefer-template */ - const code - = toCommentBlock( - toInfoHeader(quiz, locale) - + (quiz.readme[locale] || quiz.readme[defaultLocale]) - + toLinks(quiz, locale), - ) - + toDivier(t(locale, 'divider.code-start')) - + '\n' - + (quiz.template || '').trim() - + '\n\n' - + toDivier(t(locale, 'divider.test-cases')) - + (quiz.tests || '') - + '\n\n' - + toDivier(t(locale, 'divider.further-steps')) - + toCommentBlock(toFooter(quiz, locale)) - - /* eslint-enable prefer-template */ + const code = formatToCode(quiz, locale) const url = toPlaygroundUrl(code, info.tsconfig || {}) diff --git a/scripts/locales/en.json b/scripts/locales/en.json index 0fbeb8d92..3611ab000 100644 --- a/scripts/locales/en.json +++ b/scripts/locales/en.json @@ -3,6 +3,7 @@ "badge.checkout-solutions": "Check out Solutions", "badge.share-your-solutions": "Share your Solutions", "badge.take-the-challenge": "Take the Challenge", + "badge.preview-playground": "Preview in Playground", "difficulty.easy": "easy", "difficulty.extreme": "extreme", "difficulty.hard": "hard", diff --git a/scripts/locales/zh-CN.json b/scripts/locales/zh-CN.json index fc3a89992..ea9219d36 100644 --- a/scripts/locales/zh-CN.json +++ b/scripts/locales/zh-CN.json @@ -3,6 +3,7 @@ "badge.checkout-solutions": "查看解答", "badge.share-your-solutions": "分享你的解答", "badge.take-the-challenge": "接受挑战", + "badge.preview-playground": "在 Playground 中预览", "difficulty.easy": "简单", "difficulty.extreme": "地狱", "difficulty.hard": "困难", diff --git a/actions/package.json b/scripts/package.json similarity index 71% rename from actions/package.json rename to scripts/package.json index 8b327f869..7e71deffb 100644 --- a/actions/package.json +++ b/scripts/package.json @@ -4,17 +4,21 @@ "version": "1.0.0", "dependencies": { "@actions/core": "^1.2.4", - "@actions/io": "^1.0.2", "@actions/github": "^4.0.0", + "@actions/io": "^1.0.2", "@type-challenges/octokit-create-pull-request": "^0.1.8", "esbuild": "^0.6.16", "esbuild-register": "^1.0.2", "esm": "^3.2.25", + "fast-glob": "^3.2.4", + "fs-extra": "^9.0.1", "js-yaml": "^3.14.0", - "limax": "^2.1.0" + "limax": "^2.1.0", + "lz-string": "^1.4.4" }, "devDependencies": { "@octokit/types": "^5.2.0", - "@types/js-yaml": "^3.12.5" + "@types/js-yaml": "^3.12.5", + "@types/lz-string": "^1.3.34" } } diff --git a/scripts/readme.ts b/scripts/readme.ts index ce4aae390..85a63bb18 100644 --- a/scripts/readme.ts +++ b/scripts/readme.ts @@ -1,8 +1,8 @@ import path from 'path' import fs from 'fs-extra' -import { supportedLocales, defaultLocale, t, SupportedLocale, f } from './locales' +import { defaultLocale, f, SupportedLocale, supportedLocales, t } from './locales' import { loadQuizes, resolveInfo } from './loader' -import { toPlayShort, toQuizREADME, toSolutionsShort, toAnswerShort, toReadmeShort, toNearborREADME } from './toUrl' +import { toAnswerShort, toNearborREADME, toPlayShort, toQuizREADME, toSolutionsShort } from './toUrl' import { Quiz, QuizMetaInfo } from './types' const DifficultyColors: Record = { @@ -38,7 +38,7 @@ function toBadge(label: string, text: string, color: string, args = '') { return `${text}` } -function toBadgeLink(url: string, label: string, text: string, color: string, args = '') { +export function toBadgeLink(url: string, label: string, text: string, color: string, args = '') { return `${toBadge(label, text, color, args)} ` } diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json new file mode 100644 index 000000000..de18c34f6 --- /dev/null +++ b/scripts/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "module": "esnext", + "target": "es2017", + "lib": ["ESNext"], + "strict": true, + "esModuleInterop": true, + "moduleResolution": "node", + "skipLibCheck": true, + "noUnusedLocals": false, + "noUnusedParameters": true, + "noImplicitReturns": true, + "allowJs": true + }, + "exclude": ["node_modules", "dist"] +} diff --git a/scripts/types.ts b/scripts/types.ts index 7a7cb6c4f..31ebd889b 100644 --- a/scripts/types.ts +++ b/scripts/types.ts @@ -1,4 +1,11 @@ import { DeepPartial } from 'utility-types' +import type { getOctokit, context } from '@actions/github' +import type Core from '@actions/core' +import type IO from '@actions/io' + +export type Github = ReturnType +export type Context = typeof context +export type Action = (github: Github, context: Context, core: typeof Core, io: typeof IO) => Promise export interface QuizMetaInfo { title: string diff --git a/tsconfig.base.json b/tsconfig.base.json index 5d5d44138..de18c34f6 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -10,6 +10,7 @@ "noUnusedLocals": false, "noUnusedParameters": true, "noImplicitReturns": true, + "allowJs": true }, "exclude": ["node_modules", "dist"] }