Skip to content

Commit 8c209ae

Browse files
committed
new api
1 parent 53fdc14 commit 8c209ae

File tree

5 files changed

+246
-106
lines changed

5 files changed

+246
-106
lines changed

src/API.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { App, TFile } from 'obsidian';
2+
import MetaBindPlugin from './main';
3+
import { InlineAPI } from './InlineAPI';
4+
import { InputFieldMarkdownRenderChild, InputFieldMarkdownRenderChildType } from './InputFieldMarkdownRenderChild';
5+
import { InputFieldArgumentType, InputFieldDeclaration, InputFieldDeclarationParser, InputFieldType } from './parsers/InputFieldDeclarationParser';
6+
import { MetaBindBindTargetError, MetaBindParsingError } from './utils/MetaBindErrors';
7+
import { isTruthy } from './utils/Utils';
8+
9+
export class API {
10+
public app: App;
11+
public plugin: MetaBindPlugin;
12+
public parser: InputFieldDeclarationParser;
13+
14+
constructor(plugin: MetaBindPlugin) {
15+
this.plugin = plugin;
16+
17+
this.app = plugin.app;
18+
this.parser = new InputFieldDeclarationParser();
19+
}
20+
21+
public createInlineAPI(file: TFile, container?: HTMLElement): InlineAPI {
22+
return new InlineAPI(this, file, container);
23+
}
24+
25+
public createInputField(
26+
declaration: InputFieldDeclaration,
27+
templateName: string | undefined,
28+
renderType: InputFieldMarkdownRenderChildType,
29+
filePath: string,
30+
container: HTMLElement
31+
): InputFieldMarkdownRenderChild {
32+
declaration = this.parser.parseDeclaration(declaration, undefined, templateName);
33+
return new InputFieldMarkdownRenderChild(container, renderType, declaration, this.plugin, filePath, crypto.randomUUID());
34+
}
35+
36+
public createInputFieldFromString(
37+
fullDeclaration: string,
38+
renderType: InputFieldMarkdownRenderChildType,
39+
filePath: string,
40+
container: HTMLElement
41+
): InputFieldMarkdownRenderChild {
42+
const declaration: InputFieldDeclaration = this.parser.parseString(fullDeclaration);
43+
return new InputFieldMarkdownRenderChild(container, renderType, declaration, this.plugin, filePath, crypto.randomUUID());
44+
}
45+
46+
public createDeclaration(
47+
inputFieldType: InputFieldType,
48+
inputFieldArguments?: Record<InputFieldArgumentType, string>,
49+
bindTargetFile?: string,
50+
bindTargetField?: string
51+
): InputFieldDeclaration {
52+
if (bindTargetFile && !bindTargetField) {
53+
throw new MetaBindBindTargetError('if a bind target file is specified, a bind target field must also be specified');
54+
}
55+
56+
if (this.parser.getInputFieldType(inputFieldType) === InputFieldType.INVALID) {
57+
throw new MetaBindParsingError(`input field type ${inputFieldType} is invalid`);
58+
}
59+
60+
return {
61+
declaration: undefined,
62+
fullDeclaration: undefined,
63+
inputFieldType: inputFieldType,
64+
isBound: isTruthy(bindTargetField),
65+
bindTarget: bindTargetFile + '#' + bindTargetField,
66+
error: undefined,
67+
} as InputFieldDeclaration;
68+
}
69+
70+
public createDeclarationFromString(fullDeclaration: string): InputFieldDeclaration {
71+
return this.parser.parseString(fullDeclaration);
72+
}
73+
}

