Skip to content

Commit 5f3965f

Browse files
committed
use links partial
1 parent 421fcb0 commit 5f3965f

File tree

5 files changed

+118
-19
lines changed

5 files changed

+118
-19
lines changed

exampleVault/Input Fields/Suggester.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
---
2-
fileSuggest: "[[Other/Example Notes/Example Note with Embeds.md|Example Note with Embeds]]"
3-
fileSuggest2: Example Note with E
42
suggest: option 2
3+
fileSuggest: "[[Other/Example Notes/Example Note with Embeds.md|Example Note with Embeds]]"
4+
fileSuggest2: "[[Example Note with Embeds]]"
5+
fileSuggest3: Example Note with Embeds
56
---
67

78
### Simple Suggester
@@ -23,5 +24,9 @@ INPUT[suggester(optionQuery(#example-note), showcase):fileSuggest]
2324
```
2425

2526
```meta-bind
26-
INPUT[suggester(optionQuery(#example-note), useLinks(false), showcase):fileSuggest2]
27+
INPUT[suggester(optionQuery(#example-note), useLinks(partial), showcase):fileSuggest2]
28+
```
29+
30+
```meta-bind
31+
INPUT[suggester(optionQuery(#example-note), useLinks(false), showcase):fileSuggest3]
2732
```

src/config/FieldConfigs.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,12 @@ export const InputFieldConfigs: Record<InputFieldType, InputFieldConfig> = {
185185
},
186186
} as const;
187187

188+
export enum UseLinksInputFieldArgumentValue {
189+
TRUE = 'true',
190+
PARTIAL = 'partial',
191+
FALSE = 'false',
192+
}
193+
188194
export type InputFieldArgumentConfig = FieldArgumentConfig<InputFieldArgumentType, InputFieldType>;
189195

190196
export const InputFieldArgumentConfigs: Record<InputFieldArgumentType, InputFieldArgumentConfig> = {
@@ -418,7 +424,11 @@ export const InputFieldArgumentConfigs: Record<InputFieldArgumentType, InputFiel
418424
[
419425
{
420426
name: 'value',
421-
allowed: ['true', 'false'],
427+
allowed: [
428+
UseLinksInputFieldArgumentValue.TRUE,
429+
UseLinksInputFieldArgumentValue.PARTIAL,
430+
UseLinksInputFieldArgumentValue.FALSE,
431+
],
422432
description: '',
423433
},
424434
],

src/fields/fieldArguments/inputFieldArguments/arguments/UseLinksInputFieldArgument.ts

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,65 @@
11
import { AbstractInputFieldArgument } from '../AbstractInputFieldArgument';
22
import { type ParsingResultNode } from '../../../../parsers/nomParsers/GeneralNomParsers';
3-
import { type InputFieldArgumentConfig, InputFieldArgumentConfigs } from '../../../../config/FieldConfigs';
3+
import {
4+
type InputFieldArgumentConfig,
5+
InputFieldArgumentConfigs,
6+
UseLinksInputFieldArgumentValue,
7+
} from '../../../../config/FieldConfigs';
8+
import { ErrorLevel, MetaBindArgumentError } from '../../../../utils/errors/MetaBindErrors';
9+
import { DocsUtils } from '../../../../utils/DocsUtils';
10+
import { expectType, toEnumeration } from '../../../../utils/Utils';
11+
12+
export function applyUseLinksArgument(
13+
filePath: string,
14+
fileName: string,
15+
value: UseLinksInputFieldArgumentValue,
16+
): string {
17+
if (value === UseLinksInputFieldArgumentValue.TRUE) {
18+
return `[[${filePath}|${fileName}]]`;
19+
} else if (value === UseLinksInputFieldArgumentValue.PARTIAL) {
20+
return `[[${fileName}]]`;
21+
} else {
22+
expectType<UseLinksInputFieldArgumentValue.FALSE>(value);
23+
return `${fileName}`;
24+
}
25+
}
426

527
export class UseLinksInputFieldArgument extends AbstractInputFieldArgument {
6-
value: boolean = true;
28+
value: UseLinksInputFieldArgumentValue = UseLinksInputFieldArgumentValue.TRUE;
729

830
_parseValue(value: ParsingResultNode[]): void {
9-
this.value = value[0] === undefined || value[0]?.value.toLowerCase() === 'true';
31+
/* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */
32+
33+
const v = value[0]?.value.toLowerCase();
34+
if (v === undefined) {
35+
this.value = UseLinksInputFieldArgumentValue.TRUE;
36+
return;
37+
}
38+
39+
if (
40+
v === UseLinksInputFieldArgumentValue.TRUE ||
41+
v === UseLinksInputFieldArgumentValue.PARTIAL ||
42+
v === UseLinksInputFieldArgumentValue.FALSE
43+
) {
44+
this.value = v;
45+
return;
46+
}
47+
48+
throw new MetaBindArgumentError({
49+
errorLevel: ErrorLevel.WARNING,
50+
effect: 'failed to set value for input field argument',
51+
cause: `value of argument 'useLinks' must be one of ${toEnumeration(
52+
[
53+
UseLinksInputFieldArgumentValue.TRUE,
54+
UseLinksInputFieldArgumentValue.PARTIAL,
55+
UseLinksInputFieldArgumentValue.FALSE,
56+
],
57+
x => `'${x}'`,
58+
', ',
59+
'or',
60+
)}`,
61+
docs: [DocsUtils.linkToInputFieldArgument(this.getConfig().type)],
62+
});
1063
}
1164

1265
public getConfig(): InputFieldArgumentConfig {

src/fields/inputFields/fields/Suggester/SuggesterModalHelper.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
import { type MBLiteral } from '../../../../utils/Literal';
22
import { type DataArray, type DataviewApi, type Literal } from 'obsidian-dataview';
3-
import { InputFieldArgumentType } from '../../../../config/FieldConfigs';
3+
import { InputFieldArgumentType, UseLinksInputFieldArgumentValue } from '../../../../config/FieldConfigs';
44
import { type OptionInputFieldArgument } from '../../../fieldArguments/inputFieldArguments/arguments/OptionInputFieldArgument';
55
import { type OptionQueryInputFieldArgument } from '../../../fieldArguments/inputFieldArguments/arguments/OptionQueryInputFieldArgument';
66
import { Notice } from 'obsidian';
77
import { SuggesterInputModal } from './SuggesterInputModal';
88
import { type SuggesterLikeIFP, SuggesterOption } from './SuggesterHelper';
99
import type MetaBindPlugin from '../../../../main';
1010
import { getDataViewPluginAPI } from '../../../../utils/ObsUtils';
11+
import { applyUseLinksArgument } from '../../../fieldArguments/inputFieldArguments/arguments/UseLinksInputFieldArgument';
12+
import { z } from 'zod';
1113

1214
export function getSuggesterOptions(
1315
plugin: MetaBindPlugin,
1416
filePath: string,
1517
optionArgs: OptionInputFieldArgument[],
1618
optionQueryArgs: OptionQueryInputFieldArgument[],
17-
useLinks: boolean,
19+
useLinks: UseLinksInputFieldArgumentValue,
1820
): SuggesterOption<MBLiteral>[] {
1921
const options: SuggesterOption<MBLiteral>[] = [];
2022

@@ -35,22 +37,24 @@ export function getSuggesterOptions(
3537
return options;
3638
}
3739

40+
const fileValidator = z.object({
41+
name: z.string().min(1),
42+
path: z.string().min(1),
43+
});
44+
3845
for (const suggestOptionsQueryArgument of optionQueryArgs) {
3946
const result: DataArray<Record<string, Literal>> = dv.pages(suggestOptionsQueryArgument.value, filePath);
4047

4148
result.forEach((file: Record<string, Literal>) => {
4249
try {
43-
// FIXME: this is unsafe, maybe add validation
4450
const dvFile = file.file as { name: string; path: string };
4551

46-
if (useLinks) {
47-
options.push(
48-
new SuggesterOption<MBLiteral>(`[[${dvFile.path}|${dvFile.name}]]`, `file: ${dvFile.name}`),
49-
);
50-
} else {
51-
// console.log(tFile);
52-
options.push(new SuggesterOption<MBLiteral>(dvFile.name, `file: ${dvFile.name}`));
52+
if (!fileValidator.safeParse(dvFile).success) {
53+
return;
5354
}
55+
56+
const link = applyUseLinksArgument(dvFile.path, dvFile.name, useLinks);
57+
options.push(new SuggesterOption<MBLiteral>(link, `file: ${dvFile.name}`));
5458
} catch (e) {
5559
console.warn('meta-bind | error while computing suggest options', e);
5660
}
@@ -67,14 +71,14 @@ export function getSuggesterOptionsForInputField(
6771
): SuggesterOption<MBLiteral>[] {
6872
const optionArgs = inputField.base.getArguments(InputFieldArgumentType.OPTION);
6973
const optionQueryArgs = inputField.base.getArguments(InputFieldArgumentType.OPTION_QUERY);
70-
const useLinksArgs = inputField.base.getArgument(InputFieldArgumentType.USE_LINKS);
74+
const useLinksArg = inputField.base.getArgument(InputFieldArgumentType.USE_LINKS);
7175
// in not present, we treat the use links argument as true
7276
return getSuggesterOptions(
7377
plugin,
7478
inputField.base.getFilePath(),
7579
optionArgs,
7680
optionQueryArgs,
77-
useLinksArgs === undefined || useLinksArgs.value,
81+
useLinksArg === undefined ? UseLinksInputFieldArgumentValue.TRUE : useLinksArg.value,
7882
);
7983
}
8084

src/utils/Utils.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,30 @@ export function openURL(link: string): void {
167167
}
168168

169169
export type Tuple<T> = [T, ...T[]];
170+
171+
export function toEnumeration(
172+
arr: string[],
173+
map: (x: string) => string,
174+
separator: string = ', ',
175+
lastSeparator: string = 'and',
176+
): string {
177+
if (arr.length === 0) {
178+
return '';
179+
}
180+
181+
arr = arr.map(map);
182+
183+
if (arr.length === 1) {
184+
return arr[0];
185+
}
186+
187+
if (arr.length === 2) {
188+
return `${arr[0]} ${lastSeparator} ${arr[1]}`;
189+
}
190+
191+
return `${arr.slice(0, -1).join(separator)} ${lastSeparator} ${arr.slice(-1)}`;
192+
}
193+
194+
export function expectType<T>(_: T): void {
195+
// no op
196+
}

0 commit comments

Comments
 (0)