Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,6 @@ jobs:
run: pnpm install --frozen-lockfile
- name: Run build with lint
run: pnpm run build-with-lint
- name: Svelte check
run: pnpm run check

# Builds the docs site the way Cloudflare Pages does (docs/.node-version,
# frozen docs lockfile) and checks internal links and anchors. Cloudflare
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@ coverage/

# Obsidian application bundle (only ever extracted transiently for inspection)
/app.js
.svelte-check/
9 changes: 9 additions & 0 deletions .oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"extends": [
"./.oxlintrc.syntax.json"
],
"options": {
"typeAware": true
}
}
242 changes: 242 additions & 0 deletions .oxlintrc.syntax.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": [],
"categories": {
"correctness": "off"
},
"options": {
"typeAware": false
},
"env": {
"builtin": true
},
"ignorePatterns": [
"node_modules/**",
"dist/**",
"docs/**",
".audit/**",
".obsidian-e2e-vaults/**",
"main.js",
"**/*.d.ts",
".svelte-check/**"
],
"overrides": [
{
"files": [
"**/*.ts"
],
"rules": {
"no-array-constructor": "error",
"no-unused-expressions": "error",
"no-unused-vars": [
"error",
{
"args": "none"
}
],
"no-prototype-builtins": "off",
"no-empty-function": "off",
"typescript/ban-ts-comment": "off",
"typescript/no-duplicate-enum-values": "error",
"typescript/no-empty-object-type": "error",
"typescript/no-explicit-any": "off",
"typescript/no-extra-non-null-assertion": "error",
"typescript/no-misused-new": "error",
"typescript/no-namespace": "error",
"typescript/no-non-null-asserted-optional-chain": "error",
"typescript/no-require-imports": "error",
"typescript/no-this-alias": "error",
"typescript/no-unnecessary-type-constraint": "error",
"typescript/no-unsafe-declaration-merging": "error",
"typescript/no-unsafe-function-type": "error",
"typescript/no-wrapper-object-types": "error",
"typescript/prefer-as-const": "error",
"typescript/prefer-namespace-keyword": "error",
"typescript/triple-slash-reference": "error",
"typescript/consistent-type-imports": "warn",
"typescript/no-unsafe-assignment": "off",
"typescript/no-unsafe-member-access": "off",
"typescript/no-unsafe-call": "off",
"typescript/no-unsafe-return": "off",
"typescript/no-unsafe-argument": "off",
"typescript/restrict-template-expressions": "off"
},
"plugins": [
"typescript"
],
"env": {
"browser": true,
"node": true
}
},
{
"files": [
"*.svelte",
"**/*.svelte"
],
"rules": {
"no-inner-declarations": "off",
"no-self-assign": "off"
}
},
{
"files": [
"**/*.svelte",
"**/*.svelte.ts"
],
"env": {
"browser": true
}
},
{
"files": [
"src/**/*.ts"
],
"rules": {
"no-useless-escape": "error",
"typescript/no-unnecessary-type-assertion": "error",
"typescript/prefer-promise-reject-errors": "error",
"typescript/unbound-method": "error",
"typescript/no-floating-promises": "error",
"typescript/no-misused-promises": "error",
"typescript/no-deprecated": "error"
},
"plugins": [
"typescript"
]
},
{
"files": [
"src/**/*.ts",
"src/**/*.svelte"
],
"rules": {
"no-console": [
"error",
{
"allow": [
"warn",
"error"
]
}
]
}
},
{
"files": [
"src/gui/components/textareaIndent.ts",
"src/gui/imagePasteHandler.ts"
],
"rules": {
"typescript/no-deprecated": [
"error",
{
"allow": [
{
"from": "lib",
"name": "execCommand"
}
]
}
]
},
"plugins": [
"typescript"
]
},
{
"files": [
"src/gui/svelte/mountComponent.ts"
],
"rules": {
"typescript/no-explicit-any": "error"
},
"plugins": [
"typescript"
]
},
{
"files": [
"src/**/*.ts",
"src/**/*.svelte"
],
"rules": {
"no-new-func": "error",
"no-implied-eval": "error"
}
},
{
"files": [
"src/**/*.ts"
],
"rules": {
"no-implied-eval": "off",
"typescript/no-implied-eval": "error"
},
"plugins": [
"typescript"
]
},
{
"files": [
"src/utils/userScript.ts"
],
"rules": {
"no-new-func": "off",
"typescript/no-implied-eval": "off"
},
"plugins": [
"typescript"
]
},
{
"files": [
"src/**/*.test.ts"
],
"rules": {
"no-useless-escape": "off",
"typescript/no-unnecessary-type-assertion": "off",
"typescript/prefer-promise-reject-errors": "off",
"typescript/unbound-method": "off",
"typescript/no-floating-promises": "off",
"typescript/no-misused-promises": "off",
"typescript/no-deprecated": "off",
"no-console": "off",
"no-new-func": "off",
"no-implied-eval": "off",
"typescript/no-implied-eval": "off"
}
},
{
"files": [
"src/**/*.ts"
],
"rules": {
"quickadd/restricted-syntax": "error"
}
},
{
"files": [
"src/**/*.test.ts"
],
"rules": {
"quickadd/restricted-syntax": "off"
}
},
{
"files": [
"**/*.svelte.ts"
],
"rules": {
"quickadd/svelte-runes": "error",
"quickadd/svelte-debug": "warn"
}
}
],
"jsPlugins": [
{
"name": "quickadd",
"specifier": "./tooling/oxlint-plugin.mjs"
}
]
}
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ QuickAdd is an Obsidian community plugin. Source code lives in `src/`: core logi
## Build, Test, and Development Commands
- `pnpm run dev`: watch-mode bundle via `esbuild.config.mjs`, regenerating `main.js` as you edit.
- `pnpm run build`: run `tsc --noEmit` then produce the production bundle.
- `pnpm run build-with-lint`: type-check, run ESLint (`pnpm lint`), then produce the production build; use for release packaging.
- `pnpm run lint`: apply ESLint to TypeScript sources to catch type and usage issues.
- `pnpm run build-with-lint`: type-check, run Oxlint and Svelte policy checks (`pnpm lint`), then produce the production build; use for release packaging.
- `pnpm run lint`: run Oxlint, Svelte template policies, and strict Svelte compiler/type checks.
- `pnpm run test`: execute Vitest with `--passWithNoTests` for fast local verification.