src/InlineAPI.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { TFile } from 'obsidian';
2+
import { API } from './API';
3+
import { InputFieldArgumentType, InputFieldDeclaration, InputFieldType } from './parsers/InputFieldDeclarationParser';
4+
import { InputFieldMarkdownRenderChild, InputFieldMarkdownRenderChildType } from './InputFieldMarkdownRenderChild';
5+
6+
export class InlineAPI {
7+
public api: API;
8+
public file: TFile;
9+
public container?: HTMLElement;
10+
11+
constructor(api: API, file: TFile, container?: HTMLElement) {
12+
this.api = api;
13+
this.file = file;
14+
this.container = container;
15+
}
16+
17+
public createInputField(declaration: InputFieldDeclaration, templateName: string | undefined, renderType: InputFieldMarkdownRenderChildType): InputFieldMarkdownRenderChild {
18+
if (!this.container) {
19+
throw new Error('inline API was instanced without a container, please use "createInputFieldInContainer"');
20+
}
21+
22+
return this.api.createInputField(declaration, templateName, renderType, this.file.path, this.container);
23+
}
24+
25+
public createInputFieldInContainer(
26+
declaration: InputFieldDeclaration,
27+
templateName: string | undefined,
28+
renderType: InputFieldMarkdownRenderChildType,
29+
container: HTMLElement
30+
): InputFieldMarkdownRenderChild {
31+
return this.api.createInputField(declaration, templateName, renderType, this.file.path, container);
32+
}
33+
34+
public createInputFieldFromString(fullDeclaration: string, renderType: InputFieldMarkdownRenderChildType, filePath: string): InputFieldMarkdownRenderChild {
35+
if (!this.container) {
36+
throw new Error('inline API was instanced without a container, please use "createInputFieldFromStringInContainer"');
37+
}
38+
39+
return this.api.createInputFieldFromString(fullDeclaration, renderType, filePath, this.container);
40+
}
41+
42+
public createInputFieldFromStringInContainer(
43+
fullDeclaration: string,
44+
renderType: InputFieldMarkdownRenderChildType,
45+
filePath: string,
46+
container: HTMLElement
47+
): InputFieldMarkdownRenderChild {
48+
return this.api.createInputFieldFromString(fullDeclaration, renderType, filePath, container);
49+
}
50+
51+
public createDeclaration(
52+
inputFieldType: InputFieldType,
53+
inputFieldArguments?: Record<InputFieldArgumentType, string>,
54+
bindTargetFile?: string,
55+
bindTargetField?: string
56+
): InputFieldDeclaration {
57+
return this.api.createDeclaration(inputFieldType, inputFieldArguments, bindTargetFile, bindTargetField);
58+
}
59+
60+
public createDeclarationFromString(fullDeclaration: string): InputFieldDeclaration {
61+
return this.api.createDeclarationFromString(fullDeclaration);
62+
}
63+
}

src/InputFieldMarkdownRenderChild.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
2626
error: string;
2727
type: InputFieldMarkdownRenderChildType;
2828

29-
fullDeclaration: string;
29+
fullDeclaration?: string;
3030
inputFieldDeclaration: InputFieldDeclaration;
3131
bindTargetFile: TFile | undefined;
3232
bindTargetMetadataPath: string[] | undefined;

src/main.ts

Lines changed: 59 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,46 +6,54 @@ import { DateParser } from './parsers/DateParser';
66
import { InputFieldArgumentType, InputFieldDeclaration, InputFieldDeclarationParser, InputFieldType } from './parsers/InputFieldDeclarationParser';
77
import { MetadataManager } from './MetadataManager';
88
import { MetaBindBindTargetError } from './utils/MetaBindErrors';
9+
import { API } from './API';
910

