From 43f4aed6e5266fb0526b580e0ac25f1e420d7079 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Tue, 15 Aug 2023 20:27:34 +0800 Subject: [PATCH 01/16] Squashed 'workspace/plugins/wakatime/' content from commit afc0af6 git-subtree-dir: workspace/plugins/wakatime git-subtree-split: afc0af694c6ddedc1773da391bd0fd87f68433a3 --- .github/FUNDING.yml | 36 + .github/workflows/build.yml | 93 +++ .github/workflows/release-distribution.yml | 81 +++ .github/workflows/release-please.yml | 112 +++ .gitignore | 27 + LICENSE | 661 ++++++++++++++++++ README.md | 40 ++ package.json | 29 + public/README.md | 167 +++++ public/README_zh_CN.md | 167 +++++ public/i18n/en_US.json | 79 +++ public/i18n/zh_CHT.json | 79 +++ public/i18n/zh_CN.json | 79 +++ public/icon.png | Bin 0 -> 3868 bytes public/plugin.json | 35 + public/preview.png | Bin 0 -> 67702 bytes .../symbols/icon-wakatime-wakapi.symbol | 117 ++++ src/assets/symbols/icon-wakatime.symbol | 19 + src/components/Settings.svelte | 429 ++++++++++++ src/configs/default.ts | 42 ++ src/index.ts | 540 ++++++++++++++ src/types/config.d.ts | 44 ++ src/types/wakatime.d.ts | 100 +++ src/utils/i18n.ts | 33 + src/vite-env.d.ts | 2 + src/wakatime/heartbeats.ts | 41 ++ svelte.config.js | 24 + tsconfig.json | 38 + tsconfig.node.json | 11 + vite.config.ts | 77 ++ 30 files changed, 3202 insertions(+) create mode 100644 .github/FUNDING.yml create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/release-distribution.yml create mode 100644 .github/workflows/release-please.yml create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 package.json create mode 100644 public/README.md create mode 100644 public/README_zh_CN.md create mode 100644 public/i18n/en_US.json create mode 100644 public/i18n/zh_CHT.json create mode 100644 public/i18n/zh_CN.json create mode 100644 public/icon.png create mode 100644 public/plugin.json create mode 100644 public/preview.png create mode 100644 src/assets/symbols/icon-wakatime-wakapi.symbol create mode 100644 src/assets/symbols/icon-wakatime.symbol create mode 100644 src/components/Settings.svelte create mode 100644 src/configs/default.ts create mode 100644 src/index.ts create mode 100644 src/types/config.d.ts create mode 100644 src/types/wakatime.d.ts create mode 100644 src/utils/i18n.ts create mode 100644 src/vite-env.d.ts create mode 100644 src/wakatime/heartbeats.ts create mode 100644 svelte.config.js create mode 100644 tsconfig.json create mode 100644 tsconfig.node.json create mode 100644 vite.config.ts diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..5051816 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,36 @@ +# These are supported funding model platforms + + +# Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +# github: + +# Replace with a single Patreon username +# patreon: + +# Replace with a single Open Collective username +# open_collective: + +# Replace with a single Ko-fi username +ko_fi: zuoqiu + +# Replace with a single Tidelift platform-name/package-name e.g., npm/babel +# tidelift: + +# Replace with a single Community Bridge project-name e.g., cloud-foundry +# community_bridge: + +# Replace with a single Liberapay username +# liberapay: + +# Replace with a single IssueHunt username +# issuehunt: + +# Replace with a single Otechie username +# otechie: + +# Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +# lfx_crowdfunding: + +# Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] +custom: + - https://afdian.net/a/zuoqiu diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..692cc44 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,93 @@ +# 构建并部署 | Build and deploy + +name: build + +on: + workflow_dispatch: + push: + tags: + # REF https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet + - "v[0-9]+.[0-9]+.[0-9]+" + +env: + PACKAGE_PATH: ./workspace/plugins/wakatime + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + steps: + # Checkout + # REF https://github.com/marketplace/actions/checkout + - name: Checkout + uses: actions/checkout@v3 + with: + ## 将要拉取的仓库 | repository will to pull + repository: Zuoqiu-Yingyi/siyuan-packages-monorepo + + # Install Node.js + # REF https://github.com/marketplace/actions/setup-node-js-environment + - name: Install Node.js + uses: actions/setup-node@v3 + with: + ## Node.js 版本号 | Node.js version + node-version: 20 + + ## Node.js 源 | Node.js registry + registry-url: https://registry.npmjs.org + + # Install pnpm + # REF https://github.com/marketplace/actions/setup-pnpm + - name: Install pnpm + uses: pnpm/action-setup@v2 + id: pnpm-install + with: + ## pnpm 版本号 | pnpm version + version: 8 + + ## 是否安装 npm 包 | if install npm package? + run_install: false + + # Get pnpm store directory + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + + # Setup pnpm cache + # REF https://github.com/marketplace/actions/cache + - name: Setup pnpm cache + uses: actions/cache@v3 + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + # Install dependencies + - name: Install dependencies + run: | + cd $GITHUB_WORKSPACE + cd ./workspace + pnpm install + + # Build package + - name: Build package + run: | + cd $GITHUB_WORKSPACE + cd $PACKAGE_PATH + pnpm build + + # Deploy to publish branch + # REF https://github.com/marketplace/actions/github-pages + - name: Deploy to publish branch + if: success() + uses: crazy-max/ghaction-github-pages@v3 + with: + ## 构建产物目录 | directory of build artifacts + build_dir: ${{ env.PACKAGE_PATH }}/dist + + ## 提交到目标分支 + target_branch: publish + env: + GITHUB_TOKEN: ${{ secrets.PAT_ACTIONS }} diff --git a/.github/workflows/release-distribution.yml b/.github/workflows/release-distribution.yml new file mode 100644 index 0000000..03ac4a4 --- /dev/null +++ b/.github/workflows/release-distribution.yml @@ -0,0 +1,81 @@ +# 发行构建产物 | Release the distribution + +name: release-distribution + +on: + workflow_dispatch: + # REF https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run + workflow_run: + workflows: + - build + types: + - completed + push: + branches: + - publish + +permissions: + contents: write + +jobs: + release-distribution: + runs-on: ubuntu-latest + steps: + # Checkout + # REF https://github.com/marketplace/actions/checkout + - name: Checkout + uses: actions/checkout@v3 + with: + ref: publish + + # Package + - name: Package + run: | + git archive -o ./package.zip HEAD + + # Get latest release + # REF https://github.com/marketplace/actions/get-latest-release + - name: Get latest release + uses: pozetroninc/github-action-get-latest-release@v0.7.0 + id: latest-release + with: + ## 仓库所有者/仓库名 | owner/name + repository: ${{ github.repository }} + + ## 排除的发行类型 | Excluded types of release + # excludes: prerelease, draft + excludes: draft + + # Get timestamp + # REF https://github.com/marketplace/actions/get-timestamp-action + - name: Get timestamp + uses: nanzm/get-time-action@v1.1 + id: timestamp + with: + ## 时区 | time zone + timeZone: 8 + + ## 时间戳格式 | timestamp format + format: "YYYYMMDDHHmmss" + + # Release distribution + # REF https://github.com/marketplace/actions/gh-release + - name: Release distribution + uses: softprops/action-gh-release@v1 + with: + ## 发行描述 | description of release + body: ${{ steps.latest-release.outputs.description }} + + ## 是否为预发行 | is prelease? + prerelease: true + + ## 标签名称 | tag name + # REF https://semver.org/ + tag_name: ${{ steps.latest-release.outputs.release }}+${{ steps.timestamp.outputs.time }} + + ## 标签关联的提交/分支 | The commit/branch associated with the tag + target_commitish: publish + + ## 附件列表 | attachment list + files: | + package.zip diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 0000000..cd9b577 --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,112 @@ +# 发行源码 | Release the source code + +name: release-please + +on: + workflow_dispatch: + push: + branches: + - main + +permissions: + contents: write + pull-requests: write + +env: + PACKAGE_NAME: custom-fonts + PACKAGE_VERSION: 0.1.0 + +jobs: + release-please: + runs-on: ubuntu-latest + steps: + # Create release + # REF https://github.com/marketplace/actions/release-please-action + - name: Create release + uses: google-github-actions/release-please-action@v3 + id: release + with: + release-type: node + package-name: ${{ env.PACKAGE_NAME }} + release-as: ${{ env.PACKAGE_VERSION }} + + ## A GitHub secret token, the action defaults to using the special secrets.GITHUB_TOKEN + ## REF https://github.com/marketplace/actions/release-please-action#github-credentials + token: ${{ secrets.PAT_ACTIONS }} + + ## branch to open pull release PR against (detected by default) + default-branch: main + + ## Should breaking changes before 1.0.0 produce minor bumps? Default false + bump-minor-pre-major: false + + ## Should feat changes before 1.0.0 produce patch bumps instead of minor bumps? Default false + bump-patch-for-minor-pre-major: false + + ## If set, create releases that are pre-major or pre-release version marked as pre-release on GitHub. Defaults false + prerelease: true + + ## header used within the release PR body, defaults to using :robot: I have created a release *beep* *boop* + pull-request-header: ":robot: A new release will be created" + + ## A JSON formatted String containing to override the outputted changelog sections + changelog-types: |- + [ + { + "type": "build", + "section": "Build System", + "hidden": false + }, + { + "type": "chore", + "section": "Miscellaneous", + "hidden": false + }, + { + "type": "ci", + "section": "Continuous Integration", + "hidden": false + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "feat", + "section": "Features", + "hidden": false + }, + { + "type": "fix", + "section": "Bug Fixes", + "hidden": false + }, + { + "type": "perf", + "section": "Performance Improvements" + }, + { + "type": "refactor", + "section": "Code Refactoring", + "hidden": false + }, + { + "type": "revert", + "section": "Reverts" + }, + { + "type": "style", + "section": "Styles", + "hidden": false + }, + { + "type": "test", + "section": "Tests", + "hidden": false + }, + { + "type": "", + "section": "Other Changes", + "hidden": false + } + ] diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e5fe9d6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# Custom +temp + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0ad25db --- /dev/null +++ b/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5a1ac71 --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +> **[READ ONLY] Subtree split of the [siyuan-packages-monorepo](https://github.com/Zuoqiu-Yingyi/siyuan-packages-monorepo) [/workspace/plugins/wakatime](https://github.com/Zuoqiu-Yingyi/siyuan-packages-monorepo/tree/main/workspace/plugins/wakatime)** + +
+icon + +--- +[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/Zuoqiu-Yingyi/siyuan-plugin-wakatime?include_prereleases&style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime/releases/latest) +[![GitHub Release Date](https://img.shields.io/github/release-date/Zuoqiu-Yingyi/siyuan-plugin-wakatime?style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime/releases/latest) +[![GitHub License](https://img.shields.io/github/license/Zuoqiu-Yingyi/siyuan-plugin-wakatime?style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime/blob/main/LICENSE) +[![GitHub last commit](https://img.shields.io/github/last-commit/Zuoqiu-Yingyi/siyuan-plugin-wakatime?style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime/commits/main) +![GitHub repo size](https://img.shields.io/github/repo-size/Zuoqiu-Yingyi/siyuan-plugin-wakatime?style=flat-square) +![hits](https://hits.b3log.org/Zuoqiu-Yingyi/siyuan-plugin-wakatime.svg) +[![GitHub all releases](https://img.shields.io/github/downloads/Zuoqiu-Yingyi/siyuan-plugin-wakatime/total?style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime/releases) + +--- +
+ +## USER GUIDE + +[简体中文](./public/README_zh_CN.md) \| [English](./public/README.md) + +## DEVELOPER GUIDE + +### RELEASE STEPS + +1. Update the version number in `/package.json` and `/public/plugin.json`, then commit the changes in [monorepo](https://github.com/Zuoqiu-Yingyi/siyuan-packages-monorepo). +2. Run script `./scripts/git-subtree/wakatime/push.ps1` with the folowing command in **monorepo root dir** to push the subtree to sub-repository (`dev` branch). + ```powershell + pwsh -f "./scripts/git-subtree/wakatime/push.ps1" + ``` +3. Create a pull request from `dev` branch to `main` branch in sub-repository. +4. Merge the pull request. +5. Await for the CD workflow `release-please.yml` to complete, it will create a *release pull request* in sub-repository. +6. Merge the *release pull request*, it will create a new *pre-release* with current [changelog](./CHANGELOG.md) and a new *tag* with [semantic version](https://semver.org/) in sub-repository. +7. Await for the CD workflow `build.yml` to complete, it will update the distribution files to `publish` branch in sub-repository. +8. Await for the CD workflow `release-distribution.yml` to complete, it will create a new *pre-release* with an asset named `package.zip` and a new *tag* with timestamp in sub-repository. + +## CHANGELOG + +[CHANGE LOG](./CHANGELOG.md) diff --git a/package.json b/package.json new file mode 100644 index 0000000..33148ea --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "wakatime", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "build:dev": "vite build --sourcemap inline", + "preview": "vite preview", + "check": "svelte-check --tsconfig ./tsconfig.json" + }, + "devDependencies": { + "@sveltejs/vite-plugin-svelte": "^2.4.5", + "@tsconfig/svelte": "^5.0.0", + "less": "^4.2.0", + "svelte": "^4.2.0", + "svelte-check": "^3.5.0", + "svelte-preprocess-less": "^0.4.0", + "tslib": "^2.6.1", + "typescript": "^5.1.6", + "vite": "^4.4.9" + }, + "dependencies": { + "@workspace/components": "workspace:^", + "@workspace/types": "workspace:^", + "@workspace/utils": "workspace:^" + } +} diff --git a/public/README.md b/public/README.md new file mode 100644 index 0000000..d9644f9 --- /dev/null +++ b/public/README.md @@ -0,0 +1,167 @@ +
+icon + +--- +[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/Zuoqiu-Yingyi/siyuan-plugin-wakatime?include_prereleases&style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime/releases/latest) +[![GitHub Release Date](https://img.shields.io/github/release-date/Zuoqiu-Yingyi/siyuan-plugin-wakatime?style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime/releases/latest) +[![GitHub License](https://img.shields.io/github/license/Zuoqiu-Yingyi/siyuan-plugin-wakatime?style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime/blob/main/LICENSE) +[![GitHub last commit](https://img.shields.io/github/last-commit/Zuoqiu-Yingyi/siyuan-plugin-wakatime?style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime/commits/main) +![GitHub repo size](https://img.shields.io/github/repo-size/Zuoqiu-Yingyi/siyuan-plugin-wakatime?style=flat-square) +![hits](https://hits.b3log.org/Zuoqiu-Yingyi/siyuan-plugin-wakatime.svg) +[![GitHub all releases](https://img.shields.io/github/downloads/Zuoqiu-Yingyi/siyuan-plugin-wakatime/total?style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime/releases) + +--- +[简体中文](./README_zh_CN.md) \| English + +--- +
+ +# SiYuan WakaTime + +A plugin for [SiYuan Note](https://github.com/siyuan-note/siyuan) that can use [Wakapi](https://github.com/muety/wakapi) or [WakaTime](https://wakatime.com/) to generate metrics, insights, and time tracking automatically from your editing activity. + +## PREVIEW + +![preview image](https://cdn.jsdelivr.net/gh/Zuoqiu-Yingyi/siyuan-plugin-wakatime/public/preview.png) + +## Q & A + +* How can I protect my personal privacy when using the Wakapi/WakaTime service? + + * The best solution is to deploy the `muety/wakapi` project privately on your own device, which is compatible with most [WakaTime plugins](https://wakatime.com/plugins). + * Customize the following settings options for this plugin: + + * `Wakapi/WakaTime > General Settings > Project Name` + * `Wakapi/WakaTime > Service Settings > Host Name` + * Enable the following settings options for this plugin: + + * `Wakapi/WakaTime > Service Settings > Hide Notebook Name` + * `Wakapi/WakaTime > Service Settings > Hide Document Title` + +## INTRODUCTION + +### Features Introduction + +[WakaTime](https://WakaTime.com/) provides its users with a tracking service for text editing activities. Users can install open-source plugins in their integrated development environments and text editors to submit their editing activities for tracking, analysis, and visualization. + +[Wakapi](https://github.com/muety/wakapi) is an open-source alternative to the [WakaTime](https://github.com/wakatime) project. It also provides its users with a tracking service for text editing activities and is compatible with most [WakaTime plugins](https://wakatime.com/plugins). + +### Settings Introduction + +* `General` + + * `Reset Settings Options` + + * Reset all settings options to their default values. + * After clicking this button, a confirmation dialog will appear. + + * After clicking the confirmation button in the dialog, all options for this plugin will be reset to their default values, and the current interface will be automatically refreshed. +* `Wakapi/WakaTime`: Configure the functionality and service of `Wakapi` or `WakaTime` + + * `General` + + * `Heartbeat Connection` + + * Enable this option to use the API [users/current/heartbeats](https://wakatime.com/developers#heartbeats) to periodically submit activity information to the `Wakapi/WakaTime` service when viewing/editing documents. + * The time interval is set by `Wakapi/WakaTime > General Settings > Push Interval`. + * The submitted information includes: + + * `type`: `"file"` + * `hostname`: Host name + + * If `Wakapi/WakaTime > Service Settings > Host Name` is not empty, a custom host name will be used. + * If `Wakapi/WakaTime > Service Settings > Host Name` is empty, the host name of the device where the Obsidian is running will be used. + * `project`: Project name + + * If `Wakapi/WakaTime > General Settings > Project Name` is not empty, a custom project name will be used. + * If `Wakapi/WakaTime > General Settings > Project Name` is empty, `siyuan-workspace:workspace` will be used as the default project name. + * `branch`: Notebook name or notebook ID + + * When the `Wakapi/WakaTime > Service Settings > Hide Notebook Name` toggle is enabled, it will be the Notebook ID. + * `entity`: Document file path + + * When the `Wakapi/WakaTime > Service Settings > Hide Notebook Name` toggle is enabled, the Notebook Name will be replaced with the Notebook ID. + * When the `Wakapi/WakaTime > Service Settings > Hide Document Title` toggle is enabled, the Document Title will be replaced with the Block ID. + * `language`: File language name + + * If `Wakapi/WakaTime > General Settings > Language Name` is not empty, a custom language name will be used. + * If `Wakapi/WakaTime > General Settings > Language Name` is empty, `Siyuan` will be used as the default language name. + * `category`: User operation type + + * When viewing a note, it is set to the item specified by `Wakapi/WakaTime > General Settings > View Operation Tag`. + * When editing a note, it is set to the item specified by `Wakapi/WakaTime > General Settings > Edit Operation Tag`. + * `time`: Timestamp corresponding to the view/edit operation performed by the user. + * `is_write`: Whether it is an editing operation. + * `Project Name` + + * Customize the name of the current workspace. + * Corresponds to the `Projects` field in the `Wakapi/WakaTime` statistics results. + * If empty, `siyuan-workspace:workspace` will be used as the default project name. + * `Language Name` + + * Customize the language name corresponding to `*.sy` files. + * Corresponds to the `Languages` field in the `Wakapi/WakaTime` statistics results. + * If empty, `Siyuan` will be used as the default language name. + * `Push Interval` + + * If there are user operations (view/edit) within the specified time interval, the operation information will be submitted to the `Wakapi/WakaTime` service using the API [users/current/heartbeats](https://wakatime.com/developers#heartbeats). + * Unit: seconds + * For more details about the submitted information, please refer to `Wakapi/WakaTime > General Settings > Heartbeat Connection`. + * `View Operation Tag` + + * Activity tags corresponding to user view operations + + * Open a document + * Move the cursor focus in the document + * Corresponds to the `Category` in the WakaTime statistics results. + * `Edit Operation Tag` + + * Activity tags corresponding to user editing operations + + * Document content is modified + * Document attributes are modified + * Corresponds to the `Category` in the WakaTime statistics results. + * `Service Settings` + + * `Test` + + * Test whether using the `Wakapi/WakaTime > Service Settings > API Key` can successfully access the service corresponding to the `Wakapi/WakaTime > Service Settings > API URL`. + * `API URL` + + * Customize the API service address for `Wakapi/WakaTime`. + * Corresponds to the `api_url` configuration item in the `Wakapi/WakaTime` configuration file. + * If empty, the service address of `WakaTime` will be used (`https://wakatime.com/api/v1`). + * If using a hosted `Wakapi` service, it should be set to `https://wakapi.dev/api`. + * If using a privately deployed `Wakapi` service, it should be set to `http(s)://host[:port]/api`. + + * Examples + + * `http://localhost:3000/api` + * `https://wakapi.your.domain.name/api` + * Note + + * Therefore, it is necessary to ensure that the device where Obsidian is located can access the set service address. + * `API KEY` + + * Customize the access key for the `Wakapi/WakaTime` API service. + * This is a required field, and if not set, a connection cannot be established with `Wakapi/WakaTime`. + * `Hostname` + + * Customize the device name. + * If empty, the host name of the device where Obsidian is located will be used. + * `Timeout` + + * Timeout duration when calling the `Wakapi/WakaTime` API. + * Unit: seconds + * `Hide Notebook Name` + + * Whether to hide the notebook name in the submitted activity information. + * If enabled, all Notebook Name in the submitted information will be replaced with Notebook ID. + * `Hide Document Title` + + * Whether to hide the document title in the submitted activity information. + * If enabled, all Document Title in the submitted information will be replaced with Block ID. + +## CHANGELOG + +[CHANGELOG.md](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime/blob/main/CHANGELOG.md) diff --git a/public/README_zh_CN.md b/public/README_zh_CN.md new file mode 100644 index 0000000..cd19d3c --- /dev/null +++ b/public/README_zh_CN.md @@ -0,0 +1,167 @@ +
+图标 + +--- +[![GitHub 最新发行版本 (最新一次发行/预发行)](https://img.shields.io/github/v/release/Zuoqiu-Yingyi/siyuan-plugin-wakatime?include_prereleases&style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime/releases/latest) +[![GitHub 最新发行时间](https://img.shields.io/github/release-date/Zuoqiu-Yingyi/siyuan-plugin-wakatime?style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime/releases/latest) +[![GitHub 许可证](https://img.shields.io/github/license/Zuoqiu-Yingyi/siyuan-plugin-wakatime?style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime/blob/main/LICENSE) +[![GitHub 最后一次提交时间](https://img.shields.io/github/last-commit/Zuoqiu-Yingyi/siyuan-plugin-wakatime?style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime/commits/main) +![GitHub 仓库大小](https://img.shields.io/github/repo-size/Zuoqiu-Yingyi/siyuan-plugin-wakatime?style=flat-square) +![查看次数](https://hits.b3log.org/Zuoqiu-Yingyi/siyuan-plugin-wakatime.svg) +[![GitHub 发行版本下载次数](https://img.shields.io/github/downloads/Zuoqiu-Yingyi/siyuan-plugin-wakatime/total?style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime/releases) + +--- +简体中文 \| [English](./README.md) + +--- +
+ +# 思源 WakaTime + +一款可以使用 [Wakapi](https://github.com/muety/wakapi) 或 [WakaTime](https://wakatime.com/) 统计编辑活动的[思源笔记](https://github.com/siyuan-note/siyuan)插件。 + +## 预览 + +![预览图片](https://cdn.jsdelivr.net/gh/Zuoqiu-Yingyi/siyuan-plugin-wakatime/public/preview.png) + +## 常见问题 + +* 如何在使用 `Wakapi/WakaTime` 服务时最大程度保护个人隐私? + + * 最佳解决方案是在您自己的设备中私有化部署 [muety/wakapi](https://github.com/muety/wakapi) 项目, 该项目可以兼容大部分 [WakaTime 插件](https://wakatime.com/plugins) + * 自定义本插件的如下设置选项 + + * `Wakapi/WakaTime > 常规设置 > 项目名称` + * `Wakapi/WakaTime > 服务设置 > 主机名称` + * 开启本插件的如下设置选项 + + * `Wakapi/WakaTime > 服务设置 > 隐藏笔记本名称` + * `Wakapi/WakaTime > 服务设置 > 隐藏文档标题` + +## 介绍 + +### 功能介绍 + +[WakaTime](https://WakaTime.com/) 为其用户提供文本编辑活动的统计服务,用户可以通过在集成开发环境和文本编辑器中安装开源插件以提交自己的编辑活动供其统计、分析与可视化。 + +[Wakapi](https://github.com/muety/wakapi) 是 [WakaTime](https://github.com/wakatime) 项目的开源替代品,同样可以为其用户提供文本编辑活动的统计服务,并兼容大部分 [WakaTime 插件](https://wakatime.com/plugins)。 + +### 设置项介绍 + +* `常规设置` + + * `重置设置选项` + + * 重置所有设置选项为默认选项 + * 点击该按钮后会弹出确认对话框 + + * 点击对话框确认按钮后会重置本插件所有选项为默认选项, 之后会自动刷新当前界面 +* `Wakapi/WakaTime`: 配置 `Wakapi` 或 `WakaTime` 功能与服务 + + * `常规设置` + + * `心跳连接` + + * 开启后将在有查看/编辑文档操作时使用 API [users/current/heartbeats](https://wakatime.com/developers#heartbeats) 定时向 `Wakapi/WakaTime` 服务提交活动信息 + * 时间间隔由 `Wakapi/WakaTime > 常规设置 > 推送时间间隔` 设定 + * 提交的信息包含如下内容 + + * `type`: `"file"` + * `hostname`: 主机名称 + + * 若 `Wakapi/WakaTime > 服务设置 > 主机名称名称` 不为空, 则使用自定义的主机名称 + * 若 `Wakapi/WakaTime > 服务设置 > 主机名称名称` 为空, 则使用思源笔记内核所在设备的主机名称 + * `project`: 项目名称 + + * 若 `Wakapi/WakaTime > 常规设置 > 项目名称` 不为空, 则使用自定义的项目名称 + * 若 `Wakapi/WakaTime > 常规设置 > 项目名称` 为空, 则使用 `siyuan-workspace:<工作空间所在文件夹名称>` + * `branch`: 笔记本名称或笔记本 ID + + * 当 `Wakapi/WakaTime > 服务设置 > 隐藏笔记本名称` 开关开启时为 笔记本 ID + * `entity`: 文档文件路径 + + * 当 `Wakapi/WakaTime > 服务设置 > 隐藏笔记本名称` 开关开启时 笔记本名称 替换为 笔记本 ID + * 当 `Wakapi/WakaTime > 服务设置 > 隐藏文档标题` 开关开启时 文档标题 替换为 文档块 ID + * `language`: 文件语言名称 + + * 若 `Wakapi/WakaTime > 常规设置 > 语言名称` 不为空, 则使用自定义的语言名称 + * 若 `Wakapi/WakaTime > 常规设置 > 语言名称` 为空, 则使用 `Siyuan` + * `category`: 用户操作类型 + + * 查看笔记时为 `Wakapi/WakaTime > 常规设置 > 查看操作标签` 所设置的项 + * 编辑笔记时为 `Wakapi/WakaTime > 常规设置 > 编辑操作标签` 所设置的项 + * `time`: 用户进行查看/编辑操作时对应的时间戳 + * `is_write`: 是否为编辑操作 + * `项目名称` + + * 自定义当前工作空间的名称 + * 对应 `Wakapi/WakaTime` 统计结果中的 `Projects` 字段 + * 若为空, 则使用 `siyuan-workspace:<工作空间所在文件夹名称>` 作为默认的项目名称 + * `语言名称` + + * 自定义 `*.sy` 文件对应的语言名称 + * 对应 `Wakapi/WakaTime` 统计结果中的 `Languages` 字段 + * 若为空, 则使用 `Siyuan` 作为默认的语言名称 + * `推送时间间隔` + + * 在指定的时间间隔内若存在用户操作(查看/编辑), 则使用 API [users/current/heartbeats](https://wakatime.com/developers#heartbeats) 向 `Wakapi/WakaTime` 服务提交操作信息 + * 单位: 秒 + * 提交的信息详情请参考 `Wakapi/WakaTime > 常规设置 > 心跳连接` + * `查看操作标签` + + * 用户查看操作对应的活动标签 + + * 打开某一篇文档 + * 光标焦点在文档中移动 + * 对应 `WakaTime` 统计结果中的 `Category` + * `编辑操作标签` + + * 用户编辑操作对应的活动标签 + + * 文档内容发生更改 + * 文档属性发生更改 + * 对应 `WakaTime` 统计结果中的 `Category` + * `服务设置` + + * `测试` + + * 测试使用 `Wakapi/WakaTime > 服务设置 > API 密钥` 能否成功访问 `Wakapi/WakaTime > 服务设置 > API URL` 对应的服务 + * `API URL` + + * 自定义 `Wakapi/WakaTime` API 服务地址 + * 对应 `Wakapi/WakaTime` 配置文件中的 `api_url` 配置项 + * 若为空, 则使用 `WakaTime` 的服务地址 `https://wakatime.com/api/v1` + * 若使用托管的 `Wakapi` 服务, 应设置为 `https://wakapi.dev/api` + * 若使用私有部署的 `Wakapi` 服务, 应设置为 `http(s)://host[:port]/api` + + * 示例 + + * `http://localhost:3000/api` + * `https://wakapi.your.domain.name/api` + * 注意 + + * 故需要保证思源内核所在的设备能够访问所设置的服务地址 + * `API 密钥` + + * 自定义 `Wakapi/WakaTime` API 服务访问密钥 + * 必填项, 若未设置则无法与 `Wakapi/WakaTime` 建立连接 + * `主机名称` + + * 自定义设备名称 + * 若为空, 则使用思源内核所在设备的主机名 + * `超时时间` + + * 调用 `Wakapi/WakaTime` API 时的超时时间 + * 单位: 秒 + * `隐藏笔记本名称` + + * 在提交的操作活动信息中是否隐藏笔记本名称 + * 若开启, 则提交的信息中所有 笔记本名称 都替换为 笔记本 ID + * `隐藏文档标题` + + * 在提交的操作活动信息中是否隐藏文档标题 + * 若开启, 则提交的信息中所有 文档标题 都替换为 文档块 ID + +## 更改日志 + +[CHANGELOG.md](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime/blob/main/CHANGELOG.md) diff --git a/public/i18n/en_US.json b/public/i18n/en_US.json new file mode 100644 index 0000000..612d9d3 --- /dev/null +++ b/public/i18n/en_US.json @@ -0,0 +1,79 @@ +{ + "displayName": "WakaTime", + "settings": { + "generalSettings": { + "reset": { + "description": "Reset all settings options to default options (refresh page after reset)", + "text": "Reset", + "title": "Reset settings options" + }, + "title": "General" + }, + "wakatimeSettings": { + "generalTab": { + "editCategory": { + "description": "Activity type tags for editing operations", + "title": "Edit operation tags" + }, + "heartbeats": { + "description": "Enable to submit activity information to Wakapi/WakaTime service while viewing/editing documents", + "title": "Heartbeat connection" + }, + "interval": { + "description": "Time interval (in seconds) to push editing activities to Wakapi/WakaTime server", + "title": "Push interval" + }, + "language": { + "description": "Custom language name for Source file
Corresponds to Languages in Wakapi/WakaTime statistics", + "title": "Language name" + }, + "project": { + "description": "Custom current workspace name
Corresponds to Projects in Wakapi/WakaTime statistics", + "title": "Project name" + }, + "title": "General", + "viewCategory": { + "description": "Activity type tags for viewing operations", + "title": "View operation tags" + } + }, + "serviceTab": { + "apiKey": { + "description": "Wakapi/WakaTime API KEY
Corresponds to api_key in Wakapi/WakaTime configuration", + "title": "API KEY" + }, + "apiURL": { + "description": "Wakapi/WakaTime API URL
Corresponds to api_url in Wakapi/WakaTime configuration", + "title": "API URL" + }, + "hide_branch_names": { + "description": "Whether to hide notebook names. If enabled, the notebook name is replaced with the notebook ID
Corresponds to hide_branch_names in Wakapi/WakaTime configuration", + "title": "Hide notebook names" + }, + "hide_file_names": { + "description": "Whether to hide document titles. If enabled, the document title is replaced with the document block ID
Corresponds to hide_file_names in Wakapi/WakaTime configuration", + "title": "Hide document titles" + }, + "hostname": { + "description": "Custom current host name
Corresponds to hostname in Wakapi/WakaTime configuration", + "title": "Hostname" + }, + "test": { + "description": "Test if connected to Wakapi/WakaTime service correctly", + "messages": { + "error": "Cannot establish connection to ${1} service", + "success": "Connection to ${1} service is successful" + }, + "text": "Test", + "title": "Test Wakapi/WakaTime service" + }, + "timeout": { + "description": "Wakapi/WakaTime API request timeout
Corresponds to timeout in Wakapi/WakaTime configuration", + "title": "Timeout" + }, + "title": "Service" + }, + "title": "Wakapi/WakaTime" + } + } +} diff --git a/public/i18n/zh_CHT.json b/public/i18n/zh_CHT.json new file mode 100644 index 0000000..0fc92ba --- /dev/null +++ b/public/i18n/zh_CHT.json @@ -0,0 +1,79 @@ +{ + "displayName": "WakaTime", + "settings": { + "generalSettings": { + "reset": { + "description": "重置所有設定選項為預設選項(重置後將重新整理頁面)", + "text": "重置", + "title": "重置設定選項" + }, + "title": "常規設定" + }, + "wakatimeSettings": { + "generalTab": { + "editCategory": { + "description": "為編輯操作設定的活動型別標籤", + "title": "編輯操作標籤" + }, + "heartbeats": { + "description": "開啟後將在檢視/編輯文件時向 Wakapi/WakaTime 服務提交活動資訊", + "title": "心跳連線" + }, + "interval": { + "description": "將編輯活動推送到 Wakapi/WakaTime 伺服器的時間間隔(單位:秒)", + "title": "推送時間間隔" + }, + "language": { + "description": "自定義思原始檔語言名稱
對應 Wakapi/WakaTime 統計中的 Languages 項", + "title": "語言名稱" + }, + "project": { + "description": "自定義當前工作空間名稱
對應 Wakapi/WakaTime 統計中的 Projects 項", + "title": "项目名稱" + }, + "title": "常規設定", + "viewCategory": { + "description": "為檢視操作設定的活動型別標籤", + "title": "檢視操作標籤" + } + }, + "serviceTab": { + "apiKey": { + "description": "Wakapi/WakaTime API 金鑰
對應 Wakapi/WakaTime 配置中的 api_key", + "title": "API 金鑰" + }, + "apiURL": { + "description": "Wakapi/WakaTime API URL
對應 Wakapi/WakaTime 配置中的 api_url", + "title": "API URL" + }, + "hide_branch_names": { + "description": "是否隱藏筆記本名稱,開啟後將使用筆記本 ID 替換筆記本名稱
對應 Wakapi/WakaTime 配置中的 hide_branch_names", + "title": "隱藏筆記本名稱" + }, + "hide_file_names": { + "description": "是否隱藏文件標題,開啟後將使用文件塊 ID 替換文件標題
對應 Wakapi/WakaTime 配置中的 hide_file_names", + "title": "隱藏文件標題" + }, + "hostname": { + "description": "自定義當前主機名稱
對應 Wakapi/WakaTime 配置中的 hostname", + "title": "主機名稱" + }, + "test": { + "description": "測試是否正確連線到 Wakapi/WakaTime 服務", + "messages": { + "error": "無法與 ${1} 服務建立連線", + "success": "與 ${1} 服務的連線正常" + }, + "text": "測試", + "title": "測試 Wakapi/WakaTime 服務" + }, + "timeout": { + "description": "Wakapi/WakaTime API 請求超時時間
對應 Wakapi/WakaTime 配置中的 timeout", + "title": "超時時間" + }, + "title": "服務設定" + }, + "title": "Wakapi/WakaTime" + } + } +} diff --git a/public/i18n/zh_CN.json b/public/i18n/zh_CN.json new file mode 100644 index 0000000..fd119a1 --- /dev/null +++ b/public/i18n/zh_CN.json @@ -0,0 +1,79 @@ +{ + "displayName": "WakaTime", + "settings": { + "generalSettings": { + "reset": { + "description": "重置所有设置选项为默认选项(重置后将刷新页面)", + "text": "重置", + "title": "重置设置选项" + }, + "title": "常规设置" + }, + "wakatimeSettings": { + "generalTab": { + "editCategory": { + "description": "为编辑操作设置的活动类型标签", + "title": "编辑操作标签" + }, + "heartbeats": { + "description": "开启后将在查看/编辑文档时向 Wakapi/WakaTime 服务提交活动信息", + "title": "心跳连接" + }, + "interval": { + "description": "将编辑活动推送到 Wakapi/WakaTime 服务器的时间间隔(单位:秒)", + "title": "推送时间间隔" + }, + "language": { + "description": "自定义思源文件语言名称
对应 Wakapi/WakaTime 统计中的 Languages 项", + "title": "语言名称" + }, + "project": { + "description": "自定义当前工作空间名称
对应 Wakapi/WakaTime 统计中的 Projects 项", + "title": "项目名称" + }, + "title": "常规设置", + "viewCategory": { + "description": "为查看操作设置的活动类型标签", + "title": "查看操作标签" + } + }, + "serviceTab": { + "apiKey": { + "description": "Wakapi/WakaTime API 密钥
对应 Wakapi/WakaTime 配置中的 api_key", + "title": "API 密钥" + }, + "apiURL": { + "description": "Wakapi/WakaTime API URL
对应 Wakapi/WakaTime 配置中的 api_url", + "title": "API URL" + }, + "hide_branch_names": { + "description": "是否隐藏笔记本名称,开启后将使用笔记本 ID 替换笔记本名称
对应 Wakapi/WakaTime 配置中的 hide_branch_names", + "title": "隐藏笔记本名称" + }, + "hide_file_names": { + "description": "是否隐藏文档标题,开启后将使用文档块 ID 替换文档标题
对应 Wakapi/WakaTime 配置中的 hide_file_names", + "title": "隐藏文档标题" + }, + "hostname": { + "description": "自定义当前主机名称
对应 Wakapi/WakaTime 配置中的 hostname", + "title": "主机名称" + }, + "test": { + "description": "测试是否正确连接到 Wakapi/WakaTime 服务", + "messages": { + "error": "无法与 ${1} 服务建立连接", + "success": "与 ${1} 服务的连接正常" + }, + "text": "测试", + "title": "测试 Wakapi/WakaTime 服务" + }, + "timeout": { + "description": "Wakapi/WakaTime API 请求超时时间
对应 Wakapi/WakaTime 配置中的 timeout", + "title": "超时时间" + }, + "title": "服务设置" + }, + "title": "Wakapi/WakaTime" + } + } +} diff --git a/public/icon.png b/public/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..30299e14fd6739909c5267b05fda1f3adaf9f5e0 GIT binary patch literal 3868 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 M>l(wW@7P8DAHeHL=>Px# literal 0 HcmV?d00001 diff --git a/public/plugin.json b/public/plugin.json new file mode 100644 index 0000000..195a0f6 --- /dev/null +++ b/public/plugin.json @@ -0,0 +1,35 @@ +{ + "name": "wakatime", + "author": "Zuoqiu Yingyi", + "url": "https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime", + "version": "0.1.0", + "minAppVersion": "2.9.9", + "backends": [ + "all" + ], + "frontends": [ + "all" + ], + "displayName": { + "default": "WakaTime" + }, + "description": { + "default": "Use Wakapi or WakaTime to count your editing Activity", + "zh_CN": "使用 WakapiWakaTime 统计您的编辑活动", + "zh_CHT": "使用 WakapiWakaTime 統計您的編輯活動" + }, + "readme": { + "default": "README.md", + "zh_CN": "README_zh_CN.md", + "zh_CHT": "README_zh_CN.md" + }, + "funding": { + "openCollective": "", + "patreon": "", + "github": "", + "custom": [ + "https://afdian.net/a/zuoqiu", + "https://ko-fi.com/zuoqiu" + ] + } +} diff --git a/public/preview.png b/public/preview.png new file mode 100644 index 0000000000000000000000000000000000000000..4fbf81c58e944f70b48678cdf2bae4574f730d27 GIT binary patch literal 67702 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

rra=id79&FKMDrMQzt! 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 C#UK#? literal 0 HcmV?d00001 diff --git a/src/assets/symbols/icon-wakatime-wakapi.symbol b/src/assets/symbols/icon-wakatime-wakapi.symbol new file mode 100644 index 0000000..90e1819 --- /dev/null +++ b/src/assets/symbols/icon-wakatime-wakapi.symbol @@ -0,0 +1,117 @@ + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/symbols/icon-wakatime.symbol b/src/assets/symbols/icon-wakatime.symbol new file mode 100644 index 0000000..e4be9e6 --- /dev/null +++ b/src/assets/symbols/icon-wakatime.symbol @@ -0,0 +1,19 @@ + + + + + diff --git a/src/components/Settings.svelte b/src/components/Settings.svelte new file mode 100644 index 0000000..6b473b1 --- /dev/null +++ b/src/components/Settings.svelte @@ -0,0 +1,429 @@ + + + + + + + + + + + + + + + + + + + +
+ + + { + config.wakatime.heartbeats = e.detail.value; + await updated(); + }} + /> + + + + + { + config.wakatime.project = e.detail.value; + await updated(); + }} + /> + + + + + { + config.wakatime.language = e.detail.value; + await updated(); + }} + /> + + + + + { + config.wakatime.interval = e.detail.value; + await updated(); + }} + /> + + + + + { + config.wakatime.view.category = e.detail.value; + await updated(); + }} + /> + + + + + { + config.wakatime.edit.category = e.detail.value; + await updated(); + }} + /> + +
+ + +
+ + + + + + + + { + config.wakatime.api_url = e.detail.value; + await updated(); + await testService(); + }} + /> + + + + + { + config.wakatime.api_key = e.detail.value; + await updated(); + await testService(); + }} + /> + + + + + { + config.wakatime.hostname = e.detail.value; + await updated(); + }} + /> + + + + + { + config.wakatime.timeout = e.detail.value; + await updated(); + }} + /> + + + + + { + config.wakatime.hide_branch_names = e.detail.value; + await updated(); + }} + /> + + + + + { + config.wakatime.hide_file_names = e.detail.value; + await updated(); + }} + /> + +
+
+
+
+ + diff --git a/src/configs/default.ts b/src/configs/default.ts new file mode 100644 index 0000000..4164e83 --- /dev/null +++ b/src/configs/default.ts @@ -0,0 +1,42 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import type { IConfig } from "@/types/config"; +import { Category } from "@/wakatime/heartbeats"; + +export const DEFAULT_CONFIG: IConfig = { + wakatime: { + api_url: "", + api_key: "", + timeout: 30, + hide_branch_names: true, + hide_file_names: true, + + heartbeats: false, + project: "", + language: "", + hostname: "", + interval: 60, + + view: { + category: Category.Browsing, + }, + edit: { + category: Category.Learning, + }, + }, +} as const; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..ae243a0 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,540 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import siyuan from "siyuan"; + +import icon_wakatime from "./assets/symbols/icon-wakatime.symbol?raw"; +import icon_wakatime_wakapi from "./assets/symbols/icon-wakatime-wakapi.symbol?raw"; +import manifest from "~/public/plugin.json"; + +import { + Client, + type types, +} from "@siyuan-community/siyuan-sdk"; + +import Settings from "./components/Settings.svelte"; + +import { + FLAG_ELECTRON, + FLAG_DESKTOP, + FLAG_MOBILE, +} from "@workspace/utils/env/front-end"; +import { Logger } from "@workspace/utils/logger"; +import { mergeIgnoreArray } from "@workspace/utils/misc/merge"; +import { parse } from "@workspace/utils/path/browserify"; +import { normalize } from "@workspace/utils/path/normalize"; +import { DEFAULT_CONFIG } from "./configs/default"; +import { Type } from "./wakatime/heartbeats"; +import type { IConfig } from "./types/config"; +import type { + Heartbeats, + Context, +} from "./types/wakatime"; +import type { + IWebSocketMainEvent, + IClickEditorContentEvent, + ILoadedProtyleEvent, +} from "@workspace/types/siyuan/events"; +import type { ITransaction } from "@workspace/types/siyuan/transaction"; +import type { BlockID } from "@workspace/types/siyuan"; +import type { IProtyle } from "@workspace/types/siyuan/protyle"; + +type INotebook = types.kernel.api.notebook.lsNotebooks.INotebook; + +export default class WakaTimePlugin extends siyuan.Plugin { + static readonly GLOBAL_CONFIG_NAME = "global-config"; + + static readonly WAKATIME_DEFAULT_API_URL = "https://wakatime.com/api/v1"; + static readonly WAKATIME_HEARTBEATS_PATH = "users/current/heartbeats"; + static readonly WAKATIME_STATUS_BAR_PATH = "users/current/statusbar/today"; + + public readonly siyuan = siyuan; + public readonly logger: InstanceType; + public readonly client: InstanceType; + public readonly notebook = new Map(); // 笔记本 ID => 笔记本信息 + + protected readonly SETTINGS_DIALOG_ID: string; + protected readonly context: Context.IContext; // 心跳连接上下文 + + public config: IConfig; + protected timer: number; // 定时器 + + constructor(options: any) { + super(options); + + this.logger = new Logger(this.name); + this.client = new Client(undefined, "fetch"); + + this.SETTINGS_DIALOG_ID = `${this.name}-settings-dialog`; + this.context = { + url: this.wakatimeHeartbeatsUrl, + method: "POST", + project: this.wakatimeProject, + language: this.wakatimeLanguage, + headers: this.wakatimeHeaders, + blocks: new Map(), + roots: new Map(), + actions: new Array(), + }; + } + + onload(): void { + // this.logger.debug(this); + + /* 注册图标 */ + this.addIcons([ + icon_wakatime, + icon_wakatime_wakapi, + ].join("")); + + this.loadData(WakaTimePlugin.GLOBAL_CONFIG_NAME) + .then(config => { + this.config = mergeIgnoreArray(DEFAULT_CONFIG, config || {}) as IConfig; + }) + .catch(error => this.logger.error(error)) + .finally(() => { + this.updateTimer(); + this.updateContext(); + this.updateNotebook(); + + /* 总线 */ + this.eventBus.on("ws-main", this.webSocketMainEventListener); + + /* 编辑器加载 */ + this.eventBus.on("loaded-protyle", this.loadedProtyleEventListener); + + /* 编辑区点击 */ + this.eventBus.on("click-editorcontent", this.clickEditorContentEventListener); + + }); + } + + onLayoutReady(): void { + } + + onunload(): void { + this.eventBus.off("ws-main", this.webSocketMainEventListener); + this.eventBus.off("loaded-protyle", this.loadedProtyleEventListener); + this.eventBus.off("click-editorcontent", this.clickEditorContentEventListener); + + clearInterval(this.timer); + this.commit(); + } + + openSetting(): void { + const that = this; + const dialog = new siyuan.Dialog({ + title: `${this.i18n.displayName} ${this.name}`, + content: `
`, + width: FLAG_MOBILE ? "92vw" : "720px", + height: FLAG_MOBILE ? undefined : "640px", + }); + const settings = new Settings({ + target: dialog.element.querySelector(`#${that.SETTINGS_DIALOG_ID}`), + props: { + config: this.config, + plugin: this, + }, + }); + } + + /* 重置插件配置 */ + public async resetConfig(): Promise { + return this.updateConfig(mergeIgnoreArray(DEFAULT_CONFIG) as IConfig); + } + + /* 更新插件配置 */ + public async updateConfig(config?: IConfig): Promise { + if (config && config !== this.config) { + this.config = config; + } + this.updateTimer(); + this.updateContext(); + return this.saveData(WakaTimePlugin.GLOBAL_CONFIG_NAME, this.config); + } + + /* 更新定时器 */ + public updateTimer(interval: number = this.config.wakatime.interval) { + if (this.timer) { + clearInterval(this.timer); + } + this.timer = setInterval(this.commit, interval * 1_000); + } + + /* 更新 wakatime 请求上下文 */ + public updateContext() { + this.context.url = this.wakatimeHeartbeatsUrl; + this.context.project = this.wakatimeProject; + this.context.language = this.wakatimeLanguage; + this.context.headers = this.wakatimeHeaders; + } + + /* 更新 notebook */ + public updateNotebook(notebooks: INotebook[] = globalThis.siyuan?.notebooks) { + if (Array.isArray(notebooks)) { + notebooks.forEach(notebook => this.notebook.set(notebook.id, notebook)); + } + } + + /* 提交活动 */ + protected readonly commit = async () => { + const roots = Array.from(this.context.roots.values()); + this.context.blocks.clear(); + this.context.roots.clear(); + + const actions = await this.buildHeartbeats(roots); + this.context.actions.push(...actions); + + if (this.context.actions.length > 0) { + if (this.config.wakatime.heartbeats) { // 是否发送心跳连接 + // WakaTime 限制一次最多提交 25 条记录 + for (let i = 0; i < this.context.actions.length; i += 25) { + this.sentHeartbeats(this.context.actions.slice(i, i + 25)); + } + } + this.context.actions.length = 0; + } + }; + + /* 总线事件监听器 */ + protected readonly webSocketMainEventListener = (e: IWebSocketMainEvent) => { + // this.logger.debug(e); + if (e.detail.cmd === "transactions") { + const transactions = e.detail.data as ITransaction[]; + + /* 获取所有更改的块 ID */ + transactions?.forEach(transaction => { + transaction.doOperations?.forEach(operation => { + if (operation.id) { + this.addEditEvent(operation.id); + } + }); + transaction.doOperations?.forEach(operation => { + if (operation.id) { + this.addEditEvent(operation.id); + } + }); + }); + } + } + + /* 编辑器加载事件监听器 */ + protected readonly loadedProtyleEventListener = (e: ILoadedProtyleEvent) => { + // this.logger.debug(e); + const protyle = e.detail; + this.addViewEvent(protyle); + } + + /* 编辑器点击事件监听器 */ + protected readonly clickEditorContentEventListener = (e: IClickEditorContentEvent) => { + // this.logger.debug(e); + const protyle = e.detail.protyle; + this.addViewEvent(protyle); + } + + /* 添加编辑事件 */ + protected async addEditEvent(id: BlockID): Promise { + const time = this.now; + + /* 获取块对应的文档信息 */ + let root_id = this.context.blocks.get(id); + let root_info = this.context.roots.get(root_id); + if (!root_info) { + const block_info = await this.client.getBlockInfo({ id }); + + root_id = block_info.data.rootID; + root_info = { + id: root_id, + box: block_info.data.box, + path: block_info.data.path, + events: [], + }; + + this.context.blocks.set(id, root_id); + this.context.roots.set(root_id, root_info); + } + + /* 添加编辑事件 */ + return this.addEvent({ + id: root_info.id, + box: root_info.box, + path: root_info.path, + time, + is_write: true, + }); + } + + /* 添加查看事件 */ + protected addViewEvent(protyle: IProtyle): Context.IRoot | undefined { + const time = this.now; + + if (protyle.notebookId && protyle.path && protyle.block.rootID) { + const root_id = protyle.block.rootID; + this.context.blocks.set(root_id, root_id); + return this.addEvent({ + id: root_id, + box: protyle.notebookId, + path: protyle.path, + time, + is_write: false, + }); + } + } + + /* 添加事件 */ + protected addEvent(options: Omit & Context.IEvent): Context.IRoot { + let root = this.context.roots.get(options.id); + if (root) { + const event: Context.IEvent = { + time: options.time, + is_write: options.is_write, + }; + + /* 如果上一个事件为同类型的事件, 替换该事件 */ + if (root.events.at(-1)?.is_write === event.is_write) { + root.events.pop(); + } + root.events.push(event); + } + else { + root = { + id: options.id, + box: options.box, + path: options.path, + events: [{ + time: options.time, + is_write: options.is_write, + }], + }; + this.context.roots.set(options.id, root); + } + return root; + } + + /** + * 从块 ID 构造心跳连接 + * @deprecated + * @param id 块 ID + * @param is_write 是否为编辑活动 + * @returns 心跳连接活动 + */ + public async buildHeartbeatsFromID(id: BlockID | BlockID[], is_write: boolean): Promise { + const time = this.now; // 当前时间 + + if (!Array.isArray(id)) { + id = [id]; + } + + /* 获取块所在文档的信息 */ + const ids = Array.from(new Set(id)); // 块去重 + const blocks_info = await Promise.all(ids.map(id => this.client.getBlockInfo({ id }))); + + const root_set = new Set(); + const root_blocks = blocks_info.filter(info => { + if (!root_set.has(info.data.rootID)) { + root_set.add(info.data.rootID); + return true; + } + return false; + }); // 文档块去重 + + return Promise.all(root_blocks.map(doc => { + return this.buildHeartbeat( + doc.data, + time, + is_write, + ); + })); + } + + /** + * 构造心跳连接 + * @param roots 文档信息 + * @returns 心跳连接活动 + */ + public async buildHeartbeats(roots: Context.IRoot[]): Promise { + return Promise.all(roots.flatMap(root => { + return root.events.map(event => this.buildHeartbeat( + root, + event.time, + event.is_write, + )); + })); + } + + /** + * 构建一个心跳连接 + * @param doc 文档信息 + * @param time 时间 + * @param is_write 是否写入 + */ + public async buildHeartbeat( + doc: { + box: BlockID, + path: string, + }, + time: number, + is_write: boolean, + ): Promise { + const branch = this.config.wakatime.hide_branch_names + ? doc.box + : this.notebook.get(doc.box)?.name; + const entity = this.config.wakatime.hide_file_names + ? `${branch}${doc.path}` + : `${branch}${(await this.client.getHPathByPath({ + path: doc.path, + notebook: doc.box, + })).data}.sy`; + + return { + type: Type.File, + category: is_write + ? this.config.wakatime.edit.category + : this.config.wakatime.view.category, + + project: this.context.project, + branch, + entity, + language: this.context.language, + time, + is_write, + }; + } + + /** + * 发送心跳连接 + * REF: https://wakatime.com/developers#heartbeats + */ + public async sentHeartbeats(payload: Heartbeats.IAction | Heartbeats.IAction[]) { + return this.client.forwardProxy({ + url: Array.isArray(payload) + ? `${this.context.url}.bulk` + : this.context.url, + method: this.context.method, + headers: [ + this.context.headers, + ], + timeout: this.config.wakatime.timeout * 1_000, + payload, + }); + } + + /* 测试服务状态 */ + public async testService(): Promise { + try { + const response = await this.client.forwardProxy({ + url: this.wakatimeStatusBarUrl, + method: "GET", + headers: [ + this.context.headers, + ], + timeout: this.config.wakatime.timeout * 1_000, + }); + if (200 <= response.data.status && response.data.status < 300) return true; + else { + this.logger.warn(response); + return false; + }; + } catch (error) { + return false; + } + } + + /* 获取时间戳 */ + public time(date: Date = new Date()): number { + return date.getTime() / 1_000; + } + + /* 获取当前时间戳 */ + public get now(): number { + return this.time(); + } + + /* default project name */ + public get wakatimeDefaultProject(): string { + return `siyuan-workspace:${parse(normalize(globalThis.siyuan.config.system.workspaceDir)).base}`; + } + + /* default language name */ + public get wakatimeDefaultLanguage(): string { + return "Siyuan"; + } + + /* default API URL */ + public get wakatimeDefaultApiUrl(): string { + return WakaTimePlugin.WAKATIME_DEFAULT_API_URL; + } + + /* default hostname */ + public get wakatimeDefaultHostname(): string { + return globalThis.siyuan.config.system.name; + } + + /* wakatime project */ + public get wakatimeProject(): string { + return this.config?.wakatime?.project + || this.wakatimeDefaultProject; + } + + /* wakatime language */ + public get wakatimeLanguage(): string { + return this.config?.wakatime?.language + || this.wakatimeDefaultLanguage; + } + + public get wakatimeHeaders(): Context.IHeaders { + return { + "Authorization": this.wakatimeAuthorization, + "User-Agent": this.wakatimeUserAgent, + "X-Machine-Name": this.wakatimeHostname, + }; + } + + /* wakatime user agent */ + public get wakatimeUserAgent(): string { + return `wakatime/v${globalThis.siyuan.config.system.kernelVersion + } ${globalThis.siyuan.config.system.os + }-${globalThis.process?.arch || "unknown" + } siyuan-wakatime/${manifest.version + }`; + } + + /* wakatime API URL */ + public get wakatimeApiUrl(): string { + return this.config?.wakatime?.api_url || this.wakatimeDefaultApiUrl; + } + + /* wakatime url */ + public get wakatimeHeartbeatsUrl(): string { + return `${this.wakatimeApiUrl}/${WakaTimePlugin.WAKATIME_HEARTBEATS_PATH}`; + } + + /* wakatime url */ + public get wakatimeStatusBarUrl(): string { + return `${this.wakatimeApiUrl}/${WakaTimePlugin.WAKATIME_STATUS_BAR_PATH}`; + } + + /* wakatime Authorization */ + public get wakatimeAuthorization(): string { + return `Basic ${btoa(this.config?.wakatime?.api_key)}`; + } + + /* wakatime Hostname */ + public get wakatimeHostname(): string { + return this.config?.wakatime.hostname || this.wakatimeDefaultHostname; + } +}; diff --git a/src/types/config.d.ts b/src/types/config.d.ts new file mode 100644 index 0000000..a5a26a4 --- /dev/null +++ b/src/types/config.d.ts @@ -0,0 +1,44 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import type { Category } from "@/wakatime/heartbeats"; + +/* 活动 */ +export interface IActivity { + category: Category; +} + +export interface IWakaTime { + api_url: string; // API URL + api_key: string; // API KEY + timeout: number; // 请求超时时间 (单位: s) + hide_branch_names: boolean; // 是否隐藏笔记本名 (使用笔记本 ID 代替) + hide_file_names: boolean; // 是否隐藏文件路径 (使用文档 ID 代替) + + heartbeats: boolean; // 是否开启心跳连接 + project: string; // 项目名称 + language: string; // 语言名称 + hostname: string; // 设备名 + interval: number; // 推送时间间隔 (单位: s) + + view: IActivity; // 查看活动 + edit: IActivity; // 编辑活动 +} + +export interface IConfig { + wakatime: IWakaTime; +} diff --git a/src/types/wakatime.d.ts b/src/types/wakatime.d.ts new file mode 100644 index 0000000..82011b9 --- /dev/null +++ b/src/types/wakatime.d.ts @@ -0,0 +1,100 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import type { BlockID } from "@workspace/types/siyuan"; +import type { Category, Type } from "@/wakatime/heartbeats"; + +/** + * 心跳连接 + * REF: https://wakatime.com/developers#heartbeats + * REF: https://github.com/wakatime/browser-wakatime/blob/master/src/types/heartbeats.ts + */ +export namespace Heartbeats { + export interface IAction { + // , + entity: string; + + // , + type: Type; + + // , + category?: Category; + + // , + time: number; + + // , + project?: string; + + // , + project_root_count?: number; + + // , + branch?: string; + + // , + language?: string; + + // , + dependencies?: string; + + // , + lines?: number; + + // , + lineno?: number; + + // , + cursorpos?: number; + + // , + is_write?: boolean; + } +} + +export namespace Context { + export interface IHeaders { + "Authorization": string; // API KEY + "User-Agent": string; // System + Version + Editor + "X-Machine-Name": string; // Machine Name + [key: string]: string; + } + + export interface IEvent { + time: number; // UNIX 时间戳 (单位: s) + is_write: boolean; // 是否写入 + } + + export interface IRoot { + id: BlockID; // 文档 ID + box: BlockID; // 笔记本 ID + path: string; // 文档路径 + events: IEvent[]; // 事件 + } + + export interface IContext { + url: string; + method: "POST"; + project: string; + language: string; + headers: IHeaders; + blocks: Map; // block -> root + roots: Map; // root -> { box, path } + actions: Heartbeats.IAction[]; // 待提交的活动 + } +} + diff --git a/src/utils/i18n.ts b/src/utils/i18n.ts new file mode 100644 index 0000000..c5b0430 --- /dev/null +++ b/src/utils/i18n.ts @@ -0,0 +1,33 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { + i18nCheck, + i18nChecks, +} from "@workspace/types/siyuan/i18n"; + +import zh_Hans from "~/public/i18n/zh_CN.json"; +import zh_Hant from "~/public/i18n/zh_CHT.json"; +import en from "~/public/i18n/en_US.json"; + +export type I18N = typeof zh_Hans; + +i18nChecks([ + i18nCheck(), + i18nCheck(), + i18nCheck(), +]); diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..4078e74 --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/src/wakatime/heartbeats.ts b/src/wakatime/heartbeats.ts new file mode 100644 index 0000000..2535621 --- /dev/null +++ b/src/wakatime/heartbeats.ts @@ -0,0 +1,41 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation + * either version 3 of the + * License + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not + * see . + */ + +export enum Category { + Coding = "coding", + Building = "building", + Indexing = "indexing", + Debugging = "debugging", + Browsing = "browsing", + RunningTests = "running tests", + WritingTests = "writing tests", + ManualTesting = "manual testing", + WritingDocs = "writing docs", + CodeReviewing = "code reviewing", + Researching = "researching", + Learning = "learning", + Designing = "designing", +} + +export enum Type { + App = "app", + File = "file", + Domain = "domain", +} diff --git a/svelte.config.js b/svelte.config.js new file mode 100644 index 0000000..a7db43f --- /dev/null +++ b/svelte.config.js @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + // Consult https://svelte.dev/docs#compile-time-svelte-preprocess + // for more information about preprocessors + preprocess: vitePreprocess(), +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..228eb95 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,38 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "module": "ESNext", + "resolveJsonModule": true, + /** + * Typecheck JS in `.svelte` and `.js` files by default. + * Disable checkJs if you'd like to use dynamic types in JS. + * Note that setting allowJs false does not prevent the use + * of JS in `.svelte` files. + */ + "allowJs": true, + "checkJs": true, + "isolatedModules": true, + "baseUrl": "./", + "paths": { + "~/*": [ + "./*", + ], + "@/*": [ + "src/*", + ], + }, + }, + "include": [ + "src/**/*.d.ts", + "src/**/*.ts", + "src/**/*.js", + "src/**/*.svelte", + ], + "references": [ + { + "path": "./tsconfig.node.json" + }, + ], +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..f61a9de --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler" + }, + "include": [ + "vite.config.ts" + ] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..4acf21e --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,77 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { defineConfig } from "vite"; +import { resolve } from "path" +import { svelte } from "@sveltejs/vite-plugin-svelte"; +import { less } from "svelte-preprocess-less"; + +// https://vitejs.dev/config/ +export default defineConfig({ + base: `./`, + plugins: [ + svelte({ + preprocess: { + style: less(), + }, + }), + ], + resolve: { + alias: { + "~": resolve(__dirname, "./"), + "@": resolve(__dirname, "./src"), + } + }, + build: { + minify: true, + // sourcemap: "inline", + lib: { + entry: resolve(__dirname, "src/index.ts"), + fileName: "index", + formats: ["cjs"], + }, + rollupOptions: { + external: [ + "siyuan", + /^@electron\/.*$/, + ], + output: { + entryFileNames: chunkInfo => { + // console.log(chunkInfo); + switch (chunkInfo.name) { + case "index": + return "[name].js"; + + default: + return "assets/[name]-[hash].js"; + } + }, + assetFileNames: assetInfo => { + // console.log(chunkInfo); + switch (assetInfo.name) { + case "style.css": + case "index.css": + return "index.css"; + + default: + return "assets/[name]-[hash][extname]"; + } + }, + }, + }, + }, +}); From 29c38192e89a003a8488743dff496b6469e3a7dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Tue, 15 Aug 2023 21:34:12 +0800 Subject: [PATCH 02/16] =?UTF-8?q?feat(wakatime):=20=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E5=8C=85=E5=90=AB=E5=88=97=E8=A1=A8=E4=B8=8E=E6=8E=92=E9=99=A4?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E5=8A=9F=E8=83=BD=20|=20Implement=20include?= =?UTF-8?q?=20list=20and=20exclude=20list=20function.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + .../plugins/wakatime/src/configs/default.ts | 8 +- workspace/plugins/wakatime/src/index.ts | 131 +++++++++++++++++- .../plugins/wakatime/src/types/config.d.ts | 6 + .../plugins/wakatime/src/types/wakatime.d.ts | 15 +- 5 files changed, 150 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eacf7ed..d679b1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - 调整心跳活动推送策略 | Adjust the heartbeat activity push strategy. - 添加 `hostname` 设置项 | Add `hostname` setting item. - 重新添加附属仓库 `wakatime` | Re-add sub-repository `wakatime`. +- 实现包含列表与排除列表功能 | Implement include list and exclude list function. ## 2023-08-14 diff --git a/workspace/plugins/wakatime/src/configs/default.ts b/workspace/plugins/wakatime/src/configs/default.ts index 4164e83..5272d08 100644 --- a/workspace/plugins/wakatime/src/configs/default.ts +++ b/workspace/plugins/wakatime/src/configs/default.ts @@ -26,6 +26,12 @@ export const DEFAULT_CONFIG: IConfig = { hide_branch_names: true, hide_file_names: true, + includeID: [], + excludeID: [], + + include: [], + exclude: [], + heartbeats: false, project: "", language: "", @@ -39,4 +45,4 @@ export const DEFAULT_CONFIG: IConfig = { category: Category.Learning, }, }, -} as const; +}; diff --git a/workspace/plugins/wakatime/src/index.ts b/workspace/plugins/wakatime/src/index.ts index ae243a0..2994dfb 100644 --- a/workspace/plugins/wakatime/src/index.ts +++ b/workspace/plugins/wakatime/src/index.ts @@ -29,8 +29,6 @@ import { import Settings from "./components/Settings.svelte"; import { - FLAG_ELECTRON, - FLAG_DESKTOP, FLAG_MOBILE, } from "@workspace/utils/env/front-end"; import { Logger } from "@workspace/utils/logger"; @@ -83,9 +81,16 @@ export default class WakaTimePlugin extends siyuan.Plugin { this.context = { url: this.wakatimeHeartbeatsUrl, method: "POST", + headers: this.wakatimeHeaders, + project: this.wakatimeProject, language: this.wakatimeLanguage, - headers: this.wakatimeHeaders, + + includeID: [], + excludeID: [], + include: [], + exclude: [], + blocks: new Map(), roots: new Map(), actions: new Array(), @@ -178,9 +183,16 @@ export default class WakaTimePlugin extends siyuan.Plugin { /* 更新 wakatime 请求上下文 */ public updateContext() { this.context.url = this.wakatimeHeartbeatsUrl; + this.context.headers = this.wakatimeHeaders; + this.context.project = this.wakatimeProject; this.context.language = this.wakatimeLanguage; - this.context.headers = this.wakatimeHeaders; + + this.context.includeID = this.wakatimeIncludeID; + this.context.excludeID = this.wakatimeExcludeID; + + this.context.include = this.wakatimeInclude; + this.context.exclude = this.wakatimeExclude; } /* 更新 notebook */ @@ -196,8 +208,31 @@ export default class WakaTimePlugin extends siyuan.Plugin { this.context.blocks.clear(); this.context.roots.clear(); - const actions = await this.buildHeartbeats(roots); - this.context.actions.push(...actions); + /* 在 ID 中进行过滤 */ + const valid_roots = roots + .filter(root => { + const entity = `${root.box}${root.path}`; + return this.filter( + entity, + this.context.includeID, + this.context.excludeID, + ); + }); + + const actions = await this.buildHeartbeats(valid_roots); + + /* 在 entity 中进行过滤 */ + const valid_actions = actions + .filter(action => { + const entity = action.entity; + return this.filter( + entity, + this.context.include, + this.context.exclude, + ); + }); + + this.context.actions.push(...valid_actions); if (this.context.actions.length > 0) { if (this.config.wakatime.heartbeats) { // 是否发送心跳连接 @@ -454,6 +489,74 @@ export default class WakaTimePlugin extends siyuan.Plugin { } } + /** + * 黑白名单过滤 + * @param entity 文件路径 + * @param include 包含列表 + * @param exclude 排除列表 + * @returns 是否通过过滤 + */ + protected filter( + entity: string, + include: (string | RegExp)[], + exclude: (string | RegExp)[], + ): boolean { + if (include.length > 0) { // 白名单过滤 + let pass = false; // 是否通过白名单过滤 + for (const entry of include) { + if (typeof entry === "string") { + if (entity.includes(entry)) { + pass = true; + break; + } + } + else if (entry instanceof RegExp) { + if (entry.test(entity)) { + pass = true; + break; + } + } + } + if (!pass) return false; + } + if (exclude.length > 0) { // 黑名单过滤 + let pass = true; // 是否通过黑名单过滤 + for (const entry of exclude) { + if (typeof entry === "string") { + if (entity.includes(entry)) { + pass = false; + break; + } + } + else if (entry instanceof RegExp) { + if (entry.test(entity)) { + pass = false; + break; + } + } + } + return pass; + } + return true; + } + + /* 清洗列表 */ + protected washList(list: string[]): (string | RegExp)[] { + return list + .filter(entry => { + entry = entry.trim(); + return (entry !== "" && entry !== "//") + }) + .map(entry => { + if (entry.startsWith("/") && entry.endsWith("/")) { + return new RegExp(entry.slice(1, -1)); + } + else { + return entry; + } + }); + } + /* 获取时间戳 */ public time(date: Date = new Date()): number { return date.getTime() / 1_000; @@ -537,4 +640,20 @@ export default class WakaTimePlugin extends siyuan.Plugin { public get wakatimeHostname(): string { return this.config?.wakatime.hostname || this.wakatimeDefaultHostname; } + + /* wakatime include */ + public get wakatimeIncludeID(): (string | RegExp)[] { + return this.washList(this.config.wakatime.includeID); + } + public get wakatimeInclude(): (string | RegExp)[] { + return this.washList(this.config.wakatime.include); + } + + /* wakatime exclude */ + public get wakatimeExcludeID(): (string | RegExp)[] { + return this.washList(this.config.wakatime.excludeID); + } + public get wakatimeExclude(): (string | RegExp)[] { + return this.washList(this.config.wakatime.exclude); + } }; diff --git a/workspace/plugins/wakatime/src/types/config.d.ts b/workspace/plugins/wakatime/src/types/config.d.ts index a5a26a4..525ab85 100644 --- a/workspace/plugins/wakatime/src/types/config.d.ts +++ b/workspace/plugins/wakatime/src/types/config.d.ts @@ -29,6 +29,12 @@ export interface IWakaTime { hide_branch_names: boolean; // 是否隐藏笔记本名 (使用笔记本 ID 代替) hide_file_names: boolean; // 是否隐藏文件路径 (使用文档 ID 代替) + includeID: string[]; // ID 包含列表, 在 ID 中过滤, 为空则包含所有笔记本与文档 + excludeID: string[]; // ID 排除列表, 在 ID 中过滤, 为空则不排除任何笔记本与文档 + + include: string[]; // 包含列表, 在 entity 中过滤, 为空则包含所有笔记本与文档, "/foo/" 表示正则表达式 + exclude: string[]; // 排除列表, 在 entity 中过滤, 为空则不排除任何笔记本与文档, "/foo/" 表示正则表达式 + heartbeats: boolean; // 是否开启心跳连接 project: string; // 项目名称 language: string; // 语言名称 diff --git a/workspace/plugins/wakatime/src/types/wakatime.d.ts b/workspace/plugins/wakatime/src/types/wakatime.d.ts index 82011b9..1c6876a 100644 --- a/workspace/plugins/wakatime/src/types/wakatime.d.ts +++ b/workspace/plugins/wakatime/src/types/wakatime.d.ts @@ -73,25 +73,32 @@ export namespace Context { "X-Machine-Name": string; // Machine Name [key: string]: string; } - + export interface IEvent { time: number; // UNIX 时间戳 (单位: s) is_write: boolean; // 是否写入 } - + export interface IRoot { id: BlockID; // 文档 ID box: BlockID; // 笔记本 ID path: string; // 文档路径 events: IEvent[]; // 事件 } - + export interface IContext { url: string; method: "POST"; + headers: IHeaders; + project: string; language: string; - headers: IHeaders; + + includeID: (string | RegExp)[], + excludeID: (string | RegExp)[], + include: (string | RegExp)[], + exclude: (string | RegExp)[], + blocks: Map; // block -> root roots: Map; // root -> { box, path } actions: Heartbeats.IAction[]; // 待提交的活动 From 8ee32cd13ed245429fed16038d782ece043e3cb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Tue, 15 Aug 2023 23:20:22 +0800 Subject: [PATCH 03/16] =?UTF-8?q?feat(wakatime):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=8C=85=E5=90=AB=E5=88=97=E8=A1=A8=E4=B8=8E=E6=8E=92=E9=99=A4?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E8=AE=BE=E7=BD=AE=E9=A1=B9=20|=20Add=20inclu?= =?UTF-8?q?de=20list=20and=20exclude=20list=20setting=20items.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + workspace/plugins/wakatime/public/README.md | 98 ++++++++++++++++++- .../plugins/wakatime/public/README_zh_CN.md | 98 ++++++++++++++++++- .../plugins/wakatime/public/i18n/en_US.json | 20 ++++ .../plugins/wakatime/public/i18n/zh_CHT.json | 20 ++++ .../plugins/wakatime/public/i18n/zh_CN.json | 20 ++++ .../wakatime/src/components/Settings.svelte | 80 +++++++++++++++ workspace/plugins/wakatime/src/index.ts | 19 +++- 8 files changed, 353 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d679b1d..9e3364a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - 添加 `hostname` 设置项 | Add `hostname` setting item. - 重新添加附属仓库 `wakatime` | Re-add sub-repository `wakatime`. - 实现包含列表与排除列表功能 | Implement include list and exclude list function. +- 添加包含列表与排除列表设置项 | Add include list and exclude list setting items. ## 2023-08-14 diff --git a/workspace/plugins/wakatime/public/README.md b/workspace/plugins/wakatime/public/README.md index d9644f9..63f0d26 100644 --- a/workspace/plugins/wakatime/public/README.md +++ b/workspace/plugins/wakatime/public/README.md @@ -129,7 +129,7 @@ A plugin for [SiYuan Note](https://github.com/siyuan-note/siyuan) that can use [ * `API URL` * Customize the API service address for `Wakapi/WakaTime`. - * Corresponds to the `api_url` configuration item in the `Wakapi/WakaTime` configuration file. + * Corresponds to the `api_url` configuration option in the `.wakatime.cfg` configuration file of `Wakapi/WakaTime`. * If empty, the service address of `WakaTime` will be used (`https://wakatime.com/api/v1`). * If using a hosted `Wakapi` service, it should be set to `https://wakapi.dev/api`. * If using a privately deployed `Wakapi` service, it should be set to `http(s)://host[:port]/api`. @@ -144,23 +144,119 @@ A plugin for [SiYuan Note](https://github.com/siyuan-note/siyuan) that can use [ * `API KEY` * Customize the access key for the `Wakapi/WakaTime` API service. + * Corresponds to the `api_key` configuration option in the `.wakatime.cfg` configuration file of `Wakapi/WakaTime`. * This is a required field, and if not set, a connection cannot be established with `Wakapi/WakaTime`. * `Hostname` * Customize the device name. + * Corresponds to the `hostname` configuration option in the `.wakatime.cfg` configuration file of `Wakapi/WakaTime`. * If empty, the host name of the device where Obsidian is located will be used. * `Timeout` * Timeout duration when calling the `Wakapi/WakaTime` API. + * Corresponds to the `timeout` configuration option in the `.wakatime.cfg` configuration file of `Wakapi/WakaTime`. * Unit: seconds * `Hide Notebook Name` * Whether to hide the notebook name in the submitted activity information. + * Corresponds to the `hide_branch_names` configuration option in the `.wakatime.cfg` configuration file of `Wakapi/WakaTime`. * If enabled, all Notebook Name in the submitted information will be replaced with Notebook ID. * `Hide Document Title` * Whether to hide the document title in the submitted activity information. + * Corresponds to the `hide_file_names` configuration option in the `.wakatime.cfg` configuration file of `Wakapi/WakaTime`. * If enabled, all Document Title in the submitted information will be replaced with Block ID. + * `ID Include List` + + * Only submit documents whose ID path includes the list field. + * If empty, it includes all notebooks and documents. + * If not empty, only submit documents whose ID path includes the list field. + + * ID path format: `notebook/document/.../document.sy` + * ID path examples: + + * `20210808180117-czj9bvb/20200812220555-lj3enxa.sy` + * `20210808180117-czj9bvb/20200812220555-lj3enxa/20210808180320-fqgskfj.sy` + * One record per line, can be text or regular expression. Regular expressions need to be wrapped in `/` as shown below: + + ```plaintext + 20200812220555-lj3enxa + /^20210917000226-w9fa32i\/20230522022822-roxea7p/ + ``` + + The above list is equivalent to the following JavaScript code: + + ```javascript + path.includes("20200812220555-lj3enxa") && /^20210917000226-w9fa32i\/20230522022822-roxea7p/.test(path) + ``` + + * `20200812220555-lj3enxa` + + * Submit documents that have the ID `20200812220555-lj3enxa`, including itself and its sub-documents. + + * Example: + + * `20210808180117-czj9bvb/20200812220555-lj3enxa.sy`: included + * `20210808180117-czj9bvb/20200812220555-lj3enxa/20210808180320-fqgskfj.sy`: included + * `20210808180117-czj9bvb/20210117211155-56n4odu.sy`: not included + * `/^20210917000226-w9fa32i\/20230522022822-roxea7p/` + + * Submit documents that match the regular expression `^20210917000226-w9fa32i/20230522022822-roxea7p`. + + * Example: + + * `20210917000226-w9fa32i/20230522022822-roxea7p.sy`: included + * `20210917000226-w9fa32i/20230522022822-roxea7p/20230522022929-ojqqfyn.sy`: included + * `20210917000226-w9fa32i/20220424113742-2eznev2.sy`: not included + * `20210808180117-czj9bvb/20210917000226-w9fa32i/20230522022822-roxea7p.sy`: not included + * `ID Exclude List` + + * Exclude documents whose ID path includes the list field when submitting. + * If empty, do not exclude any notebooks or documents. + * If not empty, exclude documents whose ID path includes the list field. + + * ID path format and matching rules can be found in `Wakapi/WakaTime > Service Settings > ID Inclusion List`. + * One record per line, can be text or regular expression. Regular expressions need to be wrapped in `/`. + * The exclusion list takes precedence over the inclusion list. + + * If a document's ID path matches both the ID inclusion list and the ID exclusion list, the document will be excluded. + * `Include List` + + * Only submit documents whose path includes the list field. + * Corresponds to the `include` configuration option in the `.wakatime.cfg` configuration file of `Wakapi/WakaTime`. + * If empty, it includes all notebooks and documents. + * If not empty, only submit documents whose path includes the list field. + + * Path format and examples: + + | | `Hide notebook names`: ✔ | `Hide notebook names`: ✖
| + | ------------------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | + | `Hide document titles`: ✔ | `//.../.sy`
`20210808180117-czj9bvb/20200812220555-lj3enxa.sy`
| `//.../.sy`
`User Guide/20200812220555-lj3enxa.sy`
| + | `Hide document titles`: ✖ | `//.../.sy`
`20210808180117-czj9bvb/Start Here.sy` | `//.../.sy`
`User Guide/Start Here.sy`
| + * One record per line, can be text or regular expression. Regular expressions need to be wrapped in `/` as shown below: + + ```plaintext + Start Here + /^User Guide\/Start Here/ + ``` + + The above list is equivalent to the following JavaScript code: + + ```javascript + path.includes("Start Here") && /^User Guide\/Start Here/.test(path) + ``` + * `Exclude List` + + * Exclude documents whose path includes the list field when submitting. + * Corresponds to the `exclude` configuration option in the `.wakatime.cfg` configuration file of `Wakapi/WakaTime`. + * If empty, do not exclude any notebooks or documents. + * If not empty, exclude documents whose path includes the list field. + + * Path format and matching rules can be found in `Wakapi/WakaTime > Service Settings > Inclusion List`. + * One record per line, can be text or regular expression. Regular expressions need to be wrapped in `/`. + * The exclusion list takes precedence over the inclusion list. + + * If a document's path matches both the inclusion list and the exclusion list, the document will be excluded. ## CHANGELOG diff --git a/workspace/plugins/wakatime/public/README_zh_CN.md b/workspace/plugins/wakatime/public/README_zh_CN.md index cd19d3c..ab81ef3 100644 --- a/workspace/plugins/wakatime/public/README_zh_CN.md +++ b/workspace/plugins/wakatime/public/README_zh_CN.md @@ -129,7 +129,7 @@ * `API URL` * 自定义 `Wakapi/WakaTime` API 服务地址 - * 对应 `Wakapi/WakaTime` 配置文件中的 `api_url` 配置项 + * 对应 `Wakapi/WakaTime` 配置文件 `.wakatime.cfg` 中的 `api_url` 配置项 * 若为空, 则使用 `WakaTime` 的服务地址 `https://wakatime.com/api/v1` * 若使用托管的 `Wakapi` 服务, 应设置为 `https://wakapi.dev/api` * 若使用私有部署的 `Wakapi` 服务, 应设置为 `http(s)://host[:port]/api` @@ -144,23 +144,119 @@ * `API 密钥` * 自定义 `Wakapi/WakaTime` API 服务访问密钥 + * 对应 `Wakapi/WakaTime` 配置文件 `.wakatime.cfg` 中的 `api_key` 配置项 * 必填项, 若未设置则无法与 `Wakapi/WakaTime` 建立连接 * `主机名称` * 自定义设备名称 + * 对应 `Wakapi/WakaTime` 配置文件 `.wakatime.cfg` 中的 `hostname` 配置项 * 若为空, 则使用思源内核所在设备的主机名 * `超时时间` * 调用 `Wakapi/WakaTime` API 时的超时时间 + * 对应 `Wakapi/WakaTime` 配置文件 `.wakatime.cfg` 中的 `timeout` 配置项 * 单位: 秒 * `隐藏笔记本名称` * 在提交的操作活动信息中是否隐藏笔记本名称 + * 对应 `Wakapi/WakaTime` 配置文件 `.wakatime.cfg` 中的 `hide_branch_names` 配置项 * 若开启, 则提交的信息中所有 笔记本名称 都替换为 笔记本 ID * `隐藏文档标题` * 在提交的操作活动信息中是否隐藏文档标题 + * 对应 `Wakapi/WakaTime` 配置文件 `.wakatime.cfg` 中的 `hide_file_names` 配置项 * 若开启, 则提交的信息中所有 文档标题 都替换为 文档块 ID + * `ID 包含列表` + + * 仅提交 ID 路径中包含列表字段的文档 + * 若为空则包含所有笔记本与文档 + * 若不为空则仅提交 ID 路径中包含列表字段的文档 + + * ID 路径格式: `<笔记本 ID>/<文档 ID>/.../<文档 ID>.sy` + * ID 路径示例 + + * `20210808180117-czj9bvb/20200812220555-lj3enxa.sy` + * `20210808180117-czj9bvb/20200812220555-lj3enxa/20210808180320-fqgskfj.sy` + * 每行一个记录, 可以为文本或者正则表达式, 正则表达式首尾需要使用 `/` 包裹, 如下所示 + + ```plaintext + 20200812220555-lj3enxa + /^20210917000226-w9fa32i\/20230522022822-roxea7p/ + ``` + + 上述列表与下述 `JavaScript` 代码等价 + + ```javascript + path.includes("20200812220555-lj3enxa") && /^20210917000226-w9fa32i\/20230522022822-roxea7p/.test(path) + ``` + + * `20200812220555-lj3enxa` + + * 提交 ID 为 `20200812220555-lj3enxa` 的笔记本或者文档本身及其下级的文档 + + * 示例 + + * `20210808180117-czj9bvb/20200812220555-lj3enxa.sy`: 包含 + * `20210808180117-czj9bvb/20200812220555-lj3enxa/20210808180320-fqgskfj.sy`: 包含 + * `20210808180117-czj9bvb/20210117211155-56n4odu.sy`: 不包含 + * `/^20210917000226-w9fa32i\/20230522022822-roxea7p/` + + * 提交匹配正则表达式 `^20210917000226-w9fa32i/20230522022822-roxea7p`` 的文档 + + * 示例 + + * `20210917000226-w9fa32i/20230522022822-roxea7p.sy`: 包含 + * `20210917000226-w9fa32i/20230522022822-roxea7p/20230522022929-ojqqfyn.sy`: 包含 + * `20210917000226-w9fa32i/20220424113742-2eznev2.sy`: 不包含 + * `20210808180117-czj9bvb/20210917000226-w9fa32i/20230522022822-roxea7p.sy`: 不包含 + * `ID 排除列表` + + * 提交时排除 ID 路径中包含列表字段的文档 + * 若为空则不排除所有笔记本与文档 + * 若不为空则排除 ID 路径中包含列表字段的文档 + + * ID 路径格式与匹配规则请参考 `Wakapi/WakaTime > 服务设置 > ID 包含列表` + * 每行一个记录, 可以为文本或者正则表达式, 正则表达式首尾需要使用 `/` 包裹 + * 排除列表的优先级高于包含列表 + + * 若一个文档的 ID 路径同时匹配 ID 包含列表与 ID 排除列表, 则该文件会被排除 + * `包含列表` + + * 仅提交路径中包含列表字段的文档 + * 对应 `Wakapi/WakaTime` 配置文件 `.wakatime.cfg` 中的 `include` 配置项 + * 若为空则包含所有笔记本与文档 + * 若不为空则仅提交路径中包含列表字段的文档 + + * 路径格式与示例 + + | | `隐藏笔记本名称`: ✔ | `隐藏笔记本名称`: ✖
| + | ----------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- | + | `隐藏文档标题`: ✔ | `<笔记本 ID>/<文档 ID>/.../<文档 ID>.sy`
`20210808180117-czj9bvb/20200812220555-lj3enxa.sy`
| `<笔记本名称>/<文档 ID>/.../<文档 ID>.sy`
`思源笔记用户指南/20200812220555-lj3enxa.sy`
| + | `隐藏文档标题`: ✖ | `<笔记本 ID>/<文档标题>/.../<文档标题>.sy`
`20210808180117-czj9bvb/请从这里开始.sy` | `思源笔记用户指南/<文档标题>/.../<文档标题>.sy`
`思源笔记用户指南/请从这里开始.sy`
| + * 每行一个记录, 可以为文本或者正则表达式, 正则表达式首尾需要使用 `/` 包裹, 如下所示 + + ```plaintext + 请从这里开始 + /^思源笔记用户指南\/请从这里开始/ + ``` + + 上述列表与下述 `JavaScript` 代码等价 + + ```javascript + path.includes("请从这里开始") && /^思源笔记用户指南\/请从这里开始/.test(path) + ``` + * 排除列表 + + * 提交时排除路径中包含列表字段的文档 + * 对应 `Wakapi/WakaTime` 配置文件 `.wakatime.cfg` 中的 `exclude` 配置项 + * 若为空则不排除所有笔记本与文档 + * 若不为空则排除路径中包含列表字段的文档 + + * 路径格式与匹配规则请参考 `Wakapi/WakaTime > 服务设置 > 包含列表` + * 每行一个记录, 可以为文本或者正则表达式, 正则表达式首尾需要使用 `/` 包裹 + * 排除列表的优先级高于包含列表 + + * 若一个文档的路径同时匹配包含列表与排除列表, 则该文件会被排除 ## 更改日志 diff --git a/workspace/plugins/wakatime/public/i18n/en_US.json b/workspace/plugins/wakatime/public/i18n/en_US.json index 612d9d3..1e3dcdf 100644 --- a/workspace/plugins/wakatime/public/i18n/en_US.json +++ b/workspace/plugins/wakatime/public/i18n/en_US.json @@ -46,6 +46,16 @@ "description": "Wakapi/WakaTime API URL
Corresponds to api_url in Wakapi/WakaTime configuration", "title": "API URL" }, + "exclude": { + "description": "Exclude documents with fields listed in the submission path.
Each entry should be on a separate line. Use / to enclose regular expressions.
Corresponds to the exclude option in the Wakapi/WakaTime configuration.", + "placeholder": "Exclude no notebooks or documents", + "title": "Exclude List" + }, + "excludeID": { + "description": "Exclude documents with fields listed in the submission ID path.
Each entry should be on a separate line. Use / to enclose regular expressions.", + "placeholder": "Exclude no notebooks or documents", + "title": "ID Exclude List" + }, "hide_branch_names": { "description": "Whether to hide notebook names. If enabled, the notebook name is replaced with the notebook ID
Corresponds to hide_branch_names in Wakapi/WakaTime configuration", "title": "Hide notebook names" @@ -58,6 +68,16 @@ "description": "Custom current host name
Corresponds to hostname in Wakapi/WakaTime configuration", "title": "Hostname" }, + "include": { + "description": "Only include documents with fields listed in the submission path.
Each entry should be on a separate line. Use / to enclose regular expressions.
Corresponds to the include option in the Wakapi/WakaTime configuration.", + "placeholder": "Include all notebooks and documents", + "title": "Include List" + }, + "includeID": { + "description": "Only include documents with fields listed in the submission ID path.
Each entry should be on a separate line. Use / to enclose regular expressions.", + "placeholder": "Include all notebooks and documents", + "title": "ID Include List" + }, "test": { "description": "Test if connected to Wakapi/WakaTime service correctly", "messages": { diff --git a/workspace/plugins/wakatime/public/i18n/zh_CHT.json b/workspace/plugins/wakatime/public/i18n/zh_CHT.json index 0fc92ba..05ef6f8 100644 --- a/workspace/plugins/wakatime/public/i18n/zh_CHT.json +++ b/workspace/plugins/wakatime/public/i18n/zh_CHT.json @@ -46,6 +46,16 @@ "description": "Wakapi/WakaTime API URL
對應 Wakapi/WakaTime 配置中的 api_url", "title": "API URL" }, + "exclude": { + "description": "提交時排除路徑中包含列表欄位的文件
每行一條記錄,若為正則表示式則需要使用 / 包裹
對應 Wakapi/WakaTime 配置中的 exclude", + "placeholder": "不排除任何筆記本與文件", + "title": "排除列表" + }, + "excludeID": { + "description": "提交時排除 ID 路徑中包含列表欄位的文件
每行一條記錄,若為正則表示式則需要使用 / 包裹", + "placeholder": "不排除任何筆記本與文件", + "title": "ID 排除列表" + }, "hide_branch_names": { "description": "是否隱藏筆記本名稱,開啟後將使用筆記本 ID 替換筆記本名稱
對應 Wakapi/WakaTime 配置中的 hide_branch_names", "title": "隱藏筆記本名稱" @@ -58,6 +68,16 @@ "description": "自定義當前主機名稱
對應 Wakapi/WakaTime 配置中的 hostname", "title": "主機名稱" }, + "include": { + "description": "僅提交路徑中包含列表欄位的文件
每行一條記錄,若為正則表示式則需要使用 / 包裹
對應 Wakapi/WakaTime 配置中的 include", + "placeholder": "包含所有筆記本與文件", + "title": "包含列表" + }, + "includeID": { + "description": "僅提交 ID 路徑中包含列表欄位的文件
每行一條記錄,若為正則表示式則需要使用 / 包裹", + "placeholder": "包含所有筆記本與文件", + "title": "ID 包含列表" + }, "test": { "description": "測試是否正確連線到 Wakapi/WakaTime 服務", "messages": { diff --git a/workspace/plugins/wakatime/public/i18n/zh_CN.json b/workspace/plugins/wakatime/public/i18n/zh_CN.json index fd119a1..ab4f730 100644 --- a/workspace/plugins/wakatime/public/i18n/zh_CN.json +++ b/workspace/plugins/wakatime/public/i18n/zh_CN.json @@ -46,6 +46,16 @@ "description": "Wakapi/WakaTime API URL
对应 Wakapi/WakaTime 配置中的 api_url", "title": "API URL" }, + "exclude": { + "description": "提交时排除路径中包含列表字段的文档
每行一条记录,若为正则表达式则需要使用 / 包裹
对应 Wakapi/WakaTime 配置中的 exclude", + "placeholder": "不排除任何笔记本与文档", + "title": "排除列表" + }, + "excludeID": { + "description": "提交时排除 ID 路径中包含列表字段的文档
每行一条记录,若为正则表达式则需要使用 / 包裹", + "placeholder": "不排除任何笔记本与文档", + "title": "ID 排除列表" + }, "hide_branch_names": { "description": "是否隐藏笔记本名称,开启后将使用笔记本 ID 替换笔记本名称
对应 Wakapi/WakaTime 配置中的 hide_branch_names", "title": "隐藏笔记本名称" @@ -58,6 +68,16 @@ "description": "自定义当前主机名称
对应 Wakapi/WakaTime 配置中的 hostname", "title": "主机名称" }, + "include": { + "description": "仅提交路径中包含列表字段的文档
每行一条记录,若为正则表达式则需要使用 / 包裹
对应 Wakapi/WakaTime 配置中的 include", + "placeholder": "包含所有笔记本与文档", + "title": "包含列表" + }, + "includeID": { + "description": "仅提交 ID 路径中包含列表字段的文档
每行一条记录,若为正则表达式则需要使用 / 包裹", + "placeholder": "包含所有笔记本与文档", + "title": "ID 包含列表" + }, "test": { "description": "测试是否正确连接到 Wakapi/WakaTime 服务", "messages": { diff --git a/workspace/plugins/wakatime/src/components/Settings.svelte b/workspace/plugins/wakatime/src/components/Settings.svelte index 6b473b1..f193675 100644 --- a/workspace/plugins/wakatime/src/components/Settings.svelte +++ b/workspace/plugins/wakatime/src/components/Settings.svelte @@ -420,6 +420,86 @@ }} /> + + + + { + config.wakatime.includeID = e.detail.value.split("\n"); + await updated(); + }} + /> + + + + + { + config.wakatime.excludeID = e.detail.value.split("\n"); + await updated(); + }} + /> + + + + + { + config.wakatime.include = e.detail.value.split("\n"); + await updated(); + }} + /> + + + + + { + config.wakatime.exclude = e.detail.value.split("\n"); + await updated(); + }} + /> +
diff --git a/workspace/plugins/wakatime/src/index.ts b/workspace/plugins/wakatime/src/index.ts index 2994dfb..856b91b 100644 --- a/workspace/plugins/wakatime/src/index.ts +++ b/workspace/plugins/wakatime/src/index.ts @@ -545,7 +545,24 @@ export default class WakaTimePlugin extends siyuan.Plugin { return list .filter(entry => { entry = entry.trim(); - return (entry !== "" && entry !== "//") + if (entry !== "" && entry !== "//") { + /* 过滤无效的正则表达式 */ + if (entry.startsWith("/") && entry.endsWith("/")) { + try { + new RegExp(entry.slice(1, -1)); + return true; + } catch (error) { + this.siyuan.showMessage( + error, + undefined, + "error", + ); + return false; + } + } + return true; + } + else return false; }) .map(entry => { if (entry.startsWith("/") && entry.endsWith("/")) { From e0411eac6035069f0217e7d17f8a112a7490eeb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Wed, 16 Aug 2023 01:25:27 +0800 Subject: [PATCH 04/16] =?UTF-8?q?feat(monaco-editor):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=96=87=E4=BB=B6/=E6=96=87=E4=BB=B6=E5=A4=B9=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=97=B6=E9=97=B4=20|=20Add=20file/folder=20update=20?= =?UTF-8?q?time.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 ++ workspace/package.json | 2 +- workspace/plugins/monaco-editor/package.json | 4 +- .../monaco-editor/public/i18n/en_US.json | 3 + .../monaco-editor/public/i18n/zh_CHT.json | 3 + .../monaco-editor/public/i18n/zh_CN.json | 3 + .../monaco-editor/src/explorer/filetree.ts | 4 +- .../monaco-editor/src/explorer/index.ts | 13 +++- workspace/pnpm-lock.yaml | 62 +++++++++---------- 9 files changed, 60 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e3364a..e8e9f67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # 更改日志 | CHANGE LOG +## 2023-08-16 + +- 添加文件/文件夹更新时间 | Add file/folder update time. + ## 2023-08-15 - 实现 `wakatime` 插件基础功能 | Implement the basic functions of the `wakatime` plugin. diff --git a/workspace/package.json b/workspace/package.json index bae187f..52c3ea5 100644 --- a/workspace/package.json +++ b/workspace/package.json @@ -11,7 +11,7 @@ "format": "prettier --write \"**/*.{ts,tsx,md}\"" }, "dependencies": { - "@siyuan-community/siyuan-sdk": "^0.2.1", + "@siyuan-community/siyuan-sdk": "^0.2.2", "@workspace/eslint-config-custom": "workspace:*", "@workspace/tsconfig": "workspace:*", "@workspace/vite-config-custom": "workspace:*" diff --git a/workspace/plugins/monaco-editor/package.json b/workspace/plugins/monaco-editor/package.json index 1c1cce9..3064262 100644 --- a/workspace/plugins/monaco-editor/package.json +++ b/workspace/plugins/monaco-editor/package.json @@ -17,7 +17,7 @@ "@monaco-editor/loader": "^1.3.3", "@sveltejs/vite-plugin-svelte": "^2.4.5", "@tsconfig/svelte": "^4.0.1", - "@types/node": "^20.4.9", + "@types/node": "^20.5.0", "@types/streamsaver": "^2.0.1", "deepmerge": "^4.3.1", "less": "^4.2.0", @@ -25,7 +25,7 @@ "monaco-editor": "^0.41.0", "streamsaver": "^2.0.6", "svelte": "^3.59.2", - "svelte-check": "^3.4.6", + "svelte-check": "^3.5.0", "svelte-preprocess-less": "^0.4.0", "ts-node": "^10.9.1", "tslib": "^2.6.1", diff --git a/workspace/plugins/monaco-editor/public/i18n/en_US.json b/workspace/plugins/monaco-editor/public/i18n/en_US.json index 0b29806..5c40cf4 100644 --- a/workspace/plugins/monaco-editor/public/i18n/en_US.json +++ b/workspace/plugins/monaco-editor/public/i18n/en_US.json @@ -66,6 +66,9 @@ "folder": { "ariaLabel": "Folder" }, + "lastUpdated": { + "text": "Last Updated" + }, "menu": { "ariaLabel": "Menu" }, diff --git a/workspace/plugins/monaco-editor/public/i18n/zh_CHT.json b/workspace/plugins/monaco-editor/public/i18n/zh_CHT.json index 3368732..af4fd68 100644 --- a/workspace/plugins/monaco-editor/public/i18n/zh_CHT.json +++ b/workspace/plugins/monaco-editor/public/i18n/zh_CHT.json @@ -66,6 +66,9 @@ "folder": { "ariaLabel": "資料夾" }, + "lastUpdated": { + "text": "更新時間" + }, "menu": { "ariaLabel": "菜單" }, diff --git a/workspace/plugins/monaco-editor/public/i18n/zh_CN.json b/workspace/plugins/monaco-editor/public/i18n/zh_CN.json index fd178a7..7c4dbdd 100644 --- a/workspace/plugins/monaco-editor/public/i18n/zh_CN.json +++ b/workspace/plugins/monaco-editor/public/i18n/zh_CN.json @@ -66,6 +66,9 @@ "folder": { "ariaLabel": "文件夹" }, + "lastUpdated": { + "text": "更新时间" + }, "menu": { "ariaLabel": "菜单" }, diff --git a/workspace/plugins/monaco-editor/src/explorer/filetree.ts b/workspace/plugins/monaco-editor/src/explorer/filetree.ts index 2ee0f4b..ccdd54f 100644 --- a/workspace/plugins/monaco-editor/src/explorer/filetree.ts +++ b/workspace/plugins/monaco-editor/src/explorer/filetree.ts @@ -71,8 +71,8 @@ export class FileTree { } } else { // 类型一致, 比较指定层级 - const name1 = node1.paths[depth].toLocaleLowerCase(); - const name2 = node2.paths[depth].toLocaleLowerCase(); + const name1 = node1.paths[depth].toLowerCase(); + const name2 = node2.paths[depth].toLowerCase(); switch (true) { case name1 > name2: // 名称大的在后 return 1; diff --git a/workspace/plugins/monaco-editor/src/explorer/index.ts b/workspace/plugins/monaco-editor/src/explorer/index.ts index 27a6acc..40b4c45 100644 --- a/workspace/plugins/monaco-editor/src/explorer/index.ts +++ b/workspace/plugins/monaco-editor/src/explorer/index.ts @@ -51,6 +51,7 @@ import { FLAG_BROWSER } from "@workspace/utils/env/front-end"; /* 资源 */ export interface IItem { name: string; // 文件名/文件夹名 + updated: number; // 更新时间 path: string; // 绝对路径 relative: string; // 相对于工作空间目录的相对路径 isFile: boolean; // 是否为文件 @@ -651,6 +652,7 @@ export class Explorer implements ITree { if (item.isDir) { resources.folders.push({ name: item.name, + updated: item.updated, path: join(directory, item.name), relative: join(relative, item.name), isFile: false, @@ -661,6 +663,7 @@ export class Explorer implements ITree { else { resources.files.push({ name: item.name, + updated: item.updated, path: join(directory, item.name), relative: join(relative, item.name), // relative: `${relative}/${item.name}`, isFile: true, @@ -699,7 +702,10 @@ export class Explorer implements ITree { iconPopoverID: this.icon.getPopoverID(FileTreeNodeType.Folder, item.relative), text: item.name, - textAriaLabel: item.relative, + textAriaLabel: `${item.relative + }
${this.plugin.i18n.explorer.lastUpdated.text + }: ${new Date(item.updated * 1_000).toLocaleString() + }`, }); }); @@ -722,7 +728,10 @@ export class Explorer implements ITree { iconPopoverID: this.icon.getPopoverID(FileTreeNodeType.File, item.relative), text: item.name, - textAriaLabel: item.relative, + textAriaLabel: `${item.relative + }
${this.plugin.i18n.explorer.lastUpdated.text + }: ${new Date(item.updated * 1_000).toLocaleString() + }`, }); }); diff --git a/workspace/pnpm-lock.yaml b/workspace/pnpm-lock.yaml index 1975d64..b85944e 100644 --- a/workspace/pnpm-lock.yaml +++ b/workspace/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@siyuan-community/siyuan-sdk': - specifier: ^0.2.1 - version: 0.2.1 + specifier: ^0.2.2 + version: 0.2.2 '@workspace/eslint-config-custom': specifier: workspace:* version: link:tools/eslint-config-custom @@ -312,8 +312,8 @@ importers: specifier: ^4.0.1 version: 4.0.1 '@types/node': - specifier: ^20.4.9 - version: 20.4.9 + specifier: ^20.5.0 + version: 20.5.0 '@types/streamsaver': specifier: ^2.0.1 version: 2.0.1 @@ -336,14 +336,14 @@ importers: specifier: ^3.59.2 version: 3.59.2 svelte-check: - specifier: ^3.4.6 - version: 3.4.6(less@4.2.0)(svelte@3.59.2) + specifier: ^3.5.0 + version: 3.5.0(less@4.2.0)(svelte@3.59.2) svelte-preprocess-less: specifier: ^0.4.0 version: 0.4.0 ts-node: specifier: ^10.9.1 - version: 10.9.1(@types/node@20.4.9)(typescript@5.1.6) + version: 10.9.1(@types/node@20.5.0)(typescript@5.1.6) tslib: specifier: ^2.6.1 version: 2.6.1 @@ -352,7 +352,7 @@ importers: version: 5.1.6 vite: specifier: ^4.4.9 - version: 4.4.9(@types/node@20.4.9)(less@4.2.0) + version: 4.4.9(@types/node@20.5.0)(less@4.2.0) vite-plugin-static-copy: specifier: ^0.16.0 version: 0.16.0(vite@4.4.9) @@ -414,7 +414,7 @@ importers: version: 5.1.6 vite: specifier: ^4.4.9 - version: 4.4.9(@types/node@20.4.9)(less@4.2.0) + version: 4.4.9(@types/node@20.5.0)(less@4.2.0) plugins/webview: dependencies: @@ -1967,8 +1967,8 @@ packages: react-is: 18.2.0 dev: true - /@siyuan-community/siyuan-sdk@0.2.1: - resolution: {integrity: sha512-OreGHDQZCv4PEHG0ohXno+/NMkdJktASThRfzDvzjFi0yrR84QmOjPjMboAqIXHFyxfUXI01WDG1v1KDWk3fMw==} + /@siyuan-community/siyuan-sdk@0.2.2: + resolution: {integrity: sha512-WKTyTc7tpuL4CvP7gcHLqTBwt1nm8vm0svS3mdTy+zokTFfk3Pt+mDz1/tDVRPd9RXAm7cbm2uApHTXUtgjytg==} dependencies: axios: 1.4.0 ofetch: 1.1.1 @@ -2067,7 +2067,7 @@ packages: '@sveltejs/vite-plugin-svelte': 2.4.5(svelte@3.59.2)(vite@4.4.9) debug: 4.3.4 svelte: 3.59.2 - vite: 4.4.9(@types/node@20.4.9)(less@4.2.0) + vite: 4.4.9(@types/node@20.5.0)(less@4.2.0) transitivePeerDependencies: - supports-color dev: true @@ -2083,7 +2083,7 @@ packages: '@sveltejs/vite-plugin-svelte': 2.4.5(svelte@4.2.0)(vite@4.4.9) debug: 4.3.4 svelte: 4.2.0 - vite: 4.4.9(@types/node@20.4.9)(less@4.2.0) + vite: 4.4.9(@types/node@20.5.0)(less@4.2.0) transitivePeerDependencies: - supports-color dev: true @@ -2202,7 +2202,7 @@ packages: magic-string: 0.30.2 svelte: 3.59.2 svelte-hmr: 0.15.3(svelte@3.59.2) - vite: 4.4.9(@types/node@20.4.9)(less@4.2.0) + vite: 4.4.9(@types/node@20.5.0)(less@4.2.0) vitefu: 0.2.4(vite@4.4.9) transitivePeerDependencies: - supports-color @@ -2222,7 +2222,7 @@ packages: magic-string: 0.30.2 svelte: 4.2.0 svelte-hmr: 0.15.3(svelte@4.2.0) - vite: 4.4.9(@types/node@20.4.9)(less@4.2.0) + vite: 4.4.9(@types/node@20.5.0)(less@4.2.0) vitefu: 0.2.4(vite@4.4.9) transitivePeerDependencies: - supports-color @@ -2273,7 +2273,7 @@ packages: resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.4.9 + '@types/node': 20.5.0 dev: true /@types/html-escaper@3.0.0: @@ -2304,8 +2304,8 @@ packages: resolution: {integrity: sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==} dev: true - /@types/node@20.4.9: - resolution: {integrity: sha512-8e2HYcg7ohnTUbHk8focoklEQYvemQmu9M/f43DZVx43kHn0tE3BY/6gSDxS7k0SprtS0NHvj+L80cGLnoOUcQ==} + /@types/node@20.5.0: + resolution: {integrity: sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==} dev: true /@types/prettier@2.7.3: @@ -4849,8 +4849,8 @@ packages: - sugarss dev: true - /svelte-check@3.4.6(less@4.2.0)(svelte@3.59.2): - resolution: {integrity: sha512-OBlY8866Zh1zHQTkBMPS6psPi7o2umTUyj6JWm4SacnIHXpWFm658pG32m3dKvKFL49V4ntAkfFHKo4ztH07og==} + /svelte-check@3.5.0(less@4.2.0)(svelte@3.59.2): + resolution: {integrity: sha512-KHujbn4k17xKYLmtCwv0sKKM7uiHTYcQvXnvrCcNU6a7hcszh99zFTIoiu/Sp/ewAw5aJmillJ1Cs8gKLmcX4A==} hasBin: true peerDependencies: svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0 @@ -5319,7 +5319,7 @@ packages: typescript: 5.1.6 dev: true - /ts-node@10.9.1(@types/node@20.4.9)(typescript@5.1.6): + /ts-node@10.9.1(@types/node@20.5.0)(typescript@5.1.6): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true peerDependencies: @@ -5338,7 +5338,7 @@ packages: '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.4.9 + '@types/node': 20.5.0 acorn: 8.10.0 acorn-walk: 8.2.0 arg: 4.1.3 @@ -5526,7 +5526,7 @@ packages: resolution: {integrity: sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==} dev: true - /vite-node@0.32.2(@types/node@20.4.9): + /vite-node@0.32.2(@types/node@20.5.0): resolution: {integrity: sha512-dTQ1DCLwl2aEseov7cfQ+kDMNJpM1ebpyMMMwWzBvLbis8Nla/6c9WQcqpPssTwS6Rp/+U6KwlIj8Eapw4bLdA==} engines: {node: '>=v14.18.0'} hasBin: true @@ -5536,7 +5536,7 @@ packages: mlly: 1.4.0 pathe: 1.1.1 picocolors: 1.0.0 - vite: 4.4.9(@types/node@20.4.9)(less@4.2.0) + vite: 4.4.9(@types/node@20.5.0)(less@4.2.0) transitivePeerDependencies: - '@types/node' - less @@ -5558,7 +5558,7 @@ packages: fast-glob: 3.3.1 fs-extra: 11.1.1 picocolors: 1.0.0 - vite: 4.4.9(@types/node@20.4.9)(less@4.2.0) + vite: 4.4.9(@types/node@20.5.0)(less@4.2.0) dev: true /vite@4.3.9(less@4.1.3): @@ -5702,7 +5702,7 @@ packages: fsevents: 2.3.2 dev: true - /vite@4.4.9(@types/node@20.4.9)(less@4.2.0): + /vite@4.4.9(@types/node@20.5.0)(less@4.2.0): resolution: {integrity: sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true @@ -5730,7 +5730,7 @@ packages: terser: optional: true dependencies: - '@types/node': 20.4.9 + '@types/node': 20.5.0 esbuild: 0.18.20 less: 4.2.0 postcss: 8.4.27 @@ -5791,7 +5791,7 @@ packages: vite: optional: true dependencies: - vite: 4.4.9(@types/node@20.4.9)(less@4.2.0) + vite: 4.4.9(@types/node@20.5.0)(less@4.2.0) dev: true /vitest@0.32.2: @@ -5827,7 +5827,7 @@ packages: dependencies: '@types/chai': 4.3.5 '@types/chai-subset': 1.3.3 - '@types/node': 20.4.9 + '@types/node': 20.5.0 '@vitest/expect': 0.32.2 '@vitest/runner': 0.32.2 '@vitest/snapshot': 0.32.2 @@ -5847,8 +5847,8 @@ packages: strip-literal: 1.0.1 tinybench: 2.5.0 tinypool: 0.5.0 - vite: 4.4.9(@types/node@20.4.9)(less@4.2.0) - vite-node: 0.32.2(@types/node@20.4.9) + vite: 4.4.9(@types/node@20.5.0)(less@4.2.0) + vite-node: 0.32.2(@types/node@20.5.0) why-is-node-running: 2.2.2 transitivePeerDependencies: - less From 9921de83b4b20f882459504589b4ba3cc2287070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Wed, 16 Aug 2023 02:24:02 +0800 Subject: [PATCH 05/16] =?UTF-8?q?feat(monaco-editor):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=20`=E5=A4=8D=E5=88=B6=E5=AF=BC=E5=87=BA=E8=B6=85=E9=93=BE?= =?UTF-8?q?=E6=8E=A5`=20=E8=8F=9C=E5=8D=95=E9=A1=B9=20|=20Add=20`Copy=20ex?= =?UTF-8?q?port=20hyperlink`=20menu=20item.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + .../monaco-editor/public/i18n/en_US.json | 6 + .../monaco-editor/public/i18n/zh_CHT.json | 6 + .../monaco-editor/public/i18n/zh_CN.json | 6 + .../monaco-editor/src/explorer/index.ts | 2 +- .../monaco-editor/src/explorer/menu.ts | 106 +++++---------- workspace/plugins/monaco-editor/src/index.ts | 122 +++++++++++++++++- 7 files changed, 170 insertions(+), 79 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8e9f67..f4d3d57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 2023-08-16 - 添加文件/文件夹更新时间 | Add file/folder update time. +- 添加 `复制导出超链接` 菜单项 | Add `Copy export hyperlink` menu item. ## 2023-08-15 diff --git a/workspace/plugins/monaco-editor/public/i18n/en_US.json b/workspace/plugins/monaco-editor/public/i18n/en_US.json index 5c40cf4..109b02c 100644 --- a/workspace/plugins/monaco-editor/public/i18n/en_US.json +++ b/workspace/plugins/monaco-editor/public/i18n/en_US.json @@ -296,9 +296,15 @@ "copy": { "label": "Copy" }, + "copyDownloadHyperlink": { + "label": "Copy Download Hyperlink" + }, "copyEditHyperlink": { "label": "Copy Edit Hyperlink" }, + "copyExportHyperlink": { + "label": "Copy Export Hyperlink" + }, "copyFullPath": { "label": "Copy Absolute Path" }, diff --git a/workspace/plugins/monaco-editor/public/i18n/zh_CHT.json b/workspace/plugins/monaco-editor/public/i18n/zh_CHT.json index af4fd68..f53e9dc 100644 --- a/workspace/plugins/monaco-editor/public/i18n/zh_CHT.json +++ b/workspace/plugins/monaco-editor/public/i18n/zh_CHT.json @@ -296,9 +296,15 @@ "copy": { "label": "複製" }, + "copyDownloadHyperlink": { + "label": "複製下載超連結" + }, "copyEditHyperlink": { "label": "複製編輯超連結" }, + "copyExportHyperlink": { + "label": "複製匯出超連結" + }, "copyFullPath": { "label": "複製完整路徑" }, diff --git a/workspace/plugins/monaco-editor/public/i18n/zh_CN.json b/workspace/plugins/monaco-editor/public/i18n/zh_CN.json index 7c4dbdd..cd434d7 100644 --- a/workspace/plugins/monaco-editor/public/i18n/zh_CN.json +++ b/workspace/plugins/monaco-editor/public/i18n/zh_CN.json @@ -296,9 +296,15 @@ "copy": { "label": "复制" }, + "copyDownloadHyperlink": { + "label": "复制下载超链接" + }, "copyEditHyperlink": { "label": "复制编辑超链接" }, + "copyExportHyperlink": { + "label": "复制导出超链接" + }, "copyFullPath": { "label": "复制完整路径" }, diff --git a/workspace/plugins/monaco-editor/src/explorer/index.ts b/workspace/plugins/monaco-editor/src/explorer/index.ts index 40b4c45..09f36cf 100644 --- a/workspace/plugins/monaco-editor/src/explorer/index.ts +++ b/workspace/plugins/monaco-editor/src/explorer/index.ts @@ -435,7 +435,7 @@ export class Explorer implements ITree { const type = get(node.type); const name = get(node.name); const relative = get(node.relative); - await this.contextMenu.download(relative, name, type); + await this.plugin.download(relative, name, type); } break; case FileTreeNodeType.Root: // 根目录无法拖拽下载 diff --git a/workspace/plugins/monaco-editor/src/explorer/menu.ts b/workspace/plugins/monaco-editor/src/explorer/menu.ts index 9e783ab..842412c 100644 --- a/workspace/plugins/monaco-editor/src/explorer/menu.ts +++ b/workspace/plugins/monaco-editor/src/explorer/menu.ts @@ -27,7 +27,7 @@ import { copyText } from "@workspace/utils/misc/copy"; import { isStaticWebFileServicePath, workspacePath2StaticPathname } from "@workspace/utils/siyuan/url"; import { ExplorerIcon } from "./icon"; import { Explorer, ProtectedResourceType } from "."; -import { basename, extname, join, parse } from "@workspace/utils/path/browserify"; +import { extname, join, parse } from "@workspace/utils/path/browserify"; import { fn__code, ft__error, @@ -41,7 +41,7 @@ import { openPath, showItemInFolder, } from "@workspace/utils/electron/shell"; -import { showOpenDialog, showSaveDialog } from "@workspace/utils/electron/dialog"; +import { showOpenDialog } from "@workspace/utils/electron/dialog"; import { cp } from "@workspace/utils/node/fs/promises"; import { normalize } from "@workspace/utils/path/normalize"; import { OpenType } from "@/utils/url"; @@ -503,7 +503,7 @@ export class ExplorerContextMenu { ); { - const url = new URL(`siyuan://plugins/${this.plugin.name}/workspace/${relative}`); + const url = new URL(`siyuan://plugins/${this.plugin.name}/open/workspace/${relative}`); const href_edit = url.href; /* 复制编辑超链接 */ @@ -543,10 +543,28 @@ export class ExplorerContextMenu { }); } + const href_export = `siyuan://plugins/${this.plugin.name}/export/workspace/${relative}`; + + /* 复制导出超链接 */ + submenu.push({ + type: MenuItemType.Action, + options: { + icon: "iconDownload", + label: this.i18n.menu.copyExportHyperlink.label, + accelerator: escapeHTML(href_export), + click: () => { + copyText(href_export); + }, + }, + root: false, + folder: true, + file: true, + }); + submenu.push({ type: MenuItemType.Separator, root: false, - folder: false, + folder: true, file: true, }); } @@ -661,7 +679,7 @@ export class ExplorerContextMenu { label: this.i18n.menu.importFile.label, click: async () => { const result = await showOpenDialog({ - title: i10n_save_as.title.replaceAll("${1}", relative), + title: this.i18n.menu.importFile.title.replaceAll("${1}", relative), buttonLabel: this.i18n.menu.import.label, properties: [ "openFile", @@ -697,7 +715,7 @@ export class ExplorerContextMenu { label: this.i18n.menu.importFolder.label, click: async () => { const result = await showOpenDialog({ - title: i10n_save_as.title.replaceAll("${1}", relative), + title: this.i18n.menu.importFolder.title.replaceAll("${1}", relative), buttonLabel: this.i18n.menu.import.label, properties: [ "openDirectory", @@ -738,45 +756,17 @@ export class ExplorerContextMenu { * 文件/文件夹另存为 * REF: https://www.electronjs.org/zh/docs/latest/api/dialog#dialogshowsavedialogbrowserwindow-options */ - const i10n_save_as = file - ? this.i18n.menu.exportFile - : this.i18n.menu.exportFolder; items.push({ type: MenuItemType.Action, options: { icon: "iconDownload", label: this.i18n.menu.export.label, click: async () => { - const asyncFs = globalThis.require("fs/promises") as typeof import("fs/promises"); - const result = await showSaveDialog({ - title: i10n_save_as.title.replaceAll("${1}", relative), - defaultPath: name, - properties: [ - "showHiddenFiles", - "createDirectory", - "treatPackageAsDirectory", - "showOverwriteConfirmation", - ], - }); - if (!result.canceled && result.filePath) { - // this.plugin.logger.debugs(path, result.filePath); - await asyncFs.cp( - path, - result.filePath, - { - recursive: true, // 递归复制 - }, - ); - this.plugin.siyuan.confirm( - i10n_save_as.label, - i10n_save_as.message - .replaceAll("${1}", fn__code(relative)) - .replaceAll("${2}", fn__code(result.filePath)), - () => { - showItemInFolder(result.filePath); - }, - ) - } + await this.plugin.export( + relative, + name, + type, + ); }, }, root: false, @@ -871,7 +861,7 @@ export class ExplorerContextMenu { icon: "iconDownload", label: this.i18n.menu.download.label, click: async () => { - await this.download(relative, name, type); + await this.plugin.download(relative, name, type); }, }, root: false, @@ -1068,42 +1058,6 @@ export class ExplorerContextMenu { }); } - /** - * 下载文件/文件夹 - * @param path - 所需下载的文件/文件夹相对于工作空间目录的路径 - * @param name - 所需下载的文件/文件夹名称 - * @param type - 下载内容类型 - */ - public async download( - path: string, - name: string, - type: FileTreeNodeType, - ): Promise { - /* 文件夹需要首先打包为压缩文件 */ - if (type === FileTreeNodeType.Folder) { - const response = await this.plugin.client.exportResources({ - paths: [ - path, - ], - name, - }); - path = response.data.path; - } - - /* 下载文件流 */ - const response = await this.plugin.client.getFile({ path }, "stream"); - if (response) { - // this.plugin.logger.debugs(basename(path), response); - const write_stream = this.plugin.streamsaver.createWriteStream(basename(path)); - await response.pipeTo(write_stream); - } - - /* 下载完压缩文件后删除 */ - if (type === FileTreeNodeType.Folder) { - await this.plugin.client.removeFile({ path }); - } - } - /** * 新建文件/文件夹弹出框 * @param node: 当前节点节点 diff --git a/workspace/plugins/monaco-editor/src/index.ts b/workspace/plugins/monaco-editor/src/index.ts index 881bf1e..e98e32a 100644 --- a/workspace/plugins/monaco-editor/src/index.ts +++ b/workspace/plugins/monaco-editor/src/index.ts @@ -72,6 +72,11 @@ import type { I18N } from "@/utils/i18n"; import type { IDockData } from "./types/dock"; import { trimPrefix } from "@workspace/utils/misc/string"; import { OpenMode, OpenType } from "./utils/url"; +import { FileTreeNodeType } from "@workspace/components/siyuan/tree/file"; +import { basename, parse } from "@workspace/utils/path/browserify"; +import { showSaveDialog } from "@workspace/utils/electron/dialog"; +import { fn__code } from "@workspace/utils/siyuan/text/span"; +import { showItemInFolder } from "@workspace/utils/electron/shell"; export default class MonacoEditorPlugin extends siyuan.Plugin { public static readonly GLOBAL_CONFIG_NAME = "global-config"; @@ -910,10 +915,10 @@ export default class MonacoEditorPlugin extends siyuan.Plugin { protected readonly openSiyuanUrlEventListener = async (e: IOpenSiyuanUrlPluginEvent) => { // this.logger.debug(e); const url = new URL(e.detail.url); - if (url.pathname.startsWith(`//plugins/${this.name}/workspace/`)) { + if (url.pathname.startsWith(`//plugins/${this.name}/open/workspace/`)) { // 打开文件 const type = (url.searchParams.get("type") as OpenType | null); const mode = (url.searchParams.get("mode") as OpenMode | null); - const relative = trimPrefix(url.pathname, `//plugins/${this.name}/workspace/`); + const relative = trimPrefix(url.pathname, `//plugins/${this.name}/open/workspace/`); switch (type) { default: @@ -1046,6 +1051,31 @@ export default class MonacoEditorPlugin extends siyuan.Plugin { } } } + else if (url.pathname.startsWith(`//plugins/${this.name}/export/workspace/`)) { // 导出文件/文件夹 + const relative = trimPrefix(url.pathname, `//plugins/${this.name}/export/workspace/`); + const info = parse(relative); + const response = await this.client.readDir({ path: info.dir }); + const entry = response.data.find((entry) => entry.name === info.base); + + switch (entry?.isDir) { + case true: + await this.export( + relative, + info.base, + FileTreeNodeType.Folder, + ); + break; + case false: + await this.export( + relative, + info.base, + FileTreeNodeType.File, + ); + break; + default: + break; + } + } } /** @@ -1303,4 +1333,92 @@ export default class MonacoEditorPlugin extends siyuan.Plugin { ...options, }); } + + /** + * 下载文件/文件夹 + * @param path - 所需下载的文件/文件夹相对于工作空间目录的路径 + * @param name - 所需下载的文件/文件夹名称 + * @param type - 下载内容类型 + */ + public async download( + path: string, + name: string, + type: FileTreeNodeType, + ): Promise { + /* 文件夹需要首先打包为压缩文件 */ + if (type === FileTreeNodeType.Folder) { + const response = await this.client.exportResources({ + paths: [ + path, + ], + name, + }); + path = response.data.path; + } + + /* 下载文件流 */ + const response = await this.client.getFile({ path }, "stream"); + if (response) { + // this.logger.debugs(basename(path), response); + const write_stream = this.streamsaver.createWriteStream(basename(path)); + await response.pipeTo(write_stream); + } + + /* 下载完压缩文件后删除 */ + if (type === FileTreeNodeType.Folder) { + await this.client.removeFile({ path }); + } + } + + /** + * 导出文件/文件夹 + * @param path - 所需导出的文件/文件夹相对于工作空间目录的路径 + * @param name - 所需导出的文件/文件夹名称 + * @param type - 下载内容类型 + */ + public async export( + path: string, + name: string, + type: FileTreeNodeType, + ): Promise { + const i10n_save_as = type === FileTreeNodeType.File + ? this.i18n.menu.exportFile + : this.i18n.menu.exportFolder; + + const asyncFs = globalThis.require("fs/promises") as typeof import("fs/promises"); + const result = await showSaveDialog({ + title: i10n_save_as.title.replaceAll("${1}", path), + defaultPath: name, + properties: [ + "showHiddenFiles", + "createDirectory", + "treatPackageAsDirectory", + "showOverwriteConfirmation", + ], + }); + if (!result.canceled && result.filePath) { + // this.logger.debugs(path, result.filePath); + const { join } = globalThis.require("path") as typeof import("path"); + const source = join( + globalThis.siyuan.config.system.workspaceDir, + path, + ); + await asyncFs.cp( + source, + result.filePath, + { + recursive: true, // 递归复制 + }, + ); + this.siyuan.confirm( + i10n_save_as.label, + i10n_save_as.message + .replaceAll("${1}", fn__code(path)) + .replaceAll("${2}", fn__code(result.filePath)), + () => { + showItemInFolder(result.filePath); + }, + ) + } + } } From 5329be5e61fd20bea2d7f0724b4700497646c90b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Wed, 16 Aug 2023 02:27:15 +0800 Subject: [PATCH 06/16] chore(monaco-editor): release v0.1.2 --- .../monaco-editor/.github/workflows/release-please.yml | 2 +- workspace/plugins/monaco-editor/.vscode/extensions.json | 3 --- workspace/plugins/monaco-editor/package.json | 2 +- workspace/plugins/monaco-editor/public/plugin.json | 4 ++-- 4 files changed, 4 insertions(+), 7 deletions(-) delete mode 100644 workspace/plugins/monaco-editor/.vscode/extensions.json diff --git a/workspace/plugins/monaco-editor/.github/workflows/release-please.yml b/workspace/plugins/monaco-editor/.github/workflows/release-please.yml index 599c668..1c967a0 100644 --- a/workspace/plugins/monaco-editor/.github/workflows/release-please.yml +++ b/workspace/plugins/monaco-editor/.github/workflows/release-please.yml @@ -14,7 +14,7 @@ permissions: env: PACKAGE_NAME: monaco-editor - PACKAGE_VERSION: 0.1.1 + PACKAGE_VERSION: 0.1.2 jobs: release-please: diff --git a/workspace/plugins/monaco-editor/.vscode/extensions.json b/workspace/plugins/monaco-editor/.vscode/extensions.json deleted file mode 100644 index bdef820..0000000 --- a/workspace/plugins/monaco-editor/.vscode/extensions.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "recommendations": ["svelte.svelte-vscode"] -} diff --git a/workspace/plugins/monaco-editor/package.json b/workspace/plugins/monaco-editor/package.json index 3064262..35a285a 100644 --- a/workspace/plugins/monaco-editor/package.json +++ b/workspace/plugins/monaco-editor/package.json @@ -1,7 +1,7 @@ { "name": "monaco-editor", "private": true, - "version": "0.1.1", + "version": "0.1.2", "type": "module", "scripts": { "dev": "vite", diff --git a/workspace/plugins/monaco-editor/public/plugin.json b/workspace/plugins/monaco-editor/public/plugin.json index 0d54626..51519cd 100644 --- a/workspace/plugins/monaco-editor/public/plugin.json +++ b/workspace/plugins/monaco-editor/public/plugin.json @@ -2,8 +2,8 @@ "name": "monaco-editor", "author": "Zuoqiu Yingyi", "url": "https://github.com/Zuoqiu-Yingyi/siyuan-plugin-monaco-editor", - "version": "0.1.1", - "minAppVersion": "2.9.9", + "version": "0.1.2", + "minAppVersion": "2.10.0", "backends": [ "all" ], From 8035ab83c3418b0397f602446222264cb50e1e1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Wed, 16 Aug 2023 02:32:56 +0800 Subject: [PATCH 07/16] chore(wakatime): release v0.1.1 --- workspace/plugins/wakatime/.github/workflows/release-please.yml | 2 +- workspace/plugins/wakatime/package.json | 2 +- workspace/plugins/wakatime/public/plugin.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/workspace/plugins/wakatime/.github/workflows/release-please.yml b/workspace/plugins/wakatime/.github/workflows/release-please.yml index cd9b577..bdcd7ec 100644 --- a/workspace/plugins/wakatime/.github/workflows/release-please.yml +++ b/workspace/plugins/wakatime/.github/workflows/release-please.yml @@ -14,7 +14,7 @@ permissions: env: PACKAGE_NAME: custom-fonts - PACKAGE_VERSION: 0.1.0 + PACKAGE_VERSION: 0.1.1 jobs: release-please: diff --git a/workspace/plugins/wakatime/package.json b/workspace/plugins/wakatime/package.json index 33148ea..30e2dc2 100644 --- a/workspace/plugins/wakatime/package.json +++ b/workspace/plugins/wakatime/package.json @@ -1,7 +1,7 @@ { "name": "wakatime", "private": true, - "version": "0.1.0", + "version": "0.1.1", "type": "module", "scripts": { "dev": "vite", diff --git a/workspace/plugins/wakatime/public/plugin.json b/workspace/plugins/wakatime/public/plugin.json index 195a0f6..d3fccf9 100644 --- a/workspace/plugins/wakatime/public/plugin.json +++ b/workspace/plugins/wakatime/public/plugin.json @@ -2,7 +2,7 @@ "name": "wakatime", "author": "Zuoqiu Yingyi", "url": "https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime", - "version": "0.1.0", + "version": "0.1.1", "minAppVersion": "2.9.9", "backends": [ "all" From f11419ab1977de6dfcfc75593caf1290d3c0bc48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yingyi=20/=20=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Wed, 16 Aug 2023 13:27:11 +0800 Subject: [PATCH 08/16] Initial commit --- LICENSE | 661 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 661 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0ad25db --- /dev/null +++ b/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. From 38b15a33357bd124927f1f1ddf09e786786c830a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Wed, 16 Aug 2023 13:30:10 +0800 Subject: [PATCH 09/16] =?UTF-8?q?chore(script):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E9=99=84=E5=B1=9E=E4=BB=93=E5=BA=93=20`template`=20=E7=9A=84?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E8=84=9A=E6=9C=AC=20|=20Add=20management=20s?= =?UTF-8?q?cripts=20for=20sub-repository=20`template`.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + scripts/git-subtree/template/add.ps1 | 5 + scripts/git-subtree/template/pull.ps1 | 4 + scripts/git-subtree/template/push.ps1 | 4 + scripts/git-subtree/template/split.ps1 | 3 + workspace/package.json | 2 +- .../chinese-convert/.github/FUNDING.yml | 36 - workspace/plugins/chinese-convert/.gitignore | 130 ---- .../plugins/chinese-convert/CHANGELOG.md | 4 - workspace/plugins/chinese-convert/LICENSE | 661 ------------------ workspace/plugins/chinese-convert/README.md | 40 -- workspace/pnpm-lock.yaml | 19 +- 12 files changed, 32 insertions(+), 877 deletions(-) create mode 100644 scripts/git-subtree/template/add.ps1 create mode 100644 scripts/git-subtree/template/pull.ps1 create mode 100644 scripts/git-subtree/template/push.ps1 create mode 100644 scripts/git-subtree/template/split.ps1 delete mode 100644 workspace/plugins/chinese-convert/.github/FUNDING.yml delete mode 100644 workspace/plugins/chinese-convert/.gitignore delete mode 100644 workspace/plugins/chinese-convert/CHANGELOG.md delete mode 100644 workspace/plugins/chinese-convert/LICENSE delete mode 100644 workspace/plugins/chinese-convert/README.md diff --git a/CHANGELOG.md b/CHANGELOG.md index f4d3d57..a48cff8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - 添加文件/文件夹更新时间 | Add file/folder update time. - 添加 `复制导出超链接` 菜单项 | Add `Copy export hyperlink` menu item. +- 添加附属仓库 `template` 的管理脚本 | Add management scripts for sub-repository `template`. ## 2023-08-15 diff --git a/scripts/git-subtree/template/add.ps1 b/scripts/git-subtree/template/add.ps1 new file mode 100644 index 0000000..9048cdb --- /dev/null +++ b/scripts/git-subtree/template/add.ps1 @@ -0,0 +1,5 @@ +git subtree add ` + -P workspace/plugins/template ` + https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template.git ` + main ` + --squash diff --git a/scripts/git-subtree/template/pull.ps1 b/scripts/git-subtree/template/pull.ps1 new file mode 100644 index 0000000..58a06b8 --- /dev/null +++ b/scripts/git-subtree/template/pull.ps1 @@ -0,0 +1,4 @@ +git subtree pull ` + -P workspace/plugins/template ` + https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template.git ` + main diff --git a/scripts/git-subtree/template/push.ps1 b/scripts/git-subtree/template/push.ps1 new file mode 100644 index 0000000..324cf19 --- /dev/null +++ b/scripts/git-subtree/template/push.ps1 @@ -0,0 +1,4 @@ +git subtree push ` + -P workspace/plugins/template ` + https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template.git ` + main diff --git a/scripts/git-subtree/template/split.ps1 b/scripts/git-subtree/template/split.ps1 new file mode 100644 index 0000000..71954c2 --- /dev/null +++ b/scripts/git-subtree/template/split.ps1 @@ -0,0 +1,3 @@ +git subtree split ` + -P workspace/plugins/template ` + --rejoin diff --git a/workspace/package.json b/workspace/package.json index 52c3ea5..fc945d4 100644 --- a/workspace/package.json +++ b/workspace/package.json @@ -19,7 +19,7 @@ "devDependencies": { "eslint": "^8.47.0", "prettier": "^2.8.8", - "siyuan": "^0.7.9", + "siyuan": "^0.8.0", "turbo": "^1.10.12" } } diff --git a/workspace/plugins/chinese-convert/.github/FUNDING.yml b/workspace/plugins/chinese-convert/.github/FUNDING.yml deleted file mode 100644 index 5051816..0000000 --- a/workspace/plugins/chinese-convert/.github/FUNDING.yml +++ /dev/null @@ -1,36 +0,0 @@ -# These are supported funding model platforms - - -# Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] -# github: - -# Replace with a single Patreon username -# patreon: - -# Replace with a single Open Collective username -# open_collective: - -# Replace with a single Ko-fi username -ko_fi: zuoqiu - -# Replace with a single Tidelift platform-name/package-name e.g., npm/babel -# tidelift: - -# Replace with a single Community Bridge project-name e.g., cloud-foundry -# community_bridge: - -# Replace with a single Liberapay username -# liberapay: - -# Replace with a single IssueHunt username -# issuehunt: - -# Replace with a single Otechie username -# otechie: - -# Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry -# lfx_crowdfunding: - -# Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] -custom: - - https://afdian.net/a/zuoqiu diff --git a/workspace/plugins/chinese-convert/.gitignore b/workspace/plugins/chinese-convert/.gitignore deleted file mode 100644 index c6bba59..0000000 --- a/workspace/plugins/chinese-convert/.gitignore +++ /dev/null @@ -1,130 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* -.pnpm-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# Snowpack dependency directory (https://snowpack.dev/) -web_modules/ - -# TypeScript cache -*.tsbuildinfo - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional stylelint cache -.stylelintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variable files -.env -.env.development.local -.env.test.local -.env.production.local -.env.local - -# parcel-bundler cache (https://parceljs.org/) -.cache -.parcel-cache - -# Next.js build output -.next -out - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -# Comment in the public line in if your project uses Gatsby and not Next.js -# https://nextjs.org/blog/next-9-1#public-directory-support -# public - -# vuepress build output -.vuepress/dist - -# vuepress v2.x temp and cache directory -.temp -.cache - -# Docusaurus cache and generated files -.docusaurus - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - -# Stores VSCode versions used for testing VSCode extensions -.vscode-test - -# yarn v2 -.yarn/cache -.yarn/unplugged -.yarn/build-state.yml -.yarn/install-state.gz -.pnp.* diff --git a/workspace/plugins/chinese-convert/CHANGELOG.md b/workspace/plugins/chinese-convert/CHANGELOG.md deleted file mode 100644 index a2ad534..0000000 --- a/workspace/plugins/chinese-convert/CHANGELOG.md +++ /dev/null @@ -1,4 +0,0 @@ -# 更改日志 | CHANGE LOG - -本文档由持续集成工作流自动构建,不要直接编辑此文件。 -This document is automatically built by the continuous integration workflow. Do not edit this file directly. diff --git a/workspace/plugins/chinese-convert/LICENSE b/workspace/plugins/chinese-convert/LICENSE deleted file mode 100644 index 0ad25db..0000000 --- a/workspace/plugins/chinese-convert/LICENSE +++ /dev/null @@ -1,661 +0,0 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. diff --git a/workspace/plugins/chinese-convert/README.md b/workspace/plugins/chinese-convert/README.md deleted file mode 100644 index 1e45002..0000000 --- a/workspace/plugins/chinese-convert/README.md +++ /dev/null @@ -1,40 +0,0 @@ -> **[READ ONLY] Subtree split of the [siyuan-packages-monorepo](https://github.com/Zuoqiu-Yingyi/siyuan-packages-monorepo) [/workspace/plugin/chinese-convert](https://github.com/Zuoqiu-Yingyi/siyuan-packages-monorepo/tree/main/workspace/plugin/chinese-convert)** - -
-icon - ---- -[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/Zuoqiu-Yingyi/siyuan-plugin-chinese-convert?include_prereleases&style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-chinese-convert/releases/latest) -[![GitHub Release Date](https://img.shields.io/github/release-date/Zuoqiu-Yingyi/siyuan-plugin-chinese-convert?style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-chinese-convert/releases/latest) -[![GitHub License](https://img.shields.io/github/license/Zuoqiu-Yingyi/siyuan-plugin-chinese-convert?style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-chinese-convert/blob/main/LICENSE) -[![GitHub last commit](https://img.shields.io/github/last-commit/Zuoqiu-Yingyi/siyuan-plugin-chinese-convert?style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-chinese-convert/commits/main) -![GitHub repo size](https://img.shields.io/github/repo-size/Zuoqiu-Yingyi/siyuan-plugin-chinese-convert?style=flat-square) -![hits](https://hits.b3log.org/Zuoqiu-Yingyi/siyuan-plugin-chinese-convert.svg) -[![GitHub all releases](https://img.shields.io/github/downloads/Zuoqiu-Yingyi/siyuan-plugin-chinese-convert/total?style=flat-square)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-chinese-convert/releases) - ---- -
- -## USER GUIDE - -[简体中文](./public/README_zh_CN.md) \| [English](./public/README.md) - -## DEVELOPER GUIDE - -### RELEASE STEPS - -1. Update the version number in `/package.json` and `/public/plugin.json`, then commit the changes in [monorepo](https://github.com/Zuoqiu-Yingyi/siyuan-packages-monorepo). -2. Run script `./scripts/git-subtree/chinese-convert/push.ps1` with the folowing command in **monorepo root dir** to push the subtree to sub-repository (`dev` branch). - ```powershell - pwsh -f "./scripts/git-subtree/chinese-convert/push.ps1" - ``` -3. Create a pull request from `dev` branch to `main` branch in sub-repository. -4. Merge the pull request. -5. Await for the CD workflow `release-please.yml` to complete, it will create a *release pull request* in sub-repository. -6. Merge the *release pull request*, it will create a new *pre-release* with current [changelog](./CHANGELOG.md) and a new *tag* with [semantic version](https://semver.org/) in sub-repository. -7. Await for the CD workflow `build.yml` to complete, it will update the distribution files to `publish` branch in sub-repository. -8. Await for the CD workflow `release-distribution.yml` to complete, it will create a new *pre-release* with an asset named `package.zip` and a new *tag* with timestamp in sub-repository. - -## CHANGELOG - -[CHANGE LOG](./CHANGELOG.md) diff --git a/workspace/pnpm-lock.yaml b/workspace/pnpm-lock.yaml index b85944e..e98b1ef 100644 --- a/workspace/pnpm-lock.yaml +++ b/workspace/pnpm-lock.yaml @@ -28,8 +28,8 @@ importers: specifier: ^2.8.8 version: 2.8.8 siyuan: - specifier: ^0.7.9 - version: 0.7.9 + specifier: ^0.8.0 + version: 0.8.0 turbo: specifier: ^1.10.12 version: 1.10.12 @@ -4474,6 +4474,15 @@ packages: picocolors: 1.0.0 source-map-js: 1.0.2 + /postcss@8.4.28: + resolution: {integrity: sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.6 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -4702,8 +4711,8 @@ packages: is-arrayish: 0.3.2 dev: true - /siyuan@0.7.9: - resolution: {integrity: sha512-X5olBQhfkgyPRF+d8agpcbAaFnCSvSkN3LWX7XU9jApmCfpJ/4PAmK7mKPfR1YGBpjFLRa/xTrv11BQ3hxN15Q==} + /siyuan@0.8.0: + resolution: {integrity: sha512-QbT/6YKetvmJ/1D7OaqF/zIK+TUXI6eUPJ48qlbqdJtN8/aN809+hsMz+2xUO5pxq5nc3+hSGomia5sBoXQRwQ==} dev: true /slash@3.0.0: @@ -5733,7 +5742,7 @@ packages: '@types/node': 20.5.0 esbuild: 0.18.20 less: 4.2.0 - postcss: 8.4.27 + postcss: 8.4.28 rollup: 3.28.0 optionalDependencies: fsevents: 2.3.2 From a2379f83bf58a397f414c5e31c4d56250b233ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Wed, 16 Aug 2023 13:31:07 +0800 Subject: [PATCH 10/16] Squashed 'workspace/plugins/template/' content from commit f11419a git-subtree-dir: workspace/plugins/template git-subtree-split: f11419ab1977de6dfcfc75593caf1290d3c0bc48 --- LICENSE | 661 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 661 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0ad25db --- /dev/null +++ b/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. From 3546a74fd19e7d87db427d40061a508949aceb6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Wed, 16 Aug 2023 14:18:55 +0800 Subject: [PATCH 11/16] =?UTF-8?q?feat(template):=20=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E6=8F=92=E4=BB=B6=E6=A8=A1=E6=9D=BF=20|=20Improve=20plugin=20t?= =?UTF-8?q?emplate.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + .../plugins/template/.github/FUNDING.yml | 36 ++++++ .../template/.github/workflows/build.yml | 93 ++++++++++++++ .../workflows/release-distribution.yml | 81 ++++++++++++ .../.github/workflows/release-please.yml | 112 +++++++++++++++++ workspace/plugins/template/.gitignore | 24 ++++ workspace/plugins/template/README.md | 41 +++++++ workspace/plugins/template/package.json | 29 +++++ workspace/plugins/template/public/README.md | 36 ++++++ .../plugins/template/public/README_zh_CN.md | 36 ++++++ .../plugins/template/public/i18n/en_US.json | 13 ++ .../plugins/template/public/i18n/zh_CHT.json | 13 ++ .../plugins/template/public/i18n/zh_CN.json | 13 ++ workspace/plugins/template/public/plugin.json | 37 ++++++ .../plugins/template/src/assets/symbols/.keep | 0 .../template/src/components/Settings.svelte | 99 +++++++++++++++ .../plugins/template/src/configs/default.ts | 21 ++++ workspace/plugins/template/src/index.ts | 116 ++++++++++++++++++ .../plugins/template/src/types/config.d.ts | 19 +++ workspace/plugins/template/src/utils/i18n.ts | 33 +++++ workspace/plugins/template/src/vite-env.d.ts | 2 + workspace/plugins/template/svelte.config.js | 24 ++++ workspace/plugins/template/tsconfig.json | 38 ++++++ workspace/plugins/template/tsconfig.node.json | 11 ++ workspace/plugins/template/vite.config.ts | 77 ++++++++++++ workspace/pnpm-lock.yaml | 40 ++++++ 26 files changed, 1045 insertions(+) create mode 100644 workspace/plugins/template/.github/FUNDING.yml create mode 100644 workspace/plugins/template/.github/workflows/build.yml create mode 100644 workspace/plugins/template/.github/workflows/release-distribution.yml create mode 100644 workspace/plugins/template/.github/workflows/release-please.yml create mode 100644 workspace/plugins/template/.gitignore create mode 100644 workspace/plugins/template/README.md create mode 100644 workspace/plugins/template/package.json create mode 100644 workspace/plugins/template/public/README.md create mode 100644 workspace/plugins/template/public/README_zh_CN.md create mode 100644 workspace/plugins/template/public/i18n/en_US.json create mode 100644 workspace/plugins/template/public/i18n/zh_CHT.json create mode 100644 workspace/plugins/template/public/i18n/zh_CN.json create mode 100644 workspace/plugins/template/public/plugin.json create mode 100644 workspace/plugins/template/src/assets/symbols/.keep create mode 100644 workspace/plugins/template/src/components/Settings.svelte create mode 100644 workspace/plugins/template/src/configs/default.ts create mode 100644 workspace/plugins/template/src/index.ts create mode 100644 workspace/plugins/template/src/types/config.d.ts create mode 100644 workspace/plugins/template/src/utils/i18n.ts create mode 100644 workspace/plugins/template/src/vite-env.d.ts create mode 100644 workspace/plugins/template/svelte.config.js create mode 100644 workspace/plugins/template/tsconfig.json create mode 100644 workspace/plugins/template/tsconfig.node.json create mode 100644 workspace/plugins/template/vite.config.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index a48cff8..45bfc14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - 添加文件/文件夹更新时间 | Add file/folder update time. - 添加 `复制导出超链接` 菜单项 | Add `Copy export hyperlink` menu item. - 添加附属仓库 `template` 的管理脚本 | Add management scripts for sub-repository `template`. +- 完善插件模板 | Improve plugin template. ## 2023-08-15 diff --git a/workspace/plugins/template/.github/FUNDING.yml b/workspace/plugins/template/.github/FUNDING.yml new file mode 100644 index 0000000..5051816 --- /dev/null +++ b/workspace/plugins/template/.github/FUNDING.yml @@ -0,0 +1,36 @@ +# These are supported funding model platforms + + +# Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +# github: + +# Replace with a single Patreon username +# patreon: + +# Replace with a single Open Collective username +# open_collective: + +# Replace with a single Ko-fi username +ko_fi: zuoqiu + +# Replace with a single Tidelift platform-name/package-name e.g., npm/babel +# tidelift: + +# Replace with a single Community Bridge project-name e.g., cloud-foundry +# community_bridge: + +# Replace with a single Liberapay username +# liberapay: + +# Replace with a single IssueHunt username +# issuehunt: + +# Replace with a single Otechie username +# otechie: + +# Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +# lfx_crowdfunding: + +# Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] +custom: + - https://afdian.net/a/zuoqiu diff --git a/workspace/plugins/template/.github/workflows/build.yml b/workspace/plugins/template/.github/workflows/build.yml new file mode 100644 index 0000000..b100ee1 --- /dev/null +++ b/workspace/plugins/template/.github/workflows/build.yml @@ -0,0 +1,93 @@ +# 构建并部署 | Build and deploy + +name: build + +on: + workflow_dispatch: + push: + tags: + # REF https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet + - "v[0-9]+.[0-9]+.[0-9]+" + +env: + PACKAGE_PATH: ./workspace/plugins/template + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + steps: + # Checkout + # REF https://github.com/marketplace/actions/checkout + - name: Checkout + uses: actions/checkout@v3 + with: + ## 将要拉取的仓库 | repository will to pull + repository: Zuoqiu-Yingyi/siyuan-packages-monorepo + + # Install Node.js + # REF https://github.com/marketplace/actions/setup-node-js-environment + - name: Install Node.js + uses: actions/setup-node@v3 + with: + ## Node.js 版本号 | Node.js version + node-version: 20 + + ## Node.js 源 | Node.js registry + registry-url: https://registry.npmjs.org + + # Install pnpm + # REF https://github.com/marketplace/actions/setup-pnpm + - name: Install pnpm + uses: pnpm/action-setup@v2 + id: pnpm-install + with: + ## pnpm 版本号 | pnpm version + version: 8 + + ## 是否安装 npm 包 | if install npm package? + run_install: false + + # Get pnpm store directory + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + + # Setup pnpm cache + # REF https://github.com/marketplace/actions/cache + - name: Setup pnpm cache + uses: actions/cache@v3 + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + # Install dependencies + - name: Install dependencies + run: | + cd $GITHUB_WORKSPACE + cd ./workspace + pnpm install + + # Build package + - name: Build package + run: | + cd $GITHUB_WORKSPACE + cd $PACKAGE_PATH + pnpm build + + # Deploy to publish branch + # REF https://github.com/marketplace/actions/github-pages + - name: Deploy to publish branch + if: success() + uses: crazy-max/ghaction-github-pages@v3 + with: + ## 构建产物目录 | directory of build artifacts + build_dir: ${{ env.PACKAGE_PATH }}/dist + + ## 提交到目标分支 + target_branch: publish + env: + GITHUB_TOKEN: ${{ secrets.PAT_ACTIONS }} diff --git a/workspace/plugins/template/.github/workflows/release-distribution.yml b/workspace/plugins/template/.github/workflows/release-distribution.yml new file mode 100644 index 0000000..03ac4a4 --- /dev/null +++ b/workspace/plugins/template/.github/workflows/release-distribution.yml @@ -0,0 +1,81 @@ +# 发行构建产物 | Release the distribution + +name: release-distribution + +on: + workflow_dispatch: + # REF https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run + workflow_run: + workflows: + - build + types: + - completed + push: + branches: + - publish + +permissions: + contents: write + +jobs: + release-distribution: + runs-on: ubuntu-latest + steps: + # Checkout + # REF https://github.com/marketplace/actions/checkout + - name: Checkout + uses: actions/checkout@v3 + with: + ref: publish + + # Package + - name: Package + run: | + git archive -o ./package.zip HEAD + + # Get latest release + # REF https://github.com/marketplace/actions/get-latest-release + - name: Get latest release + uses: pozetroninc/github-action-get-latest-release@v0.7.0 + id: latest-release + with: + ## 仓库所有者/仓库名 | owner/name + repository: ${{ github.repository }} + + ## 排除的发行类型 | Excluded types of release + # excludes: prerelease, draft + excludes: draft + + # Get timestamp + # REF https://github.com/marketplace/actions/get-timestamp-action + - name: Get timestamp + uses: nanzm/get-time-action@v1.1 + id: timestamp + with: + ## 时区 | time zone + timeZone: 8 + + ## 时间戳格式 | timestamp format + format: "YYYYMMDDHHmmss" + + # Release distribution + # REF https://github.com/marketplace/actions/gh-release + - name: Release distribution + uses: softprops/action-gh-release@v1 + with: + ## 发行描述 | description of release + body: ${{ steps.latest-release.outputs.description }} + + ## 是否为预发行 | is prelease? + prerelease: true + + ## 标签名称 | tag name + # REF https://semver.org/ + tag_name: ${{ steps.latest-release.outputs.release }}+${{ steps.timestamp.outputs.time }} + + ## 标签关联的提交/分支 | The commit/branch associated with the tag + target_commitish: publish + + ## 附件列表 | attachment list + files: | + package.zip diff --git a/workspace/plugins/template/.github/workflows/release-please.yml b/workspace/plugins/template/.github/workflows/release-please.yml new file mode 100644 index 0000000..8cdd44e --- /dev/null +++ b/workspace/plugins/template/.github/workflows/release-please.yml @@ -0,0 +1,112 @@ +# 发行源码 | Release the source code + +name: release-please + +on: + workflow_dispatch: + push: + branches: + - main + +permissions: + contents: write + pull-requests: write + +env: + PACKAGE_NAME: custom-fonts + PACKAGE_VERSION: 0.0.0 + +jobs: + release-please: + runs-on: ubuntu-latest + steps: + # Create release + # REF https://github.com/marketplace/actions/release-please-action + - name: Create release + uses: google-github-actions/release-please-action@v3 + id: release + with: + release-type: node + package-name: ${{ env.PACKAGE_NAME }} + release-as: ${{ env.PACKAGE_VERSION }} + + ## A GitHub secret token, the action defaults to using the special secrets.GITHUB_TOKEN + ## REF https://github.com/marketplace/actions/release-please-action#github-credentials + token: ${{ secrets.PAT_ACTIONS }} + + ## branch to open pull release PR against (detected by default) + default-branch: main + + ## Should breaking changes before 1.0.0 produce minor bumps? Default false + bump-minor-pre-major: false + + ## Should feat changes before 1.0.0 produce patch bumps instead of minor bumps? Default false + bump-patch-for-minor-pre-major: false + + ## If set, create releases that are pre-major or pre-release version marked as pre-release on GitHub. Defaults false + prerelease: true + + ## header used within the release PR body, defaults to using :robot: I have created a release *beep* *boop* + pull-request-header: ":robot: A new release will be created" + + ## A JSON formatted String containing to override the outputted changelog sections + changelog-types: |- + [ + { + "type": "build", + "section": "Build System", + "hidden": false + }, + { + "type": "chore", + "section": "Miscellaneous", + "hidden": false + }, + { + "type": "ci", + "section": "Continuous Integration", + "hidden": false + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "feat", + "section": "Features", + "hidden": false + }, + { + "type": "fix", + "section": "Bug Fixes", + "hidden": false + }, + { + "type": "perf", + "section": "Performance Improvements" + }, + { + "type": "refactor", + "section": "Code Refactoring", + "hidden": false + }, + { + "type": "revert", + "section": "Reverts" + }, + { + "type": "style", + "section": "Styles", + "hidden": false + }, + { + "type": "test", + "section": "Tests", + "hidden": false + }, + { + "type": "", + "section": "Other Changes", + "hidden": false + } + ] diff --git a/workspace/plugins/template/.gitignore b/workspace/plugins/template/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/workspace/plugins/template/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/workspace/plugins/template/README.md b/workspace/plugins/template/README.md new file mode 100644 index 0000000..a78f95b --- /dev/null +++ b/workspace/plugins/template/README.md @@ -0,0 +1,41 @@ +> **[READ ONLY] Subtree split of the [siyuan-packages-monorepo](https://github.com/Zuoqiu-Yingyi/siyuan-packages-monorepo) [/workspace/plugins/template](https://github.com/Zuoqiu-Yingyi/siyuan-packages-monorepo/tree/main/workspace/plugins/template)** + +
+icon + +--- +[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/Zuoqiu-Yingyi/siyuan-plugin-template?include_prereleases)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases/latest) +[![GitHub Release Date](https://img.shields.io/github/release-date/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases/latest) +[![GitHub License](https://img.shields.io/github/license/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/blob/main/LICENSE) +[![GitHub last commit](https://img.shields.io/github/last-commit/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/commits/main) +![GitHub repo size](https://img.shields.io/github/repo-size/Zuoqiu-Yingyi/siyuan-plugin-template) + +![jsDelivr hits (GitHub)](https://img.shields.io/jsdelivr/gh/hy/Zuoqiu-Yingyi/siyuan-packages-template) +[![GitHub all releases](https://img.shields.io/github/downloads/Zuoqiu-Yingyi/siyuan-plugin-template/total)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases) + +--- +
+ +## USER GUIDE + +[简体中文](./public/README_zh_CN.md) \| [English](./public/README.md) + +## DEVELOPER GUIDE + +### RELEASE STEPS + +1. Update the version number in `/package.json` and `/public/plugin.json`, then commit the changes in [monorepo](https://github.com/Zuoqiu-Yingyi/siyuan-packages-monorepo). +2. Run script `./scripts/git-subtree/template/push.ps1` with the folowing command in **monorepo root dir** to push the subtree to sub-repository (`dev` branch). + ```powershell + pwsh -f "./scripts/git-subtree/template/push.ps1" + ``` +3. Create a pull request from `dev` branch to `main` branch in sub-repository. +4. Merge the pull request. +5. Await for the CD workflow `release-please.yml` to complete, it will create a *release pull request* in sub-repository. +6. Merge the *release pull request*, it will create a new *pre-release* with current [changelog](./CHANGELOG.md) and a new *tag* with [semantic version](https://semver.org/) in sub-repository. +7. Await for the CD workflow `build.yml` to complete, it will update the distribution files to `publish` branch in sub-repository. +8. Await for the CD workflow `release-distribution.yml` to complete, it will create a new *pre-release* with an asset named `package.zip` and a new *tag* with timestamp in sub-repository. + +## CHANGELOG + +[CHANGE LOG](./CHANGELOG.md) diff --git a/workspace/plugins/template/package.json b/workspace/plugins/template/package.json new file mode 100644 index 0000000..5528d42 --- /dev/null +++ b/workspace/plugins/template/package.json @@ -0,0 +1,29 @@ +{ + "name": "template", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "build:dev": "vite build --sourcemap inline", + "preview": "vite preview", + "check": "svelte-check --tsconfig ./tsconfig.json" + }, + "devDependencies": { + "@sveltejs/vite-plugin-svelte": "^2.4.5", + "@tsconfig/svelte": "^5.0.0", + "less": "^4.2.0", + "svelte": "^4.2.0", + "svelte-check": "^3.5.0", + "svelte-preprocess-less": "^0.4.0", + "tslib": "^2.6.1", + "typescript": "^5.1.6", + "vite": "^4.4.9" + }, + "dependencies": { + "@workspace/components": "workspace:^", + "@workspace/types": "workspace:^", + "@workspace/utils": "workspace:^" + } +} diff --git a/workspace/plugins/template/public/README.md b/workspace/plugins/template/public/README.md new file mode 100644 index 0000000..3a1795c --- /dev/null +++ b/workspace/plugins/template/public/README.md @@ -0,0 +1,36 @@ +
+icon + +--- +[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/Zuoqiu-Yingyi/siyuan-plugin-template?include_prereleases)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases/latest) +[![GitHub Release Date](https://img.shields.io/github/release-date/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases/latest) +[![GitHub License](https://img.shields.io/github/license/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/blob/main/LICENSE) +[![GitHub last commit](https://img.shields.io/github/last-commit/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/commits/main) +![GitHub repo size](https://img.shields.io/github/repo-size/Zuoqiu-Yingyi/siyuan-plugin-template) + +![jsDelivr hits (GitHub)](https://img.shields.io/jsdelivr/gh/hy/Zuoqiu-Yingyi/siyuan-packages-template) +[![GitHub all releases](https://img.shields.io/github/downloads/Zuoqiu-Yingyi/siyuan-plugin-template/total)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases) + +--- +[简体中文](./README_zh_CN.md) \| English + +--- +
+ +# SiYuan Plubin Template + +## PREVIEW + +![preview image](https://cdn.jsdelivr.net/gh/Zuoqiu-Yingyi/siyuan-plugin-template/public/preview.png) + +## Q & A + +## INTRODUCTION + +### Features Introduction + +### Settings Introduction + +## CHANGELOG + +[CHANGELOG.md](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/blob/main/CHANGELOG.md) diff --git a/workspace/plugins/template/public/README_zh_CN.md b/workspace/plugins/template/public/README_zh_CN.md new file mode 100644 index 0000000..387dbee --- /dev/null +++ b/workspace/plugins/template/public/README_zh_CN.md @@ -0,0 +1,36 @@ +
+图标 + +--- +[![GitHub 最新发行版本 (最新一次发行/预发行)](https://img.shields.io/github/v/release/Zuoqiu-Yingyi/siyuan-plugin-template?include_prereleases)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases/latest) +[![GitHub 最新发行时间](https://img.shields.io/github/release-date/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases/latest) +[![GitHub 许可证](https://img.shields.io/github/license/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/blob/main/LICENSE) +[![GitHub 最后一次提交时间](https://img.shields.io/github/last-commit/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/commits/main) +![GitHub 仓库大小](https://img.shields.io/github/repo-size/Zuoqiu-Yingyi/siyuan-plugin-template) + +![jsDelivr 查看次數 (GitHub)](https://img.shields.io/jsdelivr/gh/hy/Zuoqiu-Yingyi/siyuan-packages-template) +[![GitHub 发行版本下载次数](https://img.shields.io/github/downloads/Zuoqiu-Yingyi/siyuan-plugin-template/total)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases) + +--- +简体中文 \| [English](./README.md) + +--- +
+ +# 思源插件模板 + +## 预览 + +![预览图片](https://cdn.jsdelivr.net/gh/Zuoqiu-Yingyi/siyuan-plugin-template/public/preview.png) + +## 常见问题 + +## 介绍 + +### 功能介绍 + +### 设置项介绍 + +## 更改日志 + +[CHANGELOG.md](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/blob/main/CHANGELOG.md) diff --git a/workspace/plugins/template/public/i18n/en_US.json b/workspace/plugins/template/public/i18n/en_US.json new file mode 100644 index 0000000..f1b14f6 --- /dev/null +++ b/workspace/plugins/template/public/i18n/en_US.json @@ -0,0 +1,13 @@ +{ + "displayName": "", + "settings": { + "generalSettings": { + "reset": { + "description": "Reset all settings options to default options (refresh page after reset)", + "text": "Reset", + "title": "Reset settings options" + }, + "title": "General" + } + } +} diff --git a/workspace/plugins/template/public/i18n/zh_CHT.json b/workspace/plugins/template/public/i18n/zh_CHT.json new file mode 100644 index 0000000..3207e23 --- /dev/null +++ b/workspace/plugins/template/public/i18n/zh_CHT.json @@ -0,0 +1,13 @@ +{ + "displayName": "", + "settings": { + "generalSettings": { + "reset": { + "description": "重置所有設定選項為預設選項(重置後將重新整理頁面)", + "text": "重置", + "title": "重置設定選項" + }, + "title": "常規設定" + } + } +} diff --git a/workspace/plugins/template/public/i18n/zh_CN.json b/workspace/plugins/template/public/i18n/zh_CN.json new file mode 100644 index 0000000..5a98932 --- /dev/null +++ b/workspace/plugins/template/public/i18n/zh_CN.json @@ -0,0 +1,13 @@ +{ + "displayName": "", + "settings": { + "generalSettings": { + "reset": { + "description": "重置所有设置选项为默认选项(重置后将刷新页面)", + "text": "重置", + "title": "重置设置选项" + }, + "title": "常规设置" + } + } +} diff --git a/workspace/plugins/template/public/plugin.json b/workspace/plugins/template/public/plugin.json new file mode 100644 index 0000000..7681926 --- /dev/null +++ b/workspace/plugins/template/public/plugin.json @@ -0,0 +1,37 @@ +{ + "name": "template", + "author": "Zuoqiu Yingyi", + "url": "https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template", + "version": "0.0.0", + "minAppVersion": "2.9.0", + "backends": [ + "all" + ], + "frontends": [ + "all" + ], + "displayName": { + "default": "", + "zh_CN": "", + "zh_CHT": "" + }, + "description": { + "default": "", + "zh_CN": "", + "zh_CHT": "" + }, + "readme": { + "default": "README.md", + "zh_CN": "README_zh_CN.md", + "zh_CHT": "README_zh_CN.md" + }, + "funding": { + "openCollective": "", + "patreon": "", + "github": "", + "custom": [ + "https://afdian.net/a/zuoqiu", + "https://ko-fi.com/zuoqiu" + ] + } +} diff --git a/workspace/plugins/template/src/assets/symbols/.keep b/workspace/plugins/template/src/assets/symbols/.keep new file mode 100644 index 0000000..e69de29 diff --git a/workspace/plugins/template/src/components/Settings.svelte b/workspace/plugins/template/src/components/Settings.svelte new file mode 100644 index 0000000..b746d56 --- /dev/null +++ b/workspace/plugins/template/src/components/Settings.svelte @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + diff --git a/workspace/plugins/template/src/configs/default.ts b/workspace/plugins/template/src/configs/default.ts new file mode 100644 index 0000000..03cb049 --- /dev/null +++ b/workspace/plugins/template/src/configs/default.ts @@ -0,0 +1,21 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import type { IConfig } from "@/types/config"; + +export const DEFAULT_CONFIG: IConfig = { +}; diff --git a/workspace/plugins/template/src/index.ts b/workspace/plugins/template/src/index.ts new file mode 100644 index 0000000..fb3f1f7 --- /dev/null +++ b/workspace/plugins/template/src/index.ts @@ -0,0 +1,116 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import siyuan from "siyuan"; + +import { + Client, + type types, +} from "@siyuan-community/siyuan-sdk"; + +import Settings from "./components/Settings.svelte"; + +import { + FLAG_MOBILE, +} from "@workspace/utils/env/front-end"; +import { Logger } from "@workspace/utils/logger"; +import { mergeIgnoreArray } from "@workspace/utils/misc/merge"; +import { DEFAULT_CONFIG } from "./configs/default"; +import type { IConfig } from "./types/config"; + +import type { + IWebSocketMainEvent, + IClickEditorContentEvent, + ILoadedProtyleEvent, +} from "@workspace/types/siyuan/events"; +import type { BlockID } from "@workspace/types/siyuan"; + +type INotebook = types.kernel.api.notebook.lsNotebooks.INotebook; + +export default class WakaTimePlugin extends siyuan.Plugin { + static readonly GLOBAL_CONFIG_NAME = "global-config"; + + public readonly siyuan = siyuan; + public readonly logger: InstanceType; + public readonly client: InstanceType; + public readonly notebook = new Map(); // 笔记本 ID => 笔记本信息 + + protected readonly SETTINGS_DIALOG_ID: string; + + protected config: IConfig; + + constructor(options: any) { + super(options); + + this.logger = new Logger(this.name); + this.client = new Client(undefined, "fetch"); + + this.SETTINGS_DIALOG_ID = `${this.name}-settings-dialog`; + } + + onload(): void { + // this.logger.debug(this); + + /* 注册图标 */ + this.addIcons([ + ].join("")); + + this.loadData(WakaTimePlugin.GLOBAL_CONFIG_NAME) + .then(config => { + this.config = mergeIgnoreArray(DEFAULT_CONFIG, config || {}) as IConfig; + }) + .catch(error => this.logger.error(error)) + .finally(() => { + }); + } + + onLayoutReady(): void { + } + + onunload(): void { + } + + openSetting(): void { + const that = this; + const dialog = new siyuan.Dialog({ + title: `${this.i18n.displayName} ${this.name}`, + content: `
`, + width: FLAG_MOBILE ? "92vw" : "720px", + height: FLAG_MOBILE ? undefined : "640px", + }); + const settings = new Settings({ + target: dialog.element.querySelector(`#${that.SETTINGS_DIALOG_ID}`), + props: { + config: this.config, + plugin: this, + }, + }); + } + + /* 重置插件配置 */ + public async resetConfig(): Promise { + return this.updateConfig(mergeIgnoreArray(DEFAULT_CONFIG) as IConfig); + } + + /* 更新插件配置 */ + public async updateConfig(config?: IConfig): Promise { + if (config && config !== this.config) { + this.config = config; + } + return this.saveData(WakaTimePlugin.GLOBAL_CONFIG_NAME, this.config); + } +}; diff --git a/workspace/plugins/template/src/types/config.d.ts b/workspace/plugins/template/src/types/config.d.ts new file mode 100644 index 0000000..8b6f336 --- /dev/null +++ b/workspace/plugins/template/src/types/config.d.ts @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +export interface IConfig { +} diff --git a/workspace/plugins/template/src/utils/i18n.ts b/workspace/plugins/template/src/utils/i18n.ts new file mode 100644 index 0000000..c5b0430 --- /dev/null +++ b/workspace/plugins/template/src/utils/i18n.ts @@ -0,0 +1,33 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { + i18nCheck, + i18nChecks, +} from "@workspace/types/siyuan/i18n"; + +import zh_Hans from "~/public/i18n/zh_CN.json"; +import zh_Hant from "~/public/i18n/zh_CHT.json"; +import en from "~/public/i18n/en_US.json"; + +export type I18N = typeof zh_Hans; + +i18nChecks([ + i18nCheck(), + i18nCheck(), + i18nCheck(), +]); diff --git a/workspace/plugins/template/src/vite-env.d.ts b/workspace/plugins/template/src/vite-env.d.ts new file mode 100644 index 0000000..4078e74 --- /dev/null +++ b/workspace/plugins/template/src/vite-env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/workspace/plugins/template/svelte.config.js b/workspace/plugins/template/svelte.config.js new file mode 100644 index 0000000..a7db43f --- /dev/null +++ b/workspace/plugins/template/svelte.config.js @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + // Consult https://svelte.dev/docs#compile-time-svelte-preprocess + // for more information about preprocessors + preprocess: vitePreprocess(), +} diff --git a/workspace/plugins/template/tsconfig.json b/workspace/plugins/template/tsconfig.json new file mode 100644 index 0000000..228eb95 --- /dev/null +++ b/workspace/plugins/template/tsconfig.json @@ -0,0 +1,38 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "module": "ESNext", + "resolveJsonModule": true, + /** + * Typecheck JS in `.svelte` and `.js` files by default. + * Disable checkJs if you'd like to use dynamic types in JS. + * Note that setting allowJs false does not prevent the use + * of JS in `.svelte` files. + */ + "allowJs": true, + "checkJs": true, + "isolatedModules": true, + "baseUrl": "./", + "paths": { + "~/*": [ + "./*", + ], + "@/*": [ + "src/*", + ], + }, + }, + "include": [ + "src/**/*.d.ts", + "src/**/*.ts", + "src/**/*.js", + "src/**/*.svelte", + ], + "references": [ + { + "path": "./tsconfig.node.json" + }, + ], +} diff --git a/workspace/plugins/template/tsconfig.node.json b/workspace/plugins/template/tsconfig.node.json new file mode 100644 index 0000000..f61a9de --- /dev/null +++ b/workspace/plugins/template/tsconfig.node.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler" + }, + "include": [ + "vite.config.ts" + ] +} diff --git a/workspace/plugins/template/vite.config.ts b/workspace/plugins/template/vite.config.ts new file mode 100644 index 0000000..4acf21e --- /dev/null +++ b/workspace/plugins/template/vite.config.ts @@ -0,0 +1,77 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { defineConfig } from "vite"; +import { resolve } from "path" +import { svelte } from "@sveltejs/vite-plugin-svelte"; +import { less } from "svelte-preprocess-less"; + +// https://vitejs.dev/config/ +export default defineConfig({ + base: `./`, + plugins: [ + svelte({ + preprocess: { + style: less(), + }, + }), + ], + resolve: { + alias: { + "~": resolve(__dirname, "./"), + "@": resolve(__dirname, "./src"), + } + }, + build: { + minify: true, + // sourcemap: "inline", + lib: { + entry: resolve(__dirname, "src/index.ts"), + fileName: "index", + formats: ["cjs"], + }, + rollupOptions: { + external: [ + "siyuan", + /^@electron\/.*$/, + ], + output: { + entryFileNames: chunkInfo => { + // console.log(chunkInfo); + switch (chunkInfo.name) { + case "index": + return "[name].js"; + + default: + return "assets/[name]-[hash].js"; + } + }, + assetFileNames: assetInfo => { + // console.log(chunkInfo); + switch (assetInfo.name) { + case "style.css": + case "index.css": + return "index.css"; + + default: + return "assets/[name]-[hash][extname]"; + } + }, + }, + }, + }, +}); diff --git a/workspace/pnpm-lock.yaml b/workspace/pnpm-lock.yaml index e98b1ef..7931a8a 100644 --- a/workspace/pnpm-lock.yaml +++ b/workspace/pnpm-lock.yaml @@ -376,6 +376,46 @@ importers: specifier: ^4.3.9 version: 4.3.9(less@4.1.3) + plugins/template: + dependencies: + '@workspace/components': + specifier: workspace:^ + version: link:../../packages/components + '@workspace/types': + specifier: workspace:^ + version: link:../../packages/types + '@workspace/utils': + specifier: workspace:^ + version: link:../../packages/utils + devDependencies: + '@sveltejs/vite-plugin-svelte': + specifier: ^2.4.5 + version: 2.4.5(svelte@4.2.0)(vite@4.4.9) + '@tsconfig/svelte': + specifier: ^5.0.0 + version: 5.0.0 + less: + specifier: ^4.2.0 + version: 4.2.0 + svelte: + specifier: ^4.2.0 + version: 4.2.0 + svelte-check: + specifier: ^3.5.0 + version: 3.5.0(less@4.2.0)(svelte@4.2.0) + svelte-preprocess-less: + specifier: ^0.4.0 + version: 0.4.0 + tslib: + specifier: ^2.6.1 + version: 2.6.1 + typescript: + specifier: ^5.1.6 + version: 5.1.6 + vite: + specifier: ^4.4.9 + version: 4.4.9(@types/node@20.5.0)(less@4.2.0) + plugins/wakatime: dependencies: '@workspace/components': From a33c8ee2eb76f2a41a21941231b731fc433fad7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Wed, 16 Aug 2023 14:18:55 +0800 Subject: [PATCH 12/16] =?UTF-8?q?feat(template):=20=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E6=8F=92=E4=BB=B6=E6=A8=A1=E6=9D=BF=20|=20Improve=20plugin=20t?= =?UTF-8?q?emplate.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/FUNDING.yml | 36 +++++++ .github/workflows/build.yml | 93 +++++++++++++++++ .github/workflows/release-distribution.yml | 81 ++++++++++++++ .github/workflows/release-please.yml | 112 ++++++++++++++++++++ .gitignore | 24 +++++ README.md | 41 ++++++++ package.json | 29 ++++++ public/README.md | 36 +++++++ public/README_zh_CN.md | 36 +++++++ public/i18n/en_US.json | 13 +++ public/i18n/zh_CHT.json | 13 +++ public/i18n/zh_CN.json | 13 +++ public/plugin.json | 37 +++++++ src/assets/symbols/.keep | 0 src/components/Settings.svelte | 99 ++++++++++++++++++ src/configs/default.ts | 21 ++++ src/index.ts | 116 +++++++++++++++++++++ src/types/config.d.ts | 19 ++++ src/utils/i18n.ts | 33 ++++++ src/vite-env.d.ts | 2 + svelte.config.js | 24 +++++ tsconfig.json | 38 +++++++ tsconfig.node.json | 11 ++ vite.config.ts | 77 ++++++++++++++ 24 files changed, 1004 insertions(+) create mode 100644 .github/FUNDING.yml create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/release-distribution.yml create mode 100644 .github/workflows/release-please.yml create mode 100644 .gitignore create mode 100644 README.md create mode 100644 package.json create mode 100644 public/README.md create mode 100644 public/README_zh_CN.md create mode 100644 public/i18n/en_US.json create mode 100644 public/i18n/zh_CHT.json create mode 100644 public/i18n/zh_CN.json create mode 100644 public/plugin.json create mode 100644 src/assets/symbols/.keep create mode 100644 src/components/Settings.svelte create mode 100644 src/configs/default.ts create mode 100644 src/index.ts create mode 100644 src/types/config.d.ts create mode 100644 src/utils/i18n.ts create mode 100644 src/vite-env.d.ts create mode 100644 svelte.config.js create mode 100644 tsconfig.json create mode 100644 tsconfig.node.json create mode 100644 vite.config.ts diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..5051816 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,36 @@ +# These are supported funding model platforms + + +# Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +# github: + +# Replace with a single Patreon username +# patreon: + +# Replace with a single Open Collective username +# open_collective: + +# Replace with a single Ko-fi username +ko_fi: zuoqiu + +# Replace with a single Tidelift platform-name/package-name e.g., npm/babel +# tidelift: + +# Replace with a single Community Bridge project-name e.g., cloud-foundry +# community_bridge: + +# Replace with a single Liberapay username +# liberapay: + +# Replace with a single IssueHunt username +# issuehunt: + +# Replace with a single Otechie username +# otechie: + +# Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +# lfx_crowdfunding: + +# Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] +custom: + - https://afdian.net/a/zuoqiu diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..b100ee1 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,93 @@ +# 构建并部署 | Build and deploy + +name: build + +on: + workflow_dispatch: + push: + tags: + # REF https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet + - "v[0-9]+.[0-9]+.[0-9]+" + +env: + PACKAGE_PATH: ./workspace/plugins/template + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + steps: + # Checkout + # REF https://github.com/marketplace/actions/checkout + - name: Checkout + uses: actions/checkout@v3 + with: + ## 将要拉取的仓库 | repository will to pull + repository: Zuoqiu-Yingyi/siyuan-packages-monorepo + + # Install Node.js + # REF https://github.com/marketplace/actions/setup-node-js-environment + - name: Install Node.js + uses: actions/setup-node@v3 + with: + ## Node.js 版本号 | Node.js version + node-version: 20 + + ## Node.js 源 | Node.js registry + registry-url: https://registry.npmjs.org + + # Install pnpm + # REF https://github.com/marketplace/actions/setup-pnpm + - name: Install pnpm + uses: pnpm/action-setup@v2 + id: pnpm-install + with: + ## pnpm 版本号 | pnpm version + version: 8 + + ## 是否安装 npm 包 | if install npm package? + run_install: false + + # Get pnpm store directory + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + + # Setup pnpm cache + # REF https://github.com/marketplace/actions/cache + - name: Setup pnpm cache + uses: actions/cache@v3 + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + # Install dependencies + - name: Install dependencies + run: | + cd $GITHUB_WORKSPACE + cd ./workspace + pnpm install + + # Build package + - name: Build package + run: | + cd $GITHUB_WORKSPACE + cd $PACKAGE_PATH + pnpm build + + # Deploy to publish branch + # REF https://github.com/marketplace/actions/github-pages + - name: Deploy to publish branch + if: success() + uses: crazy-max/ghaction-github-pages@v3 + with: + ## 构建产物目录 | directory of build artifacts + build_dir: ${{ env.PACKAGE_PATH }}/dist + + ## 提交到目标分支 + target_branch: publish + env: + GITHUB_TOKEN: ${{ secrets.PAT_ACTIONS }} diff --git a/.github/workflows/release-distribution.yml b/.github/workflows/release-distribution.yml new file mode 100644 index 0000000..03ac4a4 --- /dev/null +++ b/.github/workflows/release-distribution.yml @@ -0,0 +1,81 @@ +# 发行构建产物 | Release the distribution + +name: release-distribution + +on: + workflow_dispatch: + # REF https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run + workflow_run: + workflows: + - build + types: + - completed + push: + branches: + - publish + +permissions: + contents: write + +jobs: + release-distribution: + runs-on: ubuntu-latest + steps: + # Checkout + # REF https://github.com/marketplace/actions/checkout + - name: Checkout + uses: actions/checkout@v3 + with: + ref: publish + + # Package + - name: Package + run: | + git archive -o ./package.zip HEAD + + # Get latest release + # REF https://github.com/marketplace/actions/get-latest-release + - name: Get latest release + uses: pozetroninc/github-action-get-latest-release@v0.7.0 + id: latest-release + with: + ## 仓库所有者/仓库名 | owner/name + repository: ${{ github.repository }} + + ## 排除的发行类型 | Excluded types of release + # excludes: prerelease, draft + excludes: draft + + # Get timestamp + # REF https://github.com/marketplace/actions/get-timestamp-action + - name: Get timestamp + uses: nanzm/get-time-action@v1.1 + id: timestamp + with: + ## 时区 | time zone + timeZone: 8 + + ## 时间戳格式 | timestamp format + format: "YYYYMMDDHHmmss" + + # Release distribution + # REF https://github.com/marketplace/actions/gh-release + - name: Release distribution + uses: softprops/action-gh-release@v1 + with: + ## 发行描述 | description of release + body: ${{ steps.latest-release.outputs.description }} + + ## 是否为预发行 | is prelease? + prerelease: true + + ## 标签名称 | tag name + # REF https://semver.org/ + tag_name: ${{ steps.latest-release.outputs.release }}+${{ steps.timestamp.outputs.time }} + + ## 标签关联的提交/分支 | The commit/branch associated with the tag + target_commitish: publish + + ## 附件列表 | attachment list + files: | + package.zip diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 0000000..8cdd44e --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,112 @@ +# 发行源码 | Release the source code + +name: release-please + +on: + workflow_dispatch: + push: + branches: + - main + +permissions: + contents: write + pull-requests: write + +env: + PACKAGE_NAME: custom-fonts + PACKAGE_VERSION: 0.0.0 + +jobs: + release-please: + runs-on: ubuntu-latest + steps: + # Create release + # REF https://github.com/marketplace/actions/release-please-action + - name: Create release + uses: google-github-actions/release-please-action@v3 + id: release + with: + release-type: node + package-name: ${{ env.PACKAGE_NAME }} + release-as: ${{ env.PACKAGE_VERSION }} + + ## A GitHub secret token, the action defaults to using the special secrets.GITHUB_TOKEN + ## REF https://github.com/marketplace/actions/release-please-action#github-credentials + token: ${{ secrets.PAT_ACTIONS }} + + ## branch to open pull release PR against (detected by default) + default-branch: main + + ## Should breaking changes before 1.0.0 produce minor bumps? Default false + bump-minor-pre-major: false + + ## Should feat changes before 1.0.0 produce patch bumps instead of minor bumps? Default false + bump-patch-for-minor-pre-major: false + + ## If set, create releases that are pre-major or pre-release version marked as pre-release on GitHub. Defaults false + prerelease: true + + ## header used within the release PR body, defaults to using :robot: I have created a release *beep* *boop* + pull-request-header: ":robot: A new release will be created" + + ## A JSON formatted String containing to override the outputted changelog sections + changelog-types: |- + [ + { + "type": "build", + "section": "Build System", + "hidden": false + }, + { + "type": "chore", + "section": "Miscellaneous", + "hidden": false + }, + { + "type": "ci", + "section": "Continuous Integration", + "hidden": false + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "feat", + "section": "Features", + "hidden": false + }, + { + "type": "fix", + "section": "Bug Fixes", + "hidden": false + }, + { + "type": "perf", + "section": "Performance Improvements" + }, + { + "type": "refactor", + "section": "Code Refactoring", + "hidden": false + }, + { + "type": "revert", + "section": "Reverts" + }, + { + "type": "style", + "section": "Styles", + "hidden": false + }, + { + "type": "test", + "section": "Tests", + "hidden": false + }, + { + "type": "", + "section": "Other Changes", + "hidden": false + } + ] diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/README.md b/README.md new file mode 100644 index 0000000..a78f95b --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +> **[READ ONLY] Subtree split of the [siyuan-packages-monorepo](https://github.com/Zuoqiu-Yingyi/siyuan-packages-monorepo) [/workspace/plugins/template](https://github.com/Zuoqiu-Yingyi/siyuan-packages-monorepo/tree/main/workspace/plugins/template)** + +
+icon + +--- +[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/Zuoqiu-Yingyi/siyuan-plugin-template?include_prereleases)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases/latest) +[![GitHub Release Date](https://img.shields.io/github/release-date/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases/latest) +[![GitHub License](https://img.shields.io/github/license/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/blob/main/LICENSE) +[![GitHub last commit](https://img.shields.io/github/last-commit/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/commits/main) +![GitHub repo size](https://img.shields.io/github/repo-size/Zuoqiu-Yingyi/siyuan-plugin-template) + +![jsDelivr hits (GitHub)](https://img.shields.io/jsdelivr/gh/hy/Zuoqiu-Yingyi/siyuan-packages-template) +[![GitHub all releases](https://img.shields.io/github/downloads/Zuoqiu-Yingyi/siyuan-plugin-template/total)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases) + +--- +
+ +## USER GUIDE + +[简体中文](./public/README_zh_CN.md) \| [English](./public/README.md) + +## DEVELOPER GUIDE + +### RELEASE STEPS + +1. Update the version number in `/package.json` and `/public/plugin.json`, then commit the changes in [monorepo](https://github.com/Zuoqiu-Yingyi/siyuan-packages-monorepo). +2. Run script `./scripts/git-subtree/template/push.ps1` with the folowing command in **monorepo root dir** to push the subtree to sub-repository (`dev` branch). + ```powershell + pwsh -f "./scripts/git-subtree/template/push.ps1" + ``` +3. Create a pull request from `dev` branch to `main` branch in sub-repository. +4. Merge the pull request. +5. Await for the CD workflow `release-please.yml` to complete, it will create a *release pull request* in sub-repository. +6. Merge the *release pull request*, it will create a new *pre-release* with current [changelog](./CHANGELOG.md) and a new *tag* with [semantic version](https://semver.org/) in sub-repository. +7. Await for the CD workflow `build.yml` to complete, it will update the distribution files to `publish` branch in sub-repository. +8. Await for the CD workflow `release-distribution.yml` to complete, it will create a new *pre-release* with an asset named `package.zip` and a new *tag* with timestamp in sub-repository. + +## CHANGELOG + +[CHANGE LOG](./CHANGELOG.md) diff --git a/package.json b/package.json new file mode 100644 index 0000000..5528d42 --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "template", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "build:dev": "vite build --sourcemap inline", + "preview": "vite preview", + "check": "svelte-check --tsconfig ./tsconfig.json" + }, + "devDependencies": { + "@sveltejs/vite-plugin-svelte": "^2.4.5", + "@tsconfig/svelte": "^5.0.0", + "less": "^4.2.0", + "svelte": "^4.2.0", + "svelte-check": "^3.5.0", + "svelte-preprocess-less": "^0.4.0", + "tslib": "^2.6.1", + "typescript": "^5.1.6", + "vite": "^4.4.9" + }, + "dependencies": { + "@workspace/components": "workspace:^", + "@workspace/types": "workspace:^", + "@workspace/utils": "workspace:^" + } +} diff --git a/public/README.md b/public/README.md new file mode 100644 index 0000000..3a1795c --- /dev/null +++ b/public/README.md @@ -0,0 +1,36 @@ +
+icon + +--- +[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/Zuoqiu-Yingyi/siyuan-plugin-template?include_prereleases)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases/latest) +[![GitHub Release Date](https://img.shields.io/github/release-date/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases/latest) +[![GitHub License](https://img.shields.io/github/license/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/blob/main/LICENSE) +[![GitHub last commit](https://img.shields.io/github/last-commit/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/commits/main) +![GitHub repo size](https://img.shields.io/github/repo-size/Zuoqiu-Yingyi/siyuan-plugin-template) + +![jsDelivr hits (GitHub)](https://img.shields.io/jsdelivr/gh/hy/Zuoqiu-Yingyi/siyuan-packages-template) +[![GitHub all releases](https://img.shields.io/github/downloads/Zuoqiu-Yingyi/siyuan-plugin-template/total)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases) + +--- +[简体中文](./README_zh_CN.md) \| English + +--- +
+ +# SiYuan Plubin Template + +## PREVIEW + +![preview image](https://cdn.jsdelivr.net/gh/Zuoqiu-Yingyi/siyuan-plugin-template/public/preview.png) + +## Q & A + +## INTRODUCTION + +### Features Introduction + +### Settings Introduction + +## CHANGELOG + +[CHANGELOG.md](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/blob/main/CHANGELOG.md) diff --git a/public/README_zh_CN.md b/public/README_zh_CN.md new file mode 100644 index 0000000..387dbee --- /dev/null +++ b/public/README_zh_CN.md @@ -0,0 +1,36 @@ +
+图标 + +--- +[![GitHub 最新发行版本 (最新一次发行/预发行)](https://img.shields.io/github/v/release/Zuoqiu-Yingyi/siyuan-plugin-template?include_prereleases)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases/latest) +[![GitHub 最新发行时间](https://img.shields.io/github/release-date/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases/latest) +[![GitHub 许可证](https://img.shields.io/github/license/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/blob/main/LICENSE) +[![GitHub 最后一次提交时间](https://img.shields.io/github/last-commit/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/commits/main) +![GitHub 仓库大小](https://img.shields.io/github/repo-size/Zuoqiu-Yingyi/siyuan-plugin-template) + +![jsDelivr 查看次數 (GitHub)](https://img.shields.io/jsdelivr/gh/hy/Zuoqiu-Yingyi/siyuan-packages-template) +[![GitHub 发行版本下载次数](https://img.shields.io/github/downloads/Zuoqiu-Yingyi/siyuan-plugin-template/total)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases) + +--- +简体中文 \| [English](./README.md) + +--- +
+ +# 思源插件模板 + +## 预览 + +![预览图片](https://cdn.jsdelivr.net/gh/Zuoqiu-Yingyi/siyuan-plugin-template/public/preview.png) + +## 常见问题 + +## 介绍 + +### 功能介绍 + +### 设置项介绍 + +## 更改日志 + +[CHANGELOG.md](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/blob/main/CHANGELOG.md) diff --git a/public/i18n/en_US.json b/public/i18n/en_US.json new file mode 100644 index 0000000..f1b14f6 --- /dev/null +++ b/public/i18n/en_US.json @@ -0,0 +1,13 @@ +{ + "displayName": "", + "settings": { + "generalSettings": { + "reset": { + "description": "Reset all settings options to default options (refresh page after reset)", + "text": "Reset", + "title": "Reset settings options" + }, + "title": "General" + } + } +} diff --git a/public/i18n/zh_CHT.json b/public/i18n/zh_CHT.json new file mode 100644 index 0000000..3207e23 --- /dev/null +++ b/public/i18n/zh_CHT.json @@ -0,0 +1,13 @@ +{ + "displayName": "", + "settings": { + "generalSettings": { + "reset": { + "description": "重置所有設定選項為預設選項(重置後將重新整理頁面)", + "text": "重置", + "title": "重置設定選項" + }, + "title": "常規設定" + } + } +} diff --git a/public/i18n/zh_CN.json b/public/i18n/zh_CN.json new file mode 100644 index 0000000..5a98932 --- /dev/null +++ b/public/i18n/zh_CN.json @@ -0,0 +1,13 @@ +{ + "displayName": "", + "settings": { + "generalSettings": { + "reset": { + "description": "重置所有设置选项为默认选项(重置后将刷新页面)", + "text": "重置", + "title": "重置设置选项" + }, + "title": "常规设置" + } + } +} diff --git a/public/plugin.json b/public/plugin.json new file mode 100644 index 0000000..7681926 --- /dev/null +++ b/public/plugin.json @@ -0,0 +1,37 @@ +{ + "name": "template", + "author": "Zuoqiu Yingyi", + "url": "https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template", + "version": "0.0.0", + "minAppVersion": "2.9.0", + "backends": [ + "all" + ], + "frontends": [ + "all" + ], + "displayName": { + "default": "", + "zh_CN": "", + "zh_CHT": "" + }, + "description": { + "default": "", + "zh_CN": "", + "zh_CHT": "" + }, + "readme": { + "default": "README.md", + "zh_CN": "README_zh_CN.md", + "zh_CHT": "README_zh_CN.md" + }, + "funding": { + "openCollective": "", + "patreon": "", + "github": "", + "custom": [ + "https://afdian.net/a/zuoqiu", + "https://ko-fi.com/zuoqiu" + ] + } +} diff --git a/src/assets/symbols/.keep b/src/assets/symbols/.keep new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Settings.svelte b/src/components/Settings.svelte new file mode 100644 index 0000000..b746d56 --- /dev/null +++ b/src/components/Settings.svelte @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + diff --git a/src/configs/default.ts b/src/configs/default.ts new file mode 100644 index 0000000..03cb049 --- /dev/null +++ b/src/configs/default.ts @@ -0,0 +1,21 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import type { IConfig } from "@/types/config"; + +export const DEFAULT_CONFIG: IConfig = { +}; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..fb3f1f7 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,116 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import siyuan from "siyuan"; + +import { + Client, + type types, +} from "@siyuan-community/siyuan-sdk"; + +import Settings from "./components/Settings.svelte"; + +import { + FLAG_MOBILE, +} from "@workspace/utils/env/front-end"; +import { Logger } from "@workspace/utils/logger"; +import { mergeIgnoreArray } from "@workspace/utils/misc/merge"; +import { DEFAULT_CONFIG } from "./configs/default"; +import type { IConfig } from "./types/config"; + +import type { + IWebSocketMainEvent, + IClickEditorContentEvent, + ILoadedProtyleEvent, +} from "@workspace/types/siyuan/events"; +import type { BlockID } from "@workspace/types/siyuan"; + +type INotebook = types.kernel.api.notebook.lsNotebooks.INotebook; + +export default class WakaTimePlugin extends siyuan.Plugin { + static readonly GLOBAL_CONFIG_NAME = "global-config"; + + public readonly siyuan = siyuan; + public readonly logger: InstanceType; + public readonly client: InstanceType; + public readonly notebook = new Map(); // 笔记本 ID => 笔记本信息 + + protected readonly SETTINGS_DIALOG_ID: string; + + protected config: IConfig; + + constructor(options: any) { + super(options); + + this.logger = new Logger(this.name); + this.client = new Client(undefined, "fetch"); + + this.SETTINGS_DIALOG_ID = `${this.name}-settings-dialog`; + } + + onload(): void { + // this.logger.debug(this); + + /* 注册图标 */ + this.addIcons([ + ].join("")); + + this.loadData(WakaTimePlugin.GLOBAL_CONFIG_NAME) + .then(config => { + this.config = mergeIgnoreArray(DEFAULT_CONFIG, config || {}) as IConfig; + }) + .catch(error => this.logger.error(error)) + .finally(() => { + }); + } + + onLayoutReady(): void { + } + + onunload(): void { + } + + openSetting(): void { + const that = this; + const dialog = new siyuan.Dialog({ + title: `${this.i18n.displayName} ${this.name}`, + content: `
`, + width: FLAG_MOBILE ? "92vw" : "720px", + height: FLAG_MOBILE ? undefined : "640px", + }); + const settings = new Settings({ + target: dialog.element.querySelector(`#${that.SETTINGS_DIALOG_ID}`), + props: { + config: this.config, + plugin: this, + }, + }); + } + + /* 重置插件配置 */ + public async resetConfig(): Promise { + return this.updateConfig(mergeIgnoreArray(DEFAULT_CONFIG) as IConfig); + } + + /* 更新插件配置 */ + public async updateConfig(config?: IConfig): Promise { + if (config && config !== this.config) { + this.config = config; + } + return this.saveData(WakaTimePlugin.GLOBAL_CONFIG_NAME, this.config); + } +}; diff --git a/src/types/config.d.ts b/src/types/config.d.ts new file mode 100644 index 0000000..8b6f336 --- /dev/null +++ b/src/types/config.d.ts @@ -0,0 +1,19 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +export interface IConfig { +} diff --git a/src/utils/i18n.ts b/src/utils/i18n.ts new file mode 100644 index 0000000..c5b0430 --- /dev/null +++ b/src/utils/i18n.ts @@ -0,0 +1,33 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { + i18nCheck, + i18nChecks, +} from "@workspace/types/siyuan/i18n"; + +import zh_Hans from "~/public/i18n/zh_CN.json"; +import zh_Hant from "~/public/i18n/zh_CHT.json"; +import en from "~/public/i18n/en_US.json"; + +export type I18N = typeof zh_Hans; + +i18nChecks([ + i18nCheck(), + i18nCheck(), + i18nCheck(), +]); diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..4078e74 --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/svelte.config.js b/svelte.config.js new file mode 100644 index 0000000..a7db43f --- /dev/null +++ b/svelte.config.js @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + // Consult https://svelte.dev/docs#compile-time-svelte-preprocess + // for more information about preprocessors + preprocess: vitePreprocess(), +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..228eb95 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,38 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "module": "ESNext", + "resolveJsonModule": true, + /** + * Typecheck JS in `.svelte` and `.js` files by default. + * Disable checkJs if you'd like to use dynamic types in JS. + * Note that setting allowJs false does not prevent the use + * of JS in `.svelte` files. + */ + "allowJs": true, + "checkJs": true, + "isolatedModules": true, + "baseUrl": "./", + "paths": { + "~/*": [ + "./*", + ], + "@/*": [ + "src/*", + ], + }, + }, + "include": [ + "src/**/*.d.ts", + "src/**/*.ts", + "src/**/*.js", + "src/**/*.svelte", + ], + "references": [ + { + "path": "./tsconfig.node.json" + }, + ], +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..f61a9de --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler" + }, + "include": [ + "vite.config.ts" + ] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..4acf21e --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,77 @@ +/** + * Copyright (C) 2023 Zuoqiu Yingyi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { defineConfig } from "vite"; +import { resolve } from "path" +import { svelte } from "@sveltejs/vite-plugin-svelte"; +import { less } from "svelte-preprocess-less"; + +// https://vitejs.dev/config/ +export default defineConfig({ + base: `./`, + plugins: [ + svelte({ + preprocess: { + style: less(), + }, + }), + ], + resolve: { + alias: { + "~": resolve(__dirname, "./"), + "@": resolve(__dirname, "./src"), + } + }, + build: { + minify: true, + // sourcemap: "inline", + lib: { + entry: resolve(__dirname, "src/index.ts"), + fileName: "index", + formats: ["cjs"], + }, + rollupOptions: { + external: [ + "siyuan", + /^@electron\/.*$/, + ], + output: { + entryFileNames: chunkInfo => { + // console.log(chunkInfo); + switch (chunkInfo.name) { + case "index": + return "[name].js"; + + default: + return "assets/[name]-[hash].js"; + } + }, + assetFileNames: assetInfo => { + // console.log(chunkInfo); + switch (assetInfo.name) { + case "style.css": + case "index.css": + return "index.css"; + + default: + return "assets/[name]-[hash][extname]"; + } + }, + }, + }, + }, +}); From 84be39e2a5bd7c33d1ba5adbbfc05cb0dd1d17a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Wed, 16 Aug 2023 14:24:23 +0800 Subject: [PATCH 13/16] =?UTF-8?q?chore:=20=E9=87=8D=E6=96=B0=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E9=99=84=E5=B1=9E=E4=BB=93=E5=BA=93=20`template`=20|?= =?UTF-8?q?=20Re-add=20sub-repository=20`template`.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + .../plugins/template/.github/FUNDING.yml | 36 - .../template/.github/workflows/build.yml | 93 --- .../workflows/release-distribution.yml | 81 --- .../.github/workflows/release-please.yml | 112 --- workspace/plugins/template/.gitignore | 24 - workspace/plugins/template/LICENSE | 661 ------------------ workspace/plugins/template/README.md | 41 -- workspace/plugins/template/package.json | 29 - workspace/plugins/template/public/README.md | 36 - .../plugins/template/public/README_zh_CN.md | 36 - .../plugins/template/public/i18n/en_US.json | 13 - .../plugins/template/public/i18n/zh_CHT.json | 13 - .../plugins/template/public/i18n/zh_CN.json | 13 - workspace/plugins/template/public/plugin.json | 37 - .../plugins/template/src/assets/symbols/.keep | 0 .../template/src/components/Settings.svelte | 99 --- .../plugins/template/src/configs/default.ts | 21 - workspace/plugins/template/src/index.ts | 116 --- .../plugins/template/src/types/config.d.ts | 19 - workspace/plugins/template/src/utils/i18n.ts | 33 - workspace/plugins/template/src/vite-env.d.ts | 2 - workspace/plugins/template/svelte.config.js | 24 - workspace/plugins/template/tsconfig.json | 38 - workspace/plugins/template/tsconfig.node.json | 11 - workspace/plugins/template/vite.config.ts | 77 -- 26 files changed, 1 insertion(+), 1665 deletions(-) delete mode 100644 workspace/plugins/template/.github/FUNDING.yml delete mode 100644 workspace/plugins/template/.github/workflows/build.yml delete mode 100644 workspace/plugins/template/.github/workflows/release-distribution.yml delete mode 100644 workspace/plugins/template/.github/workflows/release-please.yml delete mode 100644 workspace/plugins/template/.gitignore delete mode 100644 workspace/plugins/template/LICENSE delete mode 100644 workspace/plugins/template/README.md delete mode 100644 workspace/plugins/template/package.json delete mode 100644 workspace/plugins/template/public/README.md delete mode 100644 workspace/plugins/template/public/README_zh_CN.md delete mode 100644 workspace/plugins/template/public/i18n/en_US.json delete mode 100644 workspace/plugins/template/public/i18n/zh_CHT.json delete mode 100644 workspace/plugins/template/public/i18n/zh_CN.json delete mode 100644 workspace/plugins/template/public/plugin.json delete mode 100644 workspace/plugins/template/src/assets/symbols/.keep delete mode 100644 workspace/plugins/template/src/components/Settings.svelte delete mode 100644 workspace/plugins/template/src/configs/default.ts delete mode 100644 workspace/plugins/template/src/index.ts delete mode 100644 workspace/plugins/template/src/types/config.d.ts delete mode 100644 workspace/plugins/template/src/utils/i18n.ts delete mode 100644 workspace/plugins/template/src/vite-env.d.ts delete mode 100644 workspace/plugins/template/svelte.config.js delete mode 100644 workspace/plugins/template/tsconfig.json delete mode 100644 workspace/plugins/template/tsconfig.node.json delete mode 100644 workspace/plugins/template/vite.config.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 45bfc14..29f7419 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - 添加 `复制导出超链接` 菜单项 | Add `Copy export hyperlink` menu item. - 添加附属仓库 `template` 的管理脚本 | Add management scripts for sub-repository `template`. - 完善插件模板 | Improve plugin template. +- 重新添加附属仓库 `template` | Re-add sub-repository `template`. ## 2023-08-15 diff --git a/workspace/plugins/template/.github/FUNDING.yml b/workspace/plugins/template/.github/FUNDING.yml deleted file mode 100644 index 5051816..0000000 --- a/workspace/plugins/template/.github/FUNDING.yml +++ /dev/null @@ -1,36 +0,0 @@ -# These are supported funding model platforms - - -# Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] -# github: - -# Replace with a single Patreon username -# patreon: - -# Replace with a single Open Collective username -# open_collective: - -# Replace with a single Ko-fi username -ko_fi: zuoqiu - -# Replace with a single Tidelift platform-name/package-name e.g., npm/babel -# tidelift: - -# Replace with a single Community Bridge project-name e.g., cloud-foundry -# community_bridge: - -# Replace with a single Liberapay username -# liberapay: - -# Replace with a single IssueHunt username -# issuehunt: - -# Replace with a single Otechie username -# otechie: - -# Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry -# lfx_crowdfunding: - -# Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] -custom: - - https://afdian.net/a/zuoqiu diff --git a/workspace/plugins/template/.github/workflows/build.yml b/workspace/plugins/template/.github/workflows/build.yml deleted file mode 100644 index b100ee1..0000000 --- a/workspace/plugins/template/.github/workflows/build.yml +++ /dev/null @@ -1,93 +0,0 @@ -# 构建并部署 | Build and deploy - -name: build - -on: - workflow_dispatch: - push: - tags: - # REF https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet - - "v[0-9]+.[0-9]+.[0-9]+" - -env: - PACKAGE_PATH: ./workspace/plugins/template - -jobs: - build-and-deploy: - runs-on: ubuntu-latest - steps: - # Checkout - # REF https://github.com/marketplace/actions/checkout - - name: Checkout - uses: actions/checkout@v3 - with: - ## 将要拉取的仓库 | repository will to pull - repository: Zuoqiu-Yingyi/siyuan-packages-monorepo - - # Install Node.js - # REF https://github.com/marketplace/actions/setup-node-js-environment - - name: Install Node.js - uses: actions/setup-node@v3 - with: - ## Node.js 版本号 | Node.js version - node-version: 20 - - ## Node.js 源 | Node.js registry - registry-url: https://registry.npmjs.org - - # Install pnpm - # REF https://github.com/marketplace/actions/setup-pnpm - - name: Install pnpm - uses: pnpm/action-setup@v2 - id: pnpm-install - with: - ## pnpm 版本号 | pnpm version - version: 8 - - ## 是否安装 npm 包 | if install npm package? - run_install: false - - # Get pnpm store directory - - name: Get pnpm store directory - id: pnpm-cache - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - - # Setup pnpm cache - # REF https://github.com/marketplace/actions/cache - - name: Setup pnpm cache - uses: actions/cache@v3 - with: - path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - # Install dependencies - - name: Install dependencies - run: | - cd $GITHUB_WORKSPACE - cd ./workspace - pnpm install - - # Build package - - name: Build package - run: | - cd $GITHUB_WORKSPACE - cd $PACKAGE_PATH - pnpm build - - # Deploy to publish branch - # REF https://github.com/marketplace/actions/github-pages - - name: Deploy to publish branch - if: success() - uses: crazy-max/ghaction-github-pages@v3 - with: - ## 构建产物目录 | directory of build artifacts - build_dir: ${{ env.PACKAGE_PATH }}/dist - - ## 提交到目标分支 - target_branch: publish - env: - GITHUB_TOKEN: ${{ secrets.PAT_ACTIONS }} diff --git a/workspace/plugins/template/.github/workflows/release-distribution.yml b/workspace/plugins/template/.github/workflows/release-distribution.yml deleted file mode 100644 index 03ac4a4..0000000 --- a/workspace/plugins/template/.github/workflows/release-distribution.yml +++ /dev/null @@ -1,81 +0,0 @@ -# 发行构建产物 | Release the distribution - -name: release-distribution - -on: - workflow_dispatch: - # REF https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run - workflow_run: - workflows: - - build - types: - - completed - push: - branches: - - publish - -permissions: - contents: write - -jobs: - release-distribution: - runs-on: ubuntu-latest - steps: - # Checkout - # REF https://github.com/marketplace/actions/checkout - - name: Checkout - uses: actions/checkout@v3 - with: - ref: publish - - # Package - - name: Package - run: | - git archive -o ./package.zip HEAD - - # Get latest release - # REF https://github.com/marketplace/actions/get-latest-release - - name: Get latest release - uses: pozetroninc/github-action-get-latest-release@v0.7.0 - id: latest-release - with: - ## 仓库所有者/仓库名 | owner/name - repository: ${{ github.repository }} - - ## 排除的发行类型 | Excluded types of release - # excludes: prerelease, draft - excludes: draft - - # Get timestamp - # REF https://github.com/marketplace/actions/get-timestamp-action - - name: Get timestamp - uses: nanzm/get-time-action@v1.1 - id: timestamp - with: - ## 时区 | time zone - timeZone: 8 - - ## 时间戳格式 | timestamp format - format: "YYYYMMDDHHmmss" - - # Release distribution - # REF https://github.com/marketplace/actions/gh-release - - name: Release distribution - uses: softprops/action-gh-release@v1 - with: - ## 发行描述 | description of release - body: ${{ steps.latest-release.outputs.description }} - - ## 是否为预发行 | is prelease? - prerelease: true - - ## 标签名称 | tag name - # REF https://semver.org/ - tag_name: ${{ steps.latest-release.outputs.release }}+${{ steps.timestamp.outputs.time }} - - ## 标签关联的提交/分支 | The commit/branch associated with the tag - target_commitish: publish - - ## 附件列表 | attachment list - files: | - package.zip diff --git a/workspace/plugins/template/.github/workflows/release-please.yml b/workspace/plugins/template/.github/workflows/release-please.yml deleted file mode 100644 index 8cdd44e..0000000 --- a/workspace/plugins/template/.github/workflows/release-please.yml +++ /dev/null @@ -1,112 +0,0 @@ -# 发行源码 | Release the source code - -name: release-please - -on: - workflow_dispatch: - push: - branches: - - main - -permissions: - contents: write - pull-requests: write - -env: - PACKAGE_NAME: custom-fonts - PACKAGE_VERSION: 0.0.0 - -jobs: - release-please: - runs-on: ubuntu-latest - steps: - # Create release - # REF https://github.com/marketplace/actions/release-please-action - - name: Create release - uses: google-github-actions/release-please-action@v3 - id: release - with: - release-type: node - package-name: ${{ env.PACKAGE_NAME }} - release-as: ${{ env.PACKAGE_VERSION }} - - ## A GitHub secret token, the action defaults to using the special secrets.GITHUB_TOKEN - ## REF https://github.com/marketplace/actions/release-please-action#github-credentials - token: ${{ secrets.PAT_ACTIONS }} - - ## branch to open pull release PR against (detected by default) - default-branch: main - - ## Should breaking changes before 1.0.0 produce minor bumps? Default false - bump-minor-pre-major: false - - ## Should feat changes before 1.0.0 produce patch bumps instead of minor bumps? Default false - bump-patch-for-minor-pre-major: false - - ## If set, create releases that are pre-major or pre-release version marked as pre-release on GitHub. Defaults false - prerelease: true - - ## header used within the release PR body, defaults to using :robot: I have created a release *beep* *boop* - pull-request-header: ":robot: A new release will be created" - - ## A JSON formatted String containing to override the outputted changelog sections - changelog-types: |- - [ - { - "type": "build", - "section": "Build System", - "hidden": false - }, - { - "type": "chore", - "section": "Miscellaneous", - "hidden": false - }, - { - "type": "ci", - "section": "Continuous Integration", - "hidden": false - }, - { - "type": "docs", - "section": "Documentation" - }, - { - "type": "feat", - "section": "Features", - "hidden": false - }, - { - "type": "fix", - "section": "Bug Fixes", - "hidden": false - }, - { - "type": "perf", - "section": "Performance Improvements" - }, - { - "type": "refactor", - "section": "Code Refactoring", - "hidden": false - }, - { - "type": "revert", - "section": "Reverts" - }, - { - "type": "style", - "section": "Styles", - "hidden": false - }, - { - "type": "test", - "section": "Tests", - "hidden": false - }, - { - "type": "", - "section": "Other Changes", - "hidden": false - } - ] diff --git a/workspace/plugins/template/.gitignore b/workspace/plugins/template/.gitignore deleted file mode 100644 index a547bf3..0000000 --- a/workspace/plugins/template/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/workspace/plugins/template/LICENSE b/workspace/plugins/template/LICENSE deleted file mode 100644 index 0ad25db..0000000 --- a/workspace/plugins/template/LICENSE +++ /dev/null @@ -1,661 +0,0 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. diff --git a/workspace/plugins/template/README.md b/workspace/plugins/template/README.md deleted file mode 100644 index a78f95b..0000000 --- a/workspace/plugins/template/README.md +++ /dev/null @@ -1,41 +0,0 @@ -> **[READ ONLY] Subtree split of the [siyuan-packages-monorepo](https://github.com/Zuoqiu-Yingyi/siyuan-packages-monorepo) [/workspace/plugins/template](https://github.com/Zuoqiu-Yingyi/siyuan-packages-monorepo/tree/main/workspace/plugins/template)** - -
-icon - ---- -[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/Zuoqiu-Yingyi/siyuan-plugin-template?include_prereleases)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases/latest) -[![GitHub Release Date](https://img.shields.io/github/release-date/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases/latest) -[![GitHub License](https://img.shields.io/github/license/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/blob/main/LICENSE) -[![GitHub last commit](https://img.shields.io/github/last-commit/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/commits/main) -![GitHub repo size](https://img.shields.io/github/repo-size/Zuoqiu-Yingyi/siyuan-plugin-template) - -![jsDelivr hits (GitHub)](https://img.shields.io/jsdelivr/gh/hy/Zuoqiu-Yingyi/siyuan-packages-template) -[![GitHub all releases](https://img.shields.io/github/downloads/Zuoqiu-Yingyi/siyuan-plugin-template/total)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases) - ---- -
- -## USER GUIDE - -[简体中文](./public/README_zh_CN.md) \| [English](./public/README.md) - -## DEVELOPER GUIDE - -### RELEASE STEPS - -1. Update the version number in `/package.json` and `/public/plugin.json`, then commit the changes in [monorepo](https://github.com/Zuoqiu-Yingyi/siyuan-packages-monorepo). -2. Run script `./scripts/git-subtree/template/push.ps1` with the folowing command in **monorepo root dir** to push the subtree to sub-repository (`dev` branch). - ```powershell - pwsh -f "./scripts/git-subtree/template/push.ps1" - ``` -3. Create a pull request from `dev` branch to `main` branch in sub-repository. -4. Merge the pull request. -5. Await for the CD workflow `release-please.yml` to complete, it will create a *release pull request* in sub-repository. -6. Merge the *release pull request*, it will create a new *pre-release* with current [changelog](./CHANGELOG.md) and a new *tag* with [semantic version](https://semver.org/) in sub-repository. -7. Await for the CD workflow `build.yml` to complete, it will update the distribution files to `publish` branch in sub-repository. -8. Await for the CD workflow `release-distribution.yml` to complete, it will create a new *pre-release* with an asset named `package.zip` and a new *tag* with timestamp in sub-repository. - -## CHANGELOG - -[CHANGE LOG](./CHANGELOG.md) diff --git a/workspace/plugins/template/package.json b/workspace/plugins/template/package.json deleted file mode 100644 index 5528d42..0000000 --- a/workspace/plugins/template/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "template", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "build:dev": "vite build --sourcemap inline", - "preview": "vite preview", - "check": "svelte-check --tsconfig ./tsconfig.json" - }, - "devDependencies": { - "@sveltejs/vite-plugin-svelte": "^2.4.5", - "@tsconfig/svelte": "^5.0.0", - "less": "^4.2.0", - "svelte": "^4.2.0", - "svelte-check": "^3.5.0", - "svelte-preprocess-less": "^0.4.0", - "tslib": "^2.6.1", - "typescript": "^5.1.6", - "vite": "^4.4.9" - }, - "dependencies": { - "@workspace/components": "workspace:^", - "@workspace/types": "workspace:^", - "@workspace/utils": "workspace:^" - } -} diff --git a/workspace/plugins/template/public/README.md b/workspace/plugins/template/public/README.md deleted file mode 100644 index 3a1795c..0000000 --- a/workspace/plugins/template/public/README.md +++ /dev/null @@ -1,36 +0,0 @@ -
-icon - ---- -[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/Zuoqiu-Yingyi/siyuan-plugin-template?include_prereleases)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases/latest) -[![GitHub Release Date](https://img.shields.io/github/release-date/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases/latest) -[![GitHub License](https://img.shields.io/github/license/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/blob/main/LICENSE) -[![GitHub last commit](https://img.shields.io/github/last-commit/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/commits/main) -![GitHub repo size](https://img.shields.io/github/repo-size/Zuoqiu-Yingyi/siyuan-plugin-template) - -![jsDelivr hits (GitHub)](https://img.shields.io/jsdelivr/gh/hy/Zuoqiu-Yingyi/siyuan-packages-template) -[![GitHub all releases](https://img.shields.io/github/downloads/Zuoqiu-Yingyi/siyuan-plugin-template/total)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases) - ---- -[简体中文](./README_zh_CN.md) \| English - ---- -
- -# SiYuan Plubin Template - -## PREVIEW - -![preview image](https://cdn.jsdelivr.net/gh/Zuoqiu-Yingyi/siyuan-plugin-template/public/preview.png) - -## Q & A - -## INTRODUCTION - -### Features Introduction - -### Settings Introduction - -## CHANGELOG - -[CHANGELOG.md](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/blob/main/CHANGELOG.md) diff --git a/workspace/plugins/template/public/README_zh_CN.md b/workspace/plugins/template/public/README_zh_CN.md deleted file mode 100644 index 387dbee..0000000 --- a/workspace/plugins/template/public/README_zh_CN.md +++ /dev/null @@ -1,36 +0,0 @@ -
-图标 - ---- -[![GitHub 最新发行版本 (最新一次发行/预发行)](https://img.shields.io/github/v/release/Zuoqiu-Yingyi/siyuan-plugin-template?include_prereleases)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases/latest) -[![GitHub 最新发行时间](https://img.shields.io/github/release-date/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases/latest) -[![GitHub 许可证](https://img.shields.io/github/license/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/blob/main/LICENSE) -[![GitHub 最后一次提交时间](https://img.shields.io/github/last-commit/Zuoqiu-Yingyi/siyuan-plugin-template)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/commits/main) -![GitHub 仓库大小](https://img.shields.io/github/repo-size/Zuoqiu-Yingyi/siyuan-plugin-template) - -![jsDelivr 查看次數 (GitHub)](https://img.shields.io/jsdelivr/gh/hy/Zuoqiu-Yingyi/siyuan-packages-template) -[![GitHub 发行版本下载次数](https://img.shields.io/github/downloads/Zuoqiu-Yingyi/siyuan-plugin-template/total)](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/releases) - ---- -简体中文 \| [English](./README.md) - ---- -
- -# 思源插件模板 - -## 预览 - -![预览图片](https://cdn.jsdelivr.net/gh/Zuoqiu-Yingyi/siyuan-plugin-template/public/preview.png) - -## 常见问题 - -## 介绍 - -### 功能介绍 - -### 设置项介绍 - -## 更改日志 - -[CHANGELOG.md](https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template/blob/main/CHANGELOG.md) diff --git a/workspace/plugins/template/public/i18n/en_US.json b/workspace/plugins/template/public/i18n/en_US.json deleted file mode 100644 index f1b14f6..0000000 --- a/workspace/plugins/template/public/i18n/en_US.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "displayName": "", - "settings": { - "generalSettings": { - "reset": { - "description": "Reset all settings options to default options (refresh page after reset)", - "text": "Reset", - "title": "Reset settings options" - }, - "title": "General" - } - } -} diff --git a/workspace/plugins/template/public/i18n/zh_CHT.json b/workspace/plugins/template/public/i18n/zh_CHT.json deleted file mode 100644 index 3207e23..0000000 --- a/workspace/plugins/template/public/i18n/zh_CHT.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "displayName": "", - "settings": { - "generalSettings": { - "reset": { - "description": "重置所有設定選項為預設選項(重置後將重新整理頁面)", - "text": "重置", - "title": "重置設定選項" - }, - "title": "常規設定" - } - } -} diff --git a/workspace/plugins/template/public/i18n/zh_CN.json b/workspace/plugins/template/public/i18n/zh_CN.json deleted file mode 100644 index 5a98932..0000000 --- a/workspace/plugins/template/public/i18n/zh_CN.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "displayName": "", - "settings": { - "generalSettings": { - "reset": { - "description": "重置所有设置选项为默认选项(重置后将刷新页面)", - "text": "重置", - "title": "重置设置选项" - }, - "title": "常规设置" - } - } -} diff --git a/workspace/plugins/template/public/plugin.json b/workspace/plugins/template/public/plugin.json deleted file mode 100644 index 7681926..0000000 --- a/workspace/plugins/template/public/plugin.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "template", - "author": "Zuoqiu Yingyi", - "url": "https://github.com/Zuoqiu-Yingyi/siyuan-plugin-template", - "version": "0.0.0", - "minAppVersion": "2.9.0", - "backends": [ - "all" - ], - "frontends": [ - "all" - ], - "displayName": { - "default": "", - "zh_CN": "", - "zh_CHT": "" - }, - "description": { - "default": "", - "zh_CN": "", - "zh_CHT": "" - }, - "readme": { - "default": "README.md", - "zh_CN": "README_zh_CN.md", - "zh_CHT": "README_zh_CN.md" - }, - "funding": { - "openCollective": "", - "patreon": "", - "github": "", - "custom": [ - "https://afdian.net/a/zuoqiu", - "https://ko-fi.com/zuoqiu" - ] - } -} diff --git a/workspace/plugins/template/src/assets/symbols/.keep b/workspace/plugins/template/src/assets/symbols/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/workspace/plugins/template/src/components/Settings.svelte b/workspace/plugins/template/src/components/Settings.svelte deleted file mode 100644 index b746d56..0000000 --- a/workspace/plugins/template/src/components/Settings.svelte +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/workspace/plugins/template/src/configs/default.ts b/workspace/plugins/template/src/configs/default.ts deleted file mode 100644 index 03cb049..0000000 --- a/workspace/plugins/template/src/configs/default.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (C) 2023 Zuoqiu Yingyi - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -import type { IConfig } from "@/types/config"; - -export const DEFAULT_CONFIG: IConfig = { -}; diff --git a/workspace/plugins/template/src/index.ts b/workspace/plugins/template/src/index.ts deleted file mode 100644 index fb3f1f7..0000000 --- a/workspace/plugins/template/src/index.ts +++ /dev/null @@ -1,116 +0,0 @@ -/** - * Copyright (C) 2023 Zuoqiu Yingyi - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -import siyuan from "siyuan"; - -import { - Client, - type types, -} from "@siyuan-community/siyuan-sdk"; - -import Settings from "./components/Settings.svelte"; - -import { - FLAG_MOBILE, -} from "@workspace/utils/env/front-end"; -import { Logger } from "@workspace/utils/logger"; -import { mergeIgnoreArray } from "@workspace/utils/misc/merge"; -import { DEFAULT_CONFIG } from "./configs/default"; -import type { IConfig } from "./types/config"; - -import type { - IWebSocketMainEvent, - IClickEditorContentEvent, - ILoadedProtyleEvent, -} from "@workspace/types/siyuan/events"; -import type { BlockID } from "@workspace/types/siyuan"; - -type INotebook = types.kernel.api.notebook.lsNotebooks.INotebook; - -export default class WakaTimePlugin extends siyuan.Plugin { - static readonly GLOBAL_CONFIG_NAME = "global-config"; - - public readonly siyuan = siyuan; - public readonly logger: InstanceType; - public readonly client: InstanceType; - public readonly notebook = new Map(); // 笔记本 ID => 笔记本信息 - - protected readonly SETTINGS_DIALOG_ID: string; - - protected config: IConfig; - - constructor(options: any) { - super(options); - - this.logger = new Logger(this.name); - this.client = new Client(undefined, "fetch"); - - this.SETTINGS_DIALOG_ID = `${this.name}-settings-dialog`; - } - - onload(): void { - // this.logger.debug(this); - - /* 注册图标 */ - this.addIcons([ - ].join("")); - - this.loadData(WakaTimePlugin.GLOBAL_CONFIG_NAME) - .then(config => { - this.config = mergeIgnoreArray(DEFAULT_CONFIG, config || {}) as IConfig; - }) - .catch(error => this.logger.error(error)) - .finally(() => { - }); - } - - onLayoutReady(): void { - } - - onunload(): void { - } - - openSetting(): void { - const that = this; - const dialog = new siyuan.Dialog({ - title: `${this.i18n.displayName} ${this.name}`, - content: `
`, - width: FLAG_MOBILE ? "92vw" : "720px", - height: FLAG_MOBILE ? undefined : "640px", - }); - const settings = new Settings({ - target: dialog.element.querySelector(`#${that.SETTINGS_DIALOG_ID}`), - props: { - config: this.config, - plugin: this, - }, - }); - } - - /* 重置插件配置 */ - public async resetConfig(): Promise { - return this.updateConfig(mergeIgnoreArray(DEFAULT_CONFIG) as IConfig); - } - - /* 更新插件配置 */ - public async updateConfig(config?: IConfig): Promise { - if (config && config !== this.config) { - this.config = config; - } - return this.saveData(WakaTimePlugin.GLOBAL_CONFIG_NAME, this.config); - } -}; diff --git a/workspace/plugins/template/src/types/config.d.ts b/workspace/plugins/template/src/types/config.d.ts deleted file mode 100644 index 8b6f336..0000000 --- a/workspace/plugins/template/src/types/config.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (C) 2023 Zuoqiu Yingyi - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -export interface IConfig { -} diff --git a/workspace/plugins/template/src/utils/i18n.ts b/workspace/plugins/template/src/utils/i18n.ts deleted file mode 100644 index c5b0430..0000000 --- a/workspace/plugins/template/src/utils/i18n.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (C) 2023 Zuoqiu Yingyi - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -import { - i18nCheck, - i18nChecks, -} from "@workspace/types/siyuan/i18n"; - -import zh_Hans from "~/public/i18n/zh_CN.json"; -import zh_Hant from "~/public/i18n/zh_CHT.json"; -import en from "~/public/i18n/en_US.json"; - -export type I18N = typeof zh_Hans; - -i18nChecks([ - i18nCheck(), - i18nCheck(), - i18nCheck(), -]); diff --git a/workspace/plugins/template/src/vite-env.d.ts b/workspace/plugins/template/src/vite-env.d.ts deleted file mode 100644 index 4078e74..0000000 --- a/workspace/plugins/template/src/vite-env.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -/// -/// diff --git a/workspace/plugins/template/svelte.config.js b/workspace/plugins/template/svelte.config.js deleted file mode 100644 index a7db43f..0000000 --- a/workspace/plugins/template/svelte.config.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (C) 2023 Zuoqiu Yingyi - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' - -export default { - // Consult https://svelte.dev/docs#compile-time-svelte-preprocess - // for more information about preprocessors - preprocess: vitePreprocess(), -} diff --git a/workspace/plugins/template/tsconfig.json b/workspace/plugins/template/tsconfig.json deleted file mode 100644 index 228eb95..0000000 --- a/workspace/plugins/template/tsconfig.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "extends": "@tsconfig/svelte/tsconfig.json", - "compilerOptions": { - "target": "ESNext", - "useDefineForClassFields": true, - "module": "ESNext", - "resolveJsonModule": true, - /** - * Typecheck JS in `.svelte` and `.js` files by default. - * Disable checkJs if you'd like to use dynamic types in JS. - * Note that setting allowJs false does not prevent the use - * of JS in `.svelte` files. - */ - "allowJs": true, - "checkJs": true, - "isolatedModules": true, - "baseUrl": "./", - "paths": { - "~/*": [ - "./*", - ], - "@/*": [ - "src/*", - ], - }, - }, - "include": [ - "src/**/*.d.ts", - "src/**/*.ts", - "src/**/*.js", - "src/**/*.svelte", - ], - "references": [ - { - "path": "./tsconfig.node.json" - }, - ], -} diff --git a/workspace/plugins/template/tsconfig.node.json b/workspace/plugins/template/tsconfig.node.json deleted file mode 100644 index f61a9de..0000000 --- a/workspace/plugins/template/tsconfig.node.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "skipLibCheck": true, - "module": "ESNext", - "moduleResolution": "bundler" - }, - "include": [ - "vite.config.ts" - ] -} diff --git a/workspace/plugins/template/vite.config.ts b/workspace/plugins/template/vite.config.ts deleted file mode 100644 index 4acf21e..0000000 --- a/workspace/plugins/template/vite.config.ts +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (C) 2023 Zuoqiu Yingyi - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -import { defineConfig } from "vite"; -import { resolve } from "path" -import { svelte } from "@sveltejs/vite-plugin-svelte"; -import { less } from "svelte-preprocess-less"; - -// https://vitejs.dev/config/ -export default defineConfig({ - base: `./`, - plugins: [ - svelte({ - preprocess: { - style: less(), - }, - }), - ], - resolve: { - alias: { - "~": resolve(__dirname, "./"), - "@": resolve(__dirname, "./src"), - } - }, - build: { - minify: true, - // sourcemap: "inline", - lib: { - entry: resolve(__dirname, "src/index.ts"), - fileName: "index", - formats: ["cjs"], - }, - rollupOptions: { - external: [ - "siyuan", - /^@electron\/.*$/, - ], - output: { - entryFileNames: chunkInfo => { - // console.log(chunkInfo); - switch (chunkInfo.name) { - case "index": - return "[name].js"; - - default: - return "assets/[name]-[hash].js"; - } - }, - assetFileNames: assetInfo => { - // console.log(chunkInfo); - switch (assetInfo.name) { - case "style.css": - case "index.css": - return "index.css"; - - default: - return "assets/[name]-[hash][extname]"; - } - }, - }, - }, - }, -}); From efc1c3744d780c76a38ca0d99be865bc9cbdfd45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Thu, 17 Aug 2023 15:34:21 +0800 Subject: [PATCH 14/16] =?UTF-8?q?fix(wakatime):=20=E6=8D=95=E8=8E=B7?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=9D=97=E5=AF=BC=E8=87=B4=E7=9A=84=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=20|=20Catch=20exceptions=20caused=20by=20deleted=20bl?= =?UTF-8?q?ocks.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.ts | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/index.ts b/src/index.ts index 856b91b..87a4ed6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,6 +23,7 @@ import manifest from "~/public/plugin.json"; import { Client, + KernelError, type types, } from "@siyuan-community/siyuan-sdk"; @@ -289,18 +290,26 @@ export default class WakaTimePlugin extends siyuan.Plugin { let root_id = this.context.blocks.get(id); let root_info = this.context.roots.get(root_id); if (!root_info) { - const block_info = await this.client.getBlockInfo({ id }); - - root_id = block_info.data.rootID; - root_info = { - id: root_id, - box: block_info.data.box, - path: block_info.data.path, - events: [], - }; - - this.context.blocks.set(id, root_id); - this.context.roots.set(root_id, root_info); + try { + const block_info = await this.client.getBlockInfo({ id }); + root_id = block_info.data.rootID; + root_info = { + id: root_id, + box: block_info.data.box, + path: block_info.data.path, + events: [], + }; + + this.context.blocks.set(id, root_id); + this.context.roots.set(root_id, root_info); + } catch (error) { + if (error instanceof KernelError) { // 块删除事件导致无法查询到对应的块 + // this.logger.warn(error); + } + else { + throw error; + } + } } /* 添加编辑事件 */ From 4393980ca5d495c025c94d6a1fe4b27d470beabd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Thu, 17 Aug 2023 16:25:56 +0800 Subject: [PATCH 15/16] =?UTF-8?q?fix(wakatime):=20fix(wakatime):=20?= =?UTF-8?q?=E6=8D=95=E8=8E=B7=E5=88=A0=E9=99=A4=E5=9D=97=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E7=9A=84=E5=BC=82=E5=B8=B8=20|=20Catch=20exceptions=20caused?= =?UTF-8?q?=20by=20deleted=20blocks.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.ts | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/src/index.ts b/src/index.ts index 87a4ed6..95cb614 100644 --- a/src/index.ts +++ b/src/index.ts @@ -283,14 +283,14 @@ export default class WakaTimePlugin extends siyuan.Plugin { } /* 添加编辑事件 */ - protected async addEditEvent(id: BlockID): Promise { - const time = this.now; + protected async addEditEvent(id: BlockID): Promise { + try { + const time = this.now; - /* 获取块对应的文档信息 */ - let root_id = this.context.blocks.get(id); - let root_info = this.context.roots.get(root_id); - if (!root_info) { - try { + /* 获取块对应的文档信息 */ + let root_id = this.context.blocks.get(id); + let root_info = this.context.roots.get(root_id); + if (!root_info) { const block_info = await this.client.getBlockInfo({ id }); root_id = block_info.data.rootID; root_info = { @@ -302,24 +302,25 @@ export default class WakaTimePlugin extends siyuan.Plugin { this.context.blocks.set(id, root_id); this.context.roots.set(root_id, root_info); - } catch (error) { - if (error instanceof KernelError) { // 块删除事件导致无法查询到对应的块 - // this.logger.warn(error); - } - else { - throw error; - } } - } - /* 添加编辑事件 */ - return this.addEvent({ - id: root_info.id, - box: root_info.box, - path: root_info.path, - time, - is_write: true, - }); + /* 添加编辑事件 */ + return this.addEvent({ + id: root_info.id, + box: root_info.box, + path: root_info.path, + time, + is_write: true, + }); + } catch (error) { + if (error instanceof KernelError) { // 块删除事件导致无法查询到对应的块 + // this.logger.warn(error); + return; + } + else { + throw error; + } + } } /* 添加查看事件 */ From baf56c53ca37e5b8c011afce9aa4cabf22bbb2d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=96=E9=80=B8?= <49649786+Zuoqiu-Yingyi@users.noreply.github.com> Date: Thu, 17 Aug 2023 20:50:43 +0800 Subject: [PATCH 16/16] chore(wakatime): release v0.1.2 --- .github/workflows/release-please.yml | 2 +- package.json | 2 +- public/plugin.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index bdcd7ec..9f7e358 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -14,7 +14,7 @@ permissions: env: PACKAGE_NAME: custom-fonts - PACKAGE_VERSION: 0.1.1 + PACKAGE_VERSION: 0.1.2 jobs: release-please: diff --git a/package.json b/package.json index 30e2dc2..19d098b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wakatime", "private": true, - "version": "0.1.1", + "version": "0.1.2", "type": "module", "scripts": { "dev": "vite", diff --git a/public/plugin.json b/public/plugin.json index d3fccf9..e4068d3 100644 --- a/public/plugin.json +++ b/public/plugin.json @@ -2,7 +2,7 @@ "name": "wakatime", "author": "Zuoqiu Yingyi", "url": "https://github.com/Zuoqiu-Yingyi/siyuan-plugin-wakatime", - "version": "0.1.1", + "version": "0.1.2", "minAppVersion": "2.9.9", "backends": [ "all"