56 | …
57 | ```
58 |
59 | which can then be styled using “Style Snippets” like:
60 |
61 | ```css
62 | .obsidian-metatable::part(tag) {
63 | background-color: pink;
64 | }
65 |
66 | .obsidian-metatable::part(tag):hover {
67 | background-color: var(--text-accent-hover);
68 | }
69 |
70 | .obsidian-metatable::part(tag important) {
71 | color: white;
72 | background-color: tomato;
73 | }
74 |
75 | .obsidian-metatable::part(tag example) {
76 | color: black;
77 | background-color: deepskyblue;
78 | }
79 | ```
80 |
81 |
82 | ## Conclusion
83 |
84 | The use of the [::part element] provides a well balanced compromise between
85 | flexibility and abstraction. The only potential concern is the fact that it is
86 | a working draft rather than a well established specification which is highly
87 | mitigated by the fact that Obsidian is a controlled environment using Chromium
88 | (via Electron).
89 |
90 |
91 | [Web Components]: https://developer.mozilla.org/en-US/docs/Web/Web_Components
92 | [Custom Properties]: https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties
93 | [::part pseudo-element]: https://developer.mozilla.org/en-US/docs/Web/CSS/::part
94 | [Tag Pills]: https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/13
95 | [slot element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot
96 |
--------------------------------------------------------------------------------
/docs/decision_log/2022-08-29_sidebar_view.md:
--------------------------------------------------------------------------------
1 | ---
2 | creation_date: 2022-08-29
3 | decision_date: 2022-08-29
4 | decision_outcome: accepted
5 | tags: [decision]
6 | ---
7 | # Add a sidebar view
8 |
9 | Since the introduction of Live Preview, the plugin has lost usefulness given
10 | that most of the time is spent in Editing Mode and very rarely in Reading Mode.
11 |
12 | ## Proposal
13 |
14 | Add a Metatable view that renders on the right hand sidebar.
15 |
16 | ## Outcome
17 |
18 | Adding a new view given how the plugin works is low effort. Some of the
19 | original behaviour might feel unnecessary though, for example the ability to
20 | collapse/expand.
21 |
22 |
23 | ## Conclusion
24 |
25 | Having the sidebar, a ribbon icon and a command bring enough value that makes
26 | the Reading Mode irrelevant.
27 |
--------------------------------------------------------------------------------
/docs/decision_log/2022-08-29_solidjs.md:
--------------------------------------------------------------------------------
1 | ---
2 | creation_date: 2022-08-29
3 | decision_date: 2022-08-29
4 | decision_outcome: accepted
5 | tags: [decision]
6 | ---
7 | # Use Solid.js for the UI
8 |
9 | [Solid.js] is a library for building reactive user interfaces in TypeScript and
10 | JSX without the need for a virtual DOM layer.
11 |
12 | ## Proposal
13 |
14 | Use [Solid.js] instead of plain DOM to improve the readability and
15 | maintainability of the plugin whilst maintaining a low footprint at runtime.
16 |
17 | ## Outcome
18 |
19 | The migration has been seamless bringing clarity in terms of UI
20 | responsibilities.
21 |
22 | From a performance point of view no tests have shown anything to be concerned
23 | about which aligns with the expected minimal footprint advertised by the
24 | library.
25 |
26 |
27 | ## Conclusion
28 |
29 | Using [Solid.js] dramatically increases readability as well as state management
30 | reasoning at a very low cost.
31 |
32 |
33 |
34 | [Solid.js]: https://www.solidjs.com/
35 |
--------------------------------------------------------------------------------
/docs/examples/aliases.md:
--------------------------------------------------------------------------------
1 | ---
2 | aliases: alpha, beta, gamma
3 | tags: foo, bar
4 | ---
--------------------------------------------------------------------------------
/docs/examples/all_in_one.md:
--------------------------------------------------------------------------------
1 | ---
2 | aliases: [aio, embedded]
3 | tags: [example, embed]
4 | ---
5 | # All in one example
6 |
7 |
8 | ![[basic]]
9 |
10 | ![[links]]
11 |
12 | ![[skip_key]]
13 |
14 | ![[filtered_keys]]
15 |
16 | ![[null_values]]
--------------------------------------------------------------------------------
/docs/examples/anatomy.md:
--------------------------------------------------------------------------------
1 | ---
2 | scalar: Lorem ipsum
3 | list: [alpha, beta, gamma]
4 | set: {x: 1, y: 2}
5 | ---
6 | # Anatomy example
7 |
8 | To see it at work, open the Preferences, go to Appearance and select the `anatomy` CSS snippet and open the [[sidebar_metatable]].
9 |
10 | This example illustrates the anatomy of a metatable tree.
--------------------------------------------------------------------------------
/docs/examples/basic.md:
--------------------------------------------------------------------------------
1 | ---
2 | string: Lorem ipsum
3 | number: 11
4 | boolean: true
5 | nil: null
6 | date: 2022-08-27
7 | in-link: %index%
8 | out-link: https://www.seachess.net
9 | list: [alpha, beta, gamma]
10 | set: {x: 1, y: 2}
11 | tags: [example, basic, valid_yaml]
12 | ---
13 | # Basic example
14 |
15 | This example illustrates a frontmatter with different types:
16 |
17 | - string
18 | - number
19 | - boolean
20 | - null
21 | - date (only accepts ISO dates)
22 | - lists (i.e. arrays)
23 | - sets (i.e. objects)
24 | - tags. Tags are a special kind of array.
--------------------------------------------------------------------------------
/docs/examples/custom_properties.md:
--------------------------------------------------------------------------------
1 | ---
2 | date: 2022-09-02
3 | is_example: true
4 | ultimate_question: 42
5 | score: null
6 | website: https://www.seachess.net
7 | summary: An example to showcase customisation.
8 | tags: [test, example, avocado]
9 | ---
10 | # Custom properties
11 |
12 | To see this example at work, open the Preferences, go to Appearance and select the `custom_properties` CSS snippet.
13 |
--------------------------------------------------------------------------------
/docs/examples/filtered_keys.md:
--------------------------------------------------------------------------------
1 | ---
2 | guacamole: green
3 | metatable: false
4 | frontmatter: 42
5 | tags: [one, two, three]
6 | ---
7 | # Filtered keys
8 |
9 | This example shows the behaviour of the [[configuration#Filter | filter settings]]. When the “filter mode” is **ignore**, only the keys `guacamole` and `tags` should be displayed and when the value is **keep**, only `metatable` and `frontmatter` should be kept.
10 |
11 | This example assumes that the “filter keys” setting has the default values.
12 |
13 | If you modify the example with the following frontmatter you'll see that filtering is honoured regardless of how deep into the structure keys are found.
14 |
15 | ```yaml
16 | guacamole: green
17 | metatable: false
18 | frontmatter: 42
19 | deep:
20 | frontmatter: wave
21 | deeper:
22 | foo: 1
23 | bar:
24 | metatable: false
25 | value: qux
26 | tags: [one, two, three]
27 | ```
--------------------------------------------------------------------------------
/docs/examples/links.md:
--------------------------------------------------------------------------------
1 | ---
2 | url: https://www.obsidian.md
3 | local:
4 | - ../examples/null_values
5 | - ./filtered_keys
6 | - ./tests/title with spaces
7 | - ./tests/title%20with%20spaces
8 | wiki:
9 | - "[[autolinks]]"
10 | - "[[title with spaces]]"
11 | - "[[autolinks | Auto Links]]"
12 | frontmatter:
13 | - %autolinks%
14 | - %title with spaces%
15 | - %autolinks|Autolinks%
16 | md:
17 | - "[Basic configuration](../sections/configuration)"
18 | - "[Missing page](../missing)"
19 | - "[A remote page](https://www.obsidian.md)"
20 | - "[test spaces](../tests/title with spaces)"
21 | - "[changelog](changelog.md)"
22 | ---
23 | # Links
24 |
25 | **This example requires the [[configuration#Autolinks | Autolinks]] setting enabled.**
26 |
--------------------------------------------------------------------------------
/docs/examples/null_values.md:
--------------------------------------------------------------------------------
1 | ---
2 | explicit: null
3 | commented: # this is a comment
4 | missing-value:
5 | empty-string: ""
6 | empty-list: []
7 | empty-set: {}
8 | ---
9 | # Null values
10 |
11 | This example shows every possible type of null value:
12 |
13 | - An explicit `null` .
14 | - A commented value.
15 | - An empty string, including a missing value.
16 | - An empty list.
17 | - An empty set.
--------------------------------------------------------------------------------
/docs/examples/parts.md:
--------------------------------------------------------------------------------
1 | ---
2 | string: Lorem ipsum
3 | number: 10
4 | boolean: true
5 | nil: null
6 | date: 2022-08-27
7 | internal-link: %customising_parts%
8 | external-link: https://www.seachess.net
9 | list: [alpha, beta, gamma]
10 | set: {x: 1, y: 2}
11 | tags: [test, important, example]
12 | ---
13 | # Parts
14 |
15 | This example demontrates the topic discussed in [[customising_parts]].
16 |
17 | To see this example at work, open the Preferences, go to Appearance and select the `parts` CSS snippet.
18 |
19 | You might also be interested in the [[examples/anatomy]] and [[custom_properties]].
--------------------------------------------------------------------------------
/docs/examples/skip_key.md:
--------------------------------------------------------------------------------
1 | ---
2 | metatable: true
3 | foo: never displayed
4 | bar: also not displayed
5 | ---
6 | # Skip key
7 |
8 | This example will not display the inline metatable when the “skip key” seeting is set to `metatable` and the frontmatter has a `metatable: true` in it.
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | codebase: "[GitHub](https://github.com/arnau/obsidian-metatable)"
3 | tags: [index]
4 | ---
5 | # Obsidian Metatable
6 |
7 | **Obsidian Metatable** is an [Obsidian](https://www.obsidian.md) plugin to display the full frontmatter block instead of just the list of tags and aliases.
8 |
9 | ![[basic.png]]
10 |
11 | ## Table of contents
12 |
13 | 1. [[installation]]
14 | 2. [[getting_started]]
15 | 3. [[configuration]]
16 | 4. [[customising_colours_and_symbols]]
17 | 5. [[customising_parts]]
18 | 6. [[tags]]
19 | 7. [[autolinks]]
20 | 8. [[sections/anatomy]]
21 | 10. [[changelog]]
22 | 11. [[decision_log]]
23 |
24 |
25 | ## Licence
26 |
27 | Arnau Siches under the MIT License.
28 |
--------------------------------------------------------------------------------
/docs/screenshots/anatomy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/arnau/obsidian-metatable/df6b59af4b57e2219ef6c5e8e5bd956356da116e/docs/screenshots/anatomy.png
--------------------------------------------------------------------------------
/docs/screenshots/basic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/arnau/obsidian-metatable/df6b59af4b57e2219ef6c5e8e5bd956356da116e/docs/screenshots/basic.png
--------------------------------------------------------------------------------
/docs/screenshots/null_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/arnau/obsidian-metatable/df6b59af4b57e2219ef6c5e8e5bd956356da116e/docs/screenshots/null_settings.png
--------------------------------------------------------------------------------
/docs/sections/anatomy.md:
--------------------------------------------------------------------------------
1 | ---
2 | previous: %autolinks%
3 | tags: [section, advanced]
4 | ---
5 | # Anatomy
6 |
7 | The anatomy of a metatable reflects the hierarchical recursive structure found in YAML.
8 |
9 | Example: [[examples/anatomy]]
10 |
11 | ![[anatomy.png]]
12 |
13 | ## Root
14 |
15 | The root part (gold) as its name suggests is a wrapper around the whole metatable section, including its label.
16 |
17 | Note that the metatable is expected to start as a [[#Set]] but technically speaking it can be anything YAML allows for.
18 |
19 |
20 | ## Set
21 |
22 | The set part (light pink) wraps a set of [[#Member]] parts.
23 |
24 |
25 | ## Member
26 |
27 | The member part (brown) wraps a pair of [[#Key]], [[#Value]] parts.
28 |
29 |
30 | ## Key
31 |
32 | The key part (sky blue) contains the label of a set member.
33 |
34 | When the [[#Value]] contains either a [[#Set]] or a [[#List]], the key also includes a `toggle` part as well as either `expanded` or `collapsed`.
35 |
36 |
37 | ## Value
38 |
39 | The value part (light blue) contains the value of a set member. It can contain either a scalar value (string, number, null, date, boolean) or a collection ([[#Set]], [[#List]]).
40 |
41 | Whe the value is a collection it also contains a _marker_ which is expected to be displayed when the key toggle is collapsed.
42 |
43 |
44 | ## List
45 |
46 | The list part (light pink) wraps a set of [[#List item]] parts.
47 |
48 |
49 | ## List item
50 |
51 | The list item part (deep pink) behaves like the [[#Value]] part.
52 |
53 |
54 | ## Tag
55 |
56 | A tag part contains the text for the given tag. See [[sections/tags]] for a more in depth explanation of the particularities of tags.
--------------------------------------------------------------------------------
/docs/sections/autolinks.md:
--------------------------------------------------------------------------------
1 | ---
2 | previous: %customising_parts%
3 | next: %anatomy%
4 | tags: [section]
5 | ---
6 | # Autolinks
7 |
8 | The term “autolinks” refers to the [[configuration#Autolinks | Autolinks setting]] which, when enabled, transforms certain patterns into links.
9 |
10 | Check the [[links]] example to see them at work.
11 |
12 |
13 | ## URL
14 |
15 | Any value that is a valid HTTP or HTTPS [URLs](https://developer.mozilla.org/en-US/docs/Web/API/URL) such as `https://www.seachess.net`.
16 |
17 | It also recognises:
18 |
19 | - [Evernote](https://evernote.com/) links using the `evernote:` protocol.
20 | - [Obsidian](https://www.obsidian.md/) links using the `obsidian:` protocol.
21 | - [Zotero](https://www.zotero.org/) links using the `zotero:` protocol. Links are expected to follow a pattern such as `zotero://select/items/@citekey` or `zotero://open-pdf/...`. When used with the [obsidian-citation-plugin](https://github.com/hans/obsidian-citation-plugin), the variable `{{zoteroSelectURI}}` can be used to open the linked citation directly.
22 |
23 |
24 | ## Local
25 |
26 | Any value starting with `./` or `../` is considered a local link. For example, `./projects/obsidian-metatable` will link to the `obsidian-metatable.md` under the `projects` folder.
27 |
28 |
29 | ## Markdown
30 |
31 | Any value of the form `[label](url)` where the URL is a [valid URL](#url) or a [valid local URL](#local).
32 |
33 |
34 | ## Wiki
35 |
36 | Any value starting with `[[` and ending with `]]` is considered a wiki link. The behaviour should be the same with any other wikilink you would write in Markdown.
37 |
38 | **Warning**: Square brackets `[]` in YAML are reserved for defining arrays so in order to actually use wikilinks you have to tell YAML that it's a string.
39 |
40 | For example,
41 |
42 | ```yaml
43 | quoted: "[[basic-alt]]"
44 | long-string: >-
45 | [[target]]
46 | ```
47 |
48 | You can also customise the text displayed by using the following form:
49 |
50 | ```
51 | [[target|Text to display]]
52 | ```
53 |
54 |
55 | ## Frontmatter
56 |
57 | Any value starting and ending with `%` is considered a frontmatter link. The behaviour is the same as per wiki links.
58 |
59 | **Warning**: This format is non-standard. But it's more convenient than wiki links.
--------------------------------------------------------------------------------
/docs/sections/configuration.md:
--------------------------------------------------------------------------------
1 | ---
2 | previous: %getting_started%
3 | next: %customising_colours_and_symbols%
4 | tags: [section]
5 | ---
6 | # Configuration
7 |
8 | **Note**: Most changes in configuration will require you to reopen the documents you have opened to be able to see their effect.
9 |
10 | You should find the Metatable settings section by opening the Obsidian Preferences and scrolling down the left sidebar until you see the Community Plugins section.
11 |
12 |
13 | ## Expansion level
14 |
15 | This option lets you choose whether the metatable is fully collapsed, fully expanded or something in between.
16 |
17 | This option is most useful if you use the in-document metatable and you have large sets of metadata.
18 |
19 | Possible values:
20 |
21 | - Fully expanded: Everything is visible.
22 | - Collapse leafs: The complex leafs (lists and sets) are collapsed.
23 | - Collapse all: TODO
24 | - Collapse root: The Metatable root is collapsed.
25 |
26 |
27 | ## Skip key
28 |
29 | This option lets you define a key that, when defined in the frontmatter as `true` it makes the [[inline_metatable]] to not be displayed at all.
30 |
31 | By default the skip key is `metatable` so the following frontmatter would not be displayed at all.
32 |
33 | ```yaml
34 | metatable: true
35 | foo: never displayed
36 | bar: also not displayed
37 | ```
38 |
39 | **Warning**: This option has no effect on the [[sidebar_metatable]].
40 |
41 |
42 | ## Null values
43 |
44 | For the purpose of the metatable, a "null value" is one of the following:
45 |
46 | - An explicit `null` value.
47 | - A commented value.
48 | - An empty string, including a missing value.
49 | - An empty list.
50 | - An empty set.
51 |
52 | Example: [[null_values]]
53 |
54 | Null values can be configured in two ways: ignoring them or displaying the with a custom value.
55 |
56 | ### Ignore null values
57 |
58 | This switch is disabled by default. When enabled it never displays any member of the metatable with a null value.
59 |
60 | ### Custom null value
61 |
62 | This text is empty by default. When filled in, every null value is replaced with it.
63 |
64 |
65 | ## Filter
66 |
67 | The filter settings let you control which keys should never be displayed or the keys that should only be displayed according to the filter mode.
68 |
69 | Example: [[filtered_keys]]
70 |
71 | ### Filter mode
72 |
73 | This option lets you choose whether the filtering is either **ignore** or **keep**. By default the mode is **ignore**.
74 |
75 | - **Ignore**: Any key in the “filter keys” list is ignored.
76 | - **Keep**: Any key not in the “filter keys” list is ignored.
77 |
78 | ### Filter keys
79 |
80 | This option lets you define the list of keys that should be kept or ignored by the “filter mode”.
81 |
82 | By default the values are `metatable` and `frontmatter`.
83 |
84 |
85 | ## Autolinks
86 |
87 | This option transforms certain value patterns into actual links. This option is disabled by default.
88 |
89 | Example: [[links]]
90 |
91 | Available patterns:
92 |
93 | - **URL**. Any URL-like value.
94 | - **Local**. Any value starting with `./` or `../`.
95 | - **Markdown**. Any value like a markdown link.
96 | - **Wiki**. Any value surrounded by `[[` and `]]`.
97 | - **Frontmatter**. Any value surrounded by `%`.
98 |
99 | You can find a full explanation for each pattern in [[autolinks]].
100 |
101 | ## Naked mode
102 |
103 | This option lets you choose whether to sandbox the metatable widget using [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM). The default is to have the sandbox enabled.
104 |
105 | If you enable the naked mode no default CSS will be applied and will be your responsibility or the theme you use to style the metatable correctly.
--------------------------------------------------------------------------------
/docs/sections/customising_colours_and_symbols.md:
--------------------------------------------------------------------------------
1 | ---
2 | previous: %configuration%
3 | next: %customising_parts%
4 | tags: [section]
5 | ---
6 | # Customising colours and symbols
7 |
8 | You can customise both colours and symbols using [CSS custom properties](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties).
9 |
10 | There are two possible scopes to customise, the [[inline_metatable]] and the [[sidebar_metatable]].
11 |
12 | The [[inline_metatable]] uses the `.obsidian-metatable` CSS class whilst the [[sidebar_metatable]] uses the `.obsidian-metatable-sidebar`.
13 |
14 | Example: [[custom_properties]].
15 |
16 | ## Global palette
17 |
18 | The global palette is a small set of custom properties which the rest depend on.
19 |
20 | ### Fonts
21 |
22 | ```css
23 | --metatable-font-family
24 | --metatable-font-size
25 | ```
26 |
27 |
28 | ### `:focus` pseudo-class
29 |
30 | ```css
31 | --metatable-background-focus
32 | --metatable-text-focus
33 | ```
34 |
35 |
36 | ### Colours
37 |
38 | ```css
39 | /* global */
40 | --metatable-background-primary
41 | --metatable-text-primary
42 |
43 | --metatable-text-secondary
44 | --metatable-background-secondary
45 |
46 | --metatable-background-primary-alt
47 |
48 | /* links */
49 | --metatable-background-link
50 | --metatable-text-link
51 | --metatable-text-link-hover
52 | ```
53 |
54 | ### Deprecated in 0.14.0
55 |
56 | The following custom properties are deprecated and will be removed in future versions.
57 |
58 | - `--metatable-foreground`: Use `--metatable-text-primary` instead.
59 | - `--metatable-background`: Use `--metatable-background-primary` instead.
60 | - `--metatable-key-focus`: Use `--metatable-key-background-focus` instead.
61 | - `--metatable-member-gap`. Use `::part(member)` instead.
62 | - `--metatable-key-border-color`. Use `::part(key)` instead.
63 | - `--metatable-key-border-color-focus`. Use `::part(key)` instead.
64 |
65 |
66 | ## Global symbols
67 |
68 | - `--metatable-collapsed-symbol`
69 | - `--metatable-expanded-symbol`
70 | - `--metatable-mark-symbol`
71 | - `--metatable-tag-symbol`
72 |
73 |
74 | ## Warning
75 |
76 | When the frontmatter YAML can't be parsed, a warning is shown.
77 |
78 | ```css
79 | --metatable-warning-background
80 | --metatable-warning-foreground
81 | --metatable-warning-border
82 | ```
83 |
84 |
85 | ## Parts
86 |
87 | All part properties follow a pattern like:
88 |
89 | ```
90 | --metatable-{where?}-{what}
91 | ```
92 |
93 | For example, `--metatable-external-link-color-hover` has:
94 |
95 | - A `where` equal to `external-link`.
96 | - A `what` equal to `link-color-hover`, which implies it applies to the [CSS :hover pseudo-class](https://developer.mozilla.org/en-US/docs/Web/CSS/:hover).
97 |
98 | Read the [[sections/anatomy]] section to understand how parts compose.
99 |
100 |
101 | ### Root part
102 | ```css
103 | --metatable-root-background
104 | --metatable-root-color
105 | ```
106 |
107 | ### Summary part
108 |
109 | **v0.14.6**: The following custom properties are no longer available:
110 |
111 | ```css
112 | --metatable-summary-background
113 | --metatable-summary-color
114 | --metatable-summary-background-focus
115 | --metatable-summary-color-focus
116 | ```
117 |
118 | ### Set part
119 | ```css
120 | --metatable-set-background
121 | --metatable-set-color
122 | ```
123 |
124 | ### Member part
125 | ```css
126 | --metatable-member-background
127 | --metatable-member-color
128 | ```
129 |
130 | ### Key part
131 | ```css
132 | --metatable-key-background
133 | --metatable-key-color
134 | --metatable-key-background-focus
135 | --metatable-key-color-focus
136 | ```
137 |
138 | ### Value part
139 | ```css
140 | --metatable-value-background
141 | --metatable-value-color
142 | ```
143 |
144 |
145 | ### Tag part
146 |
147 | ```css
148 | --metatable-tag-background
149 | --metatable-tag-color
150 | --metatable-tag-border
151 | --metatable-tag-background-focus
152 | --metatable-tag-color-focus
153 | ```
154 |
155 | ### External link part
156 |
157 | ```css
158 | --metatable-external-link-background
159 | --metatable-external-link-color
160 | --metatable-external-link-background-hover
161 | --metatable-external-link-color-hover
162 | --metatable-external-link-background-focus
163 | --metatable-external-link-color-focus
164 | --metatable-external-link-icon
165 | ```
166 |
167 | ### Internal link part
168 |
169 | ```css
170 | --metatable-internal-link-background
171 | --metatable-internal-link-color
172 | --metatable-internal-link-background-hover
173 | --metatable-internal-link-color-hover
174 | --metatable-internal-link-background-focus
175 | --metatable-internal-link-color-focus
176 | ```
177 |
178 | ### Leaf types
179 |
180 | ```css
181 | --metatable-leaf-number-color
182 | --metatable-leaf-boolean-color
183 | --metatable-leaf-date-color
184 | --metatable-leaf-nil-color
185 | ```
186 |
--------------------------------------------------------------------------------
/docs/sections/customising_parts.md:
--------------------------------------------------------------------------------
1 | ---
2 | previous: %customising_colours_and_symbols%
3 | next: %tags%
4 | tags: [section]
5 | ---
6 | # Customising parts
7 |
8 | Whilst [[customising_colours_and_symbols]] go a long way, it does have limits either shortcomings of the implementation or by design. I these scenarios, parts will allow you to go further.
9 |
10 | It's worth acquainting yourself with the [[sections/anatomy]] of the metatable to see how parts compose.
11 |
12 | When we say “part” we really refer to the [::part pseudo-element](https://developer.mozilla.org/en-US/docs/Web/CSS/::part). So, when we say that there is a “list part” we mean that there is an HTML element with an attribute `part="list"` which can be targeted from CSS using `::part(list)`.
13 |
14 | Note that parts are limited by design so you won't be able to influence children such as links or deep structures in values. If that's what you need, you will have to enable the [[configuration#Naked mode | naked mode]] and style everything yourself.
15 |
16 | Example: [[parts]]
17 |
18 |
19 | ## Parts
20 |
21 | The available parts are:
22 |
23 | - [[#Root and summary]]
24 | - [[#Set member key and value]]
25 | - [[#List and list item]]
26 | - [[#Scalars]]
27 | - [[#Tags]]
28 | - [[#Links]]
29 |
30 |
31 | ## Root and summary
32 |
33 | The root contains the summary and the actual metatable.
34 |
35 | Note that the metatable is expected to start as a [[sections/anatomy#Set]] but technically speaking it can be anything YAML allows for.
36 |
37 | The summary is the header for the metatable, it is a `summary` element for the [[inline_metatable]] and an `h1` element for the [[sidebar_metatable]].
38 |
39 |
40 | ## Set, member, key and value
41 |
42 | A set is composed of members and members are composed of a key and a value. Effectively the same structure as an HTML table where you have a `table` (set), `tr` (member), `th` (key) and `td` (value).
43 |
44 | The structure uses multiple [CSS Grid Layout](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout) to arrange each part in place.
45 |
46 | For example, if you want to give more room to keys and you could remove the grid layout:
47 |
48 | ```css
49 | .obsidian-metatable::part(member) {
50 | display: block;
51 | }
52 |
53 | .obsidian-metatable::part(value) {
54 | margin-left: 20px;
55 | }
56 | ```
57 |
58 | Or, in a extreme case you could start by resetting everything for a part:
59 |
60 | ```css
61 | .obsidian-metatable::part(value) {
62 | all: unset;
63 | }
64 | ```
65 |
66 | Finally, when values contain a collection (either set or list) there is a `marker` part that allows styling the, by default, `...` when the collection is collapsed.
67 |
68 |
69 | ## List and list item
70 |
71 | A list is composed of list items. Effectively an HTML `ul` element with a collection of `li` elements.
72 |
73 | The same logic described for [[#Set member key and value]] apply here.
74 |
75 | Note that although [[#Tags]] are a list, they have different rules and structure. To customise it further you can use the [[#Named Parts]].
76 |
77 | ## Scalars
78 |
79 | Scalar parts are:
80 |
81 | - `string`: Any string not conforming to other more restrictive patterns.
82 | - `number`: Any number as per YAML.
83 | - `null`: Any value as per [[null_values]].
84 | - `link` (and `internal-link`, `external-link`): Any value as per [[autolinks]].
85 | - `isodate`: Any string conforming to an ISO date (e.g. 2022-09-03).
86 |
87 |
88 | ### Tags
89 |
90 | A tag has a `tag` part.
91 |
92 | For example, to reproduce the [Tag Pills](https://forum.obsidian.md/t/meta-post-common-css-hacks/1978/13) with this plugin you would do instead:
93 |
94 | ```css
95 | .obsidian-metatable::part(tag) {
96 | background-color: pink;
97 | }
98 |
99 | .obsidian-metatable::part(tag):hover {
100 | background-color: var(--text-accent-hover);
101 | }
102 |
103 | .obsidian-metatable::part(tag important) {
104 | color: white;
105 | background-color: tomato;
106 | }
107 |
108 | .obsidian-metatable::part(tag example) {
109 | color: black;
110 | background-color: deepskyblue;
111 | }
112 | ```
113 |
114 | ### Links
115 | A link has a `link` part and either a `internal-link` or a `external-link` part.
116 |
117 | ```css
118 | .obsidian-metatable::part(link) {
119 | /* generic link tweaks */
120 | }
121 |
122 | .obsidian-metatable::part(external-link) {
123 | /* external link tweaks */
124 | }
125 |
126 | .obsidian-metatable::part(external-link):hover {
127 | /* external link hover tweaks */
128 | }
129 | ```
130 |
131 |
132 | ## Named Parts
133 |
134 | Both [[#Set member key and value|Sets]] and [[#List and list item|Lists]] have an extra part following the pattern `{collection_type}-{key}`.
135 |
136 | For example, the list for the key `tags` has a `list-tags` part and in turn each list item a `list-item-tags` part.
137 |
138 |
--------------------------------------------------------------------------------
/docs/sections/decision_log.md:
--------------------------------------------------------------------------------
1 | ---
2 | tags: [section]
3 | ---
4 | # Decision log
5 |
6 | The decision log contains the big decisions made to architect and develop this plugin.
7 |
8 | - [[2021-04-19_web_component]]
9 | - [[2021-04-20_details_usage]]
10 | - [[2021-04-28_css_grid]]
11 | - [[2021-05-10_customise_tags]]
12 | - [[2022-08-29_sidebar_view]]
13 | - [[2022-08-29_solidjs]]
14 |
--------------------------------------------------------------------------------
/docs/sections/getting_started.md:
--------------------------------------------------------------------------------
1 | ---
2 | previous: %installation%
3 | next: %configuration%
4 | tags: [section]
5 | ---
6 | # Getting started
7 |
8 | This plugin offers two ways of displaying the metadata for a given markdown document: the [[inline_metatable]] or the [[sidebar_metatable]].
9 |
10 | Note that this version does not display the metatable in _editing mode_. It's a known limitation but contributions are welcome!
11 |
12 | After [[installation|installing the plugin]], the plugin will be ready to use straight away however it is best to have a quick tour to the [[configuration]] to tweak how the plugin displays the information.
13 |
14 | For example, if you tend to have large frontmatter structures you might want to consider [[configuration#Expansion level|tweaking the expansion level]]. I personally use a combination of having the [[sidebar_metatable]] open and collapsing just the root such that when I use the _reading mode_ I don't see the metatable again.
15 |
16 | This plugin has only been tested with the default theme so if you are like me and use a different one you might want to [[customising_colours_and_symbols|tweak a few colours]] or even going further and [[customising_parts|adjusting spacing, symbols, etc]].
17 |
18 | Thanks for using the plugin and let me know if there is any unexpected behaviour!
--------------------------------------------------------------------------------
/docs/sections/inline_metatable.md:
--------------------------------------------------------------------------------
1 | ---
2 | tags: [anatomy]
3 | ---
4 | # Inline metatable
5 |
6 | The inline metatable is a widget that gets displayed whilst viewing a markdown document in _reading mode_.
7 |
8 | Notice that when the mode is _editing_, the frontmatter is displayed as raw YAML.
9 |
10 | You might find convenient to open the [[sidebar_metatable]] whilst editing the frontmatter section.
--------------------------------------------------------------------------------
/docs/sections/installation.md:
--------------------------------------------------------------------------------
1 | ---
2 | next: %getting_started%
3 | tags: [section]
4 | ---
5 | # Installation
6 |
7 | You can install this plugin in three ways, each one with its own strengths.
8 |
9 | ## From Obsidian
10 |
11 | Use this option if you want minimum friction both installing and updating. This is the recommended way for most people.
12 |
13 | - Ensure Community Plugins are enabled.
14 | - Browse community plugins searching for **metatable**.
15 | - Click install.
16 | - Enable plugin in the “Community Plugins” Settings section.
17 | - Open a file (notice that previously opened files won't get the effects of the plugin until reopened or changed).
18 |
19 | ## From release
20 |
21 | Use this option if you want to try a particular version outside of what the Community Plugins offer or if you rather sidestep Obsidian's installation system.
22 |
23 | - Download the `obsidian-metatable-{version}.zip` file from the chosen release, for example the [latest release].
24 | - Ensure “Community Plugins” are enabled in Settings.
25 | - Ensure the `.obsidian/plugins/` directory exists in your vault directory.
26 | - Expand the zip file into the `.obsidian/plugins/` directory such that an `obsidian-metatable` directory is a direct child of `plugins`.
27 | - Enable plugin in the “Community Plugins” Settings section.
28 | - Open a file (notice that previously opened files won't get the effects of the plugin until reopened or changed).
29 |
30 | ## From source
31 |
32 | Use this option if you intent to contribute to the plugin development, you want to fork it out or don't find the previous two options suitable.
33 |
34 | - Clone the [source repository].
35 | - Run `npm install`.
36 | - Run `npm run build`.
37 | - Create an `obsidian-metatable` directory under your vault's `.obsidian/plugins/` directory.
38 | - Copy over `main.js`, `versions.json` and `manifest.json`.
39 | - Enable plugin in the “Community Plugins” Settings section.
40 | - Open a file (notice that previously opened files won't get the effects of the plugin until reopened or changed).
41 |
--------------------------------------------------------------------------------
/docs/sections/sidebar_metatable.md:
--------------------------------------------------------------------------------
1 | ---
2 | tags: [anatomy]
3 | ---
4 | # Sidebar metatable
5 |
6 | The sidebar metatable is a widget that you can open using the _open sidebar metatable_ or using the ribbon icon in the left pane.
7 |
8 | This widget displays the metadata for the current markdown file.
--------------------------------------------------------------------------------
/docs/sections/tags.md:
--------------------------------------------------------------------------------
1 | ---
2 | previous: %customising_parts%
3 | next: %autolinks%
4 | tags: [section]
5 | ---
6 | # Tags
7 |
8 | [Obsidian treats tags in a particular way](https://help.obsidian.md/How+to/Working+with+tags). From a YAML point of view it is treated in a non standard way, so this section covers this angle.
9 |
10 | The `tags` key (or any casing like `Tags`) expects a sequence of strings. In standard YAML there are two options.
11 |
12 | ## Compact notation
13 |
14 | ```yaml
15 | tags: [one, two, three]
16 | ```
17 |
18 | ## Indented notation
19 |
20 | ```yaml
21 | tags:
22 | - one
23 | - two
24 | - three
25 | ```
26 |
27 | ## Non standard notations
28 |
29 | However, the following forms are treated as valid forms by Obsidian (and by Obsidian Metatable to keep compatibility).
30 |
31 | **It is highly recommended that you stick with the standard notation to keep compatibility with other tools**.
32 |
33 |
34 | ### String (single)
35 |
36 | ```yaml
37 | tags: one
38 | ```
39 |
40 | ### String (collection)
41 |
42 | ```yaml
43 | tags: one, two, three
44 | ```
45 |
46 |
--------------------------------------------------------------------------------
/docs/tests/broken-tags.md:
--------------------------------------------------------------------------------
1 | ---
2 | tags: {a: 1}
3 | ---
4 | # Test: Broken tags
5 |
6 | A test to verify tags that are not an expected value don't fail as long as the value is valid YAML.
--------------------------------------------------------------------------------
/docs/tests/broken.md:
--------------------------------------------------------------------------------
1 | ---
2 | foo:
3 | bar: bad: yaml
4 | ---
5 | # Test: Broken
6 |
7 | A test to verify broken YAML displays a warning.
--------------------------------------------------------------------------------
/docs/tests/chinese-tags.md:
--------------------------------------------------------------------------------
1 | ---
2 | tags: 剧情 喜剧
3 | ---
4 | # Test: chinese tags are handled properly
--------------------------------------------------------------------------------
/docs/tests/emoji-tags.md:
--------------------------------------------------------------------------------
1 | ---
2 | tags: [🥑, 🥕]
3 | ---
4 | # Tags with emojis
--------------------------------------------------------------------------------
/docs/tests/extreme.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Extreme example
3 | empty-list: []
4 | empty-set: {}
5 | summary: An extreme example to show nested tables
6 | start_date: 2021-04-11
7 | end_date: none
8 | tags:
9 | - test
10 | - extreme
11 | options:
12 | - first
13 | - second with text
14 | - third with even more text
15 | social:
16 | - name: Twitter
17 | handle: "@metatable"
18 | - name: Instagram
19 | handle: "@metatable7612"
20 | a-table-inside:
21 | alpha: yada
22 | beta: badabum
23 | gamma: green
24 | list-in-list:
25 | - one
26 | -
27 | - x
28 | - y
29 | a-null:
30 | numeric: 2
31 | aliases: [extreme-test]
32 | deep-null:
33 | a-keeper: "foo"
34 | a-null:
35 | deep-ignore:
36 | frontmatter: foo
37 | ---
38 | # Test: An extreme test
39 |
40 |
--------------------------------------------------------------------------------
/docs/tests/long-keys.md:
--------------------------------------------------------------------------------
1 | ---
2 | a-very-long-key-with-no-way-to-escape: tiny value?
3 | normal-key: lorem ipsum
4 | ---
5 | # Test: Long keys
6 |
7 | A test to verify how long keys behave.
8 |
--------------------------------------------------------------------------------
/docs/tests/none.md:
--------------------------------------------------------------------------------
1 | # Test: none
2 |
3 | A test to verify how the absence of a frontmatter works.
--------------------------------------------------------------------------------
/docs/tests/normalise-tags.md:
--------------------------------------------------------------------------------
1 | ---
2 | tags: foo bar, far
3 | ---
4 | # Test: Normalise tags
--------------------------------------------------------------------------------
/docs/tests/pdf_export.md:
--------------------------------------------------------------------------------
1 | ---
2 | tags: [a, b]
3 | ---
4 | # Test: PDF export
5 |
6 | As reported in [bug #30](https://github.com/arnau/obsidian-metatable/issues/30) when exporting a note with an image embedded to PDF the metatable does not show up.
7 |
8 | 
9 |
--------------------------------------------------------------------------------
/docs/tests/tags.md:
--------------------------------------------------------------------------------
1 | ---
2 | TAGS: one, two
3 | tagS: one
4 | Tags: [test]
5 | tags: [test, no-example]
6 | ---
7 | # Test: Tag list
8 |
9 | A test to verify tags are treated correctly regardless of casing or acceptable value.
--------------------------------------------------------------------------------
/docs/tests/title with spaces.md:
--------------------------------------------------------------------------------
1 | ---
2 | tags: [test]
3 | ---
4 | # Test: title with spaces
5 |
6 | To test the [[autolinks]].
--------------------------------------------------------------------------------
/esbuild.config.mjs:
--------------------------------------------------------------------------------
1 | import esbuild from "esbuild";
2 | import process from "process";
3 | import builtins from "builtin-modules"
4 | import { solidPlugin } from "esbuild-plugin-solid"
5 |
6 | const banner =
7 | `/*
8 | THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
9 | if you want to view the source, please visit the github repository of this plugin
10 | */
11 | `;
12 |
13 | const prod = (process.argv[2] === 'production');
14 |
15 | esbuild.build({
16 | banner: {
17 | js: banner,
18 | },
19 | entryPoints: ["src/main.ts"],
20 | bundle: true,
21 | external: [
22 | "obsidian",
23 | "electron",
24 | "@codemirror/autocomplete",
25 | "@codemirror/collab",
26 | "@codemirror/commands",
27 | "@codemirror/language",
28 | "@codemirror/lint",
29 | "@codemirror/search",
30 | "@codemirror/state",
31 | "@codemirror/view",
32 | "@lezer/common",
33 | "@lezer/highlight",
34 | "@lezer/lr",
35 | ...builtins,
36 | ],
37 | format: "cjs",
38 | target: "es2018",
39 | logLevel: "info",
40 | sourcemap: prod ? false : "inline",
41 | treeShaking: true,
42 | outdir: "dist",
43 | plugins: [solidPlugin()],
44 | loader: {
45 | ".css": "text",
46 | },
47 | }).catch(() => process.exit(1));
48 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | verbose: true,
3 | preset: 'ts-jest',
4 | transform: {
5 | '^.+\\.ts$': 'ts-jest',
6 | },
7 | moduleFileExtensions: ['js', 'ts'],
8 | testEnvironment: 'jsdom',
9 | };
10 |
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "obsidian-metatable",
3 | "name": "Metatable",
4 | "version": "0.14.7",
5 | "minAppVersion": "0.15.9",
6 | "description": "Displays the full frontmatter as a table.",
7 | "author": "Arnau Siches",
8 | "authorUrl": "https://www.seachess.net/",
9 | "isDesktopOnly": false
10 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "obsidian-metatable",
3 | "version": "0.14.7",
4 | "description": "An Obsidian plugin to render the full frontmatter as a table.",
5 | "keywords": [
6 | "obsidian"
7 | ],
8 | "author": "Arnau Siches",
9 | "license": "MIT",
10 | "scripts": {
11 | "build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
12 | "dist": "rm -rf dist && mkdir dist && npm run build && cp styles.css versions.json manifest.json dist/",
13 | "docs": "npm run dist && cp dist/* docs/.obsidian/plugins/obsidian-metatable && cp CHANGELOG.md docs/changelog.md",
14 | "release": "node support/version-bump.mjs",
15 | "test": "jest --passWithNoTests"
16 | },
17 | "devDependencies": {
18 | "@types/jest": "^29.0.1",
19 | "@types/node": "^20.4.0",
20 | "@typescript-eslint/eslint-plugin": "^5.33.1",
21 | "@typescript-eslint/parser": "^5.33.1",
22 | "builtin-modules": "^3.3.0",
23 | "esbuild": "^0.18.11",
24 | "esbuild-plugin-solid": "^0.5.0",
25 | "jest": "^29.0.3",
26 | "jest-environment-jsdom": "^29.0.3",
27 | "obsidian": "^1.1.1",
28 | "ts-jest": "^29.0.0",
29 | "tslib": "^2.0.3",
30 | "typescript": "^5.1.6"
31 | },
32 | "dependencies": {
33 | "solid-js": "^1.4.7"
34 | }
35 | }
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/arnau/obsidian-metatable/df6b59af4b57e2219ef6c5e8e5bd956356da116e/screenshot.png
--------------------------------------------------------------------------------
/src/components/ExternalLink.tsx:
--------------------------------------------------------------------------------
1 |
2 | export function ExternalLink(props: any) {
3 | return (
4 |
5 | )
6 | }
7 |
8 | export function isExternalLink(value: string): boolean {
9 | const url = tryUrl(value)
10 |
11 | return isUrl(url)
12 | }
13 |
14 | function isUrl(url: URL | string): boolean {
15 | const allowedProtocols = ['http:', 'https:', 'evernote:', 'zotero:']
16 |
17 | return (url instanceof URL && allowedProtocols.some(protocol => url.protocol == protocol))
18 | }
19 |
20 |
21 | export function tryUrl(value: string): URL | string {
22 | try {
23 | return new URL(value)
24 | } catch (_) {
25 | return value
26 | }
27 | }
28 |
29 | /**
30 | * Represents an external link.
31 | */
32 | export function Link(props: LinkProps) {
33 | const label = props.label
34 | const url = props.url
35 |
36 | return (
37 | {label}
44 | )
45 | }
46 |
47 | interface LinkProps {
48 | label: string;
49 | url: string;
50 | }
51 |
--------------------------------------------------------------------------------
/src/components/Inline.tsx:
--------------------------------------------------------------------------------
1 | import { Match, Show, Switch } from "solid-js"
2 | import { ValueError, Value } from "src/value"
3 | import { parseFrontmatter } from "src/frontmatter"
4 | import { useMixture } from "src/mixture"
5 | import { ParseError } from "./ParseError"
6 | import { Metatable } from "./Metatable"
7 |
8 | // @ts-ignore
9 | import styles from "../metatable.css"
10 |
11 | interface InlineProps {
12 | data: string | null | undefined,
13 | }
14 |
15 | export function Inline(props: InlineProps) {
16 | let { settings, isOpen, cleanData } = useMixture()
17 | let metadata: Value | ValueError | undefined
18 |
19 | try {
20 | metadata = cleanData(parseFrontmatter(props.data))
21 | } catch (err) {
22 | metadata = err as ValueError
23 | }
24 |
25 | return (
26 | <>
27 |
28 |
29 |
30 |
31 |
32 | (metadata as ValueError)!.message!} />
33 |
34 |
35 |
36 | Metatable
37 |
38 |
39 |
40 |
41 | >
42 | )
43 | }
44 |
--------------------------------------------------------------------------------
/src/components/InternalLink.tsx:
--------------------------------------------------------------------------------
1 | import { MarkdownView, getLinkpath } from "obsidian"
2 | import { Match, Switch, createEffect, createSignal } from "solid-js"
3 | import { useMixture } from "../mixture"
4 |
5 | /**
6 | * Represents any form of internal link.
7 | */
8 | export function InternalLink(props: any) {
9 | const value = props.value
10 |
11 | return (
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | )
30 | }
31 |
32 | export function isInternalLink(value: string): boolean {
33 | return isWikiLink(value)
34 | || isFrontmatterLink(value)
35 | || isLocalLink(value)
36 | || isObsidianUrl(value)
37 | }
38 |
39 |
40 | /**
41 | * Represents a wiki link. It has the form `[[localId]]` or `[[localId|label]]`.
42 | */
43 | function WikiLink(props: any) {
44 | let value = props.value.slice(2, -2)
45 | let url: string
46 | let label: string
47 |
48 | if (value.includes("|")) {
49 | const [urlValue, labelValue] = value.split("|")
50 | url = urlValue.trim()
51 | label = labelValue.trim()
52 | } else {
53 | label = value
54 | url = value
55 | }
56 |
57 | return (
58 |
59 | )
60 | }
61 |
62 | function isWikiLink(value: string): boolean {
63 | return (value.startsWith("[[") && value.endsWith("]]"))
64 | }
65 |
66 |
67 | /**
68 | * Represents a frontmatter link. It has the form `%localId%` or `%localId|label%`.
69 | */
70 | function FrontmatterLink(props: any) {
71 | let value = props.value.slice(1, -1)
72 | let url: string
73 | let label: string
74 |
75 | if (value.includes("|")) {
76 | const [urlValue, labelValue] = value.split("|")
77 | url = urlValue.trim()
78 | label = labelValue.trim()
79 | } else {
80 | label = value
81 | url = value
82 | }
83 |
84 | return (
85 |
86 | )
87 | }
88 |
89 | function isFrontmatterLink(value: string): boolean {
90 | return (value.startsWith("%") && value.endsWith("%"))
91 | }
92 |
93 |
94 | /**
95 | * Reprents a local link of the form `./target/path`.
96 | */
97 | function LocalLink(props: any) {
98 | return (
99 |
100 | )
101 | }
102 |
103 | function isLocalLink(value: string): boolean {
104 | return value.startsWith("./") || value.startsWith("../")
105 | }
106 |
107 |
108 | function ObsidianLink(props: any) {
109 | return (
110 |
111 | )
112 | }
113 |
114 | function isObsidianUrl(url: URL | string): boolean {
115 | return (url instanceof URL && url.protocol == "obsidian:")
116 | }
117 |
118 | function expandUrl(url: string, parent: string | null | undefined) {
119 | if (!url.startsWith(".") || !url.startsWith("..")) { return url }
120 |
121 | const parentTrail = parent?.split("/").filter(step => step.length > 0) ?? []
122 |
123 | const [relativeStep, ...trail] = url.split("/")
124 |
125 | if (relativeStep === "..") {
126 | parentTrail.pop()
127 | }
128 |
129 | return `/${parentTrail.concat(trail).join("/")}`
130 | }
131 |
132 | /**
133 | * Represents an internal link.
134 | */
135 | export function Link(props: LinkProps) {
136 | const { workspace } = useMixture()
137 | const [parent, setParent] = createSignal()
138 | const view = () => workspace.getActiveViewOfType(MarkdownView)
139 | createEffect(() => {
140 | setParent(view()?.file.parent?.path)
141 | })
142 |
143 | const { openNote } = useMixture()
144 | const label = () => props.label
145 | const url = () => decodeURIComponent(props.url)
146 | const localUrl = () => getLinkpath(url())
147 | const clickHandler = (event: any) => {
148 | event.preventDefault()
149 | const href = event.target.dataset.href!
150 | openNote(expandUrl(href, parent()))
151 | }
152 |
153 | return (
154 | {label()}
163 | )
164 | }
165 |
166 | interface LinkProps {
167 | label: string;
168 | url: string;
169 | }
170 |
--------------------------------------------------------------------------------
/src/components/Leaf.tsx:
--------------------------------------------------------------------------------
1 | import { Match, Switch, createEffect } from "solid-js"
2 | import type { LeafValue } from "../value"
3 | import { useMixture } from "../mixture"
4 | import { Tag } from "./Tag"
5 | import { isInternalLink, InternalLink, Link as ILink } from "./InternalLink"
6 | import { isExternalLink, ExternalLink, Link as ELink } from "./ExternalLink"
7 |
8 |
9 | const ISODATE_RE = new RegExp(/^\d{4}-\d{2}-\d{2}$/)
10 | const MD_LINK_RE = new RegExp(/^\[(?