## Coding Style & Naming Conventions
Expand Down
6 changes: 6 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pnpm install
pnpm run dev # rebuild main.js on every change
pnpm run test # unit tests
pnpm run build # type-check and bundle
pnpm run lint # Oxlint, Svelte template policies, and strict Svelte checks
```

For changes that affect the plugin at runtime, verify the behavior in Obsidian
Expand All @@ -47,6 +48,11 @@ obsidian vault=dev plugin:reload id=quickadd
Keep pull requests narrow. Include generated files such as `main.js` and
`styles.css` when the source change updates them.

TypeScript checks use Oxlint. Svelte compiler and type diagnostics fail on
warnings, and a small compiler-AST checker enforces template policies and the
same custom syntax guards. [Tooling checks](tooling/README.md) lists the rules
and the migration from ESLint.

### Obsidian's plugin review

Obsidian reviews each release with ESLint (`eslint-plugin-obsidianmd`) and
Expand Down
2 changes: 0 additions & 2 deletions esbuild.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { readFileSync } from "node:fs";
import esbuild from "esbuild";
import esbuildSvelte from "esbuild-svelte";
import process from "process";
import sveltePreprocess from "svelte-preprocess";
import { getGitInfo } from "./buildGitInfo.mjs";
import { svelteCompilerOptions } from "./svelteCompilerOptions.mjs";

Expand Down Expand Up @@ -66,7 +65,6 @@ const options = Object.freeze({
plugins: [
esbuildSvelte({
compilerOptions: svelteCompilerOptions,
preprocess: sveltePreprocess(),
}),
],
format: "cjs",
Expand Down
Loading
Loading