Kirill Chokparov79 downloadsAdds custom CSS classes to tags containing any non-Latin letters (cyrillic, hieroglyphs, diacritics, etc.) in Editing view. Enables styling non-Latin tags via CSS snippets and third-party plugins.
English | [Русский][1]
The plugin adds custom CSS classes to tags containing any non-Latin letters (cyrillic, hieroglyphs, diacritics, etc.) in Editing view.
This allows you to customize the appearance of non-Latin tags via CSS or configure their styling using third-party plugins (such as Colored Tags Wrangler).
Simply install and enable the plugin in your Obsidian settings. It requires zero configuration and is controlled by a single toggle switch.
The plugin analyzes the tag content and processes only those that contain at least one non-Latin letter.
Latin tags (e.g., #task) remain untouched and retain standard Obsidian classes.
Non-Latin tags receive two additional classes:
cm-tag-non-latin — for styling all non-Latin tags.cm-tag-[tag_name] — for fine-tuning specific tags.Example 1. The #завершено tag will receive the generic class cm-tag-non-latin and the personal class cm-tag-завершено.
Example 2. The #초봄날 tag will receive the generic cm-tag-non-latin class and the personal cm-tag-초봄날 class.
You can use these classes in your CSS snippet inside the .obsidian/snippets folder to visually highlight your tags.
.cm-tag-non-latin {
background-color: green;
color: whitesmoke;
}
The #завершено tag:
.cm-tag-завершено {
background-color: royalblue;
color: #ffffff;
font-weight: bold;
}
The #초봄날 tag:
.cm-tag-초봄날 {
background-color: #E2F0D9;
color: #386641;
}
Following the Obsidian style for Latin tags, the plugin removes slashes in the class name for nested non-Latin tags, such as #книга/глава1/часть2.
In the DOM structure, the class name looks like this: <span class="cm-tag-книгаглава1часть2">.
Styling in the CSS file:
.cm-tag-книгаглава1часть2 {
color: grey;
background-color: mistyrose;
}
This approach also ensures compatibility with third-party plugins for styling nested non-Latin tags.
Emojis and digits (e.g., #test😊, #task123) do not turn a tag into a non-Latin one if all other letters inside it are Latin.
Each tag in Obsidian is composed of multiple <span> elements. When the plugin detects a non-Latin tag, it iterates through all its constituent HTML elements and injects custom classes into their class attribute.
Elements of Latin tags remain untouched.
When a class is added to a <span> element, an additional nested <span> element is automatically generated within the DOM structure, which then holds the actual tag content.
The resulting structure looks like this:
<span class="..."> <!-- original parent element -->
<span class="...">tag_name</span> <!-- nested element -->
</span>
The plugin only adds new classes to the nested <span> elements. Parent elements retain their original Obsidian classes.
To ensure third-party plugins can recognize and style tags processed by this plugin, the nested <span> elements must contain the standard Obsidian cm-hashtag class. Therefore, the plugin also injects the class into these elements.
When a nested structure of elements containing the cm-hashtag class appears, the default styling breaks: extra paddings/margins appear, and the tag's font size decreases.
This happens due to the following class layering:
<span class="cm-hashtag ..."> <!-- parent element -->
<span class="cm-hashtag ...">tag_name</span> <!-- nested element -->
</span>
To preserve the original style, the plugin integrates a custom theme extension that neutralizes the parent <span> element's impact on non-Latin tags:
const tagThemeExtension = EditorView.theme({
".cm-hashtag:has(.cm-tag-non-latin)": {
display: "contents !important",
fontSize: "inherit !important",
lineHeight: "inherit !important",
fontFamily: "inherit !important",
fontWeight: "inherit !important"
}
});
A tag in Obsidian is composed of two or more <span> elements. By traversing the syntax tree and analyzing the nodes, the plugin injects the following additional classes into the elements of non-Latin tags.
cm-hashtag — base Obsidian system class.cm-tag-non-latin — global class for all non-Latin tags.cm-tag-[tag_name] — personal dynamic class. The tag name is generated "as is", preserving all characters except for forward slashes (/).# symbol) additionally receives the cm-hashtag-begin class.cm-hashtag-end class.Let's consider the #тег_тест tag.
Obsidian splits this tag with an underscore into three separate <span> elements. The plugin locates them in the syntax tree and appends the custom classes:
<!-- 1. First element (the '#' symbol) -->
<span class="cm-hashtag cm-hashtag-begin cm-tag-non-latin cm-tag-тег_тест">#</span>
<!-- 2. Second element -->
<span class="cm-hashtag cm-tag-non-latin cm-tag-тег_тест">тег_</span>
<!-- 3. Last element -->
<span class="cm-hashtag cm-hashtag-end cm-tag-non-latin cm-tag-тег_тест">тест</span>
The source code is covered by unit tests using Vitest. The tests verify various linguistic combinations, edge-case ASCII characters, nested tags and emojis.
This project is distributed under the free MIT License.
[1]: https://github.com/javatutor-ru/obsidian-cyrillic-non-latin-tags/blob/main/README_RU.md