Skip to content

Commit 7179ba1

Browse files
committed
api part 2
1 parent 8c209ae commit 7179ba1

14 files changed

+218
-131
lines changed

exampleVault/Meta Bind JS.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
select: a
3+
---
4+
5+
test
6+
```meta-bind-js
7+
const declaration = mb.createDeclaration(
8+
'select',
9+
[
10+
{type: 'option', value: 'a'},
11+
{type: 'option', value: 'c'},
12+
],
13+
'select'
14+
);
15+
16+
const inputField = mb.createInputField(declaration, undefined, 'block');
17+
18+
ctx.addChild(inputField);
19+
```
20+
test

src/API.ts

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { App, TFile } from 'obsidian';
1+
import { App } from 'obsidian';
22
import MetaBindPlugin from './main';
33
import { InlineAPI } from './InlineAPI';
4-
import { InputFieldMarkdownRenderChild, InputFieldMarkdownRenderChildType } from './InputFieldMarkdownRenderChild';
4+
import { InputFieldMarkdownRenderChild, RenderChildType } from './InputFieldMarkdownRenderChild';
55
import { InputFieldArgumentType, InputFieldDeclaration, InputFieldDeclarationParser, InputFieldType } from './parsers/InputFieldDeclarationParser';
66
import { MetaBindBindTargetError, MetaBindParsingError } from './utils/MetaBindErrors';
77
import { isTruthy } from './utils/Utils';
@@ -18,51 +18,50 @@ export class API {
1818
this.parser = new InputFieldDeclarationParser();
1919
}
2020

