diff --git a/exampleVault/Input Fields/Select and Multi Select.md b/exampleVault/Input Fields/Select and Multi Select.md index d3b4bf01..825111a4 100644 --- a/exampleVault/Input Fields/Select and Multi Select.md +++ b/exampleVault/Input Fields/Select and Multi Select.md @@ -1,9 +1,10 @@ --- -select: 2 +select: 1 multiSelect: - option 1 - option 3 -select2: 1 +select2: false +select3: 3 --- ### Select @@ -25,6 +26,16 @@ showcase ):select2] ``` +```meta-bind +INPUT[select( +option(1, option 1), +option(2, option 2), +option(3, option 3), +option(3, option 3), +option(2, option 2), +showcase +):select3] +``` ### Multi Select ```meta-bind diff --git a/src/api/IAPI.ts b/src/api/IAPI.ts index 4f42d841..6f31bad3 100644 --- a/src/api/IAPI.ts +++ b/src/api/IAPI.ts @@ -12,6 +12,4 @@ export interface IAPI { readonly inputFieldParser: InputFieldDeclarationParser; readonly viewFieldParser: ViewFieldDeclarationParser; readonly bindTargetParser: BindTargetParser; - - readonly inputFieldFactory: NewInputFieldFactory; } diff --git a/src/cm6/Cm6_Widgets.ts b/src/cm6/Cm6_Widgets.ts index 0816b352..2e1a3ed9 100644 --- a/src/cm6/Cm6_Widgets.ts +++ b/src/cm6/Cm6_Widgets.ts @@ -50,7 +50,7 @@ export class ViewFieldWidget extends MarkdownRenderChildWidget { export class InputFieldWidget extends MarkdownRenderChildWidget { public createRenderChild(container: HTMLElement, component: Component): InputFieldMDRC | ExcludedMDRC { - return this.plugin.api.createInputFieldFromString(this.content, RenderChildType.INLINE, this.filePath, container, component); + return this.plugin.api.createInputFieldFromString(this.content, RenderChildType.INLINE, this.filePath, container, component, undefined); } } diff --git a/src/frontmatterDisplay/CmPlugin.ts b/src/frontmatterDisplay/CmPlugin.ts deleted file mode 100644 index d7c4ded4..00000000 --- a/src/frontmatterDisplay/CmPlugin.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Decoration, DecorationSet, EditorView, PluginSpec, PluginValue, ViewPlugin, ViewUpdate } from '@codemirror/view'; -import { FrontmatterWidget } from './FrontmatterWidget'; - -class CmPlugin implements PluginValue { - decorations: DecorationSet; - - constructor(view: EditorView) { - this.decorations = this.buildDecorations(view); - console.log(view); - } - - public update(update: ViewUpdate): void {} - - public destroy(): void {} - - buildDecorations(view: EditorView): DecorationSet { - const widgets: Decoration[] = []; - - widgets.push(Decoration.widget({ widget: new FrontmatterWidget() })); - - return Decoration.set(widgets.map(x => x.range(0))); - } -} - -const pluginSpec: PluginSpec = { - decorations: (value: CmPlugin) => value.decorations, -}; - -export const cmPlugin = ViewPlugin.fromClass(CmPlugin, pluginSpec); diff --git a/src/frontmatterDisplay/FrontmatterDisplay.svelte b/src/frontmatterDisplay/FrontmatterDisplay.svelte deleted file mode 100644 index 97cd0af1..00000000 --- a/src/frontmatterDisplay/FrontmatterDisplay.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - -
- -
diff --git a/src/frontmatterDisplay/FrontmatterWidget.ts b/src/frontmatterDisplay/FrontmatterWidget.ts deleted file mode 100644 index d231f323..00000000 --- a/src/frontmatterDisplay/FrontmatterWidget.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { EditorView, WidgetType } from '@codemirror/view'; -import FrontmatterDisplay from './FrontmatterDisplay.svelte'; - -export class FrontmatterWidget extends WidgetType { - toDOM(view: EditorView): HTMLElement { - const el = document.documentElement.createDiv(); - - new FrontmatterDisplay({ - target: el, - props: { - frontmatter: {}, - }, - }); - - return el; - } -} diff --git a/src/frontmatterDisplay/custom_overlay.js b/src/frontmatterDisplay/custom_overlay.js deleted file mode 100644 index 5e6abac0..00000000 --- a/src/frontmatterDisplay/custom_overlay.js +++ /dev/null @@ -1,81 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: https://codemirror.net/LICENSE - -// Utility function that allows modes to be combined. The mode given -// as the base argument takes care of most of the normal mode -// functionality, but a second (typically simple) mode is used, which -// can override the style of text. Both modes get to parse all of the -// text, but when both assign a non-null style to a piece of code, the -// overlay wins, unless the combine argument was true and not overridden, -// or state.overlay.combineTokens was true, in which case the styles are -// combined. - -(function (mod) { - mod(window.CodeMirror); -})(function (CodeMirror) { - 'use strict'; - - CodeMirror.customOverlayMode = function (base, overlay, combine) { - return { - startState: () => ({ - base: CodeMirror.startState(base), - overlay: CodeMirror.startState(overlay), - basePos: 0, - baseCur: null, - overlayPos: 0, - overlayCur: null, - streamSeen: null, - }), - copyState: state => ({ - base: CodeMirror.copyState(base, state.base), - overlay: CodeMirror.copyState(overlay, state.overlay), - basePos: state.basePos, - baseCur: null, - overlayPos: state.overlayPos, - overlayCur: null, - }), - - token: (stream, state) => { - if (stream != state.streamSeen || Math.min(state.basePos, state.overlayPos) < stream.start) { - state.streamSeen = stream; - state.basePos = state.overlayPos = stream.start; - } - - if (stream.start == state.basePos) { - state.baseCur = base.token(stream, state.base); - state.basePos = stream.pos; - } - if (stream.start == state.overlayPos) { - stream.pos = stream.start; - state.overlayCur = overlay.token(stream, state.overlay); - state.overlayPos = stream.pos; - } - stream.pos = Math.min(state.basePos, state.overlayPos); - - // state.overlay.combineTokens always takes precedence over combine, - // unless set to null - if (state.overlayCur == null) { - return state.baseCur; - } else if ((state.baseCur != null && state.overlay.combineTokens) || (combine && state.overlay.combineTokens == null)) { - return state.baseCur + ' ' + state.overlayCur; - } else { - return state.overlayCur; - } - }, - - indent: base.indent && ((state, textAfter, line) => base.indent(state.base, textAfter, line)), - - electricChars: base.electricChars, - - innerMode: state => ({ state: state.base, mode: base }), - - blankLine: state => { - let baseToken, overlayToken; - if (base.blankLine) baseToken = base.blankLine(state.base); - if (overlay.blankLine) overlayToken = overlay.blankLine(state.overlay); - - return overlayToken == null ? baseToken : combine && baseToken != null ? baseToken + ' ' + overlayToken : overlayToken; - }, - }; - }; -}); diff --git a/src/inputFields/_new/NewInputFieldFactory.ts b/src/inputFields/_new/NewInputFieldFactory.ts index f34eadf9..3dac3976 100644 --- a/src/inputFields/_new/NewInputFieldFactory.ts +++ b/src/inputFields/_new/NewInputFieldFactory.ts @@ -5,8 +5,10 @@ import { IPlugin } from '../../IPlugin'; import { Toggle } from './fields/Toggle/Toggle'; import { Text } from './fields/Text/Text'; import { Slider } from './fields/Slider/Slider'; +import { TextArea } from './fields/TextArea/TextArea'; +import { Select } from './fields/Select/Select'; -export type NewInputField = Toggle | Slider | Text; +export type NewInputField = Toggle | Slider | Text | TextArea | Select; export class NewInputFieldFactory { plugin: IPlugin; @@ -26,6 +28,12 @@ export class NewInputFieldFactory { return new Slider(renderChild); } else if (type === InputFieldType.TEXT) { return new Text(renderChild); + } else if (type === InputFieldType.TEXT_AREA) { + return new TextArea(renderChild); + } else if (type === InputFieldType.TEXT_AREA_DEPRECATED) { + return new TextArea(renderChild); + } else if (type === InputFieldType.SELECT) { + return new Select(renderChild); } return undefined; diff --git a/src/inputFields/_new/fields/Select/Select.ts b/src/inputFields/_new/fields/Select/Select.ts new file mode 100644 index 00000000..6c34ad12 --- /dev/null +++ b/src/inputFields/_new/fields/Select/Select.ts @@ -0,0 +1,43 @@ +import { NewAbstractInputField } from '../../NewAbstractInputField'; +import { isLiteral, MBLiteral, stringifyLiteral } from '../../../../utils/Utils'; +import { InputFieldMDRC } from '../../../../renderChildren/InputFieldMDRC'; +import { SvelteComponent } from 'svelte'; +import SelectComponent from './SelectComponent.svelte'; +import { OptionInputFieldArgument } from '../../../../inputFieldArguments/arguments/OptionInputFieldArgument'; +import { InputFieldArgumentType } from '../../../InputFieldConfigs'; + +export class Select extends NewAbstractInputField { + options: OptionInputFieldArgument[]; + + constructor(renderChild: InputFieldMDRC) { + super(renderChild); + + this.options = this.renderChild.getArguments(InputFieldArgumentType.OPTION) as OptionInputFieldArgument[]; + } + + protected filterValue(value: any): MBLiteral | undefined { + return isLiteral(value) ? value : undefined; + } + + protected getFallbackDefaultValue(): MBLiteral { + return null; + } + + protected getSvelteComponent(): typeof SvelteComponent { + return SelectComponent; + } + + protected rawMapValue(value: MBLiteral): MBLiteral { + return value; + } + + protected rawReverseMapValue(value: MBLiteral): MBLiteral | undefined { + return value; + } + + protected getMountArgs(): Record { + return { + options: this.options, + }; + } +} diff --git a/src/inputFields/_new/fields/Select/SelectComponent.svelte b/src/inputFields/_new/fields/Select/SelectComponent.svelte new file mode 100644 index 00000000..c5e64b72 --- /dev/null +++ b/src/inputFields/_new/fields/Select/SelectComponent.svelte @@ -0,0 +1,36 @@ + + +{#each options as option} +
selectOption(option.value)} + on:keypress={(event) => selectOptionOnKey(event, option.value)} + > + {option.name} +
+{/each} diff --git a/src/inputFields/_new/fields/TextArea/TextArea.ts b/src/inputFields/_new/fields/TextArea/TextArea.ts new file mode 100644 index 00000000..0957f60e --- /dev/null +++ b/src/inputFields/_new/fields/TextArea/TextArea.ts @@ -0,0 +1,38 @@ +import { NewAbstractInputField } from '../../NewAbstractInputField'; +import { InputFieldMDRC } from '../../../../renderChildren/InputFieldMDRC'; +import { isLiteral } from '../../../../utils/Utils'; +import { SvelteComponent } from 'svelte'; +import TextAreaComponent from './TextAreaComponent.svelte'; +import { InputFieldArgumentType } from '../../../InputFieldConfigs'; + +export class TextArea extends NewAbstractInputField { + constructor(renderChild: InputFieldMDRC) { + super(renderChild); + } + + protected filterValue(value: any): string | undefined { + return isLiteral(value) ? value?.toString() : undefined; + } + + protected getFallbackDefaultValue(): string { + return ''; + } + + protected getSvelteComponent(): typeof SvelteComponent { + return TextAreaComponent; + } + + protected rawReverseMapValue(value: string): string | undefined { + return value; + } + + protected rawMapValue(value: string): string { + return value; + } + + protected getMountArgs(): Record { + return { + placeholder: this.renderChild.getArgument(InputFieldArgumentType.PLACEHOLDER)?.value ?? 'Text', + }; + } +} diff --git a/src/inputFields/_new/fields/TextArea/TextAreaComponent.svelte b/src/inputFields/_new/fields/TextArea/TextAreaComponent.svelte new file mode 100644 index 00000000..6def64da --- /dev/null +++ b/src/inputFields/_new/fields/TextArea/TextAreaComponent.svelte @@ -0,0 +1,11 @@ + + + diff --git a/src/inputFields/_new/fields/Toggle/ToggleComponent.svelte b/src/inputFields/_new/fields/Toggle/ToggleComponent.svelte index 3f9627e7..cb786862 100644 --- a/src/inputFields/_new/fields/Toggle/ToggleComponent.svelte +++ b/src/inputFields/_new/fields/Toggle/ToggleComponent.svelte @@ -13,7 +13,7 @@ } function toggleValueOnKey(event: KeyboardEvent) { - if (event.code === ' ') { + if (event.key === ' ') { toggleValue(); } } diff --git a/src/main.ts b/src/main.ts index 7eb673e6..ea634d8d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -6,7 +6,6 @@ import { DateParser } from './parsers/DateParser'; import { MetadataManager } from './metadata/MetadataManager'; import { API } from './api/API'; import { setFirstWeekday } from './inputFields/fields/DatePicker/DatePickerInputSvelteHelpers'; -import './frontmatterDisplay/custom_overlay'; import { createMarkdownRenderChildWidgetEditorPlugin } from './cm6/Cm6_ViewPlugin'; import { MDRCManager } from './MDRCManager'; import { DEFAULT_SETTINGS, InputFieldTemplate, MetaBindPluginSettings } from './settings/Settings'; @@ -46,28 +45,22 @@ export default class MetaBindPlugin extends Plugin implements IPlugin { this.registerMarkdownPostProcessor((el: HTMLElement, ctx: MarkdownPostProcessorContext) => { const codeBlocks = el.querySelectorAll('code'); - // console.log(el.outerHTML); - for (let index = 0; index < codeBlocks.length; index++) { const codeBlock = codeBlocks.item(index); - // console.log(codeBlock.outerHTML); - // console.log(codeBlock.tagName, codeBlock.className, codeBlock.innerText); - - if (codeBlock.hasClass('meta-bind-none')) { + if (codeBlock.hasClass('mb-none')) { continue; } const content = codeBlock.innerText; const isInputField = content.startsWith('INPUT[') && content.endsWith(']'); const isViewField = content.startsWith('VIEW[') && content.endsWith(']'); + if (isInputField) { - const inputField = this.api.createInputFieldFromString(content, RenderChildType.INLINE, ctx.sourcePath, codeBlock, ctx, undefined); - // ctx.addChild(inputField); + this.api.createInputFieldFromString(content, RenderChildType.INLINE, ctx.sourcePath, codeBlock, ctx, undefined); } if (isViewField) { - const viewField = this.api.createViewFieldFromString(content, RenderChildType.INLINE, ctx.sourcePath, codeBlock, ctx); - // ctx.addChild(viewField); + this.api.createViewFieldFromString(content, RenderChildType.INLINE, ctx.sourcePath, codeBlock, ctx); } } }, 100); @@ -76,15 +69,18 @@ export default class MetaBindPlugin extends Plugin implements IPlugin { const codeBlock = el; const content = source.trim(); const isInputField = content.startsWith('INPUT[') && content.endsWith(']'); + const isViewField = content.startsWith('VIEW[') && content.endsWith(']'); + if (isInputField) { - const inputField = this.api.createInputFieldFromString(content, RenderChildType.BLOCK, ctx.sourcePath, codeBlock, ctx, undefined); - // ctx.addChild(inputField); + this.api.createInputFieldFromString(content, RenderChildType.BLOCK, ctx.sourcePath, codeBlock, ctx, undefined); + } + if (isViewField) { + this.api.createViewFieldFromString(content, RenderChildType.INLINE, ctx.sourcePath, codeBlock, ctx); } }); this.registerMarkdownCodeBlockProcessor('meta-bind-js-view', (source, el, ctx) => { - const inputField = this.api.createJsViewFieldFromString(source, RenderChildType.BLOCK, ctx.sourcePath, el, ctx); - // ctx.addChild(inputField); + this.api.createJsViewFieldFromString(source, RenderChildType.BLOCK, ctx.sourcePath, el, ctx); }); this.registerEditorExtension(createMarkdownRenderChildWidgetEditorPlugin(this)); diff --git a/src/publish/PublishAPI.ts b/src/publish/PublishAPI.ts index 1943b597..58c25b0d 100644 --- a/src/publish/PublishAPI.ts +++ b/src/publish/PublishAPI.ts @@ -33,7 +33,7 @@ export class PublishAPI implements IAPI { container: HTMLElement, component: MarkdownPostProcessorContext ): PublishInputFieldMDRC { - const declaration: InputFieldDeclaration = this.inputFieldParser.parseString(fullDeclaration); + const declaration: InputFieldDeclaration = this.inputFieldParser.parseString(fullDeclaration, undefined); const inputField = new PublishInputFieldMDRC(container, this, declaration, filePath, metadata, self.crypto.randomUUID()); component.addChild(inputField); diff --git a/src/publish/PublishViewFieldMDRC.ts b/src/publish/PublishViewFieldMDRC.ts index 6c06300a..cd4c0a03 100644 --- a/src/publish/PublishViewFieldMDRC.ts +++ b/src/publish/PublishViewFieldMDRC.ts @@ -52,13 +52,13 @@ export class PublishViewFieldMDRC extends MarkdownRenderChild { for (const entry of this.viewFieldDeclaration.declaration ?? []) { if (typeof entry !== 'string') { - const variable = { + const variable: ViewFieldVariable = { bindTargetDeclaration: entry, writeSignal: new Signal(undefined), uuid: self.crypto.randomUUID(), - metadataCache: undefined, writeSignalListener: undefined, contextName: `MB_VAR_${varCounter}`, + listenToChildren: false, }; this.variables.push(variable); diff --git a/src/renderChildren/InputFieldMDRC.ts b/src/renderChildren/InputFieldMDRC.ts index 40458587..62ff4d05 100644 --- a/src/renderChildren/InputFieldMDRC.ts +++ b/src/renderChildren/InputFieldMDRC.ts @@ -158,7 +158,7 @@ export class InputFieldMDRC extends AbstractMDRC { async onload(): Promise { console.log('meta-bind | InputFieldMarkdownRenderChild >> load', this); - this.containerEl.addClass('meta-bind-plugin-input'); + this.containerEl.addClass('mb-input'); this.containerEl.empty(); if (!this.errorCollection.hasErrors() && !this.inputField) { @@ -188,7 +188,7 @@ export class InputFieldMDRC extends AbstractMDRC { // --- Determine Wrapper Element --- if (this.shouldAddCardContainer()) { - const cardContainer: HTMLDivElement = this.containerEl.createDiv({ cls: 'meta-bind-plugin-card' }); + const cardContainer: HTMLDivElement = this.containerEl.createDiv({ cls: 'mb-card' }); if (titleArgument) { cardContainer.createEl('h3', { text: titleArgument.value }); } @@ -218,7 +218,7 @@ export class InputFieldMDRC extends AbstractMDRC { // --- Create Container Element --- const container: HTMLDivElement = createDiv(); - container.addClass('meta-bind-plugin-input-wrapper'); + container.addClass('mb-input-wrapper'); // --- Mount Input Field --- this.inputField?.mount(container); @@ -234,7 +234,7 @@ export class InputFieldMDRC extends AbstractMDRC { // --- Add Showcase Argument --- if (this.shouldAddCardContainer() && showcaseArgument) { - wrapperContainer.createEl('code', { text: this.fullDeclaration, cls: 'meta-bind-none' }); + wrapperContainer.createEl('code', { text: this.fullDeclaration, cls: 'mb-none' }); } } @@ -246,7 +246,7 @@ export class InputFieldMDRC extends AbstractMDRC { this.unregisterSelfFromMetadataManager(); this.containerEl.empty(); - this.containerEl.createEl('span', { text: 'unloaded meta bind input field', cls: 'meta-bind-plugin-error' }); + this.containerEl.createEl('span', { text: 'unloaded meta bind input field', cls: 'mb-error' }); super.onunload(); } diff --git a/src/renderChildren/JsViewFieldMDRC.ts b/src/renderChildren/JsViewFieldMDRC.ts index 4a48b51d..28d1967a 100644 --- a/src/renderChildren/JsViewFieldMDRC.ts +++ b/src/renderChildren/JsViewFieldMDRC.ts @@ -131,7 +131,7 @@ export class JsViewFieldMDRC extends AbstractViewFieldMDRC { async onload(): Promise { console.log('meta-bind | ViewFieldMarkdownRenderChild >> load', this); - this.containerEl.addClass('meta-bind-plugin-view'); + this.containerEl.addClass('mb-view'); this.containerEl.empty(); new ErrorIndicatorComponent({ @@ -150,7 +150,7 @@ export class JsViewFieldMDRC extends AbstractViewFieldMDRC { this.plugin.mdrcManager.registerMDRC(this); const container: HTMLDivElement = createDiv(); - container.addClass('meta-bind-plugin-view-wrapper'); + container.addClass('mb-view-wrapper'); this.viewField.render(container); @@ -164,7 +164,7 @@ export class JsViewFieldMDRC extends AbstractViewFieldMDRC { this.unregisterSelfFromMetadataManager(); this.containerEl.empty(); - this.containerEl.createEl('span', { text: 'unloaded meta bind view field', cls: 'meta-bind-plugin-error' }); + this.containerEl.createEl('span', { text: 'unloaded meta bind view field', cls: 'mb-error' }); super.onunload(); } diff --git a/src/renderChildren/ViewFieldMDRC.ts b/src/renderChildren/ViewFieldMDRC.ts index aa0cf7c0..72b417e4 100644 --- a/src/renderChildren/ViewFieldMDRC.ts +++ b/src/renderChildren/ViewFieldMDRC.ts @@ -140,7 +140,7 @@ export class ViewFieldMDRC extends AbstractViewFieldMDRC { async onload(): Promise { console.log('meta-bind | ViewFieldMarkdownRenderChild >> load', this); - this.containerEl.addClass('meta-bind-plugin-view'); + this.containerEl.addClass('mb-view'); this.containerEl.empty(); new ErrorIndicatorComponent({ @@ -159,7 +159,7 @@ export class ViewFieldMDRC extends AbstractViewFieldMDRC { this.plugin.mdrcManager.registerMDRC(this); const container: HTMLDivElement = createDiv(); - container.addClass('meta-bind-plugin-view-wrapper'); + container.addClass('mb-view-wrapper'); this.viewField.render(container); @@ -173,7 +173,7 @@ export class ViewFieldMDRC extends AbstractViewFieldMDRC { this.unregisterSelfFromMetadataManager(); this.containerEl.empty(); - this.containerEl.createEl('span', { text: 'unloaded meta bind view field', cls: 'meta-bind-plugin-error' }); + this.containerEl.createEl('span', { text: 'unloaded meta bind view field', cls: 'mb-error' }); super.onunload(); } diff --git a/src/utils/errors/ErrorCollectionComponent.svelte b/src/utils/errors/ErrorCollectionComponent.svelte index dbe89495..40570d5b 100644 --- a/src/utils/errors/ErrorCollectionComponent.svelte +++ b/src/utils/errors/ErrorCollectionComponent.svelte @@ -13,14 +13,14 @@ {#if errorCollection.hasWarnings()}
Warnings
{#each errorCollection.getWarnings() as warning} -
{warning.message}
-
{warning.stack}
+
{warning.message}
+
{warning.stack}
{/each} {/if} {#if errorCollection.hasErrors()}
Errors
{#each errorCollection.getErrors() as error} -
{error.message}
-
{error.stack}
+
{error.message}
+
{error.stack}
{/each} {/if} diff --git a/src/utils/errors/ErrorCollectionViewModal.ts b/src/utils/errors/ErrorCollectionViewModal.ts index f396bb5d..d07681b7 100644 --- a/src/utils/errors/ErrorCollectionViewModal.ts +++ b/src/utils/errors/ErrorCollectionViewModal.ts @@ -14,7 +14,7 @@ export class ErrorCollectionViewModal extends Modal { } public onOpen(): void { - this.modalEl.addClass('meta-bind-error-collection-modal'); + this.modalEl.addClass('mb-error-collection-modal'); this.titleEl.innerText = 'Meta Bind Field'; this.component = new ErrorCollectionComponent({ diff --git a/src/utils/errors/ErrorIndicatorComponent.svelte b/src/utils/errors/ErrorIndicatorComponent.svelte index a2180b43..957f585e 100644 --- a/src/utils/errors/ErrorIndicatorComponent.svelte +++ b/src/utils/errors/ErrorIndicatorComponent.svelte @@ -15,7 +15,7 @@ {#if !errorCollection.isEmpty()} -
openModal()} +
openModal()} on:keydown={(e) => { if (e.key === ' ') { openModal() } }} role="button" tabindex=0> {#if errorCollection.hasErrors()} - [META_BIND_ERROR] + [META_BIND_ERROR] {:else if errorCollection.hasWarnings()} div.meta-bind-plugin-view-wrapper) { +:is(code, span).mb-view:has(> div.mb-view-wrapper) { background-color: transparent; border: none; color: inherit; @@ -26,157 +26,149 @@ body { margin: 0; } -div.meta-bind-plugin-view-wrapper { +div.mb-view-wrapper { display: inline; } -.meta-bind-plugin-flex-input-wrapper { +.mb-flex-input-wrapper { display: inline-flex; } -.meta-bind-plugin-input-wrapper .checkbox-container { +.mb-input-wrapper .checkbox-container { vertical-align: text-bottom; } -.meta-bind-plugin-slider-input { +.mb-slider-input { align-self: center; - margin-left: var(--meta-bind-plugin-slider-spacing) !important; - margin-right: var(--meta-bind-plugin-slider-spacing) !important; + margin-left: var(--mb-slider-spacing) !important; + margin-right: var(--mb-slider-spacing) !important; } -.meta-bind-plugin-error { +.mb-slider-input-label { + color: var(--text-muted); +} + +.mb-error { color: var(--text-error) !important; font-weight: bold; font-family: var(--font-monospace); } -code.meta-bind-plugin-error { +code.mb-error { color: var(--text-error) !important; } -.meta-bind-code { +.mb-code { color: var(--text-normal); font-family: var(--font-monospace); } -.meta-bind-plugin-slider-input-label { - color: var(--text-muted); -} - -.meta-bind-plugin-select-input-element { +.mb-select-input-element { cursor: pointer; padding: 5px; margin: 5px 0 5px 0; - border-radius: var(--meta-bind-plugin-border-radius); - border-left: var(--meta-bind-plugin-select-element-border-width) solid transparent; + border-radius: var(--mb-border-radius); + border-left: var(--mb-select-element-border-width) solid transparent; white-space: pre-wrap; font-size: 16px; min-width: 200px; } -.meta-bind-plugin-select-input-element-selected { - border-left: var(--meta-bind-plugin-select-element-border-width) solid var(--interactive-accent) !important; +.mb-select-input-element.is-selected { + border-left: var(--mb-select-element-border-width) solid var(--interactive-accent); background: var(--background-secondary); } -.meta-bind-plugin-select-input-element-hover { +.mb-select-input-element:hover { background: var(--background-secondary); } -.meta-bind-plugin-date-input-year-input[type='number'] { - width: var(--meta-bind-plugin-date-input-year-input-width); +.mb-date-input-year-input[type='number'] { + width: var(--mb-date-input-year-input-width); height: unset; align-self: stretch; } -.meta-bind-plugin-input-element-group { +.mb-input-element-group { } -.meta-bind-plugin-input-element-group .meta-bind-plugin-input-element-group-element:focus { +.mb-input-element-group .mb-input-element-group-element:focus { z-index: 10; } -.meta-bind-plugin-input-element-group .meta-bind-plugin-input-element-group-element:first-child { - border-radius: var(--meta-bind-plugin-border-radius) 0 0 var(--meta-bind-plugin-border-radius); +.mb-input-element-group .mb-input-element-group-element:first-child { + border-radius: var(--mb-border-radius) 0 0 var(--mb-border-radius); } -.meta-bind-plugin-input-element-group .meta-bind-plugin-input-element-group-element:not(:first-child):not(:last-child) { +.mb-input-element-group .mb-input-element-group-element:not(:first-child):not(:last-child) { border-radius: 0; } -.meta-bind-plugin-input-element-group .meta-bind-plugin-input-element-group-element:last-child { - border-radius: 0 var(--meta-bind-plugin-border-radius) var(--meta-bind-plugin-border-radius) 0; +.mb-input-element-group .mb-input-element-group-element:last-child { + border-radius: 0 var(--mb-border-radius) var(--mb-border-radius) 0; } -.meta-bind-plugin-card { +.mb-card { padding: var(--size-4-2); margin: var(--size-4-2) 0; - border-radius: var(--meta-bind-plugin-border-radius); - border: var(--meta-bind-plugin-border-width) solid var(--background-modifier-border); + border-radius: var(--mb-border-radius); + border: var(--mb-border-width) solid var(--background-modifier-border); display: inline-flex; flex-direction: column; gap: var(--size-4-2); } -[class*='block-language-'] > .meta-bind-plugin-card { +[class*='block-language-'] > .mb-card { display: flex; } -.meta-bind-plugin-card > code { +.mb-card > code { display: block; } -.meta-bind-plugin-card > pre { +.mb-card > pre { margin: 0; } -.meta-bind-plugin-card > h3 { +.mb-card > h3 { margin-top: 0; } -.meta-bind-full-width { - width: 100%; -} - -.meta-bind-high { - height: 200px; -} - -.meta-bind-error-collection-card { +.mb-error-collection-card { padding: var(--size-4-2); margin: var(--size-4-2) 0; - border-radius: var(--meta-bind-plugin-border-radius); - border: var(--meta-bind-plugin-border-width) solid var(--background-modifier-border); + border-radius: var(--mb-border-radius); + border: var(--mb-border-width) solid var(--background-modifier-border); color: var(--text-normal); font-family: var(--font-default); } -.meta-bind-error-collection { +.mb-error-collection { display: inline-block; position: relative; cursor: pointer; margin-inline: var(--size-4-2); } -.publish-renderer .meta-bind-error-collection { +.publish-renderer .mb-error-collection { margin-inline: 0; } -.meta-bind-error-collection > svg { +.mb-error-collection > svg { width: var(--font-text-size); height: var(--font-text-size); vertical-align: text-bottom; } -.meta-bind-error-collection > svg.lucide-alert-circle { +.mb-error-collection > svg.lucide-alert-circle { color: var(--color-red); } -.meta-bind-error-collection > svg.lucide-alert-triangle { +.mb-error-collection > svg.lucide-alert-triangle { color: var(--color-orange); } -.meta-bind-error-collection > svg.lucide-info { +.mb-error-collection > svg.lucide-info { color: var(--text-normal); } @@ -208,14 +200,24 @@ code.meta-bind-plugin-error { flex-grow: 1; } -.meta-bind-pre { +.mb-pre { overflow-x: scroll; } -.meta-bind-pre > code { +.mb-pre > code { white-space: pre; } -.meta-bind-error-collection-modal { +.mb-error-collection-modal { width: 80%; } + +/* --- UTIL CLASSES --- */ + +.meta-bind-full-width > * { + width: 100%; +} + +.meta-bind-high > * { + height: 200px; +} diff --git a/tests/parserTests/InputFieldParser.test.ts b/tests/parserTests/InputFieldParser.test.ts index e31063a2..31f6b486 100644 --- a/tests/parserTests/InputFieldParser.test.ts +++ b/tests/parserTests/InputFieldParser.test.ts @@ -6,56 +6,56 @@ const parser = plugin.api.inputFieldParser; describe('should not error or warn cases', () => { describe('no templates, no local scope', () => { test('INPUT[text]', () => { - const res = parser.parseString('INPUT[text]'); + const res = parser.parseString('INPUT[text]', undefined); expect(res).not.toHaveWarnings(); expect(res).not.toHaveErrors(); }); test('INPUT[select(option(a), option(b, c), showcase)]', () => { - const res = parser.parseString('INPUT[select(option(a), option(b, c), showcase)]'); + const res = parser.parseString('INPUT[select(option(a), option(b, c), showcase)]', undefined); expect(res).not.toHaveWarnings(); expect(res).not.toHaveErrors(); }); test('INPUT[text:text]', () => { - const res = parser.parseString('INPUT[text:text]'); + const res = parser.parseString('INPUT[text:text]', undefined); expect(res).not.toHaveWarnings(); expect(res).not.toHaveErrors(); }); test('INPUT[text:["test"]]', () => { - const res = parser.parseString('INPUT[text:["test"]]'); + const res = parser.parseString('INPUT[text:["test"]]', undefined); expect(res).not.toHaveWarnings(); expect(res).not.toHaveErrors(); }); test('INPUT[text:[0]]', () => { - const res = parser.parseString('INPUT[text:[0]]'); + const res = parser.parseString('INPUT[text:[0]]', undefined); expect(res).not.toHaveWarnings(); expect(res).not.toHaveErrors(); }); test('INPUT[text:file#text]', () => { - const res = parser.parseString('INPUT[text:file#text]'); + const res = parser.parseString('INPUT[text:file#text]', undefined); expect(res).not.toHaveWarnings(); expect(res).not.toHaveErrors(); }); test('INPUT[text:path/to/file#text]', () => { - const res = parser.parseString('INPUT[text:path/to/file#text]'); + const res = parser.parseString('INPUT[text:path/to/file#text]', undefined); expect(res).not.toHaveWarnings(); expect(res).not.toHaveErrors(); }); test('INPUT[text:path/to/other file#text]', () => { - const res = parser.parseString('INPUT[text:path/to/other file#text]'); + const res = parser.parseString('INPUT[text:path/to/other file#text]', undefined); expect(res).not.toHaveWarnings(); expect(res).not.toHaveErrors(); @@ -65,21 +65,21 @@ describe('should not error or warn cases', () => { describe('should warn on deprecation', () => { test('INPUT[multi_select]', () => { - const res = parser.parseString('INPUT[multi_select]'); + const res = parser.parseString('INPUT[multi_select]', undefined); expect(res).toHaveWarnings(); expect(res).not.toHaveErrors(); }); test('INPUT[date_picker]', () => { - const res = parser.parseString('INPUT[date_picker]'); + const res = parser.parseString('INPUT[date_picker]', undefined); expect(res).toHaveWarnings(); expect(res).not.toHaveErrors(); }); test('INPUT[text_area]', () => { - const res = parser.parseString('INPUT[text_area]'); + const res = parser.parseString('INPUT[text_area]', undefined); expect(res).toHaveWarnings(); expect(res).not.toHaveErrors(); @@ -88,7 +88,7 @@ describe('should warn on deprecation', () => { describe('should warn on invalid argument', () => { test('INPUT[text(invalidArgument)]', () => { - const res = parser.parseString('INPUT[text(invalidArgument)]'); + const res = parser.parseString('INPUT[text(invalidArgument)]', undefined); expect(res).toHaveWarnings(); expect(res).not.toHaveErrors(); @@ -97,7 +97,7 @@ describe('should warn on invalid argument', () => { describe('should error on invalid input field type', () => { test('INPUT[invalidType]', () => { - const res = parser.parseString('INPUT[invalidType]'); + const res = parser.parseString('INPUT[invalidType]', undefined); expect(res).not.toHaveWarnings(); expect(res).toHaveErrors(); diff --git a/tests/parserTests/testAPI/TestAPI.ts b/tests/parserTests/testAPI/TestAPI.ts index 6efe86c3..58996e34 100644 --- a/tests/parserTests/testAPI/TestAPI.ts +++ b/tests/parserTests/testAPI/TestAPI.ts @@ -4,12 +4,17 @@ import { BindTargetParser } from '../../../src/parsers/BindTargetParser'; import { InputFieldAPI } from '../../../src/api/InputFieldAPI'; import { InputFieldDeclarationParser } from '../../../src/parsers/inputFieldParser/InputFieldParser'; import { ViewFieldDeclarationParser } from '../../../src/parsers/ViewFieldDeclarationParser'; +import { NewInputFieldFactory } from '../../../src/inputFields/_new/NewInputFieldFactory'; +import { DEFAULT_SETTINGS, MetaBindPluginSettings } from '../../../src/settings/Settings'; export class TestPlugin implements IPlugin { public api: TestAPI; + public settings: MetaBindPluginSettings; constructor() { this.api = new TestAPI(this); + + this.settings = DEFAULT_SETTINGS; } public getFilePathsByName(name: string): string[] { @@ -19,19 +24,19 @@ export class TestPlugin implements IPlugin { export class TestAPI implements IAPI { public readonly plugin: TestPlugin; + public readonly inputField: InputFieldAPI; public readonly bindTargetParser: BindTargetParser; public readonly inputFieldParser: InputFieldDeclarationParser; public readonly viewFieldParser: ViewFieldDeclarationParser; - public readonly inputField: InputFieldAPI; constructor(plugin: TestPlugin) { this.plugin = plugin; + this.inputField = new InputFieldAPI(this); + this.inputFieldParser = new InputFieldDeclarationParser(this.plugin); this.viewFieldParser = new ViewFieldDeclarationParser(this.plugin); this.bindTargetParser = new BindTargetParser(this.plugin); - - this.inputField = new InputFieldAPI(this); } }