1011
export default class MetaBindPlugin extends Plugin {
11-
// defined in `loadSettings`
12-
settings: MetaBindPluginSettings = null!;
12+
// @ts-ignore defined in `onload`
13+
settings: MetaBindPluginSettings;
1314

1415
// @ts-ignore defined in `onload`
1516
activeMarkdownInputFields: InputFieldMarkdownRenderChild[];
1617

1718
// @ts-ignore defined in `onload`
1819
metadataManager: MetadataManager;
1920

21+
// @ts-ignore defined in `onload`
22+
api: API;
23+
2024
async onload(): Promise<void> {
2125
console.log(`meta-bind | Main >> load`);
2226

2327
await this.loadSettings();
2428

29+
this.api = new API(this);
30+
2531
DateParser.dateFormat = this.settings.preferredDateFormat;
26-
InputFieldDeclarationParser.parseTemplates(this.settings.inputTemplates);
32+
this.api.parser.parseTemplates(this.settings.inputTemplates);
2733

2834
this.activeMarkdownInputFields = [];
2935
this.metadataManager = new MetadataManager(this);
3036

31-
this.registerMarkdownPostProcessor((element, context) => {
32-
const codeBlocks = element.querySelectorAll('code');
37+
this.registerMarkdownPostProcessor((el, ctx) => {
38+
const codeBlocks = el.querySelectorAll('code');
3339
for (let index = 0; index < codeBlocks.length; index++) {
3440
const codeBlock = codeBlocks.item(index);
35-
const text = codeBlock.innerText;
36-
const isInputField = text.startsWith('INPUT[') && text.endsWith(']');
41+
const content = codeBlock.innerText;
42+
const isInputField = content.startsWith('INPUT[') && content.endsWith(']');
3743
if (isInputField) {
38-
context.addChild(this.buildInputFieldMarkdownRenderChild(text, context.sourcePath, codeBlock, InputFieldMarkdownRenderChildType.INLINE_CODE_BLOCK));
44+
const inputField = this.api.createInputFieldFromString(content, InputFieldMarkdownRenderChildType.INLINE_CODE_BLOCK, ctx.sourcePath, codeBlock);
45+
ctx.addChild(inputField);
3946
}
4047
}
4148
}, 100);
4249

4350
this.registerMarkdownCodeBlockProcessor('meta-bind', (source, el, ctx) => {
4451
const codeBlock = el;
45-
const text = source.replace(/\n/g, '');
46-
const isInputField = text.startsWith('INPUT[') && text.endsWith(']');
52+
const content = source.replace(/\n/g, '');
53+
const isInputField = content.startsWith('INPUT[') && content.endsWith(']');
4754
if (isInputField) {
48-
ctx.addChild(this.buildInputFieldMarkdownRenderChild(text, ctx.sourcePath, codeBlock, InputFieldMarkdownRenderChildType.CODE_BLOCK));
55+
const inputField = this.api.createInputFieldFromString(content, InputFieldMarkdownRenderChildType.CODE_BLOCK, ctx.sourcePath, codeBlock);
56+
ctx.addChild(inputField);
4957
}
5058
});
5159

@@ -62,20 +70,20 @@ export default class MetaBindPlugin extends Plugin {
6270
*
6371
* @returns The render child produced.
6472
*/
65-
buildInputFieldMarkdownRenderChild(
66-
declaration: string | InputFieldDeclaration,
67-
sourcePath: string,
68-
container: HTMLElement,
69-
renderType: InputFieldMarkdownRenderChildType = InputFieldMarkdownRenderChildType.INLINE_CODE_BLOCK
70-
): InputFieldMarkdownRenderChild {
71-
if (typeof declaration === 'string') {
72-
declaration = InputFieldDeclarationParser.parseString(declaration);
73-
} else {
74-
declaration = InputFieldDeclarationParser.parseDeclaration(declaration);
75-
}
76-
77-
return new InputFieldMarkdownRenderChild(container, renderType, declaration, this, sourcePath, crypto.randomUUID());
78-
}
73+
// buildInputFieldMarkdownRenderChild(
74+
// declaration: string | InputFieldDeclaration,
75+
// sourcePath: string,
76+
// container: HTMLElement,
77+
// renderType: InputFieldMarkdownRenderChildType = InputFieldMarkdownRenderChildType.INLINE_CODE_BLOCK
78+
// ): InputFieldMarkdownRenderChild {
79+
// if (typeof declaration === 'string') {
80+
// declaration = InputFieldDeclarationParser.parseString(declaration);
81+
// } else {
82+
// declaration = InputFieldDeclarationParser.parseDeclaration(declaration);
83+
// }
84+
//
85+
// return new InputFieldMarkdownRenderChild(container, renderType, declaration, this, sourcePath, crypto.randomUUID());
86+
// }
7987

8088
/**
8189
* Helper method to build a declaration from some initial data or a string.
@@ -89,31 +97,31 @@ export default class MetaBindPlugin extends Plugin {
8997
*
9098
* @returns A constructed InputFieldDeclaration.
9199
*/
92-
buildDeclaration(
93-
declarationData: string | InputFieldDeclaration | {},
94-
inputFieldArguments?: Record<InputFieldArgumentType, string> | {},
95-
inputFieldType?: InputFieldType,
96-
isBound?: boolean,
97-
bindTarget?: string,
98-
templateName?: string
99-
): InputFieldDeclaration {
100-
if (typeof declarationData === 'string') {
101-
return InputFieldDeclarationParser.parseString(declarationData);
102-
} else {
103-
const declarationBase = declarationData as InputFieldDeclaration;
104-
declarationBase.inputFieldType = inputFieldType ?? declarationBase.inputFieldType ?? InputFieldType.INVALID;
105-
declarationBase.isBound = isBound ?? declarationBase.isBound ?? false;
106-
declarationBase.bindTarget = bindTarget ?? declarationBase.bindTarget ?? undefined;
107-
108-
// if the input field is bound should be determined by `isBound`
109-
// `isBound` is true, `bindTarget` must be set
110-
if (declarationBase.isBound && !declarationBase.bindTarget) {
111-
throw new MetaBindBindTargetError('input field declaration is bound but bind target is undefined');
112-
}
113-
114-
return InputFieldDeclarationParser.parseDeclaration(declarationBase, inputFieldArguments, templateName);
115-
}
116-
}
100+
// buildDeclaration(
101+
// declarationData: string | InputFieldDeclaration | {},
102+
// inputFieldArguments?: Record<InputFieldArgumentType, string> | {},
103+
// inputFieldType?: InputFieldType,
104+
// isBound?: boolean,
105+
// bindTarget?: string,
106+
// templateName?: string
107+
// ): InputFieldDeclaration {
108+
// if (typeof declarationData === 'string') {
109+
// return InputFieldDeclarationParser.parseString(declarationData);
110+
// } else {
111+
// const declarationBase = declarationData as InputFieldDeclaration;
112+
// declarationBase.inputFieldType = inputFieldType ?? declarationBase.inputFieldType ?? InputFieldType.INVALID;
113+
// declarationBase.isBound = isBound ?? declarationBase.isBound ?? false;
114+
// declarationBase.bindTarget = bindTarget ?? declarationBase.bindTarget ?? undefined;
115+
//
116+
// // if the input field is bound should be determined by `isBound`
117+
// // `isBound` is true, `bindTarget` must be set
118+
// if (declarationBase.isBound && !declarationBase.bindTarget) {
119+
// throw new MetaBindBindTargetError('input field declaration is bound but bind target is undefined');
120+
// }
121+
//
122+
// return InputFieldDeclarationParser.parseDeclaration(declarationBase, inputFieldArguments, templateName);
123+
// }
124+
// }
117125

118126
onunload(): void {
119127
console.log(`meta-bind | Main >> unload`);
@@ -164,7 +172,7 @@ export default class MetaBindPlugin extends Plugin {
164172
console.log(`meta-bind | Main >> settings save`);
165173

166174
DateParser.dateFormat = this.settings.preferredDateFormat;
167-
InputFieldDeclarationParser.parseTemplates(this.settings.inputTemplates);
175+
this.api.parser.parseTemplates(this.settings.inputTemplates);
168176
await this.saveData(this.settings);
169177
}
170178
}

0 commit comments

Comments
 (0)