mirror of
https://github.com/mara-li/obsidian-my-thesaurus.git
synced 2026-07-22 05:38:22 +00:00
Initial commit
This commit is contained in:
commit
05464c396a
26 changed files with 1387 additions and 0 deletions
10
.editorconfig
Normal file
10
.editorconfig
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
tab_width = 4
|
||||
104
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
104
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
name: "Bug report"
|
||||
description: Fill a bug report
|
||||
title: "[Bug]: "
|
||||
labels: ["bug"]
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Thanks for taking the time to fill out this bug report.
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Issue validation
|
||||
description: |
|
||||
- Thanks to check if your issue is relative to the repository. Any non relative or duplicate issue will be closed.
|
||||
- Please, check the documentation and the configuration files before submitting your request.
|
||||
- Issue not in English will be closed.
|
||||
options:
|
||||
- label: "I checked the issue to prevent duplicate"
|
||||
required: true
|
||||
- label: "I checked my configurations files and the documentation"
|
||||
required: true
|
||||
- type: textarea
|
||||
id: describe-bug
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: A clear and concise description of what the bug is.
|
||||
placeholder: "Tell us what you see! And don't forget the error"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: repro-bug
|
||||
attributes:
|
||||
label: How to reproduce ?
|
||||
description: Step to reproduce the behavior
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: minimal-repro
|
||||
attributes:
|
||||
label: Minimal Reproducible Example
|
||||
description: Please provide a minimal reproducible example.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Configuration
|
||||
description: |
|
||||
Open the configuration settings with any text editor. The settings are located in `.obsidian/plugins/<%= data.id %>`
|
||||
render: JSON
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: |
|
||||
Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. You can open the Obsidian's console with "CTRL+MAJ+I."
|
||||
render: bash session
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Anything else?
|
||||
description: |
|
||||
Links? References? Anything that will give us more context about the issue you are encountering!
|
||||
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
||||
validations:
|
||||
required: false
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Environment
|
||||
Please fill out the following information about your environment. If you are unsure about any of them, just leave it blank.
|
||||
- type: dropdown
|
||||
id: version
|
||||
attributes:
|
||||
label: OS
|
||||
description: Check your OS
|
||||
multiple: true
|
||||
options:
|
||||
- IOS
|
||||
- Android
|
||||
- MacOS
|
||||
- Windows
|
||||
- Linux
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Obsidian information
|
||||
description: |
|
||||
Please copy and paste the information about your Obsidian version using the command "show debug info" in the obsidian's commands palette.
|
||||
render: bash session
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: plugin-version
|
||||
attributes:
|
||||
label: Plugin version
|
||||
description: Please copy and paste the version of the plugin you are using.
|
||||
placeholder: "1.0.0"
|
||||
validations:
|
||||
required: true
|
||||
80
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
80
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
name: "Feature request"
|
||||
description: "Suggest an idea for this project"
|
||||
title: "[FR]: "
|
||||
labels: ["enhancement"]
|
||||
assignees:
|
||||
- Mara-Li
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Thanks for taking the time to fill out this Feature request!
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Issue validation
|
||||
description: |
|
||||
- Thanks to check if your issue is relative to the repository. Any non relative or duplicate issue will be closed.
|
||||
- Please, check the documentation and the configuration files before submitting your request.
|
||||
- Issue not in English will be closed.
|
||||
options:
|
||||
- label: "I checked the issue to prevent duplicate"
|
||||
required: true
|
||||
- label: "I checked my configurations files and the documentation"
|
||||
required: true
|
||||
- type: textarea
|
||||
id: describe-request
|
||||
attributes:
|
||||
label: Is your feature related to a problem ?
|
||||
description: If you found a solution with the inherent limit I had with Obsidian, please, add it here!
|
||||
placeholder: "Tell me the original problem"
|
||||
- type: textarea
|
||||
id: describe-solution
|
||||
attributes:
|
||||
label: What solution do you want to see ?
|
||||
description: Describe your idea here!
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: alternative
|
||||
attributes:
|
||||
label: Describe the alternative you've considered
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Anything else?
|
||||
description: |
|
||||
Links? References? Anything that will give us more context about the issue you are encountering!
|
||||
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
||||
validations:
|
||||
required: false
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Environment
|
||||
Please fill out the following information about your environment. If you are unsure about any of them, just leave it blank.
|
||||
- type: dropdown
|
||||
id: version
|
||||
attributes:
|
||||
label: OS
|
||||
description: Check your OS
|
||||
multiple: true
|
||||
options:
|
||||
- IOS
|
||||
- Android
|
||||
- MacOS
|
||||
- Windows
|
||||
- Linux
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Obsidian information
|
||||
description: |
|
||||
Please copy and paste the information about your Obsidian version using the command "show debug info" in the obsidian's commands palette.
|
||||
render: bash session
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: plugin-version
|
||||
attributes:
|
||||
label: Plugin version
|
||||
description: Please copy and paste the version of the plugin you are using.
|
||||
placeholder: "1.0.0"
|
||||
validations:
|
||||
required: true
|
||||
16
.github/workflows/auto_assign.yml
vendored
Normal file
16
.github/workflows/auto_assign.yml
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
name: Auto Assign
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited, labeled, unlabeled]
|
||||
pull_request:
|
||||
types: [opened, edited, labeled, unlabeled]
|
||||
jobs:
|
||||
auto-assign:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: wow-actions/auto-assign@v3
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
reviewers: ${{github.repository_owner}}
|
||||
assignees: ${{github.repository_owner}}
|
||||
skipKeywords: wip, draft
|
||||
41
.github/workflows/ci.yaml
vendored
Normal file
41
.github/workflows/ci.yaml
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
name: Release obsidian plugin
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
bump:
|
||||
default: false
|
||||
description: "Bump version based on semantic release"
|
||||
type: boolean
|
||||
required: false
|
||||
beta:
|
||||
default: false
|
||||
description: "Make a beta release"
|
||||
type: boolean
|
||||
required: false
|
||||
push:
|
||||
tags:
|
||||
- "*"
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
if: (github.event_name == 'push') || (github.event_name == 'workflow_dispatch' && !inputs.bump)
|
||||
uses: mara-li/reusable-workflows/.github/workflows/obsidian-plugin-release.yaml@main
|
||||
|
||||
with:
|
||||
PLUGIN_NAME: <%= data.id %>
|
||||
CACHE: "<%= data.packageManager %>"
|
||||
secrets:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
bump-version-and-release:
|
||||
if: ${{ inputs.bump }}
|
||||
uses: mara-li/reusable-workflows/.github/workflows/obsidian-plugin-bump-version.yaml@main
|
||||
with:
|
||||
PLUGIN_NAME: <%= data.id %>
|
||||
BETA: ${{ inputs.beta }}
|
||||
CACHE: "<%= data.packageManager %>"
|
||||
secrets:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
26
.gitignore
vendored
Normal file
26
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# vscode
|
||||
.vscode
|
||||
|
||||
# Intellij
|
||||
*.iml
|
||||
.idea
|
||||
|
||||
# npm
|
||||
node_modules
|
||||
|
||||
# Don't include the compiled main.js file in the repo.
|
||||
# They should be uploaded to GitHub releases instead.
|
||||
main.js
|
||||
styles.css
|
||||
!src/styles.css
|
||||
|
||||
# Exclude sourcemaps
|
||||
*.map
|
||||
|
||||
# obsidian
|
||||
data.json
|
||||
.hotreload
|
||||
|
||||
# Exclude macOS Finder (System Explorer) View States
|
||||
.DS_Store
|
||||
.env
|
||||
3
.npmrc
Normal file
3
.npmrc
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
tag-version-prefix=""
|
||||
auto-install-peers=true
|
||||
enable-pre-post-scripts=true
|
||||
33
README.md
Normal file
33
README.md
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# <%= data.name %>
|
||||
|
||||
<%= data.description %>
|
||||
|
||||
## ⚙️ Usage
|
||||
|
||||
|
||||
## 📥 Installation
|
||||
|
||||
- [ ] From Obsidian's community plugins
|
||||
- [x] Using BRAT with `https://github.com/<%= data.author.name%>/<% data.id%>`
|
||||
- [x] From the release page:
|
||||
- Download the latest release
|
||||
- Unzip `<%= data.id %>.zip` in `.obsidian/plugins/` path
|
||||
- In Obsidian settings, reload the plugin
|
||||
- Enable the plugin
|
||||
|
||||
|
||||
### 🎼 Languages
|
||||
|
||||
- [x] English
|
||||
- [ ] French
|
||||
|
||||
To add a translation:
|
||||
1. Fork the repository
|
||||
2. Add the translation in the `src/i18n/locales` folder with the name of the language (ex: `fr.json`).
|
||||
- You can get your locale language from Obsidian using [obsidian translation](https://github.com/obsidianmd/obsidian-translations) or using the commands (in templater for example) : `{{TEMPLATE_PLACEHOLDER LOCALE}}`
|
||||
- Copy the content of the [`en.json`](./src/i18n/locales/en.json) file in the new file
|
||||
- Translate the content
|
||||
3. Edit `i18n/i18next.ts` :
|
||||
- Add `import * as <lang> from "./locales/<lang>.json";`
|
||||
- Edit the `ressource` part with adding : `<lang> : {translation: <lang>}`
|
||||
|
||||
130
biome.json
Normal file
130
biome.json
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
{
|
||||
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
|
||||
"organizeImports": {
|
||||
"enabled": true
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": false,
|
||||
"complexity": {
|
||||
"noExtraBooleanCast": "error",
|
||||
"noMultipleSpacesInRegularExpressionLiterals": "error",
|
||||
"noUselessCatch": "error",
|
||||
"noWith": "error"
|
||||
},
|
||||
"style": {
|
||||
"noVar": "error",
|
||||
"useFilenamingConvention": "error",
|
||||
"useImportType": "error",
|
||||
"useNamingConvention": {
|
||||
"level": "warn",
|
||||
"options": {
|
||||
"strictCase": false
|
||||
}
|
||||
},
|
||||
"useTemplate": "warn",
|
||||
"useConst": "error"
|
||||
},
|
||||
"correctness": {
|
||||
"noConstAssign": "error",
|
||||
"noConstantCondition": "error",
|
||||
"noEmptyCharacterClassInRegex": "error",
|
||||
"noEmptyPattern": "error",
|
||||
"noGlobalObjectCalls": "error",
|
||||
"noInnerDeclarations": "error",
|
||||
"noInvalidConstructorSuper": "error",
|
||||
"noNewSymbol": "error",
|
||||
"noNonoctalDecimalEscape": "error",
|
||||
"noPrecisionLoss": "error",
|
||||
"noSelfAssign": "error",
|
||||
"noSetterReturn": "error",
|
||||
"noSwitchDeclarations": "error",
|
||||
"noUndeclaredVariables": "error",
|
||||
"noUnreachable": "error",
|
||||
"noUnreachableSuper": "error",
|
||||
"noUnsafeFinally": "error",
|
||||
"noUnsafeOptionalChaining": "error",
|
||||
"noUnusedLabels": "error",
|
||||
"noUnusedVariables": "warn",
|
||||
"noUnusedImports": "warn",
|
||||
"useIsNan": "error",
|
||||
"useValidForDirection": "error",
|
||||
"useYield": "error"
|
||||
},
|
||||
"suspicious": {
|
||||
"noAssignInExpressions": "error",
|
||||
"noAsyncPromiseExecutor": "error",
|
||||
"noCatchAssign": "error",
|
||||
"noClassAssign": "error",
|
||||
"noCompareNegZero": "error",
|
||||
"noControlCharactersInRegex": "error",
|
||||
"noDebugger": "error",
|
||||
"noDuplicateCase": "error",
|
||||
"noDuplicateClassMembers": "error",
|
||||
"noDuplicateObjectKeys": "error",
|
||||
"noDuplicateParameters": "error",
|
||||
"noEmptyBlockStatements": "error",
|
||||
"noFallthroughSwitchClause": "error",
|
||||
"noFunctionAssign": "error",
|
||||
"noGlobalAssign": "error",
|
||||
"noImportAssign": "error",
|
||||
"noMisleadingCharacterClass": "error",
|
||||
"noPrototypeBuiltins": "error",
|
||||
"noRedeclare": "error",
|
||||
"noShadowRestrictedNames": "error",
|
||||
"noUnsafeNegation": "error",
|
||||
"useGetterReturn": "error",
|
||||
"useValidTypeof": "error"
|
||||
},
|
||||
"nursery": {
|
||||
"noDuplicateJsonKeys": "error"
|
||||
}
|
||||
},
|
||||
"ignore": [
|
||||
"**/npm node_modules",
|
||||
"**/build",
|
||||
"**/dist",
|
||||
"**/src/i18n/locales"
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"ignore": [
|
||||
"**/*.js"
|
||||
],
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
"**/*.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"**/*.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"include": [
|
||||
"*.json"
|
||||
]
|
||||
}
|
||||
],
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
"indentStyle": "tab",
|
||||
"indentWidth": 2,
|
||||
"lineWidth": 90
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
"quoteStyle": "double",
|
||||
"semicolons": "always",
|
||||
"trailingCommas": "es5"
|
||||
}
|
||||
},
|
||||
"json": {
|
||||
"formatter": {
|
||||
"trailingCommas": "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
129
commit-and-tag-version.mjs
Normal file
129
commit-and-tag-version.mjs
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
import { Command, Option } from "commander";
|
||||
import commitAndTagVersion from "commit-and-tag-version";
|
||||
import dedent from "dedent";
|
||||
import pkg from "ansi-colors";
|
||||
const { red, dim, gray, italic, bold, cyan, blue, green, underline, yellow, theme } = pkg;
|
||||
|
||||
const program = new Command();
|
||||
|
||||
theme({
|
||||
danger: red,
|
||||
dark: dim.gray,
|
||||
disabled: gray,
|
||||
em: italic,
|
||||
heading: bold.underline,
|
||||
info: cyan,
|
||||
muted: dim,
|
||||
primary: blue,
|
||||
strong: bold,
|
||||
success: green.bold,
|
||||
warning: yellow.underline,
|
||||
});
|
||||
|
||||
const info = (msg) => pkg.info(msg);
|
||||
const heading = (msg) => pkg.heading(msg);
|
||||
const em = (msg) => pkg.em(msg);
|
||||
|
||||
program
|
||||
.description("Bump version and create a new tag")
|
||||
.option("-b, --beta", "Pre-release version")
|
||||
.option("--dry-run", "Dry run")
|
||||
.addOption(
|
||||
new Option("-r, --release-as <size>", "release type version").choices([
|
||||
"major",
|
||||
"minor",
|
||||
"patch",
|
||||
])
|
||||
);
|
||||
|
||||
program.parse();
|
||||
const opt = program.opts();
|
||||
|
||||
const betaMsg = opt.beta ? em("- Pre-release\n\t") : "";
|
||||
const dryRunMsg = opt.dryRun ? em("- Dry run\n\t") : "";
|
||||
const releaseAsMsg = opt.releaseAs ? em(`- Release as ${underline(opt.releaseAs)}`) : "";
|
||||
|
||||
const msg = dedent(`
|
||||
${heading("Options :")}
|
||||
${betaMsg}${dryRunMsg}${releaseAsMsg}
|
||||
`);
|
||||
|
||||
console.log(msg);
|
||||
console.log();
|
||||
|
||||
if (opt.beta) {
|
||||
console.log(`${bold.green(">")} ${info(underline("Bumping beta version..."))}`);
|
||||
console.log();
|
||||
const bumpFiles = [
|
||||
{
|
||||
filename: "manifest-beta.json",
|
||||
type: "json",
|
||||
},
|
||||
{
|
||||
filename: "package.json",
|
||||
type: "json",
|
||||
},
|
||||
{
|
||||
filename: "package-lock.json",
|
||||
type: "json",
|
||||
},
|
||||
];
|
||||
commitAndTagVersion({
|
||||
infile: "CHANGELOG-beta.md",
|
||||
bumpFiles,
|
||||
prerelease: "",
|
||||
dryRun: opt.dryRun,
|
||||
tagPrefix: "",
|
||||
scripts: {
|
||||
postchangelog: "node hooks/_changelog.mjs -b",
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
console.log("Done");
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
} else {
|
||||
const versionBumped = opt.releaseAs
|
||||
? info(`Release as ${underline(opt.releaseAs)}`)
|
||||
: info("Release");
|
||||
console.log(`${bold.green(">")} ${underline(versionBumped)}`);
|
||||
console.log();
|
||||
|
||||
const bumpFiles = [
|
||||
{
|
||||
filename: "manifest-beta.json",
|
||||
type: "json",
|
||||
},
|
||||
{
|
||||
filename: "package.json",
|
||||
type: "json",
|
||||
},
|
||||
{
|
||||
filename: "package-lock.json",
|
||||
type: "json",
|
||||
},
|
||||
{
|
||||
filename: "manifest.json",
|
||||
type: "json",
|
||||
},
|
||||
];
|
||||
|
||||
commitAndTagVersion({
|
||||
infile: "CHANGELOG.md",
|
||||
bumpFiles,
|
||||
dryRun: opt.dryRun,
|
||||
tagPrefix: "",
|
||||
releaseAs: opt.releaseAs,
|
||||
scripts: {
|
||||
postchangelog: "node hooks/_changelog.mjs",
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
console.log("Done");
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
185
esbuild.config.mjs
Normal file
185
esbuild.config.mjs
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import builtins from "builtin-modules";
|
||||
import { Command } from "commander";
|
||||
import dotenv from "dotenv";
|
||||
import esbuild from "esbuild";
|
||||
import manifest from "./manifest.json" with { type: "json" };
|
||||
import packageJson from "./package.json" with { type: "json" };
|
||||
|
||||
const banner = `/*
|
||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||
if you want to view the source, please visit the github repository of this plugin: ${packageJson.repository}
|
||||
*/
|
||||
`;
|
||||
|
||||
function cleanOutDir(outdir) {
|
||||
if (fs.existsSync(outdir)) {
|
||||
fs.rm(outdir, { recursive: true });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef Options
|
||||
* @prop {boolean|undefined} production
|
||||
* @prop {string|boolean|undefined} vault
|
||||
* @prop {string|undefined} outputDir
|
||||
* @prop {boolean|undefined} beta
|
||||
*/
|
||||
|
||||
dotenv.config({ path: [".env"] });
|
||||
|
||||
const program = new Command();
|
||||
program
|
||||
.option("-p, --production", "Production build")
|
||||
.option("-v, --vault [vault]", "Use vault path")
|
||||
.action((v) => {
|
||||
if (!v) return false;
|
||||
if (typeof v === "string") return path.resolve(v.replace(/\\/g, "/"));
|
||||
return process.env.VAULT;
|
||||
})
|
||||
.option("-o, --output-dir <path>", "Output path")
|
||||
.option("-b, --beta", "Pre-release version")
|
||||
.parse();
|
||||
program.parse();
|
||||
|
||||
/** OPTIONS */
|
||||
/** @type {Options} */
|
||||
const opt = program.opts();
|
||||
/** @type {boolean} */
|
||||
const prod = opt.production ?? false;
|
||||
|
||||
/** VARIABLES **/
|
||||
const isStyled = fs.existsSync("src/styles.css");
|
||||
const pluginID = manifest.id;
|
||||
|
||||
/** FOLDER PATHS **/
|
||||
const folderPlugin = opt.vault
|
||||
? path.join(opt.vault, ".obsidian", "plugins", pluginID)
|
||||
: undefined;
|
||||
|
||||
if (folderPlugin && !fs.existsSync(folderPlugin)) {
|
||||
fs.mkdirSync(folderPlugin, { recursive: true });
|
||||
}
|
||||
if (opt.beta && !fs.existsSync("manifest-beta.json")) {
|
||||
fs.copyFileSync("manifest.json", "manifest-beta.json");
|
||||
}
|
||||
|
||||
let outDir = "./";
|
||||
if (opt.outputDir) {
|
||||
outDir = opt.outputDir;
|
||||
cleanOutDir(outDir);
|
||||
} else if (opt.vault) {
|
||||
outDir = folderPlugin;
|
||||
if (!prod) fs.writeFileSync(path.join(folderPlugin, ".hotreload"), "");
|
||||
} else if (prod) {
|
||||
outDir = "./dist";
|
||||
//clean dist if
|
||||
cleanOutDir(outDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move styles.css to output directory
|
||||
*/
|
||||
const moveStyles = {
|
||||
name: "move-styles",
|
||||
setup(build) {
|
||||
build.onEnd(() => {
|
||||
fs.copyFileSync("src/styles.css", "./styles.css");
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Export to vault if set in environment variable
|
||||
*/
|
||||
const exportToVaultFunc = {
|
||||
name: "export-to-vault",
|
||||
setup(build) {
|
||||
build.onEnd(() => {
|
||||
if (!folderPlugin)
|
||||
throw new Error("VAULT environment variable not set, skipping export to vault");
|
||||
|
||||
fs.copyFileSync(`${outDir}/main.js`, path.join(folderPlugin, "main.js"));
|
||||
if (fs.existsSync(`${outDir}/styles.css`))
|
||||
fs.copyFileSync("./styles.css", path.join(folderPlugin, "styles.css"));
|
||||
if (opt.beta)
|
||||
fs.copyFileSync("manifest-beta.json", path.join(folderPlugin, "manifest.json"));
|
||||
else fs.copyFileSync("./manifest.json", path.join(folderPlugin, "manifest.json"));
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Export to production folder
|
||||
*/
|
||||
const exportToDist = {
|
||||
name: "export-to-dist",
|
||||
setup(build) {
|
||||
build.onEnd(() => {
|
||||
if (opt.beta)
|
||||
fs.copyFileSync("manifest-beta.json", path.join(outDir, "manifest.json"));
|
||||
else fs.copyFileSync("manifest.json", path.join(outDir, "manifest.json"));
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* ENTRIES *
|
||||
*/
|
||||
const entryPoints = ["src/main.ts"];
|
||||
if (isStyled) entryPoints.push("src/styles.css");
|
||||
|
||||
/** PLUGINS **/
|
||||
const plugins = [];
|
||||
if (isStyled) plugins.push(moveStyles);
|
||||
if (prod) plugins.push(exportToDist);
|
||||
if (prod && opt.vault) plugins.push(exportToVaultFunc);
|
||||
|
||||
/**
|
||||
* BUILD
|
||||
*/
|
||||
const context = await esbuild.context({
|
||||
banner: {
|
||||
js: banner,
|
||||
},
|
||||
entryPoints,
|
||||
bundle: true,
|
||||
external: [
|
||||
"obsidian",
|
||||
"electron",
|
||||
"@codemirror/autocomplete",
|
||||
"@codemirror/collab",
|
||||
"@codemirror/commands",
|
||||
"@codemirror/language",
|
||||
"@codemirror/lint",
|
||||
"@codemirror/search",
|
||||
"@codemirror/state",
|
||||
"@codemirror/view",
|
||||
"@lezer/common",
|
||||
"@lezer/highlight",
|
||||
"@lezer/lr",
|
||||
...builtins,
|
||||
],
|
||||
format: "cjs",
|
||||
target: "esnext",
|
||||
logLevel: "info",
|
||||
sourcemap: prod ? false : "inline",
|
||||
treeShaking: true,
|
||||
minifySyntax: prod,
|
||||
minifyWhitespace: prod,
|
||||
outdir: outDir,
|
||||
plugins,
|
||||
});
|
||||
|
||||
if (prod) {
|
||||
console.log("🎉 Build for production");
|
||||
console.log(`📤 Output directory: ${outDir}`);
|
||||
await context.rebuild();
|
||||
console.log("✅ Build successful");
|
||||
process.exit(0);
|
||||
} else {
|
||||
console.log("🚀 Start development build");
|
||||
console.log(`📤 Output directory: ${outDir}`);
|
||||
await context.watch();
|
||||
}
|
||||
302
generate.mjs
Normal file
302
generate.mjs
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
import c from "ansi-colors";
|
||||
import ejs from "ejs";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import prompts from "prompts";
|
||||
import licenses from "spdx-license-list/full.js";
|
||||
import { getLicense } from "license";
|
||||
import packageJson from "./package.json" assert { type: "json" };
|
||||
const { dim, reset } = c;
|
||||
import { execa } from "execa";
|
||||
import gitUserName from "git-user-name";
|
||||
c.theme({
|
||||
danger: c.red,
|
||||
dark: c.dim.gray,
|
||||
disabled: c.gray,
|
||||
em: c.italic,
|
||||
heading: c.bold.underline,
|
||||
info: c.cyan,
|
||||
muted: c.dim,
|
||||
primary: c.blue,
|
||||
strong: c.bold,
|
||||
success: c.green.bold,
|
||||
underline: c.underline,
|
||||
warning: c.yellow.underline,
|
||||
});
|
||||
|
||||
const capitalize = (s) => {
|
||||
if (typeof s !== "string") return "";
|
||||
return s.charAt(0).toUpperCase() + s.slice(1);
|
||||
};
|
||||
/**
|
||||
* Render ejs file
|
||||
* @param {fs.Dirent} file
|
||||
*/
|
||||
function ejsRender(file, data) {
|
||||
const pathFiles = path.join(file.path, file.name);
|
||||
const template = fs.readFileSync(pathFiles, { encoding: "utf-8" });
|
||||
const processedTemplate = ejs.render(template, { data });
|
||||
fs.writeFileSync(pathFiles, processedTemplate, { encoding: "utf-8" });
|
||||
}
|
||||
|
||||
function updateManifest(data, answer) {
|
||||
const manifest = fs.readFileSync("./manifest.json", { encoding: "utf-8" });
|
||||
const processedManifest = ejs.render(manifest, { data });
|
||||
fs.writeFileSync("manifest.json", processedManifest, { encoding: "utf-8" });
|
||||
const license = getLicense(answer.license, {
|
||||
author: data.author.name,
|
||||
year: new Date().getFullYear(),
|
||||
});
|
||||
fs.writeFileSync("LICENSE", license, { encoding: "utf-8" });
|
||||
fs.writeFileSync("manifest-beta.json", processedManifest, {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Get package manager
|
||||
* @returns {"pnpm" | "yarn" | "npm" | "bun" | undefined}
|
||||
*/
|
||||
function getPackageManager() {
|
||||
if (fs.existsSync("yarn.lock")) return "yarn";
|
||||
if (fs.existsSync("pnpm-lock.yaml")) return "pnpm";
|
||||
if (fs.existsSync("package-lock.json")) return "npm";
|
||||
if (fs.existsSync("bun.lockb")) return "bun";
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function processReadme(data) {
|
||||
const readme = fs.readFileSync("./README.md", { encoding: "utf-8" });
|
||||
const processedReadme = ejs.render(readme, { data });
|
||||
fs.writeFileSync(
|
||||
"README.md",
|
||||
processedReadme.replace(
|
||||
"{{TEMPLATE_PLACEHOLDER LOCALE}}",
|
||||
"<% tp.obsidian.moment.locale() %>"
|
||||
),
|
||||
{ encoding: "utf-8" }
|
||||
);
|
||||
}
|
||||
|
||||
function processCi(data) {
|
||||
const ci = fs.readFileSync("./.github/workflows/ci.yaml", {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
const processedCi = ejs.render(ci, { data });
|
||||
fs.writeFileSync(".github/workflows/ci.yaml", processedCi, {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
}
|
||||
|
||||
function processBugReport(data) {
|
||||
const path = fs.readFileSync("./.github/ISSUE_TEMPLATE/bug.yml", {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
const processedCi = ejs.render(path, { data });
|
||||
fs.writeFileSync("./.github/ISSUE_TEMPLATE/bug.yml", processedCi, {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
}
|
||||
|
||||
function updatePackageJson(data, answer) {
|
||||
packageJson.author = data.author.name;
|
||||
packageJson.name = data.id;
|
||||
packageJson.license = answer.license;
|
||||
packageJson.description = data.description;
|
||||
delete packageJson.scripts.generate;
|
||||
delete packageJson.devDependencies["@types/ejs"];
|
||||
delete packageJson.dependencies.ejs;
|
||||
delete packageJson.dependencies.prompts;
|
||||
delete packageJson.dependencies["spdx-license-list"];
|
||||
delete packageJson.dependencies.execa;
|
||||
delete packageJson.dependencies.license;
|
||||
delete packageJson.dependencies["git-user-name"];
|
||||
fs.writeFileSync("package.json", JSON.stringify(packageJson, null, 2), {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Install dep based on package manager detected (using lockfile)
|
||||
* @param {"pnpm" | "npm" | "yarn" | "bun" | undefined} packageManager
|
||||
*/
|
||||
async function updateDep(packageManager) {
|
||||
switch (packageManager) {
|
||||
case "yarn":
|
||||
console.log(c.info("Detected yarn, running yarn install"));
|
||||
//replace pnpm with yarn in package.json scripts
|
||||
fs.writeFileSync(
|
||||
"package.json",
|
||||
fs.readFileSync("package.json", "utf-8").replace("pnpm", "yarn"),
|
||||
"utf-8"
|
||||
);
|
||||
await execa("yarn", ["install"]);
|
||||
break;
|
||||
case "npm":
|
||||
console.log(c.info("Detected npm, running npm install"));
|
||||
fs.writeFileSync(
|
||||
"package.json",
|
||||
fs.readFileSync("package.json", "utf-8").replace("pnpm", "npm"),
|
||||
"utf-8"
|
||||
);
|
||||
await execa("npm", ["install"]);
|
||||
break;
|
||||
case "pnpm":
|
||||
console.log(c.info("Detected pnpm, running pnpm install"));
|
||||
await execa("pnpm", ["install"]);
|
||||
break;
|
||||
case "bun":
|
||||
console.log(c.info("Detected bun, running bun install"));
|
||||
await execa("bun", ["install"]);
|
||||
fs.writeFileSync(
|
||||
"package.json",
|
||||
fs.readFileSync("package.json", "utf-8").replace("pnpm", "bun"),
|
||||
"utf-8"
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new Error("No package manager detected, please run yarn/npm/pnpm install");
|
||||
}
|
||||
console.log(c.success("✅ Installed dependencies"));
|
||||
}
|
||||
|
||||
const defaultPluginID = process
|
||||
.cwd()
|
||||
.split(path.sep)
|
||||
.pop()
|
||||
.toLowerCase()
|
||||
.replaceAll(" ", "-")
|
||||
.replace(/-?obsidian-?/, "");
|
||||
|
||||
const answer = await prompts(
|
||||
[
|
||||
{
|
||||
type: () => "text",
|
||||
name: "id",
|
||||
message: `Enter the plugin ID ${reset("(lowercase, no spaces)")}`,
|
||||
initial: defaultPluginID,
|
||||
format: (value) => value.toLowerCase().replaceAll(" ", "-").toLowerCase(),
|
||||
validate: (value) => (value.length > 0 ? true : "Please enter a valid plugin ID"),
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
name: "name",
|
||||
message: "Enter the plugin name",
|
||||
initial: (prev) =>
|
||||
prev
|
||||
.replace("obsidian-plugin", "")
|
||||
.split("-")
|
||||
.filter((word) => word.length > 0)
|
||||
.map((word) => capitalize(word))
|
||||
.join(" "),
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
name: "description",
|
||||
message: "Enter the plugin description",
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
name: "author",
|
||||
message: "Enter the author name",
|
||||
initial: gitUserName(),
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
name: "authorUrl",
|
||||
message: "Enter the author URL",
|
||||
initial: (prev) => `https//github.com/${prev}`,
|
||||
},
|
||||
{
|
||||
type: "confirm",
|
||||
name: "desktopOnly",
|
||||
message: "Is this plugin desktop-only?",
|
||||
initial: false,
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
name: "fundingUrl",
|
||||
message: "Enter the funding URL",
|
||||
},
|
||||
{
|
||||
type: "autocomplete",
|
||||
name: "license",
|
||||
message: `Choose a license ${reset(dim("(type to filter, ↑ or ↓ to navigate)"))}`,
|
||||
initial: "MIT",
|
||||
choices: Object.entries(licenses).map(([id, license]) => {
|
||||
return {
|
||||
value: id,
|
||||
title: license.name,
|
||||
description: (license.osiApproved && "OSI Approved") || "",
|
||||
};
|
||||
}),
|
||||
},
|
||||
],
|
||||
{
|
||||
onCancel: () => {
|
||||
console.log(c.warning("❌ Generation cancelled"));
|
||||
process.exit(0);
|
||||
},
|
||||
}
|
||||
);
|
||||
/**
|
||||
* Readd recursive sync
|
||||
* @param {string} dir
|
||||
* @returns {fs.Dirent[]}
|
||||
*/
|
||||
function readdirRecursiveSync(dir) {
|
||||
const results = [];
|
||||
|
||||
function readDirRecursive(currentPath) {
|
||||
const entries = fs.readdirSync(currentPath, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(currentPath, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
readDirRecursive(fullPath);
|
||||
} else {
|
||||
results.push(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readDirRecursive(dir);
|
||||
return results;
|
||||
}
|
||||
const templateFiles = readdirRecursiveSync("./src");
|
||||
|
||||
const data = {
|
||||
name: answer.name || "Sample Plugin",
|
||||
id: answer.id || "sample-plugin",
|
||||
description: answer.description || "This is a sample plugin",
|
||||
interfaceName: answer.name.replaceAll(" ", "") || "SamplePlugin",
|
||||
author: {
|
||||
url: answer.authorUrl || "",
|
||||
name: answer.author || "Sample Author",
|
||||
},
|
||||
isDesktopOnly: !!answer.desktopOnly || false,
|
||||
packageManager: getPackageManager(),
|
||||
};
|
||||
|
||||
if (answer.fundingUrl) {
|
||||
data.fundingUrl = answer.fundingUrl;
|
||||
}
|
||||
|
||||
for (const file of templateFiles) {
|
||||
ejsRender(file, data);
|
||||
}
|
||||
|
||||
updateManifest(data, answer);
|
||||
processReadme(data);
|
||||
processCi(data);
|
||||
processBugReport(data);
|
||||
console.log(c.success("✅ Generated ") + c.info("all files"));
|
||||
|
||||
//update package.json
|
||||
updatePackageJson(data, answer);
|
||||
//create hotreload file
|
||||
fs.writeFileSync(".hotreload", "", { encoding: "utf-8" });
|
||||
|
||||
//detect if yarn or npm or pnpm
|
||||
await updateDep(data.packageManager);
|
||||
|
||||
//delete this files
|
||||
fs.unlinkSync("generate.mjs");
|
||||
30
hooks/_changelog.mjs
Normal file
30
hooks/_changelog.mjs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import { readFileSync, writeFile } from "fs";
|
||||
|
||||
import { Command } from "commander";
|
||||
const program = new Command();
|
||||
|
||||
program.option("-b, --beta", "Pre-release version");
|
||||
|
||||
program.parse();
|
||||
const opt = program.opts();
|
||||
|
||||
/**
|
||||
* Remove text from the file
|
||||
* @param {string} path
|
||||
*/
|
||||
function removeText(path) {
|
||||
const toRemove = [
|
||||
"# Changelog",
|
||||
"All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.",
|
||||
];
|
||||
let changelog = readFileSync(path, "utf8");
|
||||
for (const remove of toRemove) changelog = changelog.replace(remove, "").trim();
|
||||
changelog = changelog.replaceAll(/[\n\r]{3,}/gm, "\n\n").trim();
|
||||
changelog = changelog.replaceAll(/## (.*)[\n\r]{2}### /gm, "## $1\n### ").trim();
|
||||
writeFile(path, changelog.trim(), "utf8", (err) => {
|
||||
if (err) return console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
if (!opt.beta) removeText("CHANGELOG.md");
|
||||
else removeText("CHANGELOG-beta.md");
|
||||
14
manifest.json
Normal file
14
manifest.json
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"id": "<%= data.id %>",
|
||||
"name": "<%= data.name %>",
|
||||
"version": "0.0.0",
|
||||
"minAppVersion": "1.5.12",
|
||||
"description": "<%= data.description %>",
|
||||
"author": "<%= data.author.name %>",
|
||||
"authorUrl": "<%= data.author.url %>",
|
||||
<%_ if (data.fundingURL) { _%>
|
||||
"fundingUrl": "<%= data.fundingURL %>",
|
||||
<%_
|
||||
} _%>
|
||||
"isDesktopOnly": <%= data.isDesktopOnly %>
|
||||
}
|
||||
54
package.json
Normal file
54
package.json
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"name": "sample-plugin",
|
||||
"version": "0.0.0",
|
||||
"description": "",
|
||||
"main": "main.js",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"prebuild": "tsc --noEmit --skipLibCheck",
|
||||
"build": "node esbuild.config.mjs --production",
|
||||
"dev:prod": "node esbuild.config.mjs --vault",
|
||||
"dev": "node esbuild.config.mjs",
|
||||
"export": "node esbuild.config.mjs --production --vault",
|
||||
"bump": "dotenv -- node commit-and-tag-version.mjs",
|
||||
"postbump": "dotenv -- if-env SKIP_POST_BUMP=true && echo skip bump || git push --follow-tags origin master",
|
||||
"predeploy": "pnpm run bump",
|
||||
"deploy": "pnpm run export",
|
||||
"lint": "pnpm biome format --write src/"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^22.2.0"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.8.1",
|
||||
"@types/node": "^16.11.6",
|
||||
"builtin-modules": "4.0.0",
|
||||
"i18next": "^23.16.4",
|
||||
"esbuild": "0.21.5",
|
||||
"obsidian": "latest",
|
||||
"tslib": "2.6.3",
|
||||
"typescript": "latest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@delucis/if-env": "^1.1.2",
|
||||
"ansi-colors": "^4.1.3",
|
||||
"commander": "^12.1.0",
|
||||
"commit-and-tag-version": "^12.4.1",
|
||||
"dedent": "^1.5.3",
|
||||
"dotenv": "^16.4.5",
|
||||
"dotenv-cli": "^7.4.2",
|
||||
"ejs": "^3.1.10",
|
||||
"execa": "^9.5.2",
|
||||
"git-user-name": "^2.0.0",
|
||||
"license": "^1.0.3",
|
||||
"prompts": "^2.4.2",
|
||||
"spdx-license-list": "^6.9.0"
|
||||
},
|
||||
"trustedDependencies": [
|
||||
"@biomejs/biome",
|
||||
"esbuild"
|
||||
]
|
||||
}
|
||||
8
src/i18n/i18next.d.ts
vendored
Normal file
8
src/i18n/i18next.d.ts
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import type { resources } from "../i18n";
|
||||
|
||||
declare module "i18next" {
|
||||
interface CustomTypeOptions {
|
||||
readonly resources: (typeof resources)["en"];
|
||||
readonly returnNull: false;
|
||||
}
|
||||
}
|
||||
12
src/i18n/index.ts
Normal file
12
src/i18n/index.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { moment } from "obsidian";
|
||||
|
||||
import en from "./locales/en.json";
|
||||
//import fr from "./locales/fr.json";
|
||||
|
||||
|
||||
export const resources = {
|
||||
//fr: {translation: fr},
|
||||
en: {translation: en}
|
||||
};
|
||||
|
||||
export const translationLanguage = Object.keys(resources).find(i => i.toLocaleLowerCase() == moment.locale()) ? moment.locale() : "en";
|
||||
0
src/i18n/locales/en.json
Normal file
0
src/i18n/locales/en.json
Normal file
9
src/interfaces.ts
Normal file
9
src/interfaces.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
|
||||
export interface <%= data.interfaceName %>Settings {
|
||||
mySetting: string;
|
||||
}
|
||||
|
||||
export const DEFAULT_SETTINGS: <%= data.interfaceName %>Settings = {
|
||||
mySetting: "default"
|
||||
};
|
||||
98
src/main.ts
Normal file
98
src/main.ts
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
import { type Editor, MarkdownView, Notice, Plugin, Modal } from "obsidian";
|
||||
import { resources, translationLanguage } from "./i18n";
|
||||
import i18next from "i18next";
|
||||
|
||||
import { <%= data.interfaceName %>SettingTab } from "./settings";
|
||||
import { <%= data.interfaceName%>Modal } from "./modals";
|
||||
import { <%= data.interfaceName%>Settings, DEFAULT_SETTINGS } from "./interfaces";
|
||||
|
||||
export default class <%= data.interfaceName %> extends Plugin {
|
||||
settings!: <%= data.interfaceName %>Settings;
|
||||
|
||||
async onload() {
|
||||
console.log(`[${this.manifest.name}] Loaded`)
|
||||
await this.loadSettings();
|
||||
//load i18next
|
||||
await i18next.init({
|
||||
lng: translationLanguage,
|
||||
fallbackLng: "en",
|
||||
resources,
|
||||
returnNull: false,
|
||||
returnEmptyString: false,
|
||||
});
|
||||
// This creates an icon in the left ribbon.
|
||||
const ribbonIconEl = this.addRibbonIcon("dice", "Sample Plugin", (_evt: MouseEvent) => {
|
||||
// Called when the user clicks the icon.
|
||||
new Notice("This is a notice!");
|
||||
});
|
||||
// Perform additional things with the ribbon
|
||||
ribbonIconEl.addClass("my-plugin-ribbon-class");
|
||||
|
||||
// This adds a status bar item to the bottom of the app. Does not work on mobile apps.
|
||||
const statusBarItemEl = this.addStatusBarItem();
|
||||
statusBarItemEl.setText("Status Bar Text");
|
||||
|
||||
// This adds a simple command that can be triggered anywhere
|
||||
this.addCommand({
|
||||
id: "open-sample-modal-simple",
|
||||
name: "Open sample modal (simple)",
|
||||
callback: () => {
|
||||
new <%= data.interfaceName%>Modal(this.app).open();
|
||||
}
|
||||
});
|
||||
// This adds an editor command that can perform some operation on the current editor instance
|
||||
this.addCommand({
|
||||
id: "sample-editor-command",
|
||||
name: "Sample editor command",
|
||||
editorCallback: (editor: Editor, _view: MarkdownView|MarkdownFileInfo) => {
|
||||
console.log(editor.getSelection());
|
||||
editor.replaceSelection("Sample Editor Command");
|
||||
}
|
||||
});
|
||||
// This adds a complex command that can check whether the current state of the app allows execution of the command
|
||||
this.addCommand({
|
||||
id: "open-sample-modal-complex",
|
||||
name: "Open sample modal (complex)",
|
||||
checkCallback: (checking: boolean) => {
|
||||
// Conditions to check
|
||||
const markdownView = this.app.workspace.getActiveViewOfType(MarkdownView);
|
||||
if (markdownView) {
|
||||
// If checking is true, we're simply "checking" if the command can be run.
|
||||
// If checking is false, then we want to actually perform the operation.
|
||||
if (!checking) {
|
||||
new <%= DataTransferItem={}.name%>Modal(this.app).open();
|
||||
}
|
||||
|
||||
// This command will only show up in Command Palette when the check function returns true
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// This adds a settings tab so the user can configure various aspects of the plugin
|
||||
this.addSettingTab(new <%= data.interfaceName %>SettingTab(this.app, this));
|
||||
|
||||
// If the plugin hooks up any global DOM events (on parts of the app that doesn't belong to this plugin)
|
||||
// Using this function will automatically remove the event listener when this plugin is disabled.
|
||||
this.registerDomEvent(document, "click", (evt: MouseEvent) => {
|
||||
console.log("click", evt);
|
||||
});
|
||||
|
||||
// When registering intervals, this function will automatically clear the interval when the plugin is disabled.
|
||||
this.registerInterval(window.setInterval(() => console.log("setInterval"), 5 * 60 * 1000));
|
||||
}
|
||||
|
||||
onunload() {
|
||||
console.log(`[${this.manifest.name}] Unloaded`);
|
||||
}
|
||||
|
||||
async loadSettings() {
|
||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
||||
}
|
||||
|
||||
async saveSettings() {
|
||||
await this.saveData(this.settings);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
17
src/modals.ts
Normal file
17
src/modals.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { type App, Modal } from "obsidian";
|
||||
|
||||
export class <%= data.interfaceName%>Modal extends Modal {
|
||||
constructor(app: App) {
|
||||
super(app);
|
||||
}
|
||||
|
||||
onOpen() {
|
||||
const {contentEl} = this;
|
||||
contentEl.setText("Woah!");
|
||||
}
|
||||
|
||||
onClose() {
|
||||
const {contentEl} = this;
|
||||
contentEl.empty();
|
||||
}
|
||||
}
|
||||
28
src/settings.ts
Normal file
28
src/settings.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import { type App, PluginSettingTab, Setting } from "obsidian";
|
||||
import <%= data.interfaceName %> from "./main";
|
||||
|
||||
export class <%= data.interfaceName %>SettingTab extends PluginSettingTab {
|
||||
plugin: <%= data.interfaceName %>;
|
||||
|
||||
constructor(app: App, plugin: <%= data.interfaceName %>) {
|
||||
super(app, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
display(): void {
|
||||
const {containerEl} = this;
|
||||
|
||||
containerEl.empty();
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Setting #1")
|
||||
.setDesc("It's a secret")
|
||||
.addText(text => text
|
||||
.setPlaceholder("Enter your secret")
|
||||
.setValue(this.plugin.settings.mySetting)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.mySetting = value;
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
}
|
||||
}
|
||||
8
src/styles.css
Normal file
8
src/styles.css
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
|
||||
This CSS file will be included with your plugin, and
|
||||
available in the app when your plugin is enabled.
|
||||
|
||||
If your plugin does not need CSS, delete this file.
|
||||
|
||||
*/
|
||||
33
tsconfig.json
Normal file
33
tsconfig.json
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"noEmit": true,
|
||||
"baseUrl": ".",
|
||||
"inlineSourceMap": true,
|
||||
"inlineSources": true,
|
||||
"skipLibCheck": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"module": "ESNext",
|
||||
"target": "ESNext",
|
||||
"allowJs": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"isolatedModules": true,
|
||||
"resolveJsonModule": true,
|
||||
"strictNullChecks": true,
|
||||
"lib": [
|
||||
"DOM",
|
||||
"ES5",
|
||||
"ES6",
|
||||
"ES7",
|
||||
"ES2015",
|
||||
"ES2021",
|
||||
"ES2022",
|
||||
"DOM.Iterable"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
]
|
||||
}
|
||||
14
version-bump.mjs
Normal file
14
version-bump.mjs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { readFileSync, writeFileSync } from "fs";
|
||||
|
||||
const targetVersion = process.env.npm_package_version;
|
||||
|
||||
// read minAppVersion from manifest.json and bump version to target version
|
||||
let manifest = JSON.parse(readFileSync("manifest.json", "utf8"));
|
||||
const { minAppVersion } = manifest;
|
||||
manifest.version = targetVersion;
|
||||
writeFileSync("manifest.json", JSON.stringify(manifest, null, "\t"));
|
||||
|
||||
// update versions.json with target version and minAppVersion from manifest.json
|
||||
let versions = JSON.parse(readFileSync("versions.json", "utf8"));
|
||||
versions[targetVersion] = minAppVersion;
|
||||
writeFileSync("versions.json", JSON.stringify(versions, null, "\t"));
|
||||
3
versions.json
Normal file
3
versions.json
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"1.0.0": "0.15.0"
|
||||
}
|
||||
Loading…
Reference in a new issue