21-
public createInlineAPI(file: TFile, container?: HTMLElement): InlineAPI {
22-
return new InlineAPI(this, file, container);
21+
public createInlineAPI(filePath: string, container?: HTMLElement): InlineAPI {
22+
return new InlineAPI(this, filePath, container);
2323
}
2424

2525
public createInputField(
2626
declaration: InputFieldDeclaration,
2727
templateName: string | undefined,
28-
renderType: InputFieldMarkdownRenderChildType,
28+
renderChildType: RenderChildType,
2929
filePath: string,
3030
container: HTMLElement
3131
): InputFieldMarkdownRenderChild {
32+
if (!Object.values(RenderChildType).contains(renderChildType)) {
33+
throw new MetaBindParsingError(`unknown render child type '${renderChildType}'`);
34+
}
3235
declaration = this.parser.parseDeclaration(declaration, undefined, templateName);
33-
return new InputFieldMarkdownRenderChild(container, renderType, declaration, this.plugin, filePath, crypto.randomUUID());
36+
return new InputFieldMarkdownRenderChild(container, renderChildType, declaration, this.plugin, filePath, crypto.randomUUID());
3437
}
3538

36-
public createInputFieldFromString(
37-
fullDeclaration: string,
38-
renderType: InputFieldMarkdownRenderChildType,
39-
filePath: string,
40-
container: HTMLElement
41-
): InputFieldMarkdownRenderChild {
39+
public createInputFieldFromString(fullDeclaration: string, renderType: RenderChildType, filePath: string, container: HTMLElement): InputFieldMarkdownRenderChild {
4240
const declaration: InputFieldDeclaration = this.parser.parseString(fullDeclaration);
4341
return new InputFieldMarkdownRenderChild(container, renderType, declaration, this.plugin, filePath, crypto.randomUUID());
4442
}
4543

4644
public createDeclaration(
4745
inputFieldType: InputFieldType,
48-
inputFieldArguments?: Record<InputFieldArgumentType, string>,
49-
bindTargetFile?: string,
50-
bindTargetField?: string
46+
inputFieldArguments?: { type: InputFieldArgumentType; value: string }[],
47+
bindTargetField?: string,
48+
bindTargetFile?: string
5149
): InputFieldDeclaration {
5250
if (bindTargetFile && !bindTargetField) {
5351
throw new MetaBindBindTargetError('if a bind target file is specified, a bind target field must also be specified');
5452
}
5553

5654
if (this.parser.getInputFieldType(inputFieldType) === InputFieldType.INVALID) {
57-
throw new MetaBindParsingError(`input field type ${inputFieldType} is invalid`);
55+
throw new MetaBindParsingError(`input field type '${inputFieldType}' is invalid`);
5856
}
5957

6058
return {
6159
declaration: undefined,
6260
fullDeclaration: undefined,
6361
inputFieldType: inputFieldType,
62+
argumentContainer: this.parser.parseArguments(inputFieldType, inputFieldArguments),
6463
isBound: isTruthy(bindTargetField),
65-
bindTarget: bindTargetFile + '#' + bindTargetField,
64+
bindTarget: bindTargetFile ? bindTargetFile + '#' + bindTargetField : bindTargetField,
6665
error: undefined,
6766
} as InputFieldDeclaration;
6867
}

src/InlineAPI.ts

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,54 @@
1-
import { TFile } from 'obsidian';
21
import { API } from './API';
32
import { InputFieldArgumentType, InputFieldDeclaration, InputFieldType } from './parsers/InputFieldDeclarationParser';
4-
import { InputFieldMarkdownRenderChild, InputFieldMarkdownRenderChildType } from './InputFieldMarkdownRenderChild';
3+
import { InputFieldMarkdownRenderChild, RenderChildType } from './InputFieldMarkdownRenderChild';
54

65
export class InlineAPI {
76
public api: API;
8-
public file: TFile;
7+
public filePath: string;
98
public container?: HTMLElement;
109

11-
constructor(api: API, file: TFile, container?: HTMLElement) {
10+
constructor(api: API, filePath: string, container?: HTMLElement) {
1211
this.api = api;
13-
this.file = file;
12+
this.filePath = filePath;
1413
this.container = container;
1514
}
1615

17-
public createInputField(declaration: InputFieldDeclaration, templateName: string | undefined, renderType: InputFieldMarkdownRenderChildType): InputFieldMarkdownRenderChild {
16+
public createInputField(declaration: InputFieldDeclaration, templateName: string | undefined, renderType: RenderChildType): InputFieldMarkdownRenderChild {
1817
if (!this.container) {
1918
throw new Error('inline API was instanced without a container, please use "createInputFieldInContainer"');
2019
}
2120

22-
return this.api.createInputField(declaration, templateName, renderType, this.file.path, this.container);
21+
return this.api.createInputField(declaration, templateName, renderType, this.filePath, this.container);
2322
}
2423

2524
public createInputFieldInContainer(
2625
declaration: InputFieldDeclaration,
2726
templateName: string | undefined,
28-
renderType: InputFieldMarkdownRenderChildType,
27+
renderChildType: RenderChildType,
2928
container: HTMLElement
3029
): InputFieldMarkdownRenderChild {
31-
return this.api.createInputField(declaration, templateName, renderType, this.file.path, container);
30+
return this.api.createInputField(declaration, templateName, renderChildType, this.filePath, container);
3231
}
3332

34-
public createInputFieldFromString(fullDeclaration: string, renderType: InputFieldMarkdownRenderChildType, filePath: string): InputFieldMarkdownRenderChild {
33+
public createInputFieldFromString(fullDeclaration: string, renderType: RenderChildType, filePath: string): InputFieldMarkdownRenderChild {
3534
if (!this.container) {
3635
throw new Error('inline API was instanced without a container, please use "createInputFieldFromStringInContainer"');
3736
}
3837

3938
return this.api.createInputFieldFromString(fullDeclaration, renderType, filePath, this.container);
4039
}
4140

42-
public createInputFieldFromStringInContainer(
43-
fullDeclaration: string,
44-
renderType: InputFieldMarkdownRenderChildType,
45-
filePath: string,
46-
container: HTMLElement
47-
): InputFieldMarkdownRenderChild {
41+
public createInputFieldFromStringInContainer(fullDeclaration: string, renderType: RenderChildType, filePath: string, container: HTMLElement): InputFieldMarkdownRenderChild {
4842
return this.api.createInputFieldFromString(fullDeclaration, renderType, filePath, container);
4943
}
5044

5145
public createDeclaration(
5246
inputFieldType: InputFieldType,
53-
inputFieldArguments?: Record<InputFieldArgumentType, string>,
54-
bindTargetFile?: string,
55-
bindTargetField?: string
47+
inputFieldArguments?: { type: InputFieldArgumentType; value: string }[],
48+
bindTargetField?: string,
49+
bindTargetFile?: string
5650
): InputFieldDeclaration {
57-
return this.api.createDeclaration(inputFieldType, inputFieldArguments, bindTargetFile, bindTargetField);
51+
return this.api.createDeclaration(inputFieldType, inputFieldArguments, bindTargetField, bindTargetFile);
5852
}
5953

6054
public createDeclarationFromString(fullDeclaration: string): InputFieldDeclaration {

src/InputFieldMarkdownRenderChild.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ import { ShowcaseInputFieldArgument } from './inputFieldArguments/ShowcaseInputF
1212
import { TitleInputFieldArgument } from './inputFieldArguments/TitleInputFieldArgument';
1313
import { isTruthy } from './utils/Utils';
1414

15-
export enum InputFieldMarkdownRenderChildType {
16-
INLINE_CODE_BLOCK,
17-
CODE_BLOCK,
15+
export enum RenderChildType {
16+
INLINE = 'inline',
17+
BLOCK = 'block',
1818
}
1919

2020
export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
@@ -24,7 +24,7 @@ export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
2424
uuid: string;
2525
inputField: AbstractInputField | undefined;
2626
error: string;
27-
type: InputFieldMarkdownRenderChildType;
27+
renderChildType: RenderChildType;
2828

2929
fullDeclaration?: string;
3030
inputFieldDeclaration: InputFieldDeclaration;
@@ -35,7 +35,7 @@ export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
3535
metadataValueUpdateQueue: any[];
3636
inputFieldValueUpdateQueue: any[];
3737

38-
constructor(containerEl: HTMLElement, type: InputFieldMarkdownRenderChildType, declaration: InputFieldDeclaration, plugin: MetaBindPlugin, filePath: string, uuid: string) {
38+
constructor(containerEl: HTMLElement, type: RenderChildType, declaration: InputFieldDeclaration, plugin: MetaBindPlugin, filePath: string, uuid: string) {
3939
super(containerEl);
4040

4141
if (!declaration.error) {
@@ -47,7 +47,7 @@ export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
4747
this.filePath = filePath;
4848
this.uuid = uuid;
4949
this.plugin = plugin;
50-
this.type = type;
50+
this.renderChildType = type;
5151
this.fullDeclaration = declaration.fullDeclaration;
5252

5353
this.metadataValueUpdateQueue = [];
@@ -171,7 +171,7 @@ export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
171171

172172
addCardContainer(): boolean {
173173
return (
174-
this.type === InputFieldMarkdownRenderChildType.CODE_BLOCK &&
174+
this.renderChildType === RenderChildType.BLOCK &&
175175
(isTruthy(this.getArgument(InputFieldArgumentType.SHOWCASE)) ||
176176
isTruthy(this.getArgument(InputFieldArgumentType.TITLE)) ||
177177
this.inputFieldDeclaration.inputFieldType === InputFieldType.SELECT ||

src/ScriptMarkdownRenderChild.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { MarkdownPostProcessorContext, MarkdownRenderChild } from 'obsidian';
2+
import MetaBindPlugin from './main';
3+
import { getAPI } from 'obsidian-dataview';
4+
import { MetaBindJsError } from './utils/MetaBindErrors';
5+
6+
export class ScriptMarkdownRenderChild extends MarkdownRenderChild {
7+
content: string;
8+
ctx: MarkdownPostProcessorContext;
9+
plugin: MetaBindPlugin;
10+
11+
constructor(containerEl: HTMLElement, content: string, ctx: MarkdownPostProcessorContext, plugin: MetaBindPlugin) {
12+
super(containerEl);
13+
this.content = content;
14+
this.ctx = ctx;
15+
this.plugin = plugin;
16+
}
17+
18+
async tryRun(): Promise<void> {
19+
if (!this.content) {
20+
throw new Error(`script content can not be empty for meta bind js code block`);
21+
}
22+
23+
const isAsync = this.content.contains('await');
24+
const funcConstructor = isAsync ? async function (): Promise<void> {}.constructor : Function;
25+
const func: any = funcConstructor('app', 'mb', 'dv', 'filePath', 'ctx', this.content);
26+
const inlineAPI = this.plugin.api.createInlineAPI(this.ctx.sourcePath, this.containerEl);
27+
28+
await Promise.resolve(func(this.plugin.app, inlineAPI, getAPI(this.plugin.app), this.ctx.sourcePath, this.ctx));
29+
}
30+
31+
public async onload(): Promise<void> {
32+
try {
33+
await this.tryRun();
34+
} catch (e) {
35+
let m = '';
36+
if (e instanceof Error) {
37+
m = new MetaBindJsError(e.message).message;
38+
console.log(e.stack);
39+
} else {
40+
m = new MetaBindJsError((e as any).toString()).message;
41+
}
42+
43+
this.containerEl.addClass('meta-bind-plugin-card');
44+
45+
const preEl = this.containerEl.createEl('pre', { cls: 'language-js' });
46+
const codeEl = preEl.createEl('code', { text: this.content, cls: 'language-js' });
47+
48+
const errorEl = this.containerEl.createEl('span', { text: m, cls: 'meta-bind-plugin-error' });
49+
}
50+
}
51+
}

src/inputFields/AbstractInputField.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { InputFieldMarkdownRenderChild } from '../InputFieldMarkdownRenderChild';
22

33
export abstract class AbstractInputField {
4-
static allowCodeBlock: boolean = true;
5-
static allowInlineCodeBlock: boolean = true;
4+
static allowBlock: boolean = true;
5+
static allowInline: boolean = true;
66
inputFieldMarkdownRenderChild: InputFieldMarkdownRenderChild;
77
onValueChange: (value: any) => void | Promise<void>;
88

src/inputFields/ImageSuggest/ImageSuggestInputField.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { OptionQueryInputFieldArgument } from '../../inputFieldArguments/OptionQ
99
import { OptionInputFieldArgument } from '../../inputFieldArguments/OptionInputFieldArgument';
1010

1111
export class ImageSuggestInputField extends AbstractInputField {
12-
static allowInlineCodeBlock: boolean = false;
12+
static allowInline: boolean = false;
1313
container: HTMLDivElement | undefined;
1414
component: ImageSuggestInput | undefined;
1515
value: string;

0 commit comments

Comments
 (0)