mirror of
https://github.com/nick-de-bruin/obsidian-extended-file-support.git
synced 2026-07-22 05:37:54 +00:00
Added .kra support
This commit is contained in:
parent
ca1343e517
commit
135fffa98b
13 changed files with 3386 additions and 192 deletions
34
.github/workflows/release.yml
vendored
Normal file
34
.github/workflows/release.yml
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
name: Release Obsidian plugin
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "18.x"
|
||||
|
||||
- name: Build plugin
|
||||
run: |
|
||||
npm install
|
||||
npm run build
|
||||
|
||||
- name: Create release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
tag="${GITHUB_REF#refs/tags/}"
|
||||
|
||||
gh release create "$tag" \
|
||||
--title="$tag" \
|
||||
--draft \
|
||||
main.js manifest.json styles.css
|
||||
21
LICENSE.txt
Normal file
21
LICENSE.txt
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2025 Nick de Bruin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
100
README.md
100
README.md
|
|
@ -1,94 +1,20 @@
|
|||
# Obsidian Sample Plugin
|
||||
# Extended File Support for Obsidian
|
||||
|
||||
This is a sample plugin for Obsidian (https://obsidian.md).
|
||||
This plugin aims to add viewing and embedding support for various file types in Obsidian.
|
||||
It does *not* aim to allow these files to be edited.
|
||||
This is considered to be outside of the scope of this plugin.
|
||||
|
||||
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.
|
||||
File types can be toggled in the settings.
|
||||
|
||||
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.
|
||||
- Registers a global click event and output 'click' to the console.
|
||||
- Registers a global interval which logs 'setInterval' to the console.
|
||||
# Currently Supported
|
||||
|
||||
## First time developing plugins?
|
||||
The file types that are currently supported are:
|
||||
|
||||
Quick starting guide for new plugin devs:
|
||||
- `.kra` (Files made in Krita)
|
||||
-
|
||||
|
||||
- Check if [someone already developed a plugin for what you want](https://obsidian.md/plugins)! There might be an existing plugin similar enough that you can partner up with.
|
||||
- Make a copy of this repo as a template with the "Use this template" button (login to GitHub if you don't see it).
|
||||
- Clone your repo to a local development folder. For convenience, you can place this folder in your `.obsidian/plugins/your-plugin-name` folder.
|
||||
- Install NodeJS, then run `npm i` in the command line under your repo folder.
|
||||
- Run `npm run dev` to compile your plugin from `main.ts` to `main.js`.
|
||||
- Make changes to `main.ts` (or create new `.ts` files). Those changes should be automatically compiled into `main.js`.
|
||||
- Reload Obsidian to load the new version of your plugin.
|
||||
- Enable plugin in settings window.
|
||||
- For updates to the Obsidian API run `npm update` in the command line under your repo folder.
|
||||
## Contributing
|
||||
|
||||
## Releasing new releases
|
||||
|
||||
- Update your `manifest.json` with your new version number, such as `1.0.1`, and the minimum Obsidian version required for your latest release.
|
||||
- Update your `versions.json` file with `"new-plugin-version": "minimum-obsidian-version"` so older versions of Obsidian can download an older version of your plugin that's compatible.
|
||||
- Create new GitHub release using your new version number as the "Tag version". Use the exact version number, don't include a prefix `v`. See here for an example: https://github.com/obsidianmd/obsidian-sample-plugin/releases
|
||||
- Upload the files `manifest.json`, `main.js`, `styles.css` as binary attachments. Note: The manifest.json file must be in two places, first the root path of your repository and also in the release.
|
||||
- Publish the release.
|
||||
|
||||
> You can simplify the version bump process by running `npm version patch`, `npm version minor` or `npm version major` after updating `minAppVersion` manually in `manifest.json`.
|
||||
> The command will bump version in `manifest.json` and `package.json`, and add the entry for the new version to `versions.json`
|
||||
|
||||
## Adding your plugin to the community plugin list
|
||||
|
||||
- Check the [plugin guidelines](https://docs.obsidian.md/Plugins/Releasing/Plugin+guidelines).
|
||||
- Publish an initial version.
|
||||
- Make sure you have a `README.md` file in the root of your repo.
|
||||
- Make a pull request at https://github.com/obsidianmd/obsidian-releases to add your plugin.
|
||||
|
||||
## How to use
|
||||
|
||||
- Clone this repo.
|
||||
- Make sure your NodeJS is at least v16 (`node --version`).
|
||||
- `npm i` or `yarn` to install dependencies.
|
||||
- `npm run dev` to start compilation in watch mode.
|
||||
|
||||
## Manually installing the plugin
|
||||
|
||||
- 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.
|
||||
- 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:
|
||||
- `eslint main.ts`
|
||||
- eslint will then create a report with suggestions for code improvement by file and line number.
|
||||
- If your source code is in a folder, such as `src`, you can use eslint with this command to analyze all files in that folder:
|
||||
- `eslint .\src\`
|
||||
|
||||
## Funding URL
|
||||
|
||||
You can include funding URLs where people who use your plugin can financially support it.
|
||||
|
||||
The simple way is to set the `fundingUrl` field to your link in your `manifest.json` file:
|
||||
|
||||
```json
|
||||
{
|
||||
"fundingUrl": "https://buymeacoffee.com"
|
||||
}
|
||||
```
|
||||
|
||||
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/"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API Documentation
|
||||
|
||||
See https://github.com/obsidianmd/obsidian-api
|
||||
If you wish to contribute to the plugin, feel free to open a pull-request or an issue.
|
||||
If you're thinking about implementing a large feature, please open an issue first or contact me on discord at `n_1ck`
|
||||
so we can figure out if it's a good fit for this plugin.
|
||||
|
|
|
|||
140
main.ts
140
main.ts
|
|
@ -1,85 +1,45 @@
|
|||
import { App, Editor, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian';
|
||||
import { App, Plugin, PluginSettingTab, Setting } from 'obsidian';
|
||||
import { EXTENSION_REGISTRY } from 'src/extensionsRegistry';
|
||||
import { DEFAULT_SETTINGS, ExtendedFileSupportSettings } from 'src/settings';
|
||||
import { EmbedRegistry } from 'obsidian-typings';
|
||||
|
||||
// Remember to rename these classes and interfaces!
|
||||
|
||||
interface MyPluginSettings {
|
||||
mySetting: string;
|
||||
}
|
||||
|
||||
const DEFAULT_SETTINGS: MyPluginSettings = {
|
||||
mySetting: 'default'
|
||||
}
|
||||
|
||||
export default class MyPlugin extends Plugin {
|
||||
settings: MyPluginSettings;
|
||||
export default class ExtendedFileSupport extends Plugin {
|
||||
settings: ExtendedFileSupportSettings;
|
||||
|
||||
async onload() {
|
||||
await this.loadSettings();
|
||||
this.addSettingTab(new ExtendedFileSupportSettingTab(this.app, this));
|
||||
|
||||
// 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');
|
||||
const embedRegistry = this.app.embedRegistry as EmbedRegistry;
|
||||
|
||||
// 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');
|
||||
for (const extension of EXTENSION_REGISTRY) {
|
||||
this.registerView(extension.view_type, (leaf) => new extension.view(leaf, this));
|
||||
|
||||
// This adds a simple command that can be triggered anywhere
|
||||
this.addCommand({
|
||||
id: 'open-sample-modal-simple',
|
||||
name: 'Open sample modal (simple)',
|
||||
callback: () => {
|
||||
new SampleModal(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) => {
|
||||
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 SampleModal(this.app).open();
|
||||
}
|
||||
for (const extension_type of extension.types) {
|
||||
// @ts-ignore
|
||||
if (this.settings[extension_type]) {
|
||||
this.registerExtensions([extension_type], extension.view_type);
|
||||
|
||||
// This command will only show up in Command Palette when the check function returns true
|
||||
return true;
|
||||
embedRegistry.registerExtension(extension_type, (context, file, _) => {
|
||||
return new extension.component(context.containerEl, this, file, context.linktext);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// This adds a settings tab so the user can configure various aspects of the plugin
|
||||
this.addSettingTab(new SampleSettingTab(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() {
|
||||
const embedRegistry = this.app.embedRegistry as EmbedRegistry;
|
||||
|
||||
for (const extension of EXTENSION_REGISTRY) {
|
||||
for (const extension_type of extension.types) {
|
||||
// @ts-ignore
|
||||
if (this.settings[extension.type]) {
|
||||
this.app.viewRegistry.unregisterExtensions([extension_type]);
|
||||
embedRegistry.unregisterExtension(extension_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async loadSettings() {
|
||||
|
|
@ -89,28 +49,30 @@ export default class MyPlugin extends Plugin {
|
|||
async saveSettings() {
|
||||
await this.saveData(this.settings);
|
||||
}
|
||||
}
|
||||
|
||||
class SampleModal extends Modal {
|
||||
constructor(app: App) {
|
||||
super(app);
|
||||
}
|
||||
public toggleExtension(extension: string, enable: boolean): void {
|
||||
const e = EXTENSION_REGISTRY.find(e => e.types.contains(extension));
|
||||
const embedRegistry = this.app.embedRegistry as EmbedRegistry;
|
||||
|
||||
onOpen() {
|
||||
const {contentEl} = this;
|
||||
contentEl.setText('Woah!');
|
||||
}
|
||||
if (!e) return;
|
||||
|
||||
onClose() {
|
||||
const {contentEl} = this;
|
||||
contentEl.empty();
|
||||
if (enable) {
|
||||
this.registerExtensions(e.types, e.view_type);
|
||||
|
||||
embedRegistry.registerExtension(extension, (context, file, _) => {
|
||||
return new e.component(context.containerEl, this, file, context.linktext);
|
||||
});
|
||||
} else {
|
||||
this.app.viewRegistry.unregisterExtensions([extension]);
|
||||
embedRegistry.unregisterExtension(extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SampleSettingTab extends PluginSettingTab {
|
||||
plugin: MyPlugin;
|
||||
class ExtendedFileSupportSettingTab extends PluginSettingTab {
|
||||
plugin: ExtendedFileSupport;
|
||||
|
||||
constructor(app: App, plugin: MyPlugin) {
|
||||
constructor(app: App, plugin: ExtendedFileSupport) {
|
||||
super(app, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
|
@ -121,14 +83,14 @@ class SampleSettingTab extends PluginSettingTab {
|
|||
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)
|
||||
.setName(".kra")
|
||||
.setDesc("Files generated by Krita")
|
||||
.addToggle(toggle => toggle
|
||||
.setValue(this.plugin.settings.kra)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.mySetting = value;
|
||||
this.plugin.settings.kra = value;
|
||||
await this.plugin.saveSettings();
|
||||
this.plugin.toggleExtension("kra", value);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
{
|
||||
"id": "sample-plugin",
|
||||
"name": "Sample Plugin",
|
||||
"id": "extended-file-support",
|
||||
"name": "Extended File Support",
|
||||
"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",
|
||||
"description": "Adds file support for various file types. Allows viewing and embedding these filetypes. Includes: .kra, .psd, .obj, .gltf",
|
||||
"author": "Nick de Bruin",
|
||||
"authorUrl": "https://nickdebruin.me/",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
|
|
|
|||
3105
package-lock.json
generated
Normal file
3105
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "obsidian-sample-plugin",
|
||||
"name": "extended-file-support",
|
||||
"version": "1.0.0",
|
||||
"description": "This is a sample plugin for Obsidian (https://obsidian.md)",
|
||||
"description": "Extended file support for Obsidian",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"dev": "node esbuild.config.mjs",
|
||||
|
|
@ -18,7 +18,11 @@
|
|||
"builtin-modules": "3.3.0",
|
||||
"esbuild": "0.17.3",
|
||||
"obsidian": "latest",
|
||||
"obsidian-typings": "^2.11.1",
|
||||
"tslib": "2.4.0",
|
||||
"typescript": "4.7.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@zip.js/zip.js": "^2.6.40"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
26
src/extensionComponent.ts
Normal file
26
src/extensionComponent.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import ExtendedFileSupport from "main";
|
||||
import { Component, TFile } from "obsidian";
|
||||
|
||||
export abstract class ExtensionComponent extends Component {
|
||||
protected plugin: ExtendedFileSupport;
|
||||
protected contentEl: HTMLElement;
|
||||
protected file: TFile;
|
||||
protected linkText?: string;
|
||||
|
||||
public constructor(contentEl: HTMLElement, plugin: ExtendedFileSupport, file: TFile, linkText?: string) {
|
||||
super();
|
||||
this.contentEl = contentEl;
|
||||
this.plugin = plugin;
|
||||
this.file = file;
|
||||
this.linkText = linkText;
|
||||
}
|
||||
|
||||
abstract loadFile(): void;
|
||||
|
||||
onload() {
|
||||
this.contentEl.addClass("extended-file-loading");
|
||||
this.contentEl.createEl("i", { text: `Loading ${this.file?.name}...`});
|
||||
}
|
||||
|
||||
abstract onunload(): void;
|
||||
}
|
||||
36
src/extensionView.ts
Normal file
36
src/extensionView.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import ExtendedFileSupport from "main";
|
||||
import { FileView, TFile, WorkspaceLeaf } from "obsidian";
|
||||
import { ExtensionComponent } from "./extensionComponent";
|
||||
|
||||
export abstract class ExtensionView<T extends ExtensionComponent> extends FileView {
|
||||
private plugin: ExtendedFileSupport;
|
||||
private component: ExtensionComponent;
|
||||
|
||||
public constructor(leaf: WorkspaceLeaf, plugin: ExtendedFileSupport) {
|
||||
super(leaf);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public getDisplayText(): string {
|
||||
return this.file ? this.file.basename : "Loading...";
|
||||
}
|
||||
|
||||
// Enforce setting an icon for files
|
||||
abstract getIcon(): string;
|
||||
abstract getComponent(): new (...args: ConstructorParameters<typeof ExtensionComponent>) => T;
|
||||
|
||||
async onLoadFile(file: TFile) {
|
||||
const ComponentClass = this.getComponent();
|
||||
this.component = new ComponentClass(this.contentEl, this.plugin, file);
|
||||
this.component.loadFile();
|
||||
}
|
||||
|
||||
async onClose() {
|
||||
this.component.onunload();
|
||||
}
|
||||
|
||||
public async onOpen() {
|
||||
this.contentEl.addClass("image-container");
|
||||
this.contentEl.createEl("h1", { text: "Loading..." });
|
||||
}
|
||||
}
|
||||
61
src/extensions/kra.ts
Normal file
61
src/extensions/kra.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import { BlobReader, BlobWriter, ZipReader } from "@zip.js/zip.js";
|
||||
import { ExtensionComponent } from "src/extensionComponent";
|
||||
import { ExtensionView } from "src/extensionView";
|
||||
|
||||
export const VIEW_TYPE_KRA = "extended-file-support-kra";
|
||||
|
||||
export class KRAComponent extends ExtensionComponent {
|
||||
private objectURL?: string;
|
||||
|
||||
async loadFile(): Promise<void> {
|
||||
const MERGED_PATH = "mergedimage.png";
|
||||
|
||||
const KRA_resource = this.plugin.app.vault.getResourcePath(this.file);
|
||||
const response = await fetch(KRA_resource);
|
||||
const KRA_blob = await response.blob();
|
||||
|
||||
// Get the image from the zip
|
||||
const reader = new ZipReader(new BlobReader(KRA_blob));
|
||||
const entries = await reader.getEntries();
|
||||
const target_entry = entries.find(entry => entry.filename === MERGED_PATH);
|
||||
|
||||
if (target_entry && target_entry.getData) {
|
||||
const image_file = await target_entry.getData(new BlobWriter());
|
||||
this.objectURL = URL.createObjectURL(image_file);
|
||||
}
|
||||
|
||||
if (this.objectURL) {
|
||||
const image = new Image();
|
||||
image.src = this.objectURL;
|
||||
image.alt = this.file.name;
|
||||
|
||||
this.contentEl.empty();
|
||||
this.contentEl.removeClass("extended-file-loading");
|
||||
this.contentEl.addClasses(["media-embed", "image-embed"]);
|
||||
this.contentEl.append(image);
|
||||
} else {
|
||||
this.contentEl.empty();
|
||||
this.contentEl.createEl("i", { text: `Could not load ${this.file.path}` });
|
||||
}
|
||||
}
|
||||
onunload(): void {
|
||||
if (this.objectURL) {
|
||||
URL.revokeObjectURL(this.objectURL);
|
||||
this.objectURL = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class KRAView extends ExtensionView<KRAComponent> {
|
||||
getIcon(): string {
|
||||
return "image";
|
||||
}
|
||||
|
||||
getComponent(): new (...args: ConstructorParameters<typeof ExtensionComponent>) => KRAComponent {
|
||||
return KRAComponent;
|
||||
}
|
||||
|
||||
getViewType(): string {
|
||||
return VIEW_TYPE_KRA;
|
||||
}
|
||||
}
|
||||
15
src/extensionsRegistry.ts
Normal file
15
src/extensionsRegistry.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import { KRAComponent, KRAView, VIEW_TYPE_KRA } from "./extensions/kra"
|
||||
import { ExtensionView } from "./extensionView"
|
||||
import { ExtensionComponent } from "./extensionComponent"
|
||||
|
||||
export type Extension = {
|
||||
types: string[],
|
||||
view_type: string,
|
||||
view: new (...args: ConstructorParameters<typeof ExtensionView>) => ExtensionView<ExtensionComponent>,
|
||||
component: new (...args: ConstructorParameters<typeof ExtensionComponent>) => ExtensionComponent,
|
||||
}
|
||||
|
||||
// Type should match settings field
|
||||
export const EXTENSION_REGISTRY: Extension[] = [
|
||||
{ types: ["kra"], view_type: VIEW_TYPE_KRA, view: KRAView, component: KRAComponent }
|
||||
]
|
||||
7
src/settings.ts
Normal file
7
src/settings.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
export interface ExtendedFileSupportSettings {
|
||||
kra: boolean;
|
||||
}
|
||||
|
||||
export const DEFAULT_SETTINGS: ExtendedFileSupportSettings = {
|
||||
kra: true,
|
||||
}
|
||||
14
styles.css
14
styles.css
|
|
@ -1,8 +1,6 @@
|
|||
/*
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
.extended-file-loading {
|
||||
background-color: var(--background-secondary);
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue