Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 63 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,77 @@ The plugin allows you to set a template note that gets added to the end of any n
The plugin also offers simple template tags, for example `{{ title }}`, which will be replaced by the title of the media being imported.
Note that template tags are surrounded by two curly braces and spaces. The spaces inside the curly braces are important!

For arrays, there are two special ways of displaying them:
**Array Operators**

For arrays, there are several operators available for different formatting needs:

Body Text Operators (no quotes)

- `{{ LIST:variable_name }}` - Unlinked list:

- using `{{ LIST:variable_name }}` will result in:
```
- element 1
- element 2
- element 3
- ...
```
- using `{{ ENUM:variable_name }}` will result in:

- `{{ LIST:[[variable_name]] }}` - Wikilinked list:

```
- [[element 1]]
- [[element 2]]
- [[element 3]]
```

- `{{ ENUM:variable_name }}` - Unlinked comma-separated:

```
element 1, element 2, element 3
```

- `{{ ENUM:[[variable_name]] }}` - Wikilinked comma-separated:
```
[[element 1]], [[element 2]], [[element 3]]
```
element 1, element 2, element 3, ...

YAML Frontmatter Operators (with quotes)

- `{{ LISTYAML:variable_name }}` - Unlinked YAML list:

```yaml
variable_name:
- element 1
- element 2
- element 3
```

- `{{ LISTYAML:[[variable_name]] }}` - Wikilinked YAML list (recognized by Obsidian):

```yaml
variable_name:
- '[[element 1]]'
- '[[element 2]]'
- '[[element 3]]'
```

- `{{ ENUMYAML:variable_name }}` - Comma-separated for YAML (no wikilink support):
```yaml
variable_name: element 1, element 2, element 3
```

Single Element Operators

- `{{ FIRST:variable_name }}` - Returns the first element of an array
- `{{ FIRST:[[variable_name]] }}` - Returns the first element as a wikilink: `[[element 1]]`
- `{{ LAST:variable_name }}` - Returns the last element of an array
- `{{ LAST:[[variable_name]] }}` - Returns the last element as a wikilink: `[[element 3]]`

**Wikilink Support**

Wrap the variable name in double brackets `[[variable_name]]` to create wikilinks for array elements. This works with `LIST`, `LISTYAML`, `ENUM`, `FIRST`, and `LAST` operators. Note that `ENUMYAML` does not support wikilinks - the `[[]]` syntax will be ignored.

**Important:** Use `YAML` variants (`LISTYAML`, `ENUMYAML`) in frontmatter and regular variants (`LIST`, `ENUM`) in the note body.

Available variables that can be used in template tags are any front-matter properties.

