Find support resources, report security or community violations, and learn how to contribute to Obsidian.
## Questions and advice

If you have a question about how to use Obsidian, or want to get to know other Obsidian users, you can join one of our community channels:

- [Join our Discord server](https://discord.gg/obsidianmd)
- [Visit the forum](https://forum.obsidian.md/)

### Report bugs and request features

> [!important]
> Before you request a new feature or report a bug, please look through the other posts to make sure someone else hasn't already submitted it.

If you want to suggest a feature in Obsidian, head over to [Feature requests](https://forum.obsidian.md/c/feature-requests/8).

If you want to report a bug, head over to [Bug reports](https://forum.obsidian.md/c/bug-reports/7). Bug reports are moved to the [Bug graveyard](https://forum.obsidian.md/c/bug-graveyard/12) once they're resolved.

### Contact Obsidian support

Obsidian offers email support only for inquiries about [[Commercial license|commercial licenses]], your account, payment, and add-on services ([[Introduction to Obsidian Sync|Obsidian Sync]] and [[Introduction to Obsidian Publish|Obsidian Publish]]). If you need help with any of those topics, [email the Obsidian team](mailto:support@obsidian.md).

### Collect debug information

When you encounter a bug or need assistance from Obsidian support, it's helpful to provide them with your Obsidian application's debug information. Here's how you can obtain it:

1. Open the [[Command palette]].
2. Type **Show debug info**.
3. Select the highlighted **Show debug info** option.
4. Click the **Copy to clipboard** button.
5. Paste the copied information into your bug report or Obsidian support email.

### Capture console logs

When you need to report a bug related to an Obsidian plugin, or when requested to provide log information, you may need to access the Obsidian console. Here's how you can do it based on your operating system:

- **Windows**: `CTRL + SHIFT + i`  
- **MacOS**: `CMD + OPTION + i`  
- **Linux**: `CTRL + SHIFT + i`

Once you've opened the developer console:

1. Select on **console** in the top menu.
2. Choose the **errors** side menu option. Any errors will be displayed as `# errors`.
3. Select one of the red error messages.
4. Choose the option to **Save as...** This will save all the errors in the console.
5. Save the log file to your device.
6. Attach the log file to your bug report or Obsidian support email.

![[help-support-console-menu.png#interface|600]]

> [!warning] Mobile devices/tablets have limited access to their developer consoles. For these users, we recommend using the community plugin [Logstravaganza](https://obsidian.md/plugins?id=logstravaganza) to automatically generate the console log data in a markdown note.

## Report a security issue

If you've discovered a security issue in Obsidian, or if you suspect that a plugin is malicious, please [email the Obsidian team](mailto:support@obsidian.md).

## Report a Code of Conduct violation

Whether you're a victim or witness of a violation of our [[Community code of conduct]], you can report the incident to our moderator team

Report the incident on one of the following community channels:

- [[Community code of conduct#Report on Discord|Report on Discord]]
- [[Community code of conduct#Report on the forum|Report on the forum]]

## Contributing to Obsidian

Interested in applying some skills and free time to Obsidian? Here is where we could really use your assistance:

- Help your fellow Obsidian users out by answering questions on our [discord server](https://discord.gg/obsidianmd), our [forum](https://forum.obsidian.md/), or the [ObsidianMD](https://old.reddit.com/r/ObsidianMD/) reddit.
- [[Developers]], we could really use your help on expanding our [Obsidian Developer Documentation](https://github.com/obsidianmd/obsidian-developer-docs). 
- Do you know any written language besides English? Consider assisting with our [[Translations]] into other languages.
- Is there something in these help docs that are out of date, or confusing? Grab the [[Style guide]] and submit an [issue and pull request](https://github.com/obsidianmd/obsidian-help/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
- If able, you can [[Financial contributions|financially contribute]] by utilizing one of our paid addons.

# Obsidian Help

Welcome to the official Obsidian Help site, where you can find tips and guides on how to use [Obsidian](https://obsidian.md). For API documentation visit the [Obsidian Developer Docs](https://docs.obsidian.md/).

You can also browse this site in the following languages:

- [العربية](https://publish.obsidian.md/help-ar)
- [Dansk](https://publish.obsidian.md/help-da)
- [Español](https://publish.obsidian.md/help-es)
- [Italiano](https://publish.obsidian.md/help-it)
- [日本語](https://publish.obsidian.md/help-ja)
- [Phéasa Khmêr](https://publish.obsidian.md/help-km)
- [한국어](https://publish.obsidian.md/help-ko)
- [Português](https://publish.obsidian.md/help-pt-br)
- [Русский](https://publish.obsidian.md/help-ru)
- [Tiếng Việt](https://publish.obsidian.md/help-vi)
- [中文](https://publish.obsidian.md/help-zh)

## Getting started

If you're new to Obsidian, learn the basics of note-taking with Obsidian using our guides:

1. [[Download and install Obsidian]]
2. [[Create a vault]]
3. [[Create your first note]]
4. [[Link notes]]
5. [[Import notes]]

From here, you can build your own custom experience by enabling additional features through _plugins_. Explore the [[Core plugins]] that ship with Obsidian, or any of our [[Community plugins]].

Customize the look and feel of Obsidian using [[Themes]] and [[CSS snippets]].

## Add-on services

- [[Introduction to Obsidian Sync|Obsidian Sync]]
	- A safe and secure way to synchronize your notes across any device and OS.
- [[Introduction to Obsidian Publish|Obsidian Publish]]
	- Publish your notes as a wiki, knowledge base, documentation, or digital garden.

## Latest updates

> [!todo] Update for version 1.5 
> The documentation has been revised for the 1.5 desktop release, incorporating changes to the [[Language settings|interface language]]. 
> 
> Pre-1.5: **Settings** ( ![[lucide-settings.svg#icon]] ) → **About**
> Post-1.5: **Settings** ( ![[lucide-settings.svg#icon]] ) → **General**.
> 
> Mobile users are advised to continue referring to the "**About**" section in their settings until the next mobile release.

## Contribute

If you find any mistakes or missing information on this site, you can contribute improvements and translations via [the GitHub repo](https://github.com/obsidianmd/obsidian-docs/).

If you want to support Obsidian financially, consider a [[Catalyst license]], which offers early access to beta versions of Obsidian.

See the [[Credits]] to get to know all the amazing people who made Obsidian possible.

Obsidian 0.13 introduces a brand new editor engine that comes with several enhancements to your editing experience. In this post, we'll take a closer look at one of the biggest improvements in the latest release: _Live Preview_.

Live Preview is a new editor mode that lets you preview your notes in the same view that you're writing them in. Live Preview delivers a cleaner writing experience by only displaying Markdown syntax around the cursor. Let's see an example!

This is what your editing experience used to look like:

![[Source view.png#interface]]

And here's the same note using Live Preview:

![[Live Preview.gif]]

Live Preview gives you an improved editing experience that lets you see how your Markdown note will look like, without having to switch between Edit and Preview.

To enable Live Preview for an existing vault:

1. Open **Settings**.
2. In the sidebar, click **Editor**.
3. Under **General**, disable **Legacy Editor**.
4. Click on the **Relaunch** button for the change to take effect.
5. After Obsidian restarts, open **Settings**.
6. In the sidebar, click **Editor**.
7. Under **General**, set **Default editing mode** to **Live Preview**.

When you open a new tab, it'll use Live Preview by default. If you already have some tabs open, they'll be in _Source mode_.

## Edit notes using Live Preview or Source mode

We think you're going to love Live Preview. But if you want to keep your current editing experience, we've got you covered. You can keep editing your notes the same way as before by switching to the new Source mode.

To toggle between Live Preview and Source mode:

1. In the upper right corner of the tab, click **More options** (the three dots).
2. Select **Toggle source/live preview mode**.

You can also toggle the editing view by opening the Command palette and searching for the **Toggle source/live preview mode command**, or change it permanently by setting **Default editing mode** to Source mode.

Live Preview and Source mode are two ways to edit your Markdown notes in Obsidian. Try them out to see which one you prefer!

If you want to know how the terminology changes with the new features, here's a handy chart by [[Credits#^a4b3a2|Argentum]]:

![[Editor update chart.png]]

## Wait, I'm not ready to switch!

Some plugins and themes may not be fully compatible with the new editor. If your favorite plugin doesn't yet support the new editor, you can switch back to the old one by enabling the Legacy editor.

3. Under **General**, enable **Legacy Editor**.

Use the legacy editor if you're not ready to upgrade to the new editor. You'll miss out some sweet features, but know that you can switch to the new editor at any time.

This glossary includes common Obsidian terminology.

## Alias

An **alias** is a type of [[#property]] that defines alternative names for a [[#note]].

## Attachment

An **attachment** is an [[Accepted file formats|accepted file format]] that was created outside of the vault and added later.

## Command

A **command** is an action that can be performed either by selecting it from the [[Command palette]] or by assigning it to a [[#hotkey]].

## Embed

**Embedding** means replacing a reference to external content with the content itself, for example to include an image in your note. See also [[Embed files]].

## Frontmatter

Frontmatter is a way to define [[#property|properties]] by adding [YAML](https://yaml.org/) or [JSON](https://www.json.org/) at the top of the note. See also [[Properties#Property format|Property format]].

## Graph

A **graph** is a visualization that highlights connections between [[#note|notes]]. See also [[Graph view]].

## Hotkey

A **hotkey** is a keyboard shortcut for a [[#command]]. See also [[Hotkeys]] and [[Hotkeys|How to/Use hotkeys]].

## Link

A **link** references another note or file. An [[Internal links|internal link]] points to a file located in the current vault. An [[Basic formatting syntax#External links|external link]] points to a location outside the vault, typically a web page.

## Main area

The **main area** is the central area of the Obsidian app, where you primarily edit [[#note|notes]].

## Markdown

Markdown is a markup language for formatting text and the primary file format used for notes in Obsidian, `.md` files. See also [[Basic formatting syntax]].

## Note

A **note** is a Markdown file inside a [[#vault]].

## Note

## Plugin

A **plugin** extends Obsidian with additional features.

- [[Core plugins]] are written by the Obsidian team and included by default.
- [[Community plugins]] are written by third-party plugin developers and need to be [[Community plugins#Install a community plugin|installed]] before you can use them.

You can [build your own plugin](https://docs.obsidian.md/Plugins/Getting+started/Build+a+plugin).

## Pop-out window

By default, all notes within a vault opens in the same app window. A **pop-out window** lets you open notes from the same vault in separate windows, for example to display on a second screen.

See also [[Pop-out windows]].

## Property

[[Properties|Properties]] define additional information about a note, such as a due date or author.

## Ribbon

The **ribbon** functions as a container for frequently used action icons. 

In the desktop version, it's the vertical area situated on the far left. 

In the mobile version, it's represented by a menu button ( ![[lucide-menu.svg#icon]] ) on the [[#status bar|status bar]].

## Sidebar

An area that contains supporting [[#view|views]] organized as [[#tab|tabs]]. A sidebar can be split into multiple [[#tab group|tab groups]]. 

Obsidian desktop has two sidebars, one on each side of the [[#main area]]. Both sidebars can be accessed by icons in the upper-left and upper-right corners in the Obsidian app, in addition to swiping left or right. The upper-right icon must be held to open the window.

## Snippet

A **snippet**, or [[CSS snippets|CSS snippet]], changes the appearance of Obsidian, just like a [[#theme]]. Unlike themes, you can apply multiple snippets at the same time.

## Status bar

The **status bar** in the Obsidian application shows you essential statistics and statuses. In the desktop version, you'll find it in the bottom-right corner, while on mobile devices, it's positioned along the bottom of the app.

## Tab

A **tab** contains a [[#view]]. Tabs can be repositioned within the [[#main area]] and the [[#sidebar|sidebars]]. See also [[Tabs]].

## Tab group

A **tab group** is a collection of [[#tab|tabs]] in the [[#main area]]. Tabs in a tab group can be stacked.

## Tag

A **tag** is a word that starts with a hash (`#`), for example `#book`. Tags are primarily used to find related [[#note|notes]].

## Theme

A **theme** changes the appearance of the Obsidian app using [CSS](https://developer.mozilla.org/en-US/docs/Web/CSS). You can override parts of a theme using [[#snippet|snippets]].

## Vault

A **vault** is a folder on your file system which contains [[#note|notes]] and an `.obsidian` folder with Obsidian-specific configuration. See also [[How Obsidian stores data]].

## View

A **view** displays information, for example the [[Search|Search view]].

Notes in Obsidian are stored as plain text files. This means your data is durable and not locked into a proprietary format. By writing your notes in plain text, they'll outlive any app—even Obsidian itself.

## Create a new note

To create a new note:

1. Press `Ctrl+N` (or `Cmd+N` on macOS) on your keyboard.
2. Type "Obsidian" as the name of your note and press `Enter`.
3. Copy and paste the following text into your note:

> Obsidian is the private and flexible writing app that adapts to the way you think.

## Formatting text

Obsidian supports [[Basic formatting syntax|Markdown]] syntax to make text bold, italic, and add links and headings.

1. Copy and paste the following text at the top of the Obsidian note:

   > \# Sharpen your thinking.

   The hash symbol (`#`) turns a line of text into a heading.

2. In your note, select any text and press `Ctrl+B` (or `Cmd+B` on macOS) to make it bold.

To learn more about how to format your notes using Markdown, refer to [[Basic formatting syntax]].

## Learn more

Learn how to [[Link notes|link notes]] to create a network of connected thoughts.

A vault is a folder on your local file system where Obsidian stores your notes. You can keep all your notes in one vault, or create several vaults for each of your different projects.

The first time you open Obsidian, you'll be asked to add a new vault. You have two options, either create a new empty vault, or use an existing folder.

## Create empty vault

To create a new empty vault:

1. To the right of **Create new vault**, click **Create**.
2. In **Vault name**, enter the name of your vault.
3. Click **Browse** to select where your new vault will be created.
4. Click **Create**.

## Open existing folder

If you already have a folder that you want to use as your vault:

1. To the right of **Open folder as vault**, click **Open**.
2. In the file browser, select the folder you want to use as your vault.
3. Click **Open**.

If you want to know more about how vaults work, learn how [[How Obsidian stores data]].

Now that you've set up your vault, you're ready to [[Create your first note]].

While Obsidian is great for taking notes, the true power of Obsidian lies in being able to link your notes together. By understanding how one piece of information relates to another, you can improve your ability to remember them and to form deeper insights. In this guide, you'll learn how to create and navigate links in Obsidian.

## Step 1: Create a link

In this step, you'll create two notes and link them together using the \[\[double bracket syntax\]\].

1. [[Create your first note|Create a note]] with the name "Three laws of motion":

   > The laws of motion are three laws stated by Isaac Newton, that describe the relationship between the motion of an object, and the forces acting on it.

2. Create another note with the name "Law of Inertia" with the following text:

   > The Law of Inertia is one of the

3. At the end of the sentence, press the left square bracket (`[`) twice on your keyboard.
4. Type "three" to find the first note you created.
5. Press `Enter` to create a link to the highlighted note.

   > The Law of Inertia is one of the \[\[Three laws of motion\]\]

Open the "Three laws of motion" note by clicking on the link while pressing `Ctrl` (or `Cmd` on macOS).

## Step 2: Create a link to a non-existing note

You can create links to notes that don't exist yet, for when you want to dive into a topic at a later time.

1. In your "Three laws of motion" note, select the text "Isaac Newton".
2. Press the left square bracket (`[`) twice on your keyboard to create a link. The second link has a more muted color to indicate that the note doesn't exist yet.
3. Create the note by clicking on the link while pressing `Ctrl` (or `Cmd` on macOS).

## Step 3: Navigate between notes

As you've seen in the previous steps, you can click a link while pressing `Ctrl` (or `Cmd` on macOS) to go to the linked note.

Another way to navigate between notes is through _backlinks_. A backlink lets you navigate in the opposite direction of an existing link.

1. Open the "Isaac Newton" note.
2. In the right sidebar, click the **Backlinks** tab.
3. Under **Linked mentions**, click the mention in "Three laws of motion" to go to that note.

Another way to navigate between your notes is by using a visual representation of how your notes are connected.

**Desktop**
1. In the upper-right corner of the note, click **More options** (three dots).
2. Select **Open linked view**.
3. Select **Open local graph**.
4. Click any of the nodes in the graph to navigate to that note.

**Mobile**
1. In the top of the note, select **More options** (three dots).
2. Select **Open local graph**.
3. Click any of the nodes in the graph to navigate to that note.

Understanding how your notes are connected becomes increasingly more difficult as your vault grows. Learn how to use the [[graph view]] to gain deeper insights from your knowledge base.

Obsidian checks for new updates regularly. When a new update is available, Obsidian applies it when you restart the application.

## Check for an update and the current version

Open **Settings → General**.

You can find the current Obsidian version and installer version in the upper-left corner.

![[application-installer-current-version.png#interface]]

To apply any available updates, click **Relaunch**.

## Disable automatic updates

If you prefer to update Obsidian manually, you can disable automatic updates.

1. Open **Settings → General**.
2. Disable **Automatic updates**.

## Installer updates

Occasionally, Obsidian [release notes](https://obsidian.md/changelog/) will indicate that a manual installer update is required, and include a link to our website. These updates address the scaffolding of Obsidian, and cannot be handled within the automatic update process. 

> [!tip] 
> You **do not** need to uninstall Obsidian to update the installer version.

To update Obsidian when an installer update is required:

1. Navigate to [https://obsidian.md/download](https://obsidian.md/download "https://obsidian.md/download").
2. Download the installer onto your system.
	1. If Obsidian is open, completely close it.
3. Run the installation process as directed in [[Download and install Obsidian]].

Your installer update is now complete. You may now re-open Obsidian.

> [!Question]- Q1. A plugin author or theme developer is asking me to update my installer, but the Obsidian team has not. Why?
> This is very common when we have internal library updates within the installer that do not need a minimum application version update, which would force everyone to update. 
> 
> For example, if you were using a PDF annotation plugin, and we updated the `pdf.js` library within Obsidian, the plugin author would want to take advantage of updates of that library. 
>
> Similarly, updated CSS capability would prompt a theme developer to require an installer update, so you can have the benefit of some new options that allow more styling features. 

## Troubleshooting

Some features may depend on a more recent installer version. If you experience issues with a recently added feature, consider [[Download and install Obsidian|reinstalling Obsidian]] to update the installer version.

Apps come and go, but your data should last. Obsidian uses non-proprietary plain text Markdown files stored locally on your device. You have total control over your data, which means you can use Obsidian offline and switch to another app easily if you ever need to.

## Import from other apps and file formats

- <span class="icon-app icon-notion"></span> [[Import from Notion|Notion]]
- <span class="icon-app icon-roam"></span> [[Import from Roam Research|Roam Research]]
- <span class="icon-app icon-onenote"></span> [[Import from Microsoft OneNote|Microsoft OneNote]]
- <span class="icon-app icon-evernote"></span> [[Import from Evernote|Evernote]]
- <span class="icon-app icon-apple-notes"></span> [[Import from Apple Notes|Apple Notes]]
- <span class="icon-app icon-google-keep"></span> [[Import from Google Keep|Google Keep]]
- <span class="icon-app icon-bear"></span> [[Import from Bear|Bear]]
- <span class="icon-app icon-html"></span> [[Import HTML files|HTML files]]
- <span class="icon-app icon-md"></span> [[Import Zettelkasten notes|Zettelkasten notes]]
- <span class="icon-app icon-md"></span> [[Import Markdown files|Markdown files]]

## More formats

Don't see your app? You can request it or contribute to the [open-source repository](https://github.com/obsidianmd/obsidian-importer) for the [[Importer]] plugin.

Additional guides have been shared by our community that may help you migrate to Obsidian: 

- [Craft](https://github.com/obsidianmd/obsidian-importer/issues/27)
- [Day One](https://github.com/obsidianmd/obsidian-importer/issues/55)
- [Diaro](https://github.com/obsidianmd/obsidian-importer/issues/38)
- [Logseq](https://github.com/obsidianmd/obsidian-importer/issues/47)
- [Remnote](https://forum.obsidian.md/t/can-anybody-help-with-migrating-remnote-to-obsidian/40156/2)
- [TiddlyWiki](https://forum.obsidian.md/t/import-from-tiddlywiki-5-to-obsidian/731)
- [TheBrain](https://github.com/obsidianmd/obsidian-importer/issues/97)
- [Ulysses](https://github.com/obsidianmd/obsidian-importer/issues/18)
- [Zim](https://github.com/obsidianmd/obsidian-importer/issues/39)
- [zkn3](https://forum.obsidian.md/t/migrating-from-zkn3-to-obsidian-without-losing-your-tags-and-internal-links-documentation/7457)

Syncing means keeping your notes up to date across your devices, such as your laptop and phone.

The easiest way to sync your notes between your devices is to use [[Introduction to Obsidian Sync|Obsidian Sync]]. If you already have an Obsidian Sync subscription, see how to [[Set up Obsidian Sync]].

Note that using multiple syncing services at the same time (e.g., Obsidian Sync _and_ Dropbox) may cause data loss, corruption, and other issues. [[Back up your vault|Find out more about using Obsidian Sync with other services here.]]

> [!important] Dealing with on-demand cloud storage
> Some cloud storage services, such as OneDrive, allow you to only download files when you use them and later remove them locally to free up space. Since the files are no longer available locally, Obsidian Sync believes they've been deleted and removes them from your remote vault.
>
> To use Obsidian Sync together with Files On-Demand and similar features, make sure to configure the service to always keep the files on the device.
^sync-files-on-demand

If you don't want to use Obsidian Sync, this page lists alternative methods for syncing your vaults with multiple devices.
## Sync notes across multiple desktops

If you don't use Obsidian on your mobile devices, you can use any third-party service that syncs a local folder to a cloud storage.

For example, you can use any of the following services:

- Dropbox
- Google Drive
- iCloud Drive
- OneDrive
- Syncthing

To sync your notes, follow the instructions for the service you're using to sync a folder on your local file system. Then open the folder as an existing vault on all your desktop devices.

docs/obsidian-help/Getting started/Sync your notes across devices.md

## Sync your notes on iPhone and iPad

To sync your notes to your iPhone or iPad, we officially support the following options:

- [[#iCloud Drive]]

**Note:** The following services aren't supported. If you discover a way to sync your notes on your iOS device using any of these services, let us know on our community channels.

- Dropbox
- OneDrive

### iCloud Drive

Obsidian can use iCloud Drive as a local file system.

When utilizing iCloud Drive on macOS, make sure to upgrade your desktop app's installer version to v0.13.0 or later. Additionally, ensure that you do not surpass your iCloud storage limit, as exceeding it could lead to syncing interruptions.

> [!tip]
> Ensure that you disable "**Optimize Mac Storage**" in iCloud Drive's settings before syncing your Obsidian vault using iCloud Drive on macOS. Failing to disable this feature could cause iCloud Drive to offload your files, rendering them unusable by Obsidian, and potentially leading to unexpected behavior.

#### Create a new vault in iCloud Drive

To create a new vault in iCloud Drive on your iPhone or iPad:

1. Tap **Create new vault**.
3. Enable **Store in iCloud**.
4. Tap **Create**.

Obsidian has created a new folder inside your iCloud Drive. To open the iCloud Drive folder as a vault on your computer:

1. On your computer, open **Obsidian**.
2. At the right of **Open folder as vault**, select **Open**.
3. Navigate to **iCloud Drive → Obsidian**.
4. Select the folder with the name of the vault you want to sync with.

#### Sync an existing vault with iCloud Drive

To sync an existing vault using iCloud, you need to create an empty vault in iCloud Drive and then move your notes on your other device to the empty vault.

To create a new empty vault in iCloud Drive:

2. In **Vault name**, enter the same name as the vault you want to sync with.

To move your notes to the new vault in your iCloud Drive:

1. On your computer, open the **iCloud Drive** folder.
2. Open the **Obsidian** folder. It might take a few minutes to appear.
3. Move the files in your existing vault to the folder with the name of your vault.

iCloud syncs the files to your mobile device. Depending on the size of your vault, this might take a few minutes.

### Working Copy

If you store your notes in a [Git](https://git-scm.com/) repository, you may want to look at [Working Copy](https://apps.apple.com/us/app/working-copy-git-client/id896694807)—a Git client for your iOS.

To sync using Working Copy:

1. Create an empty vault on your iPhone or iPad.
2. Use the **Setup Folder Sync** action and select your empty vault.
3. Commit and push any changes to your vault using the Working Copy app.

**Note:** While we don't officially support this method, several of our users have reported that they've successfully used Working Copy to sync their notes.

### Why can't I sync using X?

We understand that many of you use other services for syncing files and you'd prefer to use it for syncing your notes as well.

Obsidian works differently from other Markdown editors on iOS. Editors such as 1Writer and iA Writer access one note at a time, which lets them use built-in support for documents.

In contrast, many features in Obsidian need access to your entire vault. For example if you rename a file, then Obsidian needs to update all files in the vault that links to that file.

Implementing a system to read, modify, and monitor an entire folder structure comprising of possibly thousand of notes outside of the supported locations is challenging. We hope to address this limitation in the future.

If you're a developer, you can build a plugin that uses the Web APIs for each individual sync service.

### Where are my vaults stored?

If you choose not to use iCloud Drive when you create your vault, Obsidian stores it in a local file system for the Obsidian app. Other apps, such as [[#Working Copy]], can access your vault by selecting the vault from the file system.

**Caution:** Any notes stored in the local file system are deleted by iOS when you uninstall the app. Make sure to back up your notes before you uninstall the Obsidian app.

## Sync notes on Android

The easiest way to sync your notes on your Android device is using [[Introduction to Obsidian Sync|Obsidian Sync]].

Since Obsidian stores notes in a local folder on your Android device, you can also use any app that let you sync a folder, such as:

- [Dropsync](https://play.google.com/store/apps/details?id=com.ttxapps.dropsync)
- [FolderSync](https://play.google.com/store/apps/details?id=dk.tacit.android.foldersync.lite)

**Note:** Obsidian creates an Obsidian folder in the shared Documents folder. Any folder under `Documents/Obsidian` is considered an Obsidian vault.

## Config folders

You can utilize the ability to change your configuration folder per device, to maintain device specific settings even when using a syncing service. 

![[Configuration folder#Changing your config folder]]

The mobile app aims to provide a familiar user experience for those already using the desktop app.

That being said, there are a few features unique to the mobile app. In this guide, you’ll learn about them to get the most use out of the mobile app.

## Mobile toolbar

Mobile toolbar is a customization toolbar for editing notes.

When editing a note, you will notice a row of icons at the bottom of the app. The default arrangement of actions provides quick access to commonly used functionalities. You can customize them as well.

> [!tip] Scroll the toolbar
> If you have lots of actions on the toolbar, you can swipe left and right on the toolbar to reveal more actions.

### Customize mobile toolbar

In the mobile toolbar, tap **Configure mobile toolbar** ( ![[lucide-wrench.svg#icon]] )  to open the interface to customize it.

Alternatively, you can do it in Settings.

1. Open Settings.
2. Choose **Mobile**.
3. Under **Manage toolbar options**, add, remove, or reorder the available options.

### Add command to mobile toolbar

By default, the options that are available to be added to the toolbar are editing options like "Add internal link" or "Add tag".

In addition to that, you can add global commands like "Change theme".

1. Find **Manage toolbar options** under **Settings** → **Mobile**.
2. Scroll to the very bottom, find **Add global command**.
3. Type the name of the command you wish to add.
4. Select the command you’ll like to add.
5. The new command gets added to the end of the toolbar.

## Quick Action

On the mobile app, you can define one action that gets invoked by pulling down from the top of the app, similar to how you would pull to refresh on social media apps.

Quick Action defaults to open [[Command palette]].

### Customize Quick Action

3. Under **Configure mobile Quick Action**, tap **Configure**.
4. Type the name of the command.
5. Select the command you’d like to set.
6. Close the setting page.

Now, when you pull down from the top, the new Quick Action will be invoked.

## Navigation bar

The navigation bar on mobile helps you navigate the app. The navigation bar shows up when you’re not editing the app.

With the **Toggle keyboard** toolbar option, you can close the mobile toolbar and switch to the navigation bar instead.

### Go back or forward

On the navigation bar, the first two options helps you go back (back arrow icon) or forward (forward arrow icon). If one of the options is not available, the icon is greyed out.

### Create or find note

The middle plus in circle icon lets you create a new note or switch to an existing note. This is equivalent to opening [[Quick switcher]].

### Tab management

The second icon to the right shows you how many tabs are currently open. The icon looks like a number in a box.

When you tap it, you’ll be able to switch to any open tab. You can also open a new tab.

### Ribbon actions

The mobile app has no [[Ribbon]]. Instead, the ribbon actions will be available when you tap **Open menu** ( ![[lucide-menu.svg#icon]] ), the last option on the navigation bar.

### Right sidebar

The right sidebar can be accessed by swiping left either while editing the active note or in the Reading view by holding the triple-dot icon in the upper-right corner.

This page lists all supported ways to download and install Obsidian.

## Install Obsidian on Windows

1. Open your browser and go to [Download Obsidian](https://obsidian.md/download).
2. Under **Windows**, click **64-bit installer** to download the installation file.
3. Open the installation file and follow the instructions.
4. Open Obsidian the same way you would open any other application.

> [!tip] System installer available
> For those who require a system installer for Windows, you can find the `-allusers.exe` download on the [Releases](https://github.com/obsidianmd/obsidian-releases/releases) page.

## Install Obsidian on macOS

2. Under **macOS**, click **Universal DMG (Intel and M1)** to download the installation file.
3. Open the installation file.
4. In the window that opens, drag Obsidian to the Applications folder.
5. Open Obsidian the same way you would open any other application.

## Install Obsidian on Linux

If you use Linux, you can install Obsidian in several ways. Follow the instructions for the packaging system that you're using.

### Install Obsidian using Snap

2. Under **Linux**, click **Snap** to download the installation file.
3. Open a terminal and navigate to the folder where you downloaded the installation file.
4. In the terminal, run the following command to install the Snap package: (the `--dangerous` flag is required because Canonical, the company who created Snap, didn't review our package, the `--classic` flag allows Obsidian to access outside of the sandbox, where your notes are stored)

   ```bash
   snap install obsidian_<version>_<arch>.snap --dangerous --classic
   ```

docs/obsidian-help/Getting started/Download and install Obsidian.md

### Install Obsidian using AppImage

2. Under **Linux**, click **AppImage** to download the installation file.
4. In the terminal, run the following command to open Obsidian:

   ```bash
   chmod u+x Obsidian-<version>.AppImage
   ./Obsidian-<version>.AppImage
   ```

### Install Obsidian using Flatpak

1. In your terminal, run the following command to install Obsidian:

   ```bash
   flatpak install flathub md.obsidian.Obsidian
   ```

2. Open Obsidian by running the following command:

   ```bash
   flatpak run md.obsidian.Obsidian
   ```

## Install Obsidian on Android

1. Find Obsidian on the [Play Store](https://play.google.com/store/apps/details?id=md.obsidian).
2. Tap **Install** to download the app.
3. Open Obsidian the same way you would open any other app.

## Install Obsidian on iPhone and iPad

1. Find Obsidian on the [App Store](https://apps.apple.com/us/app/obsidian-connected-notes/id1557175442).
2. Tap **Get** to download the app.

Obsidian Credit is a type of prepaid credit. It can be bought in advance and applied towards purchases of all things Obsidian has to offer.

Obsidian Credit will be applied before any payment is due, and it will also be applied at auto-renewals.

## Add credit

1. Log into your account [on our Account page](https://obsidian.md/account).
2. Under **Payment & billing → Obsidian Credit**, click **Add**.
3. Enter the amount of Obsidian Credit you want to buy. The amount is in US dollars.
4. Proceed to pay for the credit with any of the supported payment methods.

> [!Note] Sales tax
> Any applicable sales tax will be charged when you actually buy something, not when you buy Obsidian Credit.
>
> If you plan to cover auto-renewals with your credit, please take this into account.

If you use Obsidian for work in a company with two or more employees, you must purchase a Commercial license.

You and your team may use Obsidian commercially for free for 14 days to evaluate the app before purchase. For bulk discounts, [[Help and support|contact Obsidian support]].

## What is considered commercial use?

Commercial use includes, but isn't limited to, work-related activities such as:

- Meeting notes
- Project notes for teams
- Organizational wikis

You don't need a Commercial license if you work in any of the following settings:

- Schools and recognized educational institutions
- Non-commercial research
- Non-profit organizations
- Freelancing or companies with a single person

## Purchase and activate a commercial license

To purchase a commercial license, follow the steps below. You can find pricing information on the [pricing page](https://obsidian.md/pricing).

1. Create or login to [your Obsidian account](https://obsidian.md/account).
2. Scroll down to the **Commercial license** section.
3. Click **Buy license** and choose the number of seats you want to purchase.
4. Complete the payment process.
5. The license key will be displayed and can be activated using the steps below.

To activate a commercial license:

1. Open the Obsidian app.
2. Go to **Settings → General → Commercial license**.
3. Click **Activate** and enter your license key.
4. You're done! The app is now licensed for commercial use.

## FAQ

> [!question]- Q1. How do I activate my commercial license?
> You can activate your commercial license under **Settings → General → Commercial license**. See detailed instructions above.

> [!question]- Q2. Can I try Obsidian for commercial use before paying?
> Yes. You and your team may evaluate Obsidian for commercial use for 14 days. You don't need to pay before evaluating.

> [!question]- Q3. Can I buy a license for myself, or do I have to ask my company to buy it for me?
> Yes, you can buy the license for yourself by going to your [Account dashboard](https://obsidian.md/account). Most  companies will allow you to submit an expense report for the purchase. Some companies may have a different procurement process.

> [!question]- Q4. I work at the IT department and need to purchase commercial licenses for our employees. What should I do?
> You only need to sign up for one admin account and buy one Obsidian commercial license with seats equal to the number of employees who will use Obsidian in your company.
> 
> After purchasing the license, you will be given a license key which you can send to the employees to activate their license — see instructions above to activate the license. There’s no need for each employee to have an Obsidian account.

> [!question]- Q5. Do non-profit organizations require a commercial license?
> No, registered non-profit organizations may use Obsidian without a commercial license.

> [!question]- Q6. Are there bulk discounts?
> To purchase seat licenses in bulk, please [[Help and support#Contact Obsidian support|contact Obsidian support]].

> [!question]- Q7. How can I ask my company to purchase licenses for me or my team?
> Ask your IT department to [[Help and support#Contact Obsidian support|contact Obsidian support]] if they have questions or require any specific paperwork.

> [!question]- Q8. Do I need a commercial license?
> Per our [Terms of Service](https://obsidian.md/terms), if you use Obsidian for commercial use, you must obtain a commercial license. Commercial use is defined as using Obsidian for work-related activities in a for-profit company with two or more employees.

> [!question]- Q9: I'm a writer/blogger, do I need a commercial license?
> If your writing is for-profit—for example you write on a blog that generates revenue via ads or sponsorships—and your business employs two or more people, then yes, you need a commercial license.

> [!question]- Q10: I'm a solo freelancer/consultant, but my work indirectly contributes to "revenue-generating, work-related activities in a company that has two or more people". Do I need a commercial license?
> No, as long as you remain the sole employee of your freelance/consulting business, you don't need a commercial license.

> [!question]- Q11: I'm a teacher/professor, or I work at a school, and I use Obsidian for my teaching/lectures. Do I need a commercial license?
> Obsidian usage for education-related activities within schools and other recognized educational institutions doesn't require a commercial license.

> [!question]- Q12: I'm an academic researcher and I use Obsidian for my research work. Do I need a commercial license?
> If your research involves producing a commercial product—for example if your research contributes to revenue-generating commercial activities—you need a commercial license for your usage. If your research doesn't contribute to a commercial product, or if your research has not yet led to commercial activities, you don't need a license.

> [!question]- Q13: I work for a government or an arm's length body or agency. Do I need a commercial license?
> Yes, you need a commercial license. Per our [Terms of Service](https://obsidian.md/terms), if you use Obsidian for commercial use, you must obtain a commercial license. Commercial use is defined as using Obsidian for work-related activities in a for-profit company with two or more employees. Registered charitable and non-profit organizations are exempted.

> [!question]- Q14: I use Obsidian during work for things like writing down team processes and taking notes for team meetings. Do I need a commercial license?
> If you are a single-person company, then you don't require a commercial license. Otherwise, if you have more than one person in the company, then you would require a commercial license.

> [!question]- Q15: I use Obsidian to store all of my knowledge, both personal and professional, because it's difficult to separate them. Do I need a commercial license?
> If your notes contain content directly related to work projects or processes for a greater-than-one-person company, then you require a commercial license.

> [!question]- Q16: I’m still not sure if I need a commercial license. What should I do?
> If you still have questions regarding the commercial license requirements, [[Help and support#Contact Obsidian support|contact Obsidian support]] and describe your situation in detail.

Although using Obsidian for personal use is completely free of charge, you can give the gift of Obsidian to someone to help them get an add-on service like [[Introduction to Obsidian Sync|Obsidian Sync]], or to get a [[Commercial license]] so they can use Obsidian for work.

## Give gift credits

In Obsidian, you don’t gift a particular product, but rather Obsidian Credit that can be used towards anything. It’s like an Obsidian gift card.

1. If you don’t already have [[Obsidian Credit]], you must first [[Obsidian Credit#Add credit|purchase credit]].
2. [On the Account page](https://obsidian.md/account), under **Payment & billing → Obsidian Credit**, click **Gift**.
3. Follow the instructions to either get a redeem link to send yourself, or have us send an anonymized email to the recipient.
4. Click **Send gift** to complete the gifting.
5. After you send out a gift, you can view it under **Payment & billing → Gift history**. You can see the status of each gift, and cancel the ones that haven’t been redeemed yet.

Obsidian currently offers two types of discounts: education and non-profit. They both give you 40% off our add-on services, including [[Introduction to Obsidian Sync|Obsidian Sync]] and [[Introduction to Obsidian Publish|Obsidian Publish]].

## How to apply

1. Go to [your account page](https://obsidian.md/account).
2. Under **Payment & billing**, find the **Discount** section, and click on the **"Apply"** link.
3. Select a discount type depending on your situation, fill out your **educational or organization email** (not your account email).
4. Click **Send application**.
5. In your school or organization email inbox, you should get an email from us to verify your email address. Click on the link to verify.
6. You might get instantly approved for the discount. If not, our team will try to review your application within 3 business days.
7. You’ll get an email when your discount gets approved.

Congratulations! Now you’ll see the discount when you try to purchase Obsidian Sync or Publish.

## How to renew

Once you have an active discount, you can see how it will expire under **Payment & billing → Discount** on [your account page](https://obsidian.md/account).

A week before your discount expires, you will get an email reminder to renew it. You can follow the same steps in "[[#How to apply]]" to renew the discount, if you still qualify for it.

docs/obsidian-help/Licenses and payment/Education and non-profit discount.md

['Student and non-profit discount', 'Licenses & Payment/Education and non-profit discount']

## FAQ

> [!FAQ]- Q1. How long does the application process take?
> If your application isn't approved instantly after verifying your email, our team will review it. It will take up to 3 business days.
>
> You don’t need to constantly check the account page for updates. We’ll send an email when you’re approved. Thanks for the patience and understanding!

> [!FAQ]- Q2. Do these discounts work with early bird pricing?
> Thanks for being an early bird! None of these discounts stack with the early bird pricing, as early bird is likely the highest discount we’ll ever give out.
>
> If you’re already an early bird, there’s generally no point in applying for discounts. But keep in mind that early bird pricing is separate for Sync and Publish, so if you missed early bird pricing for one of them, you may still want to apply for a discount.

> [!FAQ]- Q3. Who’s eligible?
> If you are a student or faculty member of an education organization like a university or a high school, you generally qualify for education discount.
>
> If you run or work at a non-profit organization, you generally qualify for non-profit discount.

> [!FAQ]- Q4. What if my educational or non-profit organization doesn't provide an email address?
> In that case, you can send other forms of verification such as student ID card, transcript, or employee ID card to the [[Help and support#Contact Obsidian support|Obsidian support]]. Be sure to include your Obsidian account email address too.
>
> Our team will review your application and get back to you. Thanks for your patience and understanding!

> [!FAQ]- Q5. I qualify for a discount, but I already paid. Can I get a refund?
> We understand that some people have purchased Sync or Publish without discounts either because discounts were not offered back then, or that you didn't know about the discount.
>
> Unfortunately, we don't offer refunds in cases like this. Sorry! Thanks for your understanding.
>
> The good news is that future renewals will automatically have the discount applied, as long as you have a valid discount.

We offer full refunds within 7 days of purchase with no questions asked for the following services and licenses:

- [[Commercial license]]

> [!Warning] No refunds for Catalyst or Obsidian Credit
> [[Catalyst license|Catalyst licenses]] are **not** refundable. 
> 
> While they give you a number of benefits, they're intended to support the Obsidian development and aren't sold as products.
> 
> Similarly, we do not offer refunds for Obsidian Credit, as credit can be transferred to another account.
> 
> Sorry for the inconvenience.

> [!tip] Talk to a human
> If you have any trouble with a transaction, or you need a refund past 7 days after purchase due to exceptional circumstances, [[Help and support#Contact Obsidian support|contact Obsidian support]].

## Request a refund

2. Under **Payment & billing → Invoices & refunds**, click **View**.
3. Next to the payments you want a refund for, if you’re qualified for a refund, you’ll see a link to **Get refund**. Click on the click.
4. Your service will be removed and any auto-renewals will be cancelled as well. If you confirm to proceed, click **Request refund**.

## FAQ

> [!question]- Q1. What happens if I refund my service?
> If you are refunding an Obsidian Sync or Obsidian Publish subscription, any remote vaults or publish sites are deleted, and can not be retrieved even if you subscribe again.
>
> >[!info] Please note that this does not happen if your [[Sync limitations#How long do you keep my data after my subscription expires?|subscription expires]].
>
> If you are refunding an Obsidian Commercial license, the associated license key will be deactivated.
>

['Licenses & Payment/Refund policy', 'Cancel my subscription', 'Cancel subscription']

Obsidian is free for personal use. You can support the Obsidian development by purchasing a _Catalyst_ license.

Catalyst license gives you exclusive benefits including:

- Early access to [[#Enable early access versions|new versions]] of Obsidian
- Access to exclusive [[#Join our Insider channels|Insider channels]].
- Exclusive [[#Get your forum badge|forum badges]] and [[#Get your Discord badge|Discord badges]].

> [!Note] Commercial use
> If you use Obsidian for work in a company with two or more employees, you must purchase a [[Commercial license]].

## Catalyst tiers

The Catalyst license consists of three tiers: *Insider*, *Supporter*, and *VIP*.

| Benefits                                                                              | Insider | Supporter |   VIP    |
|---------------------------------------------------------------------------------------|:-------:|:---------:|:--------:|
| Early access to new versions                                                        |    ✓    |     ✓     |    ✓     |
| Access to exclusive development channels, `#insider-desktop` and `#insider-mobile` |    ✓    |     ✓     |    ✓     |
| Access to exclusive lounge channel, `#vip-lounge`                                 |         |     ✓     |    ✓     |
| Insider community badge                                                               |    ✓    |           |          |
| Supporter community badge                                                             |         |     ✓     |          |
| VIP community badge                                                                   |         |           |    ✓     |
| **Pricing**                                                                           | **$25** |  **$50**  | **$100** |

_Prices are in USD._

> [!info] Upgrading tiers
> When you already own a Catalyst license, you can upgrade to a higher Catalyst tier by paying the price difference between your current and the new tier.

## Access Catalyst benefits

Once you've purchased a Catalyst license, you can access a range of benefits. Learn how to enable them here.

### Get your forum badge

**Note:** To connect your Obsidian account and your forum account, you must use the same email address for both accounts.

1. If you haven't already, join our [forum](https://forum.obsidian.md/).
2. Browse to your [Obsidian account page](https://obsidian.md/account).
3. Under **Your license → Obsidian Catalyst**, click **Get forum badge**.

### Get your Discord badge

1. If you haven't already, join our [Discord server](https://discord.gg/veuWUTm).
3. Under **Your license → Obsidian Catalyst**, click **Get Discord badge**.

### Join our Insider channels

Insiders can chat with the Obsidian team and other Insiders in our exclusive Discord channels. You automatically join the Insider channels after you [[#Get your Discord badge]].

### Enable early access versions

Learn how to receive [[Early access versions]].

Obsidian recognizes the following file formats:

1. Markdown files: `md`
2. Image files: `avif`, `bmp`, `gif`, `jpeg`, `jpg`, `png`, `svg`, `webp`
3. Audio files: `flac`, `m4a`, `mp3`, `ogg`, `wav`, `webm`, `3gp`
4. Video files: `mkv`, `mov`, `mp4`, `ogv`, `webm`
5. PDF files: `pdf`

Learn how to [[Embed files|embed files]] in your notes.

> [!note]
> Support for audio and video formats depends on the codecs available on your device.

You can manage files and folders in several ways, using [[Hotkeys]], [[Command palette|commands]], or [[File explorer]].

To create a new file:

1. Press `Ctrl+N` (or `Cmd+N` on macOS).
2. Enter the name of the note and then press `Enter` to start editing the note.

You can also create notes using [[File explorer#Create a new note|File explorer]], or by selecting **Create new note** from the [[Command palette]].

## Rename a note

To rename an active note:

1. Select the name of the note at the top of the editor (or press `F2`).
2. Enter the new name and then press `Enter`.

When you rename a file, Obsidian automatically updates all the links to that file.

You can rename a note or folder without opening it, by using [[File explorer#Rename a file or folder|File explorer]]

## Delete a note

To delete a note, select **More options → Delete file** at the upper right of an active note.

Or, select **Delete current file** from the [[Command palette]].

You can also delete a note or folder, using the [[File explorer#Delete a file or folder|File explorer]].

> [!note] What happens to files after I delete them?
> To change what happens to deleted files, select one of the following options under **Settings → Files & Links**:
>
> - **System trash**: By default, deleted files end up in the system trash for your operating system. To restore a file, use your preferred file manager.
> - **Obsidian trash**: You can send deleted files to a `.trash` folder in your vault.
> - **Permanently delete**: Files are immediately deleted without any means to restore them.

You can use [symbolic links](https://en.wikipedia.org/wiki/Symbolic_link) (symlinks) and [junctions](https://learn.microsoft.com/en-us/windows/win32/fileio/hard-links-and-junctions#junctions) in your vault to store files outside the vault and [[How Obsidian stores data#Global settings|system folder]].

> [!danger] Use at your own risk
> We strongly advise against using symbolic links. By using symbolic links and junctions in your vault, you risk losing or corrupting your data, or crashing Obsidian. Make sure you perform regular back-ups of your vault and settings.

Below are some limitations or issues we are aware of that you may want to keep in mind:

docs/obsidian-help/Files and folders/Symbolic links and junctions.md

- Symlink loops are disallowed, to prevent crashing Obsidian due to an infinite loop.
- Symlink targets must be fully disjoint from the vault root or any other symlink targets. Disjoint means one folder doesn't contain another, or vice versa. Obsidian ignores any symlink to a parent folder of the vault, or from one folder in the vault to another folder in the same vault. It is a safeguard to ensure you don't end up with duplicated files in your vault, which could cause links to become ambiguous.
- Symlinks may not play well with Obsidian sync, or _any other kind of sync_. If the target of a symlink is itself a folder that's synced by a different Obsidian vault, you could (potentially) end up with sync conflicts or data loss. Some sync tools, such as Git, don't follow symlinks, but rather sync the _path_ the symlink points to, which may produce undesirable results if you share your vault with other people that way.
- Obsidian's file manager can't move files across device boundaries, so if you symlink to a folder on a different drive from your vault, you won't be able to drag files between that folder and other folders using Obsidian's file explorer. (You'll need to use your OS's explorer for such moves, and Obsidian will see the move as a deletion and the creation of a new file. It will also _not_ update any links that depended on the path of that file.)
- File symlinks (as opposed to folder symlinks) _may_ work, but aren't officially supported at this time. Changes performed outside of Obsidian aren't watched for, so if you change the file directly, Obsidian won't detect the change, update search indexes, etc.
- Symlinking things under the `.obsidian/` folder in order to share them between vaults **has a high chance of corrupting your settings**, unless you _really_ know what you're doing. If you decide to go this way, at least have backups.

Obsidian's configuration folder contains all the settings files pertaining to your [[Manage vaults|vault]].

By default, your configuration folder is named `.obsidian` and placed in the vault folder. When using a syncing service, or if you wish to test different profiles in the same vault, you may want to change your config folder. 

## Changing your configuration folder

To set your config folder:

1. Open **Settings → Files and Links**.
2. In **Override config folder**, type the name of your profile, starting with a period (`.`). For example, `.obsidian-awesome`.
3. Relaunch Obsidian to have the changes take effect. 

> [!info] Any settings within your config folder will not transfer to your new config folder. However, your prior config folder will remain within your vault folder.

A **vault** is a folder on your file system which contains your notes, [[attachments]], and the [[configuration folder]] with Obsidian-specific settings. For more information on vaults, refer to [[How Obsidian stores data]].

You can manage your vaults using the **vault switcher**. The **vault switcher** opens the first time you open Obsidian.

To open the vault switcher from an existing vault, select **Open another vault** (vault icon) at the bottom of the [[Ribbon]]. Or, select **Open another vault** from the [[command palette]].

## Create new vault

1. On your computer, open Obsidian.
2. At the bottom left, select **Open another vault** ( ![[obsidian-vault-switcher.svg#icon]] ).
3. To the right of **Create new vault**, select **Create**.
4. In **Vault name**, enter the name of your vault.
5. Click **Browse** to select where your new vault will be created.
6. Click **Create**.

## Create vault from an existing folder

3. At the right of **Open folder as vault**, click **Open**.
4. In the file browser, select the folder you want to use as your vault.
5. Click **Open**.

> [!tip] Open vault from Obsidian Sync
> If you want to open a remote vault using Obsidian Sync, refer to [[Set up Obsidian Sync on another device]].

## Rename vault

Since the name of a vault and the underlying folder are the same, renaming a vault also renames the folder.

3. In the vault list, select **More options** (three dots icon) next to the vault you want to rename.
4. Select **Rename vault**.
5. Enter the new name for the vault, and press `Enter`.

['User interface/Vault switcher', 'How to/Working with multiple vaults', 'Vault switcher']

## Move vault to a different folder

3. In the vault list, select **More options** (three dots icon) next to the vault you want to move.
4. Select **Move vault**, and then select the new location.

## Remove vault

Removing a vault only removes it from the vault list. Your

3. In the vault list, select **More options** ! next to the vault you want to move.
4. Select **Remove from list**.

## Transfer settings to another vault

To use the same settings for another vault, use your preferred file manager (or terminal) to copy the `.obsidian` folder from the root of the source vault to the root of the destination vault.

You may need to restart Obsidian to apply the changes.

> [!note] Where do I find the `.obsidian` folder?
> By default, most operating systems hide folders starting with a period (`.`). For more information about the `.obsidian` folder and how to access it, refer to [[How Obsidian stores data#Vault settings|vault settings]] and [[Configuration folder|config folders]].

Obsidian stores your notes as [[Basic formatting syntax|Markdown-formatted]] plain text files in a _vault_. A vault is a folder on your local file system, including any subfolders.

Because notes are plain text files, you can use other text editors and file managers to edit and manage notes. Obsidian automatically refreshes your vault to keep up with any external changes.

You can create a vault anywhere your operating system allows. Obsidian syncs with [[Introduction to Obsidian Sync|Obsidian Sync]], Dropbox, iCloud, OneDrive, Git, and many other third-party services.

You can open multiple folders as individual vaults, for example to separate notes for work and personal use.

> [!warning] Vaults within vaults
> Because [[Internal links]] are local to a vault, we recommend that you don't create vaults within vaults. Links may not be updated correctly.

## Vault settings

Obsidian creates an `.obsidian` [[configuration folder]] in the root folder of the vault, which contains preferences specific to that vault, such as [[hotkeys]], [[themes]], and [[community plugins]].

By default, most operating systems hide folders that start with a period (`.`), so you may need to update the settings for your file manager to see it.

- **macOS**: In Finder, press `Cmd+Shift+.` (period) to show hidden files.
- **Windows**: [Show hidden files](https://support.microsoft.com/en-us/windows/show-hidden-files-0320fe58-0117-fd59-6851-9b7f9840fdb2)

> [!tip] Adding `.obsidian` to Git
> The `.obsidian/workspace` file stores the current workspace layout, and changes any time you open a new file. If you use [Git](https://git-scm.com) to version control your vault, you may want to add the `.obsidian/workspace` file to `.gitignore`.

docs/obsidian-help/Files and folders/How Obsidian stores data.md

## Global settings

Obsidian stores global settings in a system folder. The location of the system folder depends on the operating system you're using.

- **macOS**: `/Users/yourusername/Library/Application Support/obsidian`
- **Windows**: `%APPDATA%\Obsidian\`
- **Linux**: `$XDG_CONFIG_HOME/Obsidian/` or `~/.config/Obsidian/`

> [!warning]
> Don't create a vault in the system folder. This may lead to corrupted data or data loss.

You can import [[Accepted file formats]], or _attachments_, to your vault, such as images, audio files, or PDFs. Attachments are regular files that you can access using your file system.

## Add an attachment

You can add attachments to your vault in multiple ways. Only [[Accepted file formats]] can be added.

> [!todo]- Copy and paste attachments
> You can paste attachments directly into your notes. Obsidian creates a file with the pasted content in the default attachment location and [[Embed files|embeds]] it in the note.

> [!todo]- Drag and drop attachments
> If you drag a file from your file system into an open editor, Obsidian copies the file to the default attachment location and [[Embed files|embeds]] it in the note.

 > [!todo]- Download attachments to vault folder
 > You can download an attachment directly to your vault, for example if you  [[Import notes#Import from browser|import from your browser]], or from other apps that saves files directly to your file system.

## Change default attachment location

By default, attachments are added to the root of your vault.

You can change the default attachment location under **Settings → Files & Links → Default location for new attachments**.

- **Vault folder** adds the attachment to the root of your vault.
- **In the folder specified below** adds the attachment to a specified folder.
- **Same folder as current file** adds the attachment to the same folder as the note you added it to.
- **In subfolder under current folder** adds attachments to a specified folder next to the note you added the attachment to. If it doesn't exist, Obsidian creates it when you add an attachment.

Use callouts to include additional content without breaking the flow of your notes.

To create a callout, add `[!info]` to the first line of a blockquote, where `info` is the _type identifier_. The type identifier determines how the callout looks and feels. To see all available types, refer to [[#Supported types]].

```markdown
> [!info]
> Here's a callout block.
> It supports **Markdown**, [[Internal link|Wikilinks]], and [[Embed files|embeds]]!
> ![[Engelbart.jpg]]
```

> [!info]
> It supports **Markdown**, [[Internal links|Wikilinks]] and [[Embed files|embeds]]!

Callouts are also supported natively on [[Introduction to Obsidian Publish|Obsidian Publish]].

> [!note]
> If you're also using the Admonitions plugin, you should update it to at least version 8.0.0 to avoid problems with the new callout feature.

### Change the title

By default, the title of the callout is its type identifier in title case. You can change it by adding text after the type identifier:

> [!tip] Callouts can have custom titles
> Like this one.
```

You can even omit the body to create title-only callouts:

> [!tip] Title-only callout
```

### Foldable callouts

You can make a callout foldable by adding a plus (+) or a minus (-) directly after the type identifier.

A plus sign expands the callout by default, and a minus sign collapses it instead.

> [!faq]- Are callouts foldable?
> Yes! In a foldable callout, the contents are hidden when the callout is collapsed.
```

> Yes! In a foldable callout, the contents are hidden when collapsed.

### Nested callouts

You can nest callouts in multiple levels.

> [!question] Can callouts be nested?
> > [!todo] Yes!, they can.
> > > [!example]  You can even use multiple layers of nesting.
```

### Customize callouts

[[CSS snippets]] and [[Community plugins]] can define custom callouts, or even overwrite the default configuration.

To define a custom callout, create the following CSS block:

```css
.callout[data-callout="custom-question-type"] {
    --callout-color: 0, 0, 0;
    --callout-icon: lucide-alert-circle;
}
```

The value of the `data-callout` attribute is the type identifier you want to use, for example `[!custom-question-type]`.

- `--callout-color` defines the background color using numbers (0–255) for red, green, and blue.
- `--callout-icon` can be an icon ID from [lucide.dev](https://lucide.dev), or an SVG element. 

> [!warning] Note about lucide icon versions
> Obsidian updates Lucide icons periodically. The current version included is shown below; use these or earlier icons in custom callouts.
> ![[Credits#^lucide]]

> [!tip] SVG icons
> Instead of using a Lucide icon, you can also use a SVG element as the callout icon.
>
> ```css
> --callout-icon: '<svg>...custom svg...</svg>';
> ```

### Supported types

You can use several callout types and aliases. Each type comes with a different background color and icon.

To use these default styles, replace `info` in the examples with any of these types, such as `[!tip]` or `[!warning]`.

Unless you [[#Customize callouts]], any unsupported type defaults to the `note` type. The type identifier is case-insensitive.

> [!note]
> ```md
> > [!note]
> > Lorem ipsum dolor sit amet
> ```

---

> [!abstract]-
> ```md
> > [!abstract]
> ```

Aliases: `summary`, `tldr`

---

> [!info]-
> ```md
> > [!info]
> ```

---

> [!todo]-
> ```md
> > [!todo]
> ```

---

> [!tip]-
> ```md
> > [!tip]
> ```

Aliases: `hint`, `important`

---

> [!success]-
> ```md
> > [!success]
> ```

Aliases: `check`, `done`

---

> [!question]-
> ```md
> > [!question]
> ```

Aliases: `help`, `faq`

---

> [!warning]-
>  ```md
> > [!warning]
> ```

Aliases: `caution`, `attention`

---

> [!failure]-
> ```md
> > [!failure]
> ```

Aliases: `fail`, `missing`

---

> [!danger]-
> ```md
> > [!danger]
> ```

Alias: `error`

---

> [!bug]-
> ```md
> > [!bug]
> ```

---

> [!example]-
> ```md
> > [!example]
> ```

---

> [!quote]-
> ```md
> > [!quote]
> ```

Alias: `cite`

Learn how to get a better overview of large notes by using _folding_ to hide parts of the note. Folding is useful when creating outlines for your notes and when you want to focus on what you're working on at the moment.

You can fold headings and indented lists by hovering the mouse cursor over the section you want to fold, and then selecting the arrow on the left. Folded sections show an arrow regardless of if you hover it or not.

Folding is turned on by default. To turn off folding, open **Settings** → **Editor**, and then turn off **Fold indent** or **Fold heading**, depending on your needs.

To toggle all sections at the same time, use the following commands:

- To collapse all sections, open the [[Command palette]], and then select **Fold all headings and lists**.
- To expand all sections, open the [[Command palette]], and then select **Unfold all headings and lists**.

> [!tip]
> If you prefer to fold using your keyboard, you can assign [[Hotkeys|hotkeys]] to the **Fold less** and **Fold more** commands.
>
> - **Fold less** unfolds the section at the text cursor.
> - **Fold more** folds the section or list that contains the text cursor.

Learn how to use the [iframe](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe) HTML element to embed web pages in your notes.

To embed a web page, add the following in your note and replace the placeholder text with the URL of the web page you want to embed:

```html
<iframe src="INSERT YOUR URL HERE"></iframe>
```

> [!note]
> Some websites don't allow you to embed them. Instead, they may provide URLs that are meant for embedding them. If the website doesn't support embedding, try searching for the name of the website followed by "embed iframe". For example, "youtube embed iframe".

> [!tip]
> If you're using [[Canvas]], you can embed a web page in a card. For more information, refer to [[Canvas#Add cards from web pages]].

## Embed a YouTube video

To embed a YouTube video, use the same Markdown syntax as [[Basic formatting syntax#External images|external images]]:

```md
![](https://www.youtube.com/watch?v=NnTvZWp5Q7o)
```

## Embed a tweet

To embed a tweet, use the same Markdown syntax as [[Basic formatting syntax#External images|external images]]:

```md
![](https://twitter.com/obsdmd/status/1580548874246443010)
```

['How to/Embedding web pages', 'Iframe', 'Editing and formatting/Embedding web pages']

Obsidian lets you customize how to edit and preview notes with Markdown syntax using _editor views_ and _editor modes_.

Markdown is a markup language that uses special syntax to format text that's mainly useful when editing your notes. Less so when reading them. Instead, Obsidian can show them in a way that's more suitable for reading.

Editor views and modes lets you customize how Markdown syntax appears when you're editing and reading notes.

## Editor views

You can switch between the _editing view_ and _reading view_, depending on whether you intend to make changes to the note.

To switch between views, select the view switcher (open book icon or pencil icon) in the upper-right corner of the editor, or press `Ctrl+E` (or `Cmd+E` on macOS) in the editor.

> [!note]
> You need to enable **Settings → Appearance → Show tab title bar** to see the icon for switching views.

You can change the default editor view under **Settings → Editor → Default view for new tabs**.

> [!tip] Side-by-side preview
> To open a note in both editing and reading view side-by-side, press `Ctrl` (or `Cmd` on macOS) and select the view switcher (open book icon or pencil icon) in the upper-right corner of the editor.

## Editor modes

In Editing view, you can edit your notes using one of two modes, _Live Preview_ or _Source mode_.

You can change the default editor mode under **Settings → Editor → Default editing mode**.

### Live Preview

Live Preview is a smart editor mode that previews Markdown-formatted text while you're editing.

You can reveal the syntax for any Markdown-formatted text by moving the text cursor to it.

> [!tip]
> Since Live Preview lets you see the formatting in the editing view, it often removes the need to switch between editor views.

### Source mode

Source mode displays the Markdown syntax for the entire note.

Use Source mode if you prefer to see the plain text representation of the note.

docs/obsidian-help/Editing and formatting/Edit and preview Markdown.md

['How to/Read and edit modes', 'Editing and formatting/Editing and previewing Markdown']

Learn how to apply basic formatting to your notes, using [Markdown](https://daringfireball.net/projects/markdown/). For more advanced formatting syntax, refer to [[Advanced formatting syntax]].

## Paragraphs

To create paragraphs, use a blank line to separate one or more lines of text.

```
This is a paragraph.

This is another paragraph.
```

> [!note]- Multiple blank spaces
> Multiple adjacent blank spaces in and between paragraphs collapse to a single space when displaying a note in [[Edit and preview Markdown#Editor views|Reading view]] and on [[Introduction to Obsidian Publish|Obsidian Publish]] sites.
> 
> ```md
> Multiple          adjacent          spaces
> 
> 
> 
> and multiple newlines between paragraphs.
> ```
> 
> > Multiple          adjacent          spaces
> > 
> > 
> > 
> > and multiple newlines between paragraphs.
> 
> If you want to add multiple spaces, you can add `&nbsp;` (blank space) and `<br>` (newline) to your note.

## Headings

To create a heading, add up to six `#` symbols before your heading text. The number of `#` symbols determines the size of the heading.

```md
# This is a heading 1
## This is a heading 2
### This is a heading 3
#### This is a heading 4
##### This is a heading 5
###### This is a heading 6
```

%% These headings use HTML to avoid cluttering the Outline/Table of contents %%
<h1>This is a heading 1</h1>
<h2>This is a heading 2</h2>
<h3>This is a heading 3</h3>
<h4>This is a heading 4</h4>
<h5>This is a heading 5</h5>
<h6>This is a heading 6</h6>

docs/obsidian-help/Editing and formatting/Basic formatting syntax.md

## Bold, italics, highlights

Text formatting can also be applied using [[Editing shortcuts]].

| Style | Syntax | Example | Output |
|-|-|-|-|
| Bold | `** **` or `__ __` | `**Bold text**` | **Bold text** |
| Italic | `* *` or `_ _`  | `*Italic text*` | *Italic text* |
| Strikethrough | `~~ ~~` |  `~~Striked out text~~` | ~~Striked out text~~ |
| Highlight | `== ==` |  `==Highlighted text==` | ==Highlighted text== |
| Bold and nested italic | `** **` and `_ _`  | `**Bold text and _nested italic_ text**` | **Bold text and _nested italic_ text** |
| Bold and italic | `*** ***` or `___ ___` |  `***Bold and italic text***` | ***Bold and italic text*** |

## Internal links

Obsidian supports two formats for [[internal links]] between notes:

- Wikilink: `[[Three laws of motion]]`
- Markdown: `[Three laws of motion](Three%20laws%20of%20motion.md)`

## External links

If you want to link to an external URL, you can create an inline link by surrounding the link text in brackets (`[ ]`), and then the URL in parentheses (`( )`).

```md
[Obsidian Help](https://help.obsidian.md)
```

You can also create external links to files in other vaults, by linking to an [[Obsidian URI|Obsidian URI]].

```md
[Note](obsidian://open?vault=MainVault&file=Note.md)
```

### Escape blank spaces in links

If your URL contains blank spaces, you must escape them by replacing them with `%20`.

```md
[My Note](obsidian://open?vault=MainVault&file=My%20Note.md)
```

You can also escape the URL by wrapping it with angled brackets (`< >`).

```md
[My Note](<obsidian://open?vault=MainVault&file=My Note.md>)
```

## External images

You can add images with external URLs, by adding a `!` symbol before an [[#External links|external link]].

```md
![Engelbart](https://history-computer.com/ModernComputer/Basis/images/Engelbart.jpg)
```

You can change the image dimensions, by adding `|640x480` to the link destination, where 640 is the width and 480 is the height.

```md
![Engelbart|100x145](https://history-computer.com/ModernComputer/Basis/images/Engelbart.jpg)
```

If you only specify the width, the image scales according to its original aspect ratio. For example:

```md
![Engelbart|100](https://history-computer.com/ModernComputer/Basis/images/Engelbart.jpg)
```

> [!tip]
> If you want to add an image from inside your vault, you can also [[Embed files#Embed an image in a note|embed an image in a note]].

## Quotes

You can quote text by adding a `>` symbols before the text.

```md
> Human beings face ever more complex and urgent problems, and their effectiveness in dealing with these problems is a matter that is critical to the stability and continued progress of society.

\- Doug Engelbart, 1961
```

> [!tip]
> You can turn your quote into a [[Callouts|callout]] by adding `[!info]` as the first line in a quote.

## Lists

You can create an unordered list by adding a `-`, `*`, or `+` before the text.

```md
- First list item
- Second list item
- Third list item
```

To create an ordered list, start each line with a number followed by a `.` symbol.

```md
1. First list item
2. Second list item
3. Third list item
```

### Task lists

To create a task list, start each list item with a hyphen and space followed by `[ ]`.

```md
- [x] This is a completed task.
- [ ] This is an incomplete task.
```

You can toggle a task in Reading view by selecting the checkbox.

> [!tip]
> You can use any character inside the brackets to mark it as complete.
>
> ```md
> - [x] Milk
> - [?] Eggs
> - [-] Eggs
> ```
>
> - [x] Milk
> - [?] Eggs
> - [-] Eggs

### Nesting lists

All list types can be nested in Obsidian.

To create a nested list, indent one or more list items:

```md
   1. Ordered nested list item
   - Unordered nested list item
```

Similarly, you can create a nested task list by indenting one or more list items:

```md
- [ ] Task item 1
	- [ ] Subtask 1
- [ ] Task item 2
```

Use `Tab` or `Shift+Tab` to indent or unindent one or more selected list items for easy organization.
## Horizontal rule

You can use three or more stars `***`, hyphens `---`, or underscore `___` on its own line to add a horizontal bar. You can also separate symbols using spaces.

```md
***
****
* * *
---
----
- - -
___
____
_ _ _
```

***

## Code

You can format code both inline within a sentence, or in its own block.

### Inline code

You can format code within a sentence using single backticks.

```md
Text inside `backticks` on a line will be formatted like code.
```

If you want to put backticks in an inline code block, surround it with double backticks like so: inline ``code with a backtick ` inside``.

### Code blocks

To format a block of code, surround the code with triple backticks.

~~~
```
cd ~/Desktop
```
~~~

```md
```

You can also create a code block by indenting the text using `Tab` or 4 blank spaces.

```md
    cd ~/Desktop
```

You can add syntax highlighting to a code block, by adding a language code after the first set of backticks.

~~~md
```js
function fancyAlert(arg) {
  if(arg) {
    $.facebox({div:'#foo'})
  }
}
```
~~~

```js
  if(arg) {
  }
}
```

Obsidian uses Prism for syntax highlighting. For more information, refer to [Supported languages](https://prismjs.com/#supported-languages).

> [!note]
> [[Edit and preview Markdown#Source mode|Source mode]] and [[Edit and preview Markdown#Live Preview|Live Preview]] do not support PrismJS, and may render syntax highlighting differently.

## Footnotes

You can add footnotes[^footnote] to your notes using the following syntax:

[^footnote]: This is a footnote.

```md
This is a simple footnote[^1].

[^1]: This is the referenced text.
[^2]: Add 2 spaces at the start of each new line.
  This lets you write footnotes that span multiple lines.
[^note]: Named footnotes still appear as numbers, but can make it easier to identify and link references.
```

You can also inline footnotes in a sentence. Note that the caret goes outside the brackets.

```md
You can also use inline footnotes. ^[This is an inline footnote.]
```

> [!note]
> Inline footnotes only work in reading view, not in Live Preview.

## Comments

You can add comments by wrapping text with `%%`. Comments are only visible in Editing view.

```md
This is an %%inline%% comment.

%%
This is a block comment.

Block comments can span multiple lines.
%%
```

To learn more advanced formatting syntax, such as tables, diagrams, and math expressions, refer to [[Advanced formatting syntax]].

To learn more about how Obsidian parses Markdown, refer to [[Obsidian Flavored Markdown]].

Learn how to use keyboard shortcuts to navigate and edit text in your notes. You can also define [[Hotkeys|custom hotkeys]].

## Windows and Linux shortcuts

### Common actions

| Action | Shortcut |
|-|-|
| Copy | `Ctrl+C` |
| Cut | `Ctrl+X` |
| Paste | `Ctrl+V` |
| Paste without formatting | `Ctrl+Shift+V` |
| Undo | `Ctrl+Z` |
| Redo | `Ctrl+Shift+Z` or `Ctrl+Y` |
| Copy paragraph | `Ctrl+C` (with no selected text) |
| Cut paragraph | `Ctrl+X` (with no selected text) |

### Text editing

|-|-|
| Insert new line| `Enter` |
| Delete the previous character | `Backspace` |
| Delete the next character | `Delete` |
| Delete the previous word | `Ctrl+Backspace` |
| Delete the next word | `Ctrl+Delete` |
| Delete the current line | `Ctrl+Shift+K` (with no selected text) |

### Text navigation

|-|-|
| Move the cursor one character | `Left/right arrow` |
| Move the cursor to the beginning of the previous word | `Ctrl+Left arrow` |
| Move the cursor to the end of the next word | `Ctrl+Right arrow` |
| Move the cursor to the beginning of the current line | `Home` |
| Move the cursor to the end of the current line | `End` |
| Move the cursor to the previous line | `Up arrow` |
| Move the cursor to the next line | `Down arrow` |
| Move the cursor to the beginning of the note | `Ctrl+Home` |
| Move the cursor to the end of the note | `Ctrl+End` |
| Move the cursor up one page | `Page up` |
| Move the cursor down one page | `Page down` |

### Text selection

|-|-|
| Simplify selection | `Escape` |
| Select all | `Ctrl+A` |
| Extend selection one character | `Shift+Left/right arrow` |
| Extend selection to the beginning of the previous word | `Ctrl+Shift+Left arrow` |
| Extend selection to the end of the next word | `Ctrl+Shift+Right arrow` |
| Extend selection to the beginning of the current line | `Shift+Home` |
| Extend selection to the end of the current line | `Shift+End` |
| Extend selection to the beginning of the note | `Ctrl+Shift+Home` |
| Extend selection to the end of the note | `Ctrl+Shift+End` |
| Extend selection one page up | `Shift+Page up` |
| Extend selection one page down | `Shift+Page down` |

## macOS shortcuts

|-|-|
| Copy | `Cmd+C` |
| Cut | `Cmd+X` |
| Paste | `Cmd+V` |
| Paste without formatting | `Cmd+Shift+V` |
| Undo | `Cmd+Z` |
| Redo | `Cmd+Shift+Z` |
| Copy paragraph | `Cmd+C` (with no selected text) |
| Cut paragraph | `Cmd+X` (with no selected text) |

### Text formatting

| ---- | ---- |
| Bold text | `Cmd+B` |
| Italic text | `Cmd+I` |

|-|-|
| Delete the previous word | `Option+Backspace` |
| Delete the next word | `Option+Delete` |
| Delete to the beginning of the current line | `Cmd+Backspace` |
| Delete to the end of the current line | `Cmd+Delete` |
| Delete the current line | `Cmd+Shift+K` (with no selected text) |

|-|-|
| Move the cursor to the beginning of the previous word | `Option+Left arrow` |
| Move the cursor to the end of the next word | `Option+Right arrow` |
| Move the cursor to the beginning of the current line | `Cmd+Left arrow` |
| Move the cursor to the end of the current line | `Cmd+Right arrow` |
| Move the cursor to the beginning of the note | `Cmd+Up arrow` |
| Move the cursor to the end of the note | `Cmd+Down arrow` |
| Move the cursor up one page | `Ctrl+Up arrow` |
| Move the cursor down one page | `Ctrl+Down arrow` |

|-|-|
| Select all | `Cmd+A` |
| Extend selection to the beginning of the previous word | `Option+Shift+Left arrow` |
| Extend selection to the end of the next word | `Option+Shift+Right arrow` |
| Extend selection to the beginning of the current line | `Cmd+Shift+Left arrow` |
| Extend selection to the end of the current line | `Cmd+Shift+Right arrow` |
| Extend selection to the beginning of the note | `Cmd+Shift+Up arrow` |
| Extend selection to the end of the note | `Cmd+Shift+Down arrow` |
| Extend selection one page up | `Ctrl+Shift+Up arrow` |
| Extend selection one page down | `Ctrl+Shift+Down arrow` |

Learn how to add advanced formatting syntax to your notes.

## Tables

You can create table using vertical bars (`|`) and hyphens (`-`). Vertical bars separate columns, and hyphens define the column header.

```md
| First name | Last name |
| ---------- | --------- |
| Max        | Planck    |
| Marie      | Curie     |
```

The vertical bars on either side of the table are optional.

Cells don't need to be perfectly aligned with the columns. Each header row must have at least two hyphens.

```md
First name | Last name
-- | --
Max | Planck
Marie | Curie
```

### Format content within a table

You can use [[basic formatting syntax]] to style content within a table.

First column | Second column
-- | --
[[Internal links]] | Link to a file _within_ your **vault**.
[[Embed files]] | ![[og-image.png\|200]]

> [!note] Vertical bars in tables
> If you want to use [[aliases]], or to [[Basic formatting syntax#External images|resize an image]] in your table, you need to add a `\` before the vertical bar.
>
> ```md
> First column | Second column
> -- | --
> [[Basic formatting syntax\|Markdown syntax]] | ![[og-image.png\|200]]
> ```
>
> -- | --

You can align text to the left, right, or center of a column by adding colons (`:`) to the header row.

```md
Left-aligned text | Center-aligned text | Right-aligned text
:-- | :--: | --:
Content | Content | Content
```

docs/obsidian-help/Editing and formatting/Advanced formatting syntax.md

## Diagram

You can add diagrams and charts to your notes, using [Mermaid](https://mermaid-js.github.io/). Mermaid supports a range of diagrams, such as [flow charts](https://mermaid.js.org/syntax/flowchart.html), [sequence diagrams](https://mermaid.js.org/syntax/sequenceDiagram.html), and [timelines](https://mermaid.js.org/syntax/timeline.html).

> [!tip]
> You can also try Mermaid's [Live Editor](https://mermaid-js.github.io/mermaid-live-editor) to help you build diagrams before you include them in your notes.

To add a Mermaid diagram, create a `mermaid` [[Basic formatting syntax#Code blocks|code block]].

````md
```mermaid
sequenceDiagram
    Alice->>+John: Hello John, how are you?
    Alice->>+John: John, can you hear me?
    John-->>-Alice: Hi Alice, I can hear you!
    John-->>-Alice: I feel great!
```
````

```

````md
graph TD

Biology --> Chemistry
```
````

graph TD

```

### Linking files in a diagram

You can create [[internal links]] in your diagrams by attaching the `internal-link` [class](https://mermaid.js.org/syntax/flowchart.html#classes) to your nodes.

````md
graph TD

class Biology,Chemistry internal-link;
```
````

graph TD

```

> [!note]
> Internal links from diagrams don't show up in the [[Graph view]].

If you have many nodes in your diagrams, you can use the following snippet.

````md
graph TD

A[Biology]
B[Chemistry]

A --> B

class A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z internal-link;
```
````

This way, each letter node becomes an internal link, with the [node text](https://mermaid.js.org/syntax/flowchart.html#a-node-with-text) as the link text.

> [!note]
> If you use special characters in your note names, you need to put the note name in double quotes.
>
> ```
> class "⨳ special character" internal-link
> ```
>
> Or, `A["⨳ special character"]`.

For more information about creating diagrams, refer to the [official Mermaid docs](https://mermaid.js.org/intro/).

## Math

You can add math expressions to your notes using [MathJax](http://docs.mathjax.org/en/latest/basic/mathjax.html) and the LaTeX notation.

To add a MathJax expression to your note, surround it with double dollar signs (`$$`).

```md
$$
\begin{vmatrix}a & b\\
c & d
\end{vmatrix}=ad-bc
$$
```

$$
c & d
$$

You can also inline math expressions by wrapping it in `$` symbols.

```md
This is an inline math expression $e^{2i\pi} = 1$.
```

For more information about the syntax, refer to [MathJax basic tutorial and quick reference](https://math.meta.stackexchange.com/questions/5020/mathjax-basic-tutorial-and-quick-reference).

For a list of supported MathJax packages, refer to [The TeX/LaTeX Extension List](http://docs.mathjax.org/en/latest/input/tex/extensions/index.html).

Properties allow you to organize information about a note. Properties contain structured data such as text, links, dates, checkboxes, and numbers. Properties can also be used in combination with [[Community plugins]] that can do useful things with your structured data.

## Add properties to a note

There are several ways to add a property to a note:

- Use the **Add file property** [[Command palette|command]].
- Use the **`Cmd/Ctrl+;`** [[Hotkeys|hotkey]].
- Choose **Add file property** from the **More actions** menu (brought up by the three dots icon or by right-clicking the tab).
- Type `---` at the very beginning of a file.

Once you add a property, a row will appear at the top of the file with two inputs: the property _name_ and the property _value_.

For the name, you can choose anything you like. Obsidian provides several default properties: `tags`, `cssclasses`, and `aliases`.

Once you choose the property name, you can give it a value.

### Property types

In addition to a name and value, properties also have a *type*. A property's type describes the kind of values it can store. To change the type of a property, click the property's icon or use the **Edit file property** command.

Obsidian supports the following property types:

- **Text**
- **List**
- **Number**
- **Checkbox**
- **Date**
- **Date & time**

Once a property type is assigned to a property, all properties with that name are assumed to have the same property type.

## Advanced uses

### Links

**Text** and **List** type properties can contain URLs and [[Internal links]] using the `[[Link]]` syntax.

### Search properties

Properties have their own [[Search|search syntax]] that you can use alongside other search terms and operators. [[Search#Search properties|See search syntax for properties]].

['front matter', 'Advanced topics/YAML front matter', 'metadata', 'property']

### Templates

You can add properties to [[Templates]]. When you insert a template into the active note, all the properties from the template will be added to the note. Obsidian will also merge any properties that exist in your note with properties in the template.

### Rename properties

You can rename a property by right-clicking it in the [[Properties view|All properties view]].

### Display modes

You can change how properties are displayed in your note by going to  **Settings → Editor → Properties in document**. The options are:

- **Visible** (default) — displays properties at the top of the note, if there are any.
- **Hidden** — hides properties, can still be displayed in the sidebar via [[Properties view]].
- **Source** — displays properties in plain text YAML format.

### Not supported

A few features are not supported in Obsidian:

- **Nested properties** — to view nested properties we recommend using the Source display.
- **Bulk editing properties** — this can be achieved with community-made tools such as Python scripts.
- **Markdown in properties** — this is an intentional limitation as properties are meant for small, atomic bits of information that are both human and machine readable.

## Hotkeys

### Add a property

| Action | Hotkey |
|---|---|
|Add new property|`Cmd + ;`|

### Navigate between properties

When a property is focused 

|---|---|
|Focus next property|`Down arrow` or `Tab`|
|Focus previous property|`Up arrow` or `Shift+Tab`|
|Jump to editor|`Alt+Down arrow`|

### Select properties

|---|---|
|Extend selection upwards|`Shift+Up arrow`|
|Extend selection downwards|`Shift+Down arrow`|
|Select all|`Cmd+A`|

|---|---|

### Edit properties

|---|---|
|Edit property name|`Left arrow`|
|Edit property value|`Right arrow`|
|Focus property|`Escape`|
|Delete property|`Cmd+Backspace`<br><br>if any properties are selected, it will delete the selection instead.|
|Undo|`Cmd+Z`|
|Redo|`Cmd+Shift+Z`|

### Vim (advanced)

|---|---|
|Move down|`j`|
|Move up|`k`|
|Focus key|`h`|
|Focus value|`l`|
|Focus value (Cursor at end)|`A`|
|Focus value (Cursor at beginning)|`i`|
|Create new property|`o`|

## Property format

Properties are stored in [YAML](https://yaml.org/)  format at the top of the file. YAML is a widely used format that's readable by both humans and machines.

Property names are separated from their values by a colon followed by a space:

```yaml
---
name: value
---
```

While the order of each name-value pair doesn't matter, each name must be unique within a note. For example, you can't have more than one `tags` property.

Values can be text, numbers, true or false, or even collections of values (arrays).

```yaml
---
title: A New Hope
year: 1977
favorite: true
cast:
  - Mark Hamill
  - Harrison Ford
  - Carrie Fisher
---
```

Internal links in **Text** and **List** type properties must be surrounded with quotes. Obsidian will automatically add these if you manually enter internal links into properties, but be careful to add them when using templating plugins.

```yaml
---
link: "[[Link]]" 
linklist: 
  - "[[Link]]" 
  - "[[Link2]]"
---
```

**Date** and **Date & time** type properties are stored in the following format:

```yaml
---
date: 2020-08-21
time: 2020-08-21T10:30:00
---
```

The date picker follows your operating system's default date and time format. You can change it in your system preferences: 

> [!info]- Windows
> **Settings → Time & Language → Language & Region → Regional Format → Change Formats**
> 
> ![[Windows-OS-DateTime.png#interface]]

> [!info]- Mac OS
> **System Preferences → Language and Region → Date format**
> 
> ![[Mac-OS-DateTime.png|450]]

With the [[Daily notes]] plugin enabled, the date property will additionally function as an internal link to the corresponding daily note for that date.

![[Daily notes#^daily-notes-date]]
### JSON Properties

While we recommend using YAML to define properties, you can also define properties using [JSON](https://www.json.org/):

```json
---
{
  "tags": "journal",
  "publish": false
}
---
```

Note that the JSON block will be read, interpreted, and saved as YAML.

## Default properties

Obsidian comes with a set of default properties:

| Property | Description |
|-|-|
| `tags` | See [[Editing and formatting/Tags\|Tags]]. |
| `aliases` | See [[Aliases]]. |
| `cssclasses` | Allows you to style individual notes using [[CSS snippets]]. |

### Properties for Obsidian Publish

The following properties can be used with [[Introduction to Obsidian Publish|Obsidian Publish]]:

|-|-|
| `publish` | See [[Publish and unpublish notes#Automatically select notes to publish\|Automatically select notes to publish]]. |
| `permalink` | See [[Publish and unpublish notes#Permalinks\|Permalinks]]. |
| `description` | See [[Social media link previews#Description\|Description]]. |
| `image` | See [[Social media link previews#Image\|Image]]. |
| `cover` | See [[Social media link previews#Image\|Image]]. |

### Deprecated properties

These properties were deprecated in Obsidian 1.4. Please do not use them anymore:

|-|-|
| `tag` | Deprecated alias for `tags`. |
| `alias` | Deprecated alias for `aliases`. |
| `cssclass` | Deprecated alias for `cssclasses`. |

Obsidian supports HTML to allow you to display your notes the way you want, or even [[Embed web pages|embed web pages]]. Allowing HTML inside your notes comes with risks. To prevent malicious code from doing harm, Obsidian _sanitizes_ any HTML in your notes. 

> [!example] 
> The `<script>` element normally lets you run JavaScript whenever it loads. If Obsidian didn't sanitize HTML, an attacker could convince you to paste a text containing JavaScript that extracts sensitive information from your computer and sends it back to them.

That said, since Markdown syntax does not support all forms of styling, using sanitized HTML can be yet another way of enhancing the quality of your notes. We've included some of the more common usages of HTML. 

> [!info] More details on using `<iframe>` can be found in [[Embed web pages]].

### Comments

[[Basic formatting syntax#Comments|Markdown comments]] are the preferred way of adding hidden comments within your notes. However some methods of converting Markdown notes, such as [Pandoc](https://pandoc.org), have limited support of Markdown comments. In those instances, you can use a `<!-- HTML Comment -->` instead!

### Underline

If you need to quickly underline an item in your notes, you can use `<u>Example</u>` to create <u>your underlined text</u>.

### Span/Div

Span and div tags can be used to apply custom classes from a [[CSS snippets|CSS snippet]], or custom defined styling, onto a selected area of text. For example, using `<span style="font-family: cursive">your text</span>` can allow you to quickly <span style="font-family: cursive">change your font</span>.

## Strikethrough

Need to strike <s>some text</s>? Use `<s>this</s>` to strike it out.

['Advanced topics/HTML sanitization', 'Editing and formatting/Using HTML']

Obsidian lets you edit text in multiple places at the same time using multiple cursors. You can add additional cursors by holding `Alt` (or `Option` on macOS) and selecting another position in the note.

To remove a selection along with all additional cursors, click anywhere in the note without holding a key. You can also remove the selection by pressing `Escape`.

## Rectangular selection

If you want to edit consecutive lines of text—for example, to turn paragraphs into list items—you can hold `Shift+Alt` (or `Shift+Option` on macOS) while dragging. You can also hold the middle mouse button while dragging.

Obsidian strives for maximum capability without breaking any existing formats. As a result, we use a combination of flavors of [[Basic formatting syntax|Markdown]].

Obsidian supports [CommonMark](https://commonmark.org/), [GitHub Flavored Markdown](https://github.github.com/gfm/), and [LaTeX](https://www.latex-project.org/). Obsidian does not support using Markdown formatting or blank lines inside of HTML tags.

### Supported Markdown extensions

Syntax | Description
-|-
`[[Link]]` | [[Internal links]]
`![[Link]]` | [[Embed files]]
`![[Link#^id]]` | [[Internal links#Link to a block in a note\|Block references]]
`^id` | [[Internal links#Link to a block in a note\|Defining a block]]
`%%Text%%` | [[Basic formatting syntax#Comments\|Comments]]
`~~Text~~`| [[Basic formatting syntax#Styling text\|Strikethroughs]]
`==Text==`| [[Basic formatting syntax#Styling text\|Highlights]]
`` ``` ``  | [[Basic formatting syntax#Code blocks\|Code blocks]]
`- [ ]`  | [[Basic formatting syntax#Task lists\|Incomplete task]]
`- [x]`  | [[Basic formatting syntax#Task lists\|Completed task]]
`> [!note]` | [[Callouts]]
| (see link) | [[Advanced formatting syntax#Tables\|Tables]]

docs/obsidian-help/Editing and formatting/Obsidian Flavored Markdown.md

Tags are keywords or topics that help you quickly find the notes you want.

## Add a tag to a note

To create a tag, enter a hash symbol (`#`) in the editor, followed by a keyword. For example, `#meeting`.

You can also add tags using the `tags` [[Properties|property]]. Tags in YAML should always be formatted as a list:

```yaml
---
tags:
  - recipe
  - cooking
---
```

## Find notes using tags

To find notes using the [[Search]] plugin, use the `tag` [[Search#Search operators|search operator]] in your search term, for example `tag:#meeting`.

You can also search for tags by clicking on them in your notes.

To find notes using the [[Tags view|Tags view]] plugin, select **Tags: Show tags** in the [[Command palette]], and then select the tag you want to search for.

## Nested tags

Nested tags define tag hierarchies that make it easier to find and filter related tags.

Create nested tags by using forward slashes (`/`) in the tag name, for example  `#inbox/to-read` and `#inbox/processing`.

Both the [[Search]] and [[Tags view|Tags view]] plugins support nested tags.

## Tag format

You can use any of the following characters in your tags:

- Alphabetical letters
- Numbers
- Underscore (`_`)
- Hyphen (`-`)
- Forward slash (`/`) for [[#Nested tags]]

Tags must contain at least one non-numerical character. For example, #1984 isn't a valid tag, but #y1984 is.

Tags are case-insensitive. For example, #tag and #TAG will be treated as identical.

> [!note] 
> Tags will display with the casing they are first created with in the [[Tags view]]. 
> For example, creating #Tag and then #TAG will display #Tag for both. 

Tags can't contain blank spaces. To separate two or more words, you can instead use the following formats:

- #camelCase
- #PascalCase
- #snake_case
- #kebab-case

Obsidian allows you to easily migrate your notes from Evernote using the [[Importer|Importer plugin]].

## Export your data from Evernote

Obsidian uses Evernote's export format `.enex` files.

You can find Evernote's instructions for exporting your data [on Evenote's website](https://help.evernote.com/hc/en-us/articles/209005557-Export-notes-and-notebooks-as-ENEX-or-HTML). This method allows you to export entire notebooks in the desktop client.

1. Go to the Notebooks screen.
2. Click on **More actions** (`•••` icon) and choose **Export Notebook...**
3. Select **ENEX** as the file format.
3. Choose a location for your exported `.enex` file.

## Import your Evernote data into Obsidian

You will need the official Obsidian [[Importer]] plugin, which you can [install here](obsidian://show-plugin?id=obsidian-importer).

2. Go to **Community Plugins** and [install Importer](obsidian://show-plugin?id=obsidian-importer).
3. Enable the Importer plugin.
4. Open the **Importer** plugin using the command palette or ribbon icon.
5. Under **File format** choose **Evernote (.enex)**.
6. Select the location of your Evernote backup file.
7. Click **Import** and wait until import is complete.
8. You're done!

### Import settings

For more advanced import options from Evernote you can also try [importing via Yarle](https://github.com/akosbalasko/yarle).

If you've been using the Zettelkasten method to name and link your notes, you may need to convert links from `[[UID]]` to `[[UID My note title]]`.

For example, if you have a note with the name `202301011230 My note title` and link to it from another note using only the UID, `[[202301011230]]`. Since Obsidian uses the full name of the note to resolve internal links, links like these will break.

To update all `[[UID]]` links in your vault to use the full name of the note instead, use the [[Format converter]].

2. Under **Core plugins**, enable **Format converter** and close the Settings window.
3. In the ribbon, on the left side of the app window, select **Open format convert** (ones and zeros icon).
4. Enable **Zettelkasten link fixer**.
5. Select **Start conversion**. This will convert all the notes in your entire vault.

> [!tip] Zettelkasten link beautifier
> [[Format converter]] can also beautify your links by removing the UID from the display name. For example, `[[UID]]` converts to `[[UID My note title|My note title]]`.
>
> To beautify your Zettelkasten links, enable **Zettelkasten link beautifier** in the format converter window.

You can also use the [[Unique note creator]] to create Zettelkasten notes in Obsidian.

Obsidian allows you to easily import individual HTML files and entire folders of HTML files using the official [[Importer|Importer plugin]]. This is useful if you want to save whole websites to [[Obsidian Flavored Markdown|Markdown]] format, or if you want to import data from a tool that exports to HTML. 

If you are importing notes from a specific app, you may want to first review the list of apps supported by [[Importer|Importer plugin]] to check if there is a specific converter that will better preserve the data you are migrating.

## Import HTML data into Obsidian

5. Under **File format** choose **HTML (.html).**
6. Select the location of your HTML files or folders.

- **Attachment size limit**: Skip importing attachments larger than the specified size.
- **Minimum image size**: Skip importing images smaller than the specified size in either dimension. Can be used to skip icons and logos.

Obsidian allows you to easily migrate your notes from Roam Research  using the [[Importer|Importer plugin]].

## Export your data from Roam Research

1. In Roam Research, click on **More actions** (`•••` icon) in the upper-right corner, and then select **Export All**.
   
   ![[Roam-exporting.png#interface]]
2. In **Export Format**, select "JSON", and then select **Export All** to download an archive with your notes.

## Import your Roam Research data into Obsidian

5. Under **File format** choose **Roam Research (.json).**
6. Select the location of your `.json` file.
7. Under **Output folder**, choose where your files should import.
8. If you want to also import attachments, toggle **Download all attachments**.
9. Click **Import** and wait until import is complete.
10. You're done!

![[Roam-Importer-importing.png]]

Obsidian allows you to easily migrate your notes from Microsoft OneNote using the [[Importer|Importer plugin]].

## Import your OneNote data into Obsidian

5. Under **File format** choose **Microsoft OneNote**.
6. Click **Sign in** to open your web browser to the Microsoft sign-in page. Enter the credentials for your Microsoft account which contains your OneNote Notebooks. More information about the Microsoft sign-in process is available below.
7. Click **Accept** to grant Obsidian permission to view your OneNote Notebooks.
8. Click **Open Link** to allow your browser to redirect you to the Obsidian app.
9. In the Obsidian app, the Importer dialog will now display that you are signed in and list your OneNote Notebooks and Sections. Check the sections you wish to import.

![[OneNote-Importer-Select-Sections.png]]

10. Click **Import** and wait until import is complete.
11. You're done!

### No sections or notebooks appear

Make sure that the notebooks you're trying to import are synced to OneDrive and visible in OneNote Web. They must be owned by you (shared notebooks written by others are unsupported).

If a specific section is missing, make sure it's not a locked section — those are invisible without removing the lock first.

docs/obsidian-help/Import notes/Import from Microsoft OneNote.md

### Imported notes are empty or missing content

This issue may occur on notebooks that you rarely use. To solve the issue follow these steps:

1. Open [OneNote Web](https://onenote.com/notebooks) in your browser.
2. **Right click** on the Notebooks which are missing content.
3. Select **Export Notebook** from the menu.
4. **Unzip** the file you've just downloaded into a folder.
5. Upload your OneNote notebooks [here](https://www.onenote.com/notebooks/exportimport?toImport=true).
6. Open **Obsidian Importer** and try importing again

If you've followed these tips and your issue remains unresolved, it's possible that there is a temporary problem with Microsoft servers. If that's the case, wait a few minutes and try again. If the problem persists, please open an issue on the [Obsidian Importer GitHub repository](https://github.com/obsidianmd/obsidian-importer/issues).

## Privacy

The Obsidian Importer plugin uses [OAuth](https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow) to authenticate with your Microsoft account and import your OneNote notebooks. This grants a short term access token to your account which is used only from your computer and is never stored. After the import completes you may optionally revoke the token from the [Microsoft apps & services page](https://account.live.com/consent/Manage).

Obsidian allows you to easily migrate your notes from Apple Notes using the [[Importer|Importer plugin]]. Currently, it only supports importing from Apple Notes on your macOS desktop. 

## Import Apple Notes data into Obsidian

5. Under **File format** choose **Apple Notes**.
6. Click **Import**.
7. Click **Open** on the popup that appears titled `Select the "group.com.apple.notes" folder to allow Obsidian to read Apple Notes data`.
8. Wait until import is complete. 
9. You're done!

## Supported content

The Obsidian Importer plugin supports virtually all Apple Notes content types. This includes tables, images, drawings, scans, PDFs, and links introduced in iOS 17.

> [!Warning]
> Password-protected notes are encrypted by Apple, so must be unlocked before importing them. Any locked notes will be skipped.

### Scans

Apple stores scans in a variety of formats depending on how they were created. To preseve the original data, this means they'll be exported differently.

* Scans created or viewed on older versions of macOS or iOS will be exported as a series of uncropped images.
* Scans created or viewed on newer versions of macOS or iOS will usually be exported as cropped images.
* Scans that have been edited using the features introduced in iOS 17 will usually be exported as PDFs.

## Alternate export methods

Apple does not provide a native option to export your notes. However several third-party tools exist such as [Exporter](https://apps.apple.com/us/app/exporter/id1099120373) by Chintan Ghate. Please be aware that most tools are limited in what data they will export from Apple Notes and might not provide the most compatible output data. These tools work best if your Apple Notes are primarily text-only, and have few attachments or special features such as drawings and scans.

Depending on the tool you used, the export may be in Markdown format or HTML format. Follow instructions based on the file format you exported to: 

- [[Import HTML files]]
- [[Import Markdown files]]

Obsidian allows you to easily migrate your notes from Bear using the [[Importer|Importer plugin]].

## Export your data from Bear

Obsidian uses Bear's backup format `.bear2bk` files. You can find Bear's instructions for creating the backup [on Bear's website](https://bear.app/faq/backup-restore/). 

1. Open Bear.
2. Create a backup
	1. On macOS: **File** → **Backup notes**.
	2. On iOS: click the more menu (⋮) at the top of the sidebar and choose **Backup all notes**.
3. Choose a location for your backup file.
4. Click **Export notes**.
5. You should now have one `.bear2bk` file that contains all your notes.

## Import your Bear data into Obsidian

5. Under **File format** choose **Bear (.bear2bk)**.
6. Select the location of your Bear backup file.

Obsidian allows you to easily migrate your notes from Google Keep using the [[Importer|Importer plugin]].

## Export your data from Google Keep

1. Go to [Google Takeout](https://takeout.google.com/settings/takeout) and log into your Google account.
2. Click **Deselect all** in the top right corner.
3. Scroll down and select **Keep** from the list. 
4. Scroll down to the bottom of the page and click **Next step**.
5. On the next screen, click the **Create export** button.
6. Download the `.zip` file once it is available.

## Import your Google Keep data into Obsidian

5. Under **File format** choose **Google Keep (.zip).**
6. Select the location of your `.zip` file.

### Supported features

- All checklists will import as top-level items because Google Keep doesn't export indentation information.
- Reminders and user assignments on notes will not be imported because these features are not supported by Obsidian.
- All other information should import as a combination of content and tags.

Obsidian uses Markdown `.md` files as the primary format for notes. This makes it easy to import Markdown files into Obsidian. Many apps can edit Markdown files or export to this format.

There are several ways to add Markdown files to your Obsidian vault:

1. Drag and drop files or folders into the [[File explorer]] window
2. Use your system file browser (e.g. Windows Explorer or Finder on macOS), and move your files directly into the Obsidian vault folder.

### Converting from other flavors of Markdown

Obsidian uses [[Obsidian Flavored Markdown]]. Some apps use slightly different Markdown syntax. You can use [[Format converter]] to convert your files to Obsidian's Markdown syntax.

Obsidian allows you to easily migrate your notes from Notion using the [[Importer|Importer plugin]].

## Export your data from Notion

Obsidian uses Notion's HTML export format. You can find Notions's instructions on how to export your entire workspace [on Notion's website](https://www.notion.so/help/export-your-content). Note that you must be a workspace admin to see this option.

1. Go to **Settings & members** at the top of your left-hand sidebar.
2. Select **Settings** in the sidebar of that window.
3. Scroll down and select the **Export all workspace content** button.
4. Under **Export format** select **HTML**.
5. Enable **Include subpages**
6. Enable **Create folders for subpages**
7. You will receive a `.zip` file via email or directly in the browser.

![[notion-export.png#interface]]

## Import your Notion data into Obsidian

5. Under **File format** select **Notion (.zip)**
6. Choose the `.zip` file with Notion files you want to import. *It's recommended to import all your Notion at once so internal links can be reconciled correctly.*
7. _Optionally_, select a folder for the import Your Notion pages and databases will be nested inside this folder.
8. Enable **Save parent pages in subfolders** to keep the Notion structure. *Note that in Notion you can write content in Folders, this is not possible in Obsidian and these pages will be added as a subpage under the folder.*
9. Select **Import** and wait until import is complete

If you run into issues while importing from Notion:

- Make sure you use **HTML** as the export format in Notion, **not Markdown**.
- If Obsidian appears to freeze during import, disable community plugins and try again.

Run into something else? Search [the Importer repository](https://github.com/obsidianmd/obsidian-importer/issues) to see if others have experienced it.

Slides lets you create presentations from your notes. To start a presentation:

**File menu:**

- Right-click the tab of a note and click **Start presentation**.

**Command palette:**

1. Press `Ctrl+P` (or `Cmd+P` on macOS) to open the [[Command palette]].
2. Search for the **Start presentation** command.
3. Press `Enter` with the command selected to start a presentation using the active note.

To navigate between slides, click the left and right arrows in the bottom-right corner, or press the left and right arrow keys on your keyboard.

You can also advance to the next slide by pressing Spacebar.

To stop the presentation, press `Escape` or click the cross in the upper-right corner of the presentation.

You can use any valid Markdown file as a presentation. To separate slides, enter `---` at the start of a line surrounded by newlines.

```md
# Presentations using Slides

A demo on how to build presentations using Slides.

---

## Formatting

You can use regular Markdown formatting, like *emphasised* and **bold** text.

---

## Slides

Use `---` to separate slides.
```

The Search plugin helps you find files in your vault.

By default, you can find Search in the left sidebar (magnifying glass icon). You can also open Search by pressing `Ctrl+Shift+F` (or `Cmd+Shift+F` on macOS).

- **Search selected text**: If you select text in the editor and open Search with the keyboard shortcut, Search shows you the search results for the selected text.
- **Search recent search terms**: Open Search with an empty search term to list recent search terms. Click any of them to use the search term again.

## Search terms

A search term is the word or phrase that you enter in the search field. Learning how to write search terms effectively can help you quickly find what you're looking for, even in large vaults. Obsidian only searches the contents of notes and canvases.

> [!tip] Searching paths and filenames
> By default, you can only search the paths and filenames of notes and canvases. To search for a path or filename of any file in the vault, use the `path` or `file` operator.

Each word in the search term is matched independently within each file. To search for an exact phrase, surround it with quotes, for example `"star wars"`. To search for quoted text within an exact phrase, you can _escape_ the quotes by adding a backslash (`\`) in front of the quote, for example `"they said \"hello\" to each other"`.

You can control whether to return files that contain _all_ the words in your search term, or _any_ of the words:

- `meeting work` returns files that contain both `meeting` and `work`.
- `meeting OR work` returns files that contain either `meeting` or `work`.

You can even combine the two in the same search term.

- `meeting work OR meetup personal` returns files for work meetings and personal meetups.

You can use parentheses to control the priority of each expression.

- `meeting (work OR meetup) personal` returns files that contain `meeting`, `personal`, and either `work` or `meetup`.

To exclude, or negate, a word from the search results, add a hyphen (`-`) in front of it:

- `meeting -work` returns files that contain `meeting` but not `work`.

You can exclude multiple expressions:

- `meeting -work -meetup` returns files that contain `meeting` but not `work` or `meetup`.

You can exclude a combination of expressions using parentheses:

- `meeting -(work meetup)` returns files that contain `meeting` but not _both_ `work` and `meetup`.

> [!tip] Explain search term
> If you need to troubleshoot a complex search term, you can click **Explain search term** in Search for an explanation of your search term.

## Search operators

Search operators enable more fine-grained search queries to filter your results even more.

Some operators even allow you to add a nested search term within parentheses, for example: `task:(call OR email)`.

| Search operator | Description                                                                                                                                                                                                          |
|-----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `file:`         | Find text in filename. Matches any file in the vault.<p/>Example: `file:.jpg` or `file:202209`.                                                                                                                                                     |
| `path:`         | Find text in file path. Matches any file in the vault.<p/>Example: `path:"Daily notes/2022-07"`.                                                                                                                                                    |
| `content:`      | Find text in file content.<p/>Example: `content:"happy cat"`.                                                                                                                                                        |
| `match-case:`   | Case-sensitive match.<p/>Example: `match-case:HappyCat`.                                                                                                                                                             |
| `ignore-case:`  | Case-insensitive match.<p/>Example: `ignore-case:ikea`.                                                                                                                                                              |
| `tag:`          | Find tag in file.<p/>Example: `tag:#work`.<p/>**Note**: Since `tag:` ignores matches in code blocks and in non-Markdown content, it's often faster and more accurate than a normal full-text search for `#work`.     |

| `line:`         | Find matches on the same line.<p/>Example: `line:(mix flour)`.                                                                                                                                                       |
| `block:`        | Find matches in the same block.<p/>Example: `block:(dog cat)`.<p/>**Note**: Since `block:` requires Search to parse the Markdown content in every file, it can cause your search term to take longer time to finish. |
| `section:`      | Find matches in the same section (text between two headings).<p/>Example: `section:(dog cat)`.                                                                                                                         |
| `task:`         | Find matches in a [[Basic formatting syntax#Task lists\|task]] on a block-by-block basis.<p/>Example: `task:call`.                                                                                                          |
| `task-todo:`    | Find matches in an *uncompleted* [[Basic formatting syntax#Task lists\|task]] on a block-by-block basis.<p/>Example: `task-todo:call`.                                                                                      |
| `task-done:`    | Find matches in a *completed* [[Basic formatting syntax#Task lists\|task]] on a block-by-block basis.<p/>Example: `task-done:call`.                                                                                         |

## Search properties

You can use data stored in [[Properties]] in your search terms.

Use brackets around a property name `[property]` to return files with that property:

- `[aliases]` returns files that contain the `aliases` property
  
Use brackets and a colon `[property:value]` to return files with that property and value:

- `[aliases:Name]` returns files where the `aliases` property value is `Name`

Both property and value allow sub-queries, such as parentheses for grouping, the `OR` operator, double-quotes for exact matching, and regex.

- Example: `[status:Draft OR Published]` to find returns files where the `status` property value is `Draft` or `Published`

## Change case sensitivity

By default, search terms are not case sensitive. If you want to search for the exact case of your search term, click **Match case** ("Aa" icon) inside the search bar.

This setting can be toggled. If **Match case** icon is highlighted, that means you’re currently doing a case sensitive search.

## Change result sort order

1. Enter a [[#Search terms|search term]].
2. Under the search field, click on the dropdown on the right.
3. Select the sort order you want. Default is "File name (A to Z)".

The following options are available:

- File name (A to Z)
- File name (Z to A)
- Modified time (new to old)
- Modified time (old to new)
- Created time (new to old)
- Created time (old to new)

## Copy search results

2. Under the search field, select the three dots icon next to the number of results.
3. Select **Copy search results**.

## Use regular expressions

A regular expression is a set of characters that describe a text pattern. To use regular expressions in your search term, surround the expression with forward slashes (`/`).

- `/\d{4}-\d{2}-\d{2}/` matches an ISO 8601 date, such as 2022-01-01.

You can even combine regular expressions with search operators:

- `path:/\d{4}-\d{2}-\d{2}/` returns files with a date in the file path.

For more information on how to write regular expressions, refer to [Regular expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions)

> [!note]
> Regular expressions come in different flavors that may look different from each other. Obsidian uses JavaScript-flavored regular expressions.

## Configure search settings

To configure Search, click on **Search settings** (three rows of switches icon) on the right side of the search bar to see the toggles.

| Setting                 | Description                                                                 |
|-------------------------|-----------------------------------------------------------------------------|
| **Explain search term** | Breaks down the search terms and explains it in plain text.                 |
| **Collapse results**    | Toggles whether to show the search context.                                 |
| **Show more context**   | Expands the search result to show more text around the match.               |

## Embed search results in a note

To embed search results in a note, add a `query` code block:

<pre><code>```query
embed OR search
```</code></pre>

For example:

> [!note]
> [[Introduction to Obsidian Publish|Obsidian Publish]] doesn't support embedded search results. To see the example, open Obsidian Help locally inside Obsidian.

```query
```

Slash commands allow you to perform commands from inside the editor by typing a forward slash (`/`) at the beginning of a line or after any blank space.

To run a command using Slash commands:

1. In the editor, type a forward slash (`/`).
2. Enter the name of the command you want to run to search the list of available commands.
3. Navigate to the command using the arrow keys.
4. Press Enter.

To exit the Slash command search without invoking a command, press `Esc` or the `Space` key.

> [!TIP] Fuzzy matching
> Like the [[Command palette]], Slash commands supports fuzzy matching which lets you search commands even if you don't know their exact names. For example, type "scf" to find the **Save current file** command.

Note composer lets you merge two notes or extract part of a note into a new note.

## Merge notes

Merging notes adds a note to another and removes the first one. Note composer updates all links to reference the merged note.

When you select the note to merge into, you can choose between the following methods:

- `Enter`: Adds the source note at the _end_ to the destination note.
- `Shift+Enter`: Adds the source note at the _start_ of the destination note.
- `Ctrl+Enter` (or `Cmd+Enter` on macOS): Creates a new note with the content of the source note.

To merge the active note with another note in your vault:

**File explorer**

1. In the File explorer, right-click the note you want to merge.
2. Click **Merge entire file with...**.
3. Select the note you want to merge into.
4. Click **Merge** to confirm.

**Command palette**

2. Select **Note composer: Merge current file with another file...**.

> [!tip]
> By default, Note composer asks you to confirm when merging notes. If you disable the confirmation, and you merge a note by mistake, you can still recover it with the [[File recovery]] plugin.

## Extract note

When you select the note to extract the selection into, you can choose between the following methods:

- `Enter`: Adds the selected text at the _end_ to the destination note.
- `Shift+Enter`: Adds the selected text at the _start_ of the destination note.
- `Ctrl+Enter` (or `Cmd+Enter` on macOS): Creates a new note with the selected text.

To extract text into a new note:

**Editor**

1. While in the **Editing view**, select the text you want to extract.
2. Right-click the selected text.
3. Click **Extract current selection...**.
4. Select the note you want to extract into.

2. Open the [[Command palette]].
3. Select **Note composer: Extract current selection...**.

> [!tip]
> By default, Note composer replaces the extracted text with a link to the destination note. Under settings, you can also change to instead [[Embed files|embed]] the destination note, or to leave nothing behind.

## Template file

By configuring a template, you can customize the content before you add it to the new note. To use a template, enter a **Template file location** in the plugin settings.

The template can contain the following variables:

| Variable          | Description                                                                                                                                              |
|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|
| `{{content}}`     | The content to merge, or the extracted text selection. If you don't include this variable, Note composer adds the content at the bottom of the template. |
| `{{fromTitle}}`   | Name of the source note.                                                                                                                                 |
| `{{newTitle}}`    | Name of the destination note. For example, to add the file name as a heading at the top of the file.                                                     |
| `{{date:FORMAT}}` | Creation date of the new note. For example, `{{date:YYYY-MM-DD}}`.                                                                                       |

The File explorer lets you manage files and folders inside your vault. You can browse notes and other [[Accepted file formats]] in your vault and perform many common file operations:

- Create, delete, and rename files and folders.
- Move files and folders with drag and drop.
- Use the context menu to access all available operations.

> [!tip]
> You can drag a file from the File explorer into your note to create a link to it, or drag a file into a folder in the File explorer to copy it.

To create a new note in the default location for new notes:

1. Click **New note** (document icon) at the top of the File explorer.
2. Type the name of the note, and then press Enter.

> [!tip]
> You can change the default location for new notes under **Settings → Files and links → Default location for new notes**.

To create a new note in a specific folder:

1. Right-click the folder and then click **New note**.

## Create a new folder

To create a new folder the root of your vault:

1. Click **New folder** (folder icon) at the top of the File explorer.
2. Type the name of the folder, and then press Enter.

To create a subfolder:

1. Right-click the folder you want to create the subfolder in, and then click **New folder**.

## Delete a file or folder

1. Right-click the file you want to delete, and then click **Delete**.
2. If prompted to confirm that you want to delete the file, click **Delete**.

For more information, refer to [[Manage notes#Delete a file]].

## Rename a file or folder

1. Right-click the file you want to rename, and then click **Rename**.
2. Type the new name, and the press Enter.

For more information, refer to [[Manage notes#Rename a note]].

## Move a file or folder

To move a file or folder, you can use drag-and-drop or the context menu.

**Drag and drop:**

- Drag a file or folder to the folder you want to move it to.
- With `Alt-Click` (Windows/Linux) or `Opt-Click` (macOS) you can select multiple individual files and drag them to another folder. If they're all in a row, you can use `Shift-Click` for it.

**Context menu:**

1. Right-click a file, and then select **Move file to...**.
2. Search for the name of the folder you want to move the file to, and then select it from the list.

With the Backlinks plugin, you can see all the _backlinks_ for the active note.

A backlink for a note is a link from another note to that note. In the following example, the "Three laws of motion" note contains a link to the "Isaac Newton" note. The corresponding backlink would link from "Isaac Newton" back to "Three laws of motion".

flowchart LR
  laws((Three laws of motion))
  newton((Isaac Newton))

  laws --link--> newton
  newton --backlink--> laws
```

Backlinks can be useful to find notes that reference the note you're writing. Just imagine if you could list the backlinks for any website on the internet.

## Show backlinks

The Backlinks plugin displays the backlinks for the active tabs. There are two collapsible sections: **Linked mentions** and **Unlinked mentions**.

- **Linked mentions** are backlinks to the notes that contain an internal link to the active note.
- **Unlinked mentions** are backlinks to any unlinked occurrence of the name of the active note.

It provides the following options:

- **Collapse results** toggles whether to expand each note to display the mentions in it.
- **Show more context** toggles whether to truncate or display the full paragraph that contains the mention.
- **Change sort order** determines how to sort the mentions.
- **Show search filter** toggles a text field that lets you filter the mentions. For more information on how to build a search query, refer to [[Search]].

## View backlinks for a note

To view the backlinks for the active note, click the **Backlinks** (link and arrow icon) tab in the right sidebar.

> [!note]
> If you can't see the Backlinks tab, you can make it visible by opening the [[Command palette]] and running the **Backlinks: Show backlinks** command.

## See backlinks of a specific note

The backlinks tab lists backlinks for the active note and updates when you switch to a different note. If you want to see the backlinks for a specific note, regardless of whether it's active or note, you can open a _linked_ backlinks tab.

To open a linked backlinks tab:

2. Select **Backlinks: Open backlinks for the current note**.

A separate tab opens next to your active note. The tab shows a link icon to let you know it's linked to a note.

## Show backlinks in a note

Instead of showing the backlinks in a separate tab, you can show the backlinks at the bottom of your note.

To show backlinks in a note:

2. Select **Backlinks: Toggle backlinks in document**.

Or, enable **Backlink in document** under the Backlinks plugin options to automatically toggle backlinks when you open a new note.

You can use Templates to insert pre-defined snippets of text into your active note.

## Set your template folder

1. In the bottom-left corner, click **Settings** (cog icon).
2. Under **Core plugins → Templates → Template folder location**, enter the folder containing your templates.

## Insert a template into the active note

**Important:**  To insert a template, you need to first [[#Set your template folder]].

1. In the ribbon, click **Insert template**.
2. Select the template to insert at the cursor position in the active note.

If your template folder contains only one note, Templates inserts it directly into the active note.

## Template variables

You can add dynamic information to your templates, using _template variables_. When you insert a template containing a template variable, Templates replaces it with its corresponding value.

| Variable    | Description                                     |
|-------------|-------------------------------------------------|
| `{{title}}` | Title of the active note.                       |
| `{{date}}`  | Today's date. **Default format:** `YYYY-MM-DD`. |
| `{{time}}`  | Current time. **Default format:** `HH:mm`.      |

Both `{{date}}` and `{{time}}` allow you to change the default format using a _format string_.

To set a format string, add a colon (`:`) followed by a string of [Moment.js format tokens](https://momentjs.com/docs/#/displaying/format/), for example `{{date:YYYY-MM-DD}}`.

You can use `{{date}}` and `{{time}}` interchangeably with format strings, for example `{{time:YYYY-MM-DD}}`.

You can change the default date and time formats under **Settings → Templates → Date format** and **Settings → Templates → Time format**.

> [!tip]
> You can also use the `{{date}}` and `{{time}}` template variables in the [[Daily notes]] and [[Unique note creator]] plugins.

The Graph view lets you visualize the relationships between the notes in your vault.

To open the Graph view, click **Open graph view** in the [[Ribbon]].

- Circles represent notes, or _nodes_.
- Lines represents [[Internal links]] between two nodes.

The more nodes that reference a given node, the bigger it gets.

To interact with notes in the graph:

- Hover over each circle to highlight that note's connections.
- Click a note in the graph to open that note.
- Right-click a note to open a context menu with the actions available for that note.

To navigate around the graph:

- Zoom in and out using the scroll wheel on your mouse, or using the `+` and `-` keys.
- Move the graph around by dragging it with your mouse cursor, or using the arrow keys.

You can hold Shift while using the keyboard to speed up the movements.

## Settings

To open the graph settings, click the cog icon in the upper-left corner of the graph view.

Click **Restore default settings** in the upper-right corner of the settings box to reset any changes you make.

### Filters

This section controls what nodes to show in the graph.

- **Search files** lets you filter notes based on a search query. To learn about how you can write more advanced search queries, refer to [[Search]].
- **Tags** toggles whether to show tags in the graph.
- **Attachments** toggles whether to show attachments in the graph.
- **Existing files only** toggles whether to show notes that exists in your vault. Since a note doesn't need to exist to link to it, this can help reduce limit your graph to notes that you actually have in your vault.
- **Orphans** toggles whether to show notes without any links.

### Groups

Create groups of notes to distinguish them from each other using color.

To create a new group:

1. Click **New group**.
2. In the search box, type a search query for the notes you want to add to the group.
3. Click the colored circle to give the group a color.

To learn about how you can write more advanced search queries, refer to [[Search]].

### Display

This section controls how to visualize nodes and links in the graph.

- **Arrows** toggles whether to show the direction of each link.
- **Text fade threshold** controls the text transparency for the name of each note.
- **Node size** controls the size of the circle representing each note.
- **Link thickness** controls the line width for each link.
- **Animate** starts a [[#Start a time-lapse animation|time-lapse animation]].

### Forces

This section controls the forces that act on each node in the graph.

- **Center force** controls how compact the graph is. A higher value creates a more circular graph.
- **Repel force** controls how much a node pushes other nodes away from it.
- **Link force** controls the pull on each link. If the link was a rubber band, the link force controls how tight or loose the band is.
- **Link distance** controls the length of the lines between each note.

## Start a time-lapse animation

Notes and attachments appear in chronological order based on their creation time.

![[obsidian-graph-view.png#interface]]

## Local Graph

To open a local Graph view, use the **Open local graph** command. While the Graph view shows all notes in your vault, a local Graph view shows you notes connected to the active note.

The local Graph view can use all of the [[#Settings]] available to the global Graph view. Additionally, you can change the depth of the local graph. Each level of depth will show notes connected to the notes revealed at the previous depth. To control local Graph depth, use the slider at the top of the local graph Settings panel.

Format converter lets you convert Markdown from other applications to Obsidian format.

> Format converter converts your entire vault based on your settings. Back up your notes before you perform the conversion.

To convert all notes in your vault:

1. In the ribbon, click **Open format converter** (ones and zeros icon).
2. Enable the formats you want to convert.
3. Click **Start conversion**.

For more information, refer to [[Basic formatting syntax]].

## Supported formats

| Application   | From                  | To                                                              |
|---------------|-----------------------|-----------------------------------------------------------------|
| Roam Research | `#tag` and `#[[tag]]` | `[[tag]]`                                                       |
| Roam Research | `^^highlight^^`       | `==highlight==`                                                 |
| Roam Research | `{{[[TODO]]}}`        | `[ ]`                                                           |
| Bear          | `::highlight::`       | `==highlight==`                                                 |
| Zettelkasten  | `[[UID]]`             | `[[UID File Name]]` (full link)                                 |
| Zettelkasten  | `[[UID]]`             | <code>\[\[UID File Name&#124;File Name\]\]</code> (pretty link) |

Word count displays the number of words and characters of the active note. You can find the word count in the bottom right status bar.

Word count even supports CJK languages (Chinese, Japanese, and Korean), which don't use spaces to separate words.

The Outline plugin lists the headings in the active note.

To navigate to that section in the note, click on the heading in the outline.

To rearrange sections in the note, click and drag the heading within the outline.

The Properties view plugin adds two sidebar views that you can use to manage [[Properties]]:

- **File properties** shows a view of the properties for the active note.
- **All properties** shows a list of all the properties in your vault and they type.

## All properties view

With the "All properties" view you can:

- Sort properties by name or by frequency (total number of uses in your vault).
- Click a property to open [[Search]] view with the [[Search#Search properties|property search]] syntax pre-filled.
- Right-click a property to rename it globally.

The Workspaces plugin lets you manage and switch between different application layouts depending on your task, for example journaling, reading, or writing.

A workspace contains information about open files and tabs, and the width and visibility of each sidebar.

## Save a workspace

**Ribbon:**

1. In the ribbon, click **Manage workspace layouts** (layout icon).
2. Enter a name for the workspace.
3. Select **Save**.

2. Search for the **Manage workspace layouts** command.
3. Press `Enter` with the command selected.
4. Enter a name for the workspace.
5. Select **Save**.

To update an existing workspace, save the workspace with the same name as the workspace you want to update.

## Load a workspace

2. Next to the workspace you want to load, select **Load**.

4. Select the workspace to load.

## Delete a workspace

2. Next to the workspace you want to delete, select **Delete layout** (cross icon).

4. Next to the workspace you want to delete, select **Delete layout** (cross icon).

Canvas is a tool for visual note-taking. Lay out notes and other resources on an infinite canvas and connect them with lines.

Visual note-taking allows you to use visual aspects, such as size and position, to make sense of your notes. Connect notes with lines and group related notes together to better understand the relationship between them.

## Create a new canvas

To start using Canvas, you first need to create a file to hold your canvas. You can create a new canvas using the following methods.

- In the ribbon on the left, select **Create new canvas** ( ![[lucide-layout-dashboard.svg#icon]] ) to create a canvas in the same folder as the active file.

2. Select **Canvas: Create new canvas** to create a canvas in the same folder as the active file.

**File explorer:**

- In the [[File explorer]], right-click the folder you want to create the canvas in.
- Select **New canvas**.

> [!note]  The .canvas file extension
> Obsidian stores the configuration for each canvas in a custom JSON format in a file with the `.canvas` extension.

## Adding cards

You can drag files into your canvas from Obsidian or from other applications. For example, Markdown files, images, audio, PDFs, or even unrecognized file types.

### Add text cards

You can add text-only cards that don't reference a file. You can use Markdown, links, and code blocks just like in a note.

To add a new text card to your canvas:

- Select or drag the blank file icon at the bottom of the canvas.

You can also add text cards by double-clicking on the canvas.

To convert a text card to a file:

1. Right-click the text card and then select **Convert to file...**.
2. Enter the note name and then select **Save**.

> [!note]
> Text-only cards don't appear in [[Backlinks]]. To make them appear, you need to convert them to a file.

### Add cards from notes

To add a note from your vault to your canvas:

1. Select or drag the document icon at the bottom of the canvas.
2. Select the note you want to add.

You can also add notes from the canvas context menu:

1. Right-click the canvas and then select **Add note from vault**.

Or, you can add them to the canvas by dragging the file from the [[File explorer]].

### Add cards from media

To add media from your vault to your canvas:

1. Select or drag the image file icon at the bottom of the canvas.
2. Select the media file you want to add.

You can also add media from the canvas context menu:

1. Right-click the canvas and then select **Add media from vault**.

### Add cards from web pages

To embed a web page in your canvas:

1. Right-click the canvas and then select **Add web page**.
2. Enter the URL to the web page and then select **Save**.

You can also select a URL in your browser and then drag it into the canvas to embed it in a card.

To open the web page in your browser, press `Ctrl` (or `Cmd` on macOS) and select the card label. Or, right-click the card and select **Open in browser**.

### Add cards from folders

Drag a folder from the file explorer to add all files in that folder to the canvas.

### Edit a card

Double-click on a text or note card to start editing it. Click outside the card to stop editing it. You can also press `Escape` to stop editing a card.

You can also edit a card by right-clicking it and selecting **Edit**.

### Delete a card

Remove selected cards by right-clicking any of them, and then selecting **Delete**. Or, press `Backspace` (or `Delete` or macOS).

You can also select **Remove** (trash icon) in the selection controls above your selection.

### Swap cards

You can swap a note or media card for another card of the same type.

To swap a note card:

1. Right-click the card you want to replace.
2. Select **Swap file**.
3. Select the note you want to replace with.

## Selecting cards

Select cards in the canvas by clicking on them. You can select multiple cards by dragging a selection around them.

You can also add and remove cards from an existing selection by pressing `Shift` and selecting them.

Press `Ctrl+a` (or `Cmd+a` on macOS) to select all cards in the canvas.

To scroll the content of a card, you first need to select it.

### Arrange cards

Drag a selected card to move it.

Press `Alt` (or `Option` on macOS) and drag to duplicate the selection.

You can press `Shift` while dragging to only move in one direction.

Press `Space` while moving a selection to disable snapping.

Selecting a card moves it to the front.

### Resize a card

Drag any of a card's edges to resize it.

You can press `Space` while resizing to disable snapping.

To maintain the aspect ratio while resizing, press `Shift` while resizing.

## Connecting cards

Draw lines between cards to create relationships between them. Use colors and labels to describe how they relate to each other.

### Connect two cards

To connect two cards with a directed line:

1. Hover the cursor over one of the edges of a card until you see a filled circle.
2. Drag the circle to the edge of a different card to connect them.

> [!tip]
> If you drag the line without connecting it to another card, you can then add the card you want to connect it to.

### Disconnect two cards

To remove the connection between two cards:

1. Hover the cursor over a connection line until two small circles appear on the line.
2. Drag one of the circles from the card without connecting it to another.

You can also disconnect two cards by right-clicking the line between them, and then selecting **Remove**. Or, by selecting the line and then pressing `Backspace` (or `Delete` on macOS).

### Connect a card to a different card

To move one of the ends of a connection line:

2. Drag the circle over the end you want to reconnect, to another card.

### Navigate a connection

If two connected cards are far apart, you can navigate to the source or the target of the connection by right-clicking the line and then select **Go to target** or **Go to source**.

### Add a label to a connection

You can add a label to a line to describe the relationship between two cards.

To label a connection:

1. Double-click the line.
2. Enter the label and then press `Escape` or click anywhere on the canvas.

You can also label a connection by selecting it and then selecting **Edit label** from the selection controls.

To edit a connection label, double-click on the line, or right-click the line and then select **Edit label**.

### Change the color of a card or connection

1. Select the cards or connections you want to color.
2. In the selection controls, select **Set color** (palette icon).
3. Select a color.

## Grouping cards

### Group selected cards

To create an empty group:

- Right-click the canvas and then select **Create group**.

To group related cards:

1. Select the cards.
2. Right-click any of the selected cards and then select **Create group**.

**Rename group:** Double-click the name of the group to edit it, and then press `Enter` to save.

## Navigating the canvas

As you start adding more cards to your canvas, you want to understand how you can navigate the canvas to look at a part of it. Learn how to pan and zoom to move across the canvas with ease.

### Pan the canvas

To move the canvas vertically and horizontally, also known as _panning_, you can use any of the following approaches:

- Press `Space` and drag the canvas.
- Drag the canvas using the middle-mouse button.
- Scroll the mouse to pan vertically, and press `Shift` while scrolling to pan horizontally.

### Zoom the canvas

To zoom the canvas, press `Space`  or `Ctrl` (or `Cmd` on macOS) and scroll using the mouse wheel. Or, select **Zoom in** (plus sign) and **Zoom out** (minus sign) from the zoom controls in the upper-right corner.

#### Zoom to fit

To zoom the canvas so that every item is visible, select **Zoom to fit** (dashed square icon). Or, use the keyboard shortcut, `Shift+1`.

#### Zoom to selection

To zoom the canvas so that all selected items are visible, right-click a selected card and then select **Zoom to selection**. Or, use a keyboard shortcut by pressing `Shift+2`.

#### Reset zoom

To change the zoom level back to the default, select **Reset zoom** in the zoom controls in the upper-right corner.

## Advanced tips

We have made some quick videos to demonstrate some advanced use cases of Canvas.

You can [check out all 72 tips here](https://obsidian.md/canvas#protips). Please note that the tip videos are only visible on desktop.

Bookmarks let you quickly access items that you use often. A bookmark is a "shortcut" that immediately takes you the bookmarked item.

You can add bookmarks to the following:

- Files
- Folders
- Graphs
- Searches
- Headings
- Blocks

Open a bookmark by selecting it in the Bookmarks tab.

You can reorder bookmarks by selecting and dragging them.

You can bookmark items and organize them into _bookmark groups_ to find them easier. You can expand and collapse bookmark groups to show or hide the bookmarks in them.

> [!todo]- Show bookmarks
> You can find your bookmarked items by clicking **Bookmarks** (bookmark icon) in the left sidebar.
>
> Or, open the Bookmarks tab by running **Bookmarks: Show bookmarks** from the [[Command palette]].

## Add a bookmark

Adding a bookmark opens the **Add bookmark** dialog where you can set an optional title and assign it to a bookmark group.

When you bookmark an item, **Add bookmark** becomes **Edit bookmark** and instead lets you edit the bookmark.

> [!todo]- Bookmark a file
>
> **Bookmarks**:
>
> - Select **Bookmark the active tab** (bookmark with plus icon) at the top of the Bookmarks tab.
>
> **File explorer**:
>
> - Right-click a file in [[File explorer]] and click **Bookmark**.
>
> **Command palette**:
>
> 1. Press `Ctrl+P` (or `Cmd+P` on macOS) to open the [[Command palette]].
> 2. Search for the **Bookmark** command.
> 3. Press `Enter` with the command selected to add a bookmark.

> [!todo]- Bookmark a folder
>
>
> - Right-click a folder in [[File explorer]] and click **Bookmark**.

> [!todo]- Bookmark a search term
>
> **Search**:
>
> 1. Enter a [[Search#Search terms|search term]].
> 2. Under the search field, select the three dots icon next to the number of results.
> 3. Select **Bookmark**.

> [!todo]- Bookmark a graph
> To bookmark a graph, right-click the tab with the graph view and select **Bookmark**.
>
> You can't bookmark local graphs.

> [!todo]- Bookmark a heading
> To bookmark a heading, right-click the heading and select **Bookmark this heading**.
>
>
> 2. Select the **Bookmark heading under cursor** command.

> [!todo]- Bookmark a block
>
>
> 2. Select the **Bookmark block under cursor** command.

## Remove a bookmark

In the Bookmarks tab, right-click the bookmark and select **Remove**.

You can also remove a bookmark from the **Edit bookmark** dialog.

## Add a bookmark group

**Bookmarks**:

- Select **New bookmark group** (folder with plus icon) at the top of the Bookmarks tab.

To move a bookmark to another group, select and drag it to the group you want to move it to.

## Remove a bookmark group

To remove a bookmark group and all bookmarks in it, right-click the bookmark group and select **Remove**.

## Bookmark multiple files

You can add multiple bookmarks at the same time.

**File explorer**:

1. Select multiple files by pressing `Alt` and selecting each file, or press `Shift` to select a range of files.
2. Right-click one of the selected files and then select **Bookmark**.

**Tab group options**:

1. In the upper-right corner of a tab group, select the down arrow.
2. Select **Bookmark 3 tabs**, where 3 is the number of tabs in the tab group.

Unique note creator lets you create notes with time-based names, also known as Zettelkasten notes.

For example, if you create a new note at 09:45 on Jan 1st, 2024, Unique note creator creates a note with `202401010945` as its name. If a note with the same name exists, the new note uses the next available timestamp.

## Create a unique note

- In the ribbon, click **Create new unique note** (overlapping sheets icon).

2. Search for the **Create new unique note** command.

## Create unique notes from a template

By default, new unique notes are empty. To use another file as a template:

- Open **Settings**.
- In the sidebar, click **Core plugins → Unique note creator**.
- In **Template file location**, enter the file you want to use as template.

For more information about how to write templates, refer to [[Templates]].

Importer helps you migrate to Obsidian from various apps and formats. See the [[Import notes]] guide for detail.

Importer is an official plugin made by the Obsidian team, with community contributions to [our open source code](https://github.com/obsidianmd/obsidian-importer). You can contribute by adding additional import formats. [See contribution guide.](https://github.com/obsidianmd/obsidian-importer/blob/master/CONTRIBUTING.md)

## Install Importer

1. Follow instructions in [[Community plugins#Install a community plugin]]
2. Download and enable [Importer](obsidian://show-plugin?id=obsidian-importer) from the list

The Quick switcher lets you search and open notes using only your keyboard.

## Open Quick switcher

There are several ways to open Quick Switcher, when it’s enabled:
- Press `Ctrl+O` (or `Cmd+O` on macOS) to open the Quick switcher;
- In the ribbon, click **Open Quick switcher** (magnifying glass on document icon);
- On mobile, when you’re not editing a note, tap the plus icon at bottom center of the app.

## Open a note with Quick switcher

1. [[#Open Quick switcher]].
2. Type to search for a note by name or alias.
3. Navigate to the note using the arrow keys.
4. Press `Enter` to open the selected note.

If the text doesn't match any notes, you can press `Enter` to create a note with that name. Even if the text matches one or more similar notes, you can still create a note with the exact name by pressing `Shift+Enter`.

You can open the selected note in a new tab by pressing `Ctrl+Enter` (or `Cmd+Enter` on macOS).

> [!tip] Toggle between two notes
> If the search term is empty, the Quick switcher shows the most recent notes. Toggle between two notes by opening the Quick switcher, pressing the `Down` arrow, and then pressing `Enter`.

File recovery helps you recover your work in the case of unintentional data loss, by regularly saving snapshots of your notes.

To avoid taking up too much space, Obsidian keeps snapshots for a certain number of days before deleting them.

> [!note] 
> By default, snapshots are saved a minimum of 5 minutes from each other, and kept for 7 days. You can configure both intervals under **Settings → File recovery**.

Snapshots are kept in the [[How Obsidian stores data#System directory|system directory]], outside of the vault, to account for vault-related data loss. This means that snapshots are stored with the absolute path to the note. If you've moved your vault recently, you may need to move it back to the location where it was when the snapshot was taken.

## Recover a snapshot

2. In the sidebar, click **File recovery** under **Plugin options**.
3. Next to **Snapshots**, click **View**.
4. In the upper-**left** text box, start typing the name of the file you want to recover, and you'll see a suggestion list. 
5. Select the file, press Enter, and you'll see a list of snapshots available.
6. Select the snapshot you want to recover.
7. Click **Copy to clipboard** to copy the snapshot.
8. Paste the snapshot in the original note, or in a new note if you want to compare them.

## Clear snapshot history

**Caution:** Clearing the snapshot history irreversibly deletes all snapshots in your vault.

3. Next to **Clear history**, click **Clear**.
4. Confirm that you want to delete all snapshots, by clicking **Clear**.

The Outgoing links plugin shows the links from the active note at a glance, as well as potential links to be made. It's similar to the [[Backlinks]] plugin, which instead shows you _incoming_ links to the active note.

The Outgoing links tab (link with right arrow icon) is available in the right sidebar and contains the following sections:

- **Links** lists all links in the active note. Click a link to open the linked note.
- **Unlinked mentions** lists any text in the active note that matches the name or [[Aliases|alias]] of another note in your vault. Unlinked mentions helps you discover links you aren't aware of yet.

To create a link from an unlinked mention, click the button with the note's name.

> [!tip]
> Unlinked mentions can refer to different notes with the same name. To show the full path of the note, hover over the button with the note's name.

> [!note] Code blocks
> While you can create a link from an unlinked mention inside a code block, due to the nature of code blocks, links don't show up under the Links section.

The Random note plugin opens a random note within your vault. Rediscover notes to add new insights, or link to recently added notes.

To open a random note, click **Open random note** (die icon) in the [[Ribbon]].

This page lists the core plugins that comes installed with Obsidian. Core plugins are officially built and supported by the Obsidian team. 

Some core plugins are disabled by default. You can enable them under **Settings → Core plugins**.

> [!tip] Community plugins
> If you can't find the plugin you're looking here, check out some of the [[Community plugins|plugins built by the community]]. You can also [Build a plugin](https://docs.obsidian.md/Plugins/Getting+started/Build+a+plugin) yourself.

### All core plugins

- [[Audio recorder]]
	- Record and save audio recordings directly in a note.
- [[Backlinks]]
	- See all the links and unlinked mentions of a note.
- [[Bookmarks]]
	- Save links to notes, headings, searches, and more.
- [[Command palette]]
	- Quickly access commands from your keyboard.
- [[Daily notes]]
	- Create and open notes based on the current date.
- [[File explorer]]
	- Browse files and folders inside your vault.
- [[File recovery]]
	-  Recover your work from regular snapshots.
- [[Format converter]]
	- Convert Markdown from other apps to Obsidian format.
- [[Graph view]]
	- Visualize relationships between notes in your vault.
- [[Importer]]
	- Convert files from various apps and formats to Obsidian.
- [[Note composer]]
	- Merge two notes or split one into two.
- [[Outgoing links]]
	- Show all links for the active note.
- [[Outline]]
	- Show the table of contents for the active note.
- [[Page preview]]
	- Preview the contents of a note by hovering over links.
- [[Properties view]]
	- List all the properties in your vault, and see properties for the active note.
- [[Introduction to Obsidian Publish|Publish]]
	- Host your notes as a website, wiki or documentation.
- [[Quick switcher]]
	- Search, create and open notes from your keyboard.
- [[Random note]]
	- Opens a random note in your vault.
- [[Search]]
	- Find files in your vault.
- [[Slash commands]]
	- Perform commands inside the editor using the `/` key.
- [[Slides]]
	- Create a presentation from your notes.
- [[Introduction to Obsidian Sync|Sync]]
	- Sync your notes across devices.
- [[Tags view|Tags view]]
	- List all the tags in your vault.
- [[Templates]]
	- Insert pre-defined content into your notes.
- [[Unique note creator]]
	- Create a unique note using a time-coded title.
- [[Word count]]
	- Display the number of words and characters.
- [[Workspaces]]
	- Save layouts and switch between them.

Page preview lets you preview a page when you hover the cursor over an internal link, without needing to navigate to that page.

In addition to editor, you can preview notes in several other parts of Obsidian, such as [[File explorer]], [[Search]], and [[Backlinks]].

To preview a page while in Editing view, press `Ctrl` (or `Cmd` on macOS) while hovering the cursor over the link.

> [!tip]
> In the plugin settings, you can configure Page preview to only open the preview automatically, or only when you press `Ctrl` (or `Cmd` on macOS).

Daily notes opens a note based on today's date, or creates it if it doesn't exist. Use daily notes to create journals, to-do lists, or daily logs for things you discovered during the day.

To open today's daily note, either:

- Click **Open today's daily note** (calendar with checkmark icon) in the [[Ribbon|ribbon]].
- Run **Open today's daily note** from the [[Command palette]].
- [[Hotkeys#Setting hotkeys|Use a hotkey]] for the **Open today's daily note** command.

By default, Obsidian creates a new empty note named after today's date in the YYYY-MM-DD format.

> [!tip] If you prefer to have your daily notes in a separate folder, you can set the <u>New file location</u> under plugin options to change where Obsidian creates new daily notes.

> [!example]- Automatic subfolders
> You can automatically organize your daily notes into folders using the **Date format** feature.
> 
> For instance, if you set the date format as `YYYY/MMMM/YYYY-MMM-DD`, your notes will be created as `2023/January/2023-Jan-01`. 
> 
> You can explore more formatting options on the [momentJS](https://momentjs.com/docs/#/displaying/format/) documentation site.

## Create a daily note from template

If your daily notes have the same structure, you can use a [[Templates|template]] to add pre-defined content to your daily notes when you create them.

1. Create a new note named "Daily template" with the following text (or whatever makes sense to you!):

   ```md
   # {{date:YYYY-MM-DD}}

   ## Tasks

   - [ ]
   ```

2. Open **Settings**.
3. In the sidebar, click **Daily notes** under **Plugin options**.
4. In the text box next to **Template file location**, select the "Daily template" note.

Obsidian uses the template the next time you create a new daily note.

## Daily notes and properties

When the Daily notes plugin is activated and a date property is present within any note, Obsidian will automatically attempt to generate a link to the daily note for that specific day. For instance, if a note titled `example.md` includes a date property like `2023-01-01`, this date will transform into a clickable link in the [[Edit and preview Markdown#Live Preview|live preview]] section.

![[daily-notes-and-date-properties.png#interface|300]]
^daily-notes-date

Obsidian gives you access to many of the commands in Obsidian directly from your keyboard. The Command palette lets you run any command from the same interactive window. You can also explore the all available commands and their respective keyboard shortcuts.

To run a command from the Command palette:

1. Press `Ctrl+P` (or `Cmd+P` on macOS) to open the Command palette.
2. Type the name of the command you want to run.
4. Press `Enter`.

> [!tip]
> The Command palette supports _fuzzy matching_, which lets you search commands even if you don't know their exact names. For example, type "scf" to find the "**S**ave **c**urrent **f**ile" command.

## Pinned commands

You can pin frequently used commands at the top of the Command palette to quickly access them without having to type their name.

> [!tip]
> If you want to quickly run frequently used commands, you can also [[Hotkeys#Setting hotkeys|set hotkeys]] for them.

### Pin a command

2. In the sidebar, click **Command palette** under **Plugin options**.
3. Next to **New pinned command**, click **Select a command**.
4. Select the command you want to pin from the list.
5. Press `Enter`.

### Unpin a command

3. Under **Pinned commands**, click the cross icon next to the command you want to unpin.

Record and save audio recordings directly into an Obsidian note. With the Audio recorder plugin, you can record details from a lecture, meeting, or other important situations where you can't type fast enough.

> [!note]
> Before you get started, make sure that your computer has a microphone configured and ready to use.

## Record audio in a note

1. Create a new note or open an existing note.
2. In the ribbon, click **Start/stop recording** (microphone icon) to start recording. The recording starts as soon as the icon changes color.
3. Click the icon again to stop the recording and add it to your note.

Obsidian saves the recorded audio file to your vault and [[Embed files|embeds]] it at the end of the active note.

> [!note]
> Audio recordings remain in your vault even after you remove them from your note. If you want to remove the recording from your computer, you can use the [[File explorer]] to delete the file.

Tags view lists all tags within your vault along with how many notes that contain them.

Click a tag to search for it using [[Search]].

To toggle a tag in the search query, click the tag while pressing `Ctrl` (or `Cmd` on macOS).

The plugin provides the following options:

- **Change sort order** determines whether to sort the tags by **Tag name** or **Frequency**.
- **Show nested tags** toggles whether to display nested tags as a tree or as a flat list.
- **Expand all** and **Collapse all** expands and collapses the nested tags hierarchy.

You can choose to expand or collapse each nested level separately by clicking the arrow next to it.

This page explains how to manage your published notes.

## Publish notes

1. In ribbon, to the left of the application window, click **Publish changes** (paper plane icon).
2. In the **Publish changes** dialog, click **NEW** to see all the notes you haven't published yet.
3. Select the notes you want to publish.
4. Click **Publish**.

## Unpublish notes

Notes remain in your local vault even after you unpublish them.

2. In the **Publish changes** dialog, click **UNCHANGED** to see all your published notes.
3. Select the notes you want to unpublish.

## Update a published note

2. In the **Publish changes** dialog, click **CHANGED** to see all the notes that have been changed since the last time they were published.
3. Select the notes you want to update.

## Publish linked notes

Publishing notes that have links to other notes results in broken links unless you publish the linked notes as well. Obsidian Publish can help you by selecting notes that are linked from the notes that are already selected.

To select all linked notes, click **Add linked** in the **Publish changes** dialog.

Review the updated selection to make sure it doesn't include any notes that you're not ready to publish yet.

## Automatically select notes to publish

To automatically select a note to be published, set `publish: true` in the [[Properties]] for the note.

## Ignore notes

To ignore a note in Obsidian Publish, set `publish: false` in the [[Properties]] for the note.

The note no longer shows up in the list of notes to publish.

docs/obsidian-help/Obsidian Publish/Publish and unpublish notes.md

## Permalinks

You can rename the URL to your notes, using _permalinks_.

For example, you can turn this:

```
https://publish.obsidian.md/username/Company/About+us
```

Into this:

```
https://publish.obsidian.md/username/about
```

To create a permalink for a note, add the `permalink` property to your [[Properties]].

```yaml
---
permalink: about
---
```

If someone visits a note using the original URL, they'll be automatically redirected to the permalink.

You can choose the notes you want to publish to [[Introduction to Obsidian Publish|Obsidian Publish]]. The rest of your notes stay safe in your vault.

Only the notes you choose to publish are sent to Obsidian's servers, and any notes you unpublish are removed.

## Password protection

For improved access control on your publish site, apply a site password. Visitors will be prompted for a password when attempting to access it. If you decide to remove the site password later, the entire site will become visible to the public again.

> [!warning] Individual password protection for published notes is currently not supported.

### Add a site password

2. In the **Publish changes** dialog, click **Change site options** (cog icon).
3. Under **Other site settings**, next to **Passwords**, click **Manage**.
4. Click **New password**.
5. In **Password**, enter a password for your site.
6. (Optional) In **Nickname**, enter a nickname for the password, for example, the person you want to give site access to.
7. Click **Add this password**.

### Remove a site password

5. Click the cross-icon next to the password you want to delete.

## Data collection
### Visitor data

By default, Obsidian Publish **does not** collect visitor data, store cookies, or process personal information. However you can implement analytics or log other user data by [[Customize your site|customizing your site]].

As the site owner, you are responsible for complying with GDPR and privacy regulations in your region. This includes creating your own notification banner, which can be implemented using publish.js, and adding a privacy policy page to your site.

['Access control for Obsidian Publish', 'Security/privacy for Obsidian Publish']

## Access
### Managing access to Obsidian Publish on your network

To regulate access to Obsidian Publish on your network, you need to manage the following domains:

- Frontend: `publish.obsidian.md`
- Backend: `publish-main.obsidian.md`

Additionally, the backend services employ the following subdomains: `publish-xx.obsidian.md`, where `xx` is a number ranging from `1 - 100`.

> [!tip] If your firewall system supports it, we recommend whitelisting `publish-*.obsidian.md` to accommodate our continuous expansion of subdomains.

[Obsidian Publish](https://obsidian.md/publish) is a cloud-based hosting service that lets you publish your notes as a wiki, knowledge base, documentation, or digital garden.

Select the notes you want to share with the world, press **Publish**, and we'll host it at `publish.obsidian.md/your-site`

If you're reading this on [help.obsidian.md](https://help.obsidian.md), you're already looking at a site that uses Obsidian Publish! You can see the vault on [GitHub](https://github.com/obsidianmd/obsidian-docs).

## How to use Obsidian Publish

- [[Set up Obsidian Publish]]
	- Get started with Obsidian Publish.
- [[Manage sites]]
	- Learn how to manage multiple Publish sites.
- [[Collaborate on a Publish site]]
	- Share a Publish site with collaborators.
- [[Customize your site]]
	- Customize your Publish site.
- [[Set up a custom domain|Custom domain]]
	- Set up Publish with your own domain.
- [[Security and privacy]]
	- How we keep your data safe.

docs/obsidian-help/Obsidian Publish/Introduction to Obsidian Publish.md

Renaming and removing notes is a natural part of maintaining a living vault. While Obsidian automatically updates links when you move a note within your local vault, other websites may still link to your old notes on your published [[Introduction to Obsidian Publish|Obsidian Publish]] site. In this article, you'll learn how to redirect readers from one note to another.

Imagine you want to move a note from one folder to another:

- **Guides**
  - ~~Making friends.md~~ (removed)
- **Tutorials**
  - *How to make friends.md* (added)

After you move the note, Obsidian automatically updates all links within the vault. However, if you publish the change to your Publish site, any links to `/Guides/Making+friends` will result in a 404.

To redirect readers from `/Guides/Making+friends` to `/Tutorials/How+to+make+friends`, you need to add an [[Aliases|alias]] in `How to make friends.md`, the note you want to redirect to.

```md
---
alias: Guides/Making friends
---

# How to make friends
```

> Make sure that you include the full path to the old note in the alias. While using only the note name as an alias works in your local vault, Publish needs the full path to the note to be able to redirect to it.

You can redirect multiple notes by adding an alias for each.

```md
---
aliases: 
  - Guides/Making friends
  - Developing friendships
---

```

[[Introduction to Obsidian Publish|Obsidian Publish]] lets you host notes and other media types, such as images and video clips, up to 4 GB per site. You can refer to our [[Accepted file formats|accepted file formats]] for more information.

You can upload files up to 50mb in size to your Publish site.

## Limitations

Obsidian Publish is not optimized for streaming video or large audio files. 

To improve the experience for your visitors, we recommend that you instead use a video hosting service, such as YouTube or Vimeo.

['Hosting large files', 'hosting media files', 'Obsidian Publish/Hosting media files']

## Search

Publish only searches page names and headings. Full text search will be added in the [future](https://obsidian.md/roadmap).

## Community plugins

Obsidian Publish has minimal support for [[Community plugins]]. 

Plugins which output in raw markdown, such as the Waypoint plugin, are compatible with Publish because they do not require the application to render their data. 

Whereas a plugin that requires a plugin codeblock to render, such as Dataview or Fantasy Statblocks, will not work by default in Publish. 

> [!tip] Members of our awesome [community](https://obsidian.md/community) have come up with workarounds to this limitation that may be worth checking out.

This page explains how you can customize how your [[Introduction to Obsidian Publish|Obsidian Publish]] site looks and feels.

## Static assets

You can customize your site by [[Publish and unpublish notes#Publish notes|publishing]] the following files to your site:

- `publish.css` to add custom CSS
- `publish.js` to add custom JavaScript
- `favicon-32x32.png` to set the favicon

**Notes:**

- Since Obsidian doesn't support CSS or JavaScript files, you need to use another application to create and edit them.
- Both `publish.css` and `publish.js` must be located in the root directory (`/`) of your vault.
- By default, `publish.css` and `publish.js` don't appear in the file explorer, but you can still publish them from the **Publish changes** dialog.
- To use custom JavaScript with `publish.js`, you need to [[Set up a custom domain]].

For favicons, Obsidian Publish supports the following naming conventions, where `32` is the icon dimensions in pixels:

- `favicon-32.png`
- `favicon-32x32.png`
- `favicon.ico`

We recommend that you provide one or more of the following dimensions:

- `favicon-128x128.png`
- `favicon-152x152.png`
- `favicon-167x167.png`
- `favicon-180x180.png`
- `favicon-192x192.png`
- `favicon-196x196.png`

You have flexibility in placing favicons anywhere within the vault, as long as they are published to your site.

## Use a community theme

To use one of the community themes for your site:

1. Open your vault in the default file explorer for your OS.
2. Go to the vault settings folder (default: `.obsidian`).
3. Open the `themes` folder.
4. Copy the CSS file for the theme you want to use for your site.
5. Paste the file into the root folder of your vault.
6. Rename the CSS file to `publish.css`.
7. [[Publish and unpublish notes#Publish notes|Publish]] `publish.css`.

- If the style doesn't change within a few minutes, you may need to refresh your browser cache.
- You can switch between light and dark mode in the [[Manage sites#View site options|site options]].

> [!tip] Developing themes
> Can't find the theme for you? Learn how to [Build a Publish theme](https://docs.obsidian.md/Themes/Obsidian+Publish+themes/Build+a+Publish+theme) yourself.

## Enable UI features

You can toggle several UI features for your site, such as the graph view or a table of contents.

Browse the available UI features under the **Reading experience** and **Components** sections in the [[Manage sites#View site options|site options]]

### Customize navigation

Within Obsidian Publish, you have the ability to customize the navigation order and display of files and folders within the Publish [[File explorer]]. Navigation items are listed in published order by default. Notes not published will not appear within this pane.

#### Accessing Customize navigation options

1. In ribbon, to the left of the application window, select **Publish changes** (paper plane icon).
2. In the **Publish changes** dialog, select **Change site options** (cog icon).
3. Under **Components settings**, next to **Customize navigation**, select the **manage** button. 

A new pop-up window titled **Navigation** will appear over your **Change site options** window.

#### Adjust navigation items

In the section labeled **Navigation preview**, you can adjust the display order of your published content.

1. Select the folder or note you want to adjust.
2. Drag the note or folder up or down until it is your desired place.
3. In the lower right of the **Navigation** window, select **Done**. 

Publish will send your navigation changes to your site. 

#### Hide and unhide navigation items

If there are notes or folders you have published, but you do not want visible within your Navigation, you can opt to hide those items instead. 

2. Right click and select **Hide in navigation**. The item should now disappear from the **Navigation preview**.

> [!tip] You can **Show hidden** files by selecting the checkbox to the right of the **Navigation Preview** title

#### FAQ

> [!question]- Q1. Can I move files from one folder to another within the **Navigation**?
> No.
> 
> The file navigation structure for notes within folders needs to be maintained. You can adjust note order within folders (including the vault root), and folder order within other folders. 

> [!question]- Q2. Can I edit the order of multiple notes and folders before selecting **Done**?
> Yes!

> [!question]- Q3. How do I revert these changes?
> **Display order**: Select the **Restore Default** icon (counter clockwise rotate arrow) next to **Navigation item display order**. This will restore your navigation items to alphabetical order.
>
> **Hidden status**: Select the **Restore Default** icon (counter clockwise rotate arrow) next to **Hide pages or folders from navigation**. This will restore your hidden navigation items to a visible state.

[Google Analytics](https://analytics.google.com) is a service that allows you to track traffic on your website. This page explains how to enable Google Analytics for your [[Introduction to Obsidian Publish|Obsidian Publish]] site.

> Before you enable Google Analytics, make sure that your local laws and regulations allow you to track your visitors.

## Prerequisites

To use Google Analytics for Obsidian, you need:

- A [[Set up a custom domain|custom domain]] for your Obsidian Publish site.

### Set up Google Analytics

To enable Google Analytics for your Obsidian Publish site:

3. In **Google Analytics tracking code**, enter your tracking code.

- To verify that your site uses Google Analytics, disable any ad-blocking browser extensions, such as uBlock Origin, that may block the tracking script from running.

- To use Google Tag Manager instead of Google Analytics, use custom JavaScript to add your own scripts.

Many social networks display a rich preview for your website when a user shares a link to it.  Using [[Properties]], you can customize how your notes appear in the preview.

> The tags overridden in this section are **only** visible by web crawlers. Regular web browsers are served the unmodified page for performance.

## Description

Obsidian automatically generates a description based on the note content, but you can provide your own using `description`.

```yaml
---
description: An introduction to our solar system.
---
```

> [!note] Meta tags
> `description` overrides the auto-generated description in `<meta name="description" content="...">` and the equivalents for `og:description` and `twitter:description`.

## Image

You can use a custom image for the link preview, by adding `image` or `cover` with a path to the image.

The path can be an absolute path from the root of your vault:

```yaml
---
cover: "Attachments/Cover image.png"
---
```

Or, an external URL:

```yaml
---
image: "https://example.com/cover%20image.png"
---
```

`image` and `cover` are identical. Only use one of them.

> `image` and `cover` overrides the auto-generated image in `<meta property="og:image" content="...">`.

docs/obsidian-help/Obsidian Publish/Social media link previews.md

In this guide, you'll enable [[Introduction to Obsidian Publish|Obsidian Publish]] for your vault, create a site, and publish your notes to it.

- An Obsidian account. If you don't have one, [sign up now](https://obsidian.md/account#mode=signup).
- An active Obsidian Publish subscription. If you don't have one, subscribe from your [account page](https://obsidian.md/account).

## Step 1: Log in with your Obsidian account

2. In the sidebar, select **General**.
3. Under **Account → Your Account**, select **Log in**.
4. In **Email**, enter your email.
5. In **Password**, enter your password.
6. Click **Login**.

## Step 2: Enable Obsidian Publish

2. In the sidebar, select **Core plugins**.
3. Enable **Publish**.

## Step 3: Create a new site

1. In ribbon, to the left of the application window, select **Publish changes** ( ![[lucide-send.svg#icon]] ).
2. In **Site ID**, enter the path you want for your site. For example, a site with the ID `my-amazing-site` is available from publish.obsidian.md/my-amazing-site.
3. Select **Create**.

## Step 4: Set a site name

1. In the **Publish changes** dialog, Select **Change site options** ( ![[lucide-cog.svg#icon]] ).
2. In **Site name**, under **General**, enter the name of your site.
3. Select **Save site settings**.

## Step 5: Select notes to publish

1. In the **Publish changes** dialog, select **NEW** to see all the notes you haven't published yet.
2. Select the notes you want to publish.
3. Click **Publish**.

The notes you selected are now available on your site. For more information, refer to [[Publish and unpublish notes]].

You've configured a Obsidian Publish site and published your first notes. Head over to the site address you configured earlier in this guide, and start sharing it with your readers.

Learn how to collaborate on your [[Introduction to Obsidian Publish|Obsidian Publish]] site with other Obsidian users. By adding your friends and colleagues as collaborators, they can publish changes to your site.

Only the site owner needs an active subscription for Obsidian Publish. Collaborators only need an [Obsidian account](https://obsidian.md/account).

> Before you publish changes to a shared site, make sure to [[#Syncing changes between collaborators|sync changes from other collaborators]]. Otherwise, you risk overwriting changes from other collaborators.

## Add a collaborator to a site

3. Next to **Site collaboration**, select **Manage**.
4. In **Invite user**, enter the email of the collaborator.
5. Select **Add**.

## Remove a collaborator from a site

4. Next to the collaborator you want to remove, select **Remove user** (cross icon).

## Sync changes between collaborators

Obsidian Publish doesn't sync published changes between local vaults automatically. Instead, collaborators need to manually sync changes from other collaborators.

To update a local note with changes from the live site:

2. Right-click the change you want to sync, and then select **Use live version**. **This will overwrite the note in your local vault.**

> [!tip]
> We recommend that you use another tool to sync changes between vaults, such as [[Introduction to Obsidian Sync|Obsidian Sync]] or [git](https://git-scm.com/).

docs/obsidian-help/Obsidian Publish/Collaborate on a Publish site.md

## Permissions

The following table lists the available site permissions for owners and collaborators:

| Action                             | Collaborator | Owner |
|------------------------------------|:------------:|:-----:|
| Publish new pages                  | ✓            | ✓     |
| Publish changes to published pages | ✓            | ✓     |
| Unpublish pages                    | ✓            | ✓     |
| Configure site options             |              | ✓     |
| Manage permissions                 |              | ✓     |

This page explains how to manage [[Introduction to Obsidian Publish|Obsidian Publish]] sites.

A site is a collection of notes that's hosted by Obsidian Publish and available online, either through a Obsidian Publish address or a [[Set up a custom domain|custom domain]].

## Create a new site

> [!note] The number of sites that you can have at the same time is determined by your Obsidian Publish subscription. Before you create a new site, make sure that your subscription allows it.

2. If you already have an existing site, click **Switch site** (arrows icon).
3. In **Site ID**, enter the path you want for your site. For example, a site with the ID `my-amazing-site` is available from publish.obsidian.md/my-amazing-site.

## Delete an existing site

> [!note] Notes remain in your vault even after you delete a site.

2. Click **Switch site** (arrows icon).
3. Click **Delete site** (cross icon) to the right of the site you want to delete.
4. Click **Delete** to confirm.

## Switch between sites

3. Click **Choose** to the right of the site you want to switch to.

## Change the site ID

3. Click **Edit site ID** (pen icon) to the right of the site you want to edit.
4. In **Site ID**, enter the new ID for your site.
5. Click **Change**.

## View site options

## Site Options

### General

| Option                          | Type   | Description                                                                                                                |
|---------------------------------|--------|----------------------------------------------------------------------------------------------------------------------------|
| Site Name                       | Input  | The public name and title of your Obsidian Publish site.                                                                   |
| Homepage File                   | Input  | The location of the markdown file you want to act as your landing page.                                                    |
| Logo                            | Input  | The image you want to act as your site banner. The image must [[Publish and unpublish notes#Publish notes\|be published]]. |
| Site Collaboration              | Button | Declare other users you want to have access to edit your published notes. Users must have an Obsidian account.             |
| Custom Domain                   | Button | [[Set up a custom domain]]                                                                                                 |
| Disallow search engine indexing | Toggle | Prevents respectful search engines from crawling your site.                                                                |

### Appearance

| Option            | Type     | Description                                                                               |
|-------------------|----------|-------------------------------------------------------------------------------------------|
| Theme             | Dropdown | Choose how your theme presents on your site; **Light**, **Dark**, or **Adapt to System**. |
| Light/Dark Toggle | Toggle   | Allow users to toggle **Light**/**Dark** mode with a toggle button on your site.          |

## Reading experience

| Option               | Type   | Description                                                                                |
|----------------------|--------|--------------------------------------------------------------------------------------------|
| Show hover preview   | Toggle | Enable or disable the ability of page preview when hovering over an active, internal link. |
| Hide page title      | Toggle | Enable or disable the inline title of a published note to be displayed.                    |
| Readable line length | Toggle | Enable or disable readable line length within your site.                                   |
| Strict line breaks   | Toggle | Enable or disable single line breaks from being displayed on your site.                    |
| Stack Pages          | Toggle | Enable or disable [[Tabs#Stack tab groups|Stacked tabs]] on your site.    |

### Components

| Option                 | Type   | Description                                                                                                                          |
|------------------------|--------|--------------------------------------------------------------------------------------------------------------------------------------|
| Show navigation        | Toggle | Enable or disable the [[File explorer]] view on your publish site.                                                                   |
| Customize navigation   | Button | [[Customize your site#Customize navigation\|Customize]] the order of how your files are listed if **Show navigation** is toggled on. |
| Show search bar        | Toggle | Enable or disable a search bar on your site.                                                                                         |
| Show graph view        | Toggle | Enable or disable the graph view within the right sidebar of your site.                                                              |
| Show table of contents | Toggle | Enable or disable the [[Outline\|Table of contents]] view on your site.                                                              |
| Show backlinks         | Toggle | Enable or disable [[Backlinks]] on your site.                                                                                        |

> [!tip] The search bar searches for published note titles, aliases, and headings.

### Other site settings

| Option                         | Type   | Description                                            |
| ------------------------------ | ------ | ------------------------------------------------------ |
| Passwords                      | Button | [[Obsidian Publish/Security and privacy#Add a site password\|Set a password]] to restrict access to your entire site. |
| Google Analytics tracking code | Input  | **Custom Domain Url Only**. Place your Google Analytics site tracking code here.                                                       |

You can set up a custom domain or subdomain for your [[Introduction to Obsidian Publish|Obsidian Publish]] site.

> At the moment, we only support configuring custom domains using the following methods:
>
> - [[#Set up using CloudFlare]] using [Full mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full/).
> - [[#Set up using a proxy]]
> 
> We don't yet have a way to provision an SSL certificate on your behalf.

## Set up using CloudFlare

The easiest way to set up a custom domain or subdomain is to create a [CloudFlare](https://cloudflare.com) account and let CloudFlare manage your domain's DNS.

The following steps use CloudFlare to configure a custom domain for your Obsidian Publish site, either using a root domain (`mysite.com`) or a subdomain (`notes.mysite.com`).

> CloudFlare is the **only officially supported provider** for setting up custom domains. Using the following instructions with any other providers will likely not work.

**CloudFlare:**

1. Open Cloudflare to the domain where you want to host your Publish site, such as `mysite.com`, even if you want a subdomain like `notes.mysite.com`.
2. Go to **DNS** and click **Add Record**.
3. Select **CNAME**.
4. In **name**, enter your domain or subdomain, for example `notes.mysite.com`.
5. In **target**, enter `publish-main.obsidian.md`. Don't include your personal sub-URL in this value. Obsidian Publish handles this from your configuration.
6. Make sure that **proxy status** is enabled. It should be enabled by default.
7. Go to **SSL/TLS** and set the SSL/TLS encryption mode to "Full" to configure the SSL/TLS certificate automatically.

> [!note]
> To redirect both `mysite.com` and `www.mysite.com` to Obsidian Publish, you need to create a [Page Rule](https://support.cloudflare.com/hc/en-us/articles/200172336-Creating-Page-Rules) with the following settings:
>
> - URL match: `www.mysite.com/*`
> - Forward URL - 301 Permanent Redirect
> - Redirect URL: `https://mysite.com/$1`
>
> After you've created the page rule, create a CNAME record for `www.mysite.com` just like you did for `mysite.com`.

**Obsidian:**

1. Open Obsidian on your computer.
2. In the [[Ribbon]] at the left, click **Publish changes** (paper plane icon).
3. Under **Publish changes**, select **Change site options** (cog icon).
4. Next to **Custom domain**, select **Configure**.
5. In **Custom URL**, enter the URL to your domain or subdomain.

> [!note]
> If your custom domain setup ends up in a redirect loop, it's likely that the encryption mode in CloudFlare has been set to "Flexible" instead of "Full".

## Set up using a proxy

You can also set up SSL/TLS for your custom domain by using your own web server.

If you are already hosting a website under your domain or subdomain, you can also use this option and set up your website to load your Obsidian Publish site under a specific URL path, instead of hosting the full site.

Proxy all requests under that URL path to `https://publish.obsidian.md/serve?url=mysite.com/my-notes/...` and configure the site options in Obsidian to the same URL path, by setting **Custom URL** to `mysite.com/my-notes`.

You can also set up Obsidian Publish as a sub-URL of a site you own. For example, `https://mysite.com/my-notes/`. To achieve this, you must host your own server and proxy all requests to our server at `https://publish.obsidian.md/`.

### NGINX

In your NGINX configuration, add the following:

```nginx
location /my-notes {
  proxy_pass https://publish.obsidian.md/serve?url=mysite.com/my-notes/;
  proxy_ssl_server_name on;
  proxy_set_header Host publish.obsidian.md;
}
```

### Apache

In `.htaccess`, add the following:

```htaccess
RewriteEngine  on
RewriteRule    "^my-notes/(.*)$"  "https://publish.obsidian.md/serve?url=mysite.com/my-notes/$1"  [L,P]
```

> [!note]
> `mod_rewrite` must be enabled, and you may also need to configure [SSLProxyEngine](https://stackoverflow.com/questions/40938148/reverse-proxy-for-external-url-apache)

### Netlify

```plain
[[redirects]]
  from = "https://mysite.com/my-notes/*"
  to = "https://publish.obsidian.md/serve?url=mysite.com/my-notes/:splat"
  status = 200
  force = true
```

### Vercel

In `vercel.json`, [configure rewrites](https://vercel.com/docs/configuration#project/rewrites):

```json
{
  ...

  "rewrites": [
    {
      "source": "/my-notes/",
      "destination": "https://publish.obsidian.md/serve?url=mysite.com/my-notes"
    },
    {
      "source": "/my-notes/:path*",
      "destination": "https://publish.obsidian.md/serve?url=mysite.com/my-notes/:path*"
    }
  ]
}
```

### Caddy

```plain
mysite.com {
  encode zstd gzip
  handle /my-notes* {
    reverse_proxy https://publish.obsidian.md {
      header_up Host {upstream_hostport}
    }
    rewrite * /serve?url=mysite.com{path}
  }
}
```

### Traefik

This minimal configuration excerpt redirects `mysite.com` to Obsidian publish.
See the [Traefik documentation](https://doc.traefik.io/traefik/routing/overview/)
for a complete example.

```yaml
http:
  routers:
    mysite:
      rule: Host(`mysite.com`)
      service: obsidian-publish
      middlewares:
        - "publish-headers"
  services:
    obsidian-publish:
      loadBalancer:
        servers:
          - url: https://publish.obsidian.md
  middlewares:
    publish-headers:
      headers:
        customRequestHeaders:
          Host: "publish.obsidian.md"
          x-obsidian-custom-domain: "mysite.com"
```

### Supported HTTP X-Headers

If your proxy service doesn't allow query paths, you can use `https://publish.obsidian.md/` with a custom header `x-obsidian-custom-domain` set to your site URL `mysite.com/my-subpath`.

## Redirect old site to custom domain

If you want to redirect your visitors from the old `publish.obsidian.md` site to your new custom domain, enable the **Redirect to your custom domain** option when configuring your custom domain.

## Troubleshoot

Once you set up your custom domain, if you've visited your site from your previous `https://publish.obsidian.md/slug` link, you may have to clear your browser cache for certain things (like fonts, graphs, or password access) to work properly. This is due to the cross-domain security restrictions that are imposed by modern browsers. The good news is that readers of your site should never run into issue this if you only let visitors use your custom domain.

This page explains the ways you can support the development of Obsidian financially.

One of the best ways to support the team is through one or more of our paid products.

- If you need to sync notes across your devices, consider a subscription for [[Introduction to Obsidian Sync|Obsidian Sync]].
- If you want to publish your notes to the world, consider a subscription for [[Introduction to Obsidian Publish|Obsidian Publish]].
- If you use Obsidian for work, we ask you to purchase a [[Commercial license]].

We understand that you might not be interested in any of our paid products right now, though we'd love to know how we can change that! If you still want to support Obsidian and you only use Obsidian for personal purposes, consider getting a [[Catalyst license]].

docs/obsidian-help/Contributing to Obsidian/Financial contributions.md

The Obsidian documentation uses the [Google developer documentation style guide](https://developers.google.com/style). For any topics not covered by the Google style guide, use the [Microsoft Style Guide](https://learn.microsoft.com/en-us/style-guide/).

This page lists any deviations from the Google style guide, or terminology worth highlighting.

> [!tip] Contribute
> Most of the documentation existed before this style guide did. If you find any violations of this style guide, please [create an issue](https://github.com/obsidianmd/obsidian-docs/issues/new) or submit a pull request to [obsidianmd/obsidian-docs](https://github.com/obsidianmd/obsidian-docs).

## Terminology and grammar

### Terms

- Prefer "keyboard shortcut" over "hotkey". Use Hotkey when referring to the specific feature.
- Prefer "the Obsidian app" on mobile, and "the Obsidian application" on desktop.
- Prefer "sync" or "syncing" over "synchronize" or "synchronizing".
- Prefer "search term" over "search query".
- Prefer "heading" over "header" when referring to a text that introduces a section.
- Prefer "maximum" over "max" and "minimum" over "min".

### Product names

Obsidian product names start with "Obsidian", for example "Obsidian Publish" and "Obsidian Sync".

If a paragraph becomes overly repetitive, you can use the short form in subsequent references.

_To allow device-specific configuration, Obsidian Sync doesn't sync its own settings. You need to configure Sync for each of your devices._

### UI and interactions

- Use **bold** to indicate button text
- Prefer "select" over "tap" or "click".
- Prefer "sidebar" over "side bar".
- Prefer "perform" over "invoke" and "execute" when referring to commands or actions.

When referring to multiple UI interactions in a sequence, use the → (U+2192) symbol. For example, "**Settings → Community plugins**".

### Notes, files, and folders

- Use "note" when referring to a Markdown file in the vault.
- Use "file" when referring to other file extensions than Markdown.
- Prefer "note name" over "note title".
- Prefer "active note" over "current note".
- Prefer "folder" over "directory".
- Prefer "file type" over "file format", unless specifically referring to the data format of the file content.

When moving between notes, use "open" if the destination is hidden, and "switch" if both source and destination notes are open in separate splits.

### Reference documentation for settings

When possible, any settings should be documented within Obsidian using a descriptive text. Avoid documenting a specific setting in Obsidian Help unless:

- It requires more in-depth knowledge on how and when to use it.
- It's commonly misused or asked about.
- It _drastically_ changes the user experience.

Consider using a tip callout if you want to draw attention to a specific setting.

### Directional terms

Hyphenate directional terms when using them as adjectives. Avoid hyphenation when direction is used as a noun.

**Recommended:**

- Select **Settings** in the bottom-left corner.
- Select **Settings** in the bottom left.

**Not recommended:**

- Select **Settings** in the bottom left corner.
- Select **Settings** in the bottom-left.

Prefer "upper-left" and "upper-right" over "top-left" and "top-right".

Don't indicate a direction when referring to settings. The location of the settings control depends on the device.

- Next to **Pick remote vault**, select **Choose**.

- To the right of **Pick remote vault**, select **Choose**.

### Instructions

Use imperatives for the names of guides, section headings, and step-by-step instructions. The imperative mood is concise and action-oriented, which is more straightforward for users following instructions.

- Prefer "Set up" over "Setting up"
- Prefer "Move a file" over "Moving a file"
- Prefer "Import your notes" over "Importing your notes"

### Sentence case

Prefer *sentence case* over *title case* for headings, buttons, and titles. When referencing UI elements always match the case of the text in the UI.

- How Obsidian stores data

- How Obsidian Stores Data
### Examples

Prefer realistic examples over nonsense terms.

- `task:(call OR schedule)`

- `task:(foo OR bar)`

### Key names

When referring to a character on the keyboard by name, add the character between parentheses right after the name:

- Add a hyphen (-) in front of the word.

- Add a hyphen in front of the word.
- Add a `-` in front of the word.

### Markdown

Use newlines between Markdown blocks:

```md
# Heading 1

This is a section.

1. First item
2. Second item
3. Third item
```

```md
# Heading 1
```

### Images

Use "**width** x **height** pixels" for describing image or screen dimensions.

**Example:**

Recommended image dimensions: 1920 x 1080 pixels.

### Images

## Icons and images

Include icons and images when they make it easier to explain things that are hard to describe with words, or when you need to show important parts of the Obsidian application. You can save images in the `Attachments` folder.

- The image should make the text it accompanies easier to understand.

 **Example**: Once enabled, the [[Word count]] plugin will create a new entry on your bottom statusbar.
 
![[Style-guide-zoomed-example.png#interface|300]]

- Images should be in either `.png` or `.svg` format.
- If an image looks too big in the note, make it smaller outside of Obsidian, or adjust its dimensions as explained in [[Embed files#Embed an image in a note|embedding an image in a note]].
- In rare cases, you may want to place especially large or complex images in a [[Callouts#Foldable callouts|folded callout]]. 
- For pop-up windows or modals, the image should show the entire Obsidian application window.
 ![[Style-guide-modal-example.png#interface]]

### Icons

[Lucide](https://lucide.dev/icons/) and custom Obsidian icons can be used alongside detailed elements to provide a visual representation of a feature.

**Example:** In the ribbon on the left, select **Create new canvas** ( ![[lucide-layout-dashboard.svg#icon]] ) to create a canvas in the same folder as the active file.

**Guidelines for icons**

- Store icons in the `Attachments/icons` folder.
- Add the prefix `lucide-` before the Lucide icon name.
- Add the prefix `obsidian-` before the Obsidian icon name.

**Example:** The icon for creating a new canvas should be named `lucide-layout-dashboard`.

- Use the SVG version of the icons available.
- Icons should be `18` pixels in width, `18` pixels in height, and have a stroke width of `1.5`. You can adjust these settings in the SVG data.

> [!info]- Adjusting size and stroke in an SVG
> ```html
> <svg xmlns="http://www.w3.org/2000/svg" width="WIDTH" height="HEIGHT" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="STROKE-WIDTH" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-layout-dashboard"><rect width="7" height="9" x="3" y="3" rx="1"/><rect width="7" height="5" x="14" y="3" rx="1"/><rect width="7" height="9" x="14" y="12" rx="1"/><rect width="7" height="5" x="3" y="16" rx="1"/></svg>
>```

- Utilize the `icon` anchor in embedded images, to tweak the spacing around the icon so that it aligns neatly with the text in the vicinity.
- Icons should be surrounded by parenthesis. ( ![[lucide-cog.svg#icon]] )

**Example**: `( ![[lucide-cog.svg#icon]] )`

### Image anchor tags

Image anchors tags are available to add decorative changes to the embedded images. 

> [!warning] Live preview warning
> The icon anchor tags will not display correctly in **Live preview.** Use **Reading view** to confirm the anchor tag has been applied. 

**Icon**

`![[lucide-menu.svg#icon]]`

The icon anchor tag ensures correct vertical alignment for icons used to indicate interface elements.

The first menu icon uses the anchor tag ( ![[lucide-menu.svg#icon]] ), while the second menu icon ( ![[lucide-menu.svg]] ) does not.

**Interface**

`![[Vault picker.png#interface]]`

The interface anchor tag adds a decorative box shadow around the image. In the first image, the interface anchor tag is applied.
![[Vault picker.png#interface]]
In contrast, the second image does not have the interface anchor applied.

![[Vault picker.png]]

**Outline**

`![[Backlinks.png#outline]]`

The outline anchor tag adds a subtle border around the image. In the first image, the outline anchor tag is applied. 

> [!tip] Observe the lower left of the image to see the difference.

![[Backlinks.png#outline]]

The second image lacks the outline anchor tag.

![[Backlinks.png]]

### Optimization

Images slow the loading time of the page, and take valuable [[Introduction to Obsidian Publish|Publish]] storage space. Optimizing images allows a reduction in file size, but maintains the visual integrity of the image. 

Both images and icons should be optimized.

> [!success] Tools for optimizing images
> Here are a some recommended programs for reducing the size of your images.
> - **Windows:** [FileOptimizer](https://sourceforge.net/projects/nikkhokkho/)
> - **macOS:** [ImageOptim](https://imageoptim.com/)
> - **Linux/Unix** [Trimage](https://trimage.org)
> 
> We recommend an optimization rate of 65-75%.

If you're familiar with TypeScript or CSS, you can develop your own [[Community plugins]] and [[Themes]]. 

Learn more by heading over to the [Obsidian Developer Documentation](https://docs.obsidian.md).

To help improve our developer documentation, submit a pull request to the [obsidian-developer-docs](https://github.com/obsidianmd/obsidian-developer-docs) repository.

If you know another language, preferably natively, you can help translate the Obsidian user interface or the documentation.

To help translate the user interface, submit a pull request to the [translations repository](https://github.com/obsidianmd/obsidian-translations).

To help improve our documentation, submit a pull request to the [obsidian-help](https://github.com/obsidianmd/obsidian-help) repository.

This help article is legacy and only serves as a bridge to avoid breaking links. For information on the mobile app, please see [[Sync your notes across devices]].

## Sync

For information on syncing on the iOS app, please see [[Sync your notes across devices#Sync your notes on iPhone and iPad|Sync your notes on iPhone and iPad]].

## Sync

For information on syncing on the Android app, please see [[Sync your notes across devices#Sync notes on Android|Sync notes on Android]].

## Storage permissions

When starting Obsidian, you may notice that it prompts for permission to access your device's documents and media.

In an ideal world, we'd prefer to only ask for access rights to the vault folders you choose. However, Android's privacy-friendly file permission API (also known as "scoped storage") has a few restrictions that makes it impossible for Obsidian to function properly.

The two biggest roadblocks are:

- Scoped storage performs many extra permission checks for every single file access, causing significant performance degradation when opening and using Obsidian.
- Scoped storage doesn't provide a way to watch for external changes, which is critical when using Obsidian with a third-party syncing tool.

Google specifically gives instructions for developers of this kind of apps a special permission. Obsidian belongs to two categories in the list of exceptions: "document management apps", and "on-device file search". [Read more about it here.](https://developer.android.com/training/data-storage/manage-all-files)

Names aren't listed by amount of contribution, but alphabetically (or at least we try!).

## Team

### Development

- Licat (Shida Li)<span class='flair mod-pop'>Obsidian office cat</span>
- liam ([Liam Cain](https://liamca.in/)) <span class='flair mod-pop'>Maker of Calendar</span> <span class='flair mod-pop'>Plugin API Master</span> <span class='flair mod-pop'>Volcano Veteran</span>
- joethei ([Johannes Theiner](https://joethei.xyz/)) <span class='flair mod-pop'>Plugin API Master</span>
- tgrosinger ([Tony Grosinger](https://grosinger.net))
- mgmeyers ([Matthew Meyers](https://matthewmeye.rs/))

### Product & Operations

- Silver ([Erica Xu](https://ericaxu.com))<span class='flair mod-pop'>Team Little Silvers</span>
- kepano ([Steph Ango](https://stephanango.com/))
- Sigrunixia ([Rebbecca Bishop](https://tenebrousdragon.com/home))<span class='flair mod-pop'>Support Dragon</span>

## Moderators

- argentum<span class='flair mod-pop'>Team Little Silvers</span> <span class='flair mod-pop'>Linux master</span> <span class='flair mod-pop'>Zotero master</span> ^a4b3a2
- cotemaxime ([Maxime Côté](https://www.maximecote.me/))<span class='flair mod-pop'>Linux master</span>
- Eleanor ([Eleanor Konik](https://eleanorkonik.com))<span class='flair mod-pop'>Halp Obsidian turned me into a dev</span>
- koala<span class='flair mod-pop'>Extreme Bug Finder</span>
- Leah ([Leah Ferguson](http://leahferguson.com))<span class='flair mod-pop'>Roll for initiative!</span> <span class='flair mod-pop'>Non-techy Apple geek</span>
- mediapathic ([Steen Comer](http://mediapathic.net/))<span class='flair mod-pop'>Bad Cop</span>
- rigmarole ([Chris Lesage](http://rigmarolestudio.com))<span class='flair mod-pop'>Forum master</span>
- ryanjamurphy ([Ryan](https://fulcra.design/) [J. A. Murphy](https://axle.design/))<span class='flair mod-pop'>That funny guy</span> <span class='flair mod-pop'>Apple Fanboy</span> <span class='flair mod-pop'>Forum master</span>
- WhiteNoise<span class='flair mod-pop'>Think Tank</span> <span class='flair mod-pop'>Zotero master</span> <span class='flair mod-pop'>Bug report exterminator</span>
- CawlinTeffid ([Colin Tedford](https://colintedford.com/)) <span class='flair mod-pop'>embedded-search ambassador</span>
- Carl the Turtle<span class='flair mod-pop'>Online 24/7</span> <span class='flair mod-pop'>Easily triggered</span> <span class='flair mod-pop'>Good and pure</span> <span class='flair mod-pop' style='background-color:#0a8c28'>Go green or go home</span>

## Plugin inspirations

Credits to these plugin developers for pioneering functionality that were adapted into Obsidian:

- pjeby for the Hotkey Helper plugin
- javalent for the Admonition plugin
- NothingIsLost for several CodeMirror 6 improvements
- mgmeyers for the Indentation Guides plugin

## Builds

- jstone for maintaining our builds on flathub
- adamgibbins and ran-dall for maintaining our builds on homebrew

## Translators

- Andrea Brandi (Italian)
- canzi-teacher, 蚕子 (Chinese Simplified)
- Daniel Mathiot (French)
- Haitham Mohamed (Arabic)
- Henrik Falk (Danish)
- JxhnnyUt8h (Russian)
- k-andzhanovskii, Константин Анджановский (Russian)
- lisachev, Сергей Лисачев (Russian)
- mafsi, (Patrick Danilevici) (Română)
- Muhammad Mauli Mubassari (Indonesian)
- taksas, 中山 拓海 (Japanese)
- VKondakoff, Валерий Кондаков (Russian)
- yo-goto, ぱだわん (Japanese)
- Zachary Shirmohammadli (Persian)

## Documentation

The first version of the help vault was written by Silver. Later part of it was written by [@mediapathic](http://mediapathic.net), with a big help from Reggie. We also got corrections from the many pairs of eyes in the Discord and forum community.

The docs was maintained by [Marcus Olsson](https://marcus.se.net/) for a while. Currently it’s maintained by the Obsidian team.

We now accept pull requests to the help vault in [our docs repo](https://github.com/obsidianmd/obsidian-docs/). Issues are welcome.

### Add your name

If you're a translator, please make a pull request to add "Your Name (contributed language)" to the section above. Please keep the list of names alphabetical, thanks!

If your name isn't in English and can't be alphabetically listed, use this format: `your-github-username, [your name in your language] (Language name)`.

## Third party acknowledgements

Obsidian uses the open source libraries below (in alphabetical order):

### Capacitor

MIT License
Copyright (c) 2017-present Drifty Co.

### CodeMirror

Vim Version `6.0.0`
Copyright (C) 2018 by Marijn Haverbeke <marijnh@gmail.com>, Adrian Heine <mail@adrianheine.de>, and others

### DOMPurify

https://github.com/cure53/DOMPurify
Licensed under the [Mozilla Public License version 2.0](http://mozilla.org/MPL/2.0/)

### Electron

Version `25.8.1`
Copyright (c) Electron contributors
Copyright (c) 2013-2020 GitHub Inc.

### i18next

Copyright (c) 2022 i18next

### Lezer

Copyright (C) 2018-2021 by Marijn Haverbeke <marijnh@gmail.com> and others

### Lucide

Version `0.268.0`
ISC License
Copyright (c) 2020, Lucide Contributors ^lucide

### MathJax

Apache License 2.0

### Mermaid

Version `10.2.3`
Copyright (c) 2014 - 2022 Knut Sveidqvist

### Moment.js

Version `2.29.4`
Copyright (c) JS Foundation and other contributors
### pdf.js

### PixiJS

Copyright (c) 2013-2017 Mathew Groves, Chad Engler

### Prism

Copyright (c) 2012 Lea Verou

### rbush

Copyright (c) 2016 Vladimir Agafonkin

### remark

Copyright (c) 2014-2020 Titus Wormer <tituswormer@gmail.com>
Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/)

### reveal.js

Version `4.3.1`
The MIT License
Copyright (C) 2011-2022 Hakim El Hattab, http://hakim.se, and reveal.js contributors

### scrypt

### Turndown

Copyright (c) 2017 Dom Christie

### Webpack

Copyright JS Foundation and other contributors

### YAML

Copyright Eemeli Aro <eemeli@gmail.com>

## Previous logo

The Obsidian logo used before v1.3.5 was adapted from:

[Crystal shard icon](https://icon-icons.com/icon/Crystal-Shard/88819)
By [Chanut is Industries](https://icon-icons.com/users/W52nHhY3W1VlvwyJTwS4d/icon-sets/ "Designer")
License: Attribution 3.0 Unported (CC BY 3.0)

## The rules

These are the behaviors we don’t tolerate.

### Serious offenses

Users who commit these offences will be immediately banned from the official Obsidian community channels.

#### Harassment

Harassment includes offensive verbal comments related to gender, sexual orientation, disability, physical appearance, body size, race, or religion, as well as sexual images in public spaces, deliberate intimidation, stalking, following, harassing photography or recording, inappropriate physical contact, and unwelcome sexual or romantic attention.

#### Threats

We don’t tolerate any threats, physically or verbally. For example, threatening to publicize sensitive information about someone’s personal life.

#### Blatant -isms

This includes saying things that are explicitly racist, sexist, homophobic, etc. For example, arguing that some people are less intelligent because of their gender, race or religion. Small mistakes made in conversation aren't code of conduct violations. However, repeating something after it has been pointed out to you, or antagonizing or arguing with someone who has pointed out your subtle -ism is considered a minor offense.

### Other offenses

Users who commit these offences will be sent a warning. Repeated offences will result in the user being banned from the official Obsidian community channels.

#### Belligerence

Belligerence is deliberately attempting to make others feel bad, name-calling, singling out others for derision or exclusion. For example, telling someone they’re not a real programmer or that they don’t belong.

#### Being especially unpleasant

For example, if we’ve received reports from multiple members of annoying or rude behavior.

#### Unsolicited messages to team or moderators

This includes unsolicited tagging, "pinging", or direct messaging Obsidian team staff and moderators for questions, bug reports, and feature requests. As much as we want to help everyone, we have a sizeable community, and the team's attention must be reserved for critical matters. You can ping or direct message members of the team for things like security-related issues or to report violations of the community code of conduct. Otherwise, please post about the issue in an appropriate channel on the forum or the Discord server.

### Other behaviors

While the following behaviors don’t result in a ban or warning, we strongly discourage you from engaging in them. They will greatly increase the risk of [[#being especially unpleasant]].

#### Sea-lioning

[Sea-lioning](https://en.wikipedia.org/wiki/Sealioning) means continuously pursuing an agenda by questioning and provoking other members. Individual provocations and questions are often perfectly acceptable, but in the case of sea-lioning, they accumulate to unhealthy levels, creating a hostile and negative conversation.

#### "Feed me"

"Feed me" means asking others to solve problems for you without putting in any effort yourself. This is particularly egregious when the problem-solving is non-trivial and yet the user begs for someone else to do the work for them.

#### Campaigning

Campaigning is continuously making the same requests. This applies to both feature requests and to requests for help. Don’t post the same question in multiple places in short time frames, and don’t ask developers for the same features or bug fixes repeatedly.

#### Excessive self promotion

We encourage sharing what you made, for example guides, videos, utilities, and tools. It's awesome to see what Obsidian users are up to. As a content creator, it’s inevitable that you will link to your own creations.

**Exclusive** self promotion is the promoting and linking of your or others' content and initiatives without contributing to the community otherwise. We won’t tolerate users whose only purpose in the community is to post links or solicitations to initiatives outside the community. Depending on the case, links may be removed, or warnings given.

**Excessive** self promotion is a judgement call. Please be respectful of the community and prioritize active community participation before linking. We reserve the right to remove links we think breach this guideline.

Note that linking to paid content made by oneself will be scrutinized even closely, as the likelihood of conflict of interest is highest with this type of content.

#### Spamming

Do not directly message any of our community member without asking for consent first. It’s okay to ask publicly if you have a question.

## Encouraged behaviors

Over the years of running the official Obsidian community channels, we’ve noticed some behaviors that positively contribute to the community.

If you’re looking to improve your communication skills as well as becoming a better community citizen, consider doing the following:

- **Try before asking**: before asking for help, please first try searching the help docs and Discord/forum history to see if the question has already been asked. Help others help you, by sharing what you've already tried.
- **Keep an open mind**: because of how customizable Obsidian can be, some people might have a completely different set-up or workflow from you. Don’t judge others for their choices.
- **Step away when heated**: the community is a place for us to grow together, not a debate competition. If a discussion escalates into an argument, try your best to step away and leave the conversation.

## Motivation

We at Obsidian want to create the best community for knowledge management. We want everyone to be able to seek help, help others, and share their experience, without fear or embarrassment.

In order to get there, all of our members are expected to be nice to each other in all interactions, whether it's on our Discord server or on our forum.

"Be nice" is a vague instruction, though. To make sure we're on the same page what's nice and what's not, we've adopted the code of conduct above.

As the community grows, we can't rely on all members to be nice, although the vast majority of our members show exceptional respect towards each other. Adopting a more formal code of conduct — and enforcing it — helps maintain a vital and healthy community.

## Please report violations

The code of conduct is enforced by our moderators, but we can't monitor every single interaction in the official Obsidian community channels. This is why we rely on our members to help us improve the official Obsidian community channels by reporting violations of our code of conduct.

Even if you're not the victim, you can still report violations as a witness.

We'll keep the identity of the reporter as confidential as we can.

### Report on Discord

In \#bots-land-mute-me channel, or any other channel, type `/moderation report @offenderName Please write your reason here`. Your message will disappear immediately, and a report will be sent to our moderator only channel.

### Report on the forum

Please flag the relevant conversation with a reason, and our moderators will investigate.

## Enforcement

> [!abstract] Summary
> A verified serious offense results in an immediate ban.
> A verified other offense results in a warning; after that a second verified violation results in a ban.

If our moderators witness or receive a report about [[#serious offenses]], we will contact the offender to have a conversation with them and verify what has happened. If verified, they will be removed from the official Obsidian community channels.

If our moderators witness or receive a report about [[#other offenses]], we will contact the member involved to explain why their behavior was unacceptable, and warn them that a second code of conduct violation will result in us removing them from the official Obsidian community channels.

## Credits

Our Code of Conduct is heavily based on [Recurse Center's Code of Conduct](https://www.recurse.com/code-of-conduct).

## Changelog

- 2023-10-28: Moved blatant -isms from "Other offenses" to "Serious offenses", meaning they’re now bannable on first offense.

## What is Obsidian

Obsidian is both a Markdown editor and a knowledge base app.

Used in the most basic way, you can edit and preview Markdown files. But its true power lies in managing a densely networked knowledge base.

How do we start creating a network, you ask? Let's first start making some [[Internal links]]!

## How we're different

### You own and control your data

We believe in plain text for something as important as your knowledge base. You don't want to put your own brain over someone else's neck, do you? Treat your second brain the same way.

Sync is only a utility to facilitate working on multiple devices, the data will always primarily live on your hard disk.

When the file system replaces the cloud, you get flexible options to work with your files: you can back them up with Dropbox, use Git to do versioning, or encrypt your disk for security. Whatever works on your file system will work on your Obsidian knowledge base.

### Links are first-class citizens

Links and connections are crucial to discovering the relations between what we know.

Obsidian greatly values this, and encourages it with [[Internal links]] and [[Graph view]], among other things.

As John Locke puts it...

> The acts of the mind, wherein it exerts its power over simple ideas, are chiefly these three:
>
> 1. Combining several simple ideas into one compound one, and thus all complex ideas are made.
> 2. The second is bringing two ideas, whether simple or complex, together, and setting them by one another so as to take a view of them at once, without uniting them into one, by which it gets all its ideas of relations.
> 3. The third is separating them from all other ideas that accompany them in their real existence: this is called abstraction, and thus all its general ideas are made.

 \- John Locke, An Essay Concerning Human Understanding (1690)

Hierarchy gives us No. 1, and linking gives us No. 2. We're still unsure what No. 3 entails in the context of note-taking, but it might have something to do with programming or macros.

### Your own toolkit

Note-taking is a highly personal activity. Naturally there is no single all-encompassing solution for everyone.

Instead of providing you with an opinionated and assembled product, [[Obsidian]] gives you a foundation and numerous functional building blocks  to discover and build your own solution.

The foundation is to be able to view files, edit them, and search them. For the minimalist, that's enough.

On top of that, you can add isolated, independent building blocks to add features to your note-taking:

- If you're taking class notes, [[Audio recorder]] and LaTeX math might be useful;
- If you're taking work notes, [[Slides]] and [[Backlinks]] may come in handy;
- If you're a researcher, [[Graph view]] and [[Word count]] might be essential to your toolkit.

We don't expect plugins to be the silver bullet to solve all the problems, but it does get us closer than a monolith solution, without all the features that you don't need cluttering the interface.

We support [[CSS snippets]], [[Themes]], and [[Community plugins]], which enable even more interface customization and support less common use cases.

## Follow our development

Curious how we continue to make Obsidian the best and most refined tool for thought-processing? Check out our [roadmap](https://obsidian.md/roadmap/) to see what we're working on.

Our Twitter handle is [@obsdmd](https://twitter.com/obsdmd), feel free to follow. We mostly tweet about product updates.

Obsidian offers users who create a [https://obsidian.md/account](https://obsidian.md/account "https://obsidian.md/account") the option to enable 2-factor authentication (2FA).

## Enable 2FA

Log into your Obsidian account from your web browser at [https://obsidian.md/account](https://obsidian.md/account "https://obsidian.md/account")

- Under the **Account** section, locate the item `2-factor authentication` and select the **Enable** button. 
- A popup window will appear to prompt you to connect an authenticator app.

> [!hint]- Popular authentication applications
> - [Authy](https://authy.com "https://authy.com")
> - [Google Authenticator](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2 "https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2")
> - [Microsoft Authenticator](https://www.microsoft.com/en-us/security/mobile-authenticator-app "https://www.microsoft.com/en-us/security/mobile-authenticator-app")
> - [iCloud Keychain](https://support.apple.com/en-gb/guide/iphone/ipha6173c19f/ios "https://support.apple.com/en-gb/guide/iphone/ipha6173c19f/ios")

- Once connected, your authenticator app will provide you a six digit code. Enter that code below the **QR code/setup key**. 
- Finally, enter your current password.
- Select **Complete set up**.
- The popup window will be replaced with a confirmation window. 

Your 2FA is now set up.

> [!warning]- QR code/setup key backups
> If you decide to keep a backup of your **QR code** or **Setup key**, we strongly recommend keeping it in a password encrypted system.

## Disable 2FA

- Under the **Account** section, locate the item `2-factor authentication` and select the **Disable** button. 
- Enter your Obsidian Password
- Enter the current six digit code from your authentication app.
- Select **Disable 2FA**
- You will be brought back to the Account management screen

The `2-factor authentication` section will once again show an **Enable** button.

## FAQ

> [!question]- Q1. I have enabled 2FA. Will I be logged out of my current Obsidian devices?
> No. 
> 
> Enabling 2FA does not log you out everywhere for your convenience. If you need to, you can manually do that from your account page, and subsequently login again on each of your devices.

> [!question]- Q2. I enabled, then disabled 2FA. I would like to set it up again. Can I use the original QR code or setup key?
> No. 
> 
> You will be provided a new **QR code** and new **Setup key** every time you initiate a new setup of 2FA.

> [!question]- Q3. I have enabled 2FA. I have yet to be asked for it after several log-out/log-in attempts. Is this working?
> Your browser cache may be allowing you to appear as if you are making changes to the page (such as logging in or out) when in actuality you are accessing the stored data. Try using a private browsing window to log-in to confirm 2FA is working.
> 
> If you continue to experience this behavior, please [submit a bug report](https://forum.obsidian.md/c/bug-reports/7).

Get early access to upcoming releases by enabling _early access versions_. Early access versions are only available to users with a [[Catalyst license]].

> Early access versions are beta releases. They include new features but may be less stable. Don't enable early access versions if you prefer a more reliable experience.
> 
> Be aware that community plugin and theme developers receive early access versions at the same time as everyone else. Be patient with developers who need to make updates to support new features.

## Enable early access versions for desktop

To receive early access versions as soon as they're available, follow these steps:

3. Under **App**, enable **Receive early access versions**.

## Install early access versions on mobile devices

To find instructions on how to install early access versions on your mobile device, follow these steps:

1. Join the [Obsidian Discord server](https://discord.gg/veuWUTm).
2. [[Catalyst license#Get your Discord badge|Get your Discord badge]] to access insider channels.
3. Open Discord.
4. In the `#insider-mobile-release` channel, open **Pinned Messages**.
   - On desktop, select the pushpin icon in the upper-right corner.
   - On mobile, swipe left and select **Pins**.
5. Under **Pinned Messages**, select the installation link for your device:
   - If you're using iOS, open the TestFlight link on your iPhone or iPad.
   - If you're using Android, download and install the APK file.

## Report issues and other feedback

If you discover an issue in an early access version, consider reporting it to the Obsidian team. Before you report an issue, search the [forum](https://forum.obsidian.md/) or Discord to see if someone has already reported it.

To report an issue, use one of the following channels:

- On Discord, report the issue in the respective `#insider-release` channel.
- In the forum, create a new topic under [Bug reports](https://forum.obsidian.md/c/bug-reports/7).

When you report an issue, include the build version and the OS you're running it on. You can find the build version under **Settings → About → App → Current version**.

## Switch back to public versions on desktop

To switch back to using public versions (not early access) on desktop:

1. Disable early access versions.
   1. Open **Settings**.
   2. In the sidebar, select **General**.
   3. Under **App**, disable **Receive early access versions**.
2. Close Obsidian.
3. Delete the `obsidian-VERSION.asar` file, where `VERSION` is the Obsidian version.
   - Windows: `%APPDATA%\obsidian\obsidian-VERSION.asar`
   - Mac: `~/Library/Application Support/obsidian/obsidian-VERSION.asar`
   - Linux: `~/.config/obsidian/obsidian-VERSION.asar`
4. Restart Obsidian.

## Switch back to public versions on mobile

To switch back to using public versions (not early access) on mobile:

1. Back up your vault data
2. Uninstall Obsidian
3. Reinstall Obsidian either from the Play Store or Apple App store
4. Restore your vault data from your backups
5. Open Obsidian

Obsidian’s official website is at https://obsidian.md

There you can:

- [Download](https://obsidian.md/download) the latest installer if your installer version is old.
- Register an account, and access your [account dashboard](https://obsidian.md/account), if you want to purchase [[Catalyst license]], [[Commercial license]], [[Introduction to Obsidian Sync|Obsidian Sync]], or [[Introduction to Obsidian Publish|Obsidian Publish]].

## Encryption

For your safety, [[Introduction to Obsidian Sync|Obsidian Sync]] encrypts your [[Local and remote vaults|remote vault]] and all communication with Obsidian's servers. Before anyone can access your remote vault, they first need to decrypt it with an _encryption password_.

When you create a new remote vault, you have two options:

- **End-to-end encryption:** Obsidian encrypts the vault on your device with a custom encryption key before it's sent to Obsidian's servers. This guarantees that no one—not even the Obsidian team—can access your notes.
- **Managed encryption:** If you don't want to have to remember another password, you can let Obsidian manage the encryption password for you. While we store your encryption password on our servers, we only use it to offer a more convenient way to manage your vaults.

If you forget or lose your custom encryption password, your data remains encrypted and unusable forever. We're not able to recover your password, or any encrypted data for you.

Your choice only affects your remote vault. Obsidian doesn't encrypt your local vault.
### What does end-to-end encryption mean?

End-to-end encryption means that the data is encrypted from the moment it leaves your device, and can only be decrypted using your encryption key once it's back on one of your devices.

We can't read your data. Neither can any potential eavesdroppers, such as your internet service provider.

In the rare case of a complete server breach, your data remains encrypted—no one can decrypt your files without knowing your password.

['Security/privacy for Obsidian Sync', 'Access control for Obsidian Sync']

### What encryption do you use?

For data security, we implement industry-standard encryption protocols. Specifically, we use [AES-256](https://www.nist.gov/publications/advanced-encryption-standard-aes-0), the strongest encryption standard, widely employed in contexts such as online banking. The encryption process involves the following technical details:

- **Key derivation function:** [scrypt](https://en.wikipedia.org/wiki/Scrypt) with salt
- **Encryption algorithm:** AES-256 using [Galois/Counter Mode (GCM)](https://en.wikipedia.org/wiki/Galois/Counter_Mode)

### Can I verify that my data is end-to-end encrypted?

Yes. See our guide, [how to verify Obsidian Sync's end-to-end encryption](https://obsidian.md/blog/verify-obsidian-sync-encryption/). This guide provide step-by-step instructions for you to trustlessly verify the end-to-end encryption of your data when it is sent and received via Sync servers.

### Has Obsidian completed a third-party security audit?

Yes. Obsidian has been independently audited. Visit our [Security page](https://obsidian.md/security) to view audit reports. Regular audits by third-party security firms ensure that Obsidian code and procedures meet the highest security standards.

### What happens if I forget my encryption password?

If you ever lose or forget the encryption password, you won't be able to connect additional vaults to your remote vault. Since the encryption password isn't saved anywhere, it's forever lost.

Your data, however, are usually safely stored locally on each of your devices.

To continue using Obsidian Sync, we suggest doing a full re-setup to be able to add new devices to your Sync system:

1. Make a full vault backup on your primary device, just in case something goes wrong. This can be as simple as making a copy of the vault folder, or creating a zip file from the vault.
2. Disconnect the remote vault in each of your devices. This can be done by going to **Settings → Sync → Pick remote vault → Disconnect**.
3. Create a new remote vault on your primary device from the same Settings page. Optionally, you can delete the previous remote vault since you don't have the password for it anyway. (You may have to delete the previous remote vault if you are at the vault limit)
4. Wait for your primary device to sync. Watch the sync indicator at the bottom right of the screen until it displays a green checkmark.
5. Connect each of your device to the same newly created remote vault. When connecting, you will be shown a warning about vault merging, this is expected and you can proceed. Wait for each device to fully sync before moving onto the next. This reduces the chances of issues.
6. Now all your devices should be connected to the new remote vault.

## Hosting
### Where do you host the servers for Obsidian Sync?

Our data centers, powered by [DigitalOcean](https://www.digitalocean.com), provide geo-regional remote vault hosting options in the following locations:

> [!info] Sync geo-regions
> **Automatic**: Your data center is chosen based off your IP location.
> 
> **Asia**: Singapore
> **Europe**: Frankfurt, Germany
> **North America**: San Francisco, USA 
> **Oceania**: Sydney, Australia
^sync-geo-regions

### I have sync-x as my server. Where is it hosted?

The list below corresponds the Sync servers to their respective data centers. 

**San Francisco**
- `sync-01` to `sync-12`
- `sync-14` to `sync-15`

**Frankfurt**
- `sync-13`
- `sync-16`

**Singapore**
- `sync-17`

**Sydney**
- `sync-18`
## Network and access

### Managing access to Obsidian Sync on your network

To regulate access to Obsidian Sync on your network, you need to manage the following domains:

`sync-xx.obsidian.md`

The `xx` in this case represents a number ranging from `1 - 100`.

> [!tip] If your firewall system supports it, we recommend whitelisting `sync-*.obsidian.md` to account for the continuous growth in subdomain numbers.

[[Introduction to Obsidian Sync|Obsidian Sync]] is a service for syncing your notes across devices. While it offers the ability to [[Version history|restore notes]], it is **not** designed to back up your vault.

To back up your vault we recommend using a dedicated one-way backup tool that pushes data from your device to a backup location, and doesn't rewrite the data on your local device.

## Using a third-party service to back up your vault

> [!danger] Though we recommend that you regularly back up your vault, be aware that **using a third-party syncing service together with Obsidian Sync may result in data corruption or data loss**.

If you set up the same third-party service on multiple devices, such as your phone, you risk having the service competing with Obsidian Sync whenever you make changes to your vault. This can lead to conflicts, duplicated files, or corrupted files.

To back up your vault using a third-party service, configure the service so that backups are only made from your primary device. For example, if you do most of your writing on your laptop, that's where you should configure your backups. 

In the vault switcher, your vault now has a vault icon instead of a cloud, to indicate it's no longer synced to iCloud Drive. 

> [!warning] Files must be available offline
> Some cloud storage services such as OneDrive and Dropbox allow you to only download files when you use them and later remove them locally to free up space. These features are sometimes called "Files on-demand" or "Online-only files".
> 
> Since the files are no longer available locally, they will appear deleted to Obsidian Sync, and will be removed from your remote vault.
>
> To use Obsidian Sync together with OneDrive, Dropbox, or other similar services,  disable on-demand downloads. Configure the third-party service settings to always keep files on the device.

## Remove your vault from a third-party sync service

If you're using Obsidian Sync and realize that you've set up your vault in a folder synced by a third-party service, you can use the following steps to move the vault to a safer location.

### Desktop

#### Option 1: Move your vault using the vault switcher

1. In the bottom-left corner, select **Open another vault** ( ![[obsidian-vault-switcher.svg#icon]] ).
2. Next to the vault you want to move, select **More options** ( ![[lucide-more-horizontal.svg#icon]] ). 
3. Choose a new location for the vault on your file system.

#### Option 2: Move your vault manually
  
1. Make backups of your vault. Copy your vault folder another location that you won't touch throughout the rest of this operation.
2. Quit Obsidian.  
3. Cut and paste (or move using drag and drop) your vault folder from the old location to your newly-selected vault location Don't put it in a folder that is being synced by another service.
4. Make sure your backup folder contains your vault.  
5. Relaunch Obsidian.  
6. At the bottom left, select **Open another vault** ( ![[obsidian-vault-switcher.svg#icon]] ).
7. Select **Open folder as vault**.
8. Navigate to your vault's new location and choose your vault folder.  
9. Check and make sure the vault looks the same. You might have to re-enable community plugins under **Settings → Community Plugins → Turn restricted mode off**.)  
10. Set up Obsidian Sync again.

### Mobile

On Android, the majority of distributions will install directly to the filesystem, and the steps to relocate the vault are identical to those outlined in [[#Option 1 Move your vault using the vault switcher|move your vault using the vault switcher]].

#### iOS

1. Make a backup of your vault.
2. On your device, create a new vault and disable **Save in iCloud Drive**.
3. Force quit the Obsidian app on all your devices to prevent Sync from performing any operations while you move the files.
4. On your iOS device, open the Files app.
5. Under **iCloud Drive → Obsidian**, long-press on the vault folder and then select **Move**.
6. Navigate to **On My iPhone → Obsidian**. Make sure that you can see the vault you created earlier.
7. Press **Copy**.
5. After the vault has been copied, navigate back to **iCloud Drive → Obsidian**. 
6. Delete your vault folder.

The next time you open Obsidian, your vault now has a vault icon instead of a cloud, indicating it's no longer on iCloud Drive.

With [[Introduction to Obsidian Sync|Obsidian Sync]] you can collaborate on a shared vault with your team.

All collaborators must have an active Sync subscription to access a shared vault. Joining a shared vault does not count towards your [[Sync limitations#How many remote vaults can I have?|vault limit]].

If the remote vault is [[Obsidian Sync/Security and privacy|end-to-end encrypted]], collaborators must enter the encryption password when they set up the vault.

## Manage users

### Add users

To invite a user to share a remote vault:

2. In the side menu, select **Sync**.
3. Next to **Remote vault**, select **Manage**.
4. Next to the remote vault you want to share, select **Manage sharing** ( ![[lucide-users.svg#icon]] ).
5. In **Invite user**, enter the email of the user you want to invite.
6. Select **Add**.

### Remove users

4. Next to the user you want to remove access from, select **Remove user** ( ![[lucide-x.svg#icon]] ).

## Collaborate with your team

### Permissions

Fine-grained permissions are not supported yet. All collaborators receive the same permissions as the vault owner, with one exception: only the vault owner can invite collaborators.

### Live editing

Shared vaults allow teams to work together on a set of files, however Obsidian does not yet support collaborative live editing on the same file. You will not see the other user's cursor, and their edits will only appear once the changes are synced.

If multiple users are editing the same file at the same time, [[Troubleshoot Obsidian Sync#Conflict resolution|changes will be merged]] during the syncing process. Changes can be viewed and restored using [[Version history]].

![[version-history-collaboration.png]]

docs/obsidian-help/Obsidian Sync/Collaborate on a shared vault.md

['Share remote vaults', 'Collaboration', 'Teams', 'Collaborating', 'Obsidian Sync/Share remote vaults']

### Limitations

Be aware that Obsidian Sync has [[Sync limitations|Limitations]] that may affect your team:

- The maximum number of collaborators on a shared vault is 10 users.
- The maximum file size for attachments is 200 MB.

In this guide, you'll create a local vault on another device to sync with your remote vault. This keeps the local vaults on all your devices in sync.

> [!tip] Obsidian URIs
> If you want Obsidian URIs to work across devices, make sure to give your local vaults the same name on all devices.

You need to have [[set up Obsidian Sync]] on at least one device and have created a remote vault on Obsidian Sync.

## Sync a remote vault on a fresh installation

If this is the first time you open Obsidian on the device, follow these steps:

1. Open Obsidian.
2. Select **Sign in** next to **Open vault from Obsidian Sync**.
3. In **Email**, enter your email.
4. In **Password**, enter your password.
5. Select **Sign in**.
6. Select **Connect** for the vault you want to set up.
7. Enter a local name for the vault, or leave to use the same name as the remote vault.
8. Select **Browse** and select the folder on your device where you want to sync the vault.
9. Select **Create**.
10. Select **Start syncing** to sync your local vault with the remote vault.

## Sync an existing local vault

This section explains how to sync an existing local vault with a remote vault.

![[Set up Obsidian Sync#Log in with your Obsidian account]]

![[Set up Obsidian Sync#Enable Obsidian Sync]]

### Connect to a remote vault

1. Open **Settings**.
2. In the sidebar, select **Sync**.
3. Next to **Pick remote vault**, click **Choose**.
4. Click **Connect** next to the remote vault you want to connect to. If the vault on your device already contains some notes (not recommended), you'll be warned that those notes will be merged before proceeding.
5. In **Encryption password**, enter the password for your vault, if you have one.

## Next steps

Obsidian Sync displays a green checkmark in the bottom-right corner when it has finished syncing the vaults.

If you don't want to sync the entire vault to your device, refer to [[Select files and settings to sync]].

docs/obsidian-help/Obsidian Sync/Set up Obsidian Sync on another device.md

Obsidian stores your notes in a _local_ vault on your computer. If you want to access your notes from other devices, you need to share your local vault with those devices.

[[Introduction to Obsidian Sync|Obsidian Sync]] makes this easier by letting you sync your local vault with a _remote_ vault that lives on Obsidian's servers.

You can connect multiple local vaults to your remote vault. When you make a change to a local vault, that change is saved to the connected remote vault. Your change is then synced across all the local vaults you've connected to that remote vault.

[Obsidian Sync](https://obsidian.md/sync) is an add-on service that allows you to store your notes on Obsidian's servers and sync them across your devices privately.

## How to use Obsidian Sync

- [[Set up Obsidian Sync]]
	- Get started with Obsidian Sync.
- [[Select files and settings to sync|Selective sync]]
	- Configure which files and settings to sync.
- [[Set up Obsidian Sync on another device|Set up a second device]]
	- Add another device to sync notes to.
- [[Version history]]
	- View or restore previous versions of a note.
- [[Collaborate on a shared vault|Collaboration]]
	- Add team members to a shared vault.
- [[Troubleshoot Obsidian Sync]]
	- Common syncing issues and solutions.
	- How Obsidian keeps your Sync data safe.
- [[Back up your vault]]
	- Back up your vault using third-party tools.

## Important

If you are using Obsidian Sync together with other cloud storage providers, such as Dropbox, Google Drive, or OneDrive, refer to [[Back up your vault]] to avoid sync conflicts.

See [[Sync limitations]] for frequently asked questions, and more details about Obsidian Sync.

docs/obsidian-help/Obsidian Sync/Introduction to Obsidian Sync.md

[[Introduction to Obsidian Sync|Obsidian Sync]] keeps a history of all the changes made to your notes. Sync regularly checks for new changes to your notes and creates a new version.

If you accidentally delete a note, or you want to go back to a previous version of your note, you can restore a note from the version history.

Older versions of your notes are retained for up to a year. 

## View version history of a note

1. In the **File explorer**, select the note you want to restore.
2. Click **View Sync version history**.

## View version history of a deleted or renamed note

2. In the sidebar, under **Plugin options**, select **Sync**.
3. Next to **Deleted files**, select **View**.
4. Click the note you want to view the version history for.

## Restore a previous version of a note

1. In the **File explorer**, right-click the note you want to restore.
3. In the list of versions to the left, select the version you want to restore.
4. Click **Restore this version**.

## Restore a deleted note

4. Choose the note you want to restore.
5. In the list of versions to the left, select the version you want to restore.
6. Select **Restore this version**.

The amount of data you can store using [[Introduction to Obsidian Sync|Obsidian Sync]] is defined by your subscription plan. Additional Sync storage can be purchased up to 100 GB via your [account dashboard](https://obsidian.md/account). See [[Sync limitations]] for more details.

There is a single account-wide storage limit for all notes across your vaults. [[Version history]] and [[attachments]] are also counted towards your account's storage limit.

When you reach your account's storage limit, the Sync plugin will cease syncing files, and you will be prompted to prune your remote vault(s).

## Identify and delete large files

To identify and delete large files from the vault:

1. Open **Settings → Sync**.
2. Select **View largest files** next to **Vault size over limit**. 
	1. If you don’t see **Vault size over limit**, it means ==you haven’t hit the size limit== yet.
3. Close the **View largest files** modal.
4. Delete some of the large files you no longer need.
5. Wait for Obsidian sync to finish the task. This can take a while.
6. Open **Settings → Sync**.
7. Select **Prune** next to **Vault size over limit**. This will remove the deleted files from the remote vault to free up space.

After the prune syncs to the server, Obsidian Sync should resume functioning.

## Create a new remote vault

You can **create a new remote vault** to exclude large files before syncing. The version history for your files will be reset if you create a new remote vault. Please be sure that you don’t need version history for older files before proceeding.

To sync to a new remote vault, follow these steps:

2. Select **Manage** next to **Remote vault**.
3. Choose **Create new vault** and follow the steps to create it. If you run out of vaults, you might need to disconnect from the current remote vault and delete it first.
4. Set up excluded files before you start syncing to the new remote vault (optional).
5. Start syncing to the new remote vault.

The new remote vault should be smaller than the previous vault, because of the absence of version history and excluded files.

This page lists some of the common questions related to questions and limitations for [[Introduction to Obsidian Sync|Obsidian Sync]].

## General

### What operating systems does Obsidian Sync support?

Obsidian Sync supports every platform that Obsidian can run on. Currently that means Windows, macOS, Linux, Android and iOS.

### How much storage do I have?

The storage limit depends on which Obsidian Sync plan you are subscribed to. The maximum storage amount is 100 GB. This storage limit includes [[Version history|version history]]. You can view **Storage usage** in the Obsidian app by going to **Settings → Sync**.

### How many remote vaults can I have?

Each account with Obsidian Sync can have up to 10 remote vaults.

### How large can each remote vault be?

You can allocate your storage any way you want across all your vaults. 

### How large can each file be?

The maximum file size is 200 MB per file.

### What type of data will sync?

By default your Obsidian notes, images, and your [[Configuration folder]] will sync. 

You can add additional syncing options of PDF's, audio files, video files, and other files when you [[select files and settings to sync]].

### Is my data being synced in the background?

No, files are only synced when Obsidian is running.

### What's the maximum number of people I can share a remote vault with?

You can [[Collaborate on a shared vault|share a remote vault]] with up to 10 people.

## Data retention
 
These are commonly asked questions on Obsidian's data retention. For more in depth answers, see [[Obsidian Sync/Security and privacy|Security and privacy]].

### How long do you keep the version history?

Older [[Version history|versions]] of Markdown files are stored for one year, and then deleted. Older versions of attachments are stored for two weeks.

### How long do you keep my data after my subscription expires?

We keep data in your remote vaults, including version history, for one month after your subscription expires. Any local vaults on your devices are unaffected.

As long as you renew within one month, there should be no impact on your usage. If you renew after a month, when your remote vaults have been removed, you can [[Set up Obsidian Sync|create a new remote vault re-connect your local vault]].

### Do you keep my data if I refund my subscription service?

No. The data is deleted immediately.

This page lists common issues that you might encounter, and how to address them.

![[Sync your notes across devices#^sync-files-on-demand]]

## Conflict resolution

A conflict happens when you make changes to the same file on two or more devices between syncs. For example, you might have changed a file on your computer, and before that change is uploaded, you also change the same file on your phone.

Conflicts usually happen more frequently if you work offline, since there are more changes and a longer period of time between syncs and thus more potential conflicts.

When Sync downloads a new version of a file, and finds that there are conflicts with the local version, the changes are merged with Google's [diff-match-patch](https://github.com/google/diff-match-patch) algorithm.

> [!help] To find when conflicts have happened, you can search for "Merging conflicted file" in **Settings → Sync → Sync activity → View**.

## Obsidian Sync deleted a note I just created on two devices

Generally, Obsidian Sync tries to [[#Conflict resolution|resolve conflicts]] between devices by merging the content of the conflicting notes. Unfortunately, merging conflicting notes can cause issues for users who *automatically generate* or *alter notes* on startup, for example using [[Daily notes]].

If a note was created locally on a device less than a couple of minutes before Sync downloads a remote version of that note, then Sync keeps the remote version without attempting to merge the two. You can still recover the local version using [[File recovery]].

## What does "Vault limit exceeded" mean?

Your account exceeds the [[Sync limitations#How large can each remote vault be|maximum size of 50 GB]]. See [[Storage limits]].

Since attachments and version history contributes to the total size of your vault, your vault can exceed the maximum size even if the actual size of your vault is less than the limit.

To identify and purge large files from the vault:

2. Explore the options under **Vault size over limit** for how you can reduce the size of your vault.

## What does "Vault not found" mean?

`{"res":"err","msg":"Vault not found."}`

This error may occur in the following scenarios:

1. The vault has been deleted from another device for any reason.
2. The sync subscription was inactive for over 30 days, leading to the removal of the remote vault.
3. The subscription was canceled or refunded, resulting in the purging of the remote vault.

In each case, it is necessary to disconnect from the remote vault and establish a new connection, ensuring the data on your device is retained.

In this guide, you'll enable [[Introduction to Obsidian Sync|Obsidian Sync]] for your vault.

> [!hint] Remote vaults and local vaults
> In this guide, you'll create a new [[Local and remote vaults|remote vault]] and connect it to an existing local vault. You don't need to create a new local vault to use Obsidian Sync.

- An active Obsidian Sync subscription. If you don't have one, subscribe from your [account page](https://obsidian.md/account).

## Log in with your Obsidian account

6. Select **Login**.
## Enable Obsidian Sync

3. Enable **Sync**.

2. In the sidebar, select **Sync**.
3. Next to **Remote vault**, select **Choose**.
4. Click **Create new vault**.
5. In **Vault name**, enter the name of the remote vault.
6. In **Region**, choose your server [[#Regional sync servers|region]] for your remote vault. 
7. In **Encryption password**, choose a password for your vault. This creates an end-to-end encrypted vault. The vault password is separate from your Obsidian account and can be different for each of your vaults. For more information, refer to [[Security and privacy]].
8. Click **Create**.

### Regional sync servers

As of [Obsidian release 1.5](https://obsidian.md/changelog/2023-11-20-desktop-v1.5.0/), users can now choose the hosting location for their remote vault. 

For users not yet on release 1.5 or a later version, the assignment of their remote vault location will be handled automatically. 

![[sync-regional-sync-servers.png#interface|300]]

After selecting a location, it's crucial to be aware that the data center **cannot** be changed afterward. If you wish to relocate your data, the process involves [[#Create a new remote vault|creating a new remote vault]] and specifying the desired hosting location during the setup.

![[Obsidian Sync/Security and privacy#^sync-geo-regions]]

## Connect to a remote vault

> [!danger] Is your current vault in an iCloud, OneDrive, Dropbox, or other syncing folder? Please [[Back up your vault|read this guide]] before proceeding.

1. Next to your newly created vault, select **Connect**.
2. In **Encryption password**, enter the password you configured for the vault if you opted into [[Obsidian Sync/Security and privacy#What does end-to-end encryption mean?|end-to-end encryption]].
3. Select **Unlock vault**.
4. It is highly recommended that you <u>do not</u> start syncing yet. Instead, proceed to [[Select files and settings to sync#Initially adjusting your Sync settings|syncing your vault settings for the first time]].
	1. If you wish to start syncing right away, select **Start Syncing**.

> [!note] Sync settings and other file types
> By default, Sync only syncs notes and images. For information how to sync other file types, refer to [[Select files and settings to sync#Select file types to sync|Select file types to sync]].
>
> If you want to sync vault configuration, such as settings for [[Core plugins]], [[Hotkeys]], or [[Community plugins]], learn how to [[Select files and settings to sync#Sync vault configuration|Sync vault configuration]].

Any files or settings that have been synced to your [[Local and remote vaults|remote vault]] count towards your [[Sync limitations#How large can each remote vault be|storage space]]. By default, [[Introduction to Obsidian Sync|Obsidian Sync]] ignores larger files such as audio, video, and PDFs.

**Synced files and exclusions**:
Synced files remain in your remote vault even if you exclude them later on. If possible, configure the files and settings you want to sync before you start syncing your vault.

**Sync does not sync .hidden folders:**
`.hidden` folders will not sync, with the exception of the [[configuration folder]], as these are considered folders hidden from the filesystem.

Common examples include `.vscode`, `.git`, and `.idea`.

==**Sync does not sync Sync's settings**==:
This allows users to configure Sync differently on each device according to their needs. This means, however, that you must configure custom Sync settings on each device.

> [!tip] Sync settings and application restarts
> Obsidian **only** applies vault settings during start-up. If you change a setting on one device, you **need to restart** Obsidian on your other devices for the new changes to take effect. 
> 
> For example, if you change the path of your daily notes in the [[Daily Notes]] plugin, you need to restart Obsidian on your other devices to use the new path.

docs/obsidian-help/Obsidian Sync/Select files and settings to sync.md

## Initially adjusting your Sync settings

> [!help] This set of instructions is intended for users who wish to modify their [[Set up Obsidian Sync on another device|sync settings on an additional device]] or a new vault after [[Set up Obsidian Sync#Connect to a remote vault|establishing a connection to a remote vault]].

1. If you haven't already, close (x) or dismiss the pop-up window prompting you to **Exclude Folders** and **Start Syncing**.
2. On your primary device, navigate to **Settings** → **Sync**.
3. Under **Vault configuration sync**, activate the settings you want to synchronize.
    1. If you make changes to any settings, restart Obsidian completely.
4. After restarting Obsidian, if any settings were modified, return to **Settings** → **Sync**.
5. Choose **Resume**.
6. The synchronization process will initiate, involving uploading, downloading, or merging your files, depending on whether the remote vault contains existing files or not.

## Syncing your vault settings

> [!help] These instructions are designed for users with existing multi-device sync setups who wish to modify these settings across their devices.

**Primary device**
1. Access **Settings** → **Sync**.
2. Activate the desired settings under **Vault configuration sync**.
3. Restart Obsidian
4. Allow time for the settings to synchronize with your remote vault.

**Secondary device(s)**
1. Navigate to **Settings** → **Sync**.
2. Enable the desired settings under **Vault configuration sync**.
3. Wait for the changes to be downloaded from your remote vault.
4. Restart the application to ensure that your synchronized settings take effect.

## Select file types to sync

2. Under **Selective sync**, enable the file types you want to sync.

## Exclude folder from being synced

By default, Obsidian syncs all files and folders in your vault. If you don't want Obsidian to sync a certain folder, you can exclude it.

2. Under **Selective sync**, next to **Excluded folders**, click **Manage**.
3. Click the checkbox to the left of folder you want to exclude.
4. Click **Done**.

## Create a settings profile

Obsidian Sync can sync multiple [[Configuration folder|configuration folders]] to the same remote vault. You can use this to create different profiles, for example one for mobile devices and another for your laptop.

To set your settings folder:

2. In **Override config folder**, type the name of your profile, starting with a period (`.`). For example, `.obsidian-mobile`.
3. Relaunch Obsidian to have the changes take effect.

Learn how to modify aspects of the Obsidian appearance without needing to [Build a theme](https://docs.obsidian.md/Themes/App+themes/Build+a+theme).

CSS is a language to describe how to present a HTML document. By adding CSS snippets, you can redefine parts of the Obsidian user interface, such as the size and color of headings. Obsidian includes [CSS variables](https://docs.obsidian.md/Reference/CSS+variables/CSS+variables) that you can use to easily customize parts of the interface.

Obsidian looks for CSS snippets inside the vault configuration folder.

To add a CSS snippet, follow these steps:

2. Under **Appearance → CSS snippets**, select **Open snippets folder** (folder icon).
3. In the snippets folder, create a CSS file that contains your snippet.
4. In Obsidian, under **Appearance → CSS snippets**, select **Reload snippets** (refresh icon) to see the snippet in the list.

Obsidian detects changes to CSS snippets automatically and applies them when you save your snippet. You don't need to restart Obsidian for changes to take effect.

> [!tip] Example: Change text color
> For example, create a file called `snippet.css` with the following content to change the text color to red:
>
>
>
> ```css
> body {
>   --text-normal: red;
> }
> ```

- If you're new to CSS, refer to [Learn to style HTML using CSS](https://developer.mozilla.org/en-US/docs/Learn/CSS) by Mozilla.
- If you want more tips on styling Obsidian, refer to [About styling](https://docs.obsidian.md/Reference/CSS+variables/About+styling).

Learn how to extend Obsidian with plugins built by the community. Use plugins to adapt Obsidian to fit your specific needs, such as support for additional file formats or integrating with a third-party service.

> Community plugins run third-party code on your behalf that could potentially do harm. To learn more about what the Obsidian team does to prevent harmful plugins, refer to [[Plugin security]].

## Browse community plugins

2. Select **Turn on community plugins**. For more information, refer to [[Plugin security#Restricted mode]].
3. Select **Browse** to list all available community plugins.

Use the text box to filter plugins based on their name, author, and description.

You can also browse available plugins in your browser, by heading to [obsidian.md/plugins](https://obsidian.md/plugins).

## Install a community plugin

To install a community plugin, you must first turn off [[#Restricted mode]].

2. In the side menu, select **Community plugins**.
3. Select **Browse** to explore available community plugins.
4. Select the plugin you want to install.
5. Select **Install**.

To use an installed plugin, you need to enable it.

## Enable a community plugin

Either select **Enable** directly after installing it, or enable it from the list of Community plugins under **Settings → Community plugins → Installed plugins**.

## Update plugins

For security purposes, community plugins don't update automatically. You can either update all plugins at once, or update individual plugins.

To update all your plugins:

2. Under **Community plugins → Current plugins**, select **Check for updates**.
3. If updates are available, select **Update all**.

To update an individual plugin:

3. Under **Installed plugins**, select **Update** next to the plugin you want to update.

## Uninstall a community plugin

3. Under **Installed plugins**, select **Uninstall** (cross icon).
4. Select **Uninstall** again to confirm.

Ready to build your own community plugin? Learn how to [Build a plugin](https://docs.obsidian.md/Plugins/Getting+started/Build+a+plugin).

The Obsidian team takes security seriously. This page explains the risks involved when installing community plugins, and what the Obsidian team does to address them.

> [!tip]
> If you're working with sensitive data and wish to install a community plugin, we recommend that you perform an independent security audit before using it.

## Restricted mode

By default, Obsidian runs in Restricted Mode to prevent third-party code execution. Only disable Restricted mode if you trust the authors of the plugins that you install.

To turn off Restricted mode:

3. Select **Turn on community plugins**.

To turn on Restricted mode:

3. Next to **Restricted mode**, select **Turn on**.

Installed plugins remain in your vault even if you turn on Restricted mode, but are ignored by Obsidian.

## Plugin capabilities

Due to technical reasons, Obsidian is unable to reliably restrict plugins to specific permissions or access levels. As a result, consider the following examples of what community plugins can do:

- Community plugins can access files on your computer.
- Community plugins can connect to internet.
- Community plugins can install additional programs.

## Plugin review process

Community plugins undergo an initial review when they're submitted to the plugin store. All plugins must adhere to [Obsidian Developer Policies](https://docs.obsidian.md/Developer+policies).

The Obsidian team is small and unable to manually review every new release of community plugins. Instead, we rely on the help of the community to identify and report issues with plugins.

- If you find any security flaws with a community plugin, create an issue on the plugin repository on GitHub.
- If you suspect that a community plugin is malicious, report it to [[Help and support#Contact Obsidian support|Obsidian support]], or by sending a DM to our moderators.

Learn how to change the look and feel of Obsidian using themes built by the community.

## Browse themes

## Install a new theme

2. Under **Appearance → Themes**, select **Manage**.
3. Select the theme you want to use, and then select **Install and use**.

Obsidian installs the theme and immediately applies it. To revert back to the default theme, select **Stop using this theme**.

## Update themes

Themes don't update automatically. You can either update all themes at once, or update individual themes.

To update all your themes:

2. Under **Appearance → Current community themes**, select **Check for updates**.

To update an individual theme:

3. Select the theme you want to update, and then select **Check for updates**.
4. If an update is available, select **Update**.

## Uninstall an existing theme

3. Select the theme you want to use, and then select **Uninstall**.

Ready to build your own theme? Learn how to [Build a theme](https://docs.obsidian.md/Themes/App+themes/Build+a+theme) or create [[CSS snippets]].

Obsidian URI is a custom URI protocol supported by Obsidian that lets you trigger various actions, such as opening a note or creating a note.

It is commonly used on macOS and mobile apps for automation and cross-app workflows.

Obsidian URIs are typically in this format:

```
obsidian://action?param1=value&param2=value
```

The `action` parameter is the action that you would like to perform.

> [!warning] Encoding
> Ensure that your values are properly URI encoded. For example, forward slash characters `/` must be encoded as `%2F` and space characters must be encoded as `%20`.
> 
 This is especially important because an improperly encoded "reserved" character may break the interpretation of the URI. [See here for details](https://en.wikipedia.org/wiki/Percent-encoding).

## Register Obsidian URI

On Windows and macOS, running the app once should be sufficient to register the Obsidian URI protocol on your computer.

On Linux, it is a much more involved process:

1. Ensure you create a `obsidian.desktop` file. [See here for details](https://developer.gnome.org/documentation/guidelines/maintainer/integrating.html#desktop-files).
2. Ensure that your desktop file specifies the `Exec` field as `Exec=executable %u`. The `%u` is used to pass the `obsidian://` URIs to the app.
3. If you're using the AppImage installer, you may have to unpack it using `Obsidian-x.y.z.AppImage --appimage-extract`. Then make sure the `Exec` directive points to the unpacked executable.

## Open notes

Opens an Obsidian vault, or open a file within that vault.

['Using Obsidian URI', 'Advanced topics/Using obsidian URI', 'Concepts/Obsidian URI']

- `obsidian://open?vault=my%20vault`
  This opens the vault `my vault`. If the vault is already open, focus on the window.

- `obsidian://open?vault=ef6ca3e3b524d22f`
  This opens the vault identified by the ID `ef6ca3e3b524d22f`.

- `obsidian://open?vault=my%20vault&file=my%20note`
  This opens the note `my note.md` in the vault `my vault`, assuming the file exists.

- `obsidian://open?path=%2Fhome%2Fuser%2Fmy%20vault%2Fpath%2Fto%2Fmy%20note`
  This will look for any vault that contains the path `/home/user/my vault/path/to/my note`. Then, the rest of the path is passed to the `file` parameter. For example, if a vault exists at `/home/user/my vault`, then this would be equivalent to `file` parameter set to `path/to/my note`.

> [!tip] Open a heading or block
> With proper URI encoding, you can navigate to a heading or block within a note. `Note%23Heading` would navigate to the heading called "Heading", whereas `Note%23%5EBlock` would navigate to the block called "Block".

### Parameters

- `vault` can be either the vault name or the vault ID[^1].
- `file` can be either a file name, or a path from the vault root to the specified file. If the file extension is `md`, the extension can be omitted.
- `path` an absolute file system path to a file.
  - Using this parameter will override both `vault` and `file`.
  - This will cause the app to search for the most specific vault which contains the specified file path.
  - Then the rest of the path replaces the `file` parameter.

## Open search

This Obsidian URI endpoint opens [[Search]] in the specified vault, and optionally perform a search query.

- `obsidian://search?vault=my%20vault`
  This opens the vault `my vault`, and opens [[Search]].

- `obsidian://search?vault=my%20vault&query=Obsidian`
  This opens the vault `my vault`, opens [[Search]], and performs a search for `Obsidian`.

- `vault` can be either the vault name, or the vault ID[^1]. Same as action `open`.
- `query` (optional) The search query to perform.

## Create note

This URI endpoint creates a new note in the vault, optionally with some content.

- `obsidian://new?vault=my%20vault&name=my%20note`
  This opens the vault `my vault`, and creates a new note called `my note`.
- `obsidian://new?vault=my%20vault&path=path%2Fto%2Fmy%20note`
  This opens the vault `my vault`, and creates a new note at `path/to/my note`.

- `name` the file name to be created. If this is specified, the file location will be chosen based on your "Default location for new notes" preferences.
- `file` a vault absolute path, including the name. Will override `name` if specified.
- `path` a globally absolute path. Works similar to the `path` option in the `open` action, which will override both `vault` and `file`.
- `content` (optional) the contents of the note.
- `silent` (optional) include this parameter if you don't want to open the new note.
- `append` (optional) include this parameter to append to an existing file if one exists.
- `overwrite` (optional) overwrite an existing file if one exists, but only if `append` isn't set.
- `x-success` (optional) see [[#x-callback-url]].

## Integrate with Hook

This Obsidian URI endpoint is to be used with [Hook](https://hookproductivity.com/). 

### Example

`obsidian://hook-get-address`

- `vault` (optional) can be either the vault name, or the vault ID[^1]. If not provided, the current or last focused vault will be used.
- `x-error` (optional) see [[#x-callback-url]].

If `x-success` is defined, this API will use it as the x-callback-url. Otherwise, it will copy a Markdown link of the current focused note to the clipboard, as an `obsidian://open` URL.

## Use x-callback-url parameters

Some endpoints will accept the x-callback-url parameters `x-success` and `x-error`. When it's provided, Obsidian will provide the following to the `x-success` callback:

- `name` the name of the file, without the file extension.
- `url` the `obsidian://` URI for this file.
- `file` (desktop only) the `file://` URL for this file.

For example, if Obsidian receives
`obsidian://.....x-success=myapp://x-callback-url`, the response would be `myapp://x-callback-url?name=...&url=obsidian%3A%2F%2Fopen...&file=file%3A%2F%2F...`

## Shorthand formats

In addition to the formats above, there are two more "shorthand" formats available to open vaults and files:

1. `obsidian://vault/my vault/my note` is equivalent to `obsidian://open?vault=my%20vault&file=my%20note`.
2. `obsidian:///absolute/path/to/my note` is equivalent to `obsidian://open?path=%2Fabsolute%2Fpath%2Fto%2Fmy%20note`.

---

[^1]: Vault ID is the random 16-character code assigned to the vault, for example `ef6ca3e3b524d22f`. This ID is unique per folder on your computer. The ID can be found by opening the vault switcher and clicking "Copy vault ID" in the context menu for the desired vault.

If you want to reference a file using different names, consider adding _aliases_ to the note. An alias is an alternative name for a note.

Use aliases for things like acronyms, nicknames, or to refer to a note in a different language.

## Add an alias to a note

To add an alias for a note, add `aliases` property in the note [[Properties]]. Aliases should always be formatted as a list in YAML.

```md
---
aliases:
  - Doggo
  - Woofer
  - Yapper
---

# Dog
```

## Link to a note using an alias

To link to a note using an alias:

1. Start typing the alias in an [[Internal links|internal link]]. Any alias shows up in the list of suggestions, with a curved arrow icon next to it.
2. Press `Enter` to select the alias.

Obsidian creates the link with the alias as its custom display text, for example `[[Artificial Intelligence|AI]]`.

> [!note]
> Rather than just using the alias as the link destination (`[[AI]]`), Obsidian uses the `[[Artificial Intelligence|AI]]` link format to ensure interoperability with other applications using the Wikilink format.

## Find unlinked mentions for an alias

By using [[Backlinks]], you can find unlinked mentions of aliases.

For example, after setting "AI" as an alias for "Artificial intelligence", you can see mentions of "AI" in other notes.

If you link an unlinked mention to an alias, Obsidian turns the mention into an [[Internal links|internal link]] with the alias as its display text.

Learn how you can embed other notes and media into your notes. By embedding files in your notes, you can reuse content across your vault.

To embed a file in your vault, add an exclamation mark (`!`) in front of an [[Internal links|Internal link]]. You can embed files in any of the [[Accepted file formats]].

## Embed a note in another note

To embed a note:

```md
![[Internal links]]
```

You can also embed links to [[Internal links#Link to a heading in a note|headings]] and [[Internal links#Link to a block in a note|blocks]].

```md
![[Internal links#^b15695]]
```

The text below is an example of an embedded block:

## Embed an image in a note

To embed an image:

```md
![[Engelbart.jpg]]
```

![[Engelbart.jpg#outline]]

```md
![[Engelbart.jpg|100x145]]
```

If you only specify the width, the image scales according to its original aspect ratio. For example, `![[Engelbart.jpg|100]]`.

![[Engelbart.jpg#outline|100]]

## Embed an audio file in a note

To embed an audio file:

```md
![[Excerpt from Mother of All Demos (1968).ogg]]
```

## Embed a PDF in a note

To embed a PDF:

```md
![[Document.pdf]]
```

You can also open a specific page in the PDF, by adding `#page=N` to the link destination, where `N` is the number of the page:

```md
![[Document.pdf#page=3]]
```

You can also specify the height in pixels for the embedded PDF viewer, by adding `#height=[number]` to the link. For example:

```md
![[Document.pdf#height=400]]
```

## Embed a list in a note

To embed a list from a different note, first add a [[Internal links#Link to a block in a note|block identifier]] to your list:

```md

- list item 1
- list item 2

^my-list-id
```

Then link to the list using the block identifier:

```md
![[My note#^my-list-id]]
```

['How to/Embed files', 'Linking notes and files/Embedding files']

## Embed search results 

![[Search#Embed search results in a note]]

Learn how to link to notes, attachments, and other files from your notes, using _internal links_. By linking notes, you can create a network of knowledge. ^b15695

Obsidian can automatically update internal links in your vault when you rename a file. If you want to be prompted instead, you can disable it under **Settings → Files & Links → Automatically update internal links**.

## Supported formats for internal links

Obsidian supports the following link formats:

The examples above are equivalent—they appear the same way in the editor, and links to the same note.

> [!note]
> When using the Markdown format, make sure to [URL encode](https://en.wikipedia.org/wiki/Percent-encoding) the link destination. For example, blank spaces become `%20`.

By default, due to its more compact format, Obsidian generates links using the Wikilink format. If interoperability is important to you, you can disable Wikilinks and use Markdown links instead.

To use the Markdown format:

2. Under **Files & Links**, disable **Use \[\[Wikilink\]\]**.

Even if you disable the Wikilink format, you can still autocomplete links by typing two square brackets `[[`. When you select one of the suggested files, Obsidian instead generates a Markdown link.

## Link to a file

To create a link while in Editing view, use either of the following ways:

- Type `[[` in the editor and then select the file you want to create a link to.
- Select text in the editor and then type `[[`.
- Open the [[Command palette]] and then select **Add internal link**.

While you can link to any of the [[Accepted file formats]], links to file formats other than Markdown needs to include a file extension, such as `[[Figure 1.png]]`.

## Link to a heading in a note

You can link to specific headings in notes, also known as _anchor links_.

To link to a heading, add a hash (`#`) at the end of the link destination, followed by the heading text.

For example, `[[Three laws of motion#Second law]]`.

You can add multiple hash symbols for each subheading.

For example, `[[My note#Heading 1#Heading 2]]`.

> [!tip]- Heading links across the vault
> You can search for headers to link to from across your vault using the `[[##header]]` syntax. 
> 
> ![[internal-links-header.png#interface]]

## Link to a block in a note

A block is a unit of text in your note, for example a paragraph, block quote, or even a list item.

You can link to a block by adding `#^` at the end of your link destination followed by a unique block identifier, for example, `[[2023-01-01#^37066d]]`.

Fortunately, you don't need to know the identifier. When you type the caret (`^`), you can select the block from a list of suggestions to insert the right identifier.

You can also create human-readable block identifiers by adding a blank space followed by the identifier, for example `^quote-of-the-day`, at the end of a block:

```md
"You do not rise to the level of your goals. You fall to the level of your systems." by James Clear ^quote-of-the-day
```

Now you can instead link to the block by typing `[[2023-01-01#^quote-of-the-day]]`.

Block identifiers can only consist of Latin letters, numbers, and dashes.

> [!tip]- Block links across the vault
> You can search for blocks to link to from across your vault using the `[[^^block]]` syntax. However, more items qualify as blocks in comparison to [[#Link to a heading in a note|heading links]] so this list will be much longer in comparison.
> 
> ![[link-block-heading.png#interface]]

> [!warning] Interoperability
> Block references are specific to Obsidian and not part of the standard Markdown format. Links containing block references won't work outside of Obsidian.

## Change the link display text

By default, Obsidian will show the link text, or the [[Aliases|alias]] if you opt to [[Aliases#Link to a note using an alias|link to an alias]]. You have the option to modify the text used for displaying a link. This feature comes in handy when you prefer to incorporate a link into a sentence without explicitly using the file name.

**Wikilink format:**

You can use the vertical bar (`|`) to change the text used to display a link.

For example, `[[Internal links|custom display text]]` appears as [[Internal links|custom display text]].

**Markdown format:**

Enter the display text between the square brackets (`[]`).

For example, `[custom display text](Internal%20links.md)` appears as [custom display text](Internal%20links.md).

## Preview a linked file

> [!note]
> To preview linked files, you first need to enable [[Page preview]].

To preview a linked file, press `Ctrl` (or `Cmd` on macOS) while hovering the cursor over the link. A preview of the file content appears next to the cursor.

### Color scheme

Obsidian comes with two color schemes, light and dark. By default, the color scheme is set to adapt to your operating system. You can change this by going to **Settings → Appearance**.

### Custom themes

You can change the appearance of Obsidian by using [[themes|custom themes]]. Browse hundreds of community-made themes by going to **Settings → Appearance**, then click **Manage** to view and install themes.

You can also tweak themes using [[CSS snippets]] and [build your own theme](https://docs.obsidian.md/Themes/App+themes/Build+a+theme) .

### Custom app icon

You can change the Obsidian desktop app icon. Try the icon editor featured on [our blog](https://obsidian.md/blog/new-obsidian-icon/) to customize the icon colors to your liking.

To change the Obsidian app icon, follow these steps:

2. Select **Appearance** on the left.
3. Scroll down to the **Advanced** section.
4. Under **Custom app icon** click **Choose** .
5. Pick your desired icon from your filesystem.  Accepted file formats are `.icns`, `.ico`, `.png`, and `.svg`.
6. Click **Relaunch**.
7. After Obsidian restarts, your new icon should appear in the taskbar on desktop and on your screen on mobile.

> [!tip] Custom app icon in the  Windows taskbar 
> For certain Windows operating systems, an extra step may be needed to adjust the custom app icon in the taskbar.
> 
> Follow these steps:
> - Right-click the Obsidian icon on your taskbar or desktop shortcut.
> - Right-click the name Obsidian (skip this step for the desktop icon).
> - Choose **Properties**.
> - Click **Change Icon**.
> - Locate the icon on your file system.
> - Click **OK**.
> 
> Afterward, you have the option to either restart `explorer.exe` within the task manager or restart your computer to apply the changes you made.

### Translucency

You can make the Obsidian window translucent by enabling this option in the settings **Appearance** tab. Currently this option is only available for Windows and macOS.

There is a known issue on Windows. Dragging the app window may be slow when translucency is enabled.

## Desktop

In the Obsidian desktop app the workspace includes:

- [[Tabs#Organize your tabs and windows|Tab groups]], in the central content area which can be split vertically or horizontally
	- [[Tabs]]
- [[Sidebar|Sidebars]] which can be collapsed on the left and right side
    - [[Sidebar#Tab groups|Sidebar tab groups]] which can be split vertically
        - [[Sidebar#Tabs|Sidebar tabs]]
- [[Ribbon]] running vertically on the left side of the app
- [[Status bar]] in the bottom right corner

## Mobile

In the Obsidian mobile app the workspace includes:

- [[Tabs]]
- [[Use the mobile app|Editor toolbar]] which appears above the keyboard when editing
- [[Sidebar|Sidebars]] can be opened using left and right swipe gestures
- [[Use the mobile app#Navigation bar|Navigation bar]] at the bottom of the screen
	- [[Ribbon|Ribbon menu]] contains customizable actions

The Obsidian interface has been translated to various languages by [[Credits#Translators|our amazing volunteer translators]]. You can change the interface language either in **Settings** ( ![[lucide-settings.svg#icon]] ) → **General** or when you create a new vault.

Is your language missing from the list? Are you seeing untranslated snippets of text? [[Translations|Help us translate Obsidian into your language]].

There are many ways to drag and drop elements in Obsidian. This includes tabs, files, folders, and content.

### Drag tabs

- You can [[Tabs#Arrange tabs|arrange tabs]] and split tab groups in the main content area and in [[Sidebar|sidebars]].

### Drag sources

- You can drag a file, or multiple files from the [[file explorer]].
- You can drag a file from a [[search]] result.
- You can drag a file from [[backlinks]] or unlinked references.
- You can drag a file from a link inside the note, in preview mode.

### Drop destinations

- You can drop a file on a tab header to open the file there. Hold `Alt` (or `Shift` on macOS) to drop anywhere in the tab.
- You can drop a file on a folder in the [[file explorer]] to move the file there.
- You can drop a file into an editor to insert it as a link. The generated link also follows your preferences, such as relative paths, or using Markdown links.
- You can drop a file on the [[Bookmarks]] tab to bookmark it.

### Dragging from outside Obsidian

- You can drag any HTML content from the browser into Obsidian to automatically convert them into Markdown
- You can drag and drop any files from your native file explorer to have Obsidian import (make a copy of) those files in your vault's attachment folder and insert them as internal links. Hold `Ctrl` on Windows/Linux or `Option` on macOS to create `file:///` absolute links to those files instead of importing a copy.

### Dropping files outside Obsidian

- This creates an `obsidian://` URL in the external application for the Obsidian note that you dragged.

Tabs in Obsidian work much like tabs in other apps, such as web browsers.

You can open as many tabs as you want in Obsidian. You can also arrange tabs to create custom layouts that persist until the next time you open the app.

## Open a new tab

At the top of the application window, next to the last tab on the right, select **New tab** (plus icon). Or, use a keyboard shortcut:

- **Windows and Linux:** `Ctrl+t`
- **macOS:** `Cmd+t`

## Open a link

Select a link in Obsidian to open it in the active tab.

To open a link in a new tab, press `Ctrl` (or `Cmd` on macOS) and select the link.

The following are all the modifier keys you can use to open links in various ways:

|Action|MacOS|Windows/Linux|
|---|---|---|
|**Navigate**|_None_|_None_|
|**New Tab**|`⌘` (+ `Shift` in Source Mode)|`Ctrl` (+ `Shift` in Source Mode)|
|**New Tab Group**|`⌘` `⌥`| `Ctrl` `Alt`|
|**New Window**|`⌘` `⌥` `Shift`|`Ctrl` `Alt` `Shift`|

## Organize your tabs and windows

Every tab belongs to a _tab group_. You can drag and drop tabs to rearrange them within a tab group, move them to a different tab group, or create a new tab group. On desktop, you can drag tabs out of their window to open them in a separate [[Pop-out windows|pop-out window]].

Tabs in sidebars only show the icon. Hover over the icon to show a tooltip with the tab title.

### Arrange tabs

To change the order of your tabs, drag the tab along the tabs in the tab group.

As you drag a tab, _drop zones_—areas onto which you can move the tab—become highlighted. The drop zone determines where to insert the tab. Some tabs can only be in of the sidebars.

### Split a tab group

Right-click a tab and select **Split right** or **Split down** to create a new tab group with that tab.

You can also split a tab group by dragging a tab to the bottom of another tab.

['Stacked tabs', 'Linked pane', 'Pane layout', 'User interface/Use tabs in Obsidian']

### Resize a tab group

To resize a tab group, hover the cursor over an edge of the tab group. The edge becomes highlighted when it can be dragged to resize.

You can resize sidebars similarly to make more space for the tab groups in the middle.

### Move tab to a new window

- Select and drag the tab outside of the application window to open it in a new window.

- Open the Command Palette, and select **Move current tab to new window**.

### Move a tab to a different window

To move a tab to another existing window, drag the tab to the window you want to move it to.

### Pin a tab

To pin a tab, right-click the tab and select **Pin**. Links in a pinned tab always open in a separate tab.

To unpin a pinned tab, right-click the tab and select **Unpin**.

## Switch to a different tab

Select a tab to switch to it. Or, use a keyboard shortcut:

| Switch To                 | MacOS            | Windows/Linux        |
|---------------------------|------------------|----------------------|
| **Next tab**              | `⌃`+`⇥`         | `Ctrl`+`Tab`         |
| **Previous tab**          | `⌃`+`⇧`+`⇥`    | `Ctrl`+`Shift`+`Tab` |
| **First tab on the left** | `⌘`+`1`          | `Ctrl`+`1`           |
| **2nd to 8th tab**        | `⌘`+`2`..`8`     | `Ctrl`+`2`..`8`      |
| **Last tab on the right** | `⌘`+`9`          | `Ctrl`+`9`           |
| **Recently closed tab**   | `⌘`+`⇧`+`t`     | `Ctrl`+`Shift`+`t`   |

## Stack tab groups

You can stack tabs to slide them over other tabs in the same tab group.

To stack notes, select the down arrow at the upper right corner of the tab group, and then select **Stack notes**.

![tab-stacks](https://user-images.githubusercontent.com/693981/188205363-0f24b2a5-3706-4a8c-b38b-7a66baa68ce6.gif)

> [!note] Matushak mode
> Tab stacks are based on [Andy Matushak's sliding notes](https://notes.andymatuschak.org/).

## Linked views

_Linked views_ are tabs that reference a different tab. When the content of the referenced tab changes, the linked view changes as well.

For note tabs, you can use the following plugins as linked views:

- [[Graph view]] (local)

To open a linked view for a note tab:

1. Select **More options** (three dots icon) in the upper right corner of the note.
2. Under **Open linked view**, select the linked view you want to open.

## Save layouts

You can save and restore window layouts using the [[Workspaces]] plugin.

On desktop Obsidian has two sidebars on both left and right. The left sidebar includes the [[Ribbon]].

On mobile, Obsidian sidebars are [[#Open hidden sidebars|collapsed by default]]. They can be opened by using left and right swipe gestures from the edge of the screen.

## Open hidden sidebars

If a sidebar is collapsed, you can open it by clicking the left expand ( ![[obsidian-side-bar-left.svg#icon]] ) or right expand ( ![[obsidian-side-bar-right.svg#icon]] ) to reveal it.

## Tabs

By default, plugins will only create new tabs instead of new [[#Tab groups]].

You can switch between tabs by clicking on the icon. A tooltip will also appear to help you identify tabs.

In each pane, you can only see one tab at any given moment. Some actions will automatically bring a tab into view, for example when you click on a tag.

### Close tabs

Some tabs can be closed via the right click menu, but some can't. If you don’t want to see a tab that can't be closed, consider disabling the relevant plugin or collapsing the sidebar by clicking on the Arrow icon.

### Rearrange tabs

You can drag and drop the tab icons to rearrange them within a group of tabs.

## Tab groups

You can have multiple tab groups in the sidebar.

### Create tab groups

To get a new tab group, drag the icon of a tab above or below a current tab group. The highlighted area will indicate where the new tab group will be created.

### Close tab groups

To close a tab group, you can [[#Close tabs|close all tabs in it]], or drag all tabs in it by their icons and drop them into existing tab groups.

When only the tab area of a tab group is highlighted, the tab being dragged will be dropped into that tab group to merge with other tabs in that group.

The status bar shows small bits of information in the bottom right corner of the window. That includes helpful information about the current file, the current vault, or the current status like time and date.

![[status-bar-desktop.png#interface]]

Status items are added both by [[Core plugins|core plugins]] and [[community plugins]]. Some items are interactive but some are purely informational. 

For example, the [[word count]] plugin adds the word and character count that’s not clickable, and the [[Introduction to Obsidian Sync|Sync plugin]] adds an icon that both shows the sync status as well as shows the sync log upon being clicked. 

The desktop version of the status bar pictured below features information about the [[Backlinks|backlinks]] present, the current [[Edit and preview Markdown#Editor views|editor view]], and the current word and character count from the word count plugin.

Learn how to open files in separate _pop-out_ windows.

Each pop-out window is associated with a vault window. If you close a vault window, all its pop-out windows close as well.

You can only move files between windows that are associated with the same vault.

## Open a file in a new window

In the [[File explorer]], right-click a note, and then select **Open in new window**.

In the [[Command palette]], select **Open current tab in new window**.

**Tab:**

Right-click a tab, and then select **Move to new window**. Or, in the upper-right corner of the editor, select **More options** (three dots icon), and then select **Move to new window**.

> [!tip]
> You can also right-click a link in the editor, and then select **Open in new window**.

## Move a file to a different window

In the [[File explorer]], drag the file to a tab group in the destination window.

In the [[Command palette]], select **Move current tab in new window**.

**Tab:**

Drag the tab to a tab group in the destination window.

Obsidian allows you to customize hotkeys, also known as keyboard shortcuts.

Default hotkeys are only defined for the most commonly used [[Command palette|commands]]. If you frequently use a command, you can define a hotkey for it. See also [[Editing shortcuts]].

### Viewing hotkeys

The fastest way to see the hotkey set for a command is to find the command in [[Command palette]]. If there's a hotkey listed for that command, it's set.

### Setting hotkeys

To add a hotkey, remove a hotkey, or restore hotkeys to default, go to Settings => Hotkeys. You can also filter the list, as the list of commands is quite long.

**Note for non-US users:** Even if the hotkey you type doesn't match on screen with what you would expect to see (given your keyboard layout), it will work fine following the actual buttons you pressed (as long as you don’t change layout).

The hotkey that appears on screen is the one that you would have to perform if you were using a US keyboard.

['How to/Use hotkeys', 'Customization/Custom hotkeys', 'Keyboard shortcuts']

The ribbon functions as a space for common commands within Obsidian. 

On desktop, it's located in the left sidebar and remains visible even when the left sidebar is closed. 

On mobile, you can access the ribbon by tapping the **Menu option** ( ![[lucide-menu.svg#icon]] ) at the bottom right corner of the app when you're not editing a note.

## Actions

Each action is represented by an icon in the ribbon. Hovering over these icons will display a tooltip, while clicking or tapping them will activate the associated action.

The top set of icons consists of actions added by various plugins, including both [[Core plugins|core plugins]] and [[Community plugins]].

The bottom three icons in the ribbon correspond to essential Obsidian system actions:

1. Open another vault ( ![[obsidian-vault-switcher.svg#icon]] ).
2. Access **help** ( ![[lucide-help-circle.svg#icon]] ).
3. Open **settings** ( ![[lucide-settings.svg#icon]] ).

In the mobile version, the ribbon can serve as a quick access action, which can be configured by following the instructions in the [[#Mobile|mobile section]] on customizing the ribbon.

## Customizing the ribbon

Your customized ribbon layout is remembered across sessions and synchronizes with other devices and the mobile app when app settings, specifically the `workspace.json` file, are synchronized.

On the desktop version, you can customize the ribbon as follows:

- Rearrange the order of ribbon actions by simply dragging and dropping the icons.
- To hide specific actions, right-click on an empty space within the ribbon and uncheck the actions you want to hide.

### Mobile

In the mobile version of Obsidian, you can perform quick access actions, rearrange items, and customize the visibility status of the ribbon menu. To access these customizations, follow these steps:

1. Open Obsidian's **settings** ( ![[lucide-cog.svg#icon]] ).
2. Navigate to the **appearance** section.
3. Scroll down to the **advanced** options.
4. Click the **Manage** button under the **Ribbon menu** item.

#### Quick access

By default, the quick access option is set to "Open ribbon menu" on a *short press*. If you choose another option as your quick access:

- The selected option will be triggered with a *short press*.
- The ribbon menu access will change to a *long press*.

> [!info] Quick access options depend on the Obsidian settings and core plugins you have enabled.

#### Rearrange and visibility

To change the order of items in the ribbon menu, press and hold the **drag-and-drop** ( ![[lucide-menu.svg#icon]] ) button and move the selected item up or down.

You can show or hide items in the ribbon menu using the red **remove** ( ![[lucide-minus-circle.svg#icon]] ) or green **add** ( ![[lucide-plus-circle.svg#icon]] ) buttons to toggle their visibility.
 
 ![[ribbon-rearrange-visibility.jpeg#interface]]

# Obsidian Developer Docs

Welcome to the official Obsidian Developer Documentation, where you can learn how to build plugins and themes for [Obsidian](https://obsidian.md/). For tips on how to use Obsidian, visit [the official Help site](https://help.obsidian.md/).

## Plugins

Build plugins to extend the existing functionality in Obsidian using TypeScript.

- [[Build a plugin|Build your first plugin]]
- [[Submit your plugin]]

## Themes

Design beautiful themes and snippets for Obsidian using CSS.

- [[Build a theme|Build your first theme]]
- [[Submit your theme]]
- [[CSS variables]]

## Join the developer community

If you get stuck, or if you're looking for feedback, [join the community](https://obsidian.md/community).

- `#plugin-dev` and `#theme-dev` channels on Discord.
- [Developers & API](https://forum.obsidian.md/c/developers-api/14) and [Share & showcase](https://forum.obsidian.md/c/share-showcase/9) on the forum.

## Contributing

If you see any errors or room for improvement on this site, or want to submit a PR, feel free to open an issue on [our GitHub repository](https://github.com/obsidianmd/obsidian-developer-docs).
Additional details are available on our [readme](https://github.com/obsidianmd/obsidian-developer-docs#readme).

Thank you in advance for contributing!

Our goal for community plugins and themes is to make it easy for users to safely modify and expand the capabilities of Obsidian, while prioritizing private and offline usage of the app.

All community plugins and themes added to the Obsidian directory must respect the following policies. Every plugin and theme is individually vetted before being included in the directory. Plugins and themes that don't follow these policies will be removed from the directory.

## Policies

### Not allowed

Plugins and themes must not:

- Obfuscate code to hide its purpose.
- Insert dynamic ads that are loaded over the internet.
- Insert static ads outside a plugin’s own interface.
- Include client-side telemetry.
- Themes may not load assets from the network. To bundle an asset, see [[Embed fonts and images in your theme|this guide]].

### Disclosures

The following are only allowed if clearly indicated in your README:

- Payment is required for full access.
- An account is required for full access.
- Network use. Clearly explain which remote services are used and why they're needed.
- Accessing files outside of Obsidian vaults. Clearly explain why this is needed.
- Static ads such as banners and pop-up messages within the plugin's own interface.
- Server-side telemetry. Link to a privacy policy that explains how the data is handled must be included.
- Close sourced code. This will be handled on a case by case basis.

### Copyright and licensing

All community plugins and themes must follow these requirements:

- Include a [LICENSE file](https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions/adding-a-license-to-a-repository) and clearly indicate the license of your plugin or theme.
- Comply with the original licenses of any code your plugin or theme makes use of, including attribution in the README if required.
- Respect Obsidian's trademark policy. Don't use the "Obsidian" trademark in a way that could confuse users into thinking your plugin or theme is a first-party creation.

## Reporting violations

If you encounter a plugin or theme that violates the policies above, please let the developer know by opening a GitHub issue in their repository. Kindly check existing issues to see if it’s already reported.

If the developer doesn’t response after 7 days, [contact the Obsidian team](https://help.obsidian.md/Help+and+support#Report+a+security+issue). For serious violations, you can contact our team immediately.

## Removing plugins and themes

In case of a policy violation, we may attempt to contact the developer and provide a reasonable timeframe for them to resolve the problem.

If the problem isn't resolved by then, we'll remove plugins or themes from our directory.

We may immediately remove a plugin or theme if:

- The plugin or theme appears to be malicious.
- The developer is uncooperative.
- This is a repeated violation.

In addition, we may also remove plugins or themes that have become unmaintained or severely broken.

Each collection of notes in Obsidian is known as a Vault. A Vault consists of a folder, and any sub-folders within it.

While your plugin can access the file system like any other Node.js application, the [[Reference/TypeScript API/Vault/Vault|Vault]] module aims to make it easier to work with files and folders within a Vault.

The following example recursively prints the paths of all Markdown files in a Vault:

```ts
const files = this.app.vault.getMarkdownFiles()

for (let i = 0; i < files.length; i++) {
  console.log(files[i].path);
}
```

> [!tip]
> If you want to list _all_ files, and not just Markdown documents, use [[getFiles|getFiles()]] instead.

## Read files

There are two methods for reading the content of a file: [[Reference/TypeScript API/Vault/read|read()]] and [[cachedRead|cachedRead()]].

- If you only want to display the content to the user, then use `cachedRead()` to avoid reading the file from disk multiple times.
- If you want to read the content, change it, and then write it back to disk, then use `read()` to avoid potentially overwriting the file with a stale copy.

> [!info]
> The only difference between `cachedRead()` and `read()` is when the file was modified outside of Obsidian just before the plugin reads it. As soon as the file system notifies Obsidian that the file has changed from the outside, `cachedRead()` behaves _exactly_ like `read()`. Similarly, if you save the file within Obsidian, the read cache is flushed as well.

The following example reads the content of all Markdown files in the Vault and returns the average document size:

```ts
import { Notice, Plugin } from "obsidian";

export default class ExamplePlugin extends Plugin {
  async onload() {
    this.addRibbonIcon("info", "Calculate average file length", async () => {
      const fileLength = await this.averageFileLength();
      new Notice(`The average file length is ${fileLength} characters.`);
    });
  }

  async averageFileLength(): Promise<number> {
    const { vault } = this.app;

    const fileContents: string[] = await Promise.all(
      vault.getMarkdownFiles().map((file) => vault.cachedRead(file))
    );

    let totalLength = 0;
    fileContents.forEach((content) => {
      totalLength += content.length;
    });

    return totalLength / fileContents.length;
  }
}
```

## Modify files

To write text content to an existing file, use [[modify|Vault.modify()]].

```ts
function writeCurrentDate(vault: Vault, file: TFile): Promise<void> {
  return vault.modify(file, `Today is ${new Intl.DateTimeFormat().format(new Date())}.`);
}
```

If you want to modify a file based on its current content, use [[process|Vault.process()]] instead. The second argument is a callback that provides the current file content and returns the modified content.

```ts
// emojify replaces all occurrences of :) with 🙂.
function emojify(vault: Vault, file: TFile): Promise<string> {
  return vault.process(file, (data) => {
    return data.replace(":)", "🙂");
  })
}
```

`Vault.process()` is an abstraction on top of [[Reference/TypeScript API/Vault/read|Vault.read()]] and [[modify|Vault.modify()]] that guarantees that the file doesn't change between reading the current content and writing the updated content. Always prefer `Vault.process()` over `Vault.read()`/`Vault.modify()` to avoid unintentional loss of data.

### Asynchronous modifications

[[process|Vault.process()]] only supports synchronous modifications. If you need to modify a file asynchronously:

1. Read the file using [[cachedRead|Vault.cachedRead()]].
2. Perform the async operations.
3. Update the file using [[Reference/TypeScript API/Vault/process|Vault.process()]].

Remember to check that the `data` in the `process()` callback is the same as the data returned by `cachedRead()`. If they aren't the same, that means that the file was changed by a different process, and you may want to ask the user for confirmation, or try again.

## Delete files

There are two methods to delete a file, [[delete|delete()]], and [[trash|trash()]]. Which one you should use depends on if you want to allow the user to change their mind.

- `delete()` removes the file without a trace.
- `trash()` moves the file to the trash bin.

When you use `trash()`, you have the option to move the file to the system's trash bin, or to a local  `.trash` folder at the root of the user's Vault.

## Is it a file or folder?

Some operations return or accept a [[TAbstractFile|TAbstractFile]] object, which can be either a file or a folder. Always check the concrete type of a `TAbstractFile` before you use it.

```ts
const folderOrFile = this.app.vault.getAbstractFileByPath("folderOrFile");

if (folderOrFile instanceof TFile) {
  console.log("It's a file!");
} else if (folderOrFile instanceof TFolder) {
  console.log("It's a folder!");
}
```

Many of the interfaces in the Obsidian lets you subscribe to events throughout the application, for example when the user makes changes to a file.

Any registered event handlers need to be detached whenever the plugin unloads. The safest way to make sure this happens is to use the [[registerEvent|registerEvent()]] method.

```ts
import { Plugin } from "obsidian";

    this.registerEvent(this.app.vault.on('create', () => {
      console.log('a new file has entered the arena')
    }));
  }
}
```

## Timing events

If you want to repeatedly call a function with a fixed delay, use the [`window.setInterval()`](https://developer.mozilla.org/en-US/docs/Web/API/setInterval) function with the [[registerInterval|registerInterval()]] method.

The following example displays the current time in the status bar, updated every second:

```ts
import { moment, Plugin } from "obsidian";

  statusBar: HTMLElement;

    this.statusBar = this.addStatusBarItem();

    this.updateStatusBar();

    this.registerInterval(
      window.setInterval(() => this.updateStatusBar(), 1000)
    );
  }

  updateStatusBar() {
    this.statusBar.setText(moment().format("H:mm:ss"));
  }
}
```

> [!tip] Date and time
> [Moment](https://momentjs.com/) is a popular JavaScript library for working with dates and time. Obsidian uses Moment internally, so you don't need to install it yourself. You can import it from the Obsidian API instead:
>
> ```ts
> import { moment } from "obsidian";
> ```

Every new version of Obsidian may introduce new capabilities for plugins. Unfortunately, using a recently introduced plugin capability in your plugin may break installations for users that haven't yet updated to the latest version of Obsidian. To avoid this, `versions.json` lets you control the plugin version based on the version of the user's Obsidian app.

`versions.json` contains a JSON object, where the key is the plugin version, and the value is the corresponding `minAppVersion`.

If a user attempts to install a plugin where the Obsidian app version is lower than the `minAppVersion` in [[Reference/Manifest|Manifest]], then Obsidian looks for a `versions.json` file at the root of the plugin repository.

In the following example, the user has Obsidian 1.1.0 installed, but the plugin `minAppVersion` is 1.2.0.

**manifest.json**:

```json
{
  // ...

  "version": "1.0.0",
  "minAppVersion": "1.2.0"
}
```

If the user runs version 1.1.0 of the Obsidian app, Obsidian then consults the `versions.json` to determine whether a fallback is available.

**versions.json**:

```json
{
  "0.1.0": "1.0.0",
  "0.12.0": "1.1.0",
}
```

In this case, the most recent plugin version for 1.1.0 is 0.12.0.

> You don't need to list every plugin relese in the `versions.json`. You only need to update `versions.json` if you change the `minAppVersion` for your plugin.

This page describes the schema for the manifest, `manifest.json`.

## Properties

The following properties are available for both plugins and themes.

| Property        | Type                                | Required | Description                                                                     |
| --------------- | ----------------------------------- | -------- | ------------------------------------------------------------------------------- |
| `author`        | `string`                            | **Yes**  | The author's name.                                                              |
| `minAppVersion` | `string`                            | **Yes**  | The minimum required Obsidian version.                                          |
| `name`          | `string`                            | **Yes**  | The display name.                                                               |
| `version`       | `string`                            | **Yes**  | The version, using [Semantic Versioning](https://semver.org/).                  |
| `authorUrl`     | `string`                            | No       | A URL to the author's website.                                                  |
| `fundingUrl`    | `string` or [`object`](#fundingurl) | No       | A URL or multiple URLs to where the users can support your project financially. |

## Plugin-specific properties

The following properties are only available to plugins.

| Property        | Type      | Required | Description                                       |
| --------------- | --------- | -------- | ------------------------------------------------- |
| `description`   | `string`  | **Yes**  | A description of your plugin.                     |
| `id`            | `string`  | **Yes**  | The ID of your plugin.                            |
| `isDesktopOnly` | `boolean` | **Yes**  | Whether your plugin uses NodeJS or Electron APIs. |

## fundingUrl

`fundingUrl` can either be a string with a single URL, or an object with multiple URLs.

**Single URL**:

```json
{
  "fundingUrl": "https://buymeacoffee.com"
}
```

**Multiple URLs**:

```json
{
  "fundingUrl": {
    "Buy Me a Coffee": "https://buymeacoffee.com",
    "GitHub Sponsor": "https://github.com/sponsors",
    "Patreon": "https://www.patreon.com/"
  }
}
```

In this guide, you'll configure your plugin to use [React](https://react.dev/). It assumes that you already have a plugin with a [[Views|custom view]] that you want to convert to use React.

While you don't need to use a separate framework to build a plugin, there are a few reasons why you'd want to use React:

- You have existing experience of React and want to use a familiar technology.
- You have existing React components that you want to reuse in your plugin.
- Your plugin requires complex state management or other features that can be cumbersome to implement with regular [[HTML elements]].

## Configure your plugin

1. Add React to your plugin dependencies:

   ```bash
   npm install react react-dom
   ```

2. Add type definitions for React:

   ```bash
   npm install --save-dev @types/react @types/react-dom
   ```

3. In `tsconfig.json`, enable JSX support on the `compilerOptions` object:

   ```ts
   {
     "compilerOptions": {
       "jsx": "preserve"
     }
   }
   ```

## Create a React component

Create a new file called `ReactView.tsx` in the plugin root directory, with the following content:

```tsx title="ReactView.tsx"
export const ReactView = () => {
  return <h4>Hello, React!</h4>;
};
```

docs/obsidian-developer/Plugins/Getting started/Use React in your plugin.md

## Mount the React component

To use the React component, it needs to be mounted on a [[HTML elements]]. The following example mounts the `ReactView` component on the `this.containerEl.children[1]` element:

```tsx
import { StrictMode } from "react";
import { ItemView, WorkspaceLeaf } from "obsidian";
import { Root, createRoot } from "react-dom/client";
import { ReactView } from "./ReactView";

const VIEW_TYPE_EXAMPLE = "example-view";

class ExampleView extends ItemView {
	root: Root | null = null;

	constructor(leaf: WorkspaceLeaf) {
		super(leaf);
	}

	getViewType() {
		return VIEW_TYPE_EXAMPLE;
	}

	getDisplayText() {
		return "Example view";
	}

	async onOpen() {
		this.root = createRoot(this.containerEl.children[1]);
		this.root.render(
			<StrictMode>
				<ReactView />,
			</StrictMode>,
		);
	}

	async onClose() {
		this.root?.unmount();
	}
}
```

For more information on `createRoot` and `unmount()`, refer to the documentation on [ReactDOM](https://react.dev/reference/react-dom/client/createRoot#root-render).

You can mount your React component on any `HTMLElement`, for example [[Plugins/User interface/Status bar|status bar items]]. Just make sure to clean up properly by calling `this.root.unmount()` when you're done.

## Create an App context

If you want to access the [[Reference/TypeScript API/App/App|App]] object from one of your React components, you need to pass it as a dependency. As your plugin grows, even though you're only using the `App` object in a few places, you start passing it through the whole component tree.

Another alternative is to create a React context for the app to make it globally available to all components inside your React view.

1. Use `createContext()` to create a new app context.

   ```tsx title="context.ts"
   import { createContext } from "react";
   import { App } from "obsidian";

   export const AppContext = createContext<App | undefined>(undefined);
   ```

2. Wrap the `ReactView` with a context provider and pass the app as the value.

   ```tsx title="view.tsx"
   this.root = createRoot(this.containerEl.children[1]);
   this.root.render(
     <AppContext.Provider value={this.app}>
       <ReactView />
     </AppContext.Provider>
   );
   ```

3. Create a custom hook to make it easier to use the context in your components.

   ```tsx title="hooks.ts"
   import { useContext } from "react";
   import { AppContext } from "./context";

   export const useApp = (): App | undefined => {
     return useContext(AppContext);
   };
   ```

4. Use the hook in any React component within `ReactView` to access the app.

   ```tsx title="ReactView.tsx"
   import { useApp } from "./hooks";

   export const ReactView = () => {
     const { vault } = useApp();

     return <h4>{vault.getName()}</h4>;
   };
   ```

For more information, refer to the React documentation for [Passing Data Deeply with Context](https://react.dev/learn/passing-data-deeply-with-context) and [Reusing Logic with Custom Hooks](https://react.dev/learn/reusing-logic-with-custom-hooks).

Plugins let you extend Obsidian with your own features to create a custom note-taking experience.

In this tutorial, you'll compile a sample plugin from source code and load it into Obsidian.

## What you'll learn

After you've completed this tutorial, you'll be able to:

- Configure an environment for developing Obsidian plugins.
- Compile a plugin from source code.
- Reload a plugin after making changes to it.

To complete this tutorial, you'll need:

- [Git](https://git-scm.com/) installed on your local machine.
- A local development environment for [Node.js](https://Node.js.org/en/about/).
- A code editor, such as [Visual Studio Code](https://code.visualstudio.com/).

## Before you start

When developing plugins, one mistake can lead to unintended changes to your vault. To prevent data loss, you should never develop plugins in your main vault. Always use a separate vault dedicated to plugin development.

[Create an empty vault](https://help.obsidian.md/Getting+started/Create+a+vault#Create+empty+vault).

docs/obsidian-developer/Plugins/Getting started/Build a plugin.md

## Step 1: Download the sample plugin

In this step, you'll download a sample plugin to the `plugins` directory in your vault's [`.obsidian` directory](https://help.obsidian.md/Advanced+topics/How+Obsidian+stores+data#Per+vault+data) so that Obsidian can find it.

The sample plugin you'll use in this tutorial is available in a [GitHub repository](https://github.com/obsidianmd/obsidian-sample-plugin).

1. Open a terminal window and change the project directory to the `plugins` directory.

   ```bash
   cd path/to/vault
   mkdir .obsidian/plugins
   cd .obsidian/plugins
   ```

2. Clone the sample plugin using Git.

   ```bash
   git clone https://github.com/obsidianmd/obsidian-sample-plugin.git
   ```

> [!tip] GitHub template repository
> The repository for the sample plugin is a GitHub template repository, which means you can create your own repository from the sample plugin. To learn how, refer to [Creating a repository from a template](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template#creating-a-repository-from-a-template).
>
> Remember to use the URL of your own repository when cloning the sample plugin.

## Step 2: Build the plugin

In this step, you'll compile the sample plugin so that Obsidian can load it.

1. Navigate to the plugin directory.

   ```bash
   cd obsidian-sample-plugin
   ```

2. Install dependencies.

   ```bash
   npm install
   ```

3. Compile the source code. The following command keeps running in the terminal and rebuilds the plugin when you modify the source code.

   ```bash
   npm run dev
   ```

Notice that the plugin directory now has a `main.js` file that contains a compiled version of the plugin.

## Step 3: Enable the plugin

To load a plugin in Obsidian, you first need to enable it.

1. In Obsidian, open **Settings**.
2. In the side menu, select **Community plugins**.
4. Under **Installed plugins**, enable the **Sample Plugin** by selecting the toggle button next to it.

You're now ready to use the plugin in Obsidian. Next, we'll make some changes to the plugin.

## Step 4: Update the plugin manifest

In this step, you'll rename the plugin by updating the plugin manifest, `manifest.json`. The manifest contains information about your plugin, such as its name and description.

1. Open `manifest.json` in your code editor.
2. Change `id` to a unique identifier, such as `"hello-world"`.
3. Change `name` to a human-friendly name, such as `"Hello world"`.
4. Restart Obsidian to load the new changes to the plugin manifest.

Go back to **Installed plugins** and notice that the name of the plugin has been updated to reflect the changes you made.

Remember to restart Obsidian whenever you make changes to `manifest.json`.

## Step 5: Update the source code

To let the user interact with your plugin, add a _ribbon icon_ that greets the user when they select it.

1. Open `main.ts` in your code editor.
2. Rename the plugin class from `MyPlugin` to `HelloWorldPlugin`.
3. Import `Notice` from the `obsidian` package.

   ```ts
   import { Notice, Plugin } from "obsidian";
   ```

4. In the `onload()` method, add the following code:

   ```ts
   this.addRibbonIcon('dice', 'Greet', () => {
     new Notice('Hello, world!');
   });
   ```

5. In the **Command palette**, select **Reload app without saving** to reload the plugin.

You can now see a dice icon in the ribbon on the left side of the Obsidian window. Select it to display a message in the upper-right corner.

Remember, you need to **reload your plugin after changing the source code**, either by disabling it then enabling it again in the community plugins panel, or using the command palette as detailed in part 5 of this step.  

> [!tip] Hot reloading
> Install the [Hot-Reload](https://github.com/pjeby/hot-reload) plugin to automatically reload your plugin while developing.

## Conclusion

In this tutorial, you've built your first Obsidian plugin using the TypeScript API. You've modified the plugin and reloaded it to reflect the changes inside Obsidian.

The [[Plugin|Plugin]] class defines the lifecycle of a plugin and exposes the operations available to all plugins:

```ts

    // Configure resources needed by the plugin.
  }
  async onunload() {
    // Release any resources configured by the plugin.
  }
}
```

## Plugin lifecycle

[[onload|onload()]] runs whenever the user starts using the plugin in Obsidian. This is where you'll configure most of the plugin's capabilities.

[[onunload|onunload()]] runs when the plugin is disabled. Any resources that your plugin is using must be released here to avoid affecting the performance of Obsidian after your plugin has been disabled.

To better understand when these methods are called, you can print a message to the console whenever the plugin loads and unloads. The console is a valuable tool that lets developers monitor the status of their code.

To view the console:

1. Toggle the Developer Tools by pressing Ctrl+Shift+I in Windows and Linux, or Cmd-Option-I on macOS.
2. Click on the Console tab in the Developer Tools window.

```ts

    console.log('loading plugin')
  }
    console.log('unloading plugin')
  }
}
```

docs/obsidian-developer/Plugins/Getting started/Anatomy of a plugin.md

This guide explains how to configure your plugin to use [Svelte](https://svelte.dev/), a light-weight alternative to traditional frameworks like React and Vue.

Svelte is built around a compiler that preprocesses your code and outputs vanilla JavaScript, which means it doesn't need to load any libraries at run time. This also means that it doesn't need a virtual DOM to track state changes, which allows your plugin to run with minimal additional overhead.

If you want to learn more about Svelte, and how to use it, refer to the [tutorial](https://svelte.dev/tutorial/basics) and the [documentation](https://svelte.dev/docs).

This guide assumes that you've finished [[Build a plugin]].

> [!tip] Visual Studio Code
> Svelte has an [official Visual Studio Code extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) that enables syntax highlighting and rich IntelliSense in Svelte components.

docs/obsidian-developer/Plugins/Getting started/Use Svelte in your plugin.md

To build a Svelte application, you need to install the dependencies and configure your plugin to compile code written using Svelte.

1. Add Svelte to your plugin dependencies:

   ```bash
   npm install --save-dev svelte svelte-preprocess @tsconfig/svelte esbuild-svelte
   ```

2. Extend the `tsconfig.json` to enable additional type checking for common Svelte issues. The `types` property is important for TypeScript to recognize `.svelte` files.

   ```json
   {
     "extends": "@tsconfig/svelte/tsconfig.json",
       "types": ["svelte", "node"],

       // ...
     }
   }
   ```

3. Remove the following line from your `tsconfig.json` as it conflicts with the Svelte configuration.

   ```json
   "inlineSourceMap": true,
   ```

4. In `esbuild.config.mjs`, add the following imports to the top of the file:

   ```js
   import esbuildSvelte from "esbuild-svelte";
   import sveltePreprocess from "svelte-preprocess";
   ```

5. Add Svelte to the list of plugins.

   ```js
    esbuild
    .build({
      plugins: [
        esbuildSvelte({
          compilerOptions: { css: true },
          preprocess: sveltePreprocess(),
        }),
      ],
      // ...
    })
    .catch(() => process.exit(1));
   ```

## Create a Svelte component

In the root directory of the plugin, create a new file called `Component.svelte`:

```tsx
<script lang="ts">
  export let variable: number;
</script>

<div class="number">
  <span>My number is {variable}!</span>
</div>

<style>
  .number {
    color: red;
  }
</style>
```

## Mount the Svelte component

To use the Svelte component, it needs to be mounted on an existing [[HTML elements|HTML element]]. For example, if you are mounting on a custom [[ItemView|ItemView]] in Obsidian:

```ts

import Component from "./Component.svelte";

export const VIEW_TYPE_EXAMPLE = "example-view";

export class ExampleView extends ItemView {
  component: Component;

  constructor(leaf: WorkspaceLeaf) {
    super(leaf);
  }

  getViewType() {
    return VIEW_TYPE_EXAMPLE;
  }

  getDisplayText() {
    return "Example view";
  }

  async onOpen() {
    this.component = new Component({
      target: this.contentEl,
      props: {
        variable: 1
      }
    });
  }

  async onClose() {
    this.component.$destroy();
  }
}
```

> [!info]
> Svelte requires at least TypeScript 4.5. If you see the following error when you build the plugin, you need to upgrade TypeScript to a more recent version.
>
> ```plain
> error TS5023: Unknown compiler option 'preserveValueImports'.
> ```
>
> To fix the error, run the following in your terminal:
>
> ```bash
> npm update typescript@~4.5.0
> ```

## Create a Svelte store

To create a store for your plugin and access it from within a generic Svelte component instead of passing the plugin as a prop, follow these steps:

1. Create a file called `store.ts`:

   ```jsx
   import { writable } from "svelte/store";
   import type ExamplePlugin from "./main";

   const plugin = writable<ExamplePlugin>();
   export default { plugin };
   ```

2. Configure the store:

   ```ts
   import { ItemView, WorkspaceLeaf } from "obsidian";
   import store from "./store";
   import Component from "./Component.svelte";

   const VIEW_TYPE_EXAMPLE = "example-view";

   class ExampleView extends ItemView {
     // ...

     async onOpen() {
       store.plugin.set(this.plugin);

       this.component = new Component({
         target: this.contentEl,
         props: {
           variable: 1
         }
       });
     }
   }
   ```

3. To use the store in your component:

   ```jsx
   <script lang="ts">
     import type MyPlugin from "./main";

     let plugin: MyPlugin;
     store.plugin.subscribe((p) => (plugin = p));
   </script>
   ```

Whenever you make a change to the plugin source code, the plugin needs to be reloaded. You can reload the plugin by quitting Obsidian and starting it again, but that gets tiring quickly.

## Reload plugin inside Obsidian

You can reload the plugin by re-enabling it in the list of installed plugins:

1. Open **Preferences**.
2. Click **Community plugins**.
3. Find your plugin under **Installed plugins**.
4. Toggle the switch off to disable the plugin.
5. Toggle the switch on to enable the plugin.

You're now running the updated version of your plugin.

## Reload plugin on file changes

The [Hot-Reload](https://github.com/pjeby/hot-reload) plugin reloads your plugin whenever the source code changes.

For more information, check out the [forum announcement](https://forum.obsidian.md/t/plugin-release-for-developers-hot-reload-the-plugin-s-youre-developing/12185).

docs/obsidian-developer/Plugins/Getting started/Development workflow.md

Learn how you can develop your plugin for mobile devices.

## Emulate mobile device on desktop

You can emulate Obsidian running a mobile device directly from the Developer Tools.

1. Open the **Developer Tools**.
2. Select the **Console** tab.
3. Enter the following and then press `Enter`.

   ```ts
   this.app.emulateMobile(true);
   ```

To disable mobile emulation, enter the following and press `Enter`:

```ts
this.app.emulateMobile(false);
```

> [!tip]
> To instead toggle mobile emulation back and forth, you can use the `this.app.isMobile` flag:
>
> ```ts
> this.app.emulateMobile(!this.app.isMobile);
> ```

## Inspecting the webview on the actual mobile device

### Android

You can inspect Obsidian running on an Android device if you enable USB Debugging in Developer settings of Android. Then go to a chromium based browser on your desktop/laptop and navigate to chrome://inspect/. If you did everything right, if you have your phone/tablet connected to your PC via USB and the browser open at that link you should see your device pop up and it will let you run the usual devtools from there on it.

### iOS

You can inspect Obsidian on an iOS device running 16.4 or later and a macOS based computer. Instructions on how to set it up can be found here: https://webkit.org/web-inspector/enabling-web-inspector/

## Platform-specific features

To detect the platform your plugin is running on, you can use `Platform`:

```ts
import { Platform } from "obsidian";

if (Platform.isIosApp) {
  // ...
}

if (Platform.isAndroidApp) {
  // ...
}
```

## Disable your plugin on mobile devices

If your plugin requires the Node.js or Electron API, you can prevent users from installing the plugin on mobile devices.

To only support the desktop app, set `isDesktopOnly` to `true` in the [[Manifest]].

This section lists common issues when developing for mobile devices.

docs/obsidian-developer/Plugins/Getting started/Mobile development.md

### Node and Electron APIs

The Node.js API and the Electron API aren't available on mobile devices. Any calls to these libraries result cause your plugin to crash.

### Lookbehind in regular expressions

Lookbehind in regular expressions is only supported on iOS 16.4 and above, and some iPhone and iPad users may still use earlier versions. To implement a fallback for iOS users, either refer to [[#Platform-specific features]], or use a JavaScript library to detect specific browser versions.

Refer to [Can I Use](https://caniuse.com/js-regexp-lookbehind) for more information and exact version statistics. Look for "Safari on iOS".

If you want to share your plugin with the Obsidian community, the best way is to submit it to the [official list of plugins](https://github.com/obsidianmd/obsidian-releases/blob/master/community-plugins.json). Once we've reviewed and published your plugin, users can install it directly from within Obsidian. It'll also be featured in the [plugin directory](https://obsidian.md/plugins) on the Obsidian website.

You only need to submit the initial version of your plugin. After your plugin has been published, users can download new releases from GitHub directly from within Obsidian.

To complete this guide, you'll need:

- A [GitHub](https://github.com/signup) account.

## Before you begin

Before you submit your plugin, make sure you have the following files in the root folder of your repository:

- A `README.md` that describes the purpose of the plugin, and how to use it.
- A `LICENSE` that determines how others are allowed to use the plugin and its source code. If you need help to [add a license](https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions/adding-a-license-to-a-repository) for your plugin, refer to [Choose a License](https://choosealicense.com/).
- A `manifest.json` that describes your plugin. For more information, refer to [[Manifest]].

## Step 1: Publish your plugin to GitHub

> [!note] Template repositories
> If you created your plugin from one of our template repositories, you may skip this step.

To review your plugin, we need to access to the source code on GitHub. If you're unfamiliar with GitHub, refer to the GitHub docs for how to [Create a new repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-new-repository).

## Step 2: Create a release

In this step, you'll prepare a release for your plugin that's ready to be submitted.

1. In `manifest.json`, update `version` to a new version that follows the [Semantic Versioning](https://semver.org/) specification, for example `1.0.0` for your initial release. You can only use numbers and periods (`.`).
2. [Create a GitHub release](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository#creating-a-release). The "Tag version" of the release must match the version in your `manifest.json`.
3. Enter a name for the release, and describe it in the description field. Obsidian doesn't use the release name for anything, so feel free to name it however you like.
4. Upload the following plugin assets to the release as binary attachments:

   - `main.js`
   - `manifest.json`
   - `styles.css` (optional)

## Step 3: Submit your plugin for review

In this step, you'll submit your plugin to the Obsidian team for review.

1. In [community-plugins.json](https://github.com/obsidianmd/obsidian-releases/edit/master/community-plugins.json), add a new entry at the end of the JSON array.

   ```json
   {
     "id": "doggo-dictation",
     "name": "Doggo Dictation",
     "author": "John Dolittle",
     "description": "Transcribes dog speech into notes.",
     "repo": "drdolittle/doggo-dictation"
   }

```

   - `id`, `name`, `author`, and `description` determines how your plugin appears to the user, and should match the corresponding properties in your [[Manifest]].
   - `id` is unique to your plugin. Search `community-plugins.json` to confirm that there's no existing plugin with the same id. The `id` can't contain `obsidian`.
   - `repo` is the path to your GitHub repository. For example, if your GitHub repo is located at https://github.com/your-username/your-repo-name, the path is `your-username/your-repo-name`.

   Remember to add a comma after the closing brace, `}`, of the previous entry.

2. Select **Commit changes...** in the upper-right corner.
3. Select **Propose changes**.
4. Select **Create pull request**.
5. Select **Preview**, and then select **Community Plugin**.
6. Click **Create pull request**.
7. In the name of the pull request, enter "Add [...] plugin", where [...] is the name of your plugin.
8. Fill in the details in the description for the pull request. For the checkboxes, insert an `x` between the brackets, `[x]`, to mark them as done.
9. Click **Create pull request** (for the last time 🤞).

You've now submitted your plugin to the Obsidian plugin directory. Sit back and wait for an initial validation by our friendly bot. It may take a few minutes before the results are ready.

- If you see a **Ready to review** label on your PR, your submission has passed the automatic validation.
- If you see a **Validation failed** label on your PR, you need to address all listed issues until the bot assigns a **Ready to review** label.

Once your submission is ready to review, you can sit back and wait for the Obsidian team to review it.

> [!question] How long does it take to review my plugin?
> The time it takes to review your submission depends on the current workload of the Obsidian team. The team is still small, so please be patient while you wait for your plugin to be reviewed. We're currently unable to give any estimates on when we'll be able to review your submission.

## Step 4: Address review comments

Once a reviewer has reviewed your plugin, they'll add a comment to your pull request with the result of the review. The reviewer may require that you update your plugin, or they can offer suggestions on how you can improve it.

Address any required changes and update the GitHub release with the new changes. Leave a comment on the PR to let us know you've addressed the feedback. Don't open a new PR.

We'll publish the plugin as soon we've verified that all required changes have been addressed.

> [!note]
> While only Obsidian team members can publish your plugin, other community members may also offer to review your submission in the meantime.

Once we've reviewed and published your plugin, it's time to announce it to the community:

- Announce in [Share & showcase](https://forum.obsidian.md/c/share-showcase/9) in the forums.
- Announce in the `#updates` channel on [Discord](https://discord.gg/veuWUTm). You need the [`developer` role](https://discord.com/channels/686053708261228577/702717892533157999/830492034807758859) to post in `#updates`.

Before you [[Submit your plugin|submit your plugin]], you may want to let users try it out first. While Obsidian doesn't officially support beta releases, we recommend that you use the [BRAT](https://github.com/TfTHacker/obsidian42-brat) plugin to distribute your plugin to beta testers before it's been published.

For more information, refer to the [BRAT](https://github.com/TfTHacker/obsidian42-brat/blob/main/README.md) documentation.

This page lists common review comments plugin authors get when submitting their plugin.

While the guidelines on this page are recommendations, depending on their severity, we may still require you to address any violations.

> [!important] Policies for plugin developers
> Make sure that you've read our [[Developer policies]] as well as the [[Submission requirements for plugins]].

## General

### Avoid using global app instance

Avoid using the global app object, `app` (or `window.app`). Instead, use the reference provided by your plugin instance, `this.app`.

The global app object is intended for debugging purposes and might be removed in the future.

## UI text

This section lists guidelines for formatting text in the user interface, such as settings, commands, and buttons.

The example below from **Settings → Appearance** demonstrates the guidelines for text in the user interface.

![[settings-headings.png]]

1. [[#Only use headings under settings if you have more than one section.|General settings are at the top and don't have a heading]].
2. [[#Avoid "settings" in settings headings|Section headings don't have "settings" in the heading text]].
3. [[#Use Sentence case in UI]].

For more information on writing and formatting text for Obsidian, refer to our [Style guide](https://help.obsidian.md/Contributing+to+Obsidian/Style+guide).

### Only use headings under settings if you have more than one section.

Avoid adding a top-level heading in the settings tab, such as "General", "Settings", or the name of your plugin.

If you have more than one section under settings, and one contains general settings, keep them at the top without adding a heading.

For example, look at the settings under **Settings → Appearance**:

### Avoid "settings" in settings headings

In the settings tab, you can add headings to organize settings. Avoid including the word "settings" to these headings. Since everything in under the settings tab is settings, repeating it for every heading becomes redundant.

- Prefer "Advanced" over "Advanced settings".
- Prefer "Templates" over "Settings for templates".

### Use sentence case in UI

Any text in UI elements should be using [Sentence case](https://en.wiktionary.org/wiki/sentence_case) instead of [Title Case](https://en.wikipedia.org/wiki/Title_case), where only the first word in a sentence, and proper nouns, should be capitalized.

- Prefer "Template folder location" over "Template Folder Location".
- Prefer "Create new note" over "Create New Note".

## Security

### Avoid `innerHTML`, `outerHTML` and `insertAdjacentHTML`

Building DOM elements from user-defined input, using `innerHTML`, `outerHTML` and `insertAdjacentHTML` can pose a security risk.

The following example builds a DOM element using a string that contains user input, `${name}`. `name` can contain other DOM elements, such as `<script>alert()</script>`, and can allow a potential attacker to execute arbitrary code on the user's computer.

```ts
function showName(name: string) {
  let containerElement = document.querySelector('.my-container');
  // DON'T DO THIS
  containerElement.innerHTML = `<div class="my-class"><b>Your name is: </b>${name}</div>`;
}
```

Instead, use the DOM API or the Obsidian helper functions, such as `createEl()`, `createDiv()` and `createSpan()` to build the DOM element programmatically. For more information, refer to [[HTML elements]].

## Resource management

### Clean up resources when plugin unloads

Any resources created by the plugin, such as event listeners, must be destroyed or released when the plugin unloads.

When possible, use methods like [[registerEvent|registerEvent()]] or [[addCommand|addCommand()]] to automatically clean up resources when the plugin unloads.

```ts
export default class MyPlugin extends Plugin {
  onload() {
    this.registerEvent(this.app.vault.on("create", this.onCreate));
  }

  onCreate: (file: TAbstractFile) => {
    // ...
  }
}
```

> [!note]
> You don't need to clean up resources that are guaranteed to be removed when your plugin unloads. For example, if you register a `mouseenter` listener on a DOM element, the event listener will be garbage-collected when the element goes out of scope.

### Don't detach leaves in `onunload`

When the user updates your plugin, any open leaves will be reinitialized at their original position, regardless of where the user had moved them.

## Commands

### Avoid setting a default hotkey for commands

Setting a default hotkey may lead to conflicts between plugins and may override hotkeys that the user has already configured.

It's also difficult to choose a default hotkey that is available on all operating systems.

### Use the appropriate callback type for commands

When you add a command in your plugin, use the appropriate callback type.

- Use `callback` if the command runs unconditionally.
- Use `checkCallback` if the command only runs under certain conditions.

If the command requires an open and active Markdown editor, use `editorCallback`, or the corresponding `editorCheckCallback`.

## Workspace

### Avoid accessing `workspace.activeLeaf` directly

If you want to access the active view, use [[getActiveViewOfType|getActiveViewOfType()]] instead:

```ts
const view = this.app.workspace.getActiveViewOfType(MarkdownView);

// getActiveViewOfType will return null if the active view is null, or if it's not a MarkdownView.
if (view) {
  // ...
}
```

If you want to access the editor in the active note, use `activeEditor` instead:

```ts
const editor = this.app.workspace.activeEditor;
```

### Avoid managing references to custom views

Managing references to custom view can cause memory leaks or unintended consequences.

**Don't** do this:

```ts
this.registerViewType(MY_VIEW_TYPE, () => this.view = new MyCustomView());
```

Do this instead:

```ts
this.registerViewType(MY_VIEW_TYPE, () => new MyCustomView());
```

To access the view from your plugin, use `Workspace.getActiveLeavesOfType()`:

```ts
for (let leaf of app.workspace.getActiveLeavesOfType(MY_VIEW_TYPE)) {
  let view = leaf.view;
  if (view instanceof MyCustomView) {
    // ...
  }
}
```

## Vault

### Prefer the Editor API instead of `Vault.modify`

If you want to edit an active note, use the [[Editor]] interface instead of [[Vault/modify|Vault.modify()]].

Editor maintains information about the active note, such as cursor position, selection, and folded content. When you use [[Vault/modify|Vault.modify()]] to edit the note, all that information is lost, which leads to a poor experience for the user.

Editor is also more efficient when making small changes to parts of the note.

Only use [[Vault/modify|Vault.modify()]] if you're editing a file in the background.

### Prefer the Vault API over the Adapter API

Obsidian exposes two APIs for file operations: the Vault API (`app.vault`) and the Adapter API (`app.vault.adapter`).

While the file operations in the Adapter API are often more familiar to many developers, the Vault API has two main advantages over the adapter.

- **Performance:** The Vault API has a caching layer that can speed up file reads when the file is already known to Obsidian.
- **Safety:** The Vault API performs file operations serially to avoid any race conditions, for example when reading a file that is being written to at the same time.

### Avoid iterating all files to find a file by its path

This is inefficient, especially for large vaults. Use [[Vault/getAbstractFileByPath|getAbstractFileByPath()]] instead.

```ts
vault.getAllFiles().find(file => file.path === filePath)
```

```ts
const filePath = 'folder/file.md';

const file = app.vault.getAbstractFileByPath(filePath);

// Check if it exists and is of the correct type
if (file instanceof TFile) {
  // file is automatically casted to TFile within this scope.
}
```

### Use `normalizePath()` to clean up user-defined paths

Use [[normalizePath|normalizePath()]] whenever you accept user-defined paths to files or folders in the vault, or when you construct your own paths in the plugin code.

`normalizePath()` takes a path and scrubs it to be safe for the file system and for cross-platform use. This function:

- Cleans up the use of forward and backward slashes, such as replacing 1 or more of `\` or `/` with a single `/`.
- Removes leading and trailing forward and backward slashes.
- Replaces any non-breaking spaces, `\u00A0`, with a regular space.
- Runs the path through [String.prototype.normalize](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize).

```ts
import { normalizePath } from "obsidian";
const pathToPlugin = normalizePath(app.vault.configDir + "//plugins/my-plugin");
// pathToPlugin contains ".obsidian/plugins/my-plugin" not .obsidian//plugins/my-plugin
```

## Editor

### Change or reconfigure editor extensions

If you want to change or reconfigure an [[Editor extensions|editor extension]] after you've registered using [[registerEditorExtension|registerEditorExtension()]], use [[updateOptions|updateOptions()]] to update all editors.

```ts
class MyPlugin extends Plugin {
  private editorExtension: Extension[] = [];

  onload() {
    //...

    this.registerEditorExtension(this.editorExtension);
  }

  updateEditorExtension() {
    // Empty the array while keeping the same reference
    // (Don't create a new array here)
    this.editorExtension.length = 0;

    // Create new editor extension
    let myNewExtension = this.createEditorExtension();
    // Add it to the array
    this.editorExtension.push(myNewExtension);

    // Flush the changes to all editors
    this.app.workspace.updateOptions();
  }
}

```

## TypeScript

### Prefer `const` and `let` over `var`

For more information, refer to [4 Reasons Why var is Considered Obsolete in Modern JavaScript](https://javascript.plainenglish.io/4-reasons-why-var-is-considered-obsolete-in-modern-javascript-a30296b5f08f).

### Prefer async/await over Promise

Recent versions of JavaScript and TypeScript support the `async` and `await` keywords to run code asynchronously, which allow for more readable code than using Promises.

```ts
function test(): Promise<string | null> {
  return requestUrl('https://example.com')
    .then(res => res.text
    .catch(e => {
      console.log(e);
      return null;
    });
}
```

```ts
async function AsyncTest(): Promise<string | null> {
  try {
    let res = await requestUrl('https://example.com');
    let text = await r.text;
    return text;
  }
  catch (e) {
    console.log(e);
    return null;
  }
}
```

### Consider organizing your code base using folders

If your plugin uses more than one `.ts` file, consider organizing them into folders to make it easier to review and maintain.

### Rename placeholder class names

The sample plugin contains placeholder names for common classes, such as `MyPlugin`, `MyPluginSettings`, and `SampleSettingTab`. Rename these to reflect the name of your plugin.

This page lists extends the [[Developer policies]] with plugin-specific requirements that all plugins must follow to be published.

## Only use `fundingUrl` to link to services for financial support

Use [[Manifest#fundingUrl|fundingUrl]] if you accept financial support for your plugin, using services like Buy Me A Coffee or GitHub Sponsors.

If you don't accept donations, remove `fundingUrl` from your manifest.

## Keep plugin descriptions short and simple

Good plugin descriptions help users understand your plugin quickly and succinctly. Good descriptions often start with an action statement such as:

- "Translate selected text into..."
- "Generate notes automatically from..."
- "Import notes from..."
- "Sync highlights and annotations from..."
- "Open links in..."

Avoid starting your description with "This is a plugin", because it'll be obvious to users in the context of the Community Plugins directory.

Your description should:

- Follow the [Obsidian style guide](https://help.obsidian.md/Contributing+to+Obsidian/Style+guide).
- Have 250 characters maximum.
- End with a period `.`.
- Avoid using emoji or special characters.
- Use correct capitalization for acronyms, proper nouns and trademarks such as "Obsidian", "Markdown", "PDF". If you are not sure how to capitalize a term, refer to its website or Wikipedia description.

docs/obsidian-developer/Plugins/Releasing/Submission requirements for plugins.md

## Node.js and Electron APIs are only allowed on desktop

The Node.js and Electron APIs are only available in the desktop version of Obsidian. For example, Node.js packages like `fs`, `crypto`, and `os`, are only available on desktop.

If your plugin uses any of these APIs, you **must** set `isDesktopOnly` to `true` in the `manifest.json`.

> [!tip]
> Many Node.js features have Web API alternatives:
>
> - [`SubtleCrypto`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto) instead of [`crypto`](https://nodejs.org/api/crypto.html).
> - `navigator.clipboard.readText()` and `navigator.clipboard.writeText()` to access clipboard contents.

## Don't include the plugin ID in the command ID

Obsidian automatically prefixes command IDs with your plugin ID. You don't need to include the plugin ID yourself.

Manually releasing your plugin can be time-consuming and error-prone. In this guide, you'll configure your plugin to use [GitHub Actions](https://github.com/features/actions) to automatically create a release when you create a new tag.

1. In the root directory of your plugin, create a file called `release.yml` under `.github/workflows` with the following content:

   ```yml
   name: Release Obsidian plugin

   on:
     push:
       tags:
         - "*"

   jobs:
     build:
       runs-on: ubuntu-latest

       steps:
         - uses: actions/checkout@v3

         - name: Use Node.js
           uses: actions/setup-node@v3
           with:
             node-version: "18.x"

         - name: Build plugin
           run: |
             npm install
             npm run build

         - name: Create release
           env:
             GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
           run: |
             tag="${GITHUB_REF#refs/tags/}"

             gh release create "$tag" \
               --title="$tag" \
               --draft \
               main.js manifest.json styles.css
   ```

2. In your terminal, commit the workflow.

   ```bash
   git add .github/workflows/release.yml
   git commit -m "Add release workflow"
   git push origin main
   ```

3. Create a tag that matches the version in the `manifest.json` file.

   ```bash
   git tag -a 1.0.1 -m "1.0.1"
   git push origin 1.0.1

docs/obsidian-developer/Plugins/Releasing/Release your plugin with GitHub Actions.md

```

   ```bash
   ```

   - `-a` creates an [annotated tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging#_creating_tags).
   - `-m` specifies the name of your release. For Obsidian plugins, this must be the same as the version.

4. Browse to your repository on GitHub and select the **Actions** tab. Your workflow might still be running, or it might have finished already.

5. When the workflow finishes, go back to the main page for your repository and select **Releases** in the sidebar on the right side. The workflow has created a draft GitHub release and uploaded the required assets as binary attachments.

6. Select **Edit** (pencil icon) on the right side of the release name.

7. Add release notes to let users know what happened in this release, and then select **Publish release**.

You've successfully set up your plugin to automatically create a GitHub release whenever you create a new tag.

- If this is the first release for this plugin, you're now ready to [[Submit your plugin]].
- If this is an update to an already published plugin, your users can now update to the latest version.

Modals display information and accept input from the user. To create a modal, create a class that extends [[Reference/TypeScript API/Modal/Modal|Modal]]:

```ts
import { App, Modal } from "obsidian";

export class ExampleModal extends Modal {
  constructor(app: App) {
    super(app);
  }

  onOpen() {
    let { contentEl } = this;
    contentEl.setText("Look at me, I'm a modal! 👀");
  }

  onClose() {
    contentEl.empty();
  }
}
```

- [[Reference/TypeScript API/View/onOpen|onOpen()]] is called when the modal is opened and is responsible for building the content of your modal. For more information, refer to [HTML elements](HTML%20elements.md).
- [[Reference/TypeScript API/Modal/onClose|onClose()]] is called when the modal is closed and is responsible for cleaning up any resources used by the modal.

To open a modal, create a new instance of `ExampleModal` and call [[Reference/TypeScript API/Modal/open|open()]] on it:

```ts
import { ExampleModal } from "./modal";

    this.addCommand({
      id: "display-modal",
      name: "Display modal",
      callback: () => {
        new ExampleModal(this.app).open();
      },
    });
  }
}
```

## Accept user input

The modal in the previous example only displayed some text. Let's look at a little more complex example that handles input from the user.

![[modal-input.png]]

```ts
import { App, Modal, Setting } from "obsidian";

  result: string;
  onSubmit: (result: string) => void;

  constructor(app: App, onSubmit: (result: string) => void) {
    this.onSubmit = onSubmit;
  }

  onOpen() {
    const { contentEl } = this;

    contentEl.createEl("h1", { text: "What's your name?" });

    new Setting(contentEl)
      .setName("Name")
      .addText((text) =>
        text.onChange((value) => {
          this.result = value
        }));

      .addButton((btn) =>
        btn
          .setButtonText("Submit")
          .setCta()
          .onClick(() => {
            this.close();
            this.onSubmit(this.result);
          }));
  }

  }
}
```

The result is stored in `this.result` and returned in the `onSubmit` callback when the user clicks **Submit**:

```ts
new ExampleModal(this.app, (result) => {
  new Notice(`Hello, ${result}!`);
}).open();
```

## Select from list of suggestions

[[SuggestModal|SuggestModal]] is a special modal that lets you display a list of suggestions to the user.

![[suggest-modal.gif]]

```ts
import { App, Notice, SuggestModal } from "obsidian";

interface Book {
  title: string;
  author: string;
}

const ALL_BOOKS = [
  {
    title: "How to Take Smart Notes",
    author: "Sönke Ahrens",
  },
  {
    title: "Thinking, Fast and Slow",
    author: "Daniel Kahneman",
  },
  {
    title: "Deep Work",
    author: "Cal Newport",
  },
];

export class ExampleModal extends SuggestModal<Book> {
  // Returns all available suggestions.
  getSuggestions(query: string): Book[] {
    return ALL_BOOKS.filter((book) =>
      book.title.toLowerCase().includes(query.toLowerCase())
    );
  }

  // Renders each suggestion item.
  renderSuggestion(book: Book, el: HTMLElement) {
    el.createEl("div", { text: book.title });
    el.createEl("small", { text: book.author });
  }

  // Perform action on the selected suggestion.
  onChooseSuggestion(book: Book, evt: MouseEvent | KeyboardEvent) {
    new Notice(`Selected ${book.title}`);
  }
}
```

In addition to `SuggestModal`, the Obsidian API provides an even more specialized type of modal for suggestions: the [[FuzzySuggestModal|FuzzySuggestModal]]. While it doesn't give you the same control of how each item is rendered, you get [fuzzy string search](https://en.wikipedia.org/wiki/Approximate_string_matching) out-of-the-box.

![[fuzzy-suggestion-modal.png]]

```ts
export class ExampleModal extends FuzzySuggestModal<Book> {
  getItems(): Book[] {
    return ALL_BOOKS;
  }

  getItemText(book: Book): string {
    return book.title;
  }

  onChooseItem(book: Book, evt: MouseEvent | KeyboardEvent) {
  }
}
```

The sidebar on the left side of the Obsidian interface is mainly known as the _ribbon_. In addition to system operations, such as opening the preferences or another vault, the ribbon can also host actions defined by plugins.

To add a action to the ribbon, use the [[addRibbonIcon|addRibbonIcon()]] method:

```ts

    this.addRibbonIcon("dice", "Print to console", () => {
      console.log("Hello, you!");
    });
  }
}
```

The first argument specifies which icon to use. For more information on the available icons, and how to add your own, refer to [[Plugins/User interface/Icons|Icons]].

docs/obsidian-developer/Plugins/User interface/Ribbon actions.md

If you want users to be able to configure parts of your plugin themselves, you can expose them as _settings_.

In this guide, you'll learn how to create a settings page like this 👇

![[settings.png]]

The main reason to add settings to a plugin is to store configuration that persists even after the user quits Obsidian. The following example demonstrates how to save and load settings from disk:

```ts
import { ExampleSettingTab } from "./settings";

interface ExamplePluginSettings {
  dateFormat: string;
}

const DEFAULT_SETTINGS: Partial<ExamplePluginSettings> = {
  dateFormat: "YYYY-MM-DD",
};

  settings: ExamplePluginSettings;

    await this.loadSettings();

    this.addSettingTab(new ExampleSettingTab(this.app, this));
  }

  async loadSettings() {
    this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
  }

  async saveSettings() {
    await this.saveData(this.settings);
  }
}
```

> [!warning] Nested properties in settings
> `Object.assign()` copies the references to any nested properties (shallow copy). If your settings object contains nested properties, you need to copy each nested property recursively (deep copy). Otherwise, any changes to a nested property will apply do all objects that were copied using `Object.assign()`.

There's a lot going on here 🤯, so let's look closer at each part.

## Create a settings definition

First, you need to create a definition, `ExamplePluginSettings`, for what settings you want the user to be able to configure. While the plugin is enabled, you can access the settings from the `settings` member variable.

```ts
}

  // ...
}
```

## Save and load the settings object

[[loadData|loadData()]] and [[saveData|saveData()]] provide an easy way to store and retrieve data from disk. The example also introduces two helper methods that makes it easier to use `loadData()` and `saveData()` from other parts of the plugin.

```ts

  // ...

  }

  }
}
```

Finally, make sure to load the settings when the plugin loads:

```ts
async onload() {
  await this.loadSettings();

  // ...
}
```

## Provide default values

When the user enables the plugin for the first time, none of the settings have been configured yet. The preceding example provides default values for any missing settings.

To understand how this work, let's look at the following code:

```ts
Object.assign({}, DEFAULT_SETTINGS, await this.loadData())
```

`Object.assign()` is a JavaScript function that copies all properties from one object to another. Any properties that are returned by `loadData()` override the properties in `DEFAULT_SETTINGS`.

```ts
};
```

> [!tip]
> `Partial<Type>` is a TypeScript utility that returns a type with all properties of `Type` set to optional. It enables type checking while letting you only define the properties you want to provide defaults for.

## Register a settings tab

The plugin can now save and load plugin configuration, but the user doesn't yet have any way of changing any of the settings. By adding a settings tab you can provide an easy-to-use interface for the user to update their plugin settings:

```ts
this.addSettingTab(new ExampleSettingTab(this.app, this));
```

Here, the `ExampleSettingTab` is a class that extends [[PluginSettingTab|PluginSettingTab]]:

```ts
import ExamplePlugin from "./main";
import { App, PluginSettingTab, Setting } from "obsidian";

export class ExampleSettingTab extends PluginSettingTab {
  plugin: ExamplePlugin;

  constructor(app: App, plugin: ExamplePlugin) {
    super(app, plugin);
    this.plugin = plugin;
  }

  display(): void {
    let { containerEl } = this;

    containerEl.empty();

    new Setting(containerEl)
      .setName("Date format")
      .setDesc("Default date format")
        text
          .setPlaceholder("MMMM dd, yyyy")
          .setValue(this.plugin.settings.dateFormat)
          .onChange(async (value) => {
            this.plugin.settings.dateFormat = value;
            await this.plugin.saveSettings();
          })
      );
  }
}
```

`display()` is where you build the content for the settings tab. For more information, refer to [[HTML elements]].

`new Setting(containerEl)` appends a setting to the container element. This example uses a text field using `addText()`, but there are several other setting types available.

Update the settings object whenever the value of the text field changes, and then save it to disk:

```ts
.onChange(async (value) => {
  this.plugin.settings.dateFormat = value;
  await this.plugin.saveSettings();
})
```

Nice work! 💪 Your users will thank you for giving them a way to customize how they interact with your plugin. Before heading to the next guide, experiment with what you've learned by adding another setting.

This page gives you an overview of how to add or change the Obsidian user interface.

You can see some of the user interface components when you first open Obsidian.

- [[Ribbon actions]]
- [[Views]]
- [[Plugins/User interface/Status bar|Status bar]]

To modify the editor, refer to [[Editor]] and [[Editor extensions]].

![User interface](user-interface.png)

docs/obsidian-developer/Plugins/User interface/About user interface.md

Commands are actions that the user can perform from the [Command Palette](https://help.obsidian.md/Plugins/Command+palette) or by using a hot key.

![[command.png]]

To register a new command for your plugin, call the [[addCommand|addCommand()]] method inside the `onload()` method:

```ts

      id: "print-greeting-to-console",
      name: "Print greeting to console",
        console.log("Hey, you!");
      },
    });
  }
}
```

## Conditional commands

If your command is only able to run under certain conditions, then consider using [[checkCallback|checkCallback()]] instead.

The `checkCallback` runs twice. First, to perform a preliminary check to determine whether the command can run. Second, to perform the action.

Since time may pass between the two runs, you need to perform the check during both calls.

To determine whether the callback should perform a preliminary check or an action, a `checking` argument is passed to the callback.

- If `checking` is set to `true`, perform a preliminary check.
- If `checking` is set to `false`, perform an action.

The command in the following example depends on a required value. In both runs, the callback checks that the value is present but only performs the action if `checking` is `false`.

```ts
this.addCommand({
  id: 'example-command',
  name: 'Example command',
  // highlight-next-line
  checkCallback: (checking: boolean) => {
    const value = getRequiredValue();

    if (value) {
      if (!checking) {
        doCommand(value);
      }

      return true
    }

    return false;
  },
});
```

## Editor commands

If your command needs access to the editor, you can also use the [[editorCallback|editorCallback()]], which provides the active editor and its view as arguments.

```ts
  editorCallback: (editor: Editor, view: MarkdownView) => {
    const sel = editor.getSelection()

    console.log(`You have selected: ${sel}`);
  },
}
```

> [!note]
> Editor commands only appear in the Command Palette when there's an active editor available.

If the editor callback can only run given under certain conditions, consider using the [[editorCheckCallback|editorCheckCallback()]] instead. For more information, refer to [[#Conditional commands]].

```ts
  editorCheckCallback: (checking: boolean, editor: Editor, view: MarkdownView) => {

      }

    }

  },
});
```

## Hot keys

The user can run commands using a keyboard shortcut, or _hot key_. While they can configure this themselves, you can also provide a default hot key.

> Avoid setting default hot keys for plugins that you intend for others to use. Hot keys are highly likely to conflict with those defined by other plugins or by the user themselves.

In this example, the user can run the command by pressing and holding Ctrl (or Cmd on Mac) and Shift together, and then pressing the letter `a` on their keyboard.

```ts
  hotkeys: [{ modifiers: ["Mod", "Shift"], key: "a" }],
  callback: () => {
    console.log('Hey, you!');
  },
});
```

> [!note]
> The Mod key is a special modifier key that becomes Ctrl on Windows and Linux, and Cmd on macOS.

Views determine how Obsidian displays content. The file explorer, graph view, and the Markdown view are all examples of views, but you can also create your own custom views that display content in a way that makes sense for your plugin.

To create a custom view, create a class that extends the [[ItemView|ItemView]] interface:

```ts

  }

  }

  }

    const container = this.containerEl.children[1];
    container.empty();
    container.createEl("h4", { text: "Example view" });
  }

    // Nothing to clean up.
  }
}

```

> [!note]
> For more information on how to use the `createEl()` method, refer to [[HTML elements]].

Each view is uniquely identified by a text string and several operations require that you specify the view you'd like to use. Extracting it to a constant, `VIEW_TYPE_EXAMPLE`, is a good idea—as you will see later in this guide.

- `getViewType()` returns a unique identifier for the view.
- `getDisplayText()` returns a human-friendly name for the view.
- `onOpen()` is called when the view is opened within a new leaf and is responsible for building the content of your view.
- `onClose()` is called when the view should close and is responsible for cleaning up any resources used by the view.

Custom views need to be registered when the plugin is enabled, and cleaned up when the plugin is disabled:

```ts
import { ExampleView, VIEW_TYPE_EXAMPLE } from "./view";

    this.registerView(
      VIEW_TYPE_EXAMPLE,
      (leaf) => new ExampleView(leaf)
    );

    this.addRibbonIcon("dice", "Activate view", () => {
      this.activateView();
    });
  }

  }

  async activateView() {
    const { workspace } = this.app;

    let leaf: WorkspaceLeaf | null = null;
    const leaves = workspace.getLeavesOfType(VIEW_TYPE_EXAMPLE);

    if (leaves.length > 0) {
      // A leaf with our view already exists, use that
      leaf = leaves[0];
    } else {
      // Our view could not be found in the workspace, create a new leaf
      // in the right sidebar for it
      leaf = workspace.getRightLeaf(false);
      await leaf.setViewState({ type: VIEW_TYPE_EXAMPLE, active: true });
    }

    // "Reveal" the leaf in case it is in a collapsed sidebar
    workspace.revealLeaf(leaf);
  }
}

```

The second argument to [[registerView|registerView()]] is a factory function that returns an instance of the view you want to register.

> Never manage references to views in your plugin. Obsidian may call the view factory function multiple times. Avoid side effects in your view, and use `getLeavesOfType()` whenever you need to access your view instances.
>
> ```ts
> this.app.workspace.getLeavesOfType(VIEW_TYPE_EXAMPLE).forEach((leaf) => {
>   if (leaf.view instanceof ExampleView) {
>     // Access your view instance.
>   }
> });
> ```

Obsidian lets you configure what content is visible to you at any given time. Hide the file explorer when you don't need it, display multiple documents side by side, or show an outline of your document while you're working on it. The configuration of visible content within your application window is known as the _workspace_.

The workspace is implemented as a [tree data structure](https://en.wikipedia.org/wiki/Tree_(data_structure)), where each node in the tree is referred to as a [[WorkspaceItem|workspace item]]. There are two types of workspace items: [[WorkspaceParent|parents]] and [[WorkspaceLeaf|leaves]]. The main difference is that parent items can contain _child_ items, including other parent items, whereas leaf items can't contain any workspace items at all.

There are two types of parent items, [[WorkspaceSplit|splits]] and [[WorkspaceTabs|tabs]], which determine how the children are presented to the user:

flowchart TD
    split{Split}
    split --> A((Leaf))
    split --> B((Leaf))
    split --> C((Leaf))

    tabs{Tabs}
    tabs --> X((Leaf))
    tabs --> Y((Leaf))
    tabs --> Z((Leaf))
```

- A split item lays out its child items one after another along a vertical or horizontal direction.
- A tabs item only displays one child item at a time and hides the others.

The workspace has three special split items under it: _left_, _right_, and _root_. The following diagram shows a example of what a typical workspace could look like:

    Workspace --> Left{Left split}
    Workspace --> Root{Root split}
    Workspace --> Right{Right split}

    Left --> leftTabs{Tabs}
    leftTabs --> A((Leaf))
    leftTabs --> B((Leaf))

    Root --> C{Split}
    Root --> D((Leaf))

    C --> E((Leaf))
    C --> F((Leaf))

    Right --> rightTabs{Tabs}

    rightTabs --> I((Leaf))
    rightTabs --> J((Leaf))
    rightTabs --> K((Leaf))

```

A leaf is a window that can display content in different ways. The type of leaf determines how content is displayed, and correspond to a specific _view_. For example, a leaf of type `graph` displays the [graph view](https://help.obsidian.md/Plugins/Graph+view).

## Splits

By default, the direction of the root split is set to vertical. When you create a new leaf to it, Obsidian creates a new column in the user interface. When you split a leaf, the resulting leaves are added to a new split item. While there's no defined limit to the number of levels you can create under the root split, in practice their usefulness diminish for each level.

    rootBefore{"Root split\n(before)"}

    rootBefore --> leaf1((Leaf))
    rootBefore --> leaf2((Leaf))

    rootAfter{"Root split\n(after)"}

    rootAfter --> split{Split}
    rootAfter --> leaf3((Leaf))
    split --> leaf4((Leaf))
    split --> leaf5((Leaf))
```

The left and right splits work a little differently. When you split a leaf in the side docks, Obsidian generates a new tabs item and adds the new leaf under it. Effectively, this means they can only have three levels of workspace items at any time, and any direct children must be tabs items.

    split1{"Right split\n(before)"}
    tabs1{Tabs}
    leaf1((Leaf))
    leaf2((Leaf))

    split1 --> tabs1
    tabs1 --> leaf1
    tabs1 --> leaf2

    split2{"Right split\n(after)"}
    tabs2{Tabs}
    tabs3{Tabs}
    leaf3((Leaf))
    leaf4((Leaf))
    leaf5((Leaf))

    split2 --> tabs2
    tabs2 --> leaf3
    tabs2 --> leaf4

    split2 --> tabs3
    tabs3 --> leaf5
```

## Inspect the workspace

You can access the workspace through the [[App|App]] object. The following example prints the type of every leaf in the workspace:

```ts

    this.addRibbonIcon("dice", "Print leaf types", () => {
      this.app.workspace.iterateAllLeaves((leaf) => {
        console.log(leaf.getViewState().type);
      });
    });
  }
}
```

## Leaf lifecycle

Plugins can add leaves of any type to the workspace, as well as define new leaf types through [[Views|custom views]]. Here are a few ways to add a leaf to the workspace. For more ways, refer to [[Reference/TypeScript API/Workspace/Workspace|Workspace]].

- If you want to add a new leaf in the root split, use [[getLeaf|getLeaf(true)]].
- If you want to add a new leaf in any of the side bars, use [[getLeftLeaf|getLeftLeaf()]] and [[getRightLeaf|getRightLeaf()]]. Both let you decide whether to add the leaf to a new split.

You can also explicitly add the leaf in the split of your choice, using [[createLeafInParent|createLeafInParent()]].

Unless explicitly removed, any leaves that a plugin add to the workspace remain even after the plugin is disabled. Plugins are responsible for removing any leaves they add to the workspace.

To remove a leaf from the workspace, call [[detach|detach()]] on the leaf you want to remove. You can also remove all leaves of a certain type, by using [[detachLeavesOfType|detachLeavesOfType()]].

## Leaf groups

You can create [linked panes](https://help.obsidian.md/User+interface/Workspace/Panes/Linked+pane) by assigning multiple leaves to the same group, using [[setGroup|setGroup()]].

```ts
leaves.forEach((leaf) => leaf.setGroup("group1");
```

Several components in the Obsidian API, such as the [[Settings]], expose _container elements_:

```ts
import { App, PluginSettingTab } from "obsidian";

class ExampleSettingTab extends PluginSettingTab {

  }

    // highlight-next-line

    // ...
  }
}
```

Container elements are `HTMLElement` objects that make it possible to create custom interfaces within Obsidian.

## Create HTML elements using `createEl()`

Every `HTMLElement`, including the container element, exposes a `createEl()` method that creates an `HTMLElement` under the original element.

For example, here's how you can add an `<h1>` heading element inside the container element:

```ts
containerEl.createEl("h1", { text: "Heading 1" });
```

`createEl()` returns a reference to the new element:

```ts
const book = containerEl.createEl("div");
book.createEl("div", { text: "How to Take Smart Notes" });
book.createEl("small", { text: "Sönke Ahrens" });
```

## Style your elements

You can add custom CSS styles to your plugin by adding a `styles.css` file in the plugin root directory. To add some styles for the previous book example:

```css title="styles.css"
.book {
  border: 1px solid var(--background-modifier-border);
  padding: 10px;
}

.book__title {
  font-weight: 600;
}

.book__author {
  color: var(--text-muted);
}
```

> [!tip]
> `--background-modifier-border` and `--text-muted` are [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties) that are defined and used by Obsidian itself. If you use these variables for your styles, your plugin will look great even if the user has a different theme! 🌈

To make the HTML elements use the styles, set the `cls` property for the HTML element:

```ts
const book = containerEl.createEl("div", { cls: "book" });
book.createEl("div", { text: "How to Take Smart Notes", cls: "book__title" });
book.createEl("small", { text: "Sönke Ahrens", cls: "book__author" });
```

Now it looks much better! 🎉

![[styles.png]]

### Conditional styles

Use the `toggleClass` method if you want to change the style of an element based on the user's settings or other values:

```ts
element.toggleClass("danger", status === "error");
```

To create a new block in the status bar, call the [[addStatusBarItem|addStatusBarItem()]] in the `onload()` method. The `addStatusBarItem()` method returns an [[HTML elements]] that you can add your own elements to.

> [!caution] Obsidian mobile
> Custom status bar items [are **not** supported](https://discord.com/channels/686053708261228577/707816848615407697/832321402106544179) on Obsidian mobile apps.

```ts

    const item = this.addStatusBarItem();
    item.createEl("span", { text: "Hello from the status bar 👋" });
  }
}
```

> [!note]

You can add multiple status bar items by calling `addStatusBarItem()` multiple times. Since Obsidian adds a gap between them, you need to create multiple HTML element on the same status bar item if you need more control of spacing.

```ts

    const fruits = this.addStatusBarItem();
    fruits.createEl("span", { text: "🍎" });
    fruits.createEl("span", { text: "🍌" });

    const veggies = this.addStatusBarItem();
    veggies.createEl("span", { text: "🥦" });
    veggies.createEl("span", { text: "🥬" });
  }
}
```

The example above results in the following status bar:

![[status-bar.png]]

Several of the UI components in the Obsidian API lets you configure an accompanying icon. You can choose from one of the built-in icons, or you can add your own.

## Browse available icons

Browse to [lucide.dev](https://lucide.dev/) to see all available icons and their corresponding names.

**Please note:** Only icons up to v0.171.0 are supported at this time.

## Use icons

If you'd like to use icons in your custom interfaces, use the [[setIcon|setIcon()]] utility function to add an icon to an [[HTML elements|HTML element]]. The following example adds icon to the status bar:

```ts
import { Plugin, setIcon } from "obsidian";

    setIcon(item, "info");
  }
}
```

To change the size of the icon, set the `--icon-size` [[Reference/CSS variables/Foundations/Icons|CSS variable]] on the element containing the icon using preset sizes:

```css
div {
  --icon-size: var(--icon-size-m);
}
```

## Add your own icon

To add a custom icon for your plugin, use the [[addIcon|addIcon()]] utility:

```ts
import { addIcon, Plugin } from "obsidian";

    addIcon("circle", `<circle cx="50" cy="50" r="50" fill="currentColor" />`);

    this.addRibbonIcon("circle", "Click me", () => {
    });
  }
}
```

`addIcon` takes two arguments:

1. A name to uniquely identify your icon.
2. The SVG content for the icon, without the surrounding `<svg>` tag.

Note that your icon needs to fit within a `0 0 100 100` view box to be drawn properly.

After the call to `addIcon`, you can use the icon just like any of the built-in icons.

### Icon design guidelines

For compatibility and cohesiveness with the Obsidian interface, your icons should [follow Lucide’s guidelines](https://lucide.dev/guide/design/icon-design-guide):

- Icons must be designed on a 24 by 24 pixels canvas
- Icons must have at least 1 pixel padding within the canvas
- Icons must have a stroke width of 2 pixels
- Icons must use round joins
- Icons must use round caps
- Icons must use centered strokes
- Shapes (such as rectangles) in icons must have border radius of 2 pixels
- Distinct elements must have 2 pixels of spacing between each other

Lucide also [provides templates and guides](https://github.com/lucide-icons/lucide/blob/main/CONTRIBUTING.md) for vector editors such as Illustrator, Figma, and Inkscape.

If you want to open up a context menu, use [[Menu|Menu]]:

```ts
import { Menu, Notice, Plugin } from "obsidian";

    this.addRibbonIcon("dice", "Open menu", (event) => {
      const menu = new Menu();

      menu.addItem((item) =>
        item
          .setTitle("Copy")
          .setIcon("documents")
            new Notice("Copied");
          })
      );

        item
          .setTitle("Paste")
          .setIcon("paste")
            new Notice("Pasted");
          })
      );

      menu.showAtMouseEvent(event);
    });
  }
}

```

[[showAtMouseEvent|showAtMouseEvent()]] opens the menu where you clicked with the mouse.

> [!tip]
> If you need more control of where the menu appears, you can use `menu.showAtPosition({ x: 20, y: 20 })` to open the menu at a position relative to the top-left corner of the Obsidian window.

For more information on what icons you can use, refer to [[Plugins/User interface/Icons|Icons]].

You can also add an item to the file menu, or the editor menu, by subscribing to the `file-menu` and `editor-menu` workspace events:

![[context-menu-positions.png]]

```ts

    this.registerEvent(
      this.app.workspace.on("file-menu", (menu, file) => {
        menu.addItem((item) => {
          item
            .setTitle("Print file path 👈")
            .setIcon("document")
            .onClick(async () => {
              new Notice(file.path);
            });
        });
      })
    );

  this.registerEvent(
      this.app.workspace.on("editor-menu", (menu, editor, view) => {
          item
              new Notice(view.file.path);
            });
        });
      })
    );
  }
}
```

For more information on handling events, refer to [[Events]].

This page aims to give an introduction to state management for [[Editor extensions|editor extensions]].

> [!note]
> This page aims to distill the official CodeMirror 6 documentation for Obsidian plugin developers. For more detailed information on state management, refer to [State and Updates](https://codemirror.net/docs/guide/#state-and-updates).

## State changes

In most applications, you would update state by assigning a new value to a property or variable. As a consequence, the old value is lost forever.

```ts
let note = "";
note = "Heading"
note = "# Heading"
note = "## Heading" // How to undo this?
```

To support features like undoing and redoing changes to a user's workspace, applications like Obsidian instead keep a history of all changes that have been made. To undo a change, you can then go back to a point in time before the change was made.

|   | State      |
|---|------------|
| 0 |            |
| 1 | Heading    |
| 2 | # Heading  |
| 3 | ## Heading |

In TypeScript, you'd then end up with something like this:

```ts
const changes: ChangeSpec[] = [];

changes.push({ from: 0, insert: "Heading" });
changes.push({ from: 0, insert: "# " });
changes.push({ from: 0, insert: "#" });
```

## Transactions

Imagine a feature where you select some text and press the double quote, `"` to surround the selection with quotes on both sides. One way to implement the feature would be to:

1. Insert `"` at the start of the selection.
2. Insert `"` at the end of the selection.

Notice that the implementation consists of _two_ state changes. If you added these to the undo history, the user would need to undo _twice_, once for each double quote. To avoid this, what if you could group these changes so that they appear as one?

For editor extensions, a group of state changes that happen together is called a _transaction_.

If you combine what you've learned so far—and if you allow transactions that contain only a single state change—then you can consider state as a _history of transactions_.

Bringing it all together to implement the surround feature from before in an editor extension, here's how you'd add, or _dispatch_, a transaction to the editor view:

```ts
view.dispatch({
  changes: [
    { from: selectionStart, insert: `"` },
    { from: selectionEnd, insert: `"` }
  ]
});
```

On this page, you've learned about modeling state as a series of state changes, and how to group them into transactions.

To learn how to manage custom state in your editor, refer to [[State fields]].

The Obsidian editor supports [huge documents](https://codemirror.net/examples/million/) with millions of lines. One of the reasons why this is possible, is because the editor only renders what's visible (and a little bit more).

Imagine that you want to edit a document that is too big to fit on your monitor. The Obsidian editor creates a "window" that moves across the document, only rendering the content within the window (and ignoring what's outside). This window is known as the editor's _viewport_.

![Viewport](viewport.svg)

Whenever the user scrolls through the document, or when the document itself changes, the viewport becomes out-of-date and needs to be recomputed.

If you want to build an editor extension that depends on the viewport, refer to [[View plugins]].

> [!note]
> This page aims to distill the official CodeMirror 6 documentation for Obsidian plugin developers. For more information on state management, refer to [Viewport](https://codemirror.net/docs/guide/#viewport).

Decorations let you control how to draw or style content in [[Editor extensions|editor extensions]]. If you intend to change the look and feel by adding, replacing, or styling elements in the editor, you most likely need to use decorations.

By the end of this page, you'll be able to:

- Understand how to use decorations to change the editor appearance.
- Understand the difference between providing decoration using state fields and view plugins.

> [!note]
> This page aims to distill the official CodeMirror 6 documentation for Obsidian plugin developers. For more detailed information on state fields, refer to [Decorating the Document](https://codemirror.net/docs/guide/#decorating-the-document).

- Basic understanding of [[State fields]].
- Basic understanding of [[View plugins]].

## Overview

Without decorations, the document would render as plain text. Not very interesting at all. Using decorations, you can change how to display the document, for example by highlighting text or adding custom HTML elements.

You can use the following types of decorations:

- [Mark decorations](https://codemirror.net/docs/ref/#view.Decoration%5Emark) style existing elements.
- [Widget decorations](https://codemirror.net/docs/ref/#view.Decoration%5Ewidget) insert elements in the document.
- [Replace decorations](https://codemirror.net/docs/ref/#view.Decoration%5Ereplace) hide or replace part of the document with another element.
- [Line decorations](https://codemirror.net/docs/ref/#view.Decoration%5Eline) add styling to the lines, rather than the document itself.

To use decorations, you need to create them inside an editor extension and have the extension _provide_ them to the editor. You can provide decorations to the editor in two ways, either _directly_ using [[State fields|state fields]] or _indirectly_ using [[View plugins|view plugins]].

## Should I use a view plugin or a state field?

Both view plugins and state fields can provide decorations to the editor, but they have some differences.

- Use a view plugin if you can determine the decoration based on what's inside the [[Viewport]].
- Use a state field if you need to manage decorations outside of the viewport.
- Use a state field if you want to make changes that could change the content of the viewport, for example by adding line breaks.

If you can implement your extension using either approach, then the view plugin generally results in better performance. For example, imagine that you want to implement an editor extension that checks the spelling of a document.

One way would be to pass the entire document to an external spell checker which then returns a list of spelling errors. In this case, you'd need to map each error to a decoration and use a state field to manage decorations regardless of what's in the viewport at the moment.

Another way would be to only spellcheck what's visible in the viewport. The extension would need to continuously run a spell check as the user scrolls through the document, but you'd be able to spell check documents with millions of lines of text.

![State field vs. view plugin](decorations.svg)

## Providing decorations

Imagine that you want to build an editor extension that replaces the bullet list item with an emoji. You can accomplish this with either a view plugin or a state field, with some differences.  In this section, you'll see how to implement it with both types of extensions.

Both implementations share the same core logic:

1. Use [syntaxTree](https://codemirror.net/docs/ref/#language.syntaxTree) to find list items.
2. For every list item, replace leading hyphens, `-`, with a _widget_.

### Widgets

Widgets are custom HTML elements that you can add to the editor. You can either insert a widget at a specific position in the document, or replace a piece of content with a widget.

The following example defines a widget that returns an HTML element, `<span>👉</span>`. You'll use this widget later on.

```ts
import { EditorView, WidgetType } from "@codemirror/view";

export class EmojiWidget extends WidgetType {
  toDOM(view: EditorView): HTMLElement {
    const div = document.createElement("span");

    div.innerText = "👉";

    return div;
  }
}
```

To replace a range of content in your document with the emoji widget, use the [replace decoration](https://codemirror.net/docs/ref/#view.Decoration%5Ereplace).

```ts
const decoration = Decoration.replace({
  widget: new EmojiWidget()
});
```

### State fields

To provide decorations from a state field:

1. [[State fields#Defining a state field|Define a state field]] with a `DecorationSet` type.
2. Add the `provide` property to the state field.

   ```ts
   provide(field: StateField<DecorationSet>): Extension {
     return EditorView.decorations.from(field);
   },
   ```

```ts
import { syntaxTree } from "@codemirror/language";
import {
  Extension,
  RangeSetBuilder,
  StateField,
  Transaction,
} from "@codemirror/state";
import {
  Decoration,
  DecorationSet,
  EditorView,
  WidgetType,
} from "@codemirror/view";
import { EmojiWidget } from "emoji";

export const emojiListField = StateField.define<DecorationSet>({
  create(state): DecorationSet {
    return Decoration.none;
  },
  update(oldState: DecorationSet, transaction: Transaction): DecorationSet {
    const builder = new RangeSetBuilder<Decoration>();

    syntaxTree(transaction.state).iterate({
      enter(node) {
        if (node.type.name.startsWith("list")) {
          // Position of the '-' or the '*'.
          const listCharFrom = node.from - 2;

          builder.add(
            listCharFrom,
            listCharFrom + 1,
            Decoration.replace({
              widget: new EmojiWidget(),
            })
          );
        }
      },
    });

    return builder.finish();
  },
  provide(field: StateField<DecorationSet>): Extension {
    return EditorView.decorations.from(field);
  },
});
```

### View plugins

To manage your decorations using a view plugin:

1. [[View plugins#Creating a view plugin|Create a view plugin]].
2. Add a `DecorationSet` member property to your plugin.
3. Initialize the decorations in the `constructor()`.
4. Rebuild decorations in `update()`.

Not all updates are reasons to rebuild your decorations. The following example only rebuilds decorations whenever the underlying document or the viewport changes.

```ts
import { RangeSetBuilder } from "@codemirror/state";
import {
  PluginSpec,
  PluginValue,
  ViewPlugin,
  ViewUpdate,

class EmojiListPlugin implements PluginValue {
  decorations: DecorationSet;

  constructor(view: EditorView) {
    this.decorations = this.buildDecorations(view);
  }

  update(update: ViewUpdate) {
    if (update.docChanged || update.viewportChanged) {
      this.decorations = this.buildDecorations(update.view);
    }
  }

  destroy() {}

  buildDecorations(view: EditorView): DecorationSet {

    for (let { from, to } of view.visibleRanges) {
      syntaxTree(view.state).iterate({
        from,
        to,
        enter(node) {
          if (node.type.name.startsWith("list")) {
            // Position of the '-' or the '*'.
            const listCharFrom = node.from - 2;

            builder.add(
              listCharFrom,
              listCharFrom + 1,
              Decoration.replace({
                widget: new EmojiWidget(),
              })
            );
          }
        },
      });
    }

  }
}

const pluginSpec: PluginSpec<EmojiListPlugin> = {
  decorations: (value: EmojiListPlugin) => value.decorations,
};

export const emojiListPlugin = ViewPlugin.fromClass(
  EmojiListPlugin,
  pluginSpec
);

```

`buildDecorations()` is a helper method that builds a complete set of decorations based on the editor view.

Notice the second argument to the `ViewPlugin.fromClass()` function. The `decorations` property in the `PluginSpec` specifies how the view plugin provides the decorations to the editor.

Since the view plugin knows what's visible to the user, you can use `view.visibleRanges` to limit what parts of the syntax tree to visit.

A state field is an [[Editor extensions|editor extension]] that lets you manage custom editor state. This page walks you through building a state field by implementing a calculator extension.

The calculator should be able to add and subtract a number from the current state, and to reset the state when you want to start over.

By the end of this page, you'll understand the basic concepts of building a state field.

> [!note]
> This page aims to distill the official CodeMirror 6 documentation for Obsidian plugin developers. For more detailed information on state fields, refer to [State Fields](https://codemirror.net/docs/guide/#state-fields).

- Basic understanding of [[State management]].

## Defining state effects

State effects describe the state change you'd like to make. You may think of them as methods on a class.

In the calculator example, you'd define a state effect for each of the calculator operations:

```ts
const addEffect = StateEffect.define<number>();
const subtractEffect = StateEffect.define<number>();
const resetEffect = StateEffect.define();
```

The type between the angle brackets, `<>`, defines the input type for the effect. For example, the number you want to add or subtract. The reset effect doesn't need any input, so you can leave it out.

## Defining a state field

Contrary to what one might think, state fields don't actually _store_ state. They _manage_ it. State fields take the current state, applies any state effects, and returns the new state.

The state field contains the calculator logic to apply the mathematical operations depending on the effects in a transaction. Since a transaction can contain multiple effects, for example two additions, the state field needs to apply them all one after another.

```ts
export const calculatorField = StateField.define<number>({
  create(state: EditorState): number {
    return 0;
  },
  update(oldState: number, transaction: Transaction): number {
    let newState = oldState;

    for (let effect of transaction.effects) {
      if (effect.is(addEffect)) {
        newState += effect.value;
      } else if (effect.is(subtractEffect)) {
        newState -= effect.value;
      } else if (effect.is(resetEffect)) {
        newState = 0;
      }
    }

    return newState;
  },
});
```

- `create` returns the value the calculator starts with.
- `update` contains the logic for applying the effects.
- `effect.is()` lets you check the type of the effect before you apply it.

## Dispatching state effects

To apply a state effect to a state field, you need to dispatch it to the editor view as part of a transaction.

```ts
  effects: [addEffect.of(num)],
});
```

You can even define a set of helper functions that provide a more familiar API:

```ts
export function add(view: EditorView, num: number) {
  view.dispatch({
    effects: [addEffect.of(num)],
  });
}

export function subtract(view: EditorView, num: number) {
    effects: [subtractEffect.of(num)],
  });
}

export function reset(view: EditorView) {
    effects: [resetEffect.of(null)],
  });
}
```

Provide [[Decorations]] from your state fields to change how to display the document.

The [[Reference/TypeScript API/Editor/Editor|Editor]] class exposes operations for reading and manipulating an active Markdown document in edit mode.

If you want to access the editor in a command, use the [[Commands#Editor commands|editorCallback]].

If you want to use the editor elsewhere, you can access it from the active view:

```ts

// Make sure the user is editing a Markdown file.
if (view) {
	const cursor = view.editor.getCursor();

	// ...
}
```

> [!note]
> Obsidian uses [CodeMirror](https://codemirror.net/) (CM) as the underlying text editor, and exposes the CodeMirror editor as part of the API. `Editor` serves as an abstraction to bridge features between CM6 and CM5 (legacy editor, only available on desktop). By using `Editor` instead of directly accessing the CodeMirror instance, you ensure that your plugin works on both platforms.

## Insert text at cursor position

The [[replaceRange|replaceRange()]] method replaces the text between two cursor positions. If you only give it one position, it inserts the new text between that position and the next.

The following command inserts today's date at the cursor position:

```ts
import { Editor, moment, Plugin } from "obsidian";

      id: "insert-todays-date",
      name: "Insert today's date",
      editorCallback: (editor: Editor) => {
        editor.replaceRange(
          moment().format("YYYY-MM-DD"),
          editor.getCursor()
        );
      },
    });
  }
}
```

![[editor-todays-date.gif]]

## Replace current selection

If you want to modify the selected text, use [[replaceRange|replaceSelection()]] to replace the current selection with a new text.

The following command reads the current selection and converts it to uppercase:

```ts
import { Editor, Plugin } from "obsidian";

      id: "convert-to-uppercase",
      name: "Convert to uppercase",
        const selection = editor.getSelection();
        editor.replaceSelection(selection.toUpperCase());
      },
    });
  }
}
```

![[editor-uppercase.gif]]

Once you've built your editor extension, you might want to communicate with it from outside the editor. For example, through a [[Commands|command]], or a [[Ribbon actions|ribbon action]].

You can access the CodeMirror 6 editor from a [[MarkdownView|MarkdownView]]. However, since the Obsidian API doesn't actually expose the editor, you need to tell TypeScript to trust that it's there, using `@ts-expect-error`.

```ts
import { EditorView } from "@codemirror/view";

// @ts-expect-error, not typed
const editorView = view.editor.cm as EditorView;
```

## View plugin

You can access the [[View plugins|view plugin]] instance from the `EditorView.plugin()` method.

```ts
	id: "example-editor-command",
	name: "Example editor command",
	editorCallback: (editor, view) => {
		// @ts-expect-error, not typed
		const editorView = view.editor.cm as EditorView;

		const plugin = editorView.plugin(examplePlugin);

		if (plugin) {
			plugin.addPointerToSelection(editorView);
		}
	},
});
```

## State field

You can dispatch changes and [[State fields#Dispatching state effects|dispatch state effects]] directly on the editor view.

```ts

		editorView.dispatch({
			effects: [
				// ...
			],
		});
	},
});
```

docs/obsidian-developer/Plugins/Editor/Communicating with editor extensions.md

Editor extensions let you customize the experience of editing notes in Obsidian. This page explains what editor extensions are, and when to use them.

Obsidian uses CodeMirror 6 (CM6) to power the Markdown editor. Just like Obsidian, CM6 has plugins of its own, called _extensions_. In other words, an Obsidian _editor extension_ is the same thing as a _CodeMirror 6 extension_.

The API for building editor extensions is a bit unconventional and requires that you have a basic understanding of its architecture before you get started. This section aims to give you enough context and examples for you to get started. If you want to learn more about building editor extensions, refer to the [CodeMirror 6 documentation](https://codemirror.net/docs/).

## Do I need an editor extension?

Building editor extensions can be challenging, so before you start building one, consider whether you really need it.

- If you want to change how to convert Markdown to HTML in the Reading view, consider building a [[Markdown post processing|Markdown post processor]].
- If you want to change how the document looks and feels in Live Preview, you need to build an editor extension.

## Registering editor extensions

CodeMirror 6 (CM6) is a powerful engine for editing code using web technologies. At its core, the editor itself has a minimal set of features. Any features you'd expect from a modern editor are available as _extensions_ that you can pick and choose. While Obsidian comes with many of these extensions out-of-the-box, you can also register your own.

To register an editor extension, use [[registerEditorExtension|registerEditorExtension()]] in the `onload` method of your Obsidian plugin:

```ts
onload() {
  this.registerEditorExtension([examplePlugin, exampleField]);
}
```

While CM6 supports several types of extensions, two of the most common ones are [[View plugins]] and [[State fields]].
<DocCardList items={useCurrentSidebarCategory().items}/>

A view plugin is an [[Editor extensions|editor extension]] that gives you access to the editor [[Viewport]].

> [!note]
> This page aims to distill the official CodeMirror 6 documentation for Obsidian plugin developers. For more information on state management, refer to [Affecting the View](https://codemirror.net/docs/guide/#affecting-the-view).

- Basic understanding of the [[Viewport]].

## Creating a view plugin

View plugins are editor extensions that run _after_ the viewport has been recomputed. While this means that they can access the viewport, it also means that a view plugin can't make any changes that would impact the viewport. For example, by inserting blocks or line breaks into the document.

> [!tip]
> If you want to make changes that impact the vertical layout of the editor, by for example inserting blocks and line breaks, you need to use a [[State fields|state field]].

To create a view plugin, create a class that implements [PluginValue](https://codemirror.net/docs/ref/#view.PluginValue) and pass it to the [ViewPlugin.fromClass()](https://codemirror.net/docs/ref/#view.ViewPlugin^fromClass) function.

```ts
import {

class ExamplePlugin implements PluginValue {
    // ...
  }

    // ...
  }

  destroy() {
    // ...
  }
}

export const examplePlugin = ViewPlugin.fromClass(ExamplePlugin);
```

The three methods of the view plugin control its lifecycle:

- `constructor()` initializes the plugin.
- `update()` updates your plugin when something has changed, for example when the user entered or selected some text.
- `destroy()` cleans up after the plugin.

While the view plugin in the example works, it doesn't do much. If you want to better understand what causes the plugin to update, you can add a `console.log(update);` line to the `update()` method to print all updates to the console.

Provide [[Decorations]] from your view plugin to change how to display the document.

If you want to change how a Markdown document is rendered in Reading view, you can add your own _Markdown post processor_. As indicated by the name, the post processor runs _after_ the Markdown has been processed into HTML. It lets you add, remove, or replace [[HTML elements]] to the rendered document.

The following example looks for any code block that contains a text between two colons, `:`, and replaces it with an appropriate emoji:

```ts

const ALL_EMOJIS: Record<string, string> = {
  ":+1:": "👍",
  ":sunglasses:": "😎",
  ":smile:": "😄",
};

    this.registerMarkdownPostProcessor((element, context) => {
      const codeblocks = element.findAll("code");

      for (let codeblock of codeblocks) {
        const text = codeblock.innerText.trim();
        if (text[0] === ":" && text[text.length - 1] === ":") {
          const emojiEl = codeblock.createSpan({
            text: ALL_EMOJIS[text] ?? text,
          });
          codeblock.replaceWith(emojiEl);
        }
      }
    });
  }
}
```

docs/obsidian-developer/Plugins/Editor/Markdown post processing.md

## Post-process Markdown code blocks

Did you know that you can create [Mermaid](https://mermaid-js.github.io/) diagrams in Obsidian by creating a `mermaid` code block with a text definition like this one?:

````md
    Start --> Stop
```
````

If you change to Preview mode, the text in the code block becomes the following diagram:

```

If you want to add your own custom code blocks like the Mermaid one, you can use [[registerMarkdownCodeBlockProcessor|registerMarkdownCodeBlockProcessor()]]. The following example renders a code block with CSV data, as a table:

```ts

    this.registerMarkdownCodeBlockProcessor("csv", (source, el, ctx) => {
      const rows = source.split("\n").filter((row) => row.length > 0);

      const table = el.createEl("table");
      const body = table.createEl("tbody");

      for (let i = 0; i < rows.length; i++) {
        const cols = rows[i].split(",");

        const row = body.createEl("tr");

        for (let j = 0; j < cols.length; j++) {
          row.createEl("td", { text: cols[j] });
        }
      }
    });
  }
}
```

### Obsidian App and Obsidian Publish are different contexts

Obsidian Publish shares common code and UI principles with Obsidian App, but also has some important differences that you should consider when creating themes. A few rules of thumb to keep in mind:

- Avoid complex selectors, use the available [[CSS variables]] instead.
- Avoid including CSS selectors and rules that are specific to Obsidian App.
- Keep CSS file size small so it loads fast for visitors.
- Consider compatibility across browsers and screen sizes.

### App-specific and Publish-specific CSS rules

While Obsidian App and Obsidian Publish share some common code, most App themes are designed to target CSS classes that are not present in the Publish context. For this reason, we recommend building Publish themes from the ground up, to minimize the amount of unnecessary code.

### File size

Obsidian App themes are stored locally on the user's device, whereas Obsidian Publish themes are loaded each time a user vists the site. For this reason, Obsidian Publish themes should be mindful of file size.

Keeping your theme file small will avoid [flashes of unstyled content](https://en.wikipedia.org/wiki/Flash_of_unstyled_content), and load faster on a variety of devices and internet connections. Ideally your `publish.css` file should be as small as possible.

In the App context it is acceptable to embed fonts and images in the CSS file using base64 encoding. In the Publish context, we recommend that you avoid this approach, especially if it leads to larger file sizes (multiple megabytes) that may block rendering when a visitor accesses the site.

docs/obsidian-developer/Themes/Obsidian Publish themes/Best practices for Publish themes.md

### Browser compatibility

Visitors to Publish sites may use older browsers that are not compatible with new CSS features. For this reason we recommend being conservative with advanced CSS features in the Publish context. This is in contrast to Obsidian App themes which target a narrow scope of rendering engines (recent versions of Chromium/Blink) that support newer browser features. Try searching [caniuse.com](https://caniuse.com/) to see which CSS features are broadly available across browsers.

### Small screens and mobile devices

Obsidian Publish has two breakpoints by default:

| Breakpoint | Device | Effect | 
| ----------- | - | - |
| 1000px | Tablet | Right sidebar is hidden |
| 750px | Mobile | Left and right sidebars are hidden. If enabled, navigation is accessible via hamburger menu in the top left corner |

You can target these devices using CSS. Any rules defined outside of the `@media` query will apply to all devices.

```css
@media screen and (min-width: 1000px) {
  /* ... rules and variables for screens larger than tablet */
}
@media screen and (max-width: 1000px) {
  /* ... rules and variables for tablet devices and smaller */
}
@media screen and (max-width: 750px) {
  /* ... rules and variables for mobile devices and smaller */
}
```

You can build themes for your [Obsidian Publish](https://help.obsidian.md/Obsidian+Publish/Introduction+to+Obsidian+Publish) site. Themes for Obsidian Publish use the same [[CSS variables]] as the Obsidian app along with [[CSS variables#Obsidian Publish|Publish-specific CSS variables]].

> [!tip] See [[Build a theme]] for more in-depth information on the `body`, `:root`, `.theme-dark`, and `.theme-light` selectors.

To build a theme for your site:

1. Add a file called `publish.css` to the root folder of your vault.
2. Publish `publish.css` to enable the theme on your live Publish site.

```css
:root {
  --input-unfocused-border-color: transparent;
  --input-disabled-border-color: transparent;
  --input-hover-border-color: black;
  
  /* ... By default, nothing is placed within :root in Publish. However, CSS variables here are considered global, and accessible to all sub-elements such as body and .theme-light. */
}

.published-container {
  --page-width: 800px;
  --page-side-padding: 48px;
  
  /* ... CSS variables for Publish that do not change when light or dark mode is enabled. They sometimes link to color variables in .theme-light or .theme-dark */
}
.body {
  --inline-title-color: var(--h1-color);
  --h2-color: red;

  /* ... CSS variables that do not change when light or dark mode is enabled. They sometimes link to color variables in .theme-light or .theme-dark */
}
.theme-light {
  --background-primary: #ebf2ff;
  --h1-color: #000000;
  
  /* ... CSS color variables for when light mode is enabled */
}
.theme-dark {
  --background-primary: #1f2a3f;
  --h1-color: #ffffff;
  
  /* ... CSS color variables for when dark mode is enabled */
}
```

For more information on how to customize your site, refer to [Customize your site](https://help.obsidian.md/Obsidian+Publish/Customize+your+site).

docs/obsidian-developer/Themes/Obsidian Publish themes/Build a Publish theme.md

Obsidian Publish gives you several options for customizing how your Publish site looks.

Obsidian Publish allows you to customize the look of your site using CSS.

The following elements can be turned on or off in the Publish site settings and influence the layout of the site.

#### Reading experience

- **Readable line length** sets a maximum width for notes and centers the content on wide screens.
- **Theme toggle** displays a switch for light and dark mode.
- **Stacked notes** enables notes to stack and scroll horizontally when links are clicked, similar to [Tab stacks](https://help.obsidian.md/User+interface/Use+tabs+in+Obsidian#Stack+tab+groups) in the Obsidian app.

#### Components

- **Navigation** adds a left sidebar similar with a list of folders and files.
- **Search** displays a search input field, it may be positioned in the left sidebar, right sidebar or top navigation depending on which UI elements are active.
- **Backlinks** displays a list of backlinks at the bottom of the page.
- **Graph** displays the local graph in the right sidebar.
- **Table of contents** displays an outline of headings in the current page in the right sidebar.

## CSS variables

Theming for Obsidian Publish is made simple with CSS variables. [Learn more about CSS variables and how to use them.](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties)

The list of [[CSS variables]] available for customization fall into two groups:

- **App variables** are inherited from the Obsidian app theme. These primarily control the colors and styling of the content.
- **Publish-specific variables** control the elements specific to Obsidian Publish.

docs/obsidian-developer/Themes/Obsidian Publish themes/About Obsidian Publish themes.md

If you want to share your theme with the Obsidian community, the best way is to submit it to the [official list of themes](https://github.com/obsidianmd/obsidian-releases/blob/master/community-css-themes.json). Once we've reviewed and published your theme, users can install it directly from within Obsidian. It'll also be featured in the [plugin directory](https://obsidian.md/plugins) on the Obsidian website.

You only need to submit the initial version of your theme. After your theme has been published, users can automatically download new releases from GitHub directly from within Obsidian.

Before you submit your theme, make sure you have the following files in the root folder of your repository:

- A `README.md` that describes the theme.
- A `LICENSE` that determines how others are allowed to use the theme and its source code. If you need help to pick a license for your theme, refer to [Choose a License](https://choosealicense.com/).
- A screenshot of your theme to be displayed in the community theme store. Recommended image dimensions: 512 x 288 pixels.
- A `manifest.json` that describes your theme. For more information, refer to [[Manifest]].

## Step 1: Publish your theme to GitHub

> If you created your theme from one of our template repositories, you may skip this step.

To review your theme, we need to access to the source code on GitHub. If you're unfamiliar with GitHub, refer to the GitHub docs for how to [Create a new repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-new-repository).

## Step 2: Submit your theme for review

In this step, you'll submit your theme to the Obsidian team for review.

1. In [community-css-themes.json](https://github.com/obsidianmd/obsidian-releases/edit/master/community-css-themes.json), add a new entry at the end of the JSON array. The following example shows the entry for the [Minimal](https://github.com/kepano/obsidian-minimal) theme.

   ```json
   {
     "name": "Minimal",
     "author": "kepano",
     "repo": "kepano/obsidian-minimal",
     "screenshot": "dark-simple.png",
     "modes": ["dark", "light"]
   },

```

   - `name` and `author` determines how your plugin appears to the user, and should match the corresponding properties in your [[Manifest]].
   - `screenshot` is the path to a screenshot of your theme. The screenshot looks best with a 16:9 aspect ratio. Recommended image dimensions: 512 x 288 pixels.
   - `modes` lists the color modes that your theme supports.

5. Select **Preview**, and then select **Community Theme**.
7. In the name of the pull request, enter "Add [...] theme", where [...] is the name of your theme.

You've now submitted your theme to the Obsidian theme directory. Sit back and wait for us to review your submission.

> [!question] How long does it take to review my theme?
> The time it takes to review your submission depends on the current workload of the Obsidian team. The team is still small, so please be patient while you wait for your theme to be reviewed. We're currently unable to give any estimates on when we'll be able to review your submission.

Once a reviewer has reviewed your theme, they'll add a comment to your pull request with the result of the review. The reviewer may require that you update your theme, or they can offer suggestions on how you can improve it.

We'll publish the theme as soon we've verified that all required changes have been addressed.

> [!note]
> While only Obsidian team members can publish your theme, other community members may also offer to review your submission in the meantime.

Once we've reviewed and published your theme, it's time to announce it to the community:

In this tutorial, you'll learn how to start developing a theme for Obsidian. Themes let you customize how Obsidian looks and feels, using CSS.

- Configure an environment for developing Obsidian themes.
- Use CSS variables to change how Obsidian looks.
- Create a theme that supports both light and dark color schemes.

## Step 1: Download the sample theme

In this step, you'll download a sample theme to the `themes` directory in your vault's [`.obsidian` directory](https://help.obsidian.md/Advanced+topics/How+Obsidian+stores+data#Per+vault+data) so that Obsidian can find it.

The sample theme you'll use in this tutorial is available in a [GitHub repository](https://github.com/obsidianmd/obsidian-sample-theme).

1. Open a terminal window and change the project directory to the `themes` directory.

   ```bash
   cd path/to/vault/.obsidian/themes
   ```

2. Clone the sample theme using Git.

   ```bash
   git clone https://github.com/obsidianmd/obsidian-sample-theme.git "Sample Theme"
   ```

> The repository for the sample theme is a GitHub template repository, which means you can create your own repository from the sample theme. To learn how, refer to [Creating a repository from a template](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template#creating-a-repository-from-a-template).
>
> Remember to use the URL to your own repository when cloning the sample theme.

## Step 2: Enable the theme

1. In Obsidian, open **Settings**.
2. In the side menu, select **Appearance**.
3. Next to **Themes**, select **Sample Theme** from the dropdown list.

You've enabled the sample theme. Next, we'll make some changes to it.

## Step 3: Update the manifest

In this step, you'll rename the theme by updating the manifest, `manifest.json`. The manifest contains information about your theme, such as its name and description.

2. Change `name` to a human-friendly name, such as `"Disco Lights"`.
3. Rename the theme directory under `themes` to the same name. The name of the theme directory must exactly match the `name` property in `manifest.json`.

   ```bash
   mv "Sample Theme" "Disco Lights"
   ```

4. Restart Obsidian to load the new changes to the manifest.

Go back to **Settings → Appearance → Themes** and notice that the name of the theme has been changed.

## Step 4: Change the font

Obsidian uses [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties) to style the user interface. In this step, you'll use a CSS variable to change the font in the editor.

1. Create a new note, for example "Theme Development".
2. Enter the following text into the note:

   ```md
   Themes let you make [Obsidian](https://obsidian.md) look the way **you** want it.
   ```

3. In `theme.css`, add the following:

   ```css
   body {
     --font-text-theme: Georgia, serif;
   }
   ```

The editor displays the note using the font you defined.

## Step 5: Change the background color

Themes can support both light and dark color schemes. Define your CSS variables under `.theme-dark` or `.theme-light`.

1. In `theme.css`, add the following:

   ```css
   .theme-dark {
     --background-primary: #18004F;
     --background-secondary: #220070;
   }

   .theme-light {
     --background-primary: #ECE4FF;
     --background-secondary: #D9C9FF;
   }
   ```

2. In Obsidian, open **Settings**.
3. Under **Appearance**, toggle **Base color scheme** between "Light" and "Dark".

You'll see that Obsidian picks the colors based on the color scheme you've selected. Try changing the colors to `red`, `green`, or `blue` for a more dramatic change.

## Step 6: Change the input hover border color

The `:root` selector is commonly used when you want a variable to be accessible by every child element within the theme. This selector is often filled with Plugin variables.

Here's an example to illustrate its usage:

> [!example]
> Let's consider an input field that can be found in various places within Obsidian, such as settings and note content. To define the variables specific to this input field, we can use the `:root` selector.
>
> ```css
> :root {
>    --input-focus-border-color: Highlight;
>    --input-focus-outline: 1px solid Canvas;
>    --input-unfocused-border-color: transparent;
>    --input-disabled-border-color: transparent;
>    --input-hover-border-color: black;
>    /* Default Input Variables for Root */
 > }
 > ```

Now, let's modify the hover border color in our CSS:

```css
:root {
   --input-hover-border-color: red;
/* Change from Black to Red */
}
```

With this update, when you hover over any input field, the border color will change to a bright red.

> [!tip]
> When defining styles that should remain the same for both light and dark themes, it is recommended to use the `body` selector.
>
> Only use `.theme-dark` or `.theme-light` selectors if you want the styles to change when switching between light and dark themes.
>
> It's also important to use `:root` with caution and consideration. If your variable can be placed within `body`, `.theme-dark`, or `.theme-light` selectors instead, it is recommended to do so.

## Step 7: Discover CSS variables in use

Obsidian exposes more than 400 different CSS variables for customizing different parts of the user interface. In this step, you'll find the CSS variable for changing the ribbon background.

1. In Obsidian, open the **Developer Tools** by pressing `Ctrl`+`Shift`+`I` (or `Cmd`+`Option`+`I` on macOS).
2. Open the **Sources** tab.
3. Under **Page → top → obsidian.md**, select **app.css**.
4. Scroll to the top of `app.css` to find all available CSS variables.
5. Search for variables related to the ribbon by pressing `Ctrl`+`F` (or `Cmd`+`F` on macOS) and typing "  --ribbon-". Notice the two blank spaces, which return the definitions rather than their uses.

One of the results is `--ribbon-background`, which sounds promising. To be sure, you can also inspect the HTML to find the CSS variable used by a specific element.

1. In the upper-left corner of the **Developer Tool**, select the icon that looks like a cursor on top of a rectangle.
2. Select the middle of the ribbon on the left side of the Obsidian window.

In the **Styles** tab, on the right side of the **Developer Tools**, you can now see the CSS that is applied to the element you selected, such as `background-color: var(--ribbon-background)`.

Now that you know `--ribbon-background` controls the ribbon background color, add the following to `theme.css`:

```css
body {
  --ribbon-background: magenta;
}
```

In this tutorial, you've built your first Obsidian theme. You've modified the theme and reloaded it to reflect the changes inside Obsidian. You've also seen how you can find the CSS variables to style specific parts of the user interface.

Learn how to include assets, such as fonts and images, in your theme.

> [!warning] Loading remote content
> For Obsidian to work offline and to preserve user privacy, themes [[Developer policies|aren't allowed]] to load remote content over the network. For more information, refer to [[Theme guidelines#Keep resources local]]

## Use data URLs

To include assets such as fonts, icons, and images in your theme, you need to _embed_ them in the CSS file by passing a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs) to the [url()](https://developer.mozilla.org/en-US/docs/Web/CSS/url) function.

To create a data URL for your assets, create a URL using the following format:

```css
url("data:<MIME_TYPE>;base64,<BASE64_DATA>")
```

- Replace `<MIME_TYPE>` with the MIME type for your asset. If you don't know it, refer to [Common MIME types](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types).
- Replace `<BASE64_DATA>` with the [Base64](https://en.wikipedia.org/wiki/Base64) encoded representation of your asset.

The following example embeds a GIF file as a background image:

```css
h1 {
  background-image: url("data:image/gif;base64,R0lGODdhAQADAPABAP////8AACwAAAAAAQADAAACAgxQADs=")
}
```

docs/obsidian-developer/Themes/App themes/Embed fonts and images in your theme.md

## Encode your assets

For instructions on how to encode an asset into base64, refer to [Encoding data into base64 format](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs#encoding_data_into_base64_format).

You can also use one of the many free online tools for encoding.

For fonts:

- [Woff2Base](https://hellogreg.github.io/woff2base/) for WOFF2 font files
- [Aspose](https://products.aspose.app/font/base64) supports a wide variety of font formats

For images:

- [WebSemantics](https://websemantics.uk/tools/image-to-data-uri-converter/) converts JPEG, JPG, GIF, PNG, SVG
- [Base64 Guru](https://base64.guru/converter/encode/image) supports a wide variety of image formats
- [Yoksel URL-encoder for SVG](https://yoksel.github.io/url-encoder/) optimized for SVG files

## Consider file size

Embedding assets increases the file size of your theme, which may lead to poor performance in the following situations:

- Downloading and updating your theme from the community theme directory.
- Loading and using your theme in the Obsidian app.
- Editing your theme in a code editor. Consider breaking up your theme into multiple files using a CSS preprocessor, such as [Sass](https://sass-lang.com/) or [Less](https://lesscss.org/).

This page lists our recommendations for building themes that are both reliable and maintainable. By following these guidelines, you can minimize the maintenance work to keep your theme updated with future versions of Obsidian.

For more information about general guidelines for developers, refer to [[Developer policies]].

## Use CSS variables

Since most of Obsidian's user interface uses CSS variables, you can create highly expressive themes by merely overriding the built-in CSS variables.

Override general variables under `body`, and colors under `.theme-light` or `.theme-dark`.

```css
:root {
  --input-focus-border-color: Highlight;
}

body {
  --font-text-size: 18px;
}

  --background-primary: white;
}

  --background-primary: black;
}
```

## Use selectors with low specificity

Avoid overly complex selectors targeting specific classes. [[#Use CSS variables]] to keep your selectors simple.

The most common issues when maintaining a theme are due to broken selectors as a result of new versions of Obsidian, which may change class names and how elements are nested.

## Keep assets local

Per [[Developer policies]] community themes must not load remote assets, such as fonts and images, that are unavailable when the user is offline. Even if the user has access to the internet, loading remote assets may violate user privacy.

If you wish to submit your theme to the official Community Themes directory, your theme must not make network calls, and therefore all resources must be bundled into your theme. See our guide [[Embed fonts and images in your theme]].

## Avoid `!important` declarations

Declaring styles as `!important` prevents users from overriding styles from your theme using snippets.

Manually releasing your theme can be time-consuming and error-prone. In this guide, you'll configure your theme to use [GitHub Actions](https://github.com/features/actions) to automatically create a release when you create a new tag.

1. In the root directory of your theme, create a file called `release.yml` under `.github/workflows` with the following content:

   ```yml
   name: Release Obsidian theme

   on:
     push:
       tags:
         - "*"

   jobs:
     build:

       steps:

           env:
           run: |

               --generate-notes \
               --draft \
               manifest.json theme.css
   ```

   ```bash
   ```

   ```bash

docs/obsidian-developer/Themes/App themes/Release your theme with GitHub Actions.md

```

   ```bash
   ```

You've successfully set up your theme to automatically create a GitHub release whenever you create a new tag.

- If this is the first release for this theme, you're now ready to [[Submit your theme]].
- If this is an update to an already published theme, your users can now update to the latest version.

<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[`WorkspaceWindowInitData`](obsidian.WorkspaceWindowInitData.md)

## WorkspaceWindowInitData interface

**Signature:**

```typescript
export interface WorkspaceWindowInitData 
```

|  Property | Modifiers | Type | Description |
|  --- | --- | --- | --- |
|  [`size?`](obsidian.WorkspaceWindowInitData.size.md) |  | <code>{         width: number;         height: number;     }</code> | _(Optional)_ The suggested size |

[`EditorRange`](obsidian.EditorRange.md)

## EditorRange interface

export interface EditorRange 
```

|  [`from`](obsidian.EditorRange.from.md) |  | [`EditorPosition`](obsidian.EditorPosition.md) |  |
|  [`to`](obsidian.EditorRange.to.md) |  | [`EditorPosition`](obsidian.EditorPosition.md) |  |

[`setTooltip`](obsidian.setTooltip.md)

## setTooltip() function

export function setTooltip(el: HTMLElement, tooltip: string, options?: TooltipOptions): void;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  <code>el</code> | <code>HTMLElement</code> | The element to show the tooltip on |
|  <code>tooltip</code> | <code>string</code> | The tooltip text to show |
|  <code>options</code> | [`TooltipOptions`](obsidian.TooltipOptions.md) | _(Optional)_ |

**Returns:**

`void`

[`parseFrontMatterTags`](obsidian.parseFrontMatterTags.md)

## parseFrontMatterTags() function

export function parseFrontMatterTags(frontmatter: any | null): string[] | null;
```

|  <code>frontmatter</code> | <code>any &#124; null</code> |  |

`string[] | null`

[`MarkdownPreviewRenderer`](obsidian.MarkdownPreviewRenderer.md)

## MarkdownPreviewRenderer class

export class MarkdownPreviewRenderer 
```

## Methods

|  Method | Modifiers | Description |
|  [`createCodeBlockPostProcessor(language, handler)`](obsidian.MarkdownPreviewRenderer.createCodeBlockPostProcessor.md) | <code>static</code> |  |
|  [`registerPostProcessor(postProcessor, sortOrder)`](obsidian.MarkdownPreviewRenderer.registerPostProcessor.md) | <code>static</code> |  |
|  [`unregisterPostProcessor(postProcessor)`](obsidian.MarkdownPreviewRenderer.unregisterPostProcessor.md) | <code>static</code> |  |

[`addIcon`](obsidian.addIcon.md)

## addIcon() function

Adds an icon to the library.

export function addIcon(iconId: string, svgContent: string): void;
```

|  <code>iconId</code> | <code>string</code> | the icon ID |
|  <code>svgContent</code> | <code>string</code> | the content of the SVG. |

`void`

[`HexString`](obsidian.HexString.md)

## HexString type

Hex strings are 6-digit hash-prefixed rgb strings in lowercase form. Example: \#ffffff

export type HexString = string;
```

[`MenuSeparator`](obsidian.MenuSeparator.md)

## MenuSeparator class

export class MenuSeparator 
```

[`Stat`](obsidian.Stat.md)

## Stat interface

export interface Stat 
```

|  [`ctime`](obsidian.Stat.ctime.md) |  | <code>number</code> | Time of creation, represented as a unix timestamp. |
|  [`mtime`](obsidian.Stat.mtime.md) |  | <code>number</code> | Time of last modification, represented as a unix timestamp. |
|  [`size`](obsidian.Stat.size.md) |  | <code>number</code> | Size on disk, as bytes. |
|  [`type`](obsidian.Stat.type.md) |  | <code>'file' &#124; 'folder'</code> |  |

[`prepareFuzzySearch`](obsidian.prepareFuzzySearch.md)

## prepareFuzzySearch() function

Construct a fuzzy search callback that runs on a target string. Performance may be an issue if you are running the search for more than a few thousand times. If performance is a problem, consider using `prepareSimpleSearch` instead.

export function prepareFuzzySearch(query: string): (text: string) => SearchResult | null;
```

|  <code>query</code> | <code>string</code> | the fuzzy query.  fn - the callback function to apply the search on. |

`(text: string) => `[`SearchResult`](obsidian.SearchResult.md)` | null`

[`parseLinktext`](obsidian.parseLinktext.md)

## parseLinktext() function

export function parseLinktext(linktext: string): {
    path: string;
    subpath: string;
};
```

|  <code>linktext</code> | <code>string</code> |  |

`{     path: string;     subpath: string; }`

[`RGB`](obsidian.RGB.md)

## RGB interface

export interface RGB 
```

|  [`b`](obsidian.RGB.b.md) |  | <code>number</code> | Blue integer value between 0 and 255 |
|  [`g`](obsidian.RGB.g.md) |  | <code>number</code> | Green integer value between 0 and 255 |
|  [`r`](obsidian.RGB.r.md) |  | <code>number</code> | Red integer value between 0 and 255 |

[`SliderComponent`](obsidian.SliderComponent.md)

## SliderComponent class

export class SliderComponent extends ValueComponent<number> 
```
**Extends:** [`ValueComponent`](obsidian.ValueComponent.md)`<number>`

## Constructors

|  Constructor | Modifiers | Description |
|  [`(constructor)(containerEl)`](obsidian.SliderComponent.(constructor).md) |  | Constructs a new instance of the <code>SliderComponent</code> class |

|  [`sliderEl`](obsidian.SliderComponent.sliderEl.md) |  | <code>HTMLInputElement</code> |  |

## Methods

|  [`getValue()`](obsidian.SliderComponent.getValue.md) |  |  |
|  [`getValuePretty()`](obsidian.SliderComponent.getValuePretty.md) |  |  |
|  [`onChange(callback)`](obsidian.SliderComponent.onChange.md) |  |  |
|  [`setDisabled(disabled)`](obsidian.SliderComponent.setDisabled.md) |  |  |
|  [`setDynamicTooltip()`](obsidian.SliderComponent.setDynamicTooltip.md) |  |  |
|  [`setLimits(min, max, step)`](obsidian.SliderComponent.setLimits.md) |  |  |
|  [`setValue(value)`](obsidian.SliderComponent.setValue.md) |  |  |
|  [`showTooltip()`](obsidian.SliderComponent.showTooltip.md) |  |  |

[`WorkspaceItem`](obsidian.WorkspaceItem.md)

## WorkspaceItem class

export abstract class WorkspaceItem extends Events 
```
**Extends:** [`Events`](obsidian.Events.md)

## Methods

|  [`getContainer()`](obsidian.WorkspaceItem.getContainer.md) |  | Get the root container parent item, which can be one of: - [WorkspaceRoot](obsidian.WorkspaceRoot.md) - [WorkspaceWindow](obsidian.WorkspaceWindow.md) |
|  [`getRoot()`](obsidian.WorkspaceItem.getRoot.md) |  |  |

[`MarkdownSubView`](obsidian.MarkdownSubView.md)

## MarkdownSubView interface

export interface MarkdownSubView 
```

## Methods

|  Method | Description |
|  --- | --- |
|  [`applyScroll(scroll)`](obsidian.MarkdownSubView.applyScroll.md) |  |
|  [`get()`](obsidian.MarkdownSubView.get.md) |  |
|  [`getScroll()`](obsidian.MarkdownSubView.getScroll.md) |  |
|  [`set(data, clear)`](obsidian.MarkdownSubView.set.md) |  |

[`Modal`](obsidian.Modal.md)

## Modal class

export class Modal implements CloseableComponent 
```
**Implements:** [`CloseableComponent`](obsidian.CloseableComponent.md)

|  [`(constructor)(app)`](obsidian.Modal.(constructor).md) |  | Constructs a new instance of the <code>Modal</code> class |

|  [`app`](obsidian.Modal.app.md) |  | [`App`](obsidian.App.md) |  |
|  [`containerEl`](obsidian.Modal.containerEl.md) |  | <code>HTMLElement</code> |  |
|  [`contentEl`](obsidian.Modal.contentEl.md) |  | <code>HTMLElement</code> |  |
|  [`modalEl`](obsidian.Modal.modalEl.md) |  | <code>HTMLElement</code> |  |
|  [`scope`](obsidian.Modal.scope.md) |  | [`Scope`](obsidian.Scope.md) |  |
|  [`shouldRestoreSelection`](obsidian.Modal.shouldRestoreSelection.md) |  | <code>boolean</code> |  |
|  [`titleEl`](obsidian.Modal.titleEl.md) |  | <code>HTMLElement</code> |  |

## Methods

|  [`close()`](obsidian.Modal.close.md) |  |  |
|  [`onClose()`](obsidian.Modal.onClose.md) |  |  |
|  [`onOpen()`](obsidian.Modal.onOpen.md) |  |  |
|  [`open()`](obsidian.Modal.open.md) |  |  |

[`MarkdownFileInfo`](obsidian.MarkdownFileInfo.md)

## MarkdownFileInfo interface

export interface MarkdownFileInfo extends HoverParent 
```
**Extends:** [`HoverParent`](obsidian.HoverParent.md)

|  [`app`](obsidian.MarkdownFileInfo.app.md) |  | [`App`](obsidian.App.md) |  |
|  [`editor?`](obsidian.MarkdownFileInfo.editor.md) |  | [`Editor`](obsidian.Editor.md) | _(Optional)_ |

[`Reference`](obsidian.Reference.md)

## Reference interface

export interface Reference 
```

|  [`displayText?`](obsidian.Reference.displayText.md) |  | <code>string</code> | _(Optional)_ if title is different than link text, in the case of \[\[page name\|display name\]\] |
|  [`link`](obsidian.Reference.link.md) |  | <code>string</code> |  |
|  [`original`](obsidian.Reference.original.md) |  | <code>string</code> |  |

[`MomentFormatComponent`](obsidian.MomentFormatComponent.md)

## MomentFormatComponent class

export class MomentFormatComponent extends TextComponent 
```
**Extends:** [`TextComponent`](obsidian.TextComponent.md)

|  [`sampleEl`](obsidian.MomentFormatComponent.sampleEl.md) |  | <code>HTMLElement</code> |  |

## Methods

|  [`onChanged()`](obsidian.MomentFormatComponent.onChanged.md) |  |  |
|  [`setDefaultFormat(defaultFormat)`](obsidian.MomentFormatComponent.setDefaultFormat.md) |  | Sets the default format when input is cleared. Also used for placeholder. |
|  [`setSampleEl(sampleEl)`](obsidian.MomentFormatComponent.setSampleEl.md) |  |  |
|  [`setValue(value)`](obsidian.MomentFormatComponent.setValue.md) |  |  |
|  [`updateSample()`](obsidian.MomentFormatComponent.updateSample.md) |  |  |

[`htmlToMarkdown`](obsidian.htmlToMarkdown.md)

## htmlToMarkdown() function

Converts HTML to Markdown using Turndown Service.

export function htmlToMarkdown(html: string | HTMLElement | Document | DocumentFragment): string;
```

|  <code>html</code> | <code>string &#124; </code><code>HTMLElement</code><code> &#124; </code><code>Document</code><code> &#124; </code><code>DocumentFragment</code> |  |

`string`

[`Plugin\_2`](obsidian.Plugin.md)

## Plugin\_2 class

export abstract class Plugin extends Component 
```
**Extends:** [`Component`](obsidian.Component.md)

|  [`(constructor)(app, manifest)`](obsidian.Plugin.(constructor).md) |  | Constructs a new instance of the <code>Plugin</code> class |

|  [`app`](obsidian.Plugin.app.md) |  | [`App`](obsidian.App.md) |  |
|  [`manifest`](obsidian.Plugin.manifest.md) |  | [`PluginManifest`](obsidian.PluginManifest.md) |  |

|  [`addCommand(command)`](obsidian.Plugin.addCommand.md) |  | Register a command globally. Registered commands will be available from the @<!-- -->{<!-- -->link https://help.obsidian.md/Plugins/Command+palette Command pallete<!-- -->}<!-- -->. The command id and name will be automatically prefixed with this plugin's id and name. |
|  [`addRibbonIcon(icon, title, callback)`](obsidian.Plugin.addRibbonIcon.md) |  | Adds a ribbon icon to the left bar. |
|  [`addSettingTab(settingTab)`](obsidian.Plugin.addSettingTab.md) |  | Register a settings tab, which allows users to change settings. |
|  [`addStatusBarItem()`](obsidian.Plugin.addStatusBarItem.md) |  | Adds a status bar item to the bottom of the app. Not available on mobile. |
|  [`loadData()`](obsidian.Plugin.loadData.md) |  | Load settings data from disk. Data is stored in <code>data.json</code> in the plugin folder. |
|  [`registerCodeMirror(callback)`](obsidian.Plugin.registerCodeMirror.md) |  | Runs callback on all currently loaded instances of CodeMirror, then registers the callback for all future CodeMirror instances. |
|  [`registerEditorExtension(extension)`](obsidian.Plugin.registerEditorExtension.md) |  | Registers a CodeMirror 6 extension. To reconfigure cm6 extensions for a plugin on the fly, an array should be passed in, and modified dynamically. Once this array is modified, calling [Workspace.updateOptions()](obsidian.Workspace.updateOptions.md) will apply the changes. |
|  [`registerEditorSuggest(editorSuggest)`](obsidian.Plugin.registerEditorSuggest.md) |  | Register an EditorSuggest which can provide live suggestions while the user is typing. |
|  [`registerExtensions(extensions, viewType)`](obsidian.Plugin.registerExtensions.md) |  |  |
|  [`registerHoverLinkSource(id, info)`](obsidian.Plugin.registerHoverLinkSource.md) |  | Registers a view with the 'Page preview' core plugin as an emitter of the 'hover-link' on the event. |

|  [`registerMarkdownCodeBlockProcessor(language, handler, sortOrder)`](obsidian.Plugin.registerMarkdownCodeBlockProcessor.md) |  | Register a special post processor that handles fenced code given a language and a handler. This special post processor takes care of removing the <pre><code> and create a <div> that will be passed to the handler, and is expected to be filled with custom elements. |
|  [`registerMarkdownPostProcessor(postProcessor, sortOrder)`](obsidian.Plugin.registerMarkdownPostProcessor.md) |  | Registers a post processor, to change how the document looks in reading mode. |
|  [`registerObsidianProtocolHandler(action, handler)`](obsidian.Plugin.registerObsidianProtocolHandler.md) |  | Register a handler for obsidian:// URLs. |
|  [`registerView(type, viewCreator)`](obsidian.Plugin.registerView.md) |  |  |
|  [`saveData(data)`](obsidian.Plugin.saveData.md) |  | Write settings data to disk. Data is stored in <code>data.json</code> in the plugin folder. |

[`FileView`](obsidian.FileView.md)

## FileView class

export abstract class FileView extends ItemView 
```
**Extends:** [`ItemView`](obsidian.ItemView.md)

|  [`(constructor)(leaf)`](obsidian.FileView.(constructor).md) |  | Constructs a new instance of the <code>FileView</code> class |

|  [`allowNoFile`](obsidian.FileView.allowNoFile.md) |  | <code>boolean</code> |  |
|  [`file`](obsidian.FileView.file.md) |  | [`TFile`](obsidian.TFile.md)<code> &#124; null</code> |  |
|  [`navigation`](obsidian.FileView.navigation.md) |  | <code>boolean</code> | File views can be navigated by default.  |

## Methods

|  [`canAcceptExtension(extension)`](obsidian.FileView.canAcceptExtension.md) |  |  |
|  [`getDisplayText()`](obsidian.FileView.getDisplayText.md) |  |  |
|  [`getState()`](obsidian.FileView.getState.md) |  |  |
|  [`onload()`](obsidian.FileView.onload.md) |  |  |
|  [`onLoadFile(file)`](obsidian.FileView.onLoadFile.md) |  |  |
|  [`onRename(file)`](obsidian.FileView.onRename.md) |  |  |
|  [`onUnloadFile(file)`](obsidian.FileView.onUnloadFile.md) |  |  |
|  [`setState(state, result)`](obsidian.FileView.setState.md) |  |  |

[`setIcon`](obsidian.setIcon.md)

## setIcon() function

Insert an SVG into the element from an iconId. Does nothing if no icon associated with the iconId.

export function setIcon(parent: HTMLElement, iconId: IconName): void;
```

|  <code>parent</code> | <code>HTMLElement</code> | the HTML element to insert the icon |
|  <code>iconId</code> | [`IconName`](obsidian.IconName.md) | the icon ID |

`void`

[`App`](obsidian.App.md)

## App class

export class App 
```

|  [`fileManager`](obsidian.App.fileManager.md) |  | [`FileManager`](obsidian.FileManager.md) |  |
|  [`keymap`](obsidian.App.keymap.md) |  | [`Keymap`](obsidian.Keymap.md) |  |
|  [`lastEvent`](obsidian.App.lastEvent.md) |  | [`UserEvent`](obsidian.UserEvent.md)<code> &#124; null</code> | The last known user interaction event, to help commands find out what modifier keys are pressed. |
|  [`metadataCache`](obsidian.App.metadataCache.md) |  | [`MetadataCache`](obsidian.MetadataCache.md) |  |
|  [`scope`](obsidian.App.scope.md) |  | [`Scope`](obsidian.Scope.md) |  |
|  [`vault`](obsidian.App.vault.md) |  | [`Vault`](obsidian.Vault.md) |  |
|  [`workspace`](obsidian.App.workspace.md) |  | [`Workspace`](obsidian.Workspace.md) |  |

[`EditorPosition`](obsidian.EditorPosition.md)

## EditorPosition interface

export interface EditorPosition 
```

|  [`ch`](obsidian.EditorPosition.ch.md) |  | <code>number</code> |  |
|  [`line`](obsidian.EditorPosition.line.md) |  | <code>number</code> |  |

[`WorkspaceContainer`](obsidian.WorkspaceContainer.md)

## WorkspaceContainer class

export abstract class WorkspaceContainer extends WorkspaceSplit 
```
**Extends:** [`WorkspaceSplit`](obsidian.WorkspaceSplit.md)

|  [`doc`](obsidian.WorkspaceContainer.doc.md) | <code>abstract</code> | <code>Document</code> |  |
|  [`win`](obsidian.WorkspaceContainer.win.md) | <code>abstract</code> | <code>Window</code> |  |

[`editorLivePreviewField`](obsidian.editorLivePreviewField.md)

## editorLivePreviewField variable

Use this StateField to check whether Live Preview is active

editorLivePreviewField: StateField<boolean>
```

[`Menu`](obsidian.Menu.md)

## Menu class

export class Menu extends Component implements CloseableComponent 
```

|  [`(constructor)()`](obsidian.Menu.(constructor).md) |  | Constructs a new instance of the <code>Menu</code> class |

## Methods

|  [`addItem(cb)`](obsidian.Menu.addItem.md) |  | Adds a menu item. Only works when menu is not shown yet. |
|  [`addSeparator()`](obsidian.Menu.addSeparator.md) |  | Adds a separator. Only works when menu is not shown yet. |
|  [`close()`](obsidian.Menu.close.md) |  |  |
|  [`hide()`](obsidian.Menu.hide.md) |  |  |
|  [`onHide(callback)`](obsidian.Menu.onHide.md) |  |  |
|  [`setNoIcon()`](obsidian.Menu.setNoIcon.md) |  |  |
|  [`setUseNativeMenu(useNativeMenu)`](obsidian.Menu.setUseNativeMenu.md) |  | Force this menu to use native or DOM. (Only works on the desktop app) |
|  [`showAtMouseEvent(evt)`](obsidian.Menu.showAtMouseEvent.md) |  |  |
|  [`showAtPosition(position, doc)`](obsidian.Menu.showAtPosition.md) |  |  |

[`SubpathResult`](obsidian.SubpathResult.md)

## SubpathResult interface

export interface SubpathResult 
```

|  [`end`](obsidian.SubpathResult.end.md) |  | [`Loc`](obsidian.Loc.md)<code> &#124; null</code> |  |
|  [`start`](obsidian.SubpathResult.start.md) |  | [`Loc`](obsidian.Loc.md) |  |

[`loadPrism`](obsidian.loadPrism.md)

## loadPrism() function

Load Prism.js and return a promise to the global Prism object. Can also use `Prism` after this promise resolves to get the same reference.

export function loadPrism(): Promise<any>;
```

`Promise``<any>`

[`EditorSuggest`](obsidian.EditorSuggest.md)

## EditorSuggest class

export abstract class EditorSuggest<T> extends PopoverSuggest<T> 
```
**Extends:** [`PopoverSuggest`](obsidian.PopoverSuggest.md)`<T>`

|  [`(constructor)(app)`](obsidian.EditorSuggest.(constructor).md) |  | Constructs a new instance of the <code>EditorSuggest</code> class |

|  [`context`](obsidian.EditorSuggest.context.md) |  | [`EditorSuggestContext`](obsidian.EditorSuggestContext.md)<code> &#124; null</code> | Current suggestion context, containing the result of <code>onTrigger</code>. This will be null any time the EditorSuggest is not supposed to run. |
|  [`limit`](obsidian.EditorSuggest.limit.md) |  | <code>number</code> | Override this to use a different limit for suggestion items |

## Methods

|  [`getSuggestions(context)`](obsidian.EditorSuggest.getSuggestions.md) | <code>abstract</code> | Generate suggestion items based on this context. Can be async, but preferably sync. When generating async suggestions, you should pass the context along. |
|  [`onTrigger(cursor, editor, file)`](obsidian.EditorSuggest.onTrigger.md) | <code>abstract</code> | <p>Based on the editor line and cursor position, determine if this EditorSuggest should be triggered at this moment. Typically, you would run a regular expression on the current line text before the cursor. Return null to indicate that this editor suggest is not supposed to be triggered.</p><p>Please be mindful of performance when implementing this function, as it will be triggered very often (on each keypress). Keep it simple, and return null as early as possible if you determine that it is not the right time.</p> |
|  [`setInstructions(instructions)`](obsidian.EditorSuggest.setInstructions.md) |  |  |

[`SplitDirection`](obsidian.SplitDirection.md)

## SplitDirection type

export type SplitDirection = 'vertical' | 'horizontal';
```

[`ReferenceCache`](obsidian.ReferenceCache.md)

## ReferenceCache interface

export interface ReferenceCache extends Reference, CacheItem 
```
**Extends:** [`Reference`](obsidian.Reference.md)<!-- -->, [`CacheItem`](obsidian.CacheItem.md)

[`Point`](obsidian.Point.md)

## Point interface

export interface Point 
```

|  [`x`](obsidian.Point.x.md) |  | <code>number</code> |  |
|  [`y`](obsidian.Point.y.md) |  | <code>number</code> |  |

[`getBlobArrayBuffer`](obsidian.getBlobArrayBuffer.md)

## getBlobArrayBuffer() function

export function getBlobArrayBuffer(blob: Blob): Promise<ArrayBuffer>;
```

|  <code>blob</code> | <code>Blob</code> |  |

`Promise``<``ArrayBuffer``>`

[`WorkspaceRoot`](obsidian.WorkspaceRoot.md)

## WorkspaceRoot class

export class WorkspaceRoot extends WorkspaceContainer 
```
**Extends:** [`WorkspaceContainer`](obsidian.WorkspaceContainer.md)

|  [`doc`](obsidian.WorkspaceRoot.doc.md) |  | <code>Document</code> |  |
|  [`win`](obsidian.WorkspaceRoot.win.md) |  | <code>Window</code> |  |

[`SuggestModal`](obsidian.SuggestModal.md)

## SuggestModal class

export abstract class SuggestModal<T> extends Modal implements ISuggestOwner<T> 
```
**Extends:** [`Modal`](obsidian.Modal.md)

**Implements:** [`ISuggestOwner`](obsidian.ISuggestOwner.md)`<T>`

|  [`(constructor)(app)`](obsidian.SuggestModal.(constructor).md) |  | Constructs a new instance of the <code>SuggestModal</code> class |

|  [`emptyStateText`](obsidian.SuggestModal.emptyStateText.md) |  | <code>string</code> |  |
|  [`inputEl`](obsidian.SuggestModal.inputEl.md) |  | <code>HTMLInputElement</code> |  |
|  [`limit`](obsidian.SuggestModal.limit.md) |  | <code>number</code> |  |
|  [`resultContainerEl`](obsidian.SuggestModal.resultContainerEl.md) |  | <code>HTMLElement</code> |  |

## Methods

|  [`getSuggestions(query)`](obsidian.SuggestModal.getSuggestions.md) | <code>abstract</code> |  |
|  [`onChooseSuggestion(item, evt)`](obsidian.SuggestModal.onChooseSuggestion.md) | <code>abstract</code> |  |
|  [`onNoSuggestion()`](obsidian.SuggestModal.onNoSuggestion.md) |  |  |
|  [`renderSuggestion(value, el)`](obsidian.SuggestModal.renderSuggestion.md) | <code>abstract</code> |  |
|  [`selectSuggestion(value, evt)`](obsidian.SuggestModal.selectSuggestion.md) |  |  |
|  [`setInstructions(instructions)`](obsidian.SuggestModal.setInstructions.md) |  |  |
|  [`setPlaceholder(placeholder)`](obsidian.SuggestModal.setPlaceholder.md) |  |  |

[`Platform`](obsidian.Platform.md)

## Platform variable

Platform: {
    isDesktop: boolean;
    isMobile: boolean;
    isDesktopApp: boolean;
    isMobileApp: boolean;
    isIosApp: boolean;
    isAndroidApp: boolean;
    isPhone: boolean;
    isTablet: boolean;
    isMacOS: boolean;
    isWin: boolean;
    isLinux: boolean;
    isSafari: boolean;
    resourcePathPrefix: string;

}
```

[`ExtraButtonComponent`](obsidian.ExtraButtonComponent.md)

## ExtraButtonComponent class

export class ExtraButtonComponent extends BaseComponent 
```
**Extends:** [`BaseComponent`](obsidian.BaseComponent.md)

|  [`(constructor)(containerEl)`](obsidian.ExtraButtonComponent.(constructor).md) |  | Constructs a new instance of the <code>ExtraButtonComponent</code> class |

|  [`extraSettingsEl`](obsidian.ExtraButtonComponent.extraSettingsEl.md) |  | <code>HTMLElement</code> |  |

## Methods

|  [`onClick(callback)`](obsidian.ExtraButtonComponent.onClick.md) |  |  |
|  [`setDisabled(disabled)`](obsidian.ExtraButtonComponent.setDisabled.md) |  |  |
|  [`setIcon(icon)`](obsidian.ExtraButtonComponent.setIcon.md) |  |  |
|  [`setTooltip(tooltip, options)`](obsidian.ExtraButtonComponent.setTooltip.md) |  |  |

[`PopoverState`](obsidian.PopoverState.md)

## PopoverState enum

export enum PopoverState 
```

[`Vault`](obsidian.Vault.md)

## Vault class

Work with files and folders stored inside a vault.

export class Vault extends Events 
```

|  [`adapter`](obsidian.Vault.adapter.md) |  | [`DataAdapter`](obsidian.DataAdapter.md) |  |
|  [`configDir`](obsidian.Vault.configDir.md) |  | <code>string</code> | Gets the path to the config folder. This value is typically <code>.obsidian</code> but it could be different. |

|  [`append(file, data, options)`](obsidian.Vault.append.md) |  | Add text to the end of a plaintext file inside the vault. |
|  [`cachedRead(file)`](obsidian.Vault.cachedRead.md) |  | Read the content of a plaintext file stored inside the vault Use this if you only want to display the content to the user. If you want to modify the file content afterward use [Vault.read()](obsidian.Vault.read.md) |
|  [`copy(file, newPath)`](obsidian.Vault.copy.md) |  | Create a copy of the selected file. |
|  [`create(path, data, options)`](obsidian.Vault.create.md) |  | Create a new plaintext file inside the vault. |
|  [`createBinary(path, data, options)`](obsidian.Vault.createBinary.md) |  | Create a new binary file inside the vault. |
|  [`createFolder(path)`](obsidian.Vault.createFolder.md) |  | Create a new folder inside the vault. |
|  [`delete(file, force)`](obsidian.Vault.delete.md) |  | Deletes the file completely. |
|  [`getAbstractFileByPath(path)`](obsidian.Vault.getAbstractFileByPath.md) |  | Get a file or folder inside the vault. If you need a file, you should test the returned object with <code>instanceof TFile</code>. Otherwise, if you need a folder, you should test it with <code>instanceof TFolder</code>. |
|  [`getAllLoadedFiles()`](obsidian.Vault.getAllLoadedFiles.md) |  | Get all files and folders in the vault. |
|  [`getFiles()`](obsidian.Vault.getFiles.md) |  | Get all files in the vault. |
|  [`getMarkdownFiles()`](obsidian.Vault.getMarkdownFiles.md) |  | Get all markdown files in the vault. |
|  [`getName()`](obsidian.Vault.getName.md) |  | Gets the name of the vault. |
|  [`getResourcePath(file)`](obsidian.Vault.getResourcePath.md) |  | Returns an URI for the browser engine to use, for example to embed an image. |
|  [`getRoot()`](obsidian.Vault.getRoot.md) |  | Get the root folder of the current vault. |

|  [`modify(file, data, options)`](obsidian.Vault.modify.md) |  | Modify the contents of a plaintext file. |
|  [`modifyBinary(file, data, options)`](obsidian.Vault.modifyBinary.md) |  | Modify the contents of a binary file. |
|  [`on(name, callback, ctx)`](obsidian.Vault.on.md) |  | Called when a file is created. This is also called when the vault is first loaded for each existing file If you do not wish to receive create events on vault load, register your event handler inside [Workspace.onLayoutReady()](obsidian.Workspace.onLayoutReady.md)<!-- -->. |
|  [`on(name, callback, ctx)`](obsidian.Vault.on_1.md) |  | Called when a file is modified. |
|  [`on(name, callback, ctx)`](obsidian.Vault.on_2.md) |  | Called when a file is deleted. |
|  [`on(name, callback, ctx)`](obsidian.Vault.on_3.md) |  | Called when a file is renamed. |
|  [`process(file, fn, options)`](obsidian.Vault.process.md) |  | Atomically read, modify, and save the contents of a note. |
|  [`read(file)`](obsidian.Vault.read.md) |  | Read a plaintext file that is stored inside the vault, directly from disk. Use this if you intend to modify the file content afterwards. Use [Vault.cachedRead()](obsidian.Vault.cachedRead.md) otherwise for better performance. |
|  [`readBinary(file)`](obsidian.Vault.readBinary.md) |  | Read the content of a binary file stored inside the vault. |
|  [`recurseChildren(root, cb)`](obsidian.Vault.recurseChildren.md) | <code>static</code> |  |
|  [`rename(file, newPath)`](obsidian.Vault.rename.md) |  | Rename or move a file. |
|  [`trash(file, system)`](obsidian.Vault.trash.md) |  | Tries to move to system trash. If that isn't successful/allowed, use local trash |

[`MenuItem`](obsidian.MenuItem.md)

## MenuItem class

export class MenuItem 
```

## Methods

|  [`onClick(callback)`](obsidian.MenuItem.onClick.md) |  |  |
|  [`setChecked(checked)`](obsidian.MenuItem.setChecked.md) |  |  |
|  [`setDisabled(disabled)`](obsidian.MenuItem.setDisabled.md) |  |  |
|  [`setIcon(icon)`](obsidian.MenuItem.setIcon.md) |  |  |
|  [`setIsLabel(isLabel)`](obsidian.MenuItem.setIsLabel.md) |  |  |
|  [`setSection(section)`](obsidian.MenuItem.setSection.md) |  | Sets the section this menu item should belong in. To find the section IDs of an existing menu, inspect the DOM elements to see their <code>data-section</code> attribute. |
|  [`setTitle(title)`](obsidian.MenuItem.setTitle.md) |  |  |

[`BlockCache`](obsidian.BlockCache.md)

## BlockCache interface

export interface BlockCache extends CacheItem 
```
**Extends:** [`CacheItem`](obsidian.CacheItem.md)

|  [`id`](obsidian.BlockCache.id.md) |  | <code>string</code> |  |

[`getIcon`](obsidian.getIcon.md)

## getIcon() function

Create an SVG from an iconId. Returns null if no icon associated with the iconId.

export function getIcon(iconId: string): SVGSVGElement | null;
```

`SVGSVGElement`` | null`

[`TAbstractFile`](obsidian.TAbstractFile.md)

## TAbstractFile class

This can be either a `TFile` or a `TFolder`<!-- -->.

export abstract class TAbstractFile 
```

|  [`name`](obsidian.TAbstractFile.name.md) |  | <code>string</code> |  |
|  [`parent`](obsidian.TAbstractFile.parent.md) |  | [`TFolder`](obsidian.TFolder.md)<code> &#124; null</code> |  |
|  [`path`](obsidian.TAbstractFile.path.md) |  | <code>string</code> |  |
|  [`vault`](obsidian.TAbstractFile.vault.md) |  | [`Vault`](obsidian.Vault.md) |  |

[`UserEvent`](obsidian.UserEvent.md)

## UserEvent type

export type UserEvent = MouseEvent | KeyboardEvent | TouchEvent | PointerEvent;
```

[`EditorSelection`](obsidian.EditorSelection.md)

## EditorSelection interface

export interface EditorSelection 
```

|  [`anchor`](obsidian.EditorSelection.anchor.md) |  | [`EditorPosition`](obsidian.EditorPosition.md) |  |
|  [`head`](obsidian.EditorSelection.head.md) |  | [`EditorPosition`](obsidian.EditorPosition.md) |  |

[`stripHeadingForLink`](obsidian.stripHeadingForLink.md)

## stripHeadingForLink() function

This function prepares headings for linking. It strips out some bad combinations of special characters that could break links.

export function stripHeadingForLink(heading: string): string;
```

|  <code>heading</code> | <code>string</code> |  |

`string`

[`View`](obsidian.View.md)

## View class

export abstract class View extends Component 
```

|  [`(constructor)(leaf)`](obsidian.View.(constructor).md) |  | Constructs a new instance of the <code>View</code> class |

|  [`app`](obsidian.View.app.md) |  | [`App`](obsidian.App.md) |  |
|  [`containerEl`](obsidian.View.containerEl.md) |  | <code>HTMLElement</code> |  |
|  [`icon`](obsidian.View.icon.md) |  | [`IconName`](obsidian.IconName.md) |  |
|  [`leaf`](obsidian.View.leaf.md) |  | [`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) |  |
|  [`navigation`](obsidian.View.navigation.md) |  | <code>boolean</code> | Whether or not the view is intended for navigation. If your view is a static view that is not intended to be navigated away, set this to false. (For example: File explorer, calendar, etc.) If your view opens a file or can be otherwise navigated, set this to true. (For example: Markdown editor view, Kanban view, PDF view, etc.) |

## Methods

|  [`getDisplayText()`](obsidian.View.getDisplayText.md) | <code>abstract</code> |  |
|  [`getEphemeralState()`](obsidian.View.getEphemeralState.md) |  |  |
|  [`getIcon()`](obsidian.View.getIcon.md) |  |  |
|  [`getState()`](obsidian.View.getState.md) |  |  |
|  [`getViewType()`](obsidian.View.getViewType.md) | <code>abstract</code> |  |
|  [`onClose()`](obsidian.View.onClose.md) | <code>protected</code> |  |
|  [`onOpen()`](obsidian.View.onOpen.md) | <code>protected</code> |  |
|  [`onPaneMenu(menu, source)`](obsidian.View.onPaneMenu.md) |  | <p>Populates the pane menu.</p><p>(Replaces the previously removed <code>onHeaderMenu</code> and <code>onMoreOptionsMenu</code>)</p> |
|  [`onResize()`](obsidian.View.onResize.md) |  | Called when the size of this view is changed. |
|  [`setEphemeralState(state)`](obsidian.View.setEphemeralState.md) |  |  |
|  [`setState(state, result)`](obsidian.View.setState.md) |  |  |

[`getIconIds`](obsidian.getIconIds.md)

## getIconIds() function

Get the list of registered icons.

export function getIconIds(): IconName[];
```

[`IconName`](obsidian.IconName.md)`[]`

[`parseFrontMatterStringArray`](obsidian.parseFrontMatterStringArray.md)

## parseFrontMatterStringArray() function

export function parseFrontMatterStringArray(frontmatter: any | null, key: string | RegExp, nospaces?: boolean): string[] | null;
```

|  <code>key</code> | <code>string &#124; </code><code>RegExp</code> |  |
|  <code>nospaces</code> | <code>boolean</code> | _(Optional)_ |

[`SearchResult`](obsidian.SearchResult.md)

## SearchResult interface

export interface SearchResult 
```

|  [`matches`](obsidian.SearchResult.matches.md) |  | [`SearchMatches`](obsidian.SearchMatches.md) |  |
|  [`score`](obsidian.SearchResult.score.md) |  | <code>number</code> |  |

[`KeymapEventListener`](obsidian.KeymapEventListener.md)

## KeymapEventListener type

Return `false` to automatically preventDefault

export type KeymapEventListener = (evt: KeyboardEvent, ctx: KeymapContext) => false | any;
```
**References:** [`KeymapContext`](obsidian.KeymapContext.md)

[`BlockSubpathResult`](obsidian.BlockSubpathResult.md)

## BlockSubpathResult interface

export interface BlockSubpathResult extends SubpathResult 
```
**Extends:** [`SubpathResult`](obsidian.SubpathResult.md)

|  [`block`](obsidian.BlockSubpathResult.block.md) |  | [`BlockCache`](obsidian.BlockCache.md) |  |
|  [`list?`](obsidian.BlockSubpathResult.list.md) |  | [`ListItemCache`](obsidian.ListItemCache.md) | _(Optional)_ |
|  [`type`](obsidian.BlockSubpathResult.type.md) |  | <code>'block'</code> |  |

[`HeadingSubpathResult`](obsidian.HeadingSubpathResult.md)

## HeadingSubpathResult interface

export interface HeadingSubpathResult extends SubpathResult 
```

|  [`current`](obsidian.HeadingSubpathResult.current.md) |  | [`HeadingCache`](obsidian.HeadingCache.md) |  |
|  [`next`](obsidian.HeadingSubpathResult.next.md) |  | [`HeadingCache`](obsidian.HeadingCache.md) |  |
|  [`type`](obsidian.HeadingSubpathResult.type.md) |  | <code>'heading'</code> |  |

[`ViewCreator`](obsidian.ViewCreator.md)

## ViewCreator type

export type ViewCreator = (leaf: WorkspaceLeaf) => View;
```
**References:** [`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md)<!-- -->, [`View`](obsidian.View.md)

[`resolveSubpath`](obsidian.resolveSubpath.md)

## resolveSubpath() function

export function resolveSubpath(cache: CachedMetadata, subpath: string): HeadingSubpathResult | BlockSubpathResult;
```

|  <code>cache</code> | [`CachedMetadata`](obsidian.CachedMetadata.md) |  |
|  <code>subpath</code> | <code>string</code> |  |

[`HeadingSubpathResult`](obsidian.HeadingSubpathResult.md)` | `[`BlockSubpathResult`](obsidian.BlockSubpathResult.md)

[`TooltipPlacement`](obsidian.TooltipPlacement.md)

## TooltipPlacement type

export type TooltipPlacement = 'bottom' | 'right' | 'left' | 'top';
```

[`SettingTab`](obsidian.SettingTab.md)

## SettingTab class

export abstract class SettingTab 
```

|  [`app`](obsidian.SettingTab.app.md) |  | [`App`](obsidian.App.md) | Reference to the app instance. |
|  [`containerEl`](obsidian.SettingTab.containerEl.md) |  | <code>HTMLElement</code> | Outermost HTML element on the setting tab. |

## Methods

|  [`display()`](obsidian.SettingTab.display.md) | <code>abstract</code> | Called when the settings tab should be rendered. |
|  [`hide()`](obsidian.SettingTab.hide.md) |  | Hides the contents of the setting tab. Any registered components should be unloaded when the view is hidden. Override this if you need to perform additional cleanup. |

[`WorkspaceWindow`](obsidian.WorkspaceWindow.md)

## WorkspaceWindow class

export class WorkspaceWindow extends WorkspaceContainer 
```

|  [`doc`](obsidian.WorkspaceWindow.doc.md) |  | <code>Document</code> |  |
|  [`win`](obsidian.WorkspaceWindow.win.md) |  | <code>Window</code> |  |

[`loadPdfJs`](obsidian.loadPdfJs.md)

## loadPdfJs() function

Load PDF.js and return a promise to the global pdfjsLib object. Can also use `window.pdfjsLib` after this promise resolves to get the same reference.

export function loadPdfJs(): Promise<any>;
```

[`OpenViewState`](obsidian.OpenViewState.md)

## OpenViewState interface

export interface OpenViewState 
```

|  [`active?`](obsidian.OpenViewState.active.md) |  | <code>boolean</code> | _(Optional)_ |
|  [`eState?`](obsidian.OpenViewState.eState.md) |  | <code>any</code> | _(Optional)_ |
|  [`group?`](obsidian.OpenViewState.group.md) |  | [`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) | _(Optional)_ |
|  [`state?`](obsidian.OpenViewState.state.md) |  | <code>any</code> | _(Optional)_ |

[`RequestUrlParam`](obsidian.RequestUrlParam.md)

## RequestUrlParam interface

export interface RequestUrlParam 
```

|  [`body?`](obsidian.RequestUrlParam.body.md) |  | <code>string &#124; </code><code>ArrayBuffer</code> | _(Optional)_ |
|  [`contentType?`](obsidian.RequestUrlParam.contentType.md) |  | <code>string</code> | _(Optional)_ |
|  [`headers?`](obsidian.RequestUrlParam.headers.md) |  | <code>Record</code><code>&lt;string, string&gt;</code> | _(Optional)_ |
|  [`method?`](obsidian.RequestUrlParam.method.md) |  | <code>string</code> | _(Optional)_ |
|  [`throw?`](obsidian.RequestUrlParam.throw.md) |  | <code>boolean</code> | _(Optional)_ Whether to throw an error when the status code is 400+ Defaults to true |
|  [`url`](obsidian.RequestUrlParam.url.md) |  | <code>string</code> |  |

[`TFolder`](obsidian.TFolder.md)

## TFolder class

export class TFolder extends TAbstractFile 
```
**Extends:** [`TAbstractFile`](obsidian.TAbstractFile.md)

|  [`children`](obsidian.TFolder.children.md) |  | [`TAbstractFile`](obsidian.TAbstractFile.md)<code>[]</code> |  |

## Methods

|  [`isRoot()`](obsidian.TFolder.isRoot.md) |  |  |

[`getAllTags`](obsidian.getAllTags.md)

## getAllTags() function

export function getAllTags(cache: CachedMetadata): string[] | null;
```

[`Scope`](obsidian.Scope.md)

## Scope class

export class Scope 
```

|  [`(constructor)(parent)`](obsidian.Scope.(constructor).md) |  | Constructs a new instance of the <code>Scope</code> class |

## Methods

|  [`register(modifiers, key, func)`](obsidian.Scope.register.md) |  |  |
|  [`unregister(handler)`](obsidian.Scope.unregister.md) |  |  |

[`TooltipOptions`](obsidian.TooltipOptions.md)

## TooltipOptions interface

export interface TooltipOptions 
```

|  [`delay?`](obsidian.TooltipOptions.delay.md) |  | <code>number</code> | _(Optional)_ |
|  [`placement?`](obsidian.TooltipOptions.placement.md) |  | [`TooltipPlacement`](obsidian.TooltipPlacement.md) | _(Optional)_ |

[`prepareSimpleSearch`](obsidian.prepareSimpleSearch.md)

## prepareSimpleSearch() function

Construct a simple search callback that runs on a target string.

export function prepareSimpleSearch(query: string): (text: string) => SearchResult | null;
```

|  <code>query</code> | <code>string</code> | the space-separated words  fn - the callback function to apply the search on |

[`IconName`](obsidian.IconName.md)

## IconName type

export type IconName = string;
```

[`CachedMetadata`](obsidian.CachedMetadata.md)

## CachedMetadata interface

export interface CachedMetadata 
```

|  [`blocks?`](obsidian.CachedMetadata.blocks.md) |  | <code>Record</code><code>&lt;string, </code>[`BlockCache`](obsidian.BlockCache.md)<code>&gt;</code> | _(Optional)_ |
|  [`embeds?`](obsidian.CachedMetadata.embeds.md) |  | [`EmbedCache`](obsidian.EmbedCache.md)<code>[]</code> | _(Optional)_ |
|  [`frontmatter?`](obsidian.CachedMetadata.frontmatter.md) |  | [`FrontMatterCache`](obsidian.FrontMatterCache.md) | _(Optional)_ |
|  [`frontmatterLinks?`](obsidian.CachedMetadata.frontmatterLinks.md) |  | [`FrontmatterLinkCache`](obsidian.FrontmatterLinkCache.md)<code>[]</code> | _(Optional)_ |
|  [`frontmatterPosition?`](obsidian.CachedMetadata.frontmatterPosition.md) |  | [`Pos`](obsidian.Pos.md) | _(Optional)_ |
|  [`headings?`](obsidian.CachedMetadata.headings.md) |  | [`HeadingCache`](obsidian.HeadingCache.md)<code>[]</code> | _(Optional)_ |
|  [`links?`](obsidian.CachedMetadata.links.md) |  | [`LinkCache`](obsidian.LinkCache.md)<code>[]</code> | _(Optional)_ |
|  [`listItems?`](obsidian.CachedMetadata.listItems.md) |  | [`ListItemCache`](obsidian.ListItemCache.md)<code>[]</code> | _(Optional)_ |
|  [`sections?`](obsidian.CachedMetadata.sections.md) |  | [`SectionCache`](obsidian.SectionCache.md)<code>[]</code> | _(Optional)_ Sections are root level markdown blocks, which can be used to divide the document up. |
|  [`tags?`](obsidian.CachedMetadata.tags.md) |  | [`TagCache`](obsidian.TagCache.md)<code>[]</code> | _(Optional)_ |

[`finishRenderMath`](obsidian.finishRenderMath.md)

## finishRenderMath() function

Flush the MathJax stylesheet.

export function finishRenderMath(): Promise<void>;
```

`Promise``<void>`

[`renderResults`](obsidian.renderResults.md)

## renderResults() function

export function renderResults(el: HTMLElement, text: string, result: SearchResult, offset?: number): void;
```

|  <code>el</code> | <code>HTMLElement</code> |  |
|  <code>text</code> | <code>string</code> |  |
|  <code>result</code> | [`SearchResult`](obsidian.SearchResult.md) |  |
|  <code>offset</code> | <code>number</code> | _(Optional)_ |

`void`

[`hexToArrayBuffer`](obsidian.hexToArrayBuffer.md)

## hexToArrayBuffer() function

export function hexToArrayBuffer(hex: string): ArrayBuffer;
```

|  <code>hex</code> | <code>string</code> |  |

`ArrayBuffer`

[`RequestUrlResponsePromise`](obsidian.RequestUrlResponsePromise.md)

## RequestUrlResponsePromise interface

export interface RequestUrlResponsePromise extends Promise<RequestUrlResponse> 
```
**Extends:** `Promise``<`[`RequestUrlResponse`](obsidian.RequestUrlResponse.md)`>`

|  [`arrayBuffer`](obsidian.RequestUrlResponsePromise.arrayBuffer.md) |  | <code>Promise</code><code>&lt;</code><code>ArrayBuffer</code><code>&gt;</code> |  |
|  [`json`](obsidian.RequestUrlResponsePromise.json.md) |  | <code>Promise</code><code>&lt;any&gt;</code> |  |
|  [`text`](obsidian.RequestUrlResponsePromise.text.md) |  | <code>Promise</code><code>&lt;string&gt;</code> |  |

[`editorInfoField`](obsidian.editorInfoField.md)

## editorInfoField variable

Use this StateField to get information about this markdown editor, such as the associated file, or the Editor.

editorInfoField: StateField<MarkdownFileInfo>
```

[`EditorTransaction`](obsidian.EditorTransaction.md)

## EditorTransaction interface

export interface EditorTransaction 
```

|  [`changes?`](obsidian.EditorTransaction.changes.md) |  | [`EditorChange`](obsidian.EditorChange.md)<code>[]</code> | _(Optional)_ |
|  [`replaceSelection?`](obsidian.EditorTransaction.replaceSelection.md) |  | <code>string</code> | _(Optional)_ |
|  [`selection?`](obsidian.EditorTransaction.selection.md) |  | [`EditorRangeOrCaret`](obsidian.EditorRangeOrCaret.md) | _(Optional)_ |
|  [`selections?`](obsidian.EditorTransaction.selections.md) |  | [`EditorRangeOrCaret`](obsidian.EditorRangeOrCaret.md)<code>[]</code> | _(Optional)_ Multiple selections, overrides <code>selection</code>. |

[`TextComponent`](obsidian.TextComponent.md)

## TextComponent class

export class TextComponent extends AbstractTextComponent<HTMLInputElement> 
```
**Extends:** [`AbstractTextComponent`](obsidian.AbstractTextComponent.md)`<``HTMLInputElement``>`

|  [`(constructor)(containerEl)`](obsidian.TextComponent.(constructor).md) |  | Constructs a new instance of the <code>TextComponent</code> class |

[`EditorScrollInfo`](obsidian.EditorScrollInfo.md)

## EditorScrollInfo interface

export interface EditorScrollInfo 
```

|  [`clientHeight`](obsidian.EditorScrollInfo.clientHeight.md) |  | <code>number</code> |  |
|  [`clientWidth`](obsidian.EditorScrollInfo.clientWidth.md) |  | <code>number</code> |  |
|  [`height`](obsidian.EditorScrollInfo.height.md) |  | <code>number</code> |  |
|  [`left`](obsidian.EditorScrollInfo.left.md) |  | <code>number</code> |  |
|  [`top`](obsidian.EditorScrollInfo.top.md) |  | <code>number</code> |  |
|  [`width`](obsidian.EditorScrollInfo.width.md) |  | <code>number</code> |  |

[`LinkCache`](obsidian.LinkCache.md)

## LinkCache interface

export interface LinkCache extends ReferenceCache 
```
**Extends:** [`ReferenceCache`](obsidian.ReferenceCache.md)

[`WorkspaceRibbon`](obsidian.WorkspaceRibbon.md)

## WorkspaceRibbon class

export class WorkspaceRibbon 
```

[`ToggleComponent`](obsidian.ToggleComponent.md)

## ToggleComponent class

export class ToggleComponent extends ValueComponent<boolean> 
```
**Extends:** [`ValueComponent`](obsidian.ValueComponent.md)`<boolean>`

|  [`(constructor)(containerEl)`](obsidian.ToggleComponent.(constructor).md) |  | Constructs a new instance of the <code>ToggleComponent</code> class |

|  [`toggleEl`](obsidian.ToggleComponent.toggleEl.md) |  | <code>HTMLElement</code> |  |

## Methods

|  [`getValue()`](obsidian.ToggleComponent.getValue.md) |  |  |
|  [`onChange(callback)`](obsidian.ToggleComponent.onChange.md) |  |  |
|  [`onClick()`](obsidian.ToggleComponent.onClick.md) |  |  |
|  [`setDisabled(disabled)`](obsidian.ToggleComponent.setDisabled.md) |  |  |
|  [`setTooltip(tooltip, options)`](obsidian.ToggleComponent.setTooltip.md) |  |  |
|  [`setValue(on)`](obsidian.ToggleComponent.setValue.md) |  |  |

[`EventRef`](obsidian.EventRef.md)

## EventRef interface

export interface EventRef 
```

[`ListItemCache`](obsidian.ListItemCache.md)

## ListItemCache interface

export interface ListItemCache extends CacheItem 
```

|  [`id?`](obsidian.ListItemCache.id.md) |  | <code>string &#124; undefined</code> | _(Optional)_ The block ID of this list item, if defined. |
|  [`parent`](obsidian.ListItemCache.parent.md) |  | <code>number</code> | <p>Line number of the parent list item (position.start.line). If this item has no parent (e.g. it's a root level list), then this value is the negative of the line number of the first list item (start of the list).</p><p>Can be used to deduce which list items belongs to the same group (item1.parent === item2.parent). Can be used to reconstruct hierarchy information (parentItem.position.start.line === childItem.parent).</p> |
|  [`task?`](obsidian.ListItemCache.task.md) |  | <code>string &#124; undefined</code> | _(Optional)_ A single character indicating the checked status of a task. The space character <code>' '</code> is interpreted as an incomplete task. An other character is interpreted as completed task. <code>undefined</code> if this item isn't a task. |

[`HoverParent`](obsidian.HoverParent.md)

## HoverParent interface

export interface HoverParent 
```

|  [`hoverPopover`](obsidian.HoverParent.hoverPopover.md) |  | [`HoverPopover`](obsidian.HoverPopover.md)<code> &#124; null</code> |  |

[`ViewState`](obsidian.ViewState.md)

## ViewState interface

export interface ViewState 
```

|  [`active?`](obsidian.ViewState.active.md) |  | <code>boolean</code> | _(Optional)_ |
|  [`group?`](obsidian.ViewState.group.md) |  | [`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) | _(Optional)_ |
|  [`pinned?`](obsidian.ViewState.pinned.md) |  | <code>boolean</code> | _(Optional)_ |
|  [`state?`](obsidian.ViewState.state.md) |  | <code>any</code> | _(Optional)_ |
|  [`type`](obsidian.ViewState.type.md) |  | <code>string</code> |  |

[`SearchMatchPart`](obsidian.SearchMatchPart.md)

## SearchMatchPart type

Text position offsets within text file. Represents a text range \[from offset, to offset\].

export type SearchMatchPart = [number, number];
```

[`CloseableComponent`](obsidian.CloseableComponent.md)

## CloseableComponent interface

export interface CloseableComponent 
```

## Methods

|  --- | --- |
|  [`close()`](obsidian.CloseableComponent.close.md) |  |

[`iterateCacheRefs`](obsidian.iterateCacheRefs.md)

## iterateCacheRefs() function

> Warning: This API is now obsolete.
> 
> 

Iterate links and embeds. If callback returns true, the iteration process will be interrupted.

export function iterateCacheRefs(cache: CachedMetadata, cb: (ref: ReferenceCache) => boolean | void): boolean;
```

|  <code>cb</code> | <code>(ref: </code>[`ReferenceCache`](obsidian.ReferenceCache.md)<code>) =&gt; boolean &#124; void</code> |  |

`boolean`

true if callback ever returns true, false otherwise.

[`MarkdownPreviewView`](obsidian.MarkdownPreviewView.md)

## MarkdownPreviewView class

export class MarkdownPreviewView extends MarkdownRenderer implements MarkdownSubView, MarkdownPreviewEvents 
```
**Extends:** [`MarkdownRenderer`](obsidian.MarkdownRenderer.md)

**Implements:** [`MarkdownSubView`](obsidian.MarkdownSubView.md)<!-- -->, [`MarkdownPreviewEvents`](obsidian.MarkdownPreviewEvents.md)

|  [`containerEl`](obsidian.MarkdownPreviewView.containerEl.md) |  | <code>HTMLElement</code> |  |
|  [`file`](obsidian.MarkdownPreviewView.file.md) | <code>readonly</code> | [`TFile`](obsidian.TFile.md) |  |

## Methods

|  [`applyScroll(scroll)`](obsidian.MarkdownPreviewView.applyScroll.md) |  |  |
|  [`clear()`](obsidian.MarkdownPreviewView.clear.md) |  |  |
|  [`get()`](obsidian.MarkdownPreviewView.get.md) |  |  |
|  [`getScroll()`](obsidian.MarkdownPreviewView.getScroll.md) |  |  |
|  [`rerender(full)`](obsidian.MarkdownPreviewView.rerender.md) |  |  |
|  [`set(data, clear)`](obsidian.MarkdownPreviewView.set.md) |  |  |

[`MarkdownPreviewEvents`](obsidian.MarkdownPreviewEvents.md)

## MarkdownPreviewEvents interface

\*

export interface MarkdownPreviewEvents extends Component 
```

[`TFile`](obsidian.TFile.md)

## TFile class

export class TFile extends TAbstractFile 
```

|  [`basename`](obsidian.TFile.basename.md) |  | <code>string</code> |  |
|  [`extension`](obsidian.TFile.extension.md) |  | <code>string</code> |  |
|  [`stat`](obsidian.TFile.stat.md) |  | [`FileStats`](obsidian.FileStats.md) |  |

[`Workspace`](obsidian.Workspace.md)

## Workspace class

export class Workspace extends Events 
```

|  [`activeEditor`](obsidian.Workspace.activeEditor.md) |  | [`MarkdownFileInfo`](obsidian.MarkdownFileInfo.md)<code> &#124; null</code> | A component managing the current editor. This can be null if the active view has no editor. |
|  [`activeLeaf`](obsidian.Workspace.activeLeaf.md) |  | [`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md)<code> &#124; null</code> | <p>Indicates the currently focused leaf, if one exists.</p><p>Please avoid using <code>activeLeaf</code> directly, especially without checking whether <code>activeLeaf</code> is null.</p><p>The recommended alternatives are: - If you need information about the current view, use [Workspace.getActiveViewOfType()](obsidian.Workspace.getActiveViewOfType.md)<!-- -->. - If you need to open a new file or navigate a view, use [Workspace.getLeaf](obsidian.workspace.getleaf_1.md).</p> |
|  [`containerEl`](obsidian.Workspace.containerEl.md) |  | <code>HTMLElement</code> |  |
|  [`layoutReady`](obsidian.Workspace.layoutReady.md) |  | <code>boolean</code> |  |
|  [`leftRibbon`](obsidian.Workspace.leftRibbon.md) |  | [`WorkspaceRibbon`](obsidian.WorkspaceRibbon.md) |  |
|  [`leftSplit`](obsidian.Workspace.leftSplit.md) |  | [`WorkspaceSidedock`](obsidian.WorkspaceSidedock.md)<code> &#124; </code>[`WorkspaceMobileDrawer`](obsidian.WorkspaceMobileDrawer.md) |  |
|  [`requestSaveLayout`](obsidian.Workspace.requestSaveLayout.md) |  | [`Debouncer`](obsidian.Debouncer.md)<code>&lt;[], </code><code>Promise</code><code>&lt;void&gt;&gt;</code> |  |
|  [`rightRibbon`](obsidian.Workspace.rightRibbon.md) |  | [`WorkspaceRibbon`](obsidian.WorkspaceRibbon.md) |  |
|  [`rightSplit`](obsidian.Workspace.rightSplit.md) |  | [`WorkspaceSidedock`](obsidian.WorkspaceSidedock.md)<code> &#124; </code>[`WorkspaceMobileDrawer`](obsidian.WorkspaceMobileDrawer.md) |  |
|  [`rootSplit`](obsidian.Workspace.rootSplit.md) |  | [`WorkspaceRoot`](obsidian.WorkspaceRoot.md) |  |

|  [`changeLayout(workspace)`](obsidian.Workspace.changeLayout.md) |  |  |
|  [`createLeafBySplit(leaf, direction, before)`](obsidian.Workspace.createLeafBySplit.md) |  |  |
|  [`createLeafInParent(parent, index)`](obsidian.Workspace.createLeafInParent.md) |  |  |
|  [`detachLeavesOfType(viewType)`](obsidian.Workspace.detachLeavesOfType.md) |  |  |
|  [`duplicateLeaf(leaf, direction)`](obsidian.Workspace.duplicateLeaf.md) |  |  |
|  [`duplicateLeaf(leaf, leafType, direction)`](obsidian.Workspace.duplicateLeaf_1.md) |  |  |
|  [`getActiveFile()`](obsidian.Workspace.getActiveFile.md) |  | <p>Returns the file for the current view if it's a FileView.</p><p>Otherwise, it will recent the most recently active file.</p> |
|  [`getActiveViewOfType(type)`](obsidian.Workspace.getActiveViewOfType.md) |  |  |
|  [`getGroupLeaves(group)`](obsidian.Workspace.getGroupLeaves.md) |  |  |
|  [`getLastOpenFiles()`](obsidian.Workspace.getLastOpenFiles.md) |  |  |
|  [`getLayout()`](obsidian.Workspace.getLayout.md) |  |  |
|  [`getLeaf(newLeaf, direction)`](obsidian.Workspace.getLeaf.md) |  | Creates a new leaf in a leaf adjacent to the currently active leaf. If direction is <code>'vertical'</code>, the leaf will appear to the right. If direction is <code>'horizontal'</code>, the leaf will appear below the current leaf. |
|  [`getLeaf(newLeaf)`](obsidian.Workspace.getLeaf_1.md) |  | <p>If newLeaf is false (or not set) then an existing leaf which can be navigated is returned, or a new leaf will be created if there was no leaf available.</p><p>If newLeaf is <code>'tab'</code> or <code>true</code> then a new leaf will be created in the preferred location within the root split and returned.</p><p>If newLeaf is <code>'split'</code> then a new leaf will be created adjacent to the currently active leaf.</p><p>If newLeaf is <code>'window'</code> then a popout window will be created with a new leaf inside.</p> |

|  [`getLeafById(id)`](obsidian.Workspace.getLeafById.md) |  |  |
|  [`getLeavesOfType(viewType)`](obsidian.Workspace.getLeavesOfType.md) |  |  |
|  [`getLeftLeaf(split)`](obsidian.Workspace.getLeftLeaf.md) |  |  |
|  [`getMostRecentLeaf(root)`](obsidian.Workspace.getMostRecentLeaf.md) |  |  |
|  [`getRightLeaf(split)`](obsidian.Workspace.getRightLeaf.md) |  |  |
|  [`getUnpinnedLeaf()`](obsidian.Workspace.getUnpinnedLeaf.md) |  |  |
|  [`iterateAllLeaves(callback)`](obsidian.Workspace.iterateAllLeaves.md) |  | Iterate through all leaves, including main area leaves, floating leaves, and sidebar leaves. |
|  [`iterateCodeMirrors(callback)`](obsidian.Workspace.iterateCodeMirrors.md) |  |  |
|  [`iterateRootLeaves(callback)`](obsidian.Workspace.iterateRootLeaves.md) |  | Iterate through all leaves in the main area of the workspace. |
|  [`moveLeafToPopout(leaf, data)`](obsidian.Workspace.moveLeafToPopout.md) |  | Migrates this leaf to a new popout window. Only works on the desktop app. |
|  [`on(name, callback, ctx)`](obsidian.Workspace.on.md) |  |  |
|  [`on(name, callback, ctx)`](obsidian.Workspace.on_9.md) |  | Triggered when the user opens the context menu with multiple files selected in the File Explorer. |
|  [`on(name, callback, ctx)`](obsidian.Workspace.on_10.md) |  | Triggered when the user opens the context menu on an editor. |
|  [`on(name, callback, ctx)`](obsidian.Workspace.on_11.md) |  | Triggered when changes to an editor has been applied, either programmatically or from a user event. |
|  [`on(name, callback, ctx)`](obsidian.Workspace.on_12.md) |  | Triggered when the editor receives a paste event. Check for <code>evt.defaultPrevented</code> before attempting to handle this event, and return if it has been already handled. Use <code>evt.preventDefault()</code> to indicate that you've handled the event. |

|  [`on(name, callback, ctx)`](obsidian.Workspace.on_13.md) |  | Triggered when the editor receives a drop event. Check for <code>evt.defaultPrevented</code> before attempting to handle this event, and return if it has been already handled. Use <code>evt.preventDefault()</code> to indicate that you've handled the event. |
|  [`on(name, callback, ctx)`](obsidian.Workspace.on_14.md) |  |  |
|  [`on(name, callback, ctx)`](obsidian.Workspace.on_15.md) |  | Triggered when the app is about to quit. Not guaranteed to actually run. Perform some best effort cleanup here. |
|  [`on(name, callback, ctx)`](obsidian.Workspace.on_1.md) |  |  |
|  [`on(name, callback, ctx)`](obsidian.Workspace.on_2.md) |  |  |
|  [`on(name, callback, ctx)`](obsidian.Workspace.on_3.md) |  |  |
|  [`on(name, callback, ctx)`](obsidian.Workspace.on_4.md) |  |  |
|  [`on(name, callback, ctx)`](obsidian.Workspace.on_5.md) |  |  |
|  [`on(name, callback, ctx)`](obsidian.Workspace.on_6.md) |  |  |
|  [`on(name, callback, ctx)`](obsidian.Workspace.on_7.md) |  | Triggered when the CSS of the app has changed. |
|  [`on(name, callback, ctx)`](obsidian.Workspace.on_8.md) |  | Triggered when the user opens the context menu on a file. |
|  [`onLayoutReady(callback)`](obsidian.Workspace.onLayoutReady.md) |  | Runs the callback function right away if layout is already ready, or push it to a queue to be called later when layout is ready. |
|  [`openLinkText(linktext, sourcePath, newLeaf, openViewState)`](obsidian.Workspace.openLinkText.md) |  |  |
|  [`openPopoutLeaf(data)`](obsidian.Workspace.openPopoutLeaf.md) |  | Open a new popout window with a single new leaf and return that leaf. Only works on the desktop app. |
|  [`revealLeaf(leaf)`](obsidian.Workspace.revealLeaf.md) |  |  |
|  [`setActiveLeaf(leaf, params)`](obsidian.Workspace.setActiveLeaf.md) |  | Sets the active leaf |
|  [`setActiveLeaf(leaf, pushHistory, focus)`](obsidian.Workspace.setActiveLeaf_1.md) |  |  |

|  [`splitActiveLeaf(direction)`](obsidian.Workspace.splitActiveLeaf.md) |  |  |
|  [`updateOptions()`](obsidian.Workspace.updateOptions.md) |  | Calling this function will update/reconfigure the options of all markdown panes. It is fairly expensive, so it should not be called frequently. |

[`BaseComponent`](obsidian.BaseComponent.md)

## BaseComponent class

export abstract class BaseComponent 
```

|  [`disabled`](obsidian.BaseComponent.disabled.md) |  | <code>boolean</code> |  |

## Methods

|  [`setDisabled(disabled)`](obsidian.BaseComponent.setDisabled.md) |  |  |
|  [`then(cb)`](obsidian.BaseComponent.then.md) |  | Facilitates chaining |

[`SearchComponent`](obsidian.SearchComponent.md)

## SearchComponent class

export class SearchComponent extends AbstractTextComponent<HTMLInputElement> 
```

|  [`(constructor)(containerEl)`](obsidian.SearchComponent.(constructor).md) |  | Constructs a new instance of the <code>SearchComponent</code> class |

|  [`clearButtonEl`](obsidian.SearchComponent.clearButtonEl.md) |  | <code>HTMLElement</code> |  |

## Methods

|  [`onChanged()`](obsidian.SearchComponent.onChanged.md) |  |  |

[`sanitizeHTMLToDom`](obsidian.sanitizeHTMLToDom.md)

## sanitizeHTMLToDom() function

export function sanitizeHTMLToDom(html: string): DocumentFragment;
```

|  <code>html</code> | <code>string</code> |  |

`DocumentFragment`

[`FrontmatterLinkCache`](obsidian.FrontmatterLinkCache.md)

## FrontmatterLinkCache interface

export interface FrontmatterLinkCache extends Reference 
```
**Extends:** [`Reference`](obsidian.Reference.md)

|  [`key`](obsidian.FrontmatterLinkCache.key.md) |  | <code>string</code> |  |

[`Editor`](obsidian.Editor.md)

## Editor class

A common interface that bridges the gap between CodeMirror 5 and CodeMirror 6.

export abstract class Editor 
```

|  [`blur()`](obsidian.Editor.blur.md) | <code>abstract</code> |  |
|  [`exec(command)`](obsidian.Editor.exec.md) | <code>abstract</code> |  |
|  [`focus()`](obsidian.Editor.focus.md) | <code>abstract</code> |  |
|  [`getCursor(string)`](obsidian.Editor.getCursor.md) | <code>abstract</code> |  |
|  [`getDoc()`](obsidian.Editor.getDoc.md) |  |  |
|  [`getLine(line)`](obsidian.Editor.getLine.md) | <code>abstract</code> | Get the text at line (0-indexed) |
|  [`getRange(from, to)`](obsidian.Editor.getRange.md) | <code>abstract</code> |  |
|  [`getScrollInfo()`](obsidian.Editor.getScrollInfo.md) | <code>abstract</code> |  |
|  [`getSelection()`](obsidian.Editor.getSelection.md) | <code>abstract</code> |  |
|  [`getValue()`](obsidian.Editor.getValue.md) | <code>abstract</code> |  |
|  [`hasFocus()`](obsidian.Editor.hasFocus.md) | <code>abstract</code> |  |
|  [`lastLine()`](obsidian.Editor.lastLine.md) | <code>abstract</code> |  |
|  [`lineCount()`](obsidian.Editor.lineCount.md) | <code>abstract</code> | Gets the number of lines in the document |
|  [`listSelections()`](obsidian.Editor.listSelections.md) | <code>abstract</code> |  |
|  [`offsetToPos(offset)`](obsidian.Editor.offsetToPos.md) | <code>abstract</code> |  |
|  [`posToOffset(pos)`](obsidian.Editor.posToOffset.md) | <code>abstract</code> |  |
|  [`processLines(read, write, ignoreEmpty)`](obsidian.Editor.processLines.md) |  |  |
|  [`redo()`](obsidian.Editor.redo.md) | <code>abstract</code> |  |
|  [`refresh()`](obsidian.Editor.refresh.md) | <code>abstract</code> |  |
|  [`replaceRange(replacement, from, to, origin)`](obsidian.Editor.replaceRange.md) | <code>abstract</code> |  |
|  [`replaceSelection(replacement, origin)`](obsidian.Editor.replaceSelection.md) | <code>abstract</code> |  |
|  [`scrollIntoView(range, center)`](obsidian.Editor.scrollIntoView.md) | <code>abstract</code> |  |

|  [`scrollTo(x, y)`](obsidian.Editor.scrollTo.md) | <code>abstract</code> |  |
|  [`setCursor(pos, ch)`](obsidian.Editor.setCursor.md) |  |  |
|  [`setLine(n, text)`](obsidian.Editor.setLine.md) |  |  |
|  [`setSelection(anchor, head)`](obsidian.Editor.setSelection.md) | <code>abstract</code> |  |
|  [`setSelections(ranges, main)`](obsidian.Editor.setSelections.md) | <code>abstract</code> |  |
|  [`setValue(content)`](obsidian.Editor.setValue.md) | <code>abstract</code> |  |
|  [`somethingSelected()`](obsidian.Editor.somethingSelected.md) |  |  |
|  [`transaction(tx, origin)`](obsidian.Editor.transaction.md) | <code>abstract</code> |  |
|  [`undo()`](obsidian.Editor.undo.md) | <code>abstract</code> |  |
|  [`wordAt(pos)`](obsidian.Editor.wordAt.md) | <code>abstract</code> |  |

[`base64ToArrayBuffer`](obsidian.base64ToArrayBuffer.md)

## base64ToArrayBuffer() function

export function base64ToArrayBuffer(base64: string): ArrayBuffer;
```

|  <code>base64</code> | <code>string</code> |  |

[`WorkspaceMobileDrawer`](obsidian.WorkspaceMobileDrawer.md)

## WorkspaceMobileDrawer class

export class WorkspaceMobileDrawer extends WorkspaceParent 
```
**Extends:** [`WorkspaceParent`](obsidian.WorkspaceParent.md)

|  [`collapsed`](obsidian.WorkspaceMobileDrawer.collapsed.md) |  | <code>boolean</code> |  |

## Methods

|  [`collapse()`](obsidian.WorkspaceMobileDrawer.collapse.md) |  |  |
|  [`expand()`](obsidian.WorkspaceMobileDrawer.expand.md) |  |  |
|  [`toggle()`](obsidian.WorkspaceMobileDrawer.toggle.md) |  |  |

[`KeymapInfo`](obsidian.KeymapInfo.md)

## KeymapInfo interface

export interface KeymapInfo 
```

|  [`key`](obsidian.KeymapInfo.key.md) |  | <code>string &#124; null</code> |  |
|  [`modifiers`](obsidian.KeymapInfo.modifiers.md) |  | <code>string &#124; null</code> |  |

[`MenuPositionDef`](obsidian.MenuPositionDef.md)

## MenuPositionDef interface

export interface MenuPositionDef 
```

|  [`left?`](obsidian.MenuPositionDef.left.md) |  | <code>boolean</code> | _(Optional)_ |
|  [`overlap?`](obsidian.MenuPositionDef.overlap.md) |  | <code>boolean</code> | _(Optional)_ |
|  [`width?`](obsidian.MenuPositionDef.width.md) |  | <code>number</code> | _(Optional)_ |
|  [`x`](obsidian.MenuPositionDef.x.md) |  | <code>number</code> |  |
|  [`y`](obsidian.MenuPositionDef.y.md) |  | <code>number</code> |  |

[`WorkspaceParent`](obsidian.WorkspaceParent.md)

## WorkspaceParent class

export abstract class WorkspaceParent extends WorkspaceItem 
```
**Extends:** [`WorkspaceItem`](obsidian.WorkspaceItem.md)

[`renderMatches`](obsidian.renderMatches.md)

## renderMatches() function

export function renderMatches(el: HTMLElement | DocumentFragment, text: string, matches: SearchMatches | null, offset?: number): void;
```

|  <code>el</code> | <code>HTMLElement</code><code> &#124; </code><code>DocumentFragment</code> |  |
|  <code>matches</code> | [`SearchMatches`](obsidian.SearchMatches.md)<code> &#124; null</code> |  |

`void`

[`FileManager`](obsidian.FileManager.md)

## FileManager class

Manage the creation, deletion and renaming of files from the UI.

export class FileManager 
```

## Methods

|  [`generateMarkdownLink(file, sourcePath, subpath, alias)`](obsidian.FileManager.generateMarkdownLink.md) |  | Generate a markdown link based on the user's preferences. |
|  [`getNewFileParent(sourcePath, newFilePath)`](obsidian.FileManager.getNewFileParent.md) |  | Gets the folder that new files should be saved to, given the user's preferences. |
|  [`processFrontMatter(file, fn, options)`](obsidian.FileManager.processFrontMatter.md) |  | <p>Atomically read, modify, and save the frontmatter of a note. The frontmatter is passed in as a JS object, and should be mutated directly to achieve the desired result.</p><p>Remember to handle errors thrown by this method.</p> |
|  [`renameFile(file, newPath)`](obsidian.FileManager.renameFile.md) |  | Rename or move a file safely, and update all links to it depending on the user's preferences. |

[`ViewStateResult`](obsidian.ViewStateResult.md)

## ViewStateResult interface

export interface ViewStateResult 
```

|  [`history`](obsidian.ViewStateResult.history.md) |  | <code>boolean</code> | Set this to true to indicate that there is a state change which should be recorded in the navigation history. |

[`parseFrontMatterEntry`](obsidian.parseFrontMatterEntry.md)

## parseFrontMatterEntry() function

export function parseFrontMatterEntry(frontmatter: any | null, key: string | RegExp): any | null;
```

`any | null`

[`ProgressBarComponent`](obsidian.ProgressBarComponent.md)

## ProgressBarComponent class

export class ProgressBarComponent extends ValueComponent<number> 
```

|  [`(constructor)(containerEl)`](obsidian.ProgressBarComponent.(constructor).md) |  | Constructs a new instance of the <code>ProgressBarComponent</code> class |

## Methods

|  [`getValue()`](obsidian.ProgressBarComponent.getValue.md) |  |  |
|  [`setValue(value)`](obsidian.ProgressBarComponent.setValue.md) |  |  |

[`ItemView`](obsidian.ItemView.md)

## ItemView class

export abstract class ItemView extends View 
```
**Extends:** [`View`](obsidian.View.md)

|  [`(constructor)(leaf)`](obsidian.ItemView.(constructor).md) |  | Constructs a new instance of the <code>ItemView</code> class |

|  [`contentEl`](obsidian.ItemView.contentEl.md) |  | <code>HTMLElement</code> |  |

## Methods

|  [`addAction(icon, title, callback)`](obsidian.ItemView.addAction.md) |  |  |

[`Component`](obsidian.Component.md)

## Component class

export class Component 
```

## Methods

|  [`addChild(component)`](obsidian.Component.addChild.md) |  | Adds a child component, loading it if this component is loaded |
|  [`load()`](obsidian.Component.load.md) |  | Load this component and its children |
|  [`onload()`](obsidian.Component.onload.md) |  | Override this to load your component |
|  [`onunload()`](obsidian.Component.onunload.md) |  | Override this to unload your component |
|  [`register(cb)`](obsidian.Component.register.md) |  | Registers a callback to be called when unloading |
|  [`registerDomEvent(el, type, callback, options)`](obsidian.Component.registerDomEvent.md) |  | Registers an DOM event to be detached when unloading |
|  [`registerDomEvent(el, type, callback, options)`](obsidian.Component.registerDomEvent_1.md) |  | Registers an DOM event to be detached when unloading |
|  [`registerDomEvent(el, type, callback, options)`](obsidian.Component.registerDomEvent_2.md) |  | Registers an DOM event to be detached when unloading |
|  [`registerEvent(eventRef)`](obsidian.Component.registerEvent.md) |  | Registers an event to be detached when unloading |
|  [`registerInterval(id)`](obsidian.Component.registerInterval.md) |  | Registers an interval (from setInterval) to be cancelled when unloading Use  instead of  to avoid TypeScript confusing between NodeJS vs Browser API |
|  [`removeChild(component)`](obsidian.Component.removeChild.md) |  | Removes a child component, unloading it |
|  [`unload()`](obsidian.Component.unload.md) |  | Unload this component and its children |

[`DropdownComponent`](obsidian.DropdownComponent.md)

## DropdownComponent class

export class DropdownComponent extends ValueComponent<string> 
```
**Extends:** [`ValueComponent`](obsidian.ValueComponent.md)`<string>`

|  [`(constructor)(containerEl)`](obsidian.DropdownComponent.(constructor).md) |  | Constructs a new instance of the <code>DropdownComponent</code> class |

|  [`selectEl`](obsidian.DropdownComponent.selectEl.md) |  | <code>HTMLSelectElement</code> |  |

## Methods

|  [`addOption(value, display)`](obsidian.DropdownComponent.addOption.md) |  |  |
|  [`addOptions(options)`](obsidian.DropdownComponent.addOptions.md) |  |  |
|  [`getValue()`](obsidian.DropdownComponent.getValue.md) |  |  |
|  [`onChange(callback)`](obsidian.DropdownComponent.onChange.md) |  |  |
|  [`setDisabled(disabled)`](obsidian.DropdownComponent.setDisabled.md) |  |  |
|  [`setValue(value)`](obsidian.DropdownComponent.setValue.md) |  |  |

[`MarkdownRenderChild`](obsidian.MarkdownRenderChild.md)

## MarkdownRenderChild class

export class MarkdownRenderChild extends Component 
```

|  [`(constructor)(containerEl)`](obsidian.MarkdownRenderChild.(constructor).md) |  | Constructs a new instance of the <code>MarkdownRenderChild</code> class |

|  [`containerEl`](obsidian.MarkdownRenderChild.containerEl.md) |  | <code>HTMLElement</code> |  |

[`debounce`](obsidian.debounce.md)

## debounce() function

A standard debounce function. Use this to have a time-delayed function only be called once in a given timeframe.

export function debounce<T extends unknown[], V>(cb: (...args: [...T]) => V, timeout?: number, resetTimer?: boolean): Debouncer<T, V>;
```

|  <code>cb</code> | <code>(...args: [...T]) =&gt; V</code> | The function to call. |
|  <code>timeout</code> | <code>number</code> | _(Optional)_ The timeout to wait, in milliseconds |
|  <code>resetTimer</code> | <code>boolean</code> | _(Optional)_ Whether to reset the timeout when the debouncer is called again. |

[`Debouncer`](obsidian.Debouncer.md)`<T, V>`

a debounced function that takes the same parameter as the original function.

## Example

```ts
const debounced = debounce((text: string) => {
    console.log(text);
}, 1000, true);
debounced("Hello world"); // this will not be printed
sleep(500);
debounced("World, hello"); // this will be printed to the console.
```

[`DataWriteOptions`](obsidian.DataWriteOptions.md)

## DataWriteOptions interface

export interface DataWriteOptions 
```

|  [`ctime?`](obsidian.DataWriteOptions.ctime.md) |  | <code>number</code> | _(Optional)_ Time of creation, represented as a unix timestamp, in milliseconds. Omit this if you want to keep the default behaviour. |
|  [`mtime?`](obsidian.DataWriteOptions.mtime.md) |  | <code>number</code> | _(Optional)_ Time of last modification, represented as a unix timestamp, in milliseconds. Omit this if you want to keep the default behaviour. |

[`HoverLinkSource`](obsidian.HoverLinkSource.md)

## HoverLinkSource interface

export interface HoverLinkSource 
```

|  [`defaultMod`](obsidian.HoverLinkSource.defaultMod.md) |  | <code>boolean</code> | Whether or not the <code>hover-link</code> event requires the 'Mod' key to be pressed to trigger. |
|  [`display`](obsidian.HoverLinkSource.display.md) |  | <code>string</code> | The string that will be displayed in the 'Page preview' plugin settings. It should match your plugin's display name. |

[`EditorRangeOrCaret`](obsidian.EditorRangeOrCaret.md)

## EditorRangeOrCaret interface

export interface EditorRangeOrCaret 
```

|  [`from`](obsidian.EditorRangeOrCaret.from.md) |  | [`EditorPosition`](obsidian.EditorPosition.md) |  |
|  [`to?`](obsidian.EditorRangeOrCaret.to.md) |  | [`EditorPosition`](obsidian.EditorPosition.md) | _(Optional)_ |

[`EditorSelectionOrCaret`](obsidian.EditorSelectionOrCaret.md)

## EditorSelectionOrCaret interface

export interface EditorSelectionOrCaret 
```

|  [`anchor`](obsidian.EditorSelectionOrCaret.anchor.md) |  | [`EditorPosition`](obsidian.EditorPosition.md) |  |
|  [`head?`](obsidian.EditorSelectionOrCaret.head.md) |  | [`EditorPosition`](obsidian.EditorPosition.md) | _(Optional)_ |

[`Instruction`](obsidian.Instruction.md)

## Instruction interface

export interface Instruction 
```

|  [`command`](obsidian.Instruction.command.md) |  | <code>string</code> |  |
|  [`purpose`](obsidian.Instruction.purpose.md) |  | <code>string</code> |  |

[`ValueComponent`](obsidian.ValueComponent.md)

## ValueComponent class

export abstract class ValueComponent<T> extends BaseComponent 
```

## Methods

|  [`getValue()`](obsidian.ValueComponent.getValue.md) | <code>abstract</code> |  |
|  [`registerOptionListener(listeners, key)`](obsidian.ValueComponent.registerOptionListener.md) |  |  |
|  [`setValue(value)`](obsidian.ValueComponent.setValue.md) | <code>abstract</code> |  |

[`Debouncer`](obsidian.Debouncer.md)

## Debouncer interface

export interface Debouncer<T extends unknown[], V> 
```

## Methods

|  --- | --- |
|  [`cancel()`](obsidian.Debouncer.cancel.md) |  |
|  [`run()`](obsidian.Debouncer.run.md) |  |

[`Loc`](obsidian.Loc.md)

## Loc interface

export interface Loc 
```

|  [`col`](obsidian.Loc.col.md) |  | <code>number</code> |  |
|  [`line`](obsidian.Loc.line.md) |  | <code>number</code> |  |
|  [`offset`](obsidian.Loc.offset.md) |  | <code>number</code> |  |

[`MarkdownSourceView`](obsidian.MarkdownSourceView.md)

## MarkdownSourceView class

export class MarkdownSourceView implements MarkdownSubView, HoverParent, MarkdownFileInfo 
```
**Implements:** [`MarkdownSubView`](obsidian.MarkdownSubView.md)<!-- -->, [`HoverParent`](obsidian.HoverParent.md)<!-- -->, [`MarkdownFileInfo`](obsidian.MarkdownFileInfo.md)

|  [`(constructor)(view)`](obsidian.MarkdownSourceView.(constructor).md) |  | Constructs a new instance of the <code>MarkdownSourceView</code> class |

|  [`app`](obsidian.MarkdownSourceView.app.md) |  | [`App`](obsidian.App.md) |  |
|  [`cmEditor`](obsidian.MarkdownSourceView.cmEditor.md) |  | <code>CodeMirror.Editor</code> |  |
|  [`file`](obsidian.MarkdownSourceView.file.md) | <code>readonly</code> | [`TFile`](obsidian.TFile.md) |  |
|  [`hoverPopover`](obsidian.MarkdownSourceView.hoverPopover.md) |  | [`HoverPopover`](obsidian.HoverPopover.md) |  |

## Methods

|  [`applyScroll(scroll)`](obsidian.MarkdownSourceView.applyScroll.md) |  |  |
|  [`clear()`](obsidian.MarkdownSourceView.clear.md) |  |  |
|  [`get()`](obsidian.MarkdownSourceView.get.md) |  |  |
|  [`getScroll()`](obsidian.MarkdownSourceView.getScroll.md) |  |  |
|  [`getSelection()`](obsidian.MarkdownSourceView.getSelection.md) |  |  |
|  [`set(data, clear)`](obsidian.MarkdownSourceView.set.md) |  |  |

[`stripHeading`](obsidian.stripHeading.md)

## stripHeading() function

This function normalizes headings for link matching by stripping out special characters and shrinking consecutive spaces.

export function stripHeading(heading: string): string;
```

`string`

[`Tasks`](obsidian.Tasks.md)

## Tasks class

export class Tasks 
```

## Methods

|  [`add(callback)`](obsidian.Tasks.add.md) |  |  |
|  [`addPromise(promise)`](obsidian.Tasks.addPromise.md) |  |  |
|  [`isEmpty()`](obsidian.Tasks.isEmpty.md) |  |  |
|  [`promise()`](obsidian.Tasks.promise.md) |  |  |

[`WorkspaceFloating`](obsidian.WorkspaceFloating.md)

## WorkspaceFloating class

export class WorkspaceFloating extends WorkspaceParent 
```

[`SectionCache`](obsidian.SectionCache.md)

## SectionCache interface

export interface SectionCache extends CacheItem 
```

|  [`id?`](obsidian.SectionCache.id.md) |  | <code>string &#124; undefined</code> | _(Optional)_ The block ID of this section, if defined. |
|  [`type`](obsidian.SectionCache.type.md) |  | <code>string</code> | The type string generated by the parser. |

[`MarkdownViewModeType`](obsidian.MarkdownViewModeType.md)

## MarkdownViewModeType type

export type MarkdownViewModeType = 'source' | 'preview';
```

[`Command`](obsidian.Command.md)

## Command interface

export interface Command 
```

|  [`callback?`](obsidian.Command.callback.md) |  | <code>() =&gt; any</code> | _(Optional)_ Simple callback, triggered globally. |
|  [`checkCallback?`](obsidian.Command.checkCallback.md) |  | <code>(checking: boolean) =&gt; boolean &#124; void</code> | _(Optional)_ Complex callback, overrides the simple callback. Used to "check" whether your command can be performed in the current circumstances. For example, if your command requires the active focused pane to be a MarkdownSourceView, then you should only return true if the condition is satisfied. Returning false or undefined causes the command to be hidden from the command palette. |
|  [`editorCallback?`](obsidian.Command.editorCallback.md) |  | <code>(editor: </code>[`Editor`](obsidian.Editor.md)<code>, ctx: </code>[`MarkdownView`](obsidian.MarkdownView.md)<code> &#124; </code>[`MarkdownFileInfo`](obsidian.MarkdownFileInfo.md)<code>) =&gt; any</code> | _(Optional)_ A command callback that is only triggered when the user is in an editor. Overrides <code>callback</code> and <code>checkCallback</code> |
|  [`editorCheckCallback?`](obsidian.Command.editorCheckCallback.md) |  | <code>(checking: boolean, editor: </code>[`Editor`](obsidian.Editor.md)<code>, ctx: </code>[`MarkdownView`](obsidian.MarkdownView.md)<code> &#124; </code>[`MarkdownFileInfo`](obsidian.MarkdownFileInfo.md)<code>) =&gt; boolean &#124; void</code> | _(Optional)_ A command callback that is only triggered when the user is in an editor. Overrides <code>editorCallback</code>, <code>callback</code> and <code>checkCallback</code> |
|  [`hotkeys?`](obsidian.Command.hotkeys.md) |  | [`Hotkey`](obsidian.Hotkey.md)<code>[]</code> | _(Optional)_ Sets the default hotkey. It is recommended for plugins to avoid setting default hotkeys if possible, to avoid conflicting hotkeys with one that's set by the user, even though customized hotkeys have higher priority. |

|  [`icon?`](obsidian.Command.icon.md) |  | [`IconName`](obsidian.IconName.md) | _(Optional)_ Icon ID to be used in the toolbar. |
|  [`id`](obsidian.Command.id.md) |  | <code>string</code> | Globally unique ID to identify this command. |
|  [`mobileOnly?`](obsidian.Command.mobileOnly.md) |  | <code>boolean</code> | _(Optional)_ |
|  [`name`](obsidian.Command.name.md) |  | <code>string</code> | Human friendly name for searching. |
|  [`repeatable?`](obsidian.Command.repeatable.md) |  | <code>boolean</code> | _(Optional)_ Whether holding the hotkey should repeatedly trigger this command. Defaults to false. |

[`ISuggestOwner`](obsidian.ISuggestOwner.md)

## ISuggestOwner interface

export interface ISuggestOwner<T> 
```

## Methods

|  --- | --- |
|  [`renderSuggestion(value, el)`](obsidian.ISuggestOwner.renderSuggestion.md) | Render the suggestion item into DOM. |
|  [`selectSuggestion(value, evt)`](obsidian.ISuggestOwner.selectSuggestion.md) | Called when the user makes a selection. |

[`EditorChange`](obsidian.EditorChange.md)

## EditorChange interface

export interface EditorChange extends EditorRangeOrCaret 
```
**Extends:** [`EditorRangeOrCaret`](obsidian.EditorRangeOrCaret.md)

|  [`text`](obsidian.EditorChange.text.md) |  | <code>string</code> |  |

[`FuzzySuggestModal`](obsidian.FuzzySuggestModal.md)

## FuzzySuggestModal class

export abstract class FuzzySuggestModal<T> extends SuggestModal<FuzzyMatch<T>> 
```
**Extends:** [`SuggestModal`](obsidian.SuggestModal.md)`<`[`FuzzyMatch`](obsidian.FuzzyMatch.md)`<T>>`

## Methods

|  [`getItems()`](obsidian.FuzzySuggestModal.getItems.md) | <code>abstract</code> |  |
|  [`getItemText(item)`](obsidian.FuzzySuggestModal.getItemText.md) | <code>abstract</code> |  |
|  [`getSuggestions(query)`](obsidian.FuzzySuggestModal.getSuggestions.md) |  |  |
|  [`onChooseItem(item, evt)`](obsidian.FuzzySuggestModal.onChooseItem.md) | <code>abstract</code> |  |
|  [`onChooseSuggestion(item, evt)`](obsidian.FuzzySuggestModal.onChooseSuggestion.md) |  |  |
|  [`renderSuggestion(item, el)`](obsidian.FuzzySuggestModal.renderSuggestion.md) |  |  |

[`Constructor`](obsidian.Constructor.md)

## Constructor type

export type Constructor<T> = abstract new (...args: any[]) => T;
```

[`sortSearchResults`](obsidian.sortSearchResults.md)

## sortSearchResults() function

export function sortSearchResults(results: SearchResultContainer[]): void;
```

|  <code>results</code> | [`SearchResultContainer`](obsidian.SearchResultContainer.md)<code>[]</code> |  |

`void`

[`normalizePath`](obsidian.normalizePath.md)

## normalizePath() function

export function normalizePath(path: string): string;
```

|  <code>path</code> | <code>string</code> |  |

`string`

[`SearchMatches`](obsidian.SearchMatches.md)

## SearchMatches type

export type SearchMatches = SearchMatchPart[];
```
**References:** [`SearchMatchPart`](obsidian.SearchMatchPart.md)

[`FuzzyMatch`](obsidian.FuzzyMatch.md)

## FuzzyMatch interface

export interface FuzzyMatch<T> 
```

|  [`item`](obsidian.FuzzyMatch.item.md) |  | <code>T</code> |  |
|  [`match`](obsidian.FuzzyMatch.match.md) |  | [`SearchResult`](obsidian.SearchResult.md) |  |

[`MarkdownSectionInformation`](obsidian.MarkdownSectionInformation.md)

## MarkdownSectionInformation interface

export interface MarkdownSectionInformation 
```

|  [`lineEnd`](obsidian.MarkdownSectionInformation.lineEnd.md) |  | <code>number</code> |  |
|  [`lineStart`](obsidian.MarkdownSectionInformation.lineStart.md) |  | <code>number</code> |  |
|  [`text`](obsidian.MarkdownSectionInformation.text.md) |  | <code>string</code> |  |

[`PluginManifest`](obsidian.PluginManifest.md)

## PluginManifest interface

Metadata about a Community plugin.

export interface PluginManifest 
```

|  [`author`](obsidian.PluginManifest.author.md) |  | <code>string</code> | The author's name. |
|  [`authorUrl?`](obsidian.PluginManifest.authorUrl.md) |  | <code>string</code> | _(Optional)_ A URL to the author's website. |
|  [`description`](obsidian.PluginManifest.description.md) |  | <code>string</code> | A description of the plugin. |
|  [`dir?`](obsidian.PluginManifest.dir.md) |  | <code>string</code> | _(Optional)_ Vault path to the plugin folder in the config directory. |
|  [`id`](obsidian.PluginManifest.id.md) |  | <code>string</code> | The plugin ID. |
|  [`isDesktopOnly?`](obsidian.PluginManifest.isDesktopOnly.md) |  | <code>boolean</code> | _(Optional)_ Whether the plugin can be used only on desktop. |
|  [`minAppVersion`](obsidian.PluginManifest.minAppVersion.md) |  | <code>string</code> | The minimum required Obsidian version to run this plugin. |
|  [`name`](obsidian.PluginManifest.name.md) |  | <code>string</code> | The display name. |
|  [`version`](obsidian.PluginManifest.version.md) |  | <code>string</code> | The current version, using . |

[`MarkdownPostProcessor`](obsidian.MarkdownPostProcessor.md)

## MarkdownPostProcessor interface

A post processor receives an element which is a section of the preview.

Post processors can mutate the DOM to render various things, such as mermaid graphs, latex equations, or custom controls.

If your post processor requires lifecycle management, for example, to clear an interval, kill a subprocess, etc when this element is removed from the app, look into 

export interface MarkdownPostProcessor 
```

|  [`sortOrder?`](obsidian.MarkdownPostProcessor.sortOrder.md) |  | <code>number</code> | _(Optional)_ An optional integer sort order. Defaults to 0. Lower number runs before higher numbers. |

[`HSL`](obsidian.HSL.md)

## HSL interface

export interface HSL 
```

|  [`h`](obsidian.HSL.h.md) |  | <code>number</code> | Hue integer value between 0 and 360 |
|  [`l`](obsidian.HSL.l.md) |  | <code>number</code> | Lightness integer value between 0 and 100 |
|  [`s`](obsidian.HSL.s.md) |  | <code>number</code> | Saturation integer value between 0 and 100 |

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md)

## WorkspaceLeaf class

export class WorkspaceLeaf extends WorkspaceItem 
```

|  [`view`](obsidian.WorkspaceLeaf.view.md) |  | [`View`](obsidian.View.md) |  |

## Methods

|  [`detach()`](obsidian.WorkspaceLeaf.detach.md) |  |  |
|  [`getDisplayText()`](obsidian.WorkspaceLeaf.getDisplayText.md) |  |  |
|  [`getEphemeralState()`](obsidian.WorkspaceLeaf.getEphemeralState.md) |  |  |
|  [`getIcon()`](obsidian.WorkspaceLeaf.getIcon.md) |  |  |
|  [`getViewState()`](obsidian.WorkspaceLeaf.getViewState.md) |  |  |
|  [`on(name, callback, ctx)`](obsidian.WorkspaceLeaf.on.md) |  |  |
|  [`on(name, callback, ctx)`](obsidian.WorkspaceLeaf.on_1.md) |  |  |
|  [`onResize()`](obsidian.WorkspaceLeaf.onResize.md) |  |  |
|  [`open(view)`](obsidian.WorkspaceLeaf.open.md) |  |  |
|  [`openFile(file, openState)`](obsidian.WorkspaceLeaf.openFile.md) |  | By default, <code>openFile</code> will also make the leaf active. Pass in <code>{ active: false }</code> to override. |
|  [`setEphemeralState(state)`](obsidian.WorkspaceLeaf.setEphemeralState.md) |  |  |
|  [`setGroup(group)`](obsidian.WorkspaceLeaf.setGroup.md) |  |  |
|  [`setGroupMember(other)`](obsidian.WorkspaceLeaf.setGroupMember.md) |  |  |
|  [`setPinned(pinned)`](obsidian.WorkspaceLeaf.setPinned.md) |  |  |
|  [`setViewState(viewState, eState)`](obsidian.WorkspaceLeaf.setViewState.md) |  |  |
|  [`togglePinned()`](obsidian.WorkspaceLeaf.togglePinned.md) |  |  |

[`Pos`](obsidian.Pos.md)

## Pos interface

export interface Pos 
```

|  [`end`](obsidian.Pos.end.md) |  | [`Loc`](obsidian.Loc.md) |  |
|  [`start`](obsidian.Pos.start.md) |  | [`Loc`](obsidian.Loc.md) |  |

[`MetadataCache`](obsidian.MetadataCache.md)

## MetadataCache class

Linktext is any internal link that is composed of a path and a subpath, such as "My note\#Heading" Linkpath (or path) is the path part of a linktext Subpath is the heading/block ID part of a linktext.

export class MetadataCache extends Events 
```

|  [`resolvedLinks`](obsidian.MetadataCache.resolvedLinks.md) |  | <code>Record</code><code>&lt;string, </code><code>Record</code><code>&lt;string, number&gt;&gt;</code> | Contains all resolved links. This object maps each source file's path to an object of destination file paths with the link count. Source and destination paths are all vault absolute paths that comes from <code>TFile.path</code> and can be used with <code>Vault.getAbstractFileByPath(path)</code>. |
|  [`unresolvedLinks`](obsidian.MetadataCache.unresolvedLinks.md) |  | <code>Record</code><code>&lt;string, </code><code>Record</code><code>&lt;string, number&gt;&gt;</code> | Contains all unresolved links. This object maps each source file to an object of unknown destinations with count. Source paths are all vault absolute paths, similar to <code>resolvedLinks</code>. |

## Methods

|  [`fileToLinktext(file, sourcePath, omitMdExtension)`](obsidian.MetadataCache.fileToLinktext.md) |  | <p>Generates a linktext for a file.</p><p>If file name is unique, use the filename. If not unique, use full path.</p> |
|  [`getCache(path)`](obsidian.MetadataCache.getCache.md) |  |  |
|  [`getFileCache(file)`](obsidian.MetadataCache.getFileCache.md) |  |  |
|  [`getFirstLinkpathDest(linkpath, sourcePath)`](obsidian.MetadataCache.getFirstLinkpathDest.md) |  | Get the best match for a linkpath. |
|  [`on(name, callback, ctx)`](obsidian.MetadataCache.on.md) |  | <p>Called when a file has been indexed, and its (updated) cache is now available.</p><p>Note: This is not called when a file is renamed for performance reasons. You must hook the vault rename event for those. (Details: https://github.com/obsidianmd/obsidian-api/issues/77)</p> |
|  [`on(name, callback, ctx)`](obsidian.MetadataCache.on_1.md) |  | Called when a file has been deleted. A best-effort previous version of the cached metadata is presented, but it could be null in case the file was not successfully cached previously. |
|  [`on(name, callback, ctx)`](obsidian.MetadataCache.on_2.md) |  | Called when a file has been resolved for <code>resolvedLinks</code> and <code>unresolvedLinks</code>. This happens sometimes after a file has been indexed. |
|  [`on(name, callback, ctx)`](obsidian.MetadataCache.on_3.md) |  | Called when all files has been resolved. This will be fired each time files get modified after the initial load. |

[`SearchResultContainer`](obsidian.SearchResultContainer.md)

## SearchResultContainer interface

export interface SearchResultContainer 
```

|  [`match`](obsidian.SearchResultContainer.match.md) |  | [`SearchResult`](obsidian.SearchResult.md) |  |

[`EmbedCache`](obsidian.EmbedCache.md)

## EmbedCache interface

export interface EmbedCache extends ReferenceCache 
```

[`EditorSuggestContext`](obsidian.EditorSuggestContext.md)

## EditorSuggestContext interface

export interface EditorSuggestContext extends EditorSuggestTriggerInfo 
```
**Extends:** [`EditorSuggestTriggerInfo`](obsidian.EditorSuggestTriggerInfo.md)

|  [`editor`](obsidian.EditorSuggestContext.editor.md) |  | [`Editor`](obsidian.Editor.md) |  |
|  [`file`](obsidian.EditorSuggestContext.file.md) |  | [`TFile`](obsidian.TFile.md) |  |

[`PreparedQuery`](obsidian.PreparedQuery.md)

## PreparedQuery interface

export interface PreparedQuery 
```

|  [`fuzzy`](obsidian.PreparedQuery.fuzzy.md) |  | <code>string[]</code> |  |
|  [`query`](obsidian.PreparedQuery.query.md) |  | <code>string</code> |  |
|  [`tokens`](obsidian.PreparedQuery.tokens.md) |  | <code>string[]</code> |  |

[`MarkdownRenderer`](obsidian.MarkdownRenderer.md)

## MarkdownRenderer class

export abstract class MarkdownRenderer extends MarkdownRenderChild implements MarkdownPreviewEvents, HoverParent 
```
**Extends:** [`MarkdownRenderChild`](obsidian.MarkdownRenderChild.md)

**Implements:** [`MarkdownPreviewEvents`](obsidian.MarkdownPreviewEvents.md)<!-- -->, [`HoverParent`](obsidian.HoverParent.md)

|  [`app`](obsidian.MarkdownRenderer.app.md) |  | [`App`](obsidian.App.md) |  |
|  [`file`](obsidian.MarkdownRenderer.file.md) | <p><code>abstract</code></p><p><code>readonly</code></p> | [`TFile`](obsidian.TFile.md) |  |
|  [`hoverPopover`](obsidian.MarkdownRenderer.hoverPopover.md) |  | [`HoverPopover`](obsidian.HoverPopover.md) |  |

## Methods

|  [`render(app, markdown, el, sourcePath, component)`](obsidian.MarkdownRenderer.render.md) | <code>static</code> | Renders markdown string to an HTML element. |
|  [`renderMarkdown(markdown, el, sourcePath, component)`](obsidian.MarkdownRenderer.renderMarkdown.md) | <code>static</code> | Renders markdown string to an HTML element. |

[`TextAreaComponent`](obsidian.TextAreaComponent.md)

## TextAreaComponent class

export class TextAreaComponent extends AbstractTextComponent<HTMLTextAreaElement> 
```
**Extends:** [`AbstractTextComponent`](obsidian.AbstractTextComponent.md)`<``HTMLTextAreaElement``>`

|  [`(constructor)(containerEl)`](obsidian.TextAreaComponent.(constructor).md) |  | Constructs a new instance of the <code>TextAreaComponent</code> class |

[`prepareQuery`](obsidian.prepareQuery.md)

## prepareQuery() function

export function prepareQuery(query: string): PreparedQuery;
```

|  <code>query</code> | <code>string</code> |  |

[`Hotkey`](obsidian.Hotkey.md)

## Hotkey interface

export interface Hotkey 
```

|  [`key`](obsidian.Hotkey.key.md) |  | <code>string</code> |  |
|  [`modifiers`](obsidian.Hotkey.modifiers.md) |  | [`Modifier`](obsidian.Modifier.md)<code>[]</code> |  |

[`arrayBufferToHex`](obsidian.arrayBufferToHex.md)

## arrayBufferToHex() function

export function arrayBufferToHex(data: ArrayBuffer): string;
```

|  <code>data</code> | <code>ArrayBuffer</code> |  |

`string`

[`arrayBufferToBase64`](obsidian.arrayBufferToBase64.md)

## arrayBufferToBase64() function

export function arrayBufferToBase64(buffer: ArrayBuffer): string;
```

|  <code>buffer</code> | <code>ArrayBuffer</code> |  |

`string`

[`ListedFiles`](obsidian.ListedFiles.md)

## ListedFiles interface

export interface ListedFiles 
```

|  [`files`](obsidian.ListedFiles.files.md) |  | <code>string[]</code> |  |
|  [`folders`](obsidian.ListedFiles.folders.md) |  | <code>string[]</code> |  |

[`iterateRefs`](obsidian.iterateRefs.md)

## iterateRefs() function

export function iterateRefs(refs: Reference[], cb: (ref: Reference) => boolean | void): boolean;
```

|  <code>refs</code> | [`Reference`](obsidian.Reference.md)<code>[]</code> |  |
|  <code>cb</code> | <code>(ref: </code>[`Reference`](obsidian.Reference.md)<code>) =&gt; boolean &#124; void</code> |  |

`boolean`

[`ObsidianProtocolHandler`](obsidian.ObsidianProtocolHandler.md)

## ObsidianProtocolHandler type

export type ObsidianProtocolHandler = (params: ObsidianProtocolData) => any;
```
**References:** [`ObsidianProtocolData`](obsidian.ObsidianProtocolData.md)

[`PopoverSuggest`](obsidian.PopoverSuggest.md)

## PopoverSuggest class

Base class for adding a type-ahead popover.

export abstract class PopoverSuggest<T> implements ISuggestOwner<T>, CloseableComponent 
```
**Implements:** [`ISuggestOwner`](obsidian.ISuggestOwner.md)`<T>`<!-- -->, [`CloseableComponent`](obsidian.CloseableComponent.md)

|  [`(constructor)(app, scope)`](obsidian.PopoverSuggest.(constructor).md) |  | Constructs a new instance of the <code>PopoverSuggest</code> class |

|  [`app`](obsidian.PopoverSuggest.app.md) |  | [`App`](obsidian.App.md) |  |
|  [`scope`](obsidian.PopoverSuggest.scope.md) |  | [`Scope`](obsidian.Scope.md) |  |

## Methods

|  [`close()`](obsidian.PopoverSuggest.close.md) |  |  |
|  [`open()`](obsidian.PopoverSuggest.open.md) |  |  |
|  [`renderSuggestion(value, el)`](obsidian.PopoverSuggest.renderSuggestion.md) | <code>abstract</code> |  |
|  [`selectSuggestion(value, evt)`](obsidian.PopoverSuggest.selectSuggestion.md) | <code>abstract</code> |  |

[`loadMermaid`](obsidian.loadMermaid.md)

## loadMermaid() function

Load Mermaid and return a promise to the global mermaid object. Can also use `mermaid` after this promise resolves to get the same reference.

export function loadMermaid(): Promise<any>;
```

[`MarkdownPostProcessorContext`](obsidian.MarkdownPostProcessorContext.md)

## MarkdownPostProcessorContext interface

export interface MarkdownPostProcessorContext 
```

|  [`docId`](obsidian.MarkdownPostProcessorContext.docId.md) |  | <code>string</code> |  |
|  [`frontmatter`](obsidian.MarkdownPostProcessorContext.frontmatter.md) |  | <code>any &#124; null &#124; undefined</code> |  |
|  [`sourcePath`](obsidian.MarkdownPostProcessorContext.sourcePath.md) |  | <code>string</code> |  |

## Methods

|  --- | --- |
|  [`addChild(child)`](obsidian.MarkdownPostProcessorContext.addChild.md) | <p>Adds a child component that will have its lifecycle managed by the renderer.</p><p>Use this to add a dependent child to the renderer such that if the containerEl of the child is ever removed, the component's unload will be called.</p> |
|  [`getSectionInfo(el)`](obsidian.MarkdownPostProcessorContext.getSectionInfo.md) | Gets the section information of this element at this point in time. Only call this function right before you need this information to get the most up-to-date version. This function may also return null in many circumstances; if you use it, you must be prepared to deal with nulls. |

[`stringifyYaml`](obsidian.stringifyYaml.md)

## stringifyYaml() function

export function stringifyYaml(obj: any): string;
```

|  <code>obj</code> | <code>any</code> |  |

`string`

[`HoverPopover`](obsidian.HoverPopover.md)

## HoverPopover class

export class HoverPopover extends Component 
```

|  [`(constructor)(parent, targetEl, waitTime)`](obsidian.HoverPopover.(constructor).md) |  | Constructs a new instance of the <code>HoverPopover</code> class |

|  [`hoverEl`](obsidian.HoverPopover.hoverEl.md) |  | <code>HTMLElement</code> |  |
|  [`state`](obsidian.HoverPopover.state.md) |  | [`PopoverState`](obsidian.PopoverState.md) |  |

[`parseFrontMatterAliases`](obsidian.parseFrontMatterAliases.md)

## parseFrontMatterAliases() function

export function parseFrontMatterAliases(frontmatter: any | null): string[] | null;
```

[`HeadingCache`](obsidian.HeadingCache.md)

## HeadingCache interface

export interface HeadingCache extends CacheItem 
```

|  [`heading`](obsidian.HeadingCache.heading.md) |  | <code>string</code> |  |
|  [`level`](obsidian.HeadingCache.level.md) |  | <code>number</code> |  |

[`PluginSettingTab`](obsidian.PluginSettingTab.md)

## PluginSettingTab class

Provides a unified interface for users to configure the plugin.

export abstract class PluginSettingTab extends SettingTab 
```
**Extends:** [`SettingTab`](obsidian.SettingTab.md)

|  [`(constructor)(app, plugin)`](obsidian.PluginSettingTab.(constructor).md) |  | Constructs a new instance of the <code>PluginSettingTab</code> class |

[`FileStats`](obsidian.FileStats.md)

## FileStats interface

export interface FileStats 
```

|  [`ctime`](obsidian.FileStats.ctime.md) |  | <code>number</code> | Time of creation, represented as a unix timestamp, in milliseconds. |
|  [`mtime`](obsidian.FileStats.mtime.md) |  | <code>number</code> | Time of last modification, represented as a unix timestamp, in milliseconds. |
|  [`size`](obsidian.FileStats.size.md) |  | <code>number</code> | Size on disk, as bytes. |

[`request`](obsidian.request.md)

## request() function

Similar to `fetch()`<!-- -->, request a URL using HTTP/HTTPS, without any CORS restrictions. Returns the text value of the response.

export function request(request: RequestUrlParam | string): Promise<string>;
```

|  <code>request</code> | [`RequestUrlParam`](obsidian.RequestUrlParam.md)<code> &#124; string</code> |  |

`Promise``<string>`

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md)

## FileSystemAdapter class

export class FileSystemAdapter implements DataAdapter 
```
**Implements:** [`DataAdapter`](obsidian.DataAdapter.md)

|  [`append(normalizedPath, data, options)`](obsidian.FileSystemAdapter.append.md) |  |  |
|  [`copy(normalizedPath, normalizedNewPath)`](obsidian.FileSystemAdapter.copy.md) |  |  |
|  [`exists(normalizedPath, sensitive)`](obsidian.FileSystemAdapter.exists.md) |  |  |
|  [`getBasePath()`](obsidian.FileSystemAdapter.getBasePath.md) |  |  |
|  [`getFilePath(normalizedPath)`](obsidian.FileSystemAdapter.getFilePath.md) |  | Returns the file:// path of this file |
|  [`getFullPath(normalizedPath)`](obsidian.FileSystemAdapter.getFullPath.md) |  |  |
|  [`getName()`](obsidian.FileSystemAdapter.getName.md) |  |  |
|  [`getResourcePath(normalizedPath)`](obsidian.FileSystemAdapter.getResourcePath.md) |  |  |
|  [`list(normalizedPath)`](obsidian.FileSystemAdapter.list.md) |  |  |
|  [`mkdir(normalizedPath)`](obsidian.FileSystemAdapter.mkdir.md) |  |  |
|  [`mkdir(path)`](obsidian.FileSystemAdapter.mkdir.md) | <code>static</code> |  |
|  [`process(normalizedPath, fn, options)`](obsidian.FileSystemAdapter.process.md) |  |  |
|  [`read(normalizedPath)`](obsidian.FileSystemAdapter.read.md) |  |  |
|  [`readBinary(normalizedPath)`](obsidian.FileSystemAdapter.readBinary.md) |  |  |
|  [`readLocalFile(path)`](obsidian.FileSystemAdapter.readLocalFile.md) | <code>static</code> |  |
|  [`remove(normalizedPath)`](obsidian.FileSystemAdapter.remove.md) |  |  |
|  [`rename(normalizedPath, normalizedNewPath)`](obsidian.FileSystemAdapter.rename.md) |  |  |
|  [`rmdir(normalizedPath, recursive)`](obsidian.FileSystemAdapter.rmdir.md) |  |  |
|  [`stat(normalizedPath)`](obsidian.FileSystemAdapter.stat.md) |  |  |
|  [`trashLocal(normalizedPath)`](obsidian.FileSystemAdapter.trashLocal.md) |  |  |
|  [`trashSystem(normalizedPath)`](obsidian.FileSystemAdapter.trashSystem.md) |  |  |
|  [`write(normalizedPath, data, options)`](obsidian.FileSystemAdapter.write.md) |  |  |

|  [`writeBinary(normalizedPath, data, options)`](obsidian.FileSystemAdapter.writeBinary.md) |  |  |

[`Modifier`](obsidian.Modifier.md)

## Modifier type

Mod = Cmd on MacOS and Ctrl on other OS Ctrl = Ctrl key for every OS Meta = Cmd on MacOS and Win key on other OS

export type Modifier = 'Mod' | 'Ctrl' | 'Meta' | 'Shift' | 'Alt';
```

[`AbstractInputSuggest`](obsidian.AbstractInputSuggest.md)

## AbstractInputSuggest class

Attach to an <input> element or a &lt;<!-- -->div contentEditable<!-- -->&gt; to add type-ahead support.

export abstract class AbstractInputSuggest<T> extends PopoverSuggest<T> 
```

|  [`(constructor)(app, textInputEl)`](obsidian.AbstractInputSuggest.(constructor).md) |  | Accepts an <code>&lt;input&gt;</code> text box or a contenteditable div. |

|  [`limit`](obsidian.AbstractInputSuggest.limit.md) |  | <code>number</code> | Limit to the number of elements rendered at once. Set to 0 to disable. Defaults to 100. |

## Methods

|  [`getValue()`](obsidian.AbstractInputSuggest.getValue.md) |  | Gets the value from the input element. |
|  [`onSelect(callback)`](obsidian.AbstractInputSuggest.onSelect.md) |  | Registers a callback to handle when a suggestion is selected by the user. |
|  [`setValue(value)`](obsidian.AbstractInputSuggest.setValue.md) |  | Sets the value into the input element. |

[`Setting`](obsidian.Setting.md)

## Setting class

export class Setting 
```

|  [`(constructor)(containerEl)`](obsidian.Setting.(constructor).md) |  | Constructs a new instance of the <code>Setting</code> class |

|  [`components`](obsidian.Setting.components.md) |  | [`BaseComponent`](obsidian.BaseComponent.md)<code>[]</code> |  |
|  [`controlEl`](obsidian.Setting.controlEl.md) |  | <code>HTMLElement</code> |  |
|  [`descEl`](obsidian.Setting.descEl.md) |  | <code>HTMLElement</code> |  |
|  [`infoEl`](obsidian.Setting.infoEl.md) |  | <code>HTMLElement</code> |  |
|  [`nameEl`](obsidian.Setting.nameEl.md) |  | <code>HTMLElement</code> |  |
|  [`settingEl`](obsidian.Setting.settingEl.md) |  | <code>HTMLElement</code> |  |

## Methods

|  [`addButton(cb)`](obsidian.Setting.addButton.md) |  |  |
|  [`addColorPicker(cb)`](obsidian.Setting.addColorPicker.md) |  |  |
|  [`addDropdown(cb)`](obsidian.Setting.addDropdown.md) |  |  |
|  [`addExtraButton(cb)`](obsidian.Setting.addExtraButton.md) |  |  |
|  [`addMomentFormat(cb)`](obsidian.Setting.addMomentFormat.md) |  |  |
|  [`addProgressBar(cb)`](obsidian.Setting.addProgressBar.md) |  |  |
|  [`addSearch(cb)`](obsidian.Setting.addSearch.md) |  |  |
|  [`addSlider(cb)`](obsidian.Setting.addSlider.md) |  |  |
|  [`addText(cb)`](obsidian.Setting.addText.md) |  |  |
|  [`addTextArea(cb)`](obsidian.Setting.addTextArea.md) |  |  |
|  [`addToggle(cb)`](obsidian.Setting.addToggle.md) |  |  |
|  [`clear()`](obsidian.Setting.clear.md) |  |  |
|  [`setClass(cls)`](obsidian.Setting.setClass.md) |  |  |
|  [`setDesc(desc)`](obsidian.Setting.setDesc.md) |  |  |
|  [`setDisabled(disabled)`](obsidian.Setting.setDisabled.md) |  |  |
|  [`setHeading()`](obsidian.Setting.setHeading.md) |  |  |
|  [`setName(name)`](obsidian.Setting.setName.md) |  |  |
|  [`setTooltip(tooltip, options)`](obsidian.Setting.setTooltip.md) |  |  |
|  [`then(cb)`](obsidian.Setting.then.md) |  | Facilitates chaining |

[`Keymap`](obsidian.Keymap.md)

## Keymap class

export class Keymap 
```

## Methods

|  [`isModEvent(evt)`](obsidian.Keymap.isModEvent.md) | <code>static</code> | Translates an event into the type of pane that should open. Returns 'tab' if the modifier key Cmd/Ctrl is pressed OR if this is a middle-click MouseEvent. Returns 'split' if Cmd/Ctrl+Alt is pressed. Returns 'window' if Cmd/Ctrl+Alt+Shift is pressed. |
|  [`isModifier(evt, modifier)`](obsidian.Keymap.isModifier.md) | <code>static</code> | Checks whether the modifier key is pressed during this event |
|  [`popScope(scope)`](obsidian.Keymap.popScope.md) |  |  |
|  [`pushScope(scope)`](obsidian.Keymap.pushScope.md) |  |  |

[`WorkspaceTabs`](obsidian.WorkspaceTabs.md)

## WorkspaceTabs class

export class WorkspaceTabs extends WorkspaceParent 
```

[`fuzzySearch`](obsidian.fuzzySearch.md)

## fuzzySearch() function

export function fuzzySearch(q: PreparedQuery, text: string): SearchResult | null;
```

|  <code>q</code> | [`PreparedQuery`](obsidian.PreparedQuery.md) |  |

[`SearchResult`](obsidian.SearchResult.md)` | null`

[`KeymapEventHandler`](obsidian.KeymapEventHandler.md)

## KeymapEventHandler interface

export interface KeymapEventHandler extends KeymapInfo 
```
**Extends:** [`KeymapInfo`](obsidian.KeymapInfo.md)

|  [`scope`](obsidian.KeymapEventHandler.scope.md) |  | [`Scope`](obsidian.Scope.md) |  |

[`FrontMatterCache`](obsidian.FrontMatterCache.md)

## FrontMatterCache interface

export interface FrontMatterCache 
```

[`MarkdownEditView`](obsidian.MarkdownEditView.md)

## MarkdownEditView class

This is the editor for Obsidian Mobile as well as the upcoming WYSIWYG editor.

export class MarkdownEditView implements MarkdownSubView, HoverParent, MarkdownFileInfo 
```

|  [`(constructor)(view)`](obsidian.MarkdownEditView.(constructor).md) |  | Constructs a new instance of the <code>MarkdownEditView</code> class |

|  [`app`](obsidian.MarkdownEditView.app.md) |  | [`App`](obsidian.App.md) |  |
|  [`file`](obsidian.MarkdownEditView.file.md) | <code>readonly</code> | [`TFile`](obsidian.TFile.md) |  |
|  [`hoverPopover`](obsidian.MarkdownEditView.hoverPopover.md) |  | [`HoverPopover`](obsidian.HoverPopover.md) |  |

## Methods

|  [`applyScroll(scroll)`](obsidian.MarkdownEditView.applyScroll.md) |  |  |
|  [`clear()`](obsidian.MarkdownEditView.clear.md) |  |  |
|  [`get()`](obsidian.MarkdownEditView.get.md) |  |  |
|  [`getScroll()`](obsidian.MarkdownEditView.getScroll.md) |  |  |
|  [`getSelection()`](obsidian.MarkdownEditView.getSelection.md) |  |  |
|  [`set(data, clear)`](obsidian.MarkdownEditView.set.md) |  |  |

[`moment`](obsidian.moment.md)

## moment variable

moment: typeof Moment
```

[`Events`](obsidian.Events.md)

## Events class

export class Events 
```

## Methods

|  [`off(name, callback)`](obsidian.Events.off.md) |  |  |
|  [`offref(ref)`](obsidian.Events.offref.md) |  |  |
|  [`on(name, callback, ctx)`](obsidian.Events.on.md) |  |  |
|  [`trigger(name, data)`](obsidian.Events.trigger.md) |  |  |
|  [`tryTrigger(evt, args)`](obsidian.Events.tryTrigger.md) |  |  |

[`MarkdownView`](obsidian.MarkdownView.md)

## MarkdownView class

export class MarkdownView extends TextFileView implements MarkdownFileInfo 
```
**Extends:** [`TextFileView`](obsidian.TextFileView.md)

**Implements:** [`MarkdownFileInfo`](obsidian.MarkdownFileInfo.md)

|  [`(constructor)(leaf)`](obsidian.MarkdownView.(constructor).md) |  | Constructs a new instance of the <code>MarkdownView</code> class |

|  [`currentMode`](obsidian.MarkdownView.currentMode.md) |  | [`MarkdownSubView`](obsidian.MarkdownSubView.md) |  |
|  [`editor`](obsidian.MarkdownView.editor.md) |  | [`Editor`](obsidian.Editor.md) |  |
|  [`hoverPopover`](obsidian.MarkdownView.hoverPopover.md) |  | [`HoverPopover`](obsidian.HoverPopover.md)<code> &#124; null</code> |  |
|  [`previewMode`](obsidian.MarkdownView.previewMode.md) |  | [`MarkdownPreviewView`](obsidian.MarkdownPreviewView.md) |  |

## Methods

|  [`clear()`](obsidian.MarkdownView.clear.md) |  |  |
|  [`getMode()`](obsidian.MarkdownView.getMode.md) |  |  |
|  [`getViewData()`](obsidian.MarkdownView.getViewData.md) |  |  |
|  [`getViewType()`](obsidian.MarkdownView.getViewType.md) |  |  |
|  [`setViewData(data, clear)`](obsidian.MarkdownView.setViewData.md) |  |  |
|  [`showSearch(replace)`](obsidian.MarkdownView.showSearch.md) |  |  |

[`requestUrl`](obsidian.requestUrl.md)

## requestUrl() function

Similar to `fetch()`<!-- -->, request a URL using HTTP/HTTPS, without any CORS restrictions.

export function requestUrl(request: RequestUrlParam | string): RequestUrlResponsePromise;
```

[`requireApiVersion`](obsidian.requireApiVersion.md)

## requireApiVersion() function

Returns true if the API version is equal or higher than the requested version. Use this to limit functionality that require specific API versions to avoid crashing on older Obsidian builds.

export function requireApiVersion(version: string): boolean;
```

|  <code>version</code> | <code>string</code> |  |

`boolean`

[`CacheItem`](obsidian.CacheItem.md)

## CacheItem interface

export interface CacheItem 
```

|  [`position`](obsidian.CacheItem.position.md) |  | [`Pos`](obsidian.Pos.md) |  |

[`WorkspaceSidedock`](obsidian.WorkspaceSidedock.md)

## WorkspaceSidedock class

export class WorkspaceSidedock extends WorkspaceSplit 
```

|  [`collapsed`](obsidian.WorkspaceSidedock.collapsed.md) |  | <code>boolean</code> |  |

## Methods

|  [`collapse()`](obsidian.WorkspaceSidedock.collapse.md) |  |  |
|  [`expand()`](obsidian.WorkspaceSidedock.expand.md) |  |  |
|  [`toggle()`](obsidian.WorkspaceSidedock.toggle.md) |  |  |

[`EditableFileView`](obsidian.EditableFileView.md)

## EditableFileView class

export abstract class EditableFileView extends FileView 
```
**Extends:** [`FileView`](obsidian.FileView.md)

[`renderMath`](obsidian.renderMath.md)

## renderMath() function

Render some LaTeX math using the MathJax engine. Returns an HTMLElement. Requires calling `finishRenderMath` when rendering is all done to flush the MathJax stylesheet.

export function renderMath(source: string, display: boolean): HTMLElement;
```

|  <code>source</code> | <code>string</code> |  |
|  <code>display</code> | <code>boolean</code> |  |

`HTMLElement`

[`DataAdapter`](obsidian.DataAdapter.md)

## DataAdapter interface

Work directly with files and folders inside a vault. If possible prefer using the [Vault](obsidian.Vault.md) API over this.

export interface DataAdapter 
```

|  --- | --- |
|  [`append(normalizedPath, data, options)`](obsidian.DataAdapter.append.md) | Add text to the end of a plaintext file. |
|  [`copy(normalizedPath, normalizedNewPath)`](obsidian.DataAdapter.copy.md) | Create a copy of a file. This will fail if there is already a file at <code>normalizedNewPath</code>. |
|  [`exists(normalizedPath, sensitive)`](obsidian.DataAdapter.exists.md) | Check if something exists at the given path. |
|  [`getName()`](obsidian.DataAdapter.getName.md) |  |
|  [`getResourcePath(normalizedPath)`](obsidian.DataAdapter.getResourcePath.md) | Returns an URI for the browser engine to use, for example to embed an image. |
|  [`list(normalizedPath)`](obsidian.DataAdapter.list.md) | Retrieve a list of all files and folders inside the given folder, non-recursive. |
|  [`mkdir(normalizedPath)`](obsidian.DataAdapter.mkdir.md) | Create a directory. |
|  [`process(normalizedPath, fn, options)`](obsidian.DataAdapter.process.md) | Atomically read, modify, and save the contents of a plaintext file. |
|  [`read(normalizedPath)`](obsidian.DataAdapter.read.md) |  |
|  [`readBinary(normalizedPath)`](obsidian.DataAdapter.readBinary.md) |  |
|  [`remove(normalizedPath)`](obsidian.DataAdapter.remove.md) | Delete a file. |
|  [`rename(normalizedPath, normalizedNewPath)`](obsidian.DataAdapter.rename.md) | Rename a file or folder. |
|  [`rmdir(normalizedPath, recursive)`](obsidian.DataAdapter.rmdir.md) | Remove a directory. |
|  [`stat(normalizedPath)`](obsidian.DataAdapter.stat.md) | Retrieve metadata about the given file/folder. |
|  [`trashLocal(normalizedPath)`](obsidian.DataAdapter.trashLocal.md) | Move to local trash. Files will be moved into the <code>.trash</code> folder at the root of the vault. |
|  [`trashSystem(normalizedPath)`](obsidian.DataAdapter.trashSystem.md) | Try moving to system trash. |

|  [`write(normalizedPath, data, options)`](obsidian.DataAdapter.write.md) | Write to a plaintext file. If the file exists its content will be overwritten, otherwise the file will be created. |
|  [`writeBinary(normalizedPath, data, options)`](obsidian.DataAdapter.writeBinary.md) | Write to a binary file. If the file exists its content will be overwritten, otherwise the file will be created. |

[`AbstractTextComponent`](obsidian.AbstractTextComponent.md)

## AbstractTextComponent class

export class AbstractTextComponent<T extends HTMLInputElement | HTMLTextAreaElement> extends ValueComponent<string> 
```

|  [`(constructor)(inputEl)`](obsidian.AbstractTextComponent.(constructor).md) |  | Constructs a new instance of the <code>AbstractTextComponent</code> class |

|  [`inputEl`](obsidian.AbstractTextComponent.inputEl.md) |  | <code>T</code> |  |

## Methods

|  [`getValue()`](obsidian.AbstractTextComponent.getValue.md) |  |  |
|  [`onChange(callback)`](obsidian.AbstractTextComponent.onChange.md) |  |  |
|  [`onChanged()`](obsidian.AbstractTextComponent.onChanged.md) |  |  |
|  [`setDisabled(disabled)`](obsidian.AbstractTextComponent.setDisabled.md) |  |  |
|  [`setPlaceholder(placeholder)`](obsidian.AbstractTextComponent.setPlaceholder.md) |  |  |
|  [`setValue(value)`](obsidian.AbstractTextComponent.setValue.md) |  |  |

[`Notice`](obsidian.Notice.md)

## Notice class

Notification component. Use to present timely, high-value information.

export class Notice 
```

|  [`(constructor)(message, duration)`](obsidian.Notice.(constructor).md) |  | Constructs a new instance of the <code>Notice</code> class |

|  [`noticeEl`](obsidian.Notice.noticeEl.md) |  | <code>HTMLElement</code> |  |

## Methods

|  [`hide()`](obsidian.Notice.hide.md) |  |  |
|  [`setMessage(message)`](obsidian.Notice.setMessage.md) |  | Change the message of this notice. |

[`EditorSuggestTriggerInfo`](obsidian.EditorSuggestTriggerInfo.md)

## EditorSuggestTriggerInfo interface

export interface EditorSuggestTriggerInfo 
```

|  [`end`](obsidian.EditorSuggestTriggerInfo.end.md) |  | [`EditorPosition`](obsidian.EditorPosition.md) | The end position of the triggering text. This is used to position the popover. |
|  [`query`](obsidian.EditorSuggestTriggerInfo.query.md) |  | <code>string</code> | They query string (usually the text between start and end) that will be used to generate the suggestion content. |
|  [`start`](obsidian.EditorSuggestTriggerInfo.start.md) |  | [`EditorPosition`](obsidian.EditorPosition.md) | The start position of the triggering text. This is used to position the popover. |

[`loadMathJax`](obsidian.loadMathJax.md)

## loadMathJax() function

Load MathJax.

export function loadMathJax(): Promise<void>;
```

[`ButtonComponent`](obsidian.ButtonComponent.md)

## ButtonComponent class

export class ButtonComponent extends BaseComponent 
```

|  [`(constructor)(containerEl)`](obsidian.ButtonComponent.(constructor).md) |  | Constructs a new instance of the <code>ButtonComponent</code> class |

|  [`buttonEl`](obsidian.ButtonComponent.buttonEl.md) |  | <code>HTMLButtonElement</code> |  |

## Methods

|  [`onClick(callback)`](obsidian.ButtonComponent.onClick.md) |  |  |
|  [`removeCta()`](obsidian.ButtonComponent.removeCta.md) |  |  |
|  [`setButtonText(name)`](obsidian.ButtonComponent.setButtonText.md) |  |  |
|  [`setClass(cls)`](obsidian.ButtonComponent.setClass.md) |  |  |
|  [`setCta()`](obsidian.ButtonComponent.setCta.md) |  |  |
|  [`setDisabled(disabled)`](obsidian.ButtonComponent.setDisabled.md) |  |  |
|  [`setIcon(icon)`](obsidian.ButtonComponent.setIcon.md) |  |  |
|  [`setTooltip(tooltip, options)`](obsidian.ButtonComponent.setTooltip.md) |  |  |
|  [`setWarning()`](obsidian.ButtonComponent.setWarning.md) |  |  |

[`editorEditorField`](obsidian.editorEditorField.md)

## editorEditorField variable

Use this StateField to get a reference to the EditorView

editorEditorField: StateField<EditorView>
```

[`livePreviewState`](obsidian.livePreviewState.md)

## livePreviewState variable

livePreviewState: ViewPlugin<LivePreviewState>
```

[`EditorCommandName`](obsidian.EditorCommandName.md)

## EditorCommandName type

export type EditorCommandName = 'goUp' | 'goDown' | 'goLeft' | 'goRight' | 'goStart' | 'goEnd' | 'goWordLeft' | 'goWordRight' | 'indentMore' | 'indentLess' | 'newlineAndIndent' | 'swapLineUp' | 'swapLineDown' | 'deleteLine' | 'toggleFold' | 'foldAll' | 'unfoldAll';
```

[`KeymapContext`](obsidian.KeymapContext.md)

## KeymapContext interface

export interface KeymapContext extends KeymapInfo 
```

|  [`vkey`](obsidian.KeymapContext.vkey.md) |  | <code>string</code> |  |

[`getLinkpath`](obsidian.getLinkpath.md)

## getLinkpath() function

export function getLinkpath(linktext: string): string;
```

`string`

[`apiVersion`](obsidian.apiVersion.md)

## apiVersion variable

This is the API version of the app, which follows the release cycle of the desktop app. Example: "0.13.21"

apiVersion: string
```

[`ObsidianProtocolData`](obsidian.ObsidianProtocolData.md)

## ObsidianProtocolData interface

export interface ObsidianProtocolData 
```

|  [`action`](obsidian.ObsidianProtocolData.action.md) |  | <code>string</code> |  |

[`TagCache`](obsidian.TagCache.md)

## TagCache interface

export interface TagCache extends CacheItem 
```

|  [`tag`](obsidian.TagCache.tag.md) |  | <code>string</code> |  |

[`PaneType`](obsidian.PaneType.md)

## PaneType type

export type PaneType = 'tab' | 'split' | 'window';
```

[`TextFileView`](obsidian.TextFileView.md)

## TextFileView class

This class implements a plaintext-based editable file view, which can be loaded and saved given an editor.

Note that by default, this view only saves when it's closing. To implement auto-save, your editor should call `this.requestSave()` when the content is changed.

export abstract class TextFileView extends EditableFileView 
```
**Extends:** [`EditableFileView`](obsidian.EditableFileView.md)

|  [`(constructor)(leaf)`](obsidian.TextFileView.(constructor).md) |  | Constructs a new instance of the <code>TextFileView</code> class |

|  [`data`](obsidian.TextFileView.data.md) |  | <code>string</code> | In memory data |
|  [`requestSave`](obsidian.TextFileView.requestSave.md) |  | <code>() =&gt; void</code> | Debounced save in 2 seconds from now |

## Methods

|  [`clear()`](obsidian.TextFileView.clear.md) | <code>abstract</code> | Clear the editor. This is usually called when we're about to open a completely different file, so it's best to clear any editor states like undo-redo history, and any caches/indexes associated with the previous file contents. |
|  [`getViewData()`](obsidian.TextFileView.getViewData.md) | <code>abstract</code> | Gets the data from the editor. This will be called to save the editor contents to the file. |
|  [`onLoadFile(file)`](obsidian.TextFileView.onLoadFile.md) |  |  |
|  [`onUnloadFile(file)`](obsidian.TextFileView.onUnloadFile.md) |  |  |
|  [`save(clear)`](obsidian.TextFileView.save.md) |  |  |
|  [`setViewData(data, clear)`](obsidian.TextFileView.setViewData.md) | <code>abstract</code> | <p>Set the data to the editor. This is used to load the file contents.</p><p>If clear is set, then it means we're opening a completely different file. In that case, you should call clear(), or implement a slightly more efficient clearing mechanism given the new data to be set.</p> |

[`ColorComponent`](obsidian.ColorComponent.md)

## ColorComponent class

Color picker component. Values are by default 6-digit hash-prefixed hex strings like `#000000`<!-- -->.

export class ColorComponent extends ValueComponent<string> 
```

|  [`(constructor)(containerEl)`](obsidian.ColorComponent.(constructor).md) |  | Constructs a new instance of the <code>ColorComponent</code> class |

## Methods

|  [`getValue()`](obsidian.ColorComponent.getValue.md) |  |  |
|  [`getValueHsl()`](obsidian.ColorComponent.getValueHsl.md) |  |  |
|  [`getValueRgb()`](obsidian.ColorComponent.getValueRgb.md) |  |  |
|  [`onChange(callback)`](obsidian.ColorComponent.onChange.md) |  |  |
|  [`setDisabled(disabled)`](obsidian.ColorComponent.setDisabled.md) |  |  |
|  [`setValue(value)`](obsidian.ColorComponent.setValue.md) |  |  |
|  [`setValueHsl(hsl)`](obsidian.ColorComponent.setValueHsl.md) |  |  |
|  [`setValueRgb(rgb)`](obsidian.ColorComponent.setValueRgb.md) |  |  |

[`RequestUrlResponse`](obsidian.RequestUrlResponse.md)

## RequestUrlResponse interface

export interface RequestUrlResponse 
```

|  [`arrayBuffer`](obsidian.RequestUrlResponse.arrayBuffer.md) |  | <code>ArrayBuffer</code> |  |
|  [`headers`](obsidian.RequestUrlResponse.headers.md) |  | <code>Record</code><code>&lt;string, string&gt;</code> |  |
|  [`json`](obsidian.RequestUrlResponse.json.md) |  | <code>any</code> |  |
|  [`status`](obsidian.RequestUrlResponse.status.md) |  | <code>number</code> |  |
|  [`text`](obsidian.RequestUrlResponse.text.md) |  | <code>string</code> |  |

[`removeIcon`](obsidian.removeIcon.md)

## removeIcon() function

Remove a custom icon from the library.

export function removeIcon(iconId: string): void;
```

`void`

[`parseYaml`](obsidian.parseYaml.md)

## parseYaml() function

export function parseYaml(yaml: string): any;
```

|  <code>yaml</code> | <code>string</code> |  |

`any`

[`editorViewField`](obsidian.editorViewField.md)

## editorViewField variable

> 
> use [editorInfoField](obsidian.editorInfoField.md) instead.
> 

Use this StateField to get a reference to the MarkdownView. This is now deprecated because it is possible for an editor to not be associated with a MarkdownView.

editorViewField: StateField<MarkdownView>
```

[`WorkspaceSplit`](obsidian.WorkspaceSplit.md)

## WorkspaceSplit class

export class WorkspaceSplit extends WorkspaceParent 
```

### Foundations

Abstracted variables for colors, spacing, typography and more

- [[Borders]]
- [[Colors]]
- [[Cursor]]
- [[Reference/CSS variables/Foundations/Icons|Icons]]
- [[Layers]]
- [[Radiuses]]
- [[Spacing]]
- [[Typography]]

Interactive components used throughout the app

- [[Button]]
- [[Checkbox]]
- [[Color input]]
- [[Dialog]]
- [[Dragging]]
- [[Indentation guides]]
- [[Modal]]
- [[Multi-select]]
- [[Navigation]]
- [[Popover]]
- [[Slider]]
- [[Tabs]]
- [[Text input]]
- [[Toggle]]

### Editor

Content types and variables used for editing and reading text files

- [[Block]]
- [[Blockquote]]
- [[Callout]]
- [[Code]]
- [[Embed]]
- [[File]]
- [[Footnote]]
- [[Headings]]
- [[Horizontal rule]]
- [[Inline title]]
- [[Link]]
- [[List]]
- [[Properties]]
- [[Table]]
- [[Tag]]

### Plugins

Variables related to interface elements in core plugins

- [[Canvas]]
- [[Graph]]

### Window

Variables related to the window chrome for the Obsidian app

- [[Divider]]
- [[Ribbon]]
- [[Scrollbar]]
- [[Reference/CSS variables/Window/Status bar|Status bar]]
- [[Window frame]]
- [[Reference/CSS variables/Window/Workspace|Workspace]]

### Obsidian Publish

Variables for Obsidian Publish sites

- [[Site fonts]]
- [[Site header]]
- [[Site navigation]]
- [[Site components]]
- [[Site sidebars]]
- [[Site pages]]

docs/obsidian-developer/Reference/CSS variables/CSS variables.md

The Obsidian app uses [Cascading Style Sheets](https://en.wikipedia.org/wiki/CSS) (CSS) to control the design of the user interface. CSS is the same markup language used for websites and web-based apps, which means you can find many resources online to help you learn how to use and edit CSS.

Obsidian includes hundreds of [[CSS variables]] that enable consistently beautiful user interfaces.

## For plugins

By using the built-in CSS variables for you own custom elements, you can create native-looking user interfaces in your plugin that look beautiful and are compatible with community themes.

**styles.css**:

```css
.todo-list {
  background-color: var(--background-secondary);
}
```

## For themes and snippets

By overriding the default values for the Obsidian CSS variables, you can create beautiful themes without the need for complex CSS selectors.

**theme.css**:

```css
  --background-primary: #18004F;
  --background-secondary: #220070;
}

  --background-primary: #ECE4FF;
  --background-secondary: #D9C9FF;
}
```

To learn more about how to build a theme using CSS variables, refer to [[Build a theme]].

docs/obsidian-developer/Reference/CSS variables/About styling.md

[`HeadingCache`](obsidian.HeadingCache.md) › [`level`](obsidian.HeadingCache.level.md)

## HeadingCache.level property

level: number;
```

[`HeadingCache`](obsidian.HeadingCache.md) › [`heading`](obsidian.HeadingCache.heading.md)

## HeadingCache.heading property

heading: string;
```

[`TFolder`](obsidian.TFolder.md) › [`isRoot`](obsidian.TFolder.isRoot.md)

## TFolder.isRoot() method

isRoot(): boolean;
```

`boolean`

[`TFolder`](obsidian.TFolder.md) › [`children`](obsidian.TFolder.children.md)

## TFolder.children property

children: TAbstractFile[];
```

[`MenuPositionDef`](obsidian.MenuPositionDef.md) › [`width`](obsidian.MenuPositionDef.width.md)

## MenuPositionDef.width property

width?: number;
```

[`MenuPositionDef`](obsidian.MenuPositionDef.md) › [`overlap`](obsidian.MenuPositionDef.overlap.md)

## MenuPositionDef.overlap property

overlap?: boolean;
```

[`MenuPositionDef`](obsidian.MenuPositionDef.md) › [`left`](obsidian.MenuPositionDef.left.md)

## MenuPositionDef.left property

left?: boolean;
```

[`MenuPositionDef`](obsidian.MenuPositionDef.md) › [`x`](obsidian.MenuPositionDef.x.md)

## MenuPositionDef.x property

x: number;
```

[`MenuPositionDef`](obsidian.MenuPositionDef.md) › [`y`](obsidian.MenuPositionDef.y.md)

## MenuPositionDef.y property

y: number;
```

[`RequestUrlResponsePromise`](obsidian.RequestUrlResponsePromise.md) › [`text`](obsidian.RequestUrlResponsePromise.text.md)

## RequestUrlResponsePromise.text property

text: Promise<string>;
```

[`RequestUrlResponsePromise`](obsidian.RequestUrlResponsePromise.md) › [`json`](obsidian.RequestUrlResponsePromise.json.md)

## RequestUrlResponsePromise.json property

json: Promise<any>;
```

[`RequestUrlResponsePromise`](obsidian.RequestUrlResponsePromise.md) › [`arrayBuffer`](obsidian.RequestUrlResponsePromise.arrayBuffer.md)

## RequestUrlResponsePromise.arrayBuffer property

arrayBuffer: Promise<ArrayBuffer>;
```

[`PreparedQuery`](obsidian.PreparedQuery.md) › [`query`](obsidian.PreparedQuery.query.md)

## PreparedQuery.query property

query: string;
```

[`PreparedQuery`](obsidian.PreparedQuery.md) › [`fuzzy`](obsidian.PreparedQuery.fuzzy.md)

## PreparedQuery.fuzzy property

fuzzy: string[];
```

[`PreparedQuery`](obsidian.PreparedQuery.md) › [`tokens`](obsidian.PreparedQuery.tokens.md)

## PreparedQuery.tokens property

tokens: string[];
```

[`MarkdownSubView`](obsidian.MarkdownSubView.md) › [`get`](obsidian.MarkdownSubView.get.md)

## MarkdownSubView.get() method

get(): string;
```

`string`

[`MarkdownSubView`](obsidian.MarkdownSubView.md) › [`set`](obsidian.MarkdownSubView.set.md)

## MarkdownSubView.set() method

set(data: string, clear: boolean): void;
```

|  <code>data</code> | <code>string</code> |  |
|  <code>clear</code> | <code>boolean</code> |  |

`void`

[`MarkdownSubView`](obsidian.MarkdownSubView.md) › [`applyScroll`](obsidian.MarkdownSubView.applyScroll.md)

## MarkdownSubView.applyScroll() method

applyScroll(scroll: number): void;
```

|  <code>scroll</code> | <code>number</code> |  |

`void`

[`MarkdownSubView`](obsidian.MarkdownSubView.md) › [`getScroll`](obsidian.MarkdownSubView.getScroll.md)

## MarkdownSubView.getScroll() method

getScroll(): number;
```

`number`

[`EditorSelection`](obsidian.EditorSelection.md) › [`head`](obsidian.EditorSelection.head.md)

## EditorSelection.head property

head: EditorPosition;
```

[`EditorSelection`](obsidian.EditorSelection.md) › [`anchor`](obsidian.EditorSelection.anchor.md)

## EditorSelection.anchor property

anchor: EditorPosition;
```

[`TooltipOptions`](obsidian.TooltipOptions.md) › [`delay`](obsidian.TooltipOptions.delay.md)

## TooltipOptions.delay property

delay?: number;
```

[`TooltipOptions`](obsidian.TooltipOptions.md) › [`placement`](obsidian.TooltipOptions.placement.md)

## TooltipOptions.placement property

placement?: TooltipPlacement;
```

[`WorkspaceWindowInitData`](obsidian.WorkspaceWindowInitData.md) › [`size`](obsidian.WorkspaceWindowInitData.size.md)

## WorkspaceWindowInitData.size property

The suggested size

size?: {
        width: number;
        height: number;
    };
```

[`EditorTransaction`](obsidian.EditorTransaction.md) › [`selection`](obsidian.EditorTransaction.selection.md)

## EditorTransaction.selection property

selection?: EditorRangeOrCaret;
```

[`EditorTransaction`](obsidian.EditorTransaction.md) › [`changes`](obsidian.EditorTransaction.changes.md)

## EditorTransaction.changes property

changes?: EditorChange[];
```

[`EditorTransaction`](obsidian.EditorTransaction.md) › [`selections`](obsidian.EditorTransaction.selections.md)

## EditorTransaction.selections property

Multiple selections, overrides `selection`<!-- -->.

selections?: EditorRangeOrCaret[];
```

[`EditorTransaction`](obsidian.EditorTransaction.md) › [`replaceSelection`](obsidian.EditorTransaction.replaceSelection.md)

## EditorTransaction.replaceSelection property

replaceSelection?: string;
```

[`LivePreviewState`](obsidian.LivePreviewState.md) › [`mousedown`](obsidian.LivePreviewState.mousedown.md)

## LivePreviewState.mousedown property

True if the left mouse is currently held down in the editor (for example, when drag-to-select text).

mousedown: boolean;
```

[`Tasks`](obsidian.Tasks.md) › [`add`](obsidian.Tasks.add.md)

## Tasks.add() method

add(callback: () => Promise<any>): void;
```

|  <code>callback</code> | <code>() =&gt; </code><code>Promise</code><code>&lt;any&gt;</code> |  |

`void`

[`Tasks`](obsidian.Tasks.md) › [`isEmpty`](obsidian.Tasks.isEmpty.md)

## Tasks.isEmpty() method

isEmpty(): boolean;
```

`boolean`

[`Tasks`](obsidian.Tasks.md) › [`promise`](obsidian.Tasks.promise.md)

## Tasks.promise() method

promise(): Promise<any>;
```

[`Tasks`](obsidian.Tasks.md) › [`addPromise`](obsidian.Tasks.addPromise.md)

## Tasks.addPromise() method

addPromise(promise: Promise<any>): void;
```

|  <code>promise</code> | <code>Promise</code><code>&lt;any&gt;</code> |  |

`void`

[`HeadingSubpathResult`](obsidian.HeadingSubpathResult.md) › [`next`](obsidian.HeadingSubpathResult.next.md)

## HeadingSubpathResult.next property

next: HeadingCache;
```

[`HeadingSubpathResult`](obsidian.HeadingSubpathResult.md) › [`current`](obsidian.HeadingSubpathResult.current.md)

## HeadingSubpathResult.current property

current: HeadingCache;
```

[`HeadingSubpathResult`](obsidian.HeadingSubpathResult.md) › [`type`](obsidian.HeadingSubpathResult.type.md)

## HeadingSubpathResult.type property

type: 'heading';
```

[`WorkspaceContainer`](obsidian.WorkspaceContainer.md) › [`doc`](obsidian.WorkspaceContainer.doc.md)

## WorkspaceContainer.doc property

abstract doc: Document;
```

[`WorkspaceContainer`](obsidian.WorkspaceContainer.md) › [`win`](obsidian.WorkspaceContainer.win.md)

## WorkspaceContainer.win property

abstract win: Window;
```

[`PluginSettingTab`](obsidian.PluginSettingTab.md) › [`(constructor)`](obsidian.PluginSettingTab.(constructor).md)

## PluginSettingTab.(constructor)

Constructs a new instance of the `PluginSettingTab` class

constructor(app: App, plugin: Plugin);
```

|  <code>app</code> | [`App`](obsidian.App.md) |  |
|  <code>plugin</code> | [`Plugin`](obsidian.Plugin.md) |  |

[`SubpathResult`](obsidian.SubpathResult.md) › [`end`](obsidian.SubpathResult.end.md)

## SubpathResult.end property

end: Loc | null;
```

[`SubpathResult`](obsidian.SubpathResult.md) › [`start`](obsidian.SubpathResult.start.md)

## SubpathResult.start property

start: Loc;
```

[`EditorRangeOrCaret`](obsidian.EditorRangeOrCaret.md) › [`to`](obsidian.EditorRangeOrCaret.to.md)

## EditorRangeOrCaret.to property

to?: EditorPosition;
```

[`EditorRangeOrCaret`](obsidian.EditorRangeOrCaret.md) › [`from`](obsidian.EditorRangeOrCaret.from.md)

## EditorRangeOrCaret.from property

from: EditorPosition;
```

[`App`](obsidian.App.md) › [`lastEvent`](obsidian.App.lastEvent.md)

## App.lastEvent property

The last known user interaction event, to help commands find out what modifier keys are pressed.

lastEvent: UserEvent | null;
```

[`App`](obsidian.App.md) › [`vault`](obsidian.App.vault.md)

## App.vault property

vault: Vault;
```

[`App`](obsidian.App.md) › [`scope`](obsidian.App.scope.md)

## App.scope property

scope: Scope;
```

[`App`](obsidian.App.md) › [`workspace`](obsidian.App.workspace.md)

## App.workspace property

workspace: Workspace;
```

[`App`](obsidian.App.md) › [`fileManager`](obsidian.App.fileManager.md)

## App.fileManager property

fileManager: FileManager;
```

[`App`](obsidian.App.md) › [`metadataCache`](obsidian.App.metadataCache.md)

## App.metadataCache property

metadataCache: MetadataCache;
```

[`App`](obsidian.App.md) › [`keymap`](obsidian.App.keymap.md)

## App.keymap property

keymap: Keymap;
```

[`MarkdownSectionInformation`](obsidian.MarkdownSectionInformation.md) › [`text`](obsidian.MarkdownSectionInformation.text.md)

## MarkdownSectionInformation.text property

text: string;
```

[`MarkdownSectionInformation`](obsidian.MarkdownSectionInformation.md) › [`lineEnd`](obsidian.MarkdownSectionInformation.lineEnd.md)

## MarkdownSectionInformation.lineEnd property

lineEnd: number;
```

[`MarkdownSectionInformation`](obsidian.MarkdownSectionInformation.md) › [`lineStart`](obsidian.MarkdownSectionInformation.lineStart.md)

## MarkdownSectionInformation.lineStart property

lineStart: number;
```

[`Loc`](obsidian.Loc.md) › [`col`](obsidian.Loc.col.md)

## Loc.col property

col: number;
```

[`Loc`](obsidian.Loc.md) › [`offset`](obsidian.Loc.offset.md)

## Loc.offset property

offset: number;
```

[`Loc`](obsidian.Loc.md) › [`line`](obsidian.Loc.line.md)

## Loc.line property

line: number;
```

[`WorkspaceSidedock`](obsidian.WorkspaceSidedock.md) › [`expand`](obsidian.WorkspaceSidedock.expand.md)

## WorkspaceSidedock.expand() method

expand(): void;
```

`void`

[`WorkspaceSidedock`](obsidian.WorkspaceSidedock.md) › [`collapsed`](obsidian.WorkspaceSidedock.collapsed.md)

## WorkspaceSidedock.collapsed property

collapsed: boolean;
```

[`WorkspaceSidedock`](obsidian.WorkspaceSidedock.md) › [`toggle`](obsidian.WorkspaceSidedock.toggle.md)

## WorkspaceSidedock.toggle() method

toggle(): void;
```

`void`

[`WorkspaceSidedock`](obsidian.WorkspaceSidedock.md) › [`collapse`](obsidian.WorkspaceSidedock.collapse.md)

## WorkspaceSidedock.collapse() method

collapse(): void;
```

`void`

[`KeymapContext`](obsidian.KeymapContext.md) › [`vkey`](obsidian.KeymapContext.vkey.md)

## KeymapContext.vkey property

vkey: string;
```

[`ObsidianProtocolData`](obsidian.ObsidianProtocolData.md) › [`action`](obsidian.ObsidianProtocolData.action.md)

## ObsidianProtocolData.action property

action: string;
```

[`MarkdownPostProcessorContext`](obsidian.MarkdownPostProcessorContext.md) › [`sourcePath`](obsidian.MarkdownPostProcessorContext.sourcePath.md)

## MarkdownPostProcessorContext.sourcePath property

sourcePath: string;
```

[`MarkdownPostProcessorContext`](obsidian.MarkdownPostProcessorContext.md) › [`frontmatter`](obsidian.MarkdownPostProcessorContext.frontmatter.md)

## MarkdownPostProcessorContext.frontmatter property

frontmatter: any | null | undefined;
```

[`MarkdownPostProcessorContext`](obsidian.MarkdownPostProcessorContext.md) › [`addChild`](obsidian.MarkdownPostProcessorContext.addChild.md)

## MarkdownPostProcessorContext.addChild() method

Adds a child component that will have its lifecycle managed by the renderer.

Use this to add a dependent child to the renderer such that if the containerEl of the child is ever removed, the component's unload will be called.

addChild(child: MarkdownRenderChild): void;
```

|  <code>child</code> | [`MarkdownRenderChild`](obsidian.MarkdownRenderChild.md) |  |

`void`

[`MarkdownPostProcessorContext`](obsidian.MarkdownPostProcessorContext.md) › [`getSectionInfo`](obsidian.MarkdownPostProcessorContext.getSectionInfo.md)

## MarkdownPostProcessorContext.getSectionInfo() method

Gets the section information of this element at this point in time. Only call this function right before you need this information to get the most up-to-date version. This function may also return null in many circumstances; if you use it, you must be prepared to deal with nulls.

getSectionInfo(el: HTMLElement): MarkdownSectionInformation | null;
```

[`MarkdownSectionInformation`](obsidian.MarkdownSectionInformation.md)` | null`

[`MarkdownPostProcessorContext`](obsidian.MarkdownPostProcessorContext.md) › [`docId`](obsidian.MarkdownPostProcessorContext.docId.md)

## MarkdownPostProcessorContext.docId property

docId: string;
```

[`ColorComponent`](obsidian.ColorComponent.md) › [`getValue`](obsidian.ColorComponent.getValue.md)

## ColorComponent.getValue() method

getValue(): HexString;
```

[`ColorComponent`](obsidian.ColorComponent.md) › [`setDisabled`](obsidian.ColorComponent.setDisabled.md)

## ColorComponent.setDisabled() method

setDisabled(disabled: boolean): this;
```

|  <code>disabled</code> | <code>boolean</code> |  |

`this`

[`ColorComponent`](obsidian.ColorComponent.md) › [`onChange`](obsidian.ColorComponent.onChange.md)

## ColorComponent.onChange() method

onChange(callback: (value: string) => any): this;
```

|  <code>callback</code> | <code>(value: string) =&gt; any</code> |  |

`this`

[`ColorComponent`](obsidian.ColorComponent.md) › [`getValueRgb`](obsidian.ColorComponent.getValueRgb.md)

## ColorComponent.getValueRgb() method

getValueRgb(): RGB;
```

[`ColorComponent`](obsidian.ColorComponent.md) › [`setValue`](obsidian.ColorComponent.setValue.md)

## ColorComponent.setValue() method

setValue(value: HexString): this;
```

|  <code>value</code> | [`HexString`](obsidian.HexString.md) |  |

`this`

[`ColorComponent`](obsidian.ColorComponent.md) › [`setValueRgb`](obsidian.ColorComponent.setValueRgb.md)

## ColorComponent.setValueRgb() method

setValueRgb(rgb: RGB): this;
```

|  <code>rgb</code> | [`RGB`](obsidian.RGB.md) |  |

`this`

[`ColorComponent`](obsidian.ColorComponent.md) › [`getValueHsl`](obsidian.ColorComponent.getValueHsl.md)

## ColorComponent.getValueHsl() method

getValueHsl(): HSL;
```

[`ColorComponent`](obsidian.ColorComponent.md) › [`(constructor)`](obsidian.ColorComponent.(constructor).md)

## ColorComponent.(constructor)

Constructs a new instance of the `ColorComponent` class

constructor(containerEl: HTMLElement);
```

|  <code>containerEl</code> | <code>HTMLElement</code> |  |

[`ColorComponent`](obsidian.ColorComponent.md) › [`setValueHsl`](obsidian.ColorComponent.setValueHsl.md)

## ColorComponent.setValueHsl() method

setValueHsl(hsl: HSL): this;
```

|  <code>hsl</code> | [`HSL`](obsidian.HSL.md) |  |

`this`

[`DataWriteOptions`](obsidian.DataWriteOptions.md) › [`ctime`](obsidian.DataWriteOptions.ctime.md)

## DataWriteOptions.ctime property

Time of creation, represented as a unix timestamp, in milliseconds. Omit this if you want to keep the default behaviour.

ctime?: number;
```

[`DataWriteOptions`](obsidian.DataWriteOptions.md) › [`mtime`](obsidian.DataWriteOptions.mtime.md)

## DataWriteOptions.mtime property

Time of last modification, represented as a unix timestamp, in milliseconds. Omit this if you want to keep the default behaviour.

mtime?: number;
```

[`WorkspaceRoot`](obsidian.WorkspaceRoot.md) › [`doc`](obsidian.WorkspaceRoot.doc.md)

## WorkspaceRoot.doc property

doc: Document;
```

[`WorkspaceRoot`](obsidian.WorkspaceRoot.md) › [`win`](obsidian.WorkspaceRoot.win.md)

## WorkspaceRoot.win property

win: Window;
```

[`ItemView`](obsidian.ItemView.md) › [`contentEl`](obsidian.ItemView.contentEl.md)

## ItemView.contentEl property

contentEl: HTMLElement;
```

[`ItemView`](obsidian.ItemView.md) › [`(constructor)`](obsidian.ItemView.(constructor).md)

## ItemView.(constructor)

Constructs a new instance of the `ItemView` class

constructor(leaf: WorkspaceLeaf);
```

|  <code>leaf</code> | [`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) |  |

[`ItemView`](obsidian.ItemView.md) › [`addAction`](obsidian.ItemView.addAction.md)

## ItemView.addAction() method

addAction(icon: IconName, title: string, callback: (evt: MouseEvent) => any): HTMLElement;
```

|  <code>icon</code> | [`IconName`](obsidian.IconName.md) |  |
|  <code>title</code> | <code>string</code> |  |
|  <code>callback</code> | <code>(evt: </code><code>MouseEvent</code><code>) =&gt; any</code> |  |

[`Point`](obsidian.Point.md) › [`x`](obsidian.Point.x.md)

## Point.x property

x: number;
```

[`Point`](obsidian.Point.md) › [`y`](obsidian.Point.y.md)

## Point.y property

y: number;
```

[`ToggleComponent`](obsidian.ToggleComponent.md) › [`getValue`](obsidian.ToggleComponent.getValue.md)

## ToggleComponent.getValue() method

getValue(): boolean;
```

`boolean`

[`ToggleComponent`](obsidian.ToggleComponent.md) › [`setTooltip`](obsidian.ToggleComponent.setTooltip.md)

## ToggleComponent.setTooltip() method

setTooltip(tooltip: string, options?: TooltipOptions): this;
```

|  <code>tooltip</code> | <code>string</code> |  |

`this`

[`ToggleComponent`](obsidian.ToggleComponent.md) › [`setDisabled`](obsidian.ToggleComponent.setDisabled.md)

## ToggleComponent.setDisabled() method

```

`this`

[`ToggleComponent`](obsidian.ToggleComponent.md) › [`onChange`](obsidian.ToggleComponent.onChange.md)

## ToggleComponent.onChange() method

onChange(callback: (value: boolean) => any): this;
```

|  <code>callback</code> | <code>(value: boolean) =&gt; any</code> |  |

`this`

[`ToggleComponent`](obsidian.ToggleComponent.md) › [`setValue`](obsidian.ToggleComponent.setValue.md)

## ToggleComponent.setValue() method

setValue(on: boolean): this;
```

|  <code>on</code> | <code>boolean</code> |  |

`this`

[`ToggleComponent`](obsidian.ToggleComponent.md) › [`(constructor)`](obsidian.ToggleComponent.(constructor).md)

## ToggleComponent.(constructor)

Constructs a new instance of the `ToggleComponent` class

```

[`ToggleComponent`](obsidian.ToggleComponent.md) › [`onClick`](obsidian.ToggleComponent.onClick.md)

## ToggleComponent.onClick() method

onClick(): void;
```

`void`

[`ToggleComponent`](obsidian.ToggleComponent.md) › [`toggleEl`](obsidian.ToggleComponent.toggleEl.md)

## ToggleComponent.toggleEl property

toggleEl: HTMLElement;
```

[`MarkdownPreviewRenderer`](obsidian.MarkdownPreviewRenderer.md) › [`unregisterPostProcessor`](obsidian.MarkdownPreviewRenderer.unregisterPostProcessor.md)

## MarkdownPreviewRenderer.unregisterPostProcessor() method

static unregisterPostProcessor(postProcessor: MarkdownPostProcessor): void;
```

|  <code>postProcessor</code> | [`MarkdownPostProcessor`](obsidian.MarkdownPostProcessor.md) |  |

`void`

[`MarkdownPreviewRenderer`](obsidian.MarkdownPreviewRenderer.md) › [`registerPostProcessor`](obsidian.MarkdownPreviewRenderer.registerPostProcessor.md)

## MarkdownPreviewRenderer.registerPostProcessor() method

static registerPostProcessor(postProcessor: MarkdownPostProcessor, sortOrder?: number): void;
```

|  <code>sortOrder</code> | <code>number</code> | _(Optional)_ |

`void`

[`MarkdownPreviewRenderer`](obsidian.MarkdownPreviewRenderer.md) › [`createCodeBlockPostProcessor`](obsidian.MarkdownPreviewRenderer.createCodeBlockPostProcessor.md)

## MarkdownPreviewRenderer.createCodeBlockPostProcessor() method

static createCodeBlockPostProcessor(language: string, handler: (source: string, el: HTMLElement, ctx: MarkdownPostProcessorContext) => Promise<any> | void): (el: HTMLElement, ctx: MarkdownPostProcessorContext) => void;
```

|  <code>language</code> | <code>string</code> |  |
|  <code>handler</code> | <code>(source: string, el: </code><code>HTMLElement</code><code>, ctx: </code>[`MarkdownPostProcessorContext`](obsidian.MarkdownPostProcessorContext.md)<code>) =&gt; </code><code>Promise</code><code>&lt;any&gt; &#124; void</code> |  |

`(el: ``HTMLElement``, ctx: `[`MarkdownPostProcessorContext`](obsidian.MarkdownPostProcessorContext.md)`) => void`

[`Workspace`](obsidian.Workspace.md) › [`on`](obsidian.Workspace.on_14.md)

## Workspace.on() method

on(name: 'codemirror', callback: (cm: CodeMirror.Editor) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'codemirror'</code> |  |
|  <code>callback</code> | <code>(cm: </code><code>CodeMirror.Editor</code><code>) =&gt; any</code> |  |
|  <code>ctx</code> | <code>any</code> | _(Optional)_ |

[`Workspace`](obsidian.Workspace.md) › [`duplicateLeaf`](obsidian.Workspace.duplicateLeaf.md)

## Workspace.duplicateLeaf() method

> 
> - Use the new form of this method instead
> 

duplicateLeaf(leaf: WorkspaceLeaf, direction?: SplitDirection): Promise<WorkspaceLeaf>;
```

|  <code>direction</code> | [`SplitDirection`](obsidian.SplitDirection.md) | _(Optional)_ |

`Promise``<`[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md)`>`

[`Workspace`](obsidian.Workspace.md) › [`rightSplit`](obsidian.Workspace.rightSplit.md)

## Workspace.rightSplit property

rightSplit: WorkspaceSidedock | WorkspaceMobileDrawer;
```

[`Workspace`](obsidian.Workspace.md) › [`getActiveFile`](obsidian.Workspace.getActiveFile.md)

## Workspace.getActiveFile() method

Returns the file for the current view if it's a FileView.

Otherwise, it will recent the most recently active file.

getActiveFile(): TFile | null;
```

[`TFile`](obsidian.TFile.md)` | null`

[`Workspace`](obsidian.Workspace.md) › [`on`](obsidian.Workspace.on_10.md)

Triggered when the user opens the context menu on an editor.

on(name: 'editor-menu', callback: (menu: Menu, editor: Editor, info: MarkdownView | MarkdownFileInfo) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'editor-menu'</code> |  |
|  <code>callback</code> | <code>(menu: </code>[`Menu`](obsidian.Menu.md)<code>, editor: </code>[`Editor`](obsidian.Editor.md)<code>, info: </code>[`MarkdownView`](obsidian.MarkdownView.md)<code> &#124; </code>[`MarkdownFileInfo`](obsidian.MarkdownFileInfo.md)<code>) =&gt; any</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`leftSplit`](obsidian.Workspace.leftSplit.md)

## Workspace.leftSplit property

leftSplit: WorkspaceSidedock | WorkspaceMobileDrawer;
```

[`Workspace`](obsidian.Workspace.md) › [`on`](obsidian.Workspace.on_11.md)

Triggered when changes to an editor has been applied, either programmatically or from a user event.

on(name: 'editor-change', callback: (editor: Editor, info: MarkdownView | MarkdownFileInfo) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'editor-change'</code> |  |
|  <code>callback</code> | <code>(editor: </code>[`Editor`](obsidian.Editor.md)<code>, info: </code>[`MarkdownView`](obsidian.MarkdownView.md)<code> &#124; </code>[`MarkdownFileInfo`](obsidian.MarkdownFileInfo.md)<code>) =&gt; any</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`layoutReady`](obsidian.Workspace.layoutReady.md)

## Workspace.layoutReady property

layoutReady: boolean;
```

[`Workspace`](obsidian.Workspace.md) › [`setActiveLeaf`](obsidian.Workspace.setActiveLeaf.md)

## Workspace.setActiveLeaf() method

Sets the active leaf

setActiveLeaf(leaf: WorkspaceLeaf, params?: {
        focus?: boolean;
    }): void;
```

|  <code>leaf</code> | [`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) | The new active leaf |
|  <code>params</code> | <code>{         focus?: boolean;     }</code> | _(Optional)_ Parameter object of whether to set the focus. |

`void`

[`Workspace`](obsidian.Workspace.md) › [`on`](obsidian.Workspace.on_15.md)

Triggered when the app is about to quit. Not guaranteed to actually run. Perform some best effort cleanup here.

on(name: 'quit', callback: (tasks: Tasks) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'quit'</code> |  |
|  <code>callback</code> | <code>(tasks: </code>[`Tasks`](obsidian.Tasks.md)<code>) =&gt; any</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`createLeafBySplit`](obsidian.Workspace.createLeafBySplit.md)

## Workspace.createLeafBySplit() method

createLeafBySplit(leaf: WorkspaceLeaf, direction?: SplitDirection, before?: boolean): WorkspaceLeaf;
```

|  <code>before</code> | <code>boolean</code> | _(Optional)_ |

[`Workspace`](obsidian.Workspace.md) › [`getLeafById`](obsidian.Workspace.getLeafById.md)

## Workspace.getLeafById() method

getLeafById(id: string): WorkspaceLeaf;
```

|  <code>id</code> | <code>string</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`on`](obsidian.Workspace.on_1.md)

on(name: 'resize', callback: () => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'resize'</code> |  |
|  <code>callback</code> | <code>() =&gt; any</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`activeEditor`](obsidian.Workspace.activeEditor.md)

## Workspace.activeEditor property

A component managing the current editor. This can be null if the active view has no editor.

activeEditor: MarkdownFileInfo | null;
```

[`Workspace`](obsidian.Workspace.md) › [`getMostRecentLeaf`](obsidian.Workspace.getMostRecentLeaf.md)

## Workspace.getMostRecentLeaf() method

getMostRecentLeaf(root?: WorkspaceParent): WorkspaceLeaf | null;
```

|  <code>root</code> | [`WorkspaceParent`](obsidian.WorkspaceParent.md) | _(Optional)_ |

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md)` | null`

[`Workspace`](obsidian.Workspace.md) › [`on`](obsidian.Workspace.on_5.md)

on(name: 'window-open', callback: (win: WorkspaceWindow, window: Window) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'window-open'</code> |  |
|  <code>callback</code> | <code>(win: </code>[`WorkspaceWindow`](obsidian.WorkspaceWindow.md)<code>, window: </code><code>Window</code><code>) =&gt; any</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`on`](obsidian.Workspace.on_4.md)

on(name: 'layout-change', callback: () => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'layout-change'</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`getRightLeaf`](obsidian.Workspace.getRightLeaf.md)

## Workspace.getRightLeaf() method

getRightLeaf(split: boolean): WorkspaceLeaf;
```

|  <code>split</code> | <code>boolean</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`requestSaveLayout`](obsidian.Workspace.requestSaveLayout.md)

## Workspace.requestSaveLayout property

requestSaveLayout: Debouncer<[], Promise<void>>;
```

[`Workspace`](obsidian.Workspace.md) › [`getLeaf`](obsidian.Workspace.getLeaf.md)

## Workspace.getLeaf() method

Creates a new leaf in a leaf adjacent to the currently active leaf. If direction is `'vertical'`<!-- -->, the leaf will appear to the right. If direction is `'horizontal'`<!-- -->, the leaf will appear below the current leaf.

getLeaf(newLeaf?: 'split', direction?: SplitDirection): WorkspaceLeaf;
```

|  <code>newLeaf</code> | <code>'split'</code> | _(Optional)_ |

[`Workspace`](obsidian.Workspace.md) › [`activeLeaf`](obsidian.Workspace.activeLeaf.md)

## Workspace.activeLeaf property

> 
> - The use of this field is discouraged.
> 

Indicates the currently focused leaf, if one exists.

Please avoid using `activeLeaf` directly, especially without checking whether `activeLeaf` is null.

The recommended alternatives are: - If you need information about the current view, use [Workspace.getActiveViewOfType()](obsidian.Workspace.getActiveViewOfType.md)<!-- -->. - If you need to open a new file or navigate a view, use [Workspace.getLeaf](obsidian.workspace.getleaf_1.md).

activeLeaf: WorkspaceLeaf | null;
```

[`Workspace`](obsidian.Workspace.md) › [`iterateAllLeaves`](obsidian.Workspace.iterateAllLeaves.md)

## Workspace.iterateAllLeaves() method

Iterate through all leaves, including main area leaves, floating leaves, and sidebar leaves.

iterateAllLeaves(callback: (leaf: WorkspaceLeaf) => any): void;
```

|  <code>callback</code> | <code>(leaf: </code>[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md)<code>) =&gt; any</code> |  |

`void`

[`Workspace`](obsidian.Workspace.md) › [`iterateCodeMirrors`](obsidian.Workspace.iterateCodeMirrors.md)

## Workspace.iterateCodeMirrors() method

iterateCodeMirrors(callback: (cm: CodeMirror.Editor) => any): void;
```

`void`

[`Workspace`](obsidian.Workspace.md) › [`on`](obsidian.Workspace.on_7.md)

Triggered when the CSS of the app has changed.

on(name: 'css-change', callback: () => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'css-change'</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`onLayoutReady`](obsidian.Workspace.onLayoutReady.md)

## Workspace.onLayoutReady() method

Runs the callback function right away if layout is already ready, or push it to a queue to be called later when layout is ready.

onLayoutReady(callback: () => any): void;
```

`void`

[`Workspace`](obsidian.Workspace.md) › [`containerEl`](obsidian.Workspace.containerEl.md)

## Workspace.containerEl property

containerEl: HTMLElement;
```

[`Workspace`](obsidian.Workspace.md) › [`on`](obsidian.Workspace.on_3.md)

on(name: 'file-open', callback: (file: TFile | null) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'file-open'</code> |  |
|  <code>callback</code> | <code>(file: </code>[`TFile`](obsidian.TFile.md)<code> &#124; null) =&gt; any</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`moveLeafToPopout`](obsidian.Workspace.moveLeafToPopout.md)

## Workspace.moveLeafToPopout() method

Migrates this leaf to a new popout window. Only works on the desktop app.

moveLeafToPopout(leaf: WorkspaceLeaf, data?: WorkspaceWindowInitData): WorkspaceWindow;
```

|  <code>data</code> | [`WorkspaceWindowInitData`](obsidian.WorkspaceWindowInitData.md) | _(Optional)_ |

[`Workspace`](obsidian.Workspace.md) › [`on`](obsidian.Workspace.on_2.md)

on(name: 'active-leaf-change', callback: (leaf: WorkspaceLeaf | null) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'active-leaf-change'</code> |  |
|  <code>callback</code> | <code>(leaf: </code>[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md)<code> &#124; null) =&gt; any</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`getLeavesOfType`](obsidian.Workspace.getLeavesOfType.md)

## Workspace.getLeavesOfType() method

getLeavesOfType(viewType: string): WorkspaceLeaf[];
```

|  <code>viewType</code> | <code>string</code> |  |

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md)`[]`

[`Workspace`](obsidian.Workspace.md) › [`createLeafInParent`](obsidian.Workspace.createLeafInParent.md)

## Workspace.createLeafInParent() method

createLeafInParent(parent: WorkspaceSplit, index: number): WorkspaceLeaf;
```

|  <code>parent</code> | [`WorkspaceSplit`](obsidian.WorkspaceSplit.md) |  |
|  <code>index</code> | <code>number</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`getLayout`](obsidian.Workspace.getLayout.md)

## Workspace.getLayout() method

getLayout(): any;
```

`any`

[`Workspace`](obsidian.Workspace.md) › [`getLastOpenFiles`](obsidian.Workspace.getLastOpenFiles.md)

## Workspace.getLastOpenFiles() method

getLastOpenFiles(): string[];
```

`string[]`

[`Workspace`](obsidian.Workspace.md) › [`splitActiveLeaf`](obsidian.Workspace.splitActiveLeaf.md)

## Workspace.splitActiveLeaf() method

> 
> - You should use [ | getLeaf(true)](obsidian.workspace.getleaf_1.md) instead which does the same thing.
> 

splitActiveLeaf(direction?: SplitDirection): WorkspaceLeaf;
```

[`Workspace`](obsidian.Workspace.md) › [`setActiveLeaf`](obsidian.Workspace.setActiveLeaf_1.md)

> 
> - function signature changed. Use other form instead
> 

setActiveLeaf(leaf: WorkspaceLeaf, pushHistory: boolean, focus: boolean): void;
```

|  <code>pushHistory</code> | <code>boolean</code> |  |
|  <code>focus</code> | <code>boolean</code> |  |

`void`

[`Workspace`](obsidian.Workspace.md) › [`openLinkText`](obsidian.Workspace.openLinkText.md)

## Workspace.openLinkText() method

openLinkText(linktext: string, sourcePath: string, newLeaf?: PaneType | boolean, openViewState?: OpenViewState): Promise<void>;
```

|  <code>sourcePath</code> | <code>string</code> |  |
|  <code>newLeaf</code> | [`PaneType`](obsidian.PaneType.md)<code> &#124; boolean</code> | _(Optional)_ |
|  <code>openViewState</code> | [`OpenViewState`](obsidian.OpenViewState.md) | _(Optional)_ |

[`Workspace`](obsidian.Workspace.md) › [`on`](obsidian.Workspace.on_6.md)

on(name: 'window-close', callback: (win: WorkspaceWindow, window: Window) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'window-close'</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`openPopoutLeaf`](obsidian.Workspace.openPopoutLeaf.md)

## Workspace.openPopoutLeaf() method

Open a new popout window with a single new leaf and return that leaf. Only works on the desktop app.

openPopoutLeaf(data?: WorkspaceWindowInitData): WorkspaceLeaf;
```

[`Workspace`](obsidian.Workspace.md) › [`on`](obsidian.Workspace.on_12.md)

Triggered when the editor receives a paste event. Check for `evt.defaultPrevented` before attempting to handle this event, and return if it has been already handled. Use `evt.preventDefault()` to indicate that you've handled the event.

on(name: 'editor-paste', callback: (evt: ClipboardEvent, editor: Editor, info: MarkdownView | MarkdownFileInfo) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'editor-paste'</code> |  |
|  <code>callback</code> | <code>(evt: </code><code>ClipboardEvent</code><code>, editor: </code>[`Editor`](obsidian.Editor.md)<code>, info: </code>[`MarkdownView`](obsidian.MarkdownView.md)<code> &#124; </code>[`MarkdownFileInfo`](obsidian.MarkdownFileInfo.md)<code>) =&gt; any</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`getLeftLeaf`](obsidian.Workspace.getLeftLeaf.md)

## Workspace.getLeftLeaf() method

getLeftLeaf(split: boolean): WorkspaceLeaf;
```

[`Workspace`](obsidian.Workspace.md) › [`rootSplit`](obsidian.Workspace.rootSplit.md)

## Workspace.rootSplit property

rootSplit: WorkspaceRoot;
```

[`Workspace`](obsidian.Workspace.md) › [`on`](obsidian.Workspace.on_9.md)

Triggered when the user opens the context menu with multiple files selected in the File Explorer.

on(name: 'files-menu', callback: (menu: Menu, files: TAbstractFile[], source: string, leaf?: WorkspaceLeaf) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'files-menu'</code> |  |
|  <code>callback</code> | <code>(menu: </code>[`Menu`](obsidian.Menu.md)<code>, files: </code>[`TAbstractFile`](obsidian.TAbstractFile.md)<code>[], source: string, leaf?: </code>[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md)<code>) =&gt; any</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`getActiveViewOfType`](obsidian.Workspace.getActiveViewOfType.md)

## Workspace.getActiveViewOfType() method

getActiveViewOfType<T extends View>(type: Constructor<T>): T | null;
```

|  <code>type</code> | [`Constructor`](obsidian.Constructor.md)<code>&lt;T&gt;</code> |  |

`T | null`

[`Workspace`](obsidian.Workspace.md) › [`detachLeavesOfType`](obsidian.Workspace.detachLeavesOfType.md)

## Workspace.detachLeavesOfType() method

detachLeavesOfType(viewType: string): void;
```

`void`

[`Workspace`](obsidian.Workspace.md) › [`on`](obsidian.Workspace.on.md)

on(name: 'quick-preview', callback: (file: TFile, data: string) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'quick-preview'</code> |  |
|  <code>callback</code> | <code>(file: </code>[`TFile`](obsidian.TFile.md)<code>, data: string) =&gt; any</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`leftRibbon`](obsidian.Workspace.leftRibbon.md)

## Workspace.leftRibbon property

leftRibbon: WorkspaceRibbon;
```

[`Workspace`](obsidian.Workspace.md) › [`revealLeaf`](obsidian.Workspace.revealLeaf.md)

## Workspace.revealLeaf() method

revealLeaf(leaf: WorkspaceLeaf): void;
```

`void`

[`Workspace`](obsidian.Workspace.md) › [`updateOptions`](obsidian.Workspace.updateOptions.md)

## Workspace.updateOptions() method

Calling this function will update/reconfigure the options of all markdown panes. It is fairly expensive, so it should not be called frequently.

updateOptions(): void;
```

`void`

[`Workspace`](obsidian.Workspace.md) › [`on`](obsidian.Workspace.on_8.md)

Triggered when the user opens the context menu on a file.

on(name: 'file-menu', callback: (menu: Menu, file: TAbstractFile, source: string, leaf?: WorkspaceLeaf) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'file-menu'</code> |  |
|  <code>callback</code> | <code>(menu: </code>[`Menu`](obsidian.Menu.md)<code>, file: </code>[`TAbstractFile`](obsidian.TAbstractFile.md)<code>, source: string, leaf?: </code>[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md)<code>) =&gt; any</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`changeLayout`](obsidian.Workspace.changeLayout.md)

## Workspace.changeLayout() method

changeLayout(workspace: any): Promise<void>;
```

|  <code>workspace</code> | <code>any</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`iterateRootLeaves`](obsidian.Workspace.iterateRootLeaves.md)

## Workspace.iterateRootLeaves() method

Iterate through all leaves in the main area of the workspace.

iterateRootLeaves(callback: (leaf: WorkspaceLeaf) => any): void;
```

`void`

[`Workspace`](obsidian.Workspace.md) › [`getGroupLeaves`](obsidian.Workspace.getGroupLeaves.md)

## Workspace.getGroupLeaves() method

getGroupLeaves(group: string): WorkspaceLeaf[];
```

|  <code>group</code> | <code>string</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`on`](obsidian.Workspace.on_13.md)

Triggered when the editor receives a drop event. Check for `evt.defaultPrevented` before attempting to handle this event, and return if it has been already handled. Use `evt.preventDefault()` to indicate that you've handled the event.

on(name: 'editor-drop', callback: (evt: DragEvent, editor: Editor, info: MarkdownView | MarkdownFileInfo) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'editor-drop'</code> |  |
|  <code>callback</code> | <code>(evt: </code><code>DragEvent</code><code>, editor: </code>[`Editor`](obsidian.Editor.md)<code>, info: </code>[`MarkdownView`](obsidian.MarkdownView.md)<code> &#124; </code>[`MarkdownFileInfo`](obsidian.MarkdownFileInfo.md)<code>) =&gt; any</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`getLeaf`](obsidian.Workspace.getLeaf_1.md)

If newLeaf is false (or not set) then an existing leaf which can be navigated is returned, or a new leaf will be created if there was no leaf available.

If newLeaf is `'tab'` or `true` then a new leaf will be created in the preferred location within the root split and returned.

If newLeaf is `'split'` then a new leaf will be created adjacent to the currently active leaf.

If newLeaf is `'window'` then a popout window will be created with a new leaf inside.

getLeaf(newLeaf?: PaneType | boolean): WorkspaceLeaf;
```

[`Workspace`](obsidian.Workspace.md) › [`duplicateLeaf`](obsidian.Workspace.duplicateLeaf_1.md)

duplicateLeaf(leaf: WorkspaceLeaf, leafType: PaneType | boolean, direction?: SplitDirection): Promise<WorkspaceLeaf>;
```

|  <code>leafType</code> | [`PaneType`](obsidian.PaneType.md)<code> &#124; boolean</code> |  |

[`Workspace`](obsidian.Workspace.md) › [`rightRibbon`](obsidian.Workspace.rightRibbon.md)

## Workspace.rightRibbon property

rightRibbon: WorkspaceRibbon;
```

[`Workspace`](obsidian.Workspace.md) › [`getUnpinnedLeaf`](obsidian.Workspace.getUnpinnedLeaf.md)

## Workspace.getUnpinnedLeaf() method

> 
> - You should use [ | getLeaf(false)](obsidian.workspace.getleaf_1.md) instead which does the same thing.
> 

getUnpinnedLeaf(): WorkspaceLeaf;
```

[`EditorSuggest`](obsidian.EditorSuggest.md) › [`context`](obsidian.EditorSuggest.context.md)

## EditorSuggest.context property

Current suggestion context, containing the result of `onTrigger`<!-- -->. This will be null any time the EditorSuggest is not supposed to run.

context: EditorSuggestContext | null;
```

[`EditorSuggest`](obsidian.EditorSuggest.md) › [`getSuggestions`](obsidian.EditorSuggest.getSuggestions.md)

## EditorSuggest.getSuggestions() method

Generate suggestion items based on this context. Can be async, but preferably sync. When generating async suggestions, you should pass the context along.

abstract getSuggestions(context: EditorSuggestContext): T[] | Promise<T[]>;
```

|  <code>context</code> | [`EditorSuggestContext`](obsidian.EditorSuggestContext.md) |  |

`T[] | ``Promise``<T[]>`

[`EditorSuggest`](obsidian.EditorSuggest.md) › [`(constructor)`](obsidian.EditorSuggest.(constructor).md)

## EditorSuggest.(constructor)

Constructs a new instance of the `EditorSuggest` class

constructor(app: App);
```

[`EditorSuggest`](obsidian.EditorSuggest.md) › [`onTrigger`](obsidian.EditorSuggest.onTrigger.md)

## EditorSuggest.onTrigger() method

Based on the editor line and cursor position, determine if this EditorSuggest should be triggered at this moment. Typically, you would run a regular expression on the current line text before the cursor. Return null to indicate that this editor suggest is not supposed to be triggered.

Please be mindful of performance when implementing this function, as it will be triggered very often (on each keypress). Keep it simple, and return null as early as possible if you determine that it is not the right time.

abstract onTrigger(cursor: EditorPosition, editor: Editor, file: TFile | null): EditorSuggestTriggerInfo | null;
```

|  <code>cursor</code> | [`EditorPosition`](obsidian.EditorPosition.md) |  |
|  <code>editor</code> | [`Editor`](obsidian.Editor.md) |  |
|  <code>file</code> | [`TFile`](obsidian.TFile.md)<code> &#124; null</code> |  |

[`EditorSuggestTriggerInfo`](obsidian.EditorSuggestTriggerInfo.md)` | null`

[`EditorSuggest`](obsidian.EditorSuggest.md) › [`setInstructions`](obsidian.EditorSuggest.setInstructions.md)

## EditorSuggest.setInstructions() method

setInstructions(instructions: Instruction[]): void;
```

|  <code>instructions</code> | [`Instruction`](obsidian.Instruction.md)<code>[]</code> |  |

`void`

[`EditorSuggest`](obsidian.EditorSuggest.md) › [`limit`](obsidian.EditorSuggest.limit.md)

## EditorSuggest.limit property

Override this to use a different limit for suggestion items

limit: number;
```

[`WorkspaceItem`](obsidian.WorkspaceItem.md) › [`getContainer`](obsidian.WorkspaceItem.getContainer.md)

## WorkspaceItem.getContainer() method

Get the root container parent item, which can be one of: - [WorkspaceRoot](obsidian.WorkspaceRoot.md) - [WorkspaceWindow](obsidian.WorkspaceWindow.md)

getContainer(): WorkspaceContainer;
```

[`WorkspaceItem`](obsidian.WorkspaceItem.md) › [`getRoot`](obsidian.WorkspaceItem.getRoot.md)

## WorkspaceItem.getRoot() method

getRoot(): WorkspaceItem;
```

[`FileStats`](obsidian.FileStats.md) › [`ctime`](obsidian.FileStats.ctime.md)

## FileStats.ctime property

Time of creation, represented as a unix timestamp, in milliseconds.

ctime: number;
```

[`FileStats`](obsidian.FileStats.md) › [`mtime`](obsidian.FileStats.mtime.md)

## FileStats.mtime property

Time of last modification, represented as a unix timestamp, in milliseconds.

mtime: number;
```

[`FileStats`](obsidian.FileStats.md) › [`size`](obsidian.FileStats.size.md)

## FileStats.size property

Size on disk, as bytes.

size: number;
```

[`OpenViewState`](obsidian.OpenViewState.md) › [`group`](obsidian.OpenViewState.group.md)

## OpenViewState.group property

group?: WorkspaceLeaf;
```

[`OpenViewState`](obsidian.OpenViewState.md) › [`active`](obsidian.OpenViewState.active.md)

## OpenViewState.active property

active?: boolean;
```

[`OpenViewState`](obsidian.OpenViewState.md) › [`state`](obsidian.OpenViewState.state.md)

## OpenViewState.state property

state?: any;
```

[`OpenViewState`](obsidian.OpenViewState.md) › [`eState`](obsidian.OpenViewState.eState.md)

## OpenViewState.eState property

eState?: any;
```

[`FuzzySuggestModal`](obsidian.FuzzySuggestModal.md) › [`getItems`](obsidian.FuzzySuggestModal.getItems.md)

## FuzzySuggestModal.getItems() method

abstract getItems(): T[];
```

`T[]`

[`FuzzySuggestModal`](obsidian.FuzzySuggestModal.md) › [`onChooseSuggestion`](obsidian.FuzzySuggestModal.onChooseSuggestion.md)

## FuzzySuggestModal.onChooseSuggestion() method

onChooseSuggestion(item: FuzzyMatch<T>, evt: MouseEvent | KeyboardEvent): void;
```

|  <code>item</code> | [`FuzzyMatch`](obsidian.FuzzyMatch.md)<code>&lt;T&gt;</code> |  |
|  <code>evt</code> | <code>MouseEvent</code><code> &#124; </code><code>KeyboardEvent</code> |  |

`void`

[`FuzzySuggestModal`](obsidian.FuzzySuggestModal.md) › [`getSuggestions`](obsidian.FuzzySuggestModal.getSuggestions.md)

## FuzzySuggestModal.getSuggestions() method

getSuggestions(query: string): FuzzyMatch<T>[];
```

[`FuzzyMatch`](obsidian.FuzzyMatch.md)`<T>[]`

[`FuzzySuggestModal`](obsidian.FuzzySuggestModal.md) › [`renderSuggestion`](obsidian.FuzzySuggestModal.renderSuggestion.md)

## FuzzySuggestModal.renderSuggestion() method

renderSuggestion(item: FuzzyMatch<T>, el: HTMLElement): void;
```

`void`

[`FuzzySuggestModal`](obsidian.FuzzySuggestModal.md) › [`onChooseItem`](obsidian.FuzzySuggestModal.onChooseItem.md)

## FuzzySuggestModal.onChooseItem() method

abstract onChooseItem(item: T, evt: MouseEvent | KeyboardEvent): void;
```

|  <code>item</code> | <code>T</code> |  |

`void`

[`FuzzySuggestModal`](obsidian.FuzzySuggestModal.md) › [`getItemText`](obsidian.FuzzySuggestModal.getItemText.md)

## FuzzySuggestModal.getItemText() method

abstract getItemText(item: T): string;
```

`string`

[`Plugin\_2`](obsidian.Plugin.md) › [`registerMarkdownPostProcessor`](obsidian.Plugin.registerMarkdownPostProcessor.md)

## Plugin\_2.registerMarkdownPostProcessor() method

Registers a post processor, to change how the document looks in reading mode.

registerMarkdownPostProcessor(postProcessor: MarkdownPostProcessor, sortOrder?: number): MarkdownPostProcessor;
```

[`Plugin\_2`](obsidian.Plugin.md) › [`registerMarkdownCodeBlockProcessor`](obsidian.Plugin.registerMarkdownCodeBlockProcessor.md)

## Plugin\_2.registerMarkdownCodeBlockProcessor() method

Register a special post processor that handles fenced code given a language and a handler. This special post processor takes care of removing the <pre><code> and create a <div> that will be passed to the handler, and is expected to be filled with custom elements.

registerMarkdownCodeBlockProcessor(language: string, handler: (source: string, el: HTMLElement, ctx: MarkdownPostProcessorContext) => Promise<any> | void, sortOrder?: number): MarkdownPostProcessor;
```

[`Plugin\_2`](obsidian.Plugin.md) › [`app`](obsidian.Plugin.app.md)

## Plugin\_2.app property

app: App;
```

[`Plugin\_2`](obsidian.Plugin.md) › [`loadData`](obsidian.Plugin.loadData.md)

## Plugin\_2.loadData() method

Load settings data from disk. Data is stored in `data.json` in the plugin folder.

loadData(): Promise<any>;
```

[`Plugin\_2`](obsidian.Plugin.md) › [`registerEditorSuggest`](obsidian.Plugin.registerEditorSuggest.md)

## Plugin\_2.registerEditorSuggest() method

Register an EditorSuggest which can provide live suggestions while the user is typing.

registerEditorSuggest(editorSuggest: EditorSuggest<any>): void;
```

|  <code>editorSuggest</code> | [`EditorSuggest`](obsidian.EditorSuggest.md)<code>&lt;any&gt;</code> |  |

`void`

[`Plugin\_2`](obsidian.Plugin.md) › [`registerCodeMirror`](obsidian.Plugin.registerCodeMirror.md)

## Plugin\_2.registerCodeMirror() method

> 
> - This is only used with the legacy editor, which is no longer maintained, and will be removed in a future update.
> 

Runs callback on all currently loaded instances of CodeMirror, then registers the callback for all future CodeMirror instances.

registerCodeMirror(callback: (cm: CodeMirror.Editor) => any): void;
```

`void`

[`Plugin\_2`](obsidian.Plugin.md) › [`saveData`](obsidian.Plugin.saveData.md)

## Plugin\_2.saveData() method

Write settings data to disk. Data is stored in `data.json` in the plugin folder.

saveData(data: any): Promise<void>;
```

|  <code>data</code> | <code>any</code> |  |

[`Plugin\_2`](obsidian.Plugin.md) › [`addRibbonIcon`](obsidian.Plugin.addRibbonIcon.md)

## Plugin\_2.addRibbonIcon() method

Adds a ribbon icon to the left bar.

addRibbonIcon(icon: IconName, title: string, callback: (evt: MouseEvent) => any): HTMLElement;
```

|  <code>icon</code> | [`IconName`](obsidian.IconName.md) | The icon name to be used. See [addIcon()](obsidian.addIcon.md) |
|  <code>title</code> | <code>string</code> | The title to be displayed in the tooltip. |
|  <code>callback</code> | <code>(evt: </code><code>MouseEvent</code><code>) =&gt; any</code> | The <code>click</code> callback. |

[`Plugin\_2`](obsidian.Plugin.md) › [`addCommand`](obsidian.Plugin.addCommand.md)

## Plugin\_2.addCommand() method

Register a command globally. Registered commands will be available from the @<!-- -->{<!-- -->link https://help.obsidian.md/Plugins/Command+palette Command pallete<!-- -->}<!-- -->. The command id and name will be automatically prefixed with this plugin's id and name.

addCommand(command: Command): Command;
```

|  <code>command</code> | [`Command`](obsidian.Command.md) |  |

[`Plugin\_2`](obsidian.Plugin.md) › [`registerEditorExtension`](obsidian.Plugin.registerEditorExtension.md)

## Plugin\_2.registerEditorExtension() method

Registers a CodeMirror 6 extension. To reconfigure cm6 extensions for a plugin on the fly, an array should be passed in, and modified dynamically. Once this array is modified, calling [Workspace.updateOptions()](obsidian.Workspace.updateOptions.md) will apply the changes.

registerEditorExtension(extension: Extension): void;
```

|  <code>extension</code> | <code>Extension</code> | must be a CodeMirror 6 <code>Extension</code>, or an array of Extensions. |

`void`

[`Plugin\_2`](obsidian.Plugin.md) › [`manifest`](obsidian.Plugin.manifest.md)

## Plugin\_2.manifest property

manifest: PluginManifest;
```

[`Plugin\_2`](obsidian.Plugin.md) › [`(constructor)`](obsidian.Plugin.(constructor).md)

## Plugin\_2.(constructor)

Constructs a new instance of the `Plugin` class

constructor(app: App, manifest: PluginManifest);
```

|  <code>manifest</code> | [`PluginManifest`](obsidian.PluginManifest.md) |  |

[`Plugin\_2`](obsidian.Plugin.md) › [`registerExtensions`](obsidian.Plugin.registerExtensions.md)

## Plugin\_2.registerExtensions() method

registerExtensions(extensions: string[], viewType: string): void;
```

|  <code>extensions</code> | <code>string[]</code> |  |

`void`

[`Plugin\_2`](obsidian.Plugin.md) › [`registerHoverLinkSource`](obsidian.Plugin.registerHoverLinkSource.md)

## Plugin\_2.registerHoverLinkSource() method

Registers a view with the 'Page preview' core plugin as an emitter of the 'hover-link' on the event.

registerHoverLinkSource(id: string, info: HoverLinkSource): void;
```

|  <code>info</code> | [`HoverLinkSource`](obsidian.HoverLinkSource.md) |  |

`void`

[`Plugin\_2`](obsidian.Plugin.md) › [`addStatusBarItem`](obsidian.Plugin.addStatusBarItem.md)

## Plugin\_2.addStatusBarItem() method

Adds a status bar item to the bottom of the app. Not available on mobile.

addStatusBarItem(): HTMLElement;
```

[`Plugin\_2`](obsidian.Plugin.md) › [`addSettingTab`](obsidian.Plugin.addSettingTab.md)

## Plugin\_2.addSettingTab() method

Register a settings tab, which allows users to change settings.

addSettingTab(settingTab: PluginSettingTab): void;
```

|  <code>settingTab</code> | [`PluginSettingTab`](obsidian.PluginSettingTab.md) |  |

`void`

[`Plugin\_2`](obsidian.Plugin.md) › [`registerObsidianProtocolHandler`](obsidian.Plugin.registerObsidianProtocolHandler.md)

## Plugin\_2.registerObsidianProtocolHandler() method

Register a handler for obsidian:// URLs.

registerObsidianProtocolHandler(action: string, handler: ObsidianProtocolHandler): void;
```

|  <code>action</code> | <code>string</code> | the action string. For example, "open" corresponds to <code>obsidian://open</code>. |
|  <code>handler</code> | [`ObsidianProtocolHandler`](obsidian.ObsidianProtocolHandler.md) | the callback to trigger. A key-value pair that is decoded from the query will be passed in. For example, <code>obsidian://open?key=value</code> would generate <code>{&quot;action&quot;: &quot;open&quot;, &quot;key&quot;: &quot;value&quot;}</code>. |

`void`

[`Plugin\_2`](obsidian.Plugin.md) › [`registerView`](obsidian.Plugin.registerView.md)

## Plugin\_2.registerView() method

registerView(type: string, viewCreator: ViewCreator): void;
```

|  <code>type</code> | <code>string</code> |  |
|  <code>viewCreator</code> | [`ViewCreator`](obsidian.ViewCreator.md) |  |

`void`

[`TagCache`](obsidian.TagCache.md) › [`tag`](obsidian.TagCache.tag.md)

## TagCache.tag property

tag: string;
```

[`MomentFormatComponent`](obsidian.MomentFormatComponent.md) › [`onChanged`](obsidian.MomentFormatComponent.onChanged.md)

## MomentFormatComponent.onChanged() method

onChanged(): void;
```

`void`

[`MomentFormatComponent`](obsidian.MomentFormatComponent.md) › [`setValue`](obsidian.MomentFormatComponent.setValue.md)

## MomentFormatComponent.setValue() method

setValue(value: string): this;
```

|  <code>value</code> | <code>string</code> |  |

`this`

[`MomentFormatComponent`](obsidian.MomentFormatComponent.md) › [`setSampleEl`](obsidian.MomentFormatComponent.setSampleEl.md)

## MomentFormatComponent.setSampleEl() method

setSampleEl(sampleEl: HTMLElement): this;
```

|  <code>sampleEl</code> | <code>HTMLElement</code> |  |

`this`

[`MomentFormatComponent`](obsidian.MomentFormatComponent.md) › [`updateSample`](obsidian.MomentFormatComponent.updateSample.md)

## MomentFormatComponent.updateSample() method

updateSample(): void;
```

`void`

[`MomentFormatComponent`](obsidian.MomentFormatComponent.md) › [`sampleEl`](obsidian.MomentFormatComponent.sampleEl.md)

## MomentFormatComponent.sampleEl property

sampleEl: HTMLElement;
```

[`MomentFormatComponent`](obsidian.MomentFormatComponent.md) › [`setDefaultFormat`](obsidian.MomentFormatComponent.setDefaultFormat.md)

## MomentFormatComponent.setDefaultFormat() method

Sets the default format when input is cleared. Also used for placeholder.

setDefaultFormat(defaultFormat: string): this;
```

|  <code>defaultFormat</code> | <code>string</code> |  |

`this`

[`SuggestModal`](obsidian.SuggestModal.md) › [`emptyStateText`](obsidian.SuggestModal.emptyStateText.md)

## SuggestModal.emptyStateText property

emptyStateText: string;
```

[`SuggestModal`](obsidian.SuggestModal.md) › [`onNoSuggestion`](obsidian.SuggestModal.onNoSuggestion.md)

## SuggestModal.onNoSuggestion() method

onNoSuggestion(): void;
```

`void`

[`SuggestModal`](obsidian.SuggestModal.md) › [`inputEl`](obsidian.SuggestModal.inputEl.md)

## SuggestModal.inputEl property

inputEl: HTMLInputElement;
```

[`SuggestModal`](obsidian.SuggestModal.md) › [`onChooseSuggestion`](obsidian.SuggestModal.onChooseSuggestion.md)

## SuggestModal.onChooseSuggestion() method

abstract onChooseSuggestion(item: T, evt: MouseEvent | KeyboardEvent): any;
```

`any`

[`SuggestModal`](obsidian.SuggestModal.md) › [`getSuggestions`](obsidian.SuggestModal.getSuggestions.md)

## SuggestModal.getSuggestions() method

abstract getSuggestions(query: string): T[] | Promise<T[]>;
```

[`SuggestModal`](obsidian.SuggestModal.md) › [`resultContainerEl`](obsidian.SuggestModal.resultContainerEl.md)

## SuggestModal.resultContainerEl property

resultContainerEl: HTMLElement;
```

[`SuggestModal`](obsidian.SuggestModal.md) › [`(constructor)`](obsidian.SuggestModal.(constructor).md)

## SuggestModal.(constructor)

Constructs a new instance of the `SuggestModal` class

```

[`SuggestModal`](obsidian.SuggestModal.md) › [`selectSuggestion`](obsidian.SuggestModal.selectSuggestion.md)

## SuggestModal.selectSuggestion() method

selectSuggestion(value: T, evt: MouseEvent | KeyboardEvent): void;
```

|  <code>value</code> | <code>T</code> |  |

`void`

[`SuggestModal`](obsidian.SuggestModal.md) › [`setInstructions`](obsidian.SuggestModal.setInstructions.md)

## SuggestModal.setInstructions() method

```

`void`

[`SuggestModal`](obsidian.SuggestModal.md) › [`setPlaceholder`](obsidian.SuggestModal.setPlaceholder.md)

## SuggestModal.setPlaceholder() method

setPlaceholder(placeholder: string): void;
```

|  <code>placeholder</code> | <code>string</code> |  |

`void`

[`SuggestModal`](obsidian.SuggestModal.md) › [`limit`](obsidian.SuggestModal.limit.md)

## SuggestModal.limit property

```

[`SuggestModal`](obsidian.SuggestModal.md) › [`renderSuggestion`](obsidian.SuggestModal.renderSuggestion.md)

## SuggestModal.renderSuggestion() method

abstract renderSuggestion(value: T, el: HTMLElement): any;
```

`any`

[`TextFileView`](obsidian.TextFileView.md) › [`setViewData`](obsidian.TextFileView.setViewData.md)

## TextFileView.setViewData() method

Set the data to the editor. This is used to load the file contents.

If clear is set, then it means we're opening a completely different file. In that case, you should call clear(), or implement a slightly more efficient clearing mechanism given the new data to be set.

abstract setViewData(data: string, clear: boolean): void;
```

`void`

[`TextFileView`](obsidian.TextFileView.md) › [`data`](obsidian.TextFileView.data.md)

## TextFileView.data property

In memory data

data: string;
```

[`TextFileView`](obsidian.TextFileView.md) › [`getViewData`](obsidian.TextFileView.getViewData.md)

## TextFileView.getViewData() method

Gets the data from the editor. This will be called to save the editor contents to the file.

abstract getViewData(): string;
```

`string`

[`TextFileView`](obsidian.TextFileView.md) › [`requestSave`](obsidian.TextFileView.requestSave.md)

## TextFileView.requestSave property

Debounced save in 2 seconds from now

requestSave: () => void;
```

[`TextFileView`](obsidian.TextFileView.md) › [`clear`](obsidian.TextFileView.clear.md)

## TextFileView.clear() method

Clear the editor. This is usually called when we're about to open a completely different file, so it's best to clear any editor states like undo-redo history, and any caches/indexes associated with the previous file contents.

abstract clear(): void;
```

`void`

[`TextFileView`](obsidian.TextFileView.md) › [`onUnloadFile`](obsidian.TextFileView.onUnloadFile.md)

## TextFileView.onUnloadFile() method

onUnloadFile(file: TFile): Promise<void>;
```

|  <code>file</code> | [`TFile`](obsidian.TFile.md) |  |

[`TextFileView`](obsidian.TextFileView.md) › [`(constructor)`](obsidian.TextFileView.(constructor).md)

## TextFileView.(constructor)

Constructs a new instance of the `TextFileView` class

```

[`TextFileView`](obsidian.TextFileView.md) › [`save`](obsidian.TextFileView.save.md)

## TextFileView.save() method

save(clear?: boolean): Promise<void>;
```

|  <code>clear</code> | <code>boolean</code> | _(Optional)_ |

[`TextFileView`](obsidian.TextFileView.md) › [`onLoadFile`](obsidian.TextFileView.onLoadFile.md)

## TextFileView.onLoadFile() method

onLoadFile(file: TFile): Promise<void>;
```

[`SettingTab`](obsidian.SettingTab.md) › [`hide`](obsidian.SettingTab.hide.md)

## SettingTab.hide() method

Hides the contents of the setting tab. Any registered components should be unloaded when the view is hidden. Override this if you need to perform additional cleanup.

hide(): any;
```

`any`

[`SettingTab`](obsidian.SettingTab.md) › [`app`](obsidian.SettingTab.app.md)

## SettingTab.app property

Reference to the app instance.

app: App;
```

[`SettingTab`](obsidian.SettingTab.md) › [`containerEl`](obsidian.SettingTab.containerEl.md)

## SettingTab.containerEl property

Outermost HTML element on the setting tab.

```

[`SettingTab`](obsidian.SettingTab.md) › [`display`](obsidian.SettingTab.display.md)

## SettingTab.display() method

Called when the settings tab should be rendered.

abstract display(): any;
```

`any`

[`ButtonComponent`](obsidian.ButtonComponent.md) › [`setTooltip`](obsidian.ButtonComponent.setTooltip.md)

## ButtonComponent.setTooltip() method

```

`this`

[`ButtonComponent`](obsidian.ButtonComponent.md) › [`removeCta`](obsidian.ButtonComponent.removeCta.md)

## ButtonComponent.removeCta() method

removeCta(): this;
```

`this`

[`ButtonComponent`](obsidian.ButtonComponent.md) › [`setWarning`](obsidian.ButtonComponent.setWarning.md)

## ButtonComponent.setWarning() method

setWarning(): this;
```

`this`

[`ButtonComponent`](obsidian.ButtonComponent.md) › [`setIcon`](obsidian.ButtonComponent.setIcon.md)

## ButtonComponent.setIcon() method

setIcon(icon: IconName): this;
```

`this`

[`ButtonComponent`](obsidian.ButtonComponent.md) › [`setClass`](obsidian.ButtonComponent.setClass.md)

## ButtonComponent.setClass() method

setClass(cls: string): this;
```

|  <code>cls</code> | <code>string</code> |  |

`this`

[`ButtonComponent`](obsidian.ButtonComponent.md) › [`setDisabled`](obsidian.ButtonComponent.setDisabled.md)

## ButtonComponent.setDisabled() method

```

`this`

[`ButtonComponent`](obsidian.ButtonComponent.md) › [`setButtonText`](obsidian.ButtonComponent.setButtonText.md)

## ButtonComponent.setButtonText() method

setButtonText(name: string): this;
```

|  <code>name</code> | <code>string</code> |  |

`this`

[`ButtonComponent`](obsidian.ButtonComponent.md) › [`buttonEl`](obsidian.ButtonComponent.buttonEl.md)

## ButtonComponent.buttonEl property

buttonEl: HTMLButtonElement;
```

[`ButtonComponent`](obsidian.ButtonComponent.md) › [`(constructor)`](obsidian.ButtonComponent.(constructor).md)

## ButtonComponent.(constructor)

Constructs a new instance of the `ButtonComponent` class

```

[`ButtonComponent`](obsidian.ButtonComponent.md) › [`onClick`](obsidian.ButtonComponent.onClick.md)

## ButtonComponent.onClick() method

onClick(callback: (evt: MouseEvent) => any): this;
```

`this`

[`ButtonComponent`](obsidian.ButtonComponent.md) › [`setCta`](obsidian.ButtonComponent.setCta.md)

## ButtonComponent.setCta() method

setCta(): this;
```

`this`

[`ViewStateResult`](obsidian.ViewStateResult.md) › [`history`](obsidian.ViewStateResult.history.md)

## ViewStateResult.history property

Set this to true to indicate that there is a state change which should be recorded in the navigation history.

history: boolean;
```

[`Component`](obsidian.Component.md) › [`registerDomEvent`](obsidian.Component.registerDomEvent.md)

## Component.registerDomEvent() method

Registers an DOM event to be detached when unloading

registerDomEvent<K extends keyof WindowEventMap>(el: Window, type: K, callback: (this: HTMLElement, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
```

|  <code>el</code> | <code>Window</code> |  |
|  <code>type</code> | <code>K</code> |  |
|  <code>callback</code> | <code>(this: </code><code>HTMLElement</code><code>, ev: </code><code>WindowEventMap</code><code>[K]) =&gt; any</code> |  |
|  <code>options</code> | <code>boolean &#124; </code><code>AddEventListenerOptions</code> | _(Optional)_ |

`void`

[`Component`](obsidian.Component.md) › [`registerEvent`](obsidian.Component.registerEvent.md)

## Component.registerEvent() method

Registers an event to be detached when unloading

registerEvent(eventRef: EventRef): void;
```

|  <code>eventRef</code> | [`EventRef`](obsidian.EventRef.md) |  |

`void`

[`Component`](obsidian.Component.md) › [`registerDomEvent`](obsidian.Component.registerDomEvent_1.md)

registerDomEvent<K extends keyof DocumentEventMap>(el: Document, type: K, callback: (this: HTMLElement, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
```

|  <code>el</code> | <code>Document</code> |  |
|  <code>callback</code> | <code>(this: </code><code>HTMLElement</code><code>, ev: </code><code>DocumentEventMap</code><code>[K]) =&gt; any</code> |  |

`void`

[`Component`](obsidian.Component.md) › [`onload`](obsidian.Component.onload.md)

## Component.onload() method

Override this to load your component

/** @virtual */
onload(): void;
```

`void`

[`Component`](obsidian.Component.md) › [`registerInterval`](obsidian.Component.registerInterval.md)

## Component.registerInterval() method

Registers an interval (from setInterval) to be cancelled when unloading Use  instead of  to avoid TypeScript confusing between NodeJS vs Browser API

registerInterval(id: number): number;
```

|  <code>id</code> | <code>number</code> |  |

`number`

[`Component`](obsidian.Component.md) › [`load`](obsidian.Component.load.md)

## Component.load() method

Load this component and its children

load(): void;
```

`void`

[`Component`](obsidian.Component.md) › [`register`](obsidian.Component.register.md)

## Component.register() method

Registers a callback to be called when unloading

register(cb: () => any): void;
```

|  <code>cb</code> | <code>() =&gt; any</code> |  |

`void`

[`Component`](obsidian.Component.md) › [`removeChild`](obsidian.Component.removeChild.md)

## Component.removeChild() method

Removes a child component, unloading it

removeChild<T extends Component>(component: T): T;
```

|  <code>component</code> | <code>T</code> |  |

`T`

[`Component`](obsidian.Component.md) › [`onunload`](obsidian.Component.onunload.md)

## Component.onunload() method

Override this to unload your component

onunload(): void;
```

`void`

[`Component`](obsidian.Component.md) › [`addChild`](obsidian.Component.addChild.md)

## Component.addChild() method

Adds a child component, loading it if this component is loaded

addChild<T extends Component>(component: T): T;
```

`T`

[`Component`](obsidian.Component.md) › [`registerDomEvent`](obsidian.Component.registerDomEvent_2.md)

registerDomEvent<K extends keyof HTMLElementEventMap>(el: HTMLElement, type: K, callback: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
```

|  <code>callback</code> | <code>(this: </code><code>HTMLElement</code><code>, ev: </code><code>HTMLElementEventMap</code><code>[K]) =&gt; any</code> |  |

`void`

[`Component`](obsidian.Component.md) › [`unload`](obsidian.Component.unload.md)

## Component.unload() method

Unload this component and its children

unload(): void;
```

`void`

[`MarkdownRenderChild`](obsidian.MarkdownRenderChild.md) › [`containerEl`](obsidian.MarkdownRenderChild.containerEl.md)

## MarkdownRenderChild.containerEl property

```

[`MarkdownRenderChild`](obsidian.MarkdownRenderChild.md) › [`(constructor)`](obsidian.MarkdownRenderChild.(constructor).md)

## MarkdownRenderChild.(constructor)

Constructs a new instance of the `MarkdownRenderChild` class

```

|  <code>containerEl</code> | <code>HTMLElement</code> | This HTMLElement will be used to test whether this component is still alive. It should be a child of the markdown preview sections, and when it's no longer attached (for example, when it is replaced with a new version because the user edited the markdown source code), this component will be unloaded. |

[`EditorSelectionOrCaret`](obsidian.EditorSelectionOrCaret.md) › [`head`](obsidian.EditorSelectionOrCaret.head.md)

## EditorSelectionOrCaret.head property

head?: EditorPosition;
```

[`EditorSelectionOrCaret`](obsidian.EditorSelectionOrCaret.md) › [`anchor`](obsidian.EditorSelectionOrCaret.anchor.md)

## EditorSelectionOrCaret.anchor property

```

[`MarkdownFileInfo`](obsidian.MarkdownFileInfo.md) › [`app`](obsidian.MarkdownFileInfo.app.md)

## MarkdownFileInfo.app property

app: App;
```

[`MarkdownFileInfo`](obsidian.MarkdownFileInfo.md) › [`editor`](obsidian.MarkdownFileInfo.editor.md)

## MarkdownFileInfo.editor property

editor?: Editor;
```

[`MenuItem`](obsidian.MenuItem.md) › [`setSection`](obsidian.MenuItem.setSection.md)

## MenuItem.setSection() method

Sets the section this menu item should belong in. To find the section IDs of an existing menu, inspect the DOM elements to see their `data-section` attribute.

setSection(section: string): this;
```

|  <code>section</code> | <code>string</code> |  |

`this`

[`MenuItem`](obsidian.MenuItem.md) › [`setIcon`](obsidian.MenuItem.setIcon.md)

## MenuItem.setIcon() method

setIcon(icon: IconName | null): this;
```

|  <code>icon</code> | [`IconName`](obsidian.IconName.md)<code> &#124; null</code> | ID of the icon, can use any icon loaded with [addIcon()](obsidian.addIcon.md) or from the built-in lucide library. |

`this`

[`MenuItem`](obsidian.MenuItem.md) › [`setDisabled`](obsidian.MenuItem.setDisabled.md)

## MenuItem.setDisabled() method

```

`this`

[`MenuItem`](obsidian.MenuItem.md) › [`setTitle`](obsidian.MenuItem.setTitle.md)

## MenuItem.setTitle() method

setTitle(title: string | DocumentFragment): this;
```

|  <code>title</code> | <code>string &#124; </code><code>DocumentFragment</code> |  |

`this`

[`MenuItem`](obsidian.MenuItem.md) › [`setIsLabel`](obsidian.MenuItem.setIsLabel.md)

## MenuItem.setIsLabel() method

setIsLabel(isLabel: boolean): this;
```

|  <code>isLabel</code> | <code>boolean</code> |  |

`this`

[`MenuItem`](obsidian.MenuItem.md) › [`onClick`](obsidian.MenuItem.onClick.md)

## MenuItem.onClick() method

onClick(callback: (evt: MouseEvent | KeyboardEvent) => any): this;
```

|  <code>callback</code> | <code>(evt: </code><code>MouseEvent</code><code> &#124; </code><code>KeyboardEvent</code><code>) =&gt; any</code> |  |

`this`

[`MenuItem`](obsidian.MenuItem.md) › [`setChecked`](obsidian.MenuItem.setChecked.md)

## MenuItem.setChecked() method

setChecked(checked: boolean | null): this;
```

|  <code>checked</code> | <code>boolean &#124; null</code> |  |

`this`

[`RGB`](obsidian.RGB.md) › [`b`](obsidian.RGB.b.md)

## RGB.b property

Blue integer value between 0 and 255

b: number;
```

[`RGB`](obsidian.RGB.md) › [`g`](obsidian.RGB.g.md)

## RGB.g property

Green integer value between 0 and 255

g: number;
```

[`RGB`](obsidian.RGB.md) › [`r`](obsidian.RGB.r.md)

## RGB.r property

Red integer value between 0 and 255

r: number;
```

[`Scope`](obsidian.Scope.md) › [`unregister`](obsidian.Scope.unregister.md)

## Scope.unregister() method

unregister(handler: KeymapEventHandler): void;
```

|  <code>handler</code> | [`KeymapEventHandler`](obsidian.KeymapEventHandler.md) |  |

`void`

[`Scope`](obsidian.Scope.md) › [`register`](obsidian.Scope.register.md)

## Scope.register() method

register(modifiers: Modifier[], key: string | null, func: KeymapEventListener): KeymapEventHandler;
```

|  <code>modifiers</code> | [`Modifier`](obsidian.Modifier.md)<code>[]</code> | <code>Mod</code>, <code>Ctrl</code>, <code>Meta</code>, <code>Shift</code>, or <code>Alt</code>. <code>Mod</code> translates to <code>Meta</code> on macOS and <code>Ctrl</code> otherwise. |
|  <code>key</code> | <code>string &#124; null</code> | Keycode from https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key\_Values |
|  <code>func</code> | [`KeymapEventListener`](obsidian.KeymapEventListener.md) | the callback |

[`Scope`](obsidian.Scope.md) › [`(constructor)`](obsidian.Scope.(constructor).md)

## Scope.(constructor)

Constructs a new instance of the `Scope` class

constructor(parent?: Scope);
```

|  <code>parent</code> | [`Scope`](obsidian.Scope.md) | _(Optional)_ |

[`ListItemCache`](obsidian.ListItemCache.md) › [`id`](obsidian.ListItemCache.id.md)

## ListItemCache.id property

The block ID of this list item, if defined.

id?: string | undefined;
```

[`ListItemCache`](obsidian.ListItemCache.md) › [`task`](obsidian.ListItemCache.task.md)

## ListItemCache.task property

A single character indicating the checked status of a task. The space character `' '` is interpreted as an incomplete task. An other character is interpreted as completed task. `undefined` if this item isn't a task.

task?: string | undefined;
```

[`ListItemCache`](obsidian.ListItemCache.md) › [`parent`](obsidian.ListItemCache.parent.md)

## ListItemCache.parent property

Line number of the parent list item (position.start.line). If this item has no parent (e.g. it's a root level list), then this value is the negative of the line number of the first list item (start of the list).

Can be used to deduce which list items belongs to the same group (item1.parent === item2.parent). Can be used to reconstruct hierarchy information (parentItem.position.start.line === childItem.parent).

parent: number;
```

[`SearchComponent`](obsidian.SearchComponent.md) › [`onChanged`](obsidian.SearchComponent.onChanged.md)

## SearchComponent.onChanged() method

```

`void`

[`SearchComponent`](obsidian.SearchComponent.md) › [`(constructor)`](obsidian.SearchComponent.(constructor).md)

## SearchComponent.(constructor)

Constructs a new instance of the `SearchComponent` class

```

[`SearchComponent`](obsidian.SearchComponent.md) › [`clearButtonEl`](obsidian.SearchComponent.clearButtonEl.md)

## SearchComponent.clearButtonEl property

clearButtonEl: HTMLElement;
```

[`HoverPopover`](obsidian.HoverPopover.md) › [`state`](obsidian.HoverPopover.state.md)

## HoverPopover.state property

state: PopoverState;
```

[`HoverPopover`](obsidian.HoverPopover.md) › [`(constructor)`](obsidian.HoverPopover.(constructor).md)

## HoverPopover.(constructor)

Constructs a new instance of the `HoverPopover` class

constructor(parent: HoverParent, targetEl: HTMLElement | null, waitTime?: number);
```

|  <code>parent</code> | [`HoverParent`](obsidian.HoverParent.md) |  |
|  <code>targetEl</code> | <code>HTMLElement</code><code> &#124; null</code> |  |
|  <code>waitTime</code> | <code>number</code> | _(Optional)_ |

[`HoverPopover`](obsidian.HoverPopover.md) › [`hoverEl`](obsidian.HoverPopover.hoverEl.md)

## HoverPopover.hoverEl property

hoverEl: HTMLElement;
```

[`FuzzyMatch`](obsidian.FuzzyMatch.md) › [`match`](obsidian.FuzzyMatch.match.md)

## FuzzyMatch.match property

match: SearchResult;
```

[`FuzzyMatch`](obsidian.FuzzyMatch.md) › [`item`](obsidian.FuzzyMatch.item.md)

## FuzzyMatch.item property

item: T;
```

[`HSL`](obsidian.HSL.md) › [`h`](obsidian.HSL.h.md)

## HSL.h property

Hue integer value between 0 and 360

h: number;
```

[`HSL`](obsidian.HSL.md) › [`l`](obsidian.HSL.l.md)

## HSL.l property

Lightness integer value between 0 and 100

l: number;
```

[`HSL`](obsidian.HSL.md) › [`s`](obsidian.HSL.s.md)

## HSL.s property

Saturation integer value between 0 and 100

s: number;
```

[`MarkdownSourceView`](obsidian.MarkdownSourceView.md) › [`app`](obsidian.MarkdownSourceView.app.md)

## MarkdownSourceView.app property

app: App;
```

[`MarkdownSourceView`](obsidian.MarkdownSourceView.md) › [`file`](obsidian.MarkdownSourceView.file.md)

## MarkdownSourceView.file property

get file(): TFile;
```

[`MarkdownSourceView`](obsidian.MarkdownSourceView.md) › [`get`](obsidian.MarkdownSourceView.get.md)

## MarkdownSourceView.get() method

```

`string`

[`MarkdownSourceView`](obsidian.MarkdownSourceView.md) › [`set`](obsidian.MarkdownSourceView.set.md)

## MarkdownSourceView.set() method

```

`void`

[`MarkdownSourceView`](obsidian.MarkdownSourceView.md) › [`clear`](obsidian.MarkdownSourceView.clear.md)

## MarkdownSourceView.clear() method

clear(): void;
```

`void`

[`MarkdownSourceView`](obsidian.MarkdownSourceView.md) › [`(constructor)`](obsidian.MarkdownSourceView.(constructor).md)

## MarkdownSourceView.(constructor)

Constructs a new instance of the `MarkdownSourceView` class

constructor(view: MarkdownView);
```

|  <code>view</code> | [`MarkdownView`](obsidian.MarkdownView.md) |  |

[`MarkdownSourceView`](obsidian.MarkdownSourceView.md) › [`applyScroll`](obsidian.MarkdownSourceView.applyScroll.md)

## MarkdownSourceView.applyScroll() method

```

`void`

[`MarkdownSourceView`](obsidian.MarkdownSourceView.md) › [`getScroll`](obsidian.MarkdownSourceView.getScroll.md)

## MarkdownSourceView.getScroll() method

```

`number`

[`MarkdownSourceView`](obsidian.MarkdownSourceView.md) › [`hoverPopover`](obsidian.MarkdownSourceView.hoverPopover.md)

## MarkdownSourceView.hoverPopover property

hoverPopover: HoverPopover;
```

[`MarkdownSourceView`](obsidian.MarkdownSourceView.md) › [`getSelection`](obsidian.MarkdownSourceView.getSelection.md)

## MarkdownSourceView.getSelection() method

getSelection(): string;
```

`string`

[`MarkdownSourceView`](obsidian.MarkdownSourceView.md) › [`cmEditor`](obsidian.MarkdownSourceView.cmEditor.md)

## MarkdownSourceView.cmEditor property

> 
> - Please use  instead. If you have to use this because you're augmenting specific CodeMirror 5 implementations, be aware that it will only work in source code mode on the desktop app, and it will not work on Mobile, or once WYSIWYG mode is released.
> 

cmEditor: CodeMirror.Editor;
```

[`PluginManifest`](obsidian.PluginManifest.md) › [`authorUrl`](obsidian.PluginManifest.authorUrl.md)

## PluginManifest.authorUrl property

A URL to the author's website.

authorUrl?: string;
```

[`PluginManifest`](obsidian.PluginManifest.md) › [`minAppVersion`](obsidian.PluginManifest.minAppVersion.md)

## PluginManifest.minAppVersion property

The minimum required Obsidian version to run this plugin.

minAppVersion: string;
```

[`PluginManifest`](obsidian.PluginManifest.md) › [`name`](obsidian.PluginManifest.name.md)

## PluginManifest.name property

The display name.

name: string;
```

[`PluginManifest`](obsidian.PluginManifest.md) › [`id`](obsidian.PluginManifest.id.md)

## PluginManifest.id property

The plugin ID.

id: string;
```

[`PluginManifest`](obsidian.PluginManifest.md) › [`dir`](obsidian.PluginManifest.dir.md)

## PluginManifest.dir property

Vault path to the plugin folder in the config directory.

dir?: string;
```

[`PluginManifest`](obsidian.PluginManifest.md) › [`version`](obsidian.PluginManifest.version.md)

## PluginManifest.version property

The current version, using .

version: string;
```

[`PluginManifest`](obsidian.PluginManifest.md) › [`description`](obsidian.PluginManifest.description.md)

## PluginManifest.description property

A description of the plugin.

description: string;
```

[`PluginManifest`](obsidian.PluginManifest.md) › [`isDesktopOnly`](obsidian.PluginManifest.isDesktopOnly.md)

## PluginManifest.isDesktopOnly property

Whether the plugin can be used only on desktop.

isDesktopOnly?: boolean;
```

[`PluginManifest`](obsidian.PluginManifest.md) › [`author`](obsidian.PluginManifest.author.md)

## PluginManifest.author property

The author's name.

author: string;
```

[`TAbstractFile`](obsidian.TAbstractFile.md) › [`vault`](obsidian.TAbstractFile.vault.md)

## TAbstractFile.vault property

```

[`TAbstractFile`](obsidian.TAbstractFile.md) › [`path`](obsidian.TAbstractFile.path.md)

## TAbstractFile.path property

path: string;
```

[`TAbstractFile`](obsidian.TAbstractFile.md) › [`name`](obsidian.TAbstractFile.name.md)

## TAbstractFile.name property

```

[`TAbstractFile`](obsidian.TAbstractFile.md) › [`parent`](obsidian.TAbstractFile.parent.md)

## TAbstractFile.parent property

parent: TFolder | null;
```

[`ISuggestOwner`](obsidian.ISuggestOwner.md) › [`selectSuggestion`](obsidian.ISuggestOwner.selectSuggestion.md)

## ISuggestOwner.selectSuggestion() method

Called when the user makes a selection.

```

`void`

[`ISuggestOwner`](obsidian.ISuggestOwner.md) › [`renderSuggestion`](obsidian.ISuggestOwner.renderSuggestion.md)

## ISuggestOwner.renderSuggestion() method

Render the suggestion item into DOM.

renderSuggestion(value: T, el: HTMLElement): void;
```

`void`

[`Notice`](obsidian.Notice.md) › [`hide`](obsidian.Notice.hide.md)

## Notice.hide() method

hide(): void;
```

`void`

[`Notice`](obsidian.Notice.md) › [`setMessage`](obsidian.Notice.setMessage.md)

## Notice.setMessage() method

Change the message of this notice.

setMessage(message: string | DocumentFragment): this;
```

|  <code>message</code> | <code>string &#124; </code><code>DocumentFragment</code> |  |

`this`

[`Notice`](obsidian.Notice.md) › [`noticeEl`](obsidian.Notice.noticeEl.md)

## Notice.noticeEl property

noticeEl: HTMLElement;
```

[`Notice`](obsidian.Notice.md) › [`(constructor)`](obsidian.Notice.(constructor).md)

## Notice.(constructor)

Constructs a new instance of the `Notice` class

constructor(message: string | DocumentFragment, duration?: number);
```

|  <code>message</code> | <code>string &#124; </code><code>DocumentFragment</code> | The message to be displayed, can either be a simple string or a  |
|  <code>duration</code> | <code>number</code> | _(Optional)_ Time in milliseconds to show the notice for. If this is 0, the Notice will stay visible until the user manually dismisses it. |

[`FrontmatterLinkCache`](obsidian.FrontmatterLinkCache.md) › [`key`](obsidian.FrontmatterLinkCache.key.md)

## FrontmatterLinkCache.key property

key: string;
```

[`SliderComponent`](obsidian.SliderComponent.md) › [`getValue`](obsidian.SliderComponent.getValue.md)

## SliderComponent.getValue() method

getValue(): number;
```

`number`

[`SliderComponent`](obsidian.SliderComponent.md) › [`setDisabled`](obsidian.SliderComponent.setDisabled.md)

## SliderComponent.setDisabled() method

```

`this`

[`SliderComponent`](obsidian.SliderComponent.md) › [`onChange`](obsidian.SliderComponent.onChange.md)

## SliderComponent.onChange() method

onChange(callback: (value: number) => any): this;
```

|  <code>callback</code> | <code>(value: number) =&gt; any</code> |  |

`this`

[`SliderComponent`](obsidian.SliderComponent.md) › [`setValue`](obsidian.SliderComponent.setValue.md)

## SliderComponent.setValue() method

setValue(value: number): this;
```

|  <code>value</code> | <code>number</code> |  |

`this`

[`SliderComponent`](obsidian.SliderComponent.md) › [`sliderEl`](obsidian.SliderComponent.sliderEl.md)

## SliderComponent.sliderEl property

sliderEl: HTMLInputElement;
```

[`SliderComponent`](obsidian.SliderComponent.md) › [`getValuePretty`](obsidian.SliderComponent.getValuePretty.md)

## SliderComponent.getValuePretty() method

getValuePretty(): string;
```

`string`

[`SliderComponent`](obsidian.SliderComponent.md) › [`setDynamicTooltip`](obsidian.SliderComponent.setDynamicTooltip.md)

## SliderComponent.setDynamicTooltip() method

setDynamicTooltip(): this;
```

`this`

[`SliderComponent`](obsidian.SliderComponent.md) › [`(constructor)`](obsidian.SliderComponent.(constructor).md)

## SliderComponent.(constructor)

Constructs a new instance of the `SliderComponent` class

```

[`SliderComponent`](obsidian.SliderComponent.md) › [`showTooltip`](obsidian.SliderComponent.showTooltip.md)

## SliderComponent.showTooltip() method

showTooltip(): void;
```

`void`

[`SliderComponent`](obsidian.SliderComponent.md) › [`setLimits`](obsidian.SliderComponent.setLimits.md)

## SliderComponent.setLimits() method

setLimits(min: number, max: number, step: number | 'any'): this;
```

|  <code>min</code> | <code>number</code> |  |
|  <code>max</code> | <code>number</code> |  |
|  <code>step</code> | <code>number &#124; 'any'</code> |  |

`this`

[`EditorScrollInfo`](obsidian.EditorScrollInfo.md) › [`width`](obsidian.EditorScrollInfo.width.md)

## EditorScrollInfo.width property

width: number;
```

[`EditorScrollInfo`](obsidian.EditorScrollInfo.md) › [`clientHeight`](obsidian.EditorScrollInfo.clientHeight.md)

## EditorScrollInfo.clientHeight property

clientHeight: number;
```

[`EditorScrollInfo`](obsidian.EditorScrollInfo.md) › [`clientWidth`](obsidian.EditorScrollInfo.clientWidth.md)

## EditorScrollInfo.clientWidth property

clientWidth: number;
```

[`EditorScrollInfo`](obsidian.EditorScrollInfo.md) › [`left`](obsidian.EditorScrollInfo.left.md)

## EditorScrollInfo.left property

left: number;
```

[`EditorScrollInfo`](obsidian.EditorScrollInfo.md) › [`height`](obsidian.EditorScrollInfo.height.md)

## EditorScrollInfo.height property

height: number;
```

[`EditorScrollInfo`](obsidian.EditorScrollInfo.md) › [`top`](obsidian.EditorScrollInfo.top.md)

## EditorScrollInfo.top property

top: number;
```

[`EditorSuggestContext`](obsidian.EditorSuggestContext.md) › [`file`](obsidian.EditorSuggestContext.file.md)

## EditorSuggestContext.file property

file: TFile;
```

[`EditorSuggestContext`](obsidian.EditorSuggestContext.md) › [`editor`](obsidian.EditorSuggestContext.editor.md)

## EditorSuggestContext.editor property

editor: Editor;
```

[`ListedFiles`](obsidian.ListedFiles.md) › [`folders`](obsidian.ListedFiles.folders.md)

## ListedFiles.folders property

folders: string[];
```

[`ListedFiles`](obsidian.ListedFiles.md) › [`files`](obsidian.ListedFiles.files.md)

## ListedFiles.files property

files: string[];
```

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`stat`](obsidian.FileSystemAdapter.stat.md)

## FileSystemAdapter.stat() method

stat(normalizedPath: string): Promise<Stat | null>;
```

|  <code>normalizedPath</code> | <code>string</code> |  |

`Promise``<`[`Stat`](obsidian.Stat.md)` | null>`

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`process`](obsidian.FileSystemAdapter.process.md)

## FileSystemAdapter.process() method

process(normalizedPath: string, fn: (data: string) => string, options?: DataWriteOptions): Promise<string>;
```

|  <code>fn</code> | <code>(data: string) =&gt; string</code> |  |
|  <code>options</code> | [`DataWriteOptions`](obsidian.DataWriteOptions.md) | _(Optional)_ |

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`mkdir`](obsidian.FileSystemAdapter.mkdir.md)

## FileSystemAdapter.mkdir() method

static mkdir(path: string): Promise<void>;
```

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`read`](obsidian.FileSystemAdapter.read.md)

## FileSystemAdapter.read() method

read(normalizedPath: string): Promise<string>;
```

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`writeBinary`](obsidian.FileSystemAdapter.writeBinary.md)

## FileSystemAdapter.writeBinary() method

writeBinary(normalizedPath: string, data: ArrayBuffer, options?: DataWriteOptions): Promise<void>;
```

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`trashLocal`](obsidian.FileSystemAdapter.trashLocal.md)

## FileSystemAdapter.trashLocal() method

trashLocal(normalizedPath: string): Promise<void>;
```

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`append`](obsidian.FileSystemAdapter.append.md)

## FileSystemAdapter.append() method

append(normalizedPath: string, data: string, options?: DataWriteOptions): Promise<void>;
```

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`list`](obsidian.FileSystemAdapter.list.md)

## FileSystemAdapter.list() method

list(normalizedPath: string): Promise<ListedFiles>;
```

`Promise``<`[`ListedFiles`](obsidian.ListedFiles.md)`>`

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`readLocalFile`](obsidian.FileSystemAdapter.readLocalFile.md)

## FileSystemAdapter.readLocalFile() method

static readLocalFile(path: string): Promise<ArrayBuffer>;
```

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`readBinary`](obsidian.FileSystemAdapter.readBinary.md)

## FileSystemAdapter.readBinary() method

readBinary(normalizedPath: string): Promise<ArrayBuffer>;
```

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`rename`](obsidian.FileSystemAdapter.rename.md)

## FileSystemAdapter.rename() method

rename(normalizedPath: string, normalizedNewPath: string): Promise<void>;
```

|  <code>normalizedNewPath</code> | <code>string</code> |  |

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`trashSystem`](obsidian.FileSystemAdapter.trashSystem.md)

## FileSystemAdapter.trashSystem() method

trashSystem(normalizedPath: string): Promise<boolean>;
```

`Promise``<boolean>`

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`write`](obsidian.FileSystemAdapter.write.md)

## FileSystemAdapter.write() method

write(normalizedPath: string, data: string, options?: DataWriteOptions): Promise<void>;
```

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`getBasePath`](obsidian.FileSystemAdapter.getBasePath.md)

## FileSystemAdapter.getBasePath() method

getBasePath(): string;
```

`string`

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`getFullPath`](obsidian.FileSystemAdapter.getFullPath.md)

## FileSystemAdapter.getFullPath() method

getFullPath(normalizedPath: string): string;
```

`string`

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`exists`](obsidian.FileSystemAdapter.exists.md)

## FileSystemAdapter.exists() method

exists(normalizedPath: string, sensitive?: boolean): Promise<boolean>;
```

|  <code>sensitive</code> | <code>boolean</code> | _(Optional)_ |

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`rmdir`](obsidian.FileSystemAdapter.rmdir.md)

## FileSystemAdapter.rmdir() method

rmdir(normalizedPath: string, recursive: boolean): Promise<void>;
```

|  <code>recursive</code> | <code>boolean</code> |  |

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`copy`](obsidian.FileSystemAdapter.copy.md)

## FileSystemAdapter.copy() method

copy(normalizedPath: string, normalizedNewPath: string): Promise<void>;
```

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`getFilePath`](obsidian.FileSystemAdapter.getFilePath.md)

## FileSystemAdapter.getFilePath() method

Returns the file:// path of this file

getFilePath(normalizedPath: string): string;
```

`string`

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`getName`](obsidian.FileSystemAdapter.getName.md)

## FileSystemAdapter.getName() method

getName(): string;
```

`string`

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`remove`](obsidian.FileSystemAdapter.remove.md)

## FileSystemAdapter.remove() method

remove(normalizedPath: string): Promise<void>;
```

[`FileSystemAdapter`](obsidian.FileSystemAdapter.md) › [`getResourcePath`](obsidian.FileSystemAdapter.getResourcePath.md)

## FileSystemAdapter.getResourcePath() method

getResourcePath(normalizedPath: string): string;
```

`string`

[`Pos`](obsidian.Pos.md) › [`end`](obsidian.Pos.end.md)

## Pos.end property

end: Loc;
```

[`Pos`](obsidian.Pos.md) › [`start`](obsidian.Pos.start.md)

## Pos.start property

```

[`SearchResultContainer`](obsidian.SearchResultContainer.md) › [`match`](obsidian.SearchResultContainer.match.md)

## SearchResultContainer.match property

```

[`Stat`](obsidian.Stat.md) › [`ctime`](obsidian.Stat.ctime.md)

## Stat.ctime property

Time of creation, represented as a unix timestamp.

```

[`Stat`](obsidian.Stat.md) › [`mtime`](obsidian.Stat.mtime.md)

## Stat.mtime property

Time of last modification, represented as a unix timestamp.

```

[`Stat`](obsidian.Stat.md) › [`size`](obsidian.Stat.size.md)

## Stat.size property

```

[`Stat`](obsidian.Stat.md) › [`type`](obsidian.Stat.type.md)

## Stat.type property

type: 'file' | 'folder';
```

[`CachedMetadata`](obsidian.CachedMetadata.md) › [`listItems`](obsidian.CachedMetadata.listItems.md)

## CachedMetadata.listItems property

listItems?: ListItemCache[];
```

[`CachedMetadata`](obsidian.CachedMetadata.md) › [`frontmatterPosition`](obsidian.CachedMetadata.frontmatterPosition.md)

## CachedMetadata.frontmatterPosition property

frontmatterPosition?: Pos;
```

[`CachedMetadata`](obsidian.CachedMetadata.md) › [`embeds`](obsidian.CachedMetadata.embeds.md)

## CachedMetadata.embeds property

embeds?: EmbedCache[];
```

[`CachedMetadata`](obsidian.CachedMetadata.md) › [`blocks`](obsidian.CachedMetadata.blocks.md)

## CachedMetadata.blocks property

blocks?: Record<string, BlockCache>;
```

[`CachedMetadata`](obsidian.CachedMetadata.md) › [`frontmatter`](obsidian.CachedMetadata.frontmatter.md)

## CachedMetadata.frontmatter property

frontmatter?: FrontMatterCache;
```

[`CachedMetadata`](obsidian.CachedMetadata.md) › [`sections`](obsidian.CachedMetadata.sections.md)

## CachedMetadata.sections property

Sections are root level markdown blocks, which can be used to divide the document up.

sections?: SectionCache[];
```

[`CachedMetadata`](obsidian.CachedMetadata.md) › [`tags`](obsidian.CachedMetadata.tags.md)

## CachedMetadata.tags property

tags?: TagCache[];
```

[`CachedMetadata`](obsidian.CachedMetadata.md) › [`headings`](obsidian.CachedMetadata.headings.md)

## CachedMetadata.headings property

headings?: HeadingCache[];
```

[`CachedMetadata`](obsidian.CachedMetadata.md) › [`links`](obsidian.CachedMetadata.links.md)

## CachedMetadata.links property

links?: LinkCache[];
```

[`CachedMetadata`](obsidian.CachedMetadata.md) › [`frontmatterLinks`](obsidian.CachedMetadata.frontmatterLinks.md)

## CachedMetadata.frontmatterLinks property

frontmatterLinks?: FrontmatterLinkCache[];
```

[`EditorSuggestTriggerInfo`](obsidian.EditorSuggestTriggerInfo.md) › [`query`](obsidian.EditorSuggestTriggerInfo.query.md)

## EditorSuggestTriggerInfo.query property

They query string (usually the text between start and end) that will be used to generate the suggestion content.

```

[`EditorSuggestTriggerInfo`](obsidian.EditorSuggestTriggerInfo.md) › [`end`](obsidian.EditorSuggestTriggerInfo.end.md)

## EditorSuggestTriggerInfo.end property

The end position of the triggering text. This is used to position the popover.

end: EditorPosition;
```

[`EditorSuggestTriggerInfo`](obsidian.EditorSuggestTriggerInfo.md) › [`start`](obsidian.EditorSuggestTriggerInfo.start.md)

## EditorSuggestTriggerInfo.start property

The start position of the triggering text. This is used to position the popover.

start: EditorPosition;
```

[`SectionCache`](obsidian.SectionCache.md) › [`id`](obsidian.SectionCache.id.md)

## SectionCache.id property

The block ID of this section, if defined.

```

[`SectionCache`](obsidian.SectionCache.md) › [`type`](obsidian.SectionCache.type.md)

## SectionCache.type property

The type string generated by the parser.

type: string;
```

[`FileView`](obsidian.FileView.md) › [`getState`](obsidian.FileView.getState.md)

## FileView.getState() method

getState(): any;
```

`any`

[`FileView`](obsidian.FileView.md) › [`file`](obsidian.FileView.file.md)

## FileView.file property

file: TFile | null;
```

[`FileView`](obsidian.FileView.md) › [`navigation`](obsidian.FileView.navigation.md)

## FileView.navigation property

File views can be navigated by default. 

navigation: boolean;
```

[`FileView`](obsidian.FileView.md) › [`onload`](obsidian.FileView.onload.md)

## FileView.onload() method

```

`void`

[`FileView`](obsidian.FileView.md) › [`setState`](obsidian.FileView.setState.md)

## FileView.setState() method

setState(state: any, result: ViewStateResult): Promise<void>;
```

|  <code>state</code> | <code>any</code> |  |
|  <code>result</code> | [`ViewStateResult`](obsidian.ViewStateResult.md) |  |

[`FileView`](obsidian.FileView.md) › [`canAcceptExtension`](obsidian.FileView.canAcceptExtension.md)

## FileView.canAcceptExtension() method

canAcceptExtension(extension: string): boolean;
```

|  <code>extension</code> | <code>string</code> |  |

`boolean`

[`FileView`](obsidian.FileView.md) › [`onUnloadFile`](obsidian.FileView.onUnloadFile.md)

## FileView.onUnloadFile() method

```

[`FileView`](obsidian.FileView.md) › [`(constructor)`](obsidian.FileView.(constructor).md)

## FileView.(constructor)

Constructs a new instance of the `FileView` class

```

[`FileView`](obsidian.FileView.md) › [`getDisplayText`](obsidian.FileView.getDisplayText.md)

## FileView.getDisplayText() method

getDisplayText(): string;
```

`string`

[`FileView`](obsidian.FileView.md) › [`onLoadFile`](obsidian.FileView.onLoadFile.md)

## FileView.onLoadFile() method

```

[`FileView`](obsidian.FileView.md) › [`allowNoFile`](obsidian.FileView.allowNoFile.md)

## FileView.allowNoFile property

allowNoFile: boolean;
```

[`FileView`](obsidian.FileView.md) › [`onRename`](obsidian.FileView.onRename.md)

## FileView.onRename() method

onRename(file: TFile): Promise<void>;
```

[`FileManager`](obsidian.FileManager.md) › [`generateMarkdownLink`](obsidian.FileManager.generateMarkdownLink.md)

## FileManager.generateMarkdownLink() method

Generate a markdown link based on the user's preferences.

generateMarkdownLink(file: TFile, sourcePath: string, subpath?: string, alias?: string): string;
```

|  <code>file</code> | [`TFile`](obsidian.TFile.md) | the file to link to. |
|  <code>sourcePath</code> | <code>string</code> | where the link is stored in, used to compute relative links. |
|  <code>subpath</code> | <code>string</code> | _(Optional)_ A subpath, starting with <code>#</code>, used for linking to headings or blocks. |
|  <code>alias</code> | <code>string</code> | _(Optional)_ The display text if it's to be different than the file name. Pass empty string to use file name. |

`string`

[`FileManager`](obsidian.FileManager.md) › [`processFrontMatter`](obsidian.FileManager.processFrontMatter.md)

## FileManager.processFrontMatter() method

Atomically read, modify, and save the frontmatter of a note. The frontmatter is passed in as a JS object, and should be mutated directly to achieve the desired result.

Remember to handle errors thrown by this method.

processFrontMatter(file: TFile, fn: (frontmatter: any) => void, options?: DataWriteOptions): Promise<void>;
```

|  <code>file</code> | [`TFile`](obsidian.TFile.md) | the file to be modified. Must be a markdown file. |
|  <code>fn</code> | <code>(frontmatter: any) =&gt; void</code> | a callback function which mutates the frontMatter object synchronously. |
|  <code>options</code> | [`DataWriteOptions`](obsidian.DataWriteOptions.md) | _(Optional)_ write options. |

## Exceptions

YAMLParseError if the YAML parsing fails

any errors that your callback function throws

[`FileManager`](obsidian.FileManager.md) › [`getNewFileParent`](obsidian.FileManager.getNewFileParent.md)

## FileManager.getNewFileParent() method

Gets the folder that new files should be saved to, given the user's preferences.

getNewFileParent(sourcePath: string, newFilePath?: string): TFolder;
```

|  <code>sourcePath</code> | <code>string</code> | The path to the current open/focused file, used when the user wants new files to be created "in the same folder". Use an empty string if there is no active file. |
|  <code>newFilePath</code> | <code>string</code> | _(Optional)_ The path to the file that will be newly created, used to infer what settings to use based on the path's extension. |

[`FileManager`](obsidian.FileManager.md) › [`renameFile`](obsidian.FileManager.renameFile.md)

## FileManager.renameFile() method

Rename or move a file safely, and update all links to it depending on the user's preferences.

renameFile(file: TAbstractFile, newPath: string): Promise<void>;
```

|  <code>file</code> | [`TAbstractFile`](obsidian.TAbstractFile.md) | the file to rename |
|  <code>newPath</code> | <code>string</code> | the new path for the file |

[`RequestUrlResponse`](obsidian.RequestUrlResponse.md) › [`text`](obsidian.RequestUrlResponse.text.md)

## RequestUrlResponse.text property

```

[`RequestUrlResponse`](obsidian.RequestUrlResponse.md) › [`json`](obsidian.RequestUrlResponse.json.md)

## RequestUrlResponse.json property

json: any;
```

[`RequestUrlResponse`](obsidian.RequestUrlResponse.md) › [`status`](obsidian.RequestUrlResponse.status.md)

## RequestUrlResponse.status property

status: number;
```

[`RequestUrlResponse`](obsidian.RequestUrlResponse.md) › [`headers`](obsidian.RequestUrlResponse.headers.md)

## RequestUrlResponse.headers property

headers: Record<string, string>;
```

[`RequestUrlResponse`](obsidian.RequestUrlResponse.md) › [`arrayBuffer`](obsidian.RequestUrlResponse.arrayBuffer.md)

## RequestUrlResponse.arrayBuffer property

arrayBuffer: ArrayBuffer;
```

[`Menu`](obsidian.Menu.md) › [`hide`](obsidian.Menu.hide.md)

## Menu.hide() method

hide(): this;
```

`this`

[`Menu`](obsidian.Menu.md) › [`onHide`](obsidian.Menu.onHide.md)

## Menu.onHide() method

onHide(callback: () => any): void;
```

`void`

[`Menu`](obsidian.Menu.md) › [`setNoIcon`](obsidian.Menu.setNoIcon.md)

## Menu.setNoIcon() method

setNoIcon(): this;
```

`this`

[`Menu`](obsidian.Menu.md) › [`showAtMouseEvent`](obsidian.Menu.showAtMouseEvent.md)

## Menu.showAtMouseEvent() method

showAtMouseEvent(evt: MouseEvent): this;
```

|  <code>evt</code> | <code>MouseEvent</code> |  |

`this`

[`Menu`](obsidian.Menu.md) › [`close`](obsidian.Menu.close.md)

## Menu.close() method

close(): void;
```

`void`

[`Menu`](obsidian.Menu.md) › [`addSeparator`](obsidian.Menu.addSeparator.md)

## Menu.addSeparator() method

Adds a separator. Only works when menu is not shown yet.

addSeparator(): this;
```

`this`

[`Menu`](obsidian.Menu.md) › [`(constructor)`](obsidian.Menu.(constructor).md)

## Menu.(constructor)

Constructs a new instance of the `Menu` class

constructor();
```

[`Menu`](obsidian.Menu.md) › [`showAtPosition`](obsidian.Menu.showAtPosition.md)

## Menu.showAtPosition() method

showAtPosition(position: MenuPositionDef, doc?: Document): this;
```

|  <code>position</code> | [`MenuPositionDef`](obsidian.MenuPositionDef.md) |  |
|  <code>doc</code> | <code>Document</code> | _(Optional)_ |

`this`

[`Menu`](obsidian.Menu.md) › [`setUseNativeMenu`](obsidian.Menu.setUseNativeMenu.md)

## Menu.setUseNativeMenu() method

Force this menu to use native or DOM. (Only works on the desktop app)

setUseNativeMenu(useNativeMenu: boolean): this;
```

|  <code>useNativeMenu</code> | <code>boolean</code> |  |

`this`

[`Menu`](obsidian.Menu.md) › [`addItem`](obsidian.Menu.addItem.md)

## Menu.addItem() method

Adds a menu item. Only works when menu is not shown yet.

addItem(cb: (item: MenuItem) => any): this;
```

|  <code>cb</code> | <code>(item: </code>[`MenuItem`](obsidian.MenuItem.md)<code>) =&gt; any</code> |  |

`this`

[`TFile`](obsidian.TFile.md) › [`stat`](obsidian.TFile.stat.md)

## TFile.stat property

stat: FileStats;
```

[`TFile`](obsidian.TFile.md) › [`extension`](obsidian.TFile.extension.md)

## TFile.extension property

extension: string;
```

[`TFile`](obsidian.TFile.md) › [`basename`](obsidian.TFile.basename.md)

## TFile.basename property

basename: string;
```

[`EditorChange`](obsidian.EditorChange.md) › [`text`](obsidian.EditorChange.text.md)

## EditorChange.text property

```

[`TextComponent`](obsidian.TextComponent.md) › [`(constructor)`](obsidian.TextComponent.(constructor).md)

## TextComponent.(constructor)

Constructs a new instance of the `TextComponent` class

```

[`CacheItem`](obsidian.CacheItem.md) › [`position`](obsidian.CacheItem.position.md)

## CacheItem.position property

position: Pos;
```

[`View`](obsidian.View.md) › [`onOpen`](obsidian.View.onOpen.md)

## View.onOpen() method

protected onOpen(): Promise<void>;
```

[`View`](obsidian.View.md) › [`app`](obsidian.View.app.md)

## View.app property

app: App;
```

[`View`](obsidian.View.md) › [`getIcon`](obsidian.View.getIcon.md)

## View.getIcon() method

getIcon(): IconName;
```

[`View`](obsidian.View.md) › [`getState`](obsidian.View.getState.md)

## View.getState() method

```

`any`

[`View`](obsidian.View.md) › [`onResize`](obsidian.View.onResize.md)

## View.onResize() method

Called when the size of this view is changed.

onResize(): void;
```

`void`

[`View`](obsidian.View.md) › [`navigation`](obsidian.View.navigation.md)

## View.navigation property

Whether or not the view is intended for navigation. If your view is a static view that is not intended to be navigated away, set this to false. (For example: File explorer, calendar, etc.) If your view opens a file or can be otherwise navigated, set this to true. (For example: Markdown editor view, Kanban view, PDF view, etc.)

```

[`View`](obsidian.View.md) › [`setState`](obsidian.View.setState.md)

## View.setState() method

```

[`View`](obsidian.View.md) › [`onPaneMenu`](obsidian.View.onPaneMenu.md)

## View.onPaneMenu() method

Populates the pane menu.

(Replaces the previously removed `onHeaderMenu` and `onMoreOptionsMenu`<!-- -->)

onPaneMenu(menu: Menu, source: 'more-options' | 'tab-header' | string): void;
```

|  <code>menu</code> | [`Menu`](obsidian.Menu.md) |  |
|  <code>source</code> | <code>'more-options' &#124; 'tab-header' &#124; string</code> |  |

`void`

[`View`](obsidian.View.md) › [`onClose`](obsidian.View.onClose.md)

## View.onClose() method

protected onClose(): Promise<void>;
```

[`View`](obsidian.View.md) › [`containerEl`](obsidian.View.containerEl.md)

## View.containerEl property

```

[`View`](obsidian.View.md) › [`(constructor)`](obsidian.View.(constructor).md)

## View.(constructor)

Constructs a new instance of the `View` class

```

[`View`](obsidian.View.md) › [`icon`](obsidian.View.icon.md)

## View.icon property

icon: IconName;
```

[`View`](obsidian.View.md) › [`getDisplayText`](obsidian.View.getDisplayText.md)

## View.getDisplayText() method

abstract getDisplayText(): string;
```

`string`

[`View`](obsidian.View.md) › [`setEphemeralState`](obsidian.View.setEphemeralState.md)

## View.setEphemeralState() method

setEphemeralState(state: any): void;
```

`void`

[`View`](obsidian.View.md) › [`getViewType`](obsidian.View.getViewType.md)

## View.getViewType() method

abstract getViewType(): string;
```

`string`

[`View`](obsidian.View.md) › [`leaf`](obsidian.View.leaf.md)

## View.leaf property

leaf: WorkspaceLeaf;
```

[`View`](obsidian.View.md) › [`getEphemeralState`](obsidian.View.getEphemeralState.md)

## View.getEphemeralState() method

getEphemeralState(): any;
```

`any`

[`Keymap`](obsidian.Keymap.md) › [`isModEvent`](obsidian.Keymap.isModEvent.md)

## Keymap.isModEvent() method

Translates an event into the type of pane that should open. Returns 'tab' if the modifier key Cmd/Ctrl is pressed OR if this is a middle-click MouseEvent. Returns 'split' if Cmd/Ctrl+Alt is pressed. Returns 'window' if Cmd/Ctrl+Alt+Shift is pressed.

static isModEvent(evt?: UserEvent | null): PaneType | boolean;
```

|  <code>evt</code> | [`UserEvent`](obsidian.UserEvent.md)<code> &#124; null</code> | _(Optional)_ |

[`PaneType`](obsidian.PaneType.md)` | boolean`

[`Keymap`](obsidian.Keymap.md) › [`popScope`](obsidian.Keymap.popScope.md)

## Keymap.popScope() method

popScope(scope: Scope): void;
```

|  <code>scope</code> | [`Scope`](obsidian.Scope.md) |  |

`void`

[`Keymap`](obsidian.Keymap.md) › [`isModifier`](obsidian.Keymap.isModifier.md)

## Keymap.isModifier() method

Checks whether the modifier key is pressed during this event

static isModifier(evt: MouseEvent | TouchEvent | KeyboardEvent, modifier: Modifier): boolean;
```

|  <code>evt</code> | <code>MouseEvent</code><code> &#124; </code><code>TouchEvent</code><code> &#124; </code><code>KeyboardEvent</code> |  |
|  <code>modifier</code> | [`Modifier`](obsidian.Modifier.md) |  |

`boolean`

[`Keymap`](obsidian.Keymap.md) › [`pushScope`](obsidian.Keymap.pushScope.md)

## Keymap.pushScope() method

pushScope(scope: Scope): void;
```

`void`

[`EditorPosition`](obsidian.EditorPosition.md) › [`ch`](obsidian.EditorPosition.ch.md)

## EditorPosition.ch property

ch: number;
```

[`EditorPosition`](obsidian.EditorPosition.md) › [`line`](obsidian.EditorPosition.line.md)

## EditorPosition.line property

```

[`EditorRange`](obsidian.EditorRange.md) › [`to`](obsidian.EditorRange.to.md)

## EditorRange.to property

to: EditorPosition;
```

[`EditorRange`](obsidian.EditorRange.md) › [`from`](obsidian.EditorRange.from.md)

## EditorRange.from property

```

[`Instruction`](obsidian.Instruction.md) › [`command`](obsidian.Instruction.command.md)

## Instruction.command property

command: string;
```

[`Instruction`](obsidian.Instruction.md) › [`purpose`](obsidian.Instruction.purpose.md)

## Instruction.purpose property

purpose: string;
```

[`MarkdownPreviewView`](obsidian.MarkdownPreviewView.md) › [`rerender`](obsidian.MarkdownPreviewView.rerender.md)

## MarkdownPreviewView.rerender() method

rerender(full?: boolean): void;
```

|  <code>full</code> | <code>boolean</code> | _(Optional)_ |

`void`

[`MarkdownPreviewView`](obsidian.MarkdownPreviewView.md) › [`file`](obsidian.MarkdownPreviewView.file.md)

## MarkdownPreviewView.file property

```

[`MarkdownPreviewView`](obsidian.MarkdownPreviewView.md) › [`get`](obsidian.MarkdownPreviewView.get.md)

## MarkdownPreviewView.get() method

```

`string`

[`MarkdownPreviewView`](obsidian.MarkdownPreviewView.md) › [`set`](obsidian.MarkdownPreviewView.set.md)

## MarkdownPreviewView.set() method

```

`void`

[`MarkdownPreviewView`](obsidian.MarkdownPreviewView.md) › [`containerEl`](obsidian.MarkdownPreviewView.containerEl.md)

## MarkdownPreviewView.containerEl property

```

[`MarkdownPreviewView`](obsidian.MarkdownPreviewView.md) › [`clear`](obsidian.MarkdownPreviewView.clear.md)

## MarkdownPreviewView.clear() method

```

`void`

[`MarkdownPreviewView`](obsidian.MarkdownPreviewView.md) › [`applyScroll`](obsidian.MarkdownPreviewView.applyScroll.md)

## MarkdownPreviewView.applyScroll() method

```

`void`

[`MarkdownPreviewView`](obsidian.MarkdownPreviewView.md) › [`getScroll`](obsidian.MarkdownPreviewView.getScroll.md)

## MarkdownPreviewView.getScroll() method

```

`number`

[`WorkspaceWindow`](obsidian.WorkspaceWindow.md) › [`doc`](obsidian.WorkspaceWindow.doc.md)

## WorkspaceWindow.doc property

```

[`WorkspaceWindow`](obsidian.WorkspaceWindow.md) › [`win`](obsidian.WorkspaceWindow.win.md)

## WorkspaceWindow.win property

```

[`SearchResult`](obsidian.SearchResult.md) › [`score`](obsidian.SearchResult.score.md)

## SearchResult.score property

score: number;
```

[`SearchResult`](obsidian.SearchResult.md) › [`matches`](obsidian.SearchResult.matches.md)

## SearchResult.matches property

matches: SearchMatches;
```

[`MetadataCache`](obsidian.MetadataCache.md) › [`getFirstLinkpathDest`](obsidian.MetadataCache.getFirstLinkpathDest.md)

## MetadataCache.getFirstLinkpathDest() method

Get the best match for a linkpath.

getFirstLinkpathDest(linkpath: string, sourcePath: string): TFile | null;
```

|  <code>linkpath</code> | <code>string</code> |  |

[`MetadataCache`](obsidian.MetadataCache.md) › [`on`](obsidian.MetadataCache.on_1.md)

## MetadataCache.on() method

Called when a file has been deleted. A best-effort previous version of the cached metadata is presented, but it could be null in case the file was not successfully cached previously.

on(name: 'deleted', callback: (file: TFile, prevCache: CachedMetadata | null) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'deleted'</code> |  |
|  <code>callback</code> | <code>(file: </code>[`TFile`](obsidian.TFile.md)<code>, prevCache: </code>[`CachedMetadata`](obsidian.CachedMetadata.md)<code> &#124; null) =&gt; any</code> |  |

[`MetadataCache`](obsidian.MetadataCache.md) › [`resolvedLinks`](obsidian.MetadataCache.resolvedLinks.md)

## MetadataCache.resolvedLinks property

Contains all resolved links. This object maps each source file's path to an object of destination file paths with the link count. Source and destination paths are all vault absolute paths that comes from `TFile.path` and can be used with `Vault.getAbstractFileByPath(path)`<!-- -->.

resolvedLinks: Record<string, Record<string, number>>;
```

[`MetadataCache`](obsidian.MetadataCache.md) › [`on`](obsidian.MetadataCache.on_3.md)

Called when all files has been resolved. This will be fired each time files get modified after the initial load.

on(name: 'resolved', callback: () => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'resolved'</code> |  |

[`MetadataCache`](obsidian.MetadataCache.md) › [`getCache`](obsidian.MetadataCache.getCache.md)

## MetadataCache.getCache() method

getCache(path: string): CachedMetadata | null;
```

[`CachedMetadata`](obsidian.CachedMetadata.md)` | null`

[`MetadataCache`](obsidian.MetadataCache.md) › [`getFileCache`](obsidian.MetadataCache.getFileCache.md)

## MetadataCache.getFileCache() method

getFileCache(file: TFile): CachedMetadata | null;
```

[`MetadataCache`](obsidian.MetadataCache.md) › [`on`](obsidian.MetadataCache.on_2.md)

Called when a file has been resolved for `resolvedLinks` and `unresolvedLinks`<!-- -->. This happens sometimes after a file has been indexed.

on(name: 'resolve', callback: (file: TFile) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'resolve'</code> |  |
|  <code>callback</code> | <code>(file: </code>[`TFile`](obsidian.TFile.md)<code>) =&gt; any</code> |  |

[`MetadataCache`](obsidian.MetadataCache.md) › [`unresolvedLinks`](obsidian.MetadataCache.unresolvedLinks.md)

## MetadataCache.unresolvedLinks property

Contains all unresolved links. This object maps each source file to an object of unknown destinations with count. Source paths are all vault absolute paths, similar to `resolvedLinks`<!-- -->.

unresolvedLinks: Record<string, Record<string, number>>;
```

[`MetadataCache`](obsidian.MetadataCache.md) › [`on`](obsidian.MetadataCache.on.md)

Called when a file has been indexed, and its (updated) cache is now available.

Note: This is not called when a file is renamed for performance reasons. You must hook the vault rename event for those. (Details: https://github.com/obsidianmd/obsidian-api/issues/77)

on(name: 'changed', callback: (file: TFile, data: string, cache: CachedMetadata) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'changed'</code> |  |
|  <code>callback</code> | <code>(file: </code>[`TFile`](obsidian.TFile.md)<code>, data: string, cache: </code>[`CachedMetadata`](obsidian.CachedMetadata.md)<code>) =&gt; any</code> |  |

[`MetadataCache`](obsidian.MetadataCache.md) › [`fileToLinktext`](obsidian.MetadataCache.fileToLinktext.md)

## MetadataCache.fileToLinktext() method

Generates a linktext for a file.

If file name is unique, use the filename. If not unique, use full path.

fileToLinktext(file: TFile, sourcePath: string, omitMdExtension?: boolean): string;
```

|  <code>omitMdExtension</code> | <code>boolean</code> | _(Optional)_ |

`string`

[`CloseableComponent`](obsidian.CloseableComponent.md) › [`close`](obsidian.CloseableComponent.close.md)

## CloseableComponent.close() method

close(): any;
```

`any`

[`Hotkey`](obsidian.Hotkey.md) › [`modifiers`](obsidian.Hotkey.modifiers.md)

## Hotkey.modifiers property

modifiers: Modifier[];
```

[`Hotkey`](obsidian.Hotkey.md) › [`key`](obsidian.Hotkey.key.md)

## Hotkey.key property

```

[`ExtraButtonComponent`](obsidian.ExtraButtonComponent.md) › [`setTooltip`](obsidian.ExtraButtonComponent.setTooltip.md)

## ExtraButtonComponent.setTooltip() method

```

`this`

[`ExtraButtonComponent`](obsidian.ExtraButtonComponent.md) › [`setIcon`](obsidian.ExtraButtonComponent.setIcon.md)

## ExtraButtonComponent.setIcon() method

```

|  <code>icon</code> | [`IconName`](obsidian.IconName.md) | ID of the icon, can use any icon loaded with [addIcon()](obsidian.addIcon.md) or from the inbuilt library. |

`this`

[`ExtraButtonComponent`](obsidian.ExtraButtonComponent.md) › [`setDisabled`](obsidian.ExtraButtonComponent.setDisabled.md)

## ExtraButtonComponent.setDisabled() method

```

`this`

[`ExtraButtonComponent`](obsidian.ExtraButtonComponent.md) › [`(constructor)`](obsidian.ExtraButtonComponent.(constructor).md)

## ExtraButtonComponent.(constructor)

Constructs a new instance of the `ExtraButtonComponent` class

```

[`ExtraButtonComponent`](obsidian.ExtraButtonComponent.md) › [`onClick`](obsidian.ExtraButtonComponent.onClick.md)

## ExtraButtonComponent.onClick() method

onClick(callback: () => any): this;
```

`this`

[`ExtraButtonComponent`](obsidian.ExtraButtonComponent.md) › [`extraSettingsEl`](obsidian.ExtraButtonComponent.extraSettingsEl.md)

## ExtraButtonComponent.extraSettingsEl property

extraSettingsEl: HTMLElement;
```

[`DropdownComponent`](obsidian.DropdownComponent.md) › [`getValue`](obsidian.DropdownComponent.getValue.md)

## DropdownComponent.getValue() method

getValue(): string;
```

`string`

[`DropdownComponent`](obsidian.DropdownComponent.md) › [`setDisabled`](obsidian.DropdownComponent.setDisabled.md)

## DropdownComponent.setDisabled() method

```

`this`

[`DropdownComponent`](obsidian.DropdownComponent.md) › [`onChange`](obsidian.DropdownComponent.onChange.md)

## DropdownComponent.onChange() method

```

`this`

[`DropdownComponent`](obsidian.DropdownComponent.md) › [`setValue`](obsidian.DropdownComponent.setValue.md)

## DropdownComponent.setValue() method

```

`this`

[`DropdownComponent`](obsidian.DropdownComponent.md) › [`addOptions`](obsidian.DropdownComponent.addOptions.md)

## DropdownComponent.addOptions() method

addOptions(options: Record<string, string>): this;
```

|  <code>options</code> | <code>Record</code><code>&lt;string, string&gt;</code> |  |

`this`

[`DropdownComponent`](obsidian.DropdownComponent.md) › [`(constructor)`](obsidian.DropdownComponent.(constructor).md)

## DropdownComponent.(constructor)

Constructs a new instance of the `DropdownComponent` class

```

[`DropdownComponent`](obsidian.DropdownComponent.md) › [`addOption`](obsidian.DropdownComponent.addOption.md)

## DropdownComponent.addOption() method

addOption(value: string, display: string): this;
```

|  <code>display</code> | <code>string</code> |  |

`this`

[`DropdownComponent`](obsidian.DropdownComponent.md) › [`selectEl`](obsidian.DropdownComponent.selectEl.md)

## DropdownComponent.selectEl property

selectEl: HTMLSelectElement;
```

[`DataAdapter`](obsidian.DataAdapter.md) › [`stat`](obsidian.DataAdapter.stat.md)

## DataAdapter.stat() method

Retrieve metadata about the given file/folder.

```

|  <code>normalizedPath</code> | <code>string</code> | path to file/folder, use [normalizePath()](obsidian.normalizePath.md) to normalize beforehand. |

[`DataAdapter`](obsidian.DataAdapter.md) › [`process`](obsidian.DataAdapter.process.md)

## DataAdapter.process() method

Atomically read, modify, and save the contents of a plaintext file.

```

|  <code>fn</code> | <code>(data: string) =&gt; string</code> | a callback function which returns the new content of the file synchronously. |

string - the text value of the file that was written.

[`DataAdapter`](obsidian.DataAdapter.md) › [`mkdir`](obsidian.DataAdapter.mkdir.md)

## DataAdapter.mkdir() method

Create a directory.

mkdir(normalizedPath: string): Promise<void>;
```

|  <code>normalizedPath</code> | <code>string</code> | path to use for new folder, use [normalizePath()](obsidian.normalizePath.md) to normalize beforehand. |

[`DataAdapter`](obsidian.DataAdapter.md) › [`read`](obsidian.DataAdapter.read.md)

## DataAdapter.read() method

```

|  <code>normalizedPath</code> | <code>string</code> | path to file, use [normalizePath()](obsidian.normalizePath.md) to normalize beforehand. |

[`DataAdapter`](obsidian.DataAdapter.md) › [`writeBinary`](obsidian.DataAdapter.writeBinary.md)

## DataAdapter.writeBinary() method

Write to a binary file. If the file exists its content will be overwritten, otherwise the file will be created.

```

|  <code>data</code> | <code>ArrayBuffer</code> | the new file content |
|  <code>options</code> | [`DataWriteOptions`](obsidian.DataWriteOptions.md) | _(Optional)_ (Optional) |

[`DataAdapter`](obsidian.DataAdapter.md) › [`trashLocal`](obsidian.DataAdapter.trashLocal.md)

## DataAdapter.trashLocal() method

Move to local trash. Files will be moved into the `.trash` folder at the root of the vault.

```

[`DataAdapter`](obsidian.DataAdapter.md) › [`append`](obsidian.DataAdapter.append.md)

## DataAdapter.append() method

Add text to the end of a plaintext file.

```

|  <code>data</code> | <code>string</code> | the text to append. |

[`DataAdapter`](obsidian.DataAdapter.md) › [`list`](obsidian.DataAdapter.list.md)

## DataAdapter.list() method

Retrieve a list of all files and folders inside the given folder, non-recursive.

```

|  <code>normalizedPath</code> | <code>string</code> | path to folder, use [normalizePath()](obsidian.normalizePath.md) to normalize beforehand. |

[`DataAdapter`](obsidian.DataAdapter.md) › [`readBinary`](obsidian.DataAdapter.readBinary.md)

## DataAdapter.readBinary() method

```

[`DataAdapter`](obsidian.DataAdapter.md) › [`rename`](obsidian.DataAdapter.rename.md)

## DataAdapter.rename() method

Rename a file or folder.

```

|  <code>normalizedPath</code> | <code>string</code> | current path to file/folder, use [normalizePath()](obsidian.normalizePath.md) to normalize beforehand. |
|  <code>normalizedNewPath</code> | <code>string</code> | new path to file/folder, use [normalizePath()](obsidian.normalizePath.md) to normalize beforehand. |

[`DataAdapter`](obsidian.DataAdapter.md) › [`trashSystem`](obsidian.DataAdapter.trashSystem.md)

## DataAdapter.trashSystem() method

Try moving to system trash.

```

Returns true if succeeded. This can fail due to system trash being disabled.

[`DataAdapter`](obsidian.DataAdapter.md) › [`write`](obsidian.DataAdapter.write.md)

## DataAdapter.write() method

Write to a plaintext file. If the file exists its content will be overwritten, otherwise the file will be created.

```

|  <code>data</code> | <code>string</code> | new file content |

[`DataAdapter`](obsidian.DataAdapter.md) › [`exists`](obsidian.DataAdapter.exists.md)

## DataAdapter.exists() method

Check if something exists at the given path.

```

|  <code>sensitive</code> | <code>boolean</code> | _(Optional)_ Some file systems/operating systems are case-insensitive, set to true to force a case-sensitivity check. |

[`DataAdapter`](obsidian.DataAdapter.md) › [`rmdir`](obsidian.DataAdapter.rmdir.md)

## DataAdapter.rmdir() method

Remove a directory.

```

|  <code>recursive</code> | <code>boolean</code> | If <code>true</code>, delete folders under this folder recursively, if `<!-- -->false´ the folder needs to be empty. |

[`DataAdapter`](obsidian.DataAdapter.md) › [`copy`](obsidian.DataAdapter.copy.md)

## DataAdapter.copy() method

Create a copy of a file. This will fail if there is already a file at `normalizedNewPath`<!-- -->.

```

|  <code>normalizedNewPath</code> | <code>string</code> | path to file, use [normalizePath()](obsidian.normalizePath.md) to normalize beforehand. |

[`DataAdapter`](obsidian.DataAdapter.md) › [`getName`](obsidian.DataAdapter.getName.md)

## DataAdapter.getName() method

```

`string`

[`DataAdapter`](obsidian.DataAdapter.md) › [`remove`](obsidian.DataAdapter.remove.md)

## DataAdapter.remove() method

Delete a file.

```

[`DataAdapter`](obsidian.DataAdapter.md) › [`getResourcePath`](obsidian.DataAdapter.getResourcePath.md)

## DataAdapter.getResourcePath() method

Returns an URI for the browser engine to use, for example to embed an image.

```

`string`

[`Command`](obsidian.Command.md) › [`repeatable`](obsidian.Command.repeatable.md)

## Command.repeatable property

Whether holding the hotkey should repeatedly trigger this command. Defaults to false.

repeatable?: boolean;
```

[`Command`](obsidian.Command.md) › [`checkCallback`](obsidian.Command.checkCallback.md)

## Command.checkCallback property

Complex callback, overrides the simple callback. Used to "check" whether your command can be performed in the current circumstances. For example, if your command requires the active focused pane to be a MarkdownSourceView, then you should only return true if the condition is satisfied. Returning false or undefined causes the command to be hidden from the command palette.

checkCallback?: (checking: boolean) => boolean | void;
```

[`Command`](obsidian.Command.md) › [`name`](obsidian.Command.name.md)

## Command.name property

Human friendly name for searching.

```

[`Command`](obsidian.Command.md) › [`editorCheckCallback`](obsidian.Command.editorCheckCallback.md)

## Command.editorCheckCallback property

A command callback that is only triggered when the user is in an editor. Overrides `editorCallback`<!-- -->, `callback` and `checkCallback`

editorCheckCallback?: (checking: boolean, editor: Editor, ctx: MarkdownView | MarkdownFileInfo) => boolean | void;
```

[`Command`](obsidian.Command.md) › [`id`](obsidian.Command.id.md)

## Command.id property

Globally unique ID to identify this command.

```

[`Command`](obsidian.Command.md) › [`callback`](obsidian.Command.callback.md)

## Command.callback property

Simple callback, triggered globally.

callback?: () => any;
```

[`Command`](obsidian.Command.md) › [`icon`](obsidian.Command.icon.md)

## Command.icon property

Icon ID to be used in the toolbar.

icon?: IconName;
```

[`Command`](obsidian.Command.md) › [`mobileOnly`](obsidian.Command.mobileOnly.md)

## Command.mobileOnly property

mobileOnly?: boolean;
```

[`Command`](obsidian.Command.md) › [`editorCallback`](obsidian.Command.editorCallback.md)

## Command.editorCallback property

A command callback that is only triggered when the user is in an editor. Overrides `callback` and `checkCallback`

editorCallback?: (editor: Editor, ctx: MarkdownView | MarkdownFileInfo) => any;
```

[`Command`](obsidian.Command.md) › [`hotkeys`](obsidian.Command.hotkeys.md)

## Command.hotkeys property

Sets the default hotkey. It is recommended for plugins to avoid setting default hotkeys if possible, to avoid conflicting hotkeys with one that's set by the user, even though customized hotkeys have higher priority.

hotkeys?: Hotkey[];
```

[`HoverLinkSource`](obsidian.HoverLinkSource.md) › [`defaultMod`](obsidian.HoverLinkSource.defaultMod.md)

## HoverLinkSource.defaultMod property

Whether or not the `hover-link` event requires the 'Mod' key to be pressed to trigger.

defaultMod: boolean;
```

[`HoverLinkSource`](obsidian.HoverLinkSource.md) › [`display`](obsidian.HoverLinkSource.display.md)

## HoverLinkSource.display property

The string that will be displayed in the 'Page preview' plugin settings. It should match your plugin's display name.

display: string;
```

[`ValueComponent`](obsidian.ValueComponent.md) › [`getValue`](obsidian.ValueComponent.getValue.md)

## ValueComponent.getValue() method

abstract getValue(): T;
```

`T`

[`ValueComponent`](obsidian.ValueComponent.md) › [`setValue`](obsidian.ValueComponent.setValue.md)

## ValueComponent.setValue() method

abstract setValue(value: T): this;
```

`this`

[`ValueComponent`](obsidian.ValueComponent.md) › [`registerOptionListener`](obsidian.ValueComponent.registerOptionListener.md)

## ValueComponent.registerOptionListener() method

registerOptionListener(listeners: Record<string, (value?: T) => T>, key: string): this;
```

|  <code>listeners</code> | <code>Record</code><code>&lt;string, (value?: T) =&gt; T&gt;</code> |  |
|  <code>key</code> | <code>string</code> |  |

`this`

[`BlockCache`](obsidian.BlockCache.md) › [`id`](obsidian.BlockCache.id.md)

## BlockCache.id property

```

[`ViewState`](obsidian.ViewState.md) › [`group`](obsidian.ViewState.group.md)

## ViewState.group property

```

[`ViewState`](obsidian.ViewState.md) › [`active`](obsidian.ViewState.active.md)

## ViewState.active property

```

[`ViewState`](obsidian.ViewState.md) › [`state`](obsidian.ViewState.state.md)

## ViewState.state property

```

[`ViewState`](obsidian.ViewState.md) › [`type`](obsidian.ViewState.type.md)

## ViewState.type property

```

[`ViewState`](obsidian.ViewState.md) › [`pinned`](obsidian.ViewState.pinned.md)

## ViewState.pinned property

pinned?: boolean;
```

[`MarkdownEditView`](obsidian.MarkdownEditView.md) › [`app`](obsidian.MarkdownEditView.app.md)

## MarkdownEditView.app property

app: App;
```

[`MarkdownEditView`](obsidian.MarkdownEditView.md) › [`file`](obsidian.MarkdownEditView.file.md)

## MarkdownEditView.file property

```

[`MarkdownEditView`](obsidian.MarkdownEditView.md) › [`get`](obsidian.MarkdownEditView.get.md)

## MarkdownEditView.get() method

```

`string`

[`MarkdownEditView`](obsidian.MarkdownEditView.md) › [`set`](obsidian.MarkdownEditView.set.md)

## MarkdownEditView.set() method

```

`void`

[`MarkdownEditView`](obsidian.MarkdownEditView.md) › [`clear`](obsidian.MarkdownEditView.clear.md)

## MarkdownEditView.clear() method

```

`void`

[`MarkdownEditView`](obsidian.MarkdownEditView.md) › [`(constructor)`](obsidian.MarkdownEditView.(constructor).md)

## MarkdownEditView.(constructor)

Constructs a new instance of the `MarkdownEditView` class

```

[`MarkdownEditView`](obsidian.MarkdownEditView.md) › [`applyScroll`](obsidian.MarkdownEditView.applyScroll.md)

## MarkdownEditView.applyScroll() method

```

`void`

[`MarkdownEditView`](obsidian.MarkdownEditView.md) › [`getScroll`](obsidian.MarkdownEditView.getScroll.md)

## MarkdownEditView.getScroll() method

```

`number`

[`MarkdownEditView`](obsidian.MarkdownEditView.md) › [`hoverPopover`](obsidian.MarkdownEditView.hoverPopover.md)

## MarkdownEditView.hoverPopover property

```

[`MarkdownEditView`](obsidian.MarkdownEditView.md) › [`getSelection`](obsidian.MarkdownEditView.getSelection.md)

## MarkdownEditView.getSelection() method

```

`string`

[`Setting`](obsidian.Setting.md) › [`setTooltip`](obsidian.Setting.setTooltip.md)

## Setting.setTooltip() method

```

`this`

[`Setting`](obsidian.Setting.md) › [`addSlider`](obsidian.Setting.addSlider.md)

## Setting.addSlider() method

addSlider(cb: (component: SliderComponent) => any): this;
```

|  <code>cb</code> | <code>(component: </code>[`SliderComponent`](obsidian.SliderComponent.md)<code>) =&gt; any</code> |  |

`this`

[`Setting`](obsidian.Setting.md) › [`addButton`](obsidian.Setting.addButton.md)

## Setting.addButton() method

addButton(cb: (component: ButtonComponent) => any): this;
```

|  <code>cb</code> | <code>(component: </code>[`ButtonComponent`](obsidian.ButtonComponent.md)<code>) =&gt; any</code> |  |

`this`

[`Setting`](obsidian.Setting.md) › [`addColorPicker`](obsidian.Setting.addColorPicker.md)

## Setting.addColorPicker() method

addColorPicker(cb: (component: ColorComponent) => any): this;
```

|  <code>cb</code> | <code>(component: </code>[`ColorComponent`](obsidian.ColorComponent.md)<code>) =&gt; any</code> |  |

`this`

[`Setting`](obsidian.Setting.md) › [`setClass`](obsidian.Setting.setClass.md)

## Setting.setClass() method

```

`this`

[`Setting`](obsidian.Setting.md) › [`then`](obsidian.Setting.then.md)

## Setting.then() method

Facilitates chaining

then(cb: (setting: this) => any): this;
```

|  <code>cb</code> | <code>(setting: this) =&gt; any</code> |  |

`this`

[`Setting`](obsidian.Setting.md) › [`setDisabled`](obsidian.Setting.setDisabled.md)

## Setting.setDisabled() method

```

`this`

[`Setting`](obsidian.Setting.md) › [`settingEl`](obsidian.Setting.settingEl.md)

## Setting.settingEl property

settingEl: HTMLElement;
```

[`Setting`](obsidian.Setting.md) › [`addSearch`](obsidian.Setting.addSearch.md)

## Setting.addSearch() method

addSearch(cb: (component: SearchComponent) => any): this;
```

|  <code>cb</code> | <code>(component: </code>[`SearchComponent`](obsidian.SearchComponent.md)<code>) =&gt; any</code> |  |

`this`

[`Setting`](obsidian.Setting.md) › [`descEl`](obsidian.Setting.descEl.md)

## Setting.descEl property

descEl: HTMLElement;
```

[`Setting`](obsidian.Setting.md) › [`addMomentFormat`](obsidian.Setting.addMomentFormat.md)

## Setting.addMomentFormat() method

addMomentFormat(cb: (component: MomentFormatComponent) => any): this;
```

|  <code>cb</code> | <code>(component: </code>[`MomentFormatComponent`](obsidian.MomentFormatComponent.md)<code>) =&gt; any</code> |  |

`this`

[`Setting`](obsidian.Setting.md) › [`nameEl`](obsidian.Setting.nameEl.md)

## Setting.nameEl property

nameEl: HTMLElement;
```

[`Setting`](obsidian.Setting.md) › [`components`](obsidian.Setting.components.md)

## Setting.components property

components: BaseComponent[];
```

[`Setting`](obsidian.Setting.md) › [`addTextArea`](obsidian.Setting.addTextArea.md)

## Setting.addTextArea() method

addTextArea(cb: (component: TextAreaComponent) => any): this;
```

|  <code>cb</code> | <code>(component: </code>[`TextAreaComponent`](obsidian.TextAreaComponent.md)<code>) =&gt; any</code> |  |

`this`

[`Setting`](obsidian.Setting.md) › [`addExtraButton`](obsidian.Setting.addExtraButton.md)

## Setting.addExtraButton() method

addExtraButton(cb: (component: ExtraButtonComponent) => any): this;
```

|  <code>cb</code> | <code>(component: </code>[`ExtraButtonComponent`](obsidian.ExtraButtonComponent.md)<code>) =&gt; any</code> |  |

`this`

[`Setting`](obsidian.Setting.md) › [`addToggle`](obsidian.Setting.addToggle.md)

## Setting.addToggle() method

addToggle(cb: (component: ToggleComponent) => any): this;
```

|  <code>cb</code> | <code>(component: </code>[`ToggleComponent`](obsidian.ToggleComponent.md)<code>) =&gt; any</code> |  |

`this`

[`Setting`](obsidian.Setting.md) › [`setDesc`](obsidian.Setting.setDesc.md)

## Setting.setDesc() method

setDesc(desc: string | DocumentFragment): this;
```

|  <code>desc</code> | <code>string &#124; </code><code>DocumentFragment</code> |  |

`this`

[`Setting`](obsidian.Setting.md) › [`clear`](obsidian.Setting.clear.md)

## Setting.clear() method

clear(): this;
```

`this`

[`Setting`](obsidian.Setting.md) › [`addDropdown`](obsidian.Setting.addDropdown.md)

## Setting.addDropdown() method

addDropdown(cb: (component: DropdownComponent) => any): this;
```

|  <code>cb</code> | <code>(component: </code>[`DropdownComponent`](obsidian.DropdownComponent.md)<code>) =&gt; any</code> |  |

`this`

[`Setting`](obsidian.Setting.md) › [`(constructor)`](obsidian.Setting.(constructor).md)

## Setting.(constructor)

Constructs a new instance of the `Setting` class

```

[`Setting`](obsidian.Setting.md) › [`addText`](obsidian.Setting.addText.md)

## Setting.addText() method

addText(cb: (component: TextComponent) => any): this;
```

|  <code>cb</code> | <code>(component: </code>[`TextComponent`](obsidian.TextComponent.md)<code>) =&gt; any</code> |  |

`this`

[`Setting`](obsidian.Setting.md) › [`infoEl`](obsidian.Setting.infoEl.md)

## Setting.infoEl property

infoEl: HTMLElement;
```

[`Setting`](obsidian.Setting.md) › [`addProgressBar`](obsidian.Setting.addProgressBar.md)

## Setting.addProgressBar() method

addProgressBar(cb: (component: ProgressBarComponent) => any): this;
```

|  <code>cb</code> | <code>(component: </code>[`ProgressBarComponent`](obsidian.ProgressBarComponent.md)<code>) =&gt; any</code> |  |

`this`

[`Setting`](obsidian.Setting.md) › [`controlEl`](obsidian.Setting.controlEl.md)

## Setting.controlEl property

controlEl: HTMLElement;
```

[`Setting`](obsidian.Setting.md) › [`setName`](obsidian.Setting.setName.md)

## Setting.setName() method

setName(name: string | DocumentFragment): this;
```

|  <code>name</code> | <code>string &#124; </code><code>DocumentFragment</code> |  |

`this`

[`Setting`](obsidian.Setting.md) › [`setHeading`](obsidian.Setting.setHeading.md)

## Setting.setHeading() method

setHeading(): this;
```

`this`

[`Events`](obsidian.Events.md) › [`trigger`](obsidian.Events.trigger.md)

## Events.trigger() method

trigger(name: string, ...data: any[]): void;
```

|  <code>data</code> | <code>any[]</code> |  |

`void`

[`Events`](obsidian.Events.md) › [`off`](obsidian.Events.off.md)

## Events.off() method

off(name: string, callback: (...data: any) => any): void;
```

|  <code>callback</code> | <code>(...data: any) =&gt; any</code> |  |

`void`

[`Events`](obsidian.Events.md) › [`offref`](obsidian.Events.offref.md)

## Events.offref() method

offref(ref: EventRef): void;
```

|  <code>ref</code> | [`EventRef`](obsidian.EventRef.md) |  |

`void`

[`Events`](obsidian.Events.md) › [`tryTrigger`](obsidian.Events.tryTrigger.md)

## Events.tryTrigger() method

tryTrigger(evt: EventRef, args: any[]): void;
```

|  <code>evt</code> | [`EventRef`](obsidian.EventRef.md) |  |
|  <code>args</code> | <code>any[]</code> |  |

`void`

[`Events`](obsidian.Events.md) › [`on`](obsidian.Events.on.md)

## Events.on() method

on(name: string, callback: (...data: any) => any, ctx?: any): EventRef;
```

[`Debouncer`](obsidian.Debouncer.md) › [`cancel`](obsidian.Debouncer.cancel.md)

## Debouncer.cancel() method

cancel(): this;
```

`this`

[`Debouncer`](obsidian.Debouncer.md) › [`run`](obsidian.Debouncer.run.md)

## Debouncer.run() method

run(): V | void;
```

`V | void`

[`Modal`](obsidian.Modal.md) › [`open`](obsidian.Modal.open.md)

## Modal.open() method

open(): void;
```

`void`

[`Modal`](obsidian.Modal.md) › [`onOpen`](obsidian.Modal.onOpen.md)

## Modal.onOpen() method

onOpen(): void;
```

`void`

[`Modal`](obsidian.Modal.md) › [`contentEl`](obsidian.Modal.contentEl.md)

## Modal.contentEl property

```

[`Modal`](obsidian.Modal.md) › [`app`](obsidian.Modal.app.md)

## Modal.app property

app: App;
```

[`Modal`](obsidian.Modal.md) › [`modalEl`](obsidian.Modal.modalEl.md)

## Modal.modalEl property

modalEl: HTMLElement;
```

[`Modal`](obsidian.Modal.md) › [`scope`](obsidian.Modal.scope.md)

## Modal.scope property

```

[`Modal`](obsidian.Modal.md) › [`close`](obsidian.Modal.close.md)

## Modal.close() method

```

`void`

[`Modal`](obsidian.Modal.md) › [`onClose`](obsidian.Modal.onClose.md)

## Modal.onClose() method

onClose(): void;
```

`void`

[`Modal`](obsidian.Modal.md) › [`containerEl`](obsidian.Modal.containerEl.md)

## Modal.containerEl property

```

[`Modal`](obsidian.Modal.md) › [`(constructor)`](obsidian.Modal.(constructor).md)

## Modal.(constructor)

Constructs a new instance of the `Modal` class

```

[`Modal`](obsidian.Modal.md) › [`titleEl`](obsidian.Modal.titleEl.md)

## Modal.titleEl property

titleEl: HTMLElement;
```

[`Modal`](obsidian.Modal.md) › [`shouldRestoreSelection`](obsidian.Modal.shouldRestoreSelection.md)

## Modal.shouldRestoreSelection property

shouldRestoreSelection: boolean;
```

[`PopoverSuggest`](obsidian.PopoverSuggest.md) › [`open`](obsidian.PopoverSuggest.open.md)

## PopoverSuggest.open() method

```

`void`

[`PopoverSuggest`](obsidian.PopoverSuggest.md) › [`app`](obsidian.PopoverSuggest.app.md)

## PopoverSuggest.app property

app: App;
```

[`PopoverSuggest`](obsidian.PopoverSuggest.md) › [`scope`](obsidian.PopoverSuggest.scope.md)

## PopoverSuggest.scope property

```

[`PopoverSuggest`](obsidian.PopoverSuggest.md) › [`close`](obsidian.PopoverSuggest.close.md)

## PopoverSuggest.close() method

```

`void`

[`PopoverSuggest`](obsidian.PopoverSuggest.md) › [`(constructor)`](obsidian.PopoverSuggest.(constructor).md)

## PopoverSuggest.(constructor)

Constructs a new instance of the `PopoverSuggest` class

constructor(app: App, scope?: Scope);
```

|  <code>scope</code> | [`Scope`](obsidian.Scope.md) | _(Optional)_ |

[`PopoverSuggest`](obsidian.PopoverSuggest.md) › [`selectSuggestion`](obsidian.PopoverSuggest.selectSuggestion.md)

## PopoverSuggest.selectSuggestion() method

abstract selectSuggestion(value: T, evt: MouseEvent | KeyboardEvent): void;
```

`void`

[`PopoverSuggest`](obsidian.PopoverSuggest.md) › [`renderSuggestion`](obsidian.PopoverSuggest.renderSuggestion.md)

## PopoverSuggest.renderSuggestion() method

abstract renderSuggestion(value: T, el: HTMLElement): void;
```

`void`

[`ProgressBarComponent`](obsidian.ProgressBarComponent.md) › [`getValue`](obsidian.ProgressBarComponent.getValue.md)

## ProgressBarComponent.getValue() method

```

`number`

[`ProgressBarComponent`](obsidian.ProgressBarComponent.md) › [`setValue`](obsidian.ProgressBarComponent.setValue.md)

## ProgressBarComponent.setValue() method

```

|  <code>value</code> | <code>number</code> | The progress amount, a value between 0-100. |

`this`

[`ProgressBarComponent`](obsidian.ProgressBarComponent.md) › [`(constructor)`](obsidian.ProgressBarComponent.(constructor).md)

## ProgressBarComponent.(constructor)

Constructs a new instance of the `ProgressBarComponent` class

```

[`AbstractInputSuggest`](obsidian.AbstractInputSuggest.md) › [`getValue`](obsidian.AbstractInputSuggest.getValue.md)

## AbstractInputSuggest.getValue() method

Gets the value from the input element.

```

`string`

[`AbstractInputSuggest`](obsidian.AbstractInputSuggest.md) › [`onSelect`](obsidian.AbstractInputSuggest.onSelect.md)

## AbstractInputSuggest.onSelect() method

Registers a callback to handle when a suggestion is selected by the user.

onSelect(callback: (value: T, evt: MouseEvent | KeyboardEvent) => any): this;
```

|  <code>callback</code> | <code>(value: T, evt: </code><code>MouseEvent</code><code> &#124; </code><code>KeyboardEvent</code><code>) =&gt; any</code> |  |

`this`

[`AbstractInputSuggest`](obsidian.AbstractInputSuggest.md) › [`setValue`](obsidian.AbstractInputSuggest.setValue.md)

## AbstractInputSuggest.setValue() method

Sets the value into the input element.

setValue(value: string): void;
```

`void`

[`AbstractInputSuggest`](obsidian.AbstractInputSuggest.md) › [`(constructor)`](obsidian.AbstractInputSuggest.(constructor).md)

## AbstractInputSuggest.(constructor)

Accepts an `<input>` text box or a contenteditable div.

constructor(app: App, textInputEl: HTMLInputElement | HTMLDivElement);
```

|  <code>textInputEl</code> | <code>HTMLInputElement</code><code> &#124; </code><code>HTMLDivElement</code> |  |

[`AbstractInputSuggest`](obsidian.AbstractInputSuggest.md) › [`limit`](obsidian.AbstractInputSuggest.limit.md)

## AbstractInputSuggest.limit property

Limit to the number of elements rendered at once. Set to 0 to disable. Defaults to 100.

```

[`MarkdownRenderer`](obsidian.MarkdownRenderer.md) › [`app`](obsidian.MarkdownRenderer.app.md)

## MarkdownRenderer.app property

app: App;
```

[`MarkdownRenderer`](obsidian.MarkdownRenderer.md) › [`renderMarkdown`](obsidian.MarkdownRenderer.renderMarkdown.md)

## MarkdownRenderer.renderMarkdown() method

> 
> - use [MarkdownRenderer.render()](obsidian.MarkdownRenderer.render.md)
> 

Renders markdown string to an HTML element.

static renderMarkdown(markdown: string, el: HTMLElement, sourcePath: string, component: Component): Promise<void>;
```

|  <code>markdown</code> | <code>string</code> |  |
|  <code>component</code> | [`Component`](obsidian.Component.md) |  |

[`MarkdownRenderer`](obsidian.MarkdownRenderer.md) › [`file`](obsidian.MarkdownRenderer.file.md)

## MarkdownRenderer.file property

abstract get file(): TFile;
```

[`MarkdownRenderer`](obsidian.MarkdownRenderer.md) › [`render`](obsidian.MarkdownRenderer.render.md)

## MarkdownRenderer.render() method

static render(app: App, markdown: string, el: HTMLElement, sourcePath: string, component: Component): Promise<void>;
```

|  <code>app</code> | [`App`](obsidian.App.md) | A reference to the app object |
|  <code>markdown</code> | <code>string</code> | The markdown source code |
|  <code>el</code> | <code>HTMLElement</code> | The element to append to |
|  <code>sourcePath</code> | <code>string</code> | The normalized path of this markdown file, used to resolve relative internal links |
|  <code>component</code> | [`Component`](obsidian.Component.md) | A parent component to manage the lifecycle of the rendered child components. |

[`MarkdownRenderer`](obsidian.MarkdownRenderer.md) › [`hoverPopover`](obsidian.MarkdownRenderer.hoverPopover.md)

## MarkdownRenderer.hoverPopover property

```

[`AbstractTextComponent`](obsidian.AbstractTextComponent.md) › [`getValue`](obsidian.AbstractTextComponent.getValue.md)

## AbstractTextComponent.getValue() method

```

`string`

[`AbstractTextComponent`](obsidian.AbstractTextComponent.md) › [`onChanged`](obsidian.AbstractTextComponent.onChanged.md)

## AbstractTextComponent.onChanged() method

```

`void`

[`AbstractTextComponent`](obsidian.AbstractTextComponent.md) › [`setDisabled`](obsidian.AbstractTextComponent.setDisabled.md)

## AbstractTextComponent.setDisabled() method

```

`this`

[`AbstractTextComponent`](obsidian.AbstractTextComponent.md) › [`onChange`](obsidian.AbstractTextComponent.onChange.md)

## AbstractTextComponent.onChange() method

```

`this`

[`AbstractTextComponent`](obsidian.AbstractTextComponent.md) › [`setValue`](obsidian.AbstractTextComponent.setValue.md)

## AbstractTextComponent.setValue() method

```

`this`

[`AbstractTextComponent`](obsidian.AbstractTextComponent.md) › [`inputEl`](obsidian.AbstractTextComponent.inputEl.md)

## AbstractTextComponent.inputEl property

inputEl: T;
```

[`AbstractTextComponent`](obsidian.AbstractTextComponent.md) › [`(constructor)`](obsidian.AbstractTextComponent.(constructor).md)

## AbstractTextComponent.(constructor)

Constructs a new instance of the `AbstractTextComponent` class

constructor(inputEl: T);
```

|  <code>inputEl</code> | <code>T</code> |  |

[`AbstractTextComponent`](obsidian.AbstractTextComponent.md) › [`setPlaceholder`](obsidian.AbstractTextComponent.setPlaceholder.md)

## AbstractTextComponent.setPlaceholder() method

setPlaceholder(placeholder: string): this;
```

`this`

[`KeymapEventHandler`](obsidian.KeymapEventHandler.md) › [`scope`](obsidian.KeymapEventHandler.scope.md)

## KeymapEventHandler.scope property

```

[`KeymapInfo`](obsidian.KeymapInfo.md) › [`modifiers`](obsidian.KeymapInfo.modifiers.md)

## KeymapInfo.modifiers property

modifiers: string | null;
```

[`KeymapInfo`](obsidian.KeymapInfo.md) › [`key`](obsidian.KeymapInfo.key.md)

## KeymapInfo.key property

key: string | null;
```

[`RequestUrlParam`](obsidian.RequestUrlParam.md) › [`throw`](obsidian.RequestUrlParam.throw.md)

## RequestUrlParam.throw property

Whether to throw an error when the status code is 400+ Defaults to true

throw?: boolean;
```

[`RequestUrlParam`](obsidian.RequestUrlParam.md) › [`method`](obsidian.RequestUrlParam.method.md)

## RequestUrlParam.method property

method?: string;
```

[`RequestUrlParam`](obsidian.RequestUrlParam.md) › [`url`](obsidian.RequestUrlParam.url.md)

## RequestUrlParam.url property

url: string;
```

[`RequestUrlParam`](obsidian.RequestUrlParam.md) › [`headers`](obsidian.RequestUrlParam.headers.md)

## RequestUrlParam.headers property

headers?: Record<string, string>;
```

[`RequestUrlParam`](obsidian.RequestUrlParam.md) › [`body`](obsidian.RequestUrlParam.body.md)

## RequestUrlParam.body property

body?: string | ArrayBuffer;
```

[`RequestUrlParam`](obsidian.RequestUrlParam.md) › [`contentType`](obsidian.RequestUrlParam.contentType.md)

## RequestUrlParam.contentType property

contentType?: string;
```

[`Reference`](obsidian.Reference.md) › [`original`](obsidian.Reference.original.md)

## Reference.original property

original: string;
```

[`Reference`](obsidian.Reference.md) › [`link`](obsidian.Reference.link.md)

## Reference.link property

link: string;
```

[`Reference`](obsidian.Reference.md) › [`displayText`](obsidian.Reference.displayText.md)

## Reference.displayText property

if title is different than link text, in the case of \[\[page name\|display name\]\]

displayText?: string;
```

[`Editor`](obsidian.Editor.md) › [`getValue`](obsidian.Editor.getValue.md)

## Editor.getValue() method

abstract getValue(): string;
```

`string`

[`Editor`](obsidian.Editor.md) › [`refresh`](obsidian.Editor.refresh.md)

## Editor.refresh() method

abstract refresh(): void;
```

`void`

[`Editor`](obsidian.Editor.md) › [`scrollIntoView`](obsidian.Editor.scrollIntoView.md)

## Editor.scrollIntoView() method

abstract scrollIntoView(range: EditorRange, center?: boolean): void;
```

|  <code>range</code> | [`EditorRange`](obsidian.EditorRange.md) |  |
|  <code>center</code> | <code>boolean</code> | _(Optional)_ |

`void`

[`Editor`](obsidian.Editor.md) › [`redo`](obsidian.Editor.redo.md)

## Editor.redo() method

abstract redo(): void;
```

`void`

[`Editor`](obsidian.Editor.md) › [`getCursor`](obsidian.Editor.getCursor.md)

## Editor.getCursor() method

abstract getCursor(string?: 'from' | 'to' | 'head' | 'anchor'): EditorPosition;
```

|  <code>string</code> | <code>'from' &#124; 'to' &#124; 'head' &#124; 'anchor'</code> | _(Optional)_ |

[`Editor`](obsidian.Editor.md) › [`undo`](obsidian.Editor.undo.md)

## Editor.undo() method

abstract undo(): void;
```

`void`

[`Editor`](obsidian.Editor.md) › [`blur`](obsidian.Editor.blur.md)

## Editor.blur() method

abstract blur(): void;
```

`void`

[`Editor`](obsidian.Editor.md) › [`setSelection`](obsidian.Editor.setSelection.md)

## Editor.setSelection() method

abstract setSelection(anchor: EditorPosition, head?: EditorPosition): void;
```

|  <code>anchor</code> | [`EditorPosition`](obsidian.EditorPosition.md) |  |
|  <code>head</code> | [`EditorPosition`](obsidian.EditorPosition.md) | _(Optional)_ |

`void`

[`Editor`](obsidian.Editor.md) › [`posToOffset`](obsidian.Editor.posToOffset.md)

## Editor.posToOffset() method

abstract posToOffset(pos: EditorPosition): number;
```

|  <code>pos</code> | [`EditorPosition`](obsidian.EditorPosition.md) |  |

`number`

[`Editor`](obsidian.Editor.md) › [`lineCount`](obsidian.Editor.lineCount.md)

## Editor.lineCount() method

Gets the number of lines in the document

abstract lineCount(): number;
```

`number`

[`Editor`](obsidian.Editor.md) › [`setLine`](obsidian.Editor.setLine.md)

## Editor.setLine() method

setLine(n: number, text: string): void;
```

|  <code>n</code> | <code>number</code> |  |

`void`

[`Editor`](obsidian.Editor.md) › [`setValue`](obsidian.Editor.setValue.md)

## Editor.setValue() method

abstract setValue(content: string): void;
```

|  <code>content</code> | <code>string</code> |  |

`void`

[`Editor`](obsidian.Editor.md) › [`focus`](obsidian.Editor.focus.md)

## Editor.focus() method

abstract focus(): void;
```

`void`

[`Editor`](obsidian.Editor.md) › [`replaceRange`](obsidian.Editor.replaceRange.md)

## Editor.replaceRange() method

abstract replaceRange(replacement: string, from: EditorPosition, to?: EditorPosition, origin?: string): void;
```

|  <code>replacement</code> | <code>string</code> |  |
|  <code>from</code> | [`EditorPosition`](obsidian.EditorPosition.md) |  |
|  <code>to</code> | [`EditorPosition`](obsidian.EditorPosition.md) | _(Optional)_ |
|  <code>origin</code> | <code>string</code> | _(Optional)_ |

`void`

[`Editor`](obsidian.Editor.md) › [`getLine`](obsidian.Editor.getLine.md)

## Editor.getLine() method

Get the text at line (0-indexed)

abstract getLine(line: number): string;
```

|  <code>line</code> | <code>number</code> |  |

`string`

[`Editor`](obsidian.Editor.md) › [`offsetToPos`](obsidian.Editor.offsetToPos.md)

## Editor.offsetToPos() method

abstract offsetToPos(offset: number): EditorPosition;
```

|  <code>offset</code> | <code>number</code> |  |

[`Editor`](obsidian.Editor.md) › [`setCursor`](obsidian.Editor.setCursor.md)

## Editor.setCursor() method

setCursor(pos: EditorPosition | number, ch?: number): void;
```

|  <code>pos</code> | [`EditorPosition`](obsidian.EditorPosition.md)<code> &#124; number</code> |  |
|  <code>ch</code> | <code>number</code> | _(Optional)_ |

`void`

[`Editor`](obsidian.Editor.md) › [`processLines`](obsidian.Editor.processLines.md)

## Editor.processLines() method

processLines<T>(read: (line: number, lineText: string) => T | null, write: (line: number, lineText: string, value: T | null) => EditorChange | void, ignoreEmpty?: boolean): void;
```

|  <code>read</code> | <code>(line: number, lineText: string) =&gt; T &#124; null</code> |  |
|  <code>write</code> | <code>(line: number, lineText: string, value: T &#124; null) =&gt; </code>[`EditorChange`](obsidian.EditorChange.md)<code> &#124; void</code> |  |
|  <code>ignoreEmpty</code> | <code>boolean</code> | _(Optional)_ |

`void`

[`Editor`](obsidian.Editor.md) › [`getRange`](obsidian.Editor.getRange.md)

## Editor.getRange() method

abstract getRange(from: EditorPosition, to: EditorPosition): string;
```

|  <code>to</code> | [`EditorPosition`](obsidian.EditorPosition.md) |  |

`string`

[`Editor`](obsidian.Editor.md) › [`somethingSelected`](obsidian.Editor.somethingSelected.md)

## Editor.somethingSelected() method

somethingSelected(): boolean;
```

`boolean`

[`Editor`](obsidian.Editor.md) › [`setSelections`](obsidian.Editor.setSelections.md)

## Editor.setSelections() method

abstract setSelections(ranges: EditorSelectionOrCaret[], main?: number): void;
```

|  <code>ranges</code> | [`EditorSelectionOrCaret`](obsidian.EditorSelectionOrCaret.md)<code>[]</code> |  |
|  <code>main</code> | <code>number</code> | _(Optional)_ |

`void`

[`Editor`](obsidian.Editor.md) › [`listSelections`](obsidian.Editor.listSelections.md)

## Editor.listSelections() method

abstract listSelections(): EditorSelection[];
```

[`EditorSelection`](obsidian.EditorSelection.md)`[]`

[`Editor`](obsidian.Editor.md) › [`getDoc`](obsidian.Editor.getDoc.md)

## Editor.getDoc() method

getDoc(): this;
```

`this`

[`Editor`](obsidian.Editor.md) › [`lastLine`](obsidian.Editor.lastLine.md)

## Editor.lastLine() method

abstract lastLine(): number;
```

`number`

[`Editor`](obsidian.Editor.md) › [`wordAt`](obsidian.Editor.wordAt.md)

## Editor.wordAt() method

abstract wordAt(pos: EditorPosition): EditorRange | null;
```

[`EditorRange`](obsidian.EditorRange.md)` | null`

[`Editor`](obsidian.Editor.md) › [`getScrollInfo`](obsidian.Editor.getScrollInfo.md)

## Editor.getScrollInfo() method

abstract getScrollInfo(): {
        top: number;
        left: number;
    };
```

`{         top: number;         left: number;     }`

[`Editor`](obsidian.Editor.md) › [`getSelection`](obsidian.Editor.getSelection.md)

## Editor.getSelection() method

abstract getSelection(): string;
```

`string`

[`Editor`](obsidian.Editor.md) › [`transaction`](obsidian.Editor.transaction.md)

## Editor.transaction() method

abstract transaction(tx: EditorTransaction, origin?: string): void;
```

|  <code>tx</code> | [`EditorTransaction`](obsidian.EditorTransaction.md) |  |

`void`

[`Editor`](obsidian.Editor.md) › [`exec`](obsidian.Editor.exec.md)

## Editor.exec() method

abstract exec(command: EditorCommandName): void;
```

|  <code>command</code> | [`EditorCommandName`](obsidian.EditorCommandName.md) |  |

`void`

[`Editor`](obsidian.Editor.md) › [`hasFocus`](obsidian.Editor.hasFocus.md)

## Editor.hasFocus() method

abstract hasFocus(): boolean;
```

`boolean`

[`Editor`](obsidian.Editor.md) › [`replaceSelection`](obsidian.Editor.replaceSelection.md)

## Editor.replaceSelection() method

abstract replaceSelection(replacement: string, origin?: string): void;
```

`void`

[`Editor`](obsidian.Editor.md) › [`scrollTo`](obsidian.Editor.scrollTo.md)

## Editor.scrollTo() method

abstract scrollTo(x?: number | null, y?: number | null): void;
```

|  <code>x</code> | <code>number &#124; null</code> | _(Optional)_ |
|  <code>y</code> | <code>number &#124; null</code> | _(Optional)_ |

`void`

[`BlockSubpathResult`](obsidian.BlockSubpathResult.md) › [`block`](obsidian.BlockSubpathResult.block.md)

## BlockSubpathResult.block property

block: BlockCache;
```

[`BlockSubpathResult`](obsidian.BlockSubpathResult.md) › [`list`](obsidian.BlockSubpathResult.list.md)

## BlockSubpathResult.list property

list?: ListItemCache;
```

[`BlockSubpathResult`](obsidian.BlockSubpathResult.md) › [`type`](obsidian.BlockSubpathResult.type.md)

## BlockSubpathResult.type property

type: 'block';
```

[`WorkspaceMobileDrawer`](obsidian.WorkspaceMobileDrawer.md) › [`expand`](obsidian.WorkspaceMobileDrawer.expand.md)

## WorkspaceMobileDrawer.expand() method

```

`void`

[`WorkspaceMobileDrawer`](obsidian.WorkspaceMobileDrawer.md) › [`collapsed`](obsidian.WorkspaceMobileDrawer.collapsed.md)

## WorkspaceMobileDrawer.collapsed property

```

[`WorkspaceMobileDrawer`](obsidian.WorkspaceMobileDrawer.md) › [`toggle`](obsidian.WorkspaceMobileDrawer.toggle.md)

## WorkspaceMobileDrawer.toggle() method

```

`void`

[`WorkspaceMobileDrawer`](obsidian.WorkspaceMobileDrawer.md) › [`collapse`](obsidian.WorkspaceMobileDrawer.collapse.md)

## WorkspaceMobileDrawer.collapse() method

```

`void`

[`Vault`](obsidian.Vault.md) › [`process`](obsidian.Vault.process.md)

## Vault.process() method

Atomically read, modify, and save the contents of a note.

process(file: TFile, fn: (data: string) => string, options?: DataWriteOptions): Promise<string>;
```

|  <code>file</code> | [`TFile`](obsidian.TFile.md) | the file to be read and modified. |
|  <code>fn</code> | <code>(data: string) =&gt; string</code> | a callback function which returns the new content of the note synchronously. |

string - the text value of the note that was written.

[`Vault`](obsidian.Vault.md) › [`modify`](obsidian.Vault.modify.md)

## Vault.modify() method

Modify the contents of a plaintext file.

modify(file: TFile, data: string, options?: DataWriteOptions): Promise<void>;
```

|  <code>file</code> | [`TFile`](obsidian.TFile.md) | The file |
|  <code>data</code> | <code>string</code> | The new file content |

[`Vault`](obsidian.Vault.md) › [`trash`](obsidian.Vault.trash.md)

## Vault.trash() method

Tries to move to system trash. If that isn't successful/allowed, use local trash

trash(file: TAbstractFile, system: boolean): Promise<void>;
```

|  <code>file</code> | [`TAbstractFile`](obsidian.TAbstractFile.md) | The file or folder to be deleted |
|  <code>system</code> | <code>boolean</code> | Set to <code>false</code> to use local trash by default. |

[`Vault`](obsidian.Vault.md) › [`getMarkdownFiles`](obsidian.Vault.getMarkdownFiles.md)

## Vault.getMarkdownFiles() method

Get all markdown files in the vault.

getMarkdownFiles(): TFile[];
```

[`TFile`](obsidian.TFile.md)`[]`

[`Vault`](obsidian.Vault.md) › [`modifyBinary`](obsidian.Vault.modifyBinary.md)

## Vault.modifyBinary() method

Modify the contents of a binary file.

modifyBinary(file: TFile, data: ArrayBuffer, options?: DataWriteOptions): Promise<void>;
```

|  <code>data</code> | <code>ArrayBuffer</code> | The new file content |

[`Vault`](obsidian.Vault.md) › [`recurseChildren`](obsidian.Vault.recurseChildren.md)

## Vault.recurseChildren() method

static recurseChildren(root: TFolder, cb: (file: TAbstractFile) => any): void;
```

|  <code>root</code> | [`TFolder`](obsidian.TFolder.md) |  |
|  <code>cb</code> | <code>(file: </code>[`TAbstractFile`](obsidian.TAbstractFile.md)<code>) =&gt; any</code> |  |

`void`

[`Vault`](obsidian.Vault.md) › [`on`](obsidian.Vault.on_1.md)

## Vault.on() method

Called when a file is modified.

on(name: 'modify', callback: (file: TAbstractFile) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'modify'</code> |  |
|  <code>callback</code> | <code>(file: </code>[`TAbstractFile`](obsidian.TAbstractFile.md)<code>) =&gt; any</code> |  |

[`Vault`](obsidian.Vault.md) › [`read`](obsidian.Vault.read.md)

## Vault.read() method

Read a plaintext file that is stored inside the vault, directly from disk. Use this if you intend to modify the file content afterwards. Use [Vault.cachedRead()](obsidian.Vault.cachedRead.md) otherwise for better performance.

read(file: TFile): Promise<string>;
```

[`Vault`](obsidian.Vault.md) › [`getAbstractFileByPath`](obsidian.Vault.getAbstractFileByPath.md)

## Vault.getAbstractFileByPath() method

Get a file or folder inside the vault. If you need a file, you should test the returned object with `instanceof TFile`<!-- -->. Otherwise, if you need a folder, you should test it with `instanceof TFolder`<!-- -->.

getAbstractFileByPath(path: string): TAbstractFile | null;
```

|  <code>path</code> | <code>string</code> | vault absolute path to the folder or file, with extension, case sensitive. |

[`TAbstractFile`](obsidian.TAbstractFile.md)` | null`

the abstract file, if it's found.

[`Vault`](obsidian.Vault.md) › [`append`](obsidian.Vault.append.md)

## Vault.append() method

Add text to the end of a plaintext file inside the vault.

append(file: TFile, data: string, options?: DataWriteOptions): Promise<void>;
```

|  <code>data</code> | <code>string</code> | the text to add |

[`Vault`](obsidian.Vault.md) › [`readBinary`](obsidian.Vault.readBinary.md)

## Vault.readBinary() method

Read the content of a binary file stored inside the vault.

readBinary(file: TFile): Promise<ArrayBuffer>;
```

[`Vault`](obsidian.Vault.md) › [`configDir`](obsidian.Vault.configDir.md)

## Vault.configDir property

Gets the path to the config folder. This value is typically `.obsidian` but it could be different.

configDir: string;
```

[`Vault`](obsidian.Vault.md) › [`rename`](obsidian.Vault.rename.md)

## Vault.rename() method

Rename or move a file.

rename(file: TAbstractFile, newPath: string): Promise<void>;
```

|  <code>file</code> | [`TAbstractFile`](obsidian.TAbstractFile.md) | the file to rename/move |
|  <code>newPath</code> | <code>string</code> | vault absolute path to move file to. |

[`Vault`](obsidian.Vault.md) › [`on`](obsidian.Vault.on_3.md)

Called when a file is renamed.

on(name: 'rename', callback: (file: TAbstractFile, oldPath: string) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'rename'</code> |  |
|  <code>callback</code> | <code>(file: </code>[`TAbstractFile`](obsidian.TAbstractFile.md)<code>, oldPath: string) =&gt; any</code> |  |

[`Vault`](obsidian.Vault.md) › [`create`](obsidian.Vault.create.md)

## Vault.create() method

Create a new plaintext file inside the vault.

create(path: string, data: string, options?: DataWriteOptions): Promise<TFile>;
```

|  <code>path</code> | <code>string</code> | Vault absolute path for the new file, with extension. |
|  <code>data</code> | <code>string</code> | text content for the new file. |

`Promise``<`[`TFile`](obsidian.TFile.md)`>`

[`Vault`](obsidian.Vault.md) › [`on`](obsidian.Vault.on_2.md)

Called when a file is deleted.

on(name: 'delete', callback: (file: TAbstractFile) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'delete'</code> |  |

[`Vault`](obsidian.Vault.md) › [`delete`](obsidian.Vault.delete.md)

## Vault.delete() method

Deletes the file completely.

delete(file: TAbstractFile, force?: boolean): Promise<void>;
```

|  <code>force</code> | <code>boolean</code> | _(Optional)_ Should attempt to delete folder even if it has hidden children |

[`Vault`](obsidian.Vault.md) › [`getAllLoadedFiles`](obsidian.Vault.getAllLoadedFiles.md)

## Vault.getAllLoadedFiles() method

Get all files and folders in the vault.

getAllLoadedFiles(): TAbstractFile[];
```

[`TAbstractFile`](obsidian.TAbstractFile.md)`[]`

[`Vault`](obsidian.Vault.md) › [`createBinary`](obsidian.Vault.createBinary.md)

## Vault.createBinary() method

Create a new binary file inside the vault.

createBinary(path: string, data: ArrayBuffer, options?: DataWriteOptions): Promise<TFile>;
```

|  <code>data</code> | <code>ArrayBuffer</code> | content for the new file. |

Error if file already exists

[`Vault`](obsidian.Vault.md) › [`copy`](obsidian.Vault.copy.md)

## Vault.copy() method

Create a copy of the selected file.

copy(file: TFile, newPath: string): Promise<TFile>;
```

|  <code>newPath</code> | <code>string</code> | Vault absolute path for the new copy. |

[`Vault`](obsidian.Vault.md) › [`getFiles`](obsidian.Vault.getFiles.md)

## Vault.getFiles() method

Get all files in the vault.

getFiles(): TFile[];
```

[`Vault`](obsidian.Vault.md) › [`getName`](obsidian.Vault.getName.md)

## Vault.getName() method

Gets the name of the vault.

```

`string`

[`Vault`](obsidian.Vault.md) › [`on`](obsidian.Vault.on.md)

Called when a file is created. This is also called when the vault is first loaded for each existing file If you do not wish to receive create events on vault load, register your event handler inside [Workspace.onLayoutReady()](obsidian.Workspace.onLayoutReady.md)<!-- -->.

on(name: 'create', callback: (file: TAbstractFile) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'create'</code> |  |

[`Vault`](obsidian.Vault.md) › [`adapter`](obsidian.Vault.adapter.md)

## Vault.adapter property

adapter: DataAdapter;
```

[`Vault`](obsidian.Vault.md) › [`createFolder`](obsidian.Vault.createFolder.md)

## Vault.createFolder() method

Create a new folder inside the vault.

createFolder(path: string): Promise<TFolder>;
```

|  <code>path</code> | <code>string</code> | Vault absolute path for the new folder. |

`Promise``<`[`TFolder`](obsidian.TFolder.md)`>`

Error if folder already exists

[`Vault`](obsidian.Vault.md) › [`cachedRead`](obsidian.Vault.cachedRead.md)

## Vault.cachedRead() method

Read the content of a plaintext file stored inside the vault Use this if you only want to display the content to the user. If you want to modify the file content afterward use [Vault.read()](obsidian.Vault.read.md)

cachedRead(file: TFile): Promise<string>;
```

[`Vault`](obsidian.Vault.md) › [`getRoot`](obsidian.Vault.getRoot.md)

## Vault.getRoot() method

Get the root folder of the current vault.

getRoot(): TFolder;
```

[`Vault`](obsidian.Vault.md) › [`getResourcePath`](obsidian.Vault.getResourcePath.md)

## Vault.getResourcePath() method

getResourcePath(file: TFile): string;
```

`string`

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) › [`open`](obsidian.WorkspaceLeaf.open.md)

## WorkspaceLeaf.open() method

open(view: View): Promise<View>;
```

|  <code>view</code> | [`View`](obsidian.View.md) |  |

`Promise``<`[`View`](obsidian.View.md)`>`

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) › [`setViewState`](obsidian.WorkspaceLeaf.setViewState.md)

## WorkspaceLeaf.setViewState() method

setViewState(viewState: ViewState, eState?: any): Promise<void>;
```

|  <code>viewState</code> | [`ViewState`](obsidian.ViewState.md) |  |
|  <code>eState</code> | <code>any</code> | _(Optional)_ |

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) › [`openFile`](obsidian.WorkspaceLeaf.openFile.md)

## WorkspaceLeaf.openFile() method

By default, `openFile` will also make the leaf active. Pass in `{ active: false }` to override.

openFile(file: TFile, openState?: OpenViewState): Promise<void>;
```

|  <code>openState</code> | [`OpenViewState`](obsidian.OpenViewState.md) | _(Optional)_ |

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) › [`getIcon`](obsidian.WorkspaceLeaf.getIcon.md)

## WorkspaceLeaf.getIcon() method

```

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) › [`view`](obsidian.WorkspaceLeaf.view.md)

## WorkspaceLeaf.view property

view: View;
```

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) › [`setGroup`](obsidian.WorkspaceLeaf.setGroup.md)

## WorkspaceLeaf.setGroup() method

setGroup(group: string): void;
```

`void`

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) › [`on`](obsidian.WorkspaceLeaf.on_1.md)

## WorkspaceLeaf.on() method

on(name: 'group-change', callback: (group: string) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'group-change'</code> |  |
|  <code>callback</code> | <code>(group: string) =&gt; any</code> |  |

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) › [`setGroupMember`](obsidian.WorkspaceLeaf.setGroupMember.md)

## WorkspaceLeaf.setGroupMember() method

setGroupMember(other: WorkspaceLeaf): void;
```

|  <code>other</code> | [`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) |  |

`void`

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) › [`onResize`](obsidian.WorkspaceLeaf.onResize.md)

## WorkspaceLeaf.onResize() method

```

`void`

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) › [`getDisplayText`](obsidian.WorkspaceLeaf.getDisplayText.md)

## WorkspaceLeaf.getDisplayText() method

```

`string`

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) › [`setEphemeralState`](obsidian.WorkspaceLeaf.setEphemeralState.md)

## WorkspaceLeaf.setEphemeralState() method

```

`void`

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) › [`setPinned`](obsidian.WorkspaceLeaf.setPinned.md)

## WorkspaceLeaf.setPinned() method

setPinned(pinned: boolean): void;
```

|  <code>pinned</code> | <code>boolean</code> |  |

`void`

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) › [`detach`](obsidian.WorkspaceLeaf.detach.md)

## WorkspaceLeaf.detach() method

detach(): void;
```

`void`

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) › [`togglePinned`](obsidian.WorkspaceLeaf.togglePinned.md)

## WorkspaceLeaf.togglePinned() method

togglePinned(): void;
```

`void`

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) › [`on`](obsidian.WorkspaceLeaf.on.md)

on(name: 'pinned-change', callback: (pinned: boolean) => any, ctx?: any): EventRef;
```

|  <code>name</code> | <code>'pinned-change'</code> |  |
|  <code>callback</code> | <code>(pinned: boolean) =&gt; any</code> |  |

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) › [`getEphemeralState`](obsidian.WorkspaceLeaf.getEphemeralState.md)

## WorkspaceLeaf.getEphemeralState() method

```

`any`

[`WorkspaceLeaf`](obsidian.WorkspaceLeaf.md) › [`getViewState`](obsidian.WorkspaceLeaf.getViewState.md)

## WorkspaceLeaf.getViewState() method

getViewState(): ViewState;
```

[`MarkdownPostProcessor`](obsidian.MarkdownPostProcessor.md) › [`sortOrder`](obsidian.MarkdownPostProcessor.sortOrder.md)

## MarkdownPostProcessor.sortOrder property

An optional integer sort order. Defaults to 0. Lower number runs before higher numbers.

sortOrder?: number;
```

[`MarkdownView`](obsidian.MarkdownView.md) › [`showSearch`](obsidian.MarkdownView.showSearch.md)

## MarkdownView.showSearch() method

showSearch(replace?: boolean): void;
```

|  <code>replace</code> | <code>boolean</code> | _(Optional)_ |

`void`

[`MarkdownView`](obsidian.MarkdownView.md) › [`setViewData`](obsidian.MarkdownView.setViewData.md)

## MarkdownView.setViewData() method

setViewData(data: string, clear: boolean): void;
```

`void`

[`MarkdownView`](obsidian.MarkdownView.md) › [`currentMode`](obsidian.MarkdownView.currentMode.md)

## MarkdownView.currentMode property

currentMode: MarkdownSubView;
```

[`MarkdownView`](obsidian.MarkdownView.md) › [`getViewData`](obsidian.MarkdownView.getViewData.md)

## MarkdownView.getViewData() method

getViewData(): string;
```

`string`

[`MarkdownView`](obsidian.MarkdownView.md) › [`editor`](obsidian.MarkdownView.editor.md)

## MarkdownView.editor property

```

[`MarkdownView`](obsidian.MarkdownView.md) › [`previewMode`](obsidian.MarkdownView.previewMode.md)

## MarkdownView.previewMode property

previewMode: MarkdownPreviewView;
```

[`MarkdownView`](obsidian.MarkdownView.md) › [`clear`](obsidian.MarkdownView.clear.md)

## MarkdownView.clear() method

```

`void`

[`MarkdownView`](obsidian.MarkdownView.md) › [`(constructor)`](obsidian.MarkdownView.(constructor).md)

## MarkdownView.(constructor)

Constructs a new instance of the `MarkdownView` class

```

[`MarkdownView`](obsidian.MarkdownView.md) › [`getMode`](obsidian.MarkdownView.getMode.md)

## MarkdownView.getMode() method

getMode(): MarkdownViewModeType;
```

[`MarkdownView`](obsidian.MarkdownView.md) › [`hoverPopover`](obsidian.MarkdownView.hoverPopover.md)

## MarkdownView.hoverPopover property

hoverPopover: HoverPopover | null;
```

[`MarkdownView`](obsidian.MarkdownView.md) › [`getViewType`](obsidian.MarkdownView.getViewType.md)

## MarkdownView.getViewType() method

getViewType(): string;
```

`string`

[`BaseComponent`](obsidian.BaseComponent.md) › [`then`](obsidian.BaseComponent.then.md)

## BaseComponent.then() method

then(cb: (component: this) => any): this;
```

|  <code>cb</code> | <code>(component: this) =&gt; any</code> |  |

`this`

[`BaseComponent`](obsidian.BaseComponent.md) › [`setDisabled`](obsidian.BaseComponent.setDisabled.md)

## BaseComponent.setDisabled() method

```

`this`

[`BaseComponent`](obsidian.BaseComponent.md) › [`disabled`](obsidian.BaseComponent.disabled.md)

## BaseComponent.disabled property

disabled: boolean;
```

[`HoverParent`](obsidian.HoverParent.md) › [`hoverPopover`](obsidian.HoverParent.hoverPopover.md)

## HoverParent.hoverPopover property

```

[`TextAreaComponent`](obsidian.TextAreaComponent.md) › [`(constructor)`](obsidian.TextAreaComponent.(constructor).md)

## TextAreaComponent.(constructor)

Constructs a new instance of the `TextAreaComponent` class

```

This page lists CSS variables used by the [Search](https://help.obsidian.md/Plugins/Search) plugin.

| Variable                      | Description                        |
| ----------------------------- | ---------------------------------- |
| `--search-clear-button-color` | Clear search button color          |
| `--search-clear-button-size`  | Clear search button size           |
| `--search-icon-color`         | Search magnifying glass icon color |
| `--search-icon-size`          | Search icon size                   |
| `--search-result-background`  | Search result background color     |

This page lists CSS variables used by the [File explorer](https://help.obsidian.md/Plugins/File+explorer) plugin.

| Variable                   | Description |
| -------------------------- | ----------- |
| `--vault-name-font-size`   | Font size   |
| `--vault-name-font-weight` | Font weight |
| `--vault-name-color`       | Text color  |

docs/obsidian-developer/Reference/CSS variables/Plugins/File explorer.md

This page lists CSS variables used by the [Canvas](https://help.obsidian.md/Plugins/Canvas) plugin.

| Variable                    | Description                  |
| --------------------------- | ---------------------------- |
| `--canvas-background`       | Canvas background color      |
| `--canvas-card-label-color` | Canvas card label text color |
| `--canvas-dot-pattern`      | Canvas dot pattern color     |
| `--canvas-color-1`          | Canvas card color 1          |
| `--canvas-color-2`          | Canvas card color 2          |
| `--canvas-color-3`          | Canvas card color 3          |
| `--canvas-color-4`          | Canvas card color 4          |
| `--canvas-color-5`          | Canvas card color 5          |
| `--canvas-color-6`          | Canvas card color 6          |

This page lists CSS variables used by the [Graph view](https://help.obsidian.md/Plugins/Graph+view) plugin.

| Variable                  | Description           |
| ------------------------- | --------------------- |
| `--graph-controls-width`  | Graph controls width  |
| `--graph-text`            | Node text color       |
| `--graph-line`            | Line color            |
| `--graph-node`            | Resolved node color   |
| `--graph-node-unresolved` | Unresolved node color |
| `--graph-node-focused`    | Focused node color    |
| `--graph-node-tag`        | Tag node color        |
| `--graph-node-attachment` | Attachment node color |

The Obsidian color palette defines a range of colors used in the app.

## Base colors

The base colors is a neutral color palette ranging from light to dark. These values should typically only be defined by themes.

| Variable           | Default value (light mode) | Default value (dark mode) |
| ------------------ | -------------------------- | ------------------------- |
| `--color-base-00`  | `#ffffff`                  | `#1e1e1e`                 |
| `--color-base-05`  | `#fcfcfc`                  | `#212121`                 |
| `--color-base-10`  | `#fafafa`                  | `#242424`                 |
| `--color-base-20`  | `#f6f6f6`                  | `#262626`                 |
| `--color-base-25`  | `#e3e3e3`                  | `#2a2a2a`                 |
| `--color-base-30`  | `#e0e0e0`                  | `#363636`                 |
| `--color-base-35`  | `#d4d4d4`                  | `#3f3f3f`                 |
| `--color-base-40`  | `#bdbdbd`                  | `#555555`                 |
| `--color-base-50`  | `#ababab`                  | `#666666`                 |
| `--color-base-60`  | `#707070`                  | `#999999`                 |
| `--color-base-70`  | `#5a5a5a`                  | `#bababa`                 |
| `--color-base-100` | `#222222`                  | `#dadada`                 |

## Accent color

The accent color is used to draw attention to interactive elements, such as links and primary buttons, and can be overridden by the user under **Settings → Appearance** in the Obsidian app.

| Variable     | Default value | Description       |
| ------------ | ------------- | ----------------- |
| `--accent-h` | `254`           | Accent hue        |
| `--accent-s` | `80%`           | Accent saturation |
| `--accent-l` | `68%`           | Accent lightness  |

> [!tip]
> You can use [CSS calculations](https://developer.mozilla.org/en-US/docs/Web/CSS/calc) to create a variety of shades based on the accent color.

## Extended colors

Extended color variables define the broader range of colors used for status messages (errors, warnings, success), callouts, syntax highlighting, graph nodes, and Canvas elements.

Each extended color has an additional RGB variable with a `-rgb` suffix that you can use to create colors with opacity, using the `rgba` function.

For example, the following snippet uses the default variable to set the text color, and the RGB variable to set a background color to red with 20% opacity.

```css
color: var(--color-red);
background-color: rgba(var(--color-red-rgb), 0.2);

```

| Variable             | Default value (light mode) | Default value (dark mode) |
| -------------------- | -------------------------- | ------------------------- |
| `--color-red`        | `#e93147`                  | `#fb464c`                 |
| `--color-orange`     | `#ec7500`                  | `#e9973f`                 |
| `--color-yellow`     | `#e0ac00`                  | `#e0de71`                 |
| `--color-green`      | `#08b94e`                  | `#44cf6e`                 |
| `--color-cyan`       | `#00bfbc`                  | `#53dfdd`                 |
| `--color-blue`       | `#086ddd`                  | `#027aff`                 |
| `--color-purple`     | `#7852ee`                  | `#a882ff`                 |
| `--color-pink`       | `#d53984`                  | `#fa99cd`                 |
| `--color-red-rgb`    | `233, 49, 71`              | `251, 70, 76`             |
| `--color-orange-rgb` | `236, 117, 0`              | `233, 151, 63`            |
| `--color-yellow-rgb` | `224, 172, 0`              | `224, 222, 113`           |
| `--color-green-rgb`  | `8, 185, 78`               | `68, 207, 110`            |
| `--color-cyan-rgb`   | `0, 191, 188`              | `83, 223, 221`            |
| `--color-blue-rgb`   | `8, 109, 221`              | `2, 122, 255`             |
| `--color-purple-rgb` | `120, 82, 238`             | `168, 130, 255`           |
| `--color-pink-rgb`   | `213, 57, 132`             | `250, 153, 205`           |

## Black and white

Black and white colors let you create masks with opacity.

| Variable         | Default value (light mode) | Default value (dark mode) |
| ---------------- | -------------------------- | ------------------------- |
| `--mono-rgb-0`   | `255, 255, 255`            | `0, 0, 0`                 |
| `--mono-rgb-100` | `0, 0, 0`                  | `255, 255, 255`           |

> Avoid changing the value of black and white variables.

## Semantic colors

Semantic colors are derived from the base color palette based on their intended use.

#### Surface colors

<div style="display: flex; gap: var(--size-4-4)">
  <div style="background-color: var(--background-primary); padding: var(--size-4-4); border: 1px solid var(--background-modifier-border)">Primary background
  <div style="background-color: var(--background-primary-alt); padding: var(--size-4-4); margin-top: var(--size-4-4)">Alt. primary background</div>
  </div>
  <div style="background-color: var(--background-secondary); padding: var(--size-4-4); border: 1px solid var(--background-modifier-border)">Secondary background
  <div style="background-color: var(--background-secondary-alt); padding: var(--size-4-4); margin-top: var(--size-4-4)">Alt. secondary background</div></div>
</div>

| Variable                             | Description                   |
| ------------------------------------ | ----------------------------- |
| `--background-primary`               | Primary background            |
| `--background-primary-alt`           | Background for surfaces on top of primary background         |
| `--background-secondary`             | Secondary background          |
| `--background-secondary-alt`           | Background for surfaces on top of secondary background         |
| `--background-modifier-hover`        | Hovered elements              |
| `--background-modifier-active-hover` | Active hovered elements       |
| `--background-modifier-border`       | Border color                  |
| `--background-modifier-border-hover` | Border color (hover)        |
| `--background-modifier-border-focus` | Border color (focus)        |
| `--background-modifier-error-rgb`    | Error background, RGB value   |
| `--background-modifier-error`        | Error background              |
| `--background-modifier-error-hover`  | Error background (hover)    |
| `--background-modifier-success-rgb`  | Success background, RGB value |
| `--background-modifier-success`      | Success background            |
| `--background-modifier-message`      | Messages background           |
| `--background-modifier-form-field`   | Form field background         |

#### Interactive colors

| Variable                     | Description                                             |
| ---------------------------- | ------------------------------------------------------- |
| `--interactive-normal`       | Background for standard interactive elements            |
| `--interactive-hover`        | Background for standard interactive elements (hover)    |
| `--interactive-accent`       | Background for accented interactive elements            |
| `--interactive-accent-hsl`   | Background for accented interactive elements in HSL |
| `--interactive-accent-hover` | Background for accented interactive elements (hover)    |

### Text colors

#### Text foreground colors

| Variable                    | Description                                    |
| --------------------------- | ---------------------------------------------- |
| `--text-normal`             | Normal text                                    |
| `--text-muted`              | Muted text                                     |
| `--text-faint`              | Faint text                                     |
| `--text-on-accent`          | Text on accent background when accent is dark  |
| `--text-on-accent-inverted` | Text on accent background when accent is light |
| `--text-success`            | Success text                                   |
| `--text-warning`            | Warning text                                   | 
| `--text-error`              | Error text                                     |
| `--text-accent`             | Accent text                                    |
| `--text-accent-hover`       | Accent text (hover)                            |

#### Text background colors

| Variable              | Description                 |
| --------------------- | --------------------------- |
| `--text-selection`    | Selected text background    |
| `--text-highlight-bg` | Highlighted text background |

Obsidian follows operating system conventions for cursors, which means interactive elements use the arrow cursor instead of the pointer cursor.

| Variable        | Default value | Description                     |
| --------------- | ------------- | ------------------------------- |
| `--cursor`      | `default`     | Cursor for interactive elements |
| `--cursor-link` | `pointer`     | Cursor for links                |

Radiuses define the rounded corners for UI elements.

| Variable      | Default value |
| ------------- | ------------- |
| `--radius-s`  | `4px`         |
| `--radius-m`  | `8px`         |
| `--radius-l`  | `12px`        |
| `--radius-xl` | `16px`        |

Layers define the depth, or z-index, of an element.

| Variable               | Default value |
| ---------------------- | ------------- |
| `--layer-cover`        | `5`           |
| `--layer-sidedock`     | `10`          |
| `--layer-status-bar`   | `15`          |
| `--layer-popover`      | `30`          |
| `--layer-slides`       | `45`          |
| `--layer-modal`        | `50`          |
| `--layer-notice`       | `60`          |
| `--layer-menu`         | `65`          |
| `--layer-tooltip`      | `70`          |
| `--layer-dragged-item` | `80`          |

Obsidian uses a 4-pixel grid to structure UI elements. By using multiples of 4 for padding and margin, the grid provides convenient ratios for layouts and allows the interface to scale up and down across high and low DPI screens.

To align with the 4-pixel grid, all elements should use the predefined `--size` CSS variables for spacing and dimensions properties.

Each size variable contains two numbers which represent the base and the multiple.

- `--size-4-1` represents `4px` (4x1)
- `--size-4-2` represents `8px` (4x2)
- `--size-4-4` represents `16px` (4x4)

In addition to the 4-pixel grid, Obsidan also provides a set of variables that uses a 2-pixel grid. Use these sparingly and only when you need more fine-grained spacing.

| `--size-2-1`  | `2px`         |
| `--size-2-2`  | `4px`         |
| `--size-2-3`  | `6px`         |
| `--size-4-1`  | `4px`         |
| `--size-4-2`  | `8px`         |
| `--size-4-3`  | `12px`        |
| `--size-4-4`  | `16px`        |
| `--size-4-5`  | `20px`        |
| `--size-4-6`  | `24px`        |
| `--size-4-8`  | `32px`        |
| `--size-4-9`  | `36px`        |
| `--size-4-12` | `48px`        |
| `--size-4-16` | `64px`        |
| `--size-4-18` | `72px`        |

## Font size

Obsidian uses both relative and fixed font sizes depending on the context.

- Use `--font-*` (relative) variables in the editor.
- Use `--font-ui-*` (fixed) variables for UI elements.

| Variable            | Default value | Description |
| ------------------- | ------------- | ----------- |
| `--font-text-size`  | `16px`          | Editor font size. Defined by the user under Appearance settings.            |
| `--font-smallest`   | `0.8em`       |             |
| `--font-smaller`    | `0.875em`     |             |
| `--font-small`      | `0.933em`     |             |
| `--font-ui-smaller` | `12px`        |             |
| `--font-ui-small`   | `13px`        |             |
| `--font-ui-medium`  | `15px`        |             |
| `--font-ui-larger`  | `20px`        |             |

## Font weight

| Variable            | Default value |
| ------------------- | ------------- |
| `--font-thin`       | `100`           |
| `--font-extralight` | `200`           |
| `--font-light`      | `300`           |
| `--font-normal`     | `400`           |
| `--font-medium`     | `500`           |
| `--font-semibold`   | `600`           |
| `--font-bold`       | `700`           |
| `--font-extrabold`  | `800`           |
| `--font-black`      | `900`              |

## Text formatting

| Variable        | Description             |
| --------------- | ----------------------- |
| `--bold-weight` | Bold text font weight |
| `--bold-color`  | Bold text color       |
| `--italic-color` | Italic text color |

## Line heights

| Variable               | Default value | Description                                                            |
| ---------------------- | ------------- | ---------------------------------------------------------------------- |
| `--line-height-normal` | `1.5`         | Default line height                                                    |
| `--line-height-tight`  | `1.3`         | Used in search results, tree items, tooltips, and other smaller spaces |

Icons communicate messages at a glance, and draw attention to important information.

Obsidian uses the [Lucide](https://lucide.dev/) icon library, which includes more than 800 icons. You can find all available icons on their website.

> [!important] Custom icons
> If you want to create your own icons for Obsidian, you need to follow the [Icon Design Principles](https://lucide.dev/guide/design/icon-design-guide). You can find [templates and guides](https://github.com/lucide-icons/lucide/blob/main/CONTRIBUTING.md) for vector editors, such as Illustrator, Figma, and Inkscape.

| Variable                  | Description                         |
| ------------------------- | ----------------------------------- |
| `--icon-size`             | Shorthand for icon width and length |
| `--icon-stroke`           | Shorthand for icon stroke width     |
| `--icon-color`            | Icon color                          |
| `--icon-color-hover`      | Icon color (hovered)                |
| `--icon-color-active`     | Icon color (active)                 |
| `--icon-color-focused`    | Icon color (focused)                |
| `--icon-opacity`          | Icon opacity                        |
| `--icon-opacity-hover`    | Icon opacity (hovered)              |
| `--icon-opacity-active`   | Icon opacity (active)               |
| `--clickable-icon-radius` | Clickable icon button radius        |

### Icon sizes

| Variable                 | Default value |
| ------------------------ | ------------- |
| `--icon-xs`              | `14px`        |
| `--icon-s`               | `16px`        |
| `--icon-m`               | `18px`        |
| `--icon-l`               | `18px`        |
| `--icon-xl`              | `32px`        |
| `--icon-xs-stroke-width` | `2px`         |
| `--icon-s-stroke-width`  | `2px`         |
| `--icon-m-stroke-width`  | `1.75px`      |
| `--icon-l-stroke-width`  | `1.75px`      |
| `--icon-xl-stroke-width` | `1.25px`      |

Border thicknesses applied to UI elements. 

| Variable         | Default value |
| ---------------- | ------------- |
| `--border-width` | `1px`         |

This page lists CSS variables for color inputs, such as the accent color picker.

| Variable          | Description         |
| ----------------- | ------------------- |
| `--swatch-radius` | Color swatch radius |
| `--swatch-height` | Color swatch height |
| `--swatch-width`  | Color swatch width  |
| `--swatch-shadow` | Color swatch shadow |

docs/obsidian-developer/Reference/CSS variables/Components/Color input.md

Obsidian displays dragging affordances while the user drag files or tabs.

| Variable                  | Description                 |
| ------------------------- | --------------------------- |
| `--drag-ghost-background` | Drag ghost background color |
| `--drag-ghost-text-color` | Drag ghost text color       |

This page lists CSS variables for modals, such as the settings window and [[Dialog|dialogs]].

| Variable                          | Description                          |
| --------------------------------- | ------------------------------------ |
| `--modal-background`              | Modal background color               |
| `--modal-width`                   | Modal default width                  |
| `--modal-height`                  | Modal default height                 |
| `--modal-max-width`               | Modal maximum width                  |
| `--modal-max-height`              | Modal maximum height                 |
| `--modal-max-width-narrow`        | Narrow modal maximum width           |
| `--modal-border-width`            | Modal border thickness               |
| `--modal-border-color`            | Modal border color                   |
| `--modal-radius`                  | Modal radius                         |
| `--modal-community-sidebar-width` | Community plugin/theme sidebar width |

This page lists CSS variables for slider controls.

| Variable                      | Description                     |
| ----------------------------- | ------------------------------- |
| `--slider-thumb-border-width` | Slider thumb border width       |
| `--slider-thumb-border-color` | Slider thumb border color       |
| `--slider-thumb-height`       | Slider thumb height             |
| `--slider-thumb-width`        | Slider thumb width              |
| `--slider-thumb-y`            | Slider thumb Y position         |
| `--slider-thumb-radius`       | Slider thumb radius             |
| `--slider-track-background`   | Slider track background color   |
| `--slider-track-height`       | Slider track height             |

This page lists CSS variables for indentation guides. Indentation guides visualize the indentation level in nested lists.

| Variable                           | Description                             |
| ---------------------------------- | --------------------------------------- |
| `--indentation-guide-width`        | Indentation guide border width          |
| `--indentation-guide-width-active` | Indentation guide border width (active) |
| `--indentation-guide-color`        | Indentation guide border color          |
| `--indentation-guide-color-active` | Indentation guide border color (active) |
| `--indentation-guide-editing-indent`                                   | Width of the indent in edit mode                                        |

docs/obsidian-developer/Reference/CSS variables/Components/Indentation guides.md

This page lists CSS variables for buttons. For button colors, refer to [[Colors#Interactive colors|Interactive colors]].

| Variable          | Description   |
| ----------------- | ------------- |
| `--button-radius` | Button radius |

This page lists CSS variables for checkboxes and text inside of task lists.

| Variable                        | Description                                |
| ------------------------------- | ------------------------------------------ |
| `--checkbox-radius`             | Checkbox radius                            |
| `--checkbox-size`               | Checkbox height and width                  |
| `--checkbox-marker-color`       | Checkbox marker color for the check itself |
| `--checkbox-color`              | Checkbox background color                  |
| `--checkbox-color-hover`        | Checkbox background color (hover)          |
| `--checkbox-border-color`       | Checkbox unchecked border color            |
| `--checkbox-border-color-hover` | Checkbox unchecked border color (hover)    |
| `--checklist-done-decoration`   | Checkbox checked text decoration           |
| `--checklist-done-color`        | Checkbox checked text color                |

This page lists CSS variables for popovers and file previews.

| Variable               | Description             |
| ---------------------- | ----------------------- |
| `--popover-width`      | Popover default width   |
| `--popover-height`     | Popover default height  |
| `--popover-max-height` | Popover maximum height  |
| `--popover-font-size`  | Popover font size       |
| `--popover-pdf-width`  | PDF file preview width  |
| `--popover-pdf-height` | PDF file preview height |

This page lists CSS variables for prompts, such as the [Quick switcher](https://help.obsidian.md/Plugins/Quick+switcher) and [Command palette](https://help.obsidian.md/Plugins/Command+palette).

| Variable                | Description                           |
| ----------------------- | ------------------------------------- |
| `--prompt-width`        | Prompt width                          |
| `--prompt-max-width`    | Prompt max width (for narrow windows) |
| `--prompt-max-height`   | Prompt max height                     |
| `--prompt-border-width` | Prompt border width                   |
| `--prompt-border-color` | Prompt border color                  |

This page lists CSS variables for navigational items, such as files and folders in [[File explorer]].

| Variable                              | Description                                 |
| ------------------------------------- | ------------------------------------------- |
| `--nav-item-size`                     | Nav item font size                          |
| `--nav-item-color`                    | Nav item text color                         |
| `--nav-item-color-hover`              | Nav item text color (hover)                 |
| `--nav-item-color-active`             | Nav item text color (active)                |
| `--nav-item-color-selected`           | Nav item text color (selected)              |
| `--nav-item-color-highlighted`        | Nav item text color (highlighted)           |
| `--nav-item-background-hover`         | Nav item background color (hover)           |
| `--nav-item-background-active`        | Nav item background color (active)          |
| `--nav-item-background-selected`      | Nav item background color (selected)        |
| `--nav-item-padding`                  | Nav item padding                            |
| `--nav-item-parent-padding`           | Nav item padding for parent elements        |
| `--nav-item-children-padding-left`    | Nav item children left padding              |
| `--nav-item-children-margin-left`     | Nav item children left margin               |
| `--nav-item-weight`                   | Nav item font weight                        |
| `--nav-item-weight-hover`             | Nav item font weight (hover)                |
| `--nav-item-weight-active`            | Nav item font weight (active)               |
| `--nav-item-white-space`              | Nav item `white-space`                      |
| `--nav-indentation-guide-width`       | Nav item indentation guide border width     |
| `--nav-indetation-guide-color`        | Nav item indentation guide border color     |
| `--nav-collapse-icon-color`           | Nav item collapse chevron color             |

| `--nav-collapse-icon-color-collapsed` | Nav item collapse chevron color (collapsed) |

This page lists CSS variables for dialogs. A dialog is a smaller modal that's primarily used for confirmation.

| Variable              | Description           |
| --------------------- | --------------------- |
| `--dialog-width`      | Dialog default width  |
| `--dialog-max-width`  | Dialog maximum width  |
| `--dialog-max-height` | Dialog maximum height |

This page lists CSS variables for tabs.

| Variable                                  | Description                                  |
| ----------------------------------------- | -------------------------------------------- |
| `--tab-background-active`                 | Tab background color (active tab)            |
| `--tab-text-color`                        | Tab text color                               |
| `--tab-text-color-active`                 | Tab text color (non-focused window, active)  |
| `--tab-text-color-focused`                | Tab text color (focused window)              |
| `--tab-text-color-focused-active`         | Tab text color (focused window, active)      |
| `--tab-text-color-focused-highlighted`    | Tab text color (focused window, highlighted) |
| `--tab-text-color-focused-active-current` | Tab text color (focused window, current tab) |
| `--tab-font-size`                         | Tab font size                                |
| `--tab-font-weight`                       | Tab font weight                              |
| `--tab-container-background`              | Tab container background color               |
| `--tab-divider-color`                     | Tab divider color                            |
| `--tab-outline-color`                     | Tab outline color                            |
| `--tab-outline-width`                     | Tab outline width                            |
| `--tab-curve`                             | Tab curve radius                             |
| `--tab-radius`                            | Tab outer radius                             |
| `--tab-radius-active`                     | Tab outer radius (active tab)                |
| `--tab-width`                             | Tab default width                            |
| `--tab-max-width`                         | Tab maximum width                            |

### Tab stacks

Styling for stacked tabs

| Variable                          | Description                   |
| --------------------------------- | ----------------------------- |
| `--tab-stacked-pane-width`        | Stacked pane width            |
| `--tab-stacked-header-width`      | Stacked header width          |
| `--tab-stacked-font-size`         | Stacked tab font size         |
| `--tab-stacked-font-weight`       | Stacked tab font weight       |
| `--tab-stacked-text-align`        | Stacked tab text alignment    |
| `--tab-stacked-text-transform`    | Stacked tab text transform    |
| `--tab-stacked-text-writing-mode` | Stacked tab text writing mode |
| `--tab-stacked-shadow`            | Stacked tab shadow            |

This page lists CSS variables toggles.

| Variable                  | Description                   |
| ------------------------- | ----------------------------- |
| `--toggle-border-width`   | Toggle border width           |
| `--toggle-width`          | Toggle width                  |
| `--toggle-radius`         | Toggle radius                 |
| `--toggle-thumb-color`    | Toggle thumb background color |
| `--toggle-thumb-radius`   | Toggle thumb radius           |
| `--toggle-thumb-height`   | Toggle thumb height           |
| `--toggle-thumb-width`    | Toggle thumb width            |
| `--toggle-s-border-width` | Small toggle border width     |
| `--toggle-s-width`        | Small toggle width            |
| `--toggle-s-thumb-height` | Small toggle thumb height     |
| `--toggle-s-thumb-width`  | Small toggle thumb width      |

This page lists CSS variables for multi-select inputs. For example, used in List type [[Properties]].

| Variable                    | Description                           |
| --------------------------- | ------------------------------------- |
| `--pill-color`              | Pill text color                       |
| `--pill-color-hover`        | Pill text color (hover)               |
| `--pill-color-remove`       | Pill text color when removing         |
| `--pill-color-remove-hover` | Pill text color when removing (hover) |
| `--pill-decoration`         | Pill text decoration                  |
| `--pill-decoration-hover`   | Pill text decoration (hover)          |
| `--pill-background`         | Pill background color                 |
| `--pill-background-hover`   | Pill background color (hover)         |
| `--pill-border-color`       | Pill border color                     |
| `--pill-border-color-hover` | Pill border color (hover)             |
| `--pill-border-width`       | Pill border width                     |
| `--pill-padding-x`          | Pill left/right padding               |
| `--pill-padding-y`          | Pill top/bottom padding               |
| `--pill-radius`             | Pill corner radius                    |
| `--pill-weight`             | Pill font weight                      |

This page lists CSS variables for text inputs.

| Variable               | Description        |
| ---------------------- | ------------------ |
| `--input-height`       | Input height       |
| `--input-radius`       | Input radius       |
| `--input-font-weight`  | Input font weight  |
| `--input-border-width` | Input border width |

docs/obsidian-developer/Reference/CSS variables/Components/Text input.md

This page lists CSS variables used for Obsidian Publish pages.

Publish-specific variables should be defined on the `.published-container`.

### Page width and padding

| Variable                | Description                                    |
| ----------------------- | ---------------------------------------------- |
| `--page-width`          | Width of a note when readable line width is on |
| `--page-padding`        | Padding around a note                          |

### Page title

The note title displayed at the top of the page. This title can be hidden in the Publish site settings using the "**Hide page title**" option.

| Variable                   | Description                       |
| -------------------------- | --------------------------------- |
| `--page-title-color`       | Font color                        |
| `--page-title-font`        | Font family, see [[Site fonts]]                       |
| `--page-title-line-height` | Line height                       |
| `--page-title-size`        | Font size                         |
| `--page-title-style`       | Font style, e.g. normal or italic |
| `--page-title-variant`     | Font variant                      |
| `--page-title-weight`      | Font weight                       |

docs/obsidian-developer/Reference/CSS variables/Publish/Site pages.md

### Introduction

Many of the [[CSS variables]] utilised in the Obsidian app can also be employed in Obsidian Publish (Publish), with corresponding selectors. However, to address to the differing requirements of Publish, the variables in this section were specifically created for Publish, and are to be inserted within the `.published-container` selector. 

See [[Build a Publish theme]] for more details.

### Index

To load remote fonts we recommend using CSS with `@import` or defining your fonts with `@font-face` and an absolute URL. [Learn more.](https://css-tricks.com/snippets/css/using-font-face-in-css/)

For example you can use [Google Fonts](https://fonts.google.com/) in your `publish.css` file. Here's how you would use the font Poppins:

```css
@import url('https://fonts.googleapis.com/css2?family=Poppins:ital@1&display=swap');

  --font-text-theme: 'Poppins';
}
```

| Variable                 | Description                                           |
| ------------------------ | ----------------------------------------------------- |
| `--font-text-size`       | Font size for page text                               |
| `--font-text-theme`      | Font family for page text                             |
| `--font-monospace-theme` | Font family for code                                  |
| `--font-interface-theme` | Font family for interface elements such as navigation |
| `--font-mermaid`         | Font family for Mermaid diagrams                      |
| `--page-title-font`      | Font family for [[Site pages\|page titles]]                                                       |

docs/obsidian-developer/Reference/CSS variables/Publish/Site fonts.md

This page lists CSS variables used for Obsidian Publish site components.

### Component titles

Styles for the title above components such as **Backlinks**, **Graph**, **Table of contents**, when these components are turned on in the site settings.

| Variable                      | Description                       |
| ----------------------------- | --------------------------------- |
| `--component-title-color`     | Font color                        |
| `--component-title-font`      | Font family                       |
| `--component-title-size`      | Font size                         |
| `--component-title-style`     | Font style, e.g. normal or italic |
| `--component-title-transform` | Text transform, e.g. uppercase                                  |
| `--component-title-variant`   | Font variant                      |
| `--component-title-weight`    | Font weight                       |

### Outline

When activated in Publish settings, a table of contents is displayed in the right sidebar showing a navigable list of headings on the page.

| Variable                          | Description                      |
| --------------------------------- | -------------------------------- |
| `--outline-heading-color`         | Font color for inactive headings |
| `--outline-heading-color-hover`   | Font color for hovered heading   |
| `--outline-heading-color-active`  | Font color for active heading    |
| `--outline-heading-weight-active` | Font weight for active heading   |

### Graph

The graph component can be turned on in Publish settings. More graph CSS variables for node and line colors are present in the inherited CSS.

| Variable         | Description                   |
| ---------------- | ----------------------------- |
| `--graph-height` | Height of the graph component |

docs/obsidian-developer/Reference/CSS variables/Publish/Site components.md

When activated in Publish settings, navigation is placed in the left sidebar and can be styled with the following variables. Top-level items and folders can be treated differently than nested items.

| Variable                          | Description                                |
| --------------------------------- | ------------------------------------------ |
| `--nav-collapse-icon-color`       | Collapse icon color                        |
| `--nav-collapse-icon-color-hover` | Collapse icon color (hovered)              |
| `--nav-parent-item-color`         | Font color for folders and top-level items |
| `--nav-parent-item-color-active`  | Font color for active top-level items      |
| `--nav-parent-item-weight`        | Font weight for top-level items            |
| `--nav-item-color`                | Font color for nested items                |
| `--nav-item-color-hover`          | Font color for hovered nested items        |
| `--nav-item-color-active`         | Font color for active nested items         |
| `--nav-item-border-color`         | Border color for nested items              |
| `--nav-item-border-color-hover`   | Border color for hovered nested items      |
| `--nav-item-border-color-active`  | Border color for active nested items       |
| `--nav-item-weight-active`        | Font weight for active nested items        |

docs/obsidian-developer/Reference/CSS variables/Publish/Site navigation.md

The site header contains the site logo (if added in Publish settings), the site name, and the mobile hamburger menu if navigation is turned on.

The site header appears as a horizontal header at the top of the page on mobile devices and when navigation is turned off. When navigation is turned on in Publish settings, the site name and logo appear in the left sidebar.

This page lists CSS variables used for Obsidian Publish site header, site logo, and site name

| Variable                       | Description                    |
| ------------------------------ | ------------------------------ |
| `--logo-width`                 | Logo default width             |
| `--logo-height`                | Logo default height            |
| `--logo-max-width`             | Logo max width                 |
| `--logo-max-height`            | Logo max height                |
| `--logo-radius`                | Logo corner radius             |
| `--header-height`              | Height of the site header      |
| `--site-name-color`            | Site name color                |
| `--site-name-color-hover`      | Site name hovered color        |
| `--site-name-font`             | Site name font family          |
| `--site-name-size`             | Site name font size            |
| `--site-name-weight`           | Site name font weight          |
| `--site-menu-icon-color`       | Mobile menu icon color         |
| `--site-menu-icon-color-hover` | Mobile menu hovered icon color |
| `--site-menu-icon-size`        | Mobile menu icon size          |

docs/obsidian-developer/Reference/CSS variables/Publish/Site header.md

The left sidebar is present when [[Site navigation]] is turned on. The right sidebar is present when the **Graph** and/or **Table of Contents** [[Site components]] are turned on. When these components are turned off, the following variables have no effect.

| Variable                       | Description                        |
| ------------------------------ | ---------------------------------- |
| `--sidebar-left-width`         | Width of the left sidebar          |
| `--sidebar-left-background`    | Background color of left sidebar   |
| `--sidebar-left-border-width`  | Right border width of left sidebar |
| `--sidebar-left-border-color`  | Right border color of left sidebar |
| `--sidebar-right-width`        | Width of the right sidebar         |
| `--sidebar-right-background`   | Background color of right sidebar  |
| `--sidebar-right-border-width` | Left border width of right sidebar |
| `--sidebar-right-border-color` | Left border color of right sidebar |

docs/obsidian-developer/Reference/CSS variables/Publish/Site sidebars.md

This page lists CSS variables for non-native scrollbars.

> [!note]
> Custom scrollbars are only used on Windows and Linux.

| Variable                      | Description                               |
| ----------------------------- | ----------------------------------------- |
| `--scrollbar-bg`              | Scrollbar background color                |
| `--scrollbar-thumb-bg`        | Scrollbar thumb background color          |
| `--scrollbar-active-thumb-bg` | Scrollbar thumb background color (active) |

This page lists CSS variables the workspace.

| Variable                             | Description                        |
| ------------------------------------ | ---------------------------------- |
| `--workspace-background-translucent` | Background for translucent windows |

This page lists CSS variables for the window frame, including the title bar.

> [!note]
> To see the title bar, you need to change **Settings → Appearance → Window frame style** to **Obsidian frame**.

| `--titlebar-background`         | Titlebar background color                  |
| `--titlebar-background-focused` | Titlebar background color (focused window) |
| `--titlebar-border-width`       | Titlebar border width                      |
| `--titlebar-border-color`       | Titlebar border color                      |
| `--titlebar-text-color`         | Titlebar text color                        |
| `--titlebar-text-color-focused` | Titlebar text color (focused window)       |
| `--titlebar-text-weight`        | Titlebar font weight                       |
| `--header-height`               | Default height for frame elements          |

docs/obsidian-developer/Reference/CSS variables/Window/Window frame.md

This page lists CSS variables for the [Sidebar](https://help.obsidian.md/User+interface/Workspace/Sidebar).

| Variable                       | Description                                 |
| ------------------------------ | ------------------------------------------- |
| `--sidebar-markdown-font-size` | Font size for Markdown files in sidebars    |
| `--sidebar-tab-text-display`   | `display` property for tab text in sidebars |

This page lists CSS variables for the [Status bar](https://help.obsidian.md/User+interface/Workspace/Status+bar).

| Variable                      | Description                    |
| ----------------------------- | ------------------------------ |
| `--status-bar-background`     | Status bar background color    |
| `--status-bar-border-color`   | Status bar border color        |
| `--status-bar-border-width`   | Status bar border width        |
| `--status-bar-font-size`      | Status bar font size           |
| `--status-bar-text-color`     | Status bar text color          |
| `--status-bar-position`       | Status bar `position` property |
| `--status-bar-radius`         | Status bar radius              |
| `--status-bar-scroll-padding` | Status bar scroll padding      |

docs/obsidian-developer/Reference/CSS variables/Window/Status bar.md

This page lists CSS variables for the [Ribbon](https://help.obsidian.md/User+interface/Workspace/Ribbon).

| Variable                        | Description                                 |
| ------------------------------- | ------------------------------------------- |
| `--ribbon-background`           | Ribbon background color                     |
| `--ribbon-background-collapsed` | Ribbon background color (collapsed sidebar) |
| `--ribbon-width`                | Ribbon width                                |
| `--ribbon-padding`              | Ribbon padding                              |

This page lists CSS variables for dividers and resize handles between sidebars, tabs, and split panes.

| `--divider-color`           | Divider border color         |
| `--divider-color-hover`     | Divider border color (hover) |
| `--divider-width`           | Divider border width         |
| `--divider-width-hover`     | Divider border width (hover) |
| `--divider-vertical-height` | Divider vertical height      |

This page lists CSS variables for blockquotes.

| `--blockquote-background-color` | Blockquote background color                 |
| `--blockquote-border-thickness` | Blockquote left border thickness            |
| `--blockquote-border-color`     | Blockquote left border color                |
| `--blockquote-font-style`       | Blockquote font style (e.g. normal, italic) |
| `--blockquote-color`            | Blockquote text color                       |

This page lists CSS variables for open files in the editor.

| Variable                    | Description                                           |
| --------------------------- | ----------------------------------------------------- |
| `--file-line-width`         | Width of a line when readable line width is turned on |
| `--file-folding-offset`     | Width of the line offset for fold indicators          |
| `--file-margins`            | File margins                                          |
| `--file-header-font-size`   | File header font size                                 |
| `--file-header-font-weight` | File header font weight                               |
| `--file-header-border`      | File header `border-bottom` property                  |
| `--file-header-justify`     | File header text alignment, uses `justify-content`    |

This page lists CSS variables for tags.

| Variable                   | Description                  |
| -------------------------- | ---------------------------- |
| `--tag-size`               | Tag font size                |
| `--tag-color`              | Tag text color               |
| `--tag-color-hover`        | Tag text color (hover)       |
| `--tag-decoration`         | Tag text decoration          |
| `--tag-decoration-hover`   | Tag text decoration (hover)  |
| `--tag-background`         | Tag background color         |
| `--tag-background-hover`   | Tag background color (hover) |
| `--tag-border-color`       | Tag border color             |
| `--tag-border-color-hover` | Tag border color (hover)     |
| `--tag-border-width`       | Tag border width             |
| `--tag-padding-x`          | Tag left/right padding       |
| `--tag-padding-y`          | Tag top/down padding         |
| `--tag-radius`             | Tag radius                   |
| `--tag-weight`             | Tag font weight              |

This page lists CSS variables for rendered blocks in Live Preview.

| Variable                     | Description                                            |
| ---------------------------- | ------------------------------------------------------ |
| `--embed-block-shadow-hover` | Hover shadow for rendered embed blocks in Live Preview |

| Variable                                | Description                           |
| --------------------------------------- | ------------------------------------- |
| `--table-background`                    | Table background color                |
| `--table-border-width`                  | Table border width                    |
| `--table-border-color`                  | Table border color                    |
| `--table-cell-vertical-alignment`       | Cell vertical alignment               |
| `--table-white-space`                   | Table `white-space` property          |
| `--table-header-background`             | Table header background color         |
| `--table-header-background-hover`       | Table header background color (hover) |
| `--table-header-border-width`           | Table header border width             |
| `--table-header-border-color`           | Table header border color             |
| `--table-header-font`                   | Table header font family              |
| `--table-header-size`                   | Table header font size                |
| `--table-header-weight`                 | Table header font weight              |
| `--table-header-color`                  | Table header text color               |
| `--table-line-height`                   | Line height for cell text                                      |
| `--table-text-size`                     | Cell font size                        |
| `--table-text-color`                    | Cell text color                       |
| `--table-column-max-width`              | Column maximum width                  |
| `--table-column-alt-background`         | Alternating column background color   |
| `--table-column-first-border-width`     | First column left border width        |
| `--table-column-last-border-width`      | Last column right border width        |
| `--table-row-background-hover`          | Row background color (hover)          |

| `--table-row-alt-background`            | Alternating row background color      |
| `--table-last-border-width`             | Last row bottom border width          |
| `--table-selection`                     | Selection background color            |
| `--table-selection-blend-mode`          | Selection blend mode                  |
| `--table-selection-border-color`        | Selection border color                |
| `--table-selection-border-width`        | Selection border width                |
| `--table-selection-border-radius`       | Selection border radius               |
| `--table-drag-handle-background`        | Drag handle background color          |
| `--table-drag-handle-background-active` | Drag handle background color (active) |
| `--table-drag-handle-color`             | Drag handle icon color                |
| `--table-drag-handle-color-active`      | Drag handle icon color (active)       |

This page lists CSS variables for inline titles.

> [!note]
> To see inline titles, you need to enable **Settings → Appearance → Show inline title**.

| Variable                     | Description               |
| ---------------------------- | ------------------------- |
| `--inline-title-color`       | Inline title text color   |
| `--inline-title-font`        | Inline title font family  |
| `--inline-title-line-height` | Inline title line height  |
| `--inline-title-size`        | Inline title font size    |
| `--inline-title-style`       | Inline title font style   |
| `--inline-title-variant`     | Inline title font variant |
| `--inline-title-weight`      | Inline title font weight  |

docs/obsidian-developer/Reference/CSS variables/Editor/Inline title.md

This page lists CSS variables for [Callouts](https://help.obsidian.md/Editing+and+formatting/Callouts).

| Variable                       | Description                                                 |
| ------------------------------ | ----------------------------------------------------------- |
| `--callout-border-width`       | Callout border width                                        |
| `--callout-border-opacity`     | Callout border opacity                                      |
| `--callout-padding`            | Callout padding                                             |
| `--callout-radius`             | Callout radius                                              |
| `--callout-blend-mode`         | Callout blend mode, allows color mixing for nested callouts |
| `--callout-title-color`        | Callout title text color                                    |
| `--callout-title-padding`      | Callout title padding                                       |
| `--callout-title-size`         | Callout title font size                                     |
| `--callout-content-padding`    | Callout content padding                                     |
| `--callout-content-background` | Callout content background color                            |

### Type colors

Callout types have unique icons and colors, and may have multiple aliases.

| Variable              | Callout type                      |
| --------------------- | --------------------------------- |
| `--callout-bug`       | `bug`                             |
| `--callout-default`   | `default`, `note`                 |
| `--callout-error`     | `error`, `danger`                 |
| `--callout-example`   | `example`                         |
| `--callout-fail`      | `fail`, `failure`, `missing`      |
| `--callout-important` | `important`                       |
| `--callout-info`      | `info`                            |
| `--callout-question`  | `question`, `help`, `faq`         |
| `--callout-success`   | `success`, `check`, `done`        |
| `--callout-summary`   | `summary`, `abstract`, `tldr`     |
| `--callout-tip`       | `tip`, `hint`                     |
| `--callout-todo`      | `todo`                            |
| `--callout-warning`   | `warning`, `caution`, `attention` |
| `--callout-quote`     | `quote`, `cite`                   |

This page lists CSS variables for ordered and unordered lists.

| Variable | Description |
| `--list-indent` | Horizontal indentation depth for nested items |
| `--list-spacing` | Vertical spacing between list items |
| `--list-marker-align` | List marker text alignment |
| `--list-marker-color` | List marker color |
| `--list-marker-color-hover` | List marker color (hover) |
| `--list-marker-color-collapsed` | List marker color for collapsed items |
| `--list-marker-min-width` | List marker minimum width |
| `--list-bullet-border` | List bullet border |
| `--list-bullet-radius` | List bullet radius |
| `--list-bullet-size` | List bullet width/height |
| `--list-bullet-transform` | List bullet `transform` property |
| `--list-numbered-style` | `list-style-type` for numbered lists |

This page lists CSS variables for [Properties](https://help.obsidian.md/Editing+and+formatting/Properties), the YAML metadata editor for frontmatter. See also [[Checkbox]], [[Text input]] and [[Multi-select]] for variables related to the input types.

### Properties container

These variables apply to the entire Properties container.

| Variable                     | Description             |
| ---------------------------- | ----------------------- |
| `--metadata-background`      | Background color        |
| `--metadata-display-editing` | Display in editing mode |
| `--metadata-display-reading` | Display in reading mode |
| `--metadata-max-width`       | Max width               |
| `--metadata-padding`         | Padding                 |
| `--metadata-border-color`    | Border color            |
| `--metadata-border-radius`   | Corner radius           |
| `--metadata-border-width`    | Border width            |
| `--metadata-gap`             | Gap between properties  |

### Individual properties

These variables apply to individual properties in the list.

| Variable                                | Description                               |
| --------------------------------------- | ----------------------------------------- |
| `--metadata-divider-color`              | Color of divider lines between properties |
| `--metadata-divider-color-hover`        | Color of dividers when property (hover)   |
| `--metadata-divider-color-focus`        | Color of dividers when property (focused) |
| `--metadata-divider-width`              | Width of divider lines                    |
| `--metadata-property-padding`           | Property adding                           |
| `--metadata-property-radius`            | Property corner radius                    |
| `--metadata-property-background`        | Property background color                 |
| `--metadata-property-background-hover`  | Property background color (hover)         |
| `--metadata-property-background-active` | Property background color (active)        |
| `--metadata-label-background-hover`     | Property label background color(hover)    |
| `--metadata-label-background-active`    | Property label background color (active)  |
| `--metadata-label-font-size`            | Property label font size                  |
| `--metadata-label-font-weight`          | Property label font weight                |
| `--metadata-sidebar-label-font-size`    | Property label font size (sidebar)        |
| `--metadata-label-text-color`           | Property label text color                 |
| `--metadata-label-text-color-hover`     | Property label text color (hover)         |
| `--metadata-label-width`                | Property label width                      |
| `--metadata-input-height`               | Property input height                     |
| `--metadata-input-text-color`           | Property input text color                 |
| `--metadata-input-font-size`            | Property input font size                  |

| `--metadata-sidebar-input-font-size`    | Property input font size (sidebar)        |
| `--metadata-input-background`           | Property input background color           |
| `--metadata-input-background-hover`     | Property input background color (hover)   |
| `--metadata-input-background-active`    | Property input background color (active)  |

This page lists CSS variables for [embedded files](https://help.obsidian.md/Linking+notes+and+files/Embedding+files).

| `--embed-max-height`         | Embed max height                                       |
| `--embed-canvas-max-height`  | Embedded Canvas element max height                     |
| `--embed-background`         | Embed background color                                 |
| `--embed-border-left`        | Embed left border, shorthand property                  |
| `--embed-border-right`       | Embed right border, shorthand property                 |
| `--embed-border-top`         | Embed top border, shorthand property                   |
| `--embed-border-bottom`      | Embed bottom border, shorthand property                |
| `--embed-padding`            | Embedd padding                                         |
| `--embed-font-style`         | Embed `font-style`                                     |

This page lists CSS variables for footnotes.

| Variable          | Description        |
| ----------------- | ------------------ |
| `--footnote-size` | Footnote font size |

This page lists CSS variables for links.

Obsidian supports three different types of links:

- **Resolved internal links** link to an existing note.
- **Unresolved internal links** link to a non-existing note.
- **External links** link to an external URL or URI.

| Variable                             | Description                               |
| ------------------------------------ | ----------------------------------------- |
| `--link-color`                       | Resolved link text color                  |
| `--link-color-hover`                 | Resolved link text color (hover)          |
| `--link-decoration`                  | Resolved link text decoration             |
| `--link-decoration-hover`            | Resolved link text decoration (hover)     |
| `--link-decoration-thickness`        | Resolved link text decoration thickness   |
| `--link-unresolved-color`            | Unresolved link text color                |
| `--link-unresolved-opacity`          | Unresolved link opacity                   |
| `--link-unresolved-filter`           | Unresolved link filter, e.g. `hue-rotate` |
| `--link-unresolved-decoration-style` | Unresolved link text decoration style     |
| `--link-unresolved-decoration-color` | Unresolved link text decoration color     |
| `--link-external-color`              | External link text color                  |
| `--link-external-color-hover`        | External link text color (hover)          |
| `--link-external-decoration`         | External link text decoration             |
| `--link-external-decoration-hover`   | External link text decoration (hover)     |

| Variable               | Description                                  |
| ---------------------- | -------------------------------------------- |
| `--heading-formatting` | Text color for Markdown heading depth syntax |
| `--h1-color`           | H1 text color                                |
| `--h2-color`           | H2 text color                                |
| `--h3-color`           | H3 text color                                |
| `--h4-color`           | H4 text color                                |
| `--h5-color`           | H5 text color                                |
| `--h6-color`           | H6 text color                                |
| `--h1-font`            | H1 font family                               |
| `--h2-font`            | H2 font family                               |
| `--h3-font`            | H3 font family                               |
| `--h4-font`            | H4 font family                               |
| `--h5-font`            | H5 font family                               |
| `--h6-font`            | H6 font family                               |
| `--h1-line-height`     | H1 line height                               |
| `--h2-line-height`     | H2 line height                               |
| `--h3-line-height`     | H3 line height                               |
| `--h4-line-height`     | H4 line height                               |
| `--h5-line-height`     | H5 line height                               |
| `--h6-line-height`     | H6 line height                               |
| `--h1-size`            | H1 font size                                 |
| `--h2-size`            | H2 font size                                 |
| `--h3-size`            | H3 font size                                 |
| `--h4-size`            | H4 font size                                 |
| `--h5-size`            | H5 font size                                 |
| `--h6-size`            | H6 font size                                 |

| `--h1-style`           | H1 font style                                |
| `--h2-style`           | H2 font style                                |
| `--h3-style`           | H3 font style                                |
| `--h4-style`           | H4 font style                                |
| `--h5-style`           | H5 font style                                |
| `--h6-style`           | H6 font style                                |
| `--h1-variant`         | H1 font variant                              |
| `--h2-variant`         | H2 font variant                              |
| `--h3-variant`         | H3 font variant                              |
| `--h4-variant`         | H4 font variant                              |
| `--h5-variant`         | H5 font variant                              |
| `--h6-variant`         | H6 font variant                              |
| `--h1-weight`          | H1 font weight                               |
| `--h2-weight`          | H2 font weight                               |
| `--h3-weight`          | H3 font weight                               |
| `--h4-weight`          | H4 font weight                               |
| `--h5-weight`          | H5 font weight                               |
| `--h6-weight`          | H6 font weight                               |

This page lists CSS variables for horizontal rules.

| Variable         | Description                      |
| ---------------- | -------------------------------- |
| `--hr-color`     | Horizontal rule border color     |
| `--hr-thickness` | Horizontal rule border thickness |

docs/obsidian-developer/Reference/CSS variables/Editor/Horizontal rule.md

This page lists CSS variables for code.

| Variable             | Description           |
| -------------------- | --------------------- |
| `--code-background`  | Code background color |
| `--code-white-space` | Code `white-space`    |
| `--code-size`        | Code font size        |

### Syntax highlighting

> [!note]
> Since Obsidian uses two different libraries for syntax highlighting—one for Editing view and another for Reading view—styling may not match perfectly between the two.

| Variable             | Description              |
| -------------------- | ------------------------ |
| `--code-normal`      | Non-highlighted syntax   |
| `--code-comment`     | Comments                 |
| `--code-function`    | Functions                |
| `--code-important`   | Important, regex         |
| `--code-keyword`     | Keywords                 |
| `--code-operator`    | Operators                |
| `--code-property`    | Properties               |
| `--code-punctuation` | Punctuation              |
| `--code-string`      | Strings                  |
| `--code-tag`         | Tags, symbols, constants |
| `--code-value`       | Values                   |