Introduction to Obsidian-Inputs
Obsidian-Inputs is a lightweight, efficient plugin designed to offer a simple inline-code pattern for creating input and button components in ObsidianMD's preview mode. These components dynamically modify markdown files, ensuring long-term readability even if Obsidian or other plugins fail.
Existing Obsidian plugins for creating input components are often unstable and slow due to their reliance on complex libraries. This affects your experience and productivity within ObsidianMD, leading to frustration and inefficiency.
Key Features
- Quick Loading: Average loading time of ~10ms.
- Markdown Compatibility: Updates are made directly within markdown files, not external settings.
- User-Friendly Syntax: Simple and easy-to-read syntax, avoiding complex bidirectional elements. like :
(
. - No External Libraries: Uses Obsidian's API and simple HTML elements for seamless integration.
Plugin Capabilities
- Input/Button Creation: Create text inputs, text areas, radio inputs, and buttons easily.
- Markdown Modification: Effortlessly update headers, dataview-inline fields, and frontmatter fields.
- File Operations: Automatically create, modify, rename, or remove files.
- Macro Creation: Automate steps and reference previous results or files.
Input Sources
Retrieve options from Dataview queries or input them manually.
Context Modification
- File Operations: Create, modify, rename, or remove files.
- Header Manipulation: Manage headers within files.
- Front Matter Management: Create, update, and modify front matter fields.
- Inline Field Interaction (Dataview): Interact with inline fields.
- Pattern: Use input patterns to append, prepend, or replace values dynamically.
Planned Enhancements
- Additional features and capabilities will be introduced in future releases.
Terminology
- Page/File: Used interchangeably.
- Notation/Pattern: Refers to plugin syntax written on the page.
- Components: All UI elements created by the plugin, including inputs and buttons.
For detailed syntax information, refer to the Syntax Documentation. Screenshots
Screenshoots:
![[Pasted image 20240328003625.png]]
Syntax for creating input components follows the convention:
<"id"?> <"type"> <":name"> "|" <"expression"> <", opts"> <">target">
"type"
החלק הזה אחראי על הקומפוננטה שתתרנדר בview. שתי האופציות שכרגע נתמכות הן text: שמייצר text input, the experstion in this case run after the user unfocus the input button: שמייצר button, the expertion in this case run when user click on the input
צריך לרשום את זה כך
text:
or button:
":name"
free text that be the name of the button or the placeholder in the input must be end with |
"expression"
Expressions undergo evaluation in three steps and can incorporate data from the current or other pages or the last updated file, such as frontmatter fields, dataview inline fields. They can load files as templates or execute JavaScript files or interact with global api.
Step 1: Utilize pre-processing string template on the expression
to replace all placeholders in the format {{path.of.data}}
or &path.to.data
with corresponding data from frontmatter, inline fields, or file properties.
- If the property exist on frontmatter and elso on dataview-inline-field the priority is by the target type. if target type is frontmatter priority is to read from frontmatter and if it inline-field priority is inline-field
- If the data to inject is a tFile, it's replaced by an Obsidian link (by setting, default: wiki link).
- The last ten files touched by the plugin are referred to as
page0
topage9
. you can refer them and there variable like{{ page0.book-name }}
- while the last ten files created by the plugin are called
new0
tonew9
{{ new2.book-name }}
- you can refer any file and read it data by using
[[file-name]]
syntax{{ [[harry potter]].book-name }}
- Current file is refer by using the name
activeFile
, most time it can omit, because default context always being to current active file.
Step 2: After Step 1, the evaluated expression undergoes content testing.
If the expression matches the pattern import [[file name]]
:
- If the file name ends with
.md
, its content is loaded and processed using the templater, with the result sent to the target. - If the file name ends with
.js
, it's imported as a JavaScript module, enabling the use of all Obsidian-Inputs API functions. Theexport default
value is sent to the target. If it's undefined, the target part is not executed. - If an error occurs during templater or JavaScript module import, it's displayed in the developer console.
Step 3: If the expression doesn't match the import pattern, it's evaluated as a JavaScript expression, and the return value is sent to the target.
Step 4: If the expression throws an error, it's considered plaintext and sent to the target as is. and that is you way to write arbitrary text to the target
"> target"
After the > symbol, the target part specifies the area to be modified by the expression value. It is constructed with the following sub-pattern:
<"file"?><"(::|#|:)path"?><" method">
by combine file
path
the plugin define the type of the entity that should be modified, target type
can be file
, header
, dataview inline field
, frontmatter or yaml
, pattern
himself
-
<"file"?>
Optional,Specifies the name of the file or page to be modified.- If no
file
is provided, it refers to the current active file. - If the file does not exist, it is created. Otherwise, it is modified.
- If no next part
path
is omitted, targetType is the file himself.
- If no
-
<"(::|#|:)path">
-
::path
: Specifies the targetType as an inline field in the target file.- In the case of multiple fields by the same name the closer one to the pattern will be chosen
-
:path
- Specifies the targetType asYAML
in the front matter of the target file. -
#path
- Specifies the targetType as aheader
in the target file.- when mention header name you should ignore
input pattern
if you write it in the same line of the header. so the next line should work -
book list
text: add | just read &input >#book list
- when mention header name you should ignore
-
if no
file
orpath
provide thetargetType
ispattern
which use the currentinput-pattern
as context
-
-
<" method">
followed by space there is the method that can be one of the next actions. the meaning of the action change a little by thetargetType
- append
- for
inline field
andyaml
it convert the value to array (if is not) and append the new value to end of the array. - for
header
it append the value after the last line of the header content (the not empty line before the next header ) - for
file
it append the value to bottom of the file - for
pattern
it add the value after theinput-pattern
- for
- replace
- for
inline field
andyaml
it replace the curent value (or array) with the new value - for
header
it repace the whol header content with new value - for
file
It replaced the whole file with the new value - for
pattern
It replaced the whole input pattern with the new value so it actually deleted it- caution: if there is a two or more pattern that look the same it replaced the first one. To avoid that use the ID section .etc
-identify- text:activity| {{input}}> #Activity
- caution: if there is a two or more pattern that look the same it replaced the first one. To avoid that use the ID section .etc
- for
- prepend
- same as
append
Just add the new value to the start of everything
- same as
- create
- for
file
it created the file. If the file exist it create a new one with increment free number after the name
- for
- clear
- for
header
,file
,inline field
andyaml
it clear the current value or content and ignore the new value - for
pattern
it clear the text beforeinput-pattern
until firstinline field
in that line. another run of that target clear the value of theinline field
, another run remove all text until start of the line
- for
- remove: Deletes the specified target entirely.
- For
header
, it removes the entire header and its content. - For
file
, it deletes the file entirely. - For
inline field
andyaml
, it removes the current value or content entirely. - For
pattern
, it removes the entire input pattern.
- For
- rename
- For
file
, new value become the newpath
of target file.- if
file
not exist nothing happen - If
path
is exist it generate a newpath
by incrementing index ex.file 0
,file 1
, etc - new
path
is coenacted to exist path of the target file - but is legit to be started the
path
with:\
for make the path start from root valut folder..
go one folder back relative target file.
stay in the same place of target file. ( default )
- if
- For other targets such as
inline field
,yaml
, orheader
, therename
method is not applicable yet
- For
- append
If you're interested in testing the Obsidian-Inputs plugin before it's published in the plugin community, follow these steps:
- Download the plugin files from the repository or source provided by the developer.
- Open ObsidianMD and navigate to the Settings pane.
- Click on the "Community plugins" tab.
- Locate the "Developers" section and click on the "Load plugin" button.
- Select the downloaded plugin files from your local directory.
- Once loaded, the plugin will appear in the list of installed plugins.
- Enable the plugin by toggling the switch next to its name.
- Test the plugin's functionality within ObsidianMD to provide feedback and report any issues to the developer.
Please note that as this plugin is still in the testing phase and not yet published in the plugin community, it may have limited features and could encounter bugs or errors. Your feedback as a tester is invaluable in helping improve the plugin before its official release.
If you encounter any issues during the testing process, provide detailed feedback to the developer to assist in troubleshooting and improvement efforts. You can also collaborate with other testers and developers in the ObsidianMD community forums or Discord channels to share experiences and insights.
Input Notation Syntax:
Syntax for creating input components follows the convention:
<"-id-"?> <"type"> <":name"> "|" <"expression"> <", opts"> <">target">
-id-?
: Optional identifier for the Component element, aiding in recognition for refocusing or pattern replacement.
type
: Specifies the type of the input element, such as text
, textarea
, or button
, followed by a colon :
.
can be:
text
: simple text input. it run the expression when it unfocus and value is not emptybutton
: simple button. it run the expression when click on ittextarea
: text area input that fill the screen
:name
: Label of button or placeholder for inputs. indicating the purpose of the input field.
now |
: Pipe symbol separating the introduction part and the actual expiration/target notation.
expression
: Expression generating the value to be injected into the target. It could be a string with placeholder, a JS expression, a JS file to import and run or md template file.
examples:
- placeholder: I read today the book &book-name
or I read today the book {{book-name}}
can result to I read today the book Harry Potter
if somewhere is the page
[book-name::Harry Potter] exist
- JS expression: number + 1
if somewhere is the page [number::2] exist the result to target will be
3 - **JS import:**
import [[create-book.js]]that import and run
create-book.jsif it exists in the vault - **md import:**
import [[create-book.md]] that read and run throw templater
create-book.mdif it exists in the vault and return the result see detail [here](../)
, opts`: comma separated values for created radio button or dataview query for create autocomplete input, start with comma
>target
: Specifies where and how the value of the expression part is stored or processed. including the target file or context and the method of saving or updating the target.
Target own mini pattern
<filename><type><path> <method>
(#|::|:)
Examples :
Example 1: Create a text input element:
text: Enter your name| {{input}} >::name
value will saved in inline-field called
name
in the same file. If the field doesn't exist, it's created.
Example 2: Create a text area with autocomplete:
text:select game| {{input}}, = #games >:games append
Creates an input element that autocompletes from a Dataview query of files tagged with #games, appending the value the end of front matter
games::
key as an array.
Example 3: Create a radio input element
text: Select color| red, blue, green| = #colors >:selectedColor
Example 4: Creates a button element that increments the inline field number:
button:click me| (number || 0)+1 >::number
Example 5: Create a button to delete a specific header:
button: Delete section| >::file#Section Name remove
Example 6: same, just clear the header content:
button: Delete section| >::file#Section Name clear
Example 7: mood tracking
text:Mood| - (@time) {{input}} [reasone], ☺️,😑,🥰,😎,🤩,🤔,🫥,😮,😏,🤑 >#Activities