mirror of
https://github.com/dnlbauer/obsidian-dataview-autocompletion.git
synced 2026-09-10 14:15:29 +00:00
feat: use prettier
This commit is contained in:
@@ -1,10 +1,17 @@
|
||||
# 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
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.json]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.{ts,js}]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
1
.husky/pre-commit
Normal file
1
.husky/pre-commit
Normal file
@@ -0,0 +1 @@
|
||||
npx lint-staged
|
||||
4
.prettierignore
Normal file
4
.prettierignore
Normal file
@@ -0,0 +1,4 @@
|
||||
# Ignore artifacts:
|
||||
build
|
||||
coverage
|
||||
test-vault
|
||||
1
.prettierrc
Normal file
1
.prettierrc
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
8
.prettierrc.json
Normal file
8
.prettierrc.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"tabWidth": 4,
|
||||
"semi": true,
|
||||
"embeddedLanguageFormatting": "off",
|
||||
"parser": "typescript",
|
||||
"printWidth": 120,
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
16
README.md
16
README.md
@@ -6,6 +6,7 @@ This project uses TypeScript to provide type checking and documentation.
|
||||
The repo depends on the latest plugin API (obsidian.d.ts) in TypeScript Definition format, which contains TSDoc comments describing what it does.
|
||||
|
||||
This sample plugin demonstrates some of the basic functionality the plugin API can do.
|
||||
|
||||
- Adds a ribbon icon, which shows a Notice when clicked.
|
||||
- Adds a command "Open Sample Modal" which opens a Modal.
|
||||
- Adds a plugin setting tab to the settings page.
|
||||
@@ -56,7 +57,8 @@ Quick starting guide for new plugin devs:
|
||||
- Copy over `main.js`, `styles.css`, `manifest.json` to your vault `VaultFolder/.obsidian/plugins/your-plugin-id/`.
|
||||
|
||||
## Improve code quality with eslint (optional)
|
||||
- [ESLint](https://eslint.org/) is a tool that analyzes your code to quickly find problems. You can run ESLint against your plugin to find common bugs and ways to improve your code.
|
||||
|
||||
- [ESLint](https://eslint.org/) is a tool that analyzes your code to quickly find problems. You can run ESLint against your plugin to find common bugs and ways to improve your code.
|
||||
- To use eslint with this project, make sure to install eslint from terminal:
|
||||
- `npm install -g eslint`
|
||||
- To use eslint to analyze this project use this command:
|
||||
@@ -73,7 +75,7 @@ The simple way is to set the `fundingUrl` field to your link in your `manifest.j
|
||||
|
||||
```json
|
||||
{
|
||||
"fundingUrl": "https://buymeacoffee.com"
|
||||
"fundingUrl": "https://buymeacoffee.com"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -81,11 +83,11 @@ If you have multiple URLs, you can also do:
|
||||
|
||||
```json
|
||||
{
|
||||
"fundingUrl": {
|
||||
"Buy Me a Coffee": "https://buymeacoffee.com",
|
||||
"GitHub Sponsor": "https://github.com/sponsors",
|
||||
"Patreon": "https://www.patreon.com/"
|
||||
}
|
||||
"fundingUrl": {
|
||||
"Buy Me a Coffee": "https://buymeacoffee.com",
|
||||
"GitHub Sponsor": "https://github.com/sponsors",
|
||||
"Patreon": "https://www.patreon.com/"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -2,48 +2,48 @@ import esbuild from "esbuild";
|
||||
import process from "process";
|
||||
import builtins from "builtin-modules";
|
||||
|
||||
const banner =
|
||||
`/*
|
||||
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
|
||||
*/
|
||||
`;
|
||||
|
||||
const prod = (process.argv[2] === "production");
|
||||
const prod = process.argv[2] === "production";
|
||||
|
||||
const context = await esbuild.context({
|
||||
banner: {
|
||||
js: banner,
|
||||
},
|
||||
entryPoints: ["main.ts"],
|
||||
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: "es2018",
|
||||
logLevel: "info",
|
||||
sourcemap: prod ? false : "inline",
|
||||
treeShaking: true,
|
||||
outfile: "main.js",
|
||||
minify: prod,
|
||||
banner: {
|
||||
js: banner,
|
||||
},
|
||||
entryPoints: ["main.ts"],
|
||||
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: "es2018",
|
||||
logLevel: "info",
|
||||
sourcemap: prod ? false : "inline",
|
||||
treeShaking: true,
|
||||
outfile: "main.js",
|
||||
minify: prod,
|
||||
});
|
||||
|
||||
if (prod) {
|
||||
await context.rebuild();
|
||||
process.exit(0);
|
||||
await context.rebuild();
|
||||
process.exit(0);
|
||||
} else {
|
||||
await context.watch();
|
||||
await context.watch();
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"id": "sample-plugin",
|
||||
"name": "Sample Plugin",
|
||||
"version": "1.0.0",
|
||||
"minAppVersion": "0.15.0",
|
||||
"description": "Demonstrates some of the capabilities of the Obsidian API.",
|
||||
"author": "Obsidian",
|
||||
"authorUrl": "https://obsidian.md",
|
||||
"fundingUrl": "https://obsidian.md/pricing",
|
||||
"isDesktopOnly": false
|
||||
"id": "sample-plugin",
|
||||
"name": "Sample Plugin",
|
||||
"version": "1.0.0",
|
||||
"minAppVersion": "0.15.0",
|
||||
"description": "Demonstrates some of the capabilities of the Obsidian API.",
|
||||
"author": "Obsidian",
|
||||
"authorUrl": "https://obsidian.md",
|
||||
"fundingUrl": "https://obsidian.md/pricing",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
|
||||
11130
package-lock.json
generated
11130
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
83
package.json
83
package.json
@@ -1,40 +1,47 @@
|
||||
{
|
||||
"name": "obsidian-sample-plugin",
|
||||
"version": "1.0.0",
|
||||
"description": "This is a sample plugin for Obsidian (https://obsidian.md)",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"dev": "npx rollup --config rollup.config.js -w",
|
||||
"build": "npx rollup --config rollup.config.js --environment BUILD:production",
|
||||
"test": "npx jest",
|
||||
"version": "node version-bump.mjs && git add manifest.json versions.json"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.14",
|
||||
"@types/node": "^16.11.6",
|
||||
"@typescript-eslint/eslint-plugin": "5.29.0",
|
||||
"@typescript-eslint/parser": "5.29.0",
|
||||
"babel-jest": "^29.7.0",
|
||||
"builtin-modules": "3.3.0",
|
||||
"esbuild": "0.17.3",
|
||||
"obsidian": "latest",
|
||||
"ts-jest": "^29.2.5",
|
||||
"tslib": "2.4.0",
|
||||
"typescript": "4.7.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@rollup/plugin-commonjs": "^28.0.1",
|
||||
"@rollup/plugin-node-resolve": "^15.3.0",
|
||||
"rollup": "^2.79.2",
|
||||
"rollup-plugin-copy": "^3.5.0",
|
||||
"rollup-plugin-typescript2": "^0.36.0"
|
||||
},
|
||||
"jest": {
|
||||
"transform": {
|
||||
"^.+\\.(ts|tsx|js|jsx)$": "ts-jest"
|
||||
}
|
||||
}
|
||||
"name": "obsidian-sample-plugin",
|
||||
"version": "1.0.0",
|
||||
"description": "This is a sample plugin for Obsidian (https://obsidian.md)",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"dev": "npx rollup --config rollup.config.js -w",
|
||||
"build": "npx rollup --config rollup.config.js --environment BUILD:production",
|
||||
"test": "npx jest",
|
||||
"version": "node version-bump.mjs && git add manifest.json versions.json",
|
||||
"prepare": "husky"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.14",
|
||||
"@types/node": "^16.11.6",
|
||||
"@typescript-eslint/eslint-plugin": "5.29.0",
|
||||
"@typescript-eslint/parser": "5.29.0",
|
||||
"babel-jest": "^29.7.0",
|
||||
"builtin-modules": "3.3.0",
|
||||
"esbuild": "0.17.3",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^15.2.11",
|
||||
"obsidian": "latest",
|
||||
"prettier": "3.4.2",
|
||||
"ts-jest": "^29.2.5",
|
||||
"tslib": "2.4.0",
|
||||
"typescript": "4.7.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@rollup/plugin-commonjs": "^28.0.1",
|
||||
"@rollup/plugin-node-resolve": "^15.3.0",
|
||||
"rollup": "^2.79.2",
|
||||
"rollup-plugin-copy": "^3.5.0",
|
||||
"rollup-plugin-typescript2": "^0.36.0"
|
||||
},
|
||||
"jest": {
|
||||
"transform": {
|
||||
"^.+\\.(ts|tsx|js|jsx)$": "ts-jest"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"**/*": "prettier --write --ignore-unknown"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,15 +5,13 @@ import typescript2 from "rollup-plugin-typescript2";
|
||||
|
||||
const BASE_CONFIG = {
|
||||
input: "src/main.ts",
|
||||
external: ["obsidian"]
|
||||
external: ["obsidian"],
|
||||
};
|
||||
|
||||
const getRollupPlugins = (tsconfig, ...plugins) =>
|
||||
[
|
||||
typescript2(tsconfig),
|
||||
nodeResolve({ browser: true }),
|
||||
commonjs(),
|
||||
].concat(plugins);
|
||||
[typescript2(tsconfig), nodeResolve({ browser: true }), commonjs()].concat(
|
||||
plugins,
|
||||
);
|
||||
|
||||
const DEV_PLUGIN_CONFIG = {
|
||||
...BASE_CONFIG,
|
||||
@@ -28,10 +26,16 @@ const DEV_PLUGIN_CONFIG = {
|
||||
undefined,
|
||||
copy({
|
||||
targets: [
|
||||
{ src: "manifest.json", dest: "test-vault/.obsidian/plugins/dataview-suggester/" },
|
||||
{ src: "styles.css", dest: "test-vault/.obsidian/plugins/dataview-suggester/" },
|
||||
{
|
||||
src: "manifest.json",
|
||||
dest: "test-vault/.obsidian/plugins/dataview-suggester/",
|
||||
},
|
||||
{
|
||||
src: "styles.css",
|
||||
dest: "test-vault/.obsidian/plugins/dataview-suggester/",
|
||||
},
|
||||
],
|
||||
})
|
||||
}),
|
||||
),
|
||||
};
|
||||
|
||||
|
||||
@@ -1,72 +1,84 @@
|
||||
import { App, Editor, Plugin, EditorPosition, EditorSuggest, EditorSuggestContext, EditorSuggestTriggerInfo, TFile } from 'obsidian';
|
||||
import { getTriggerText } from './trigger';
|
||||
import {
|
||||
App,
|
||||
Editor,
|
||||
Plugin,
|
||||
EditorPosition,
|
||||
EditorSuggest,
|
||||
EditorSuggestContext,
|
||||
EditorSuggestTriggerInfo,
|
||||
TFile,
|
||||
} from "obsidian";
|
||||
import { getTriggerText } from "./trigger";
|
||||
|
||||
export class DataviewSuggester extends EditorSuggest<String> {
|
||||
constructor(plugin: Plugin) {
|
||||
super(plugin.app);
|
||||
}
|
||||
|
||||
constructor(plugin: Plugin) {
|
||||
super(plugin.app)
|
||||
}
|
||||
onTrigger(
|
||||
cursor: EditorPosition,
|
||||
editor: Editor,
|
||||
file: TFile,
|
||||
): EditorSuggestTriggerInfo | null {
|
||||
const line = editor.getLine(cursor.line);
|
||||
|
||||
onTrigger(
|
||||
cursor: EditorPosition,
|
||||
editor: Editor,
|
||||
file: TFile,
|
||||
): EditorSuggestTriggerInfo | null {
|
||||
const line = editor.getLine(cursor.line);
|
||||
|
||||
let trigger = getTriggerText(line, cursor.ch)
|
||||
if (trigger !== null) {
|
||||
return {
|
||||
query: trigger[0],
|
||||
start: { line: cursor.line, ch: trigger[1] },
|
||||
end: { line: cursor.line, ch: trigger[2] },
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
let trigger = getTriggerText(line, cursor.ch);
|
||||
if (trigger !== null) {
|
||||
return {
|
||||
query: trigger[0],
|
||||
start: { line: cursor.line, ch: trigger[1] },
|
||||
end: { line: cursor.line, ch: trigger[2] },
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
getSuggestions(context: EditorSuggestContext): string[] | Promise<string[]> {
|
||||
const suggestions: string[] = []
|
||||
// TODO use official dv api?
|
||||
// @ts-ignore
|
||||
for (const page of this.app.plugins.plugins.dataview.index.pages) {
|
||||
const fields = page[1].fields
|
||||
for (let [key, val] of fields) {
|
||||
let arrayVal
|
||||
if (!Array.isArray(val)) {
|
||||
arrayVal = [val]
|
||||
} else {
|
||||
arrayVal = val
|
||||
}
|
||||
getSuggestions(
|
||||
context: EditorSuggestContext,
|
||||
): string[] | Promise<string[]> {
|
||||
const suggestions: string[] = [];
|
||||
// TODO use official dv api?
|
||||
// @ts-ignore
|
||||
for (const page of this.app.plugins.plugins.dataview.index.pages) {
|
||||
const fields = page[1].fields;
|
||||
for (let [key, val] of fields) {
|
||||
let arrayVal;
|
||||
if (!Array.isArray(val)) {
|
||||
arrayVal = [val];
|
||||
} else {
|
||||
arrayVal = val;
|
||||
}
|
||||
|
||||
for (const value of arrayVal) {
|
||||
// TODO whitespace in match
|
||||
// Fuzzy matching?
|
||||
const suggestion = key + ":: " + value
|
||||
if (suggestion.includes(context.query) && !suggestions.includes(suggestion)) {
|
||||
suggestions.push(key+ ":: " + value)
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const value of arrayVal) {
|
||||
// TODO whitespace in match
|
||||
// Fuzzy matching?
|
||||
const suggestion = key + ":: " + value;
|
||||
if (
|
||||
suggestion.includes(context.query) &&
|
||||
!suggestions.includes(suggestion)
|
||||
) {
|
||||
suggestions.push(key + ":: " + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(suggestions);
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
}
|
||||
console.log(suggestions)
|
||||
return suggestions
|
||||
}
|
||||
renderSuggestion(value: string, el: HTMLElement): void {
|
||||
el.setText(value);
|
||||
}
|
||||
|
||||
renderSuggestion(value: string, el: HTMLElement): void {
|
||||
el.setText(value)
|
||||
}
|
||||
selectSuggestion(value: string, evt: MouseEvent | KeyboardEvent): void {
|
||||
console.log("selected", value);
|
||||
const { editor, start, end } = this.context!;
|
||||
editor.replaceRange(value, start, end);
|
||||
|
||||
selectSuggestion(value: string, evt: MouseEvent | KeyboardEvent): void {
|
||||
console.log("selected", value)
|
||||
const { editor, start, end } = this.context!;
|
||||
editor.replaceRange(value, start, end);
|
||||
|
||||
const newCursorPos = {
|
||||
line: end.line + 1,
|
||||
ch: 0,
|
||||
};
|
||||
editor.setCursor(newCursorPos);
|
||||
}
|
||||
const newCursorPos = {
|
||||
line: end.line + 1,
|
||||
ch: 0,
|
||||
};
|
||||
editor.setCursor(newCursorPos);
|
||||
}
|
||||
}
|
||||
|
||||
48
src/main.ts
48
src/main.ts
@@ -1,35 +1,37 @@
|
||||
import { App, Plugin, PluginSettingTab, Setting } from 'obsidian';
|
||||
import { DataviewSuggester } from './DataviewSuggester';
|
||||
import { App, Plugin, PluginSettingTab, Setting } from "obsidian";
|
||||
import { DataviewSuggester } from "./DataviewSuggester";
|
||||
|
||||
interface DataviewAutocompleteSettings {
|
||||
// mySetting: string;
|
||||
// mySetting: string;
|
||||
}
|
||||
|
||||
const DEFAULT_SETTINGS: DataviewAutocompleteSettings = {
|
||||
// mySetting: 'default'
|
||||
}
|
||||
// mySetting: 'default'
|
||||
};
|
||||
|
||||
export default class DataviewAutocompletePlugin extends Plugin {
|
||||
settings: DataviewAutocompleteSettings;
|
||||
suggester: DataviewSuggester
|
||||
settings: DataviewAutocompleteSettings;
|
||||
suggester: DataviewSuggester;
|
||||
|
||||
async onload() {
|
||||
await this.loadSettings();
|
||||
|
||||
// register suggester
|
||||
this.suggester = new DataviewSuggester(this);
|
||||
this.registerEditorSuggest(this.suggester);
|
||||
}
|
||||
async onload() {
|
||||
await this.loadSettings();
|
||||
|
||||
onunload() {
|
||||
// register suggester
|
||||
this.suggester = new DataviewSuggester(this);
|
||||
this.registerEditorSuggest(this.suggester);
|
||||
}
|
||||
|
||||
}
|
||||
onunload() {}
|
||||
|
||||
async loadSettings() {
|
||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
||||
}
|
||||
async loadSettings() {
|
||||
this.settings = Object.assign(
|
||||
{},
|
||||
DEFAULT_SETTINGS,
|
||||
await this.loadData(),
|
||||
);
|
||||
}
|
||||
|
||||
async saveSettings() {
|
||||
await this.saveData(this.settings);
|
||||
}
|
||||
}
|
||||
async saveSettings() {
|
||||
await this.saveData(this.settings);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,139 +1,262 @@
|
||||
import { getTriggerText } from "./trigger"
|
||||
import { getTriggerText } from "./trigger";
|
||||
|
||||
describe("trigger", () => {
|
||||
describe("empty", () => {
|
||||
test("empty parantheses", () => {
|
||||
expect(getTriggerText("() testing", 1)).toEqual(["", 1, 1])
|
||||
})
|
||||
expect(getTriggerText("() testing", 1)).toEqual(["", 1, 1]);
|
||||
});
|
||||
test("empty square brackets", () => {
|
||||
expect(getTriggerText("[] testing", 1)).toEqual(["", 1, 1])
|
||||
})
|
||||
expect(getTriggerText("[] testing", 1)).toEqual(["", 1, 1]);
|
||||
});
|
||||
test("empty square brackets in text", () => {
|
||||
expect(getTriggerText("test [] testing", 6)).toEqual(["", 6, 6])
|
||||
})
|
||||
expect(getTriggerText("test [] testing", 6)).toEqual(["", 6, 6]);
|
||||
});
|
||||
// test("not match empty double square brackets", () => {
|
||||
// expect(getTriggerText("[[]] testing", 2)).toEqual(null)
|
||||
// })
|
||||
test("multiple empty brackets in text", () => {
|
||||
expect(getTriggerText("test [] and [] testing", 13)).toEqual(["", 13, 13])
|
||||
})
|
||||
})
|
||||
expect(getTriggerText("test [] and [] testing", 13)).toEqual([
|
||||
"",
|
||||
13,
|
||||
13,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("text in parantheses", () => {
|
||||
test("text behind", () => {
|
||||
expect(getTriggerText("(capture) testing", 1)).toEqual(["capture", 1, 8])
|
||||
})
|
||||
expect(getTriggerText("(capture) testing", 1)).toEqual([
|
||||
"capture",
|
||||
1,
|
||||
8,
|
||||
]);
|
||||
});
|
||||
test("text before", () => {
|
||||
expect(getTriggerText("testing (capture)", 12)).toEqual(["capture", 9, 16])
|
||||
})
|
||||
expect(getTriggerText("testing (capture)", 12)).toEqual([
|
||||
"capture",
|
||||
9,
|
||||
16,
|
||||
]);
|
||||
});
|
||||
test("text behind no whitespace", () => {
|
||||
expect(getTriggerText("(capture)testing", 1)).toEqual(["capture", 1, 8])
|
||||
})
|
||||
expect(getTriggerText("(capture)testing", 1)).toEqual([
|
||||
"capture",
|
||||
1,
|
||||
8,
|
||||
]);
|
||||
});
|
||||
test("text before no whitespace", () => {
|
||||
expect(getTriggerText("test(capture)", 5)).toEqual(["capture", 5, 12])
|
||||
})
|
||||
expect(getTriggerText("test(capture)", 5)).toEqual([
|
||||
"capture",
|
||||
5,
|
||||
12,
|
||||
]);
|
||||
});
|
||||
test("text before and behind", () => {
|
||||
expect(getTriggerText("test (capture) testing", 6)).toEqual(["capture", 6, 13])
|
||||
})
|
||||
expect(getTriggerText("test (capture) testing", 6)).toEqual([
|
||||
"capture",
|
||||
6,
|
||||
13,
|
||||
]);
|
||||
});
|
||||
test("text and colon", () => {
|
||||
expect(getTriggerText("(capture:) testing", 1)).toEqual(["capture:", 1, 9])
|
||||
})
|
||||
expect(getTriggerText("(capture:) testing", 1)).toEqual([
|
||||
"capture:",
|
||||
1,
|
||||
9,
|
||||
]);
|
||||
});
|
||||
test("text and double colon", () => {
|
||||
expect(getTriggerText("(capture::) testing", 1)).toEqual(["capture::", 1, 10])
|
||||
})
|
||||
expect(getTriggerText("(capture::) testing", 1)).toEqual([
|
||||
"capture::",
|
||||
1,
|
||||
10,
|
||||
]);
|
||||
});
|
||||
test("metadata field", () => {
|
||||
expect(getTriggerText("(capture::Bob) testing", 1)).toEqual(["capture::Bob", 1, 13])
|
||||
})
|
||||
expect(getTriggerText("(capture::Bob) testing", 1)).toEqual([
|
||||
"capture::Bob",
|
||||
1,
|
||||
13,
|
||||
]);
|
||||
});
|
||||
test("metadata field with whitespace", () => {
|
||||
expect(getTriggerText("(capture:: Bob) testing", 1)).toEqual(["capture:: Bob", 1, 14])
|
||||
})
|
||||
expect(getTriggerText("(capture:: Bob) testing", 1)).toEqual([
|
||||
"capture:: Bob",
|
||||
1,
|
||||
14,
|
||||
]);
|
||||
});
|
||||
test("metadata field with more white space", () => {
|
||||
expect(getTriggerText("(capture:: Bob) testing", 1)).toEqual(["capture:: Bob", 1, 16])
|
||||
})
|
||||
expect(getTriggerText("(capture:: Bob) testing", 1)).toEqual([
|
||||
"capture:: Bob",
|
||||
1,
|
||||
16,
|
||||
]);
|
||||
});
|
||||
test("text with markdown link", () => {
|
||||
expect(getTriggerText("([[test]]) testing", 1)).toEqual(["[[test]]", 1, 9])
|
||||
})
|
||||
expect(getTriggerText("([[test]]) testing", 1)).toEqual([
|
||||
"[[test]]",
|
||||
1,
|
||||
9,
|
||||
]);
|
||||
});
|
||||
test("text with aliased markdown link", () => {
|
||||
expect(getTriggerText("([[test|display]]) testing", 1)).toEqual(["[[test|display]]", 1, 17])
|
||||
})
|
||||
expect(getTriggerText("([[test|display]]) testing", 1)).toEqual([
|
||||
"[[test|display]]",
|
||||
1,
|
||||
17,
|
||||
]);
|
||||
});
|
||||
test("text with wiki link", () => {
|
||||
expect(getTriggerText("([[test](https://example.com)]) testing", 1)).toEqual(["[[test](https://example.com)]", 1, 30])
|
||||
})
|
||||
expect(
|
||||
getTriggerText("([[test](https://example.com)]) testing", 1),
|
||||
).toEqual(["[[test](https://example.com)]", 1, 30]);
|
||||
});
|
||||
test("text with wiki link local", () => {
|
||||
expect(getTriggerText("([[test](test)]) testing", 1)).toEqual(["[[test](test)]", 1, 15])
|
||||
})
|
||||
})
|
||||
expect(getTriggerText("([[test](test)]) testing", 1)).toEqual([
|
||||
"[[test](test)]",
|
||||
1,
|
||||
15,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("text in square brackets", () => {
|
||||
test("text behind", () => {
|
||||
expect(getTriggerText("[capture] testing", 1)).toEqual(["capture", 1, 8])
|
||||
})
|
||||
expect(getTriggerText("[capture] testing", 1)).toEqual([
|
||||
"capture",
|
||||
1,
|
||||
8,
|
||||
]);
|
||||
});
|
||||
test("text before", () => {
|
||||
expect(getTriggerText("testing [capture]", 12)).toEqual(["capture", 9, 16])
|
||||
})
|
||||
expect(getTriggerText("testing [capture]", 12)).toEqual([
|
||||
"capture",
|
||||
9,
|
||||
16,
|
||||
]);
|
||||
});
|
||||
test("text behind no whitespace", () => {
|
||||
expect(getTriggerText("[capture]testing", 1)).toEqual(["capture", 1, 8])
|
||||
})
|
||||
expect(getTriggerText("[capture]testing", 1)).toEqual([
|
||||
"capture",
|
||||
1,
|
||||
8,
|
||||
]);
|
||||
});
|
||||
test("text before no whitespace", () => {
|
||||
expect(getTriggerText("test[capture]", 5)).toEqual(["capture", 5, 12])
|
||||
})
|
||||
expect(getTriggerText("test[capture]", 5)).toEqual([
|
||||
"capture",
|
||||
5,
|
||||
12,
|
||||
]);
|
||||
});
|
||||
test("text before and behind", () => {
|
||||
expect(getTriggerText("test [capture] testing", 6)).toEqual(["capture", 6, 13])
|
||||
})
|
||||
expect(getTriggerText("test [capture] testing", 6)).toEqual([
|
||||
"capture",
|
||||
6,
|
||||
13,
|
||||
]);
|
||||
});
|
||||
test("text and colon", () => {
|
||||
expect(getTriggerText("[capture:] testing", 1)).toEqual(["capture:", 1, 9])
|
||||
})
|
||||
expect(getTriggerText("[capture:] testing", 1)).toEqual([
|
||||
"capture:",
|
||||
1,
|
||||
9,
|
||||
]);
|
||||
});
|
||||
test("text and double colon", () => {
|
||||
expect(getTriggerText("[capture::] testing", 1)).toEqual(["capture::", 1, 10])
|
||||
})
|
||||
expect(getTriggerText("[capture::] testing", 1)).toEqual([
|
||||
"capture::",
|
||||
1,
|
||||
10,
|
||||
]);
|
||||
});
|
||||
test("metadata field", () => {
|
||||
expect(getTriggerText("[capture::Bob] testing", 1)).toEqual(["capture::Bob", 1, 13])
|
||||
})
|
||||
expect(getTriggerText("[capture::Bob] testing", 1)).toEqual([
|
||||
"capture::Bob",
|
||||
1,
|
||||
13,
|
||||
]);
|
||||
});
|
||||
test("metadata field with whitespace", () => {
|
||||
expect(getTriggerText("[capture:: Bob] testing", 1)).toEqual(["capture:: Bob", 1, 14])
|
||||
})
|
||||
expect(getTriggerText("[capture:: Bob] testing", 1)).toEqual([
|
||||
"capture:: Bob",
|
||||
1,
|
||||
14,
|
||||
]);
|
||||
});
|
||||
test("metadata field with more white space", () => {
|
||||
expect(getTriggerText("[capture:: Bob] testing", 1)).toEqual(["capture:: Bob", 1, 16])
|
||||
})
|
||||
expect(getTriggerText("[capture:: Bob] testing", 1)).toEqual([
|
||||
"capture:: Bob",
|
||||
1,
|
||||
16,
|
||||
]);
|
||||
});
|
||||
test("text with markdown link", () => {
|
||||
expect(getTriggerText("[[[test]]] testing", 1)).toEqual(["[[test]]", 1, 9])
|
||||
})
|
||||
expect(getTriggerText("[[[test]]] testing", 1)).toEqual([
|
||||
"[[test]]",
|
||||
1,
|
||||
9,
|
||||
]);
|
||||
});
|
||||
test("text with aliased markdown link", () => {
|
||||
expect(getTriggerText("[[[test|display]]] testing", 1)).toEqual(["[[test|display]]", 1, 17])
|
||||
})
|
||||
expect(getTriggerText("[[[test|display]]] testing", 1)).toEqual([
|
||||
"[[test|display]]",
|
||||
1,
|
||||
17,
|
||||
]);
|
||||
});
|
||||
test("text with wiki link", () => {
|
||||
expect(getTriggerText("[[[test](https://example.com)]] testing", 1)).toEqual(["[[test](https://example.com)]", 1, 30])
|
||||
})
|
||||
expect(
|
||||
getTriggerText("[[[test](https://example.com)]] testing", 1),
|
||||
).toEqual(["[[test](https://example.com)]", 1, 30]);
|
||||
});
|
||||
test("text with wiki link local", () => {
|
||||
expect(getTriggerText("[[[test](test)]] testing", 1)).toEqual(["[[test](test)]", 1, 15])
|
||||
})
|
||||
})
|
||||
expect(getTriggerText("[[[test](test)]] testing", 1)).toEqual([
|
||||
"[[test](test)]",
|
||||
1,
|
||||
15,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("cursor position", () => {
|
||||
test("cursor in first field", () => {
|
||||
expect(getTriggerText("test (test) string (test2) testing", 9)).toEqual(["test", 6, 10])
|
||||
})
|
||||
expect(
|
||||
getTriggerText("test (test) string (test2) testing", 9),
|
||||
).toEqual(["test", 6, 10]);
|
||||
});
|
||||
test("cursor in second field", () => {
|
||||
expect(getTriggerText("test (test) string (test2) testing", 21)).toEqual(["test2", 20, 25])
|
||||
})
|
||||
expect(
|
||||
getTriggerText("test (test) string (test2) testing", 21),
|
||||
).toEqual(["test2", 20, 25]);
|
||||
});
|
||||
test("ignore cursor out of field", () => {
|
||||
expect(getTriggerText("test (test) string (test2) testing", 2)).toEqual(null)
|
||||
})
|
||||
})
|
||||
expect(
|
||||
getTriggerText("test (test) string (test2) testing", 2),
|
||||
).toEqual(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe("ignore plain markdown links", () => {
|
||||
test("cursor in link text", () => {
|
||||
expect(getTriggerText("test [test](https://example.com)", 8)).toEqual(null)
|
||||
})
|
||||
expect(
|
||||
getTriggerText("test [test](https://example.com)", 8),
|
||||
).toEqual(null);
|
||||
});
|
||||
test("cursor in link url", () => {
|
||||
expect(getTriggerText("test [test](https://example.com)", 15)).toEqual(null)
|
||||
})
|
||||
expect(
|
||||
getTriggerText("test [test](https://example.com)", 15),
|
||||
).toEqual(null);
|
||||
});
|
||||
test("cursor in empty link text", () => {
|
||||
expect(getTriggerText("test [](https://example.com)", 6)).toEqual(null)
|
||||
})
|
||||
expect(getTriggerText("test [](https://example.com)", 6)).toEqual(
|
||||
null,
|
||||
);
|
||||
});
|
||||
test("cursor in empty link url", () => {
|
||||
expect(getTriggerText("test [test]()", 12)).toEqual(null)
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
expect(getTriggerText("test [test]()", 12)).toEqual(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/**
|
||||
* Matches single square bracket pair [] or parahtheses (), but not a double square bracket pair [[]]
|
||||
* (?<!\[) # Negative lookbehind to make sure there is no second [
|
||||
* \[] # Matches []
|
||||
* \[] # Matches []
|
||||
* (?![\]\(]) # Negative lookahead to make sure there is no second closing ] from wiki link or opening ( from a markdown link
|
||||
* | # OR
|
||||
* (?<!\]) # Negative lookbehind to make sure there is no closing ] from a markdown link
|
||||
* \(\) # Matches ()
|
||||
*/
|
||||
const emptyRegex = /(?<!\[)\[](?![\]\(])|(?<!\])\(\)/g
|
||||
const emptyRegex = /(?<!\[)\[](?![\]\(])|(?<!\])\(\)/g;
|
||||
|
||||
/**
|
||||
* Maches single square brackets or parantheses with some text in them
|
||||
* and captures the text
|
||||
* If the brackets start a wiki link or markdown link, they are ignored
|
||||
* but links inside another layer of brackets are returned:
|
||||
*
|
||||
*
|
||||
* (
|
||||
* (?<=^\(|\s\() # Pattern for parantheses
|
||||
* .+?:{0,2}.*?
|
||||
@@ -25,7 +25,8 @@ const emptyRegex = /(?<!\[)\[](?![\]\(])|(?<!\])\(\)/g
|
||||
* (?=\]$|\]\s)
|
||||
* )
|
||||
*/
|
||||
const filledRegex = /((?<=^\(|\s\().+?:{0,2}.*?(?=\)$|\)\s)|(?<=^\[|\s\[).+?:{0,2}.*?(?=\]$|\]\s))/g
|
||||
const filledRegex =
|
||||
/((?<=^\(|\s\().+?:{0,2}.*?(?=\)$|\)\s)|(?<=^\[|\s\[).+?:{0,2}.*?(?=\]$|\]\s))/g;
|
||||
|
||||
/**
|
||||
* Finds the dataview metadata field the user is currently inside.
|
||||
@@ -33,38 +34,44 @@ const filledRegex = /((?<=^\(|\s\().+?:{0,2}.*?(?=\)$|\)\s)|(?<=^\[|\s\[).+?:{0,
|
||||
* and start and end are the cursor positions of the start and end of the field.
|
||||
* If the user is not inside a field, it returns null.
|
||||
*/
|
||||
export function getTriggerText(line: string, cursorPos: number): [string, number, number] | null {
|
||||
export function getTriggerText(
|
||||
line: string,
|
||||
cursorPos: number,
|
||||
): [string, number, number] | null {
|
||||
// Check for empty [] or ().
|
||||
// If the user starts typing with no text in the field, this is the fastest way to find it.
|
||||
let match = getEmptyTrigger(line, cursorPos)
|
||||
let match = getEmptyTrigger(line, cursorPos);
|
||||
if (match) {
|
||||
return match
|
||||
return match;
|
||||
}
|
||||
|
||||
// If the user types inside an existing field, this is the function to find it.
|
||||
match = getTriggerTextFromRegex(line, cursorPos, filledRegex)
|
||||
match = getTriggerTextFromRegex(line, cursorPos, filledRegex);
|
||||
if (match !== null) {
|
||||
return match
|
||||
return match;
|
||||
}
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches an empty [] or empty (), but not [[]]
|
||||
* Has its own function since there is no capture group resulting in a different index calculation
|
||||
*/
|
||||
function getEmptyTrigger(line: string, cursorPos: number): [string, number, number] | null {
|
||||
let matches = Array.from(line.matchAll(emptyRegex))
|
||||
function getEmptyTrigger(
|
||||
line: string,
|
||||
cursorPos: number,
|
||||
): [string, number, number] | null {
|
||||
let matches = Array.from(line.matchAll(emptyRegex));
|
||||
for (const match of matches) {
|
||||
if (match.index === undefined) {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cursorPos === match.index+1) {
|
||||
return ["", match.index+1, match.index+1]
|
||||
if (cursorPos === match.index + 1) {
|
||||
return ["", match.index + 1, match.index + 1];
|
||||
}
|
||||
}
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,20 +81,24 @@ function getEmptyTrigger(line: string, cursorPos: number): [string, number, numb
|
||||
* start is the position of the start of the match, and end is the position of the end of the match.
|
||||
* Otherwise, returns null.
|
||||
*/
|
||||
function getTriggerTextFromRegex(line: string, cursorPos: number, regex: RegExp): [string, number, number] | null {
|
||||
let matches = Array.from(line.matchAll(regex))
|
||||
function getTriggerTextFromRegex(
|
||||
line: string,
|
||||
cursorPos: number,
|
||||
regex: RegExp,
|
||||
): [string, number, number] | null {
|
||||
let matches = Array.from(line.matchAll(regex));
|
||||
for (const match of matches) {
|
||||
if (match.index === undefined) {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
|
||||
const matchStart = match!.index
|
||||
const matchEnd = matchStart + match[1].length
|
||||
const cursorInMatch = cursorPos >= matchStart && cursorPos <= matchEnd
|
||||
const matchStart = match!.index;
|
||||
const matchEnd = matchStart + match[1].length;
|
||||
const cursorInMatch = cursorPos >= matchStart && cursorPos <= matchEnd;
|
||||
|
||||
if (cursorInMatch) {
|
||||
return [match[1], matchStart, matchEnd]
|
||||
return [match[1], matchStart, matchEnd];
|
||||
}
|
||||
}
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
4
test-vault/.obsidian/community-plugins.json
vendored
4
test-vault/.obsidian/community-plugins.json
vendored
@@ -1,4 +0,0 @@
|
||||
[
|
||||
"dataview",
|
||||
"sample-plugin"
|
||||
]
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"id": "sample-plugin",
|
||||
"name": "Sample Plugin",
|
||||
"version": "1.0.0",
|
||||
"minAppVersion": "0.15.0",
|
||||
"description": "Demonstrates some of the capabilities of the Obsidian API.",
|
||||
"author": "Obsidian",
|
||||
"authorUrl": "https://obsidian.md",
|
||||
"fundingUrl": "https://obsidian.md/pricing",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
/*
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"id": "dataview",
|
||||
"name": "Dataview",
|
||||
"version": "0.5.67",
|
||||
"minAppVersion": "0.13.11",
|
||||
"description": "Complex data views for the data-obsessed.",
|
||||
"author": "Michael Brenan <blacksmithgu@gmail.com>",
|
||||
"authorUrl": "https://github.com/blacksmithgu",
|
||||
"helpUrl": "https://blacksmithgu.github.io/obsidian-dataview/",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
146
test-vault/.obsidian/plugins/dataview/styles.css
vendored
146
test-vault/.obsidian/plugins/dataview/styles.css
vendored
@@ -1,146 +0,0 @@
|
||||
/** Live Preview padding fixes, specifically for DataviewJS custom HTML elements. */
|
||||
.is-live-preview .block-language-dataviewjs > p, .is-live-preview .block-language-dataviewjs > span {
|
||||
line-height: 1.0;
|
||||
}
|
||||
|
||||
.block-language-dataview {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/*****************/
|
||||
/** Table Views **/
|
||||
/*****************/
|
||||
|
||||
/* List View Default Styling; rendered internally as a table. */
|
||||
.table-view-table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.table-view-table > thead > tr, .table-view-table > tbody > tr {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.table-view-table > tbody > tr:hover {
|
||||
background-color: var(--table-row-background-hover);
|
||||
}
|
||||
|
||||
.table-view-table > thead > tr > th {
|
||||
font-weight: 700;
|
||||
font-size: larger;
|
||||
border-top: none;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
border-bottom: solid;
|
||||
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.table-view-table > tbody > tr > td {
|
||||
text-align: left;
|
||||
border: none;
|
||||
font-weight: 400;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.table-view-table ul, .table-view-table ol {
|
||||
margin-block-start: 0.2em !important;
|
||||
margin-block-end: 0.2em !important;
|
||||
}
|
||||
|
||||
/** Rendered value styling for any view. */
|
||||
.dataview-result-list-root-ul {
|
||||
padding: 0em !important;
|
||||
margin: 0em !important;
|
||||
}
|
||||
|
||||
.dataview-result-list-ul {
|
||||
margin-block-start: 0.2em !important;
|
||||
margin-block-end: 0.2em !important;
|
||||
}
|
||||
|
||||
/** Generic grouping styling. */
|
||||
.dataview.result-group {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
/*******************/
|
||||
/** Inline Fields **/
|
||||
/*******************/
|
||||
|
||||
.dataview.inline-field-key {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
font-family: var(--font-monospace);
|
||||
background-color: var(--background-primary-alt);
|
||||
color: var(--text-nav-selected);
|
||||
}
|
||||
|
||||
.dataview.inline-field-value {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
font-family: var(--font-monospace);
|
||||
background-color: var(--background-secondary-alt);
|
||||
color: var(--text-nav-selected);
|
||||
}
|
||||
|
||||
.dataview.inline-field-standalone-value {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
font-family: var(--font-monospace);
|
||||
background-color: var(--background-secondary-alt);
|
||||
color: var(--text-nav-selected);
|
||||
}
|
||||
|
||||
/***************/
|
||||
/** Task View **/
|
||||
/***************/
|
||||
|
||||
.dataview.task-list-item, .dataview.task-list-basic-item {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
transition: 0.4s;
|
||||
}
|
||||
|
||||
.dataview.task-list-item:hover, .dataview.task-list-basic-item:hover {
|
||||
background-color: var(--text-selection);
|
||||
box-shadow: -40px 0 0 var(--text-selection);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/*****************/
|
||||
/** Error Views **/
|
||||
/*****************/
|
||||
|
||||
div.dataview-error-box {
|
||||
width: 100%;
|
||||
min-height: 150px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 4px dashed var(--background-secondary);
|
||||
}
|
||||
|
||||
.dataview-error-message {
|
||||
color: var(--text-muted);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/*************************/
|
||||
/** Additional Metadata **/
|
||||
/*************************/
|
||||
|
||||
.dataview.small-text {
|
||||
font-size: smaller;
|
||||
color: var(--text-muted);
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.dataview.small-text::before {
|
||||
content: "(";
|
||||
}
|
||||
|
||||
.dataview.small-text::after {
|
||||
content: ")";
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
(test:: test)
|
||||
(test::test)
|
||||
(test:: test)
|
||||
(test:: test)
|
||||
(test::)
|
||||
[test:: test]
|
||||
[test:: test]
|
||||
[test:: test]
|
||||
[test:: [[Moods]]]
|
||||
[test:: [[Moods|Wiki link display]]]
|
||||
[test:: [example link](https://example.com)]
|
||||
[test::Text with [[Moods|wiki link]] and more text]
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"sourceMap": true,
|
||||
"inlineSourceMap": false,
|
||||
"sourceMap": true,
|
||||
"inlineSourceMap": false,
|
||||
"inlineSources": true,
|
||||
"module": "ESNext",
|
||||
"target": "ES6",
|
||||
@@ -12,15 +12,7 @@
|
||||
"importHelpers": true,
|
||||
"isolatedModules": true,
|
||||
"strictNullChecks": true,
|
||||
"lib": [
|
||||
"DOM",
|
||||
"ES5",
|
||||
"ES6",
|
||||
"ES7",
|
||||
"es2020.string"
|
||||
]
|
||||
"lib": ["DOM", "ES5", "ES6", "ES7", "es2020.string"]
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
]
|
||||
"include": ["**/*.ts"]
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"1.0.0": "0.15.0"
|
||||
"1.0.0": "0.15.0"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user