I also published my own templates [here](https://github.com/mProjectsCode/obsidian-media-db-templates).
Expand Down Expand Up @@ -125,7 +182,7 @@ Now you select the result you want, and the plugin will cast its magic, creating
| [Wikipedia](https://en.wikipedia.org/wiki/Main_Page) | The Wikipedia API allows access to all Wikipedia articles. | wiki articles | No | None | No |
| [Steam](https://store.steampowered.com/) | The Steam API offers information on all Steam games. | games | No | 10000 per day | No |
| [Open Library](https://openlibrary.org) | The OpenLibrary API offers metadata for books | books | No | Cover access is rate-limited when not using CoverID or OLID by max 100 requests/IP every 5 minutes. This plugin uses OLID, so there shouldn't be a rate limit. | No |
| Comic Vine | The Comic Vine API offers metadata for comic books | comicbooks | Yes, by making an account [here](https://comicvine.gamespot.com/login-signup/) and going to the [api section](https://comicvine.gamespot.com/api/) of the site | 200 requests per resource, per hour. There is also a velocity detection to prevent malicious use. If too many requests are made per second, you may receive temporary blocks to resources. | No |
| [Comic Vine](https://comicvine.gamespot.com/) | The Comic Vine API offers metadata for comic books | comicbooks | Yes, by making an account [here](https://comicvine.gamespot.com/login-signup/) and going to the [api section](https://comicvine.gamespot.com/api/) of the site | 200 requests per resource, per hour. There is also a velocity detection to prevent malicious use. If too many requests are made per second, you may receive temporary blocks to resources. | No |
| [VNDB](https://vndb.org/) | The VNDB API offers metadata for visual novels | games | No | 200 requests per 5 minutes | Yes |
| [Boardgame Geek](https://boardgamegeek.com) | The Boardgame Geek API offers metadata for boardgames | boardgames | Yes, by making an account [here](https://boardgamegeek.com/join/) and then [requesting an application token](https://boardgamegeek.com/applications) | Exact usage limits are still undetermined | No |

Expand Down
Binary file added bun.lockb
Binary file not shown.
4 changes: 2 additions & 2 deletions packages/obsidian/src/settings/Settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ export class MediaDbSettingTab extends PluginSettingTab {
apiKeyGroup.addSetting(
setting =>
void setting
.setName('OMDb API key')
.setName('OMDb API Key')
.setDesc('API key for "www.omdbapi.com".')
.addComponent(el => {
const component = new SecretComponent(this.app, el);
Expand Down Expand Up @@ -613,7 +613,7 @@ export class MediaDbSettingTab extends PluginSettingTab {
apiKeyGroup.addSetting(
setting =>
void setting
.setName('Moby Games key')
.setName('Moby Games Key')
.setDesc('API key for "www.mobygames.com".')
.addComponent(el => {
const component = new SecretComponent(this.app, el);
Expand Down
59 changes: 54 additions & 5 deletions packages/obsidian/src/utils/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ function replaceTag(match: string, mediaTypeModel: MediaTypeModel, ignoreUndefin
tag = tag.trim();

const parts = tag.split(':');

if (parts.length === 1) {
const path = parts[0].split('.');

const obj = traverseMetaData(path, mediaTypeModel);

if (obj === undefined) {
Expand All @@ -47,9 +47,18 @@ function replaceTag(match: string, mediaTypeModel: MediaTypeModel, ignoreUndefin
return obj?.toString() ?? 'null';
} else if (parts.length === 2) {
const operator = parts[0];
let pathString = parts[1];

const path = parts[1].split('.');
// Check if the path is wrapped in [[]] for wikilinks
const wikilinkMatch = /^\[\[(.+?)\]\]$/.exec(pathString);
const useWikilinks = !!wikilinkMatch;

// Extract the actual path (remove [[ ]] if present)
if (wikilinkMatch) {
pathString = wikilinkMatch[1];
}

const path = pathString.split('.');
const obj = traverseMetaData(path, mediaTypeModel);

if (obj === undefined) {
Expand All @@ -61,26 +70,66 @@ function replaceTag(match: string, mediaTypeModel: MediaTypeModel, ignoreUndefin
return '{{ INVALID TEMPLATE TAG - operator LIST is only applicable on an array }}';
}

return obj.map((e: unknown) => `- ${e}`).join('\n');
if (useWikilinks) {
// LIST with wikilinks: no quotes for body text
return obj.map((e: unknown) => `\n - [[${e}]]`).join('');
} else {
return obj.map((e: unknown) => `\n - ${e}`).join('');
}
} else if (operator === 'LISTYAML') {
if (!Array.isArray(obj)) {
return '{{ INVALID TEMPLATE TAG - operator LISTYAML is only applicable on an array }}';
}

if (useWikilinks) {
// LISTYAML with wikilinks: quoted for frontmatter
return obj.map((e: unknown) => `\n - "[[${e}]]"`).join('');
} else {
return obj.map((e: unknown) => `\n - ${e}`).join('');
}
} else if (operator === 'ENUM') {
if (!Array.isArray(obj)) {
return '{{ INVALID TEMPLATE TAG - operator ENUM is only applicable on an array }}';
}

if (useWikilinks) {
// ENUM with wikilinks: no quotes for body text
return obj.map((e: unknown) => `[[${e}]]`).join(', ');
} else {
return obj.join(', ');
}
} else if (operator === 'ENUMYAML') {
if (!Array.isArray(obj)) {
return '{{ INVALID TEMPLATE TAG - operator ENUMYAML is only applicable on an array }}';
}
// ENUMYAML - always comma-separated, no wikilinks support and [[]] syntax is simply ignored since they are not valid in comma-separated YAML values
return obj.join(', ');
} else if (operator === 'FIRST') {
if (!Array.isArray(obj)) {
return '{{ INVALID TEMPLATE TAG - operator FIRST is only applicable on an array }}';
}

const first = obj[0] as unknown;
return first?.toString() ?? 'null';
const value = first?.toString() ?? 'null';

if (useWikilinks && value !== 'null') {
return `[[${value}]]`;
} else {
return value;
}
} else if (operator === 'LAST') {
if (!Array.isArray(obj)) {
return '{{ INVALID TEMPLATE TAG - operator LAST is only applicable on an array }}';
}

const last = obj[obj.length - 1] as unknown;
return last?.toString() ?? 'null';
const value = last?.toString() ?? 'null';

if (useWikilinks && value !== 'null') {
return `[[${value}]]`;
} else {
return value;
}
}

return `{{ INVALID TEMPLATE TAG - unknown operator ${operator} }}`;
Expand Down
Loading