code-editor: Improve code highlight performance. (#885)

- Split code to lines to improve performance and cache hit rate, close
#881
- Update default code highlight theme to use `macOS Classic`.

<img width="1208" alt="image"
src="https://github.com/user-attachments/assets/511b442d-5960-493f-88cc-b8aceb68f77b"
/>
<img width="1208" alt="image"
src="https://github.com/user-attachments/assets/6e5b2728-384f-4b62-b069-268118dec9ab"
/>
This commit is contained in:
Jason Lee 2025-05-22 18:09:18 +08:00 committed by GitHub
parent 244090ddc5
commit d0ccb6bf17
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 756 additions and 1134 deletions

View file

@ -75,16 +75,16 @@ impl<'a> Highlighter<'a> {
}
}
/// Highlight a text and returns a vector of ranges and highlight styles
pub fn highlight(&self, text: &str) -> Vec<(Range<usize>, HighlightStyle)> {
/// Highlight a line and returns a vector of ranges and highlight styles
pub fn highlight(&self, line: &str) -> Vec<(Range<usize>, HighlightStyle)> {
let mut parser = parsing::ParseState::new(self.syntax);
let mut stack = parsing::ScopeStack::new();
let ops = parser.parse_line(text, &SYNTAXES).unwrap_or_default();
let ops = parser.parse_line(line, &SYNTAXES).unwrap_or_default();
ScopeRangeIterator {
ops,
line_length: text.len(),
line_length: line.len(),
index: 0,
last_str_index: 0,
}

View file

@ -1,597 +1,324 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>author</key>
<string>Michael Sheets</string>
<key>gutterSettings</key>
<dict>
<key>background</key>
<string>#2F2F31</string>
<key>divider</key>
<string>#414143</string>
<key>foreground</key>
<string>#8F8F8F</string>
<key>selectionBackground</key>
<string>#414143</string>
<key>selectionBorder</key>
<string>#484848</string>
<key>selectionForeground</key>
<string>#BABABA</string>
</dict>
<key>name</key>
<string>Twilight</string>
<key>semanticClass</key>
<string>theme.dark.twilight</string>
<key>settings</key>
<array>
<dict>
<key>settings</key>
<dict>
<key>background</key>
<string>#181818</string>
<key>caret</key>
<string>#A7A7A7</string>
<key>foreground</key>
<string>#F8F8F8</string>
<key>invisibles</key>
<string>#FFFFFF40</string>
<key>lineHighlight</key>
<string>#FFFFFF08</string>
<key>selection</key>
<string>#DDF0FF33</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Foldings</string>
<key>scope</key>
<string>deco.folding</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#5A6A65</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Comment</string>
<key>scope</key>
<string>comment</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#5F5A60</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Constant</string>
<key>scope</key>
<string>constant</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#CF6A4C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Entity</string>
<key>scope</key>
<string>entity</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#9B703F</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Keyword</string>
<key>scope</key>
<string>keyword</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#CDA869</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Storage</string>
<key>scope</key>
<string>storage</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#F9EE98</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>String</string>
<key>scope</key>
<string>string</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#8F9D6A</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Support</string>
<key>scope</key>
<string>support</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#9B859D</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Variable</string>
<key>scope</key>
<string>variable</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#7587A6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Invalid Deprecated</string>
<key>scope</key>
<string>invalid.deprecated</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic underline</string>
<key>foreground</key>
<string>#D2A8A1</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Invalid Illegal</string>
<key>scope</key>
<string>invalid.illegal</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#562D56BF</string>
<key>foreground</key>
<string>#F8F8F8</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>-----------------------------------</string>
<key>settings</key>
<dict/>
</dict>
<dict>
<key>name</key>
<string>♦ Embedded Source</string>
<key>scope</key>
<string>meta.embedded.block, punctuation.whitespace.embedded</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#B0B3BA14</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>♦ Embedded Source (Bright)</string>
<key>scope</key>
<string>meta.embedded.line</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#B1B3BA21</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>♦ Entity inherited-class</string>
<key>scope</key>
<string>entity.other.inherited-class</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#9B5C2E</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>♦ String embedded-source</string>
<key>scope</key>
<string>string meta.embedded</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#DAEFA3</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>♦ String constant</string>
<key>scope</key>
<string>string constant</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#DDF2A4</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>♦ String.regexp</string>
<key>scope</key>
<string>string.regexp</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#E9C062</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>♦ String.regexp.«special»</string>
<key>scope</key>
<string>string.regexp constant.character.escape, string.regexp source.ruby.embedded, string.regexp string.regexp.arbitrary-repetition</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#CF7D34</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>♦ String variable</string>
<key>scope</key>
<string>string variable</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#8A9A95</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>♦ Support.function</string>
<key>scope</key>
<string>support.function</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#DAD085</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>♦ Support.constant</string>
<key>scope</key>
<string>support.constant</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#CF6A4C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>c C/C++ Preprocessor Line</string>
<key>scope</key>
<string>meta.preprocessor.c, source.swift meta.preprocessor</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#8996A8</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>c C/C++ Preprocessor Directive</string>
<key>scope</key>
<string>meta.preprocessor.c keyword, source.swift meta.preprocessor keyword</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#AFC4DB</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>✘ Doctype/XML Processing</string>
<key>scope</key>
<string>meta.tag.metadata.doctype, meta.tag.metadata.doctype entity, meta.tag.metadata.doctype string, meta.tag.metadata.processing.xml, meta.tag.metadata.processing.xml entity, meta.tag.metadata.processing.xml string</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#494949</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>✘ Meta.tag.«all»</string>
<key>scope</key>
<string>declaration.tag, declaration.tag entity, meta.tag, meta.tag entity</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#AC885B</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>✘ Meta.tag.inline</string>
<key>scope</key>
<string>declaration.tag.inline, declaration.tag.inline entity, meta.tag.inline, meta.tag.inline entity</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#E0C589</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>§ css tag-name</string>
<key>scope</key>
<string>meta.selector.css entity.name.tag</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#CDA869</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>§ css:pseudo-class</string>
<key>scope</key>
<string>meta.selector.css entity.other.attribute-name.tag.pseudo-class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#8F9D6A</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>§ css#id</string>
<key>scope</key>
<string>meta.selector.css entity.other.attribute-name.id</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#8B98AB</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>§ css.class</string>
<key>scope</key>
<string>meta.selector.css entity.other.attribute-name.class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#9B703F</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>§ css property-name:</string>
<key>scope</key>
<string>support.type.property-name.css</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#C5AF75</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>§ css property-value;</string>
<key>scope</key>
<string>meta.property-group support.constant.property-value.css, meta.property-value support.constant.property-value.css</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#F9EE98</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>§ css @at-rule</string>
<key>scope</key>
<string>meta.preprocessor.at-rule keyword.control.at-rule</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#8693A5</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>§ css additional-constants</string>
<key>scope</key>
<string>meta.property-value support.constant.named-color.css, meta.property-value constant</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#CA7840</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>§ css constructor.argument</string>
<key>scope</key>
<string>meta.constructor.argument.css</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#8F9D6A</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>⎇ diff.header</string>
<key>scope</key>
<string>meta.diff, meta.diff.header, meta.separator, meta.diff.range, meta.diff.index</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#0E2231</string>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#F8F8F8</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>⎇ diff.deleted</string>
<key>scope</key>
<string>markup.deleted</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#420E09</string>
<key>foreground</key>
<string>#F8F8F8</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>⎇ diff.changed</string>
<key>scope</key>
<string>markup.changed</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#4A410D</string>
<key>foreground</key>
<string>#F8F8F8</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>⎇ diff.inserted</string>
<key>scope</key>
<string>markup.inserted</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#253B22</string>
<key>foreground</key>
<string>#F8F8F8</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup: List</string>
<key>scope</key>
<string>markup.list</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#F9EE98</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup: Heading</string>
<key>scope</key>
<string>markup.heading</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#CF6A4C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup: Raw Block</string>
<key>scope</key>
<string>markup.raw.block</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#B0B3BA14</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Test: 1</string>
<key>scope</key>
<string>meta.test1</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#0E2231C5</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Test: 2</string>
<key>scope</key>
<string>meta.test2</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#420E0990</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Test: 3</string>
<key>scope</key>
<string>meta.test3</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#4A410D90</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Test: 4</string>
<key>scope</key>
<string>meta.test4</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#253B2290</string>
</dict>
</dict>
</array>
<key>uuid</key>
<string>766026CB-703D-4610-B070-8DE07D967C5F</string>
</dict>
<dict>
<key>name</key>
<string>macOS Classic Dark</string>
<key>semanticClass</key>
<string>theme.dark.mac-classic</string>
<key>settings</key>
<array>
<!-- Editor UI -->
<dict>
<key>settings</key>
<dict>
<key>background</key>
<string>#131313</string> <!-- style.background -->
<key>caret</key>
<string>#CACCCA</string> <!-- text -->
<key>foreground</key>
<string>#DDDDDD</string> <!-- editor.foreground -->
<key>invisibles</key>
<string>#9E9E9E</string> <!-- text.muted -->
<key>lineHighlight</key>
<string>#272727</string> <!-- editor.active_line.background -->
<key>selection</key>
<string>#72CFFE3D</string> <!-- players[0].selection -->
</dict>
</dict>
<!-- Attribute -->
<dict>
<key>name</key>
<string>Attribute</string>
<key>scope</key>
<string>entity.other.attribute-name</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#BE9A52</string> <!-- syntax.attribute.color -->
</dict>
</dict>
<!-- Boolean -->
<dict>
<key>name</key>
<string>Boolean</string>
<key>scope</key>
<string>constant.language.boolean, constant.numeric.boolean</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#E1D797</string> <!-- syntax.boolean.color -->
</dict>
</dict>
<!-- Comment -->
<dict>
<key>name</key>
<string>Comment</string>
<key>scope</key>
<string>comment, comment.block.documentation</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#9E9E9E</string> <!-- syntax.comment.color -->
</dict>
</dict>
<!-- Constant -->
<dict>
<key>name</key>
<string>Constant</string>
<key>scope</key>
<string>constant, constant.other, constant.language</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#E1D797</string> <!-- syntax.constant.color -->
</dict>
</dict>
<!-- Constructor -->
<dict>
<key>name</key>
<string>Constructor</string>
<key>scope</key>
<string>entity.name.function.constructor</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#b5af9a</string> <!-- syntax.constructor.color -->
</dict>
</dict>
<!-- Embedded -->
<dict>
<key>name</key>
<string>Embedded</string>
<key>scope</key>
<string>meta.embedded, text source</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#CACCCA</string> <!-- syntax.embedded.color -->
</dict>
</dict>
<!-- Function -->
<dict>
<key>name</key>
<string>Function Name</string>
<key>scope</key>
<string>entity.name.function, support.function, support.function.any-method</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#E1D797</string> <!-- syntax.function.color -->
</dict>
</dict>
<!-- Keyword -->
<dict>
<key>name</key>
<string>Keyword</string>
<key>scope</key>
<string>keyword, storage</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#E19773</string> <!-- syntax.keyword.color -->
</dict>
</dict>
<!-- Class -->
<dict>
<key>name</key>
<string>Class</string>
<key>scope</key>
<string>support.class, support.type, entity.name.class, entity.name.type.class, meta.class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#A86D3B</string> <!-- syntax.type.color variant -->
</dict>
</dict>
<!-- Link text -->
<dict>
<key>name</key>
<string>Link Text</string>
<key>scope</key>
<string>markup.underline.link, string.other.link</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#A86D3B</string> <!-- syntax.link_text.color -->
</dict>
</dict>
<!-- Link URI -->
<dict>
<key>name</key>
<string>Link URI</string>
<key>scope</key>
<string>string.other.link.title, string.other.link.description</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#6F6D66</string> <!-- syntax.link_uri.color -->
</dict>
</dict>
<!-- Number -->
<dict>
<key>name</key>
<string>Number</string>
<key>scope</key>
<string>constant.numeric</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#E19773</string> <!-- syntax.number.color -->
</dict>
</dict>
<!-- String -->
<dict>
<key>name</key>
<string>String</string>
<key>scope</key>
<string>string, string.quoted</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#76BA53</string> <!-- syntax.string.color -->
</dict>
</dict>
<!-- String Escape / Regex -->
<dict>
<key>name</key>
<string>String Escape / Regex</string>
<key>scope</key>
<string>string.escape, string.regex</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#76BA53</string> <!-- syntax.string.escape & regex -->
</dict>
</dict>
<!-- String Special -->
<dict>
<key>name</key>
<string>String Special</string>
<key>scope</key>
<string>string.special, string.special.symbol</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#E1D797</string> <!-- syntax.string.special & symbol -->
</dict>
</dict>
<!-- Tag -->
<dict>
<key>name</key>
<string>Tag</string>
<key>scope</key>
<string>meta.tag, declaration.tag</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#B5AF9A</string> <!-- syntax.tag.color -->
</dict>
</dict>
<!-- Text Literal -->
<dict>
<key>name</key>
<string>Text Literal</string>
<key>scope</key>
<string>text.literal</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#E1D797</string> <!-- syntax.text.literal.color -->
</dict>
</dict>
<!-- Title -->
<dict>
<key>name</key>
<string>Title</string>
<key>scope</key>
<string>entity.name.section, entity.name.title</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#A76D3B</string> <!-- syntax.title.color -->
</dict>
</dict>
<!-- Type -->
<dict>
<key>name</key>
<string>Type</string>
<key>scope</key>
<string>entity.name.type</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>underline</string>
<key>foreground</key>
<string>#A86D3B</string> <!-- syntax.type.color -->
</dict>
</dict>
<!-- Property -->
<dict>
<key>name</key>
<string>Property</string>
<key>scope</key>
<string>variable.other.property</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#CACCCA</string> <!-- fallback to text -->
</dict>
</dict>
<!-- Variable -->
<dict>
<key>name</key>
<string>Variable</string>
<key>scope</key>
<string>variable.language, variable.other</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#DDDDDD</string> <!-- editor.foreground -->
</dict>
</dict>
<!-- Variable Special -->
<dict>
<key>name</key>
<string>Variable Special</string>
<key>scope</key>
<string>variable.other.readwrite, variable.other.other</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#E19773</string> <!-- syntax.variable.special.color -->
</dict>
</dict>
</array>
<key>uuid</key>
<string>82d2fb7d-4049-44ec-a5b1-135fd5f7ce9f</string>
</dict>
</plist>

View file

@ -1,467 +1,325 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>author</key>
<string>Chris Thomas</string>
<key>name</key>
<string>Mac Classic</string>
<key>semanticClass</key>
<string>theme.light.mac-classic</string>
<key>settings</key>
<array>
<dict>
<key>settings</key>
<dict>
<key>background</key>
<string>#FFFFFF</string>
<key>caret</key>
<string>#000000</string>
<key>foreground</key>
<string>#000000</string>
<key>invisibles</key>
<string>#BFBFBF</string>
<key>lineHighlight</key>
<string>#00000012</string>
<key>selection</key>
<string>#4D97FF54</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Comment</string>
<key>scope</key>
<string>comment</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#0066FF</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Foldings</string>
<key>scope</key>
<string>deco.folding</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#BFBFBF</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Keyword</string>
<key>scope</key>
<string>keyword, storage</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#0000FF</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Number</string>
<key>scope</key>
<string>constant.numeric</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#0000CD</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>User-defined constant</string>
<key>scope</key>
<string>constant</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#C5060B</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Built-in constant</string>
<key>scope</key>
<string>constant.language</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#585CF6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Variable</string>
<key>scope</key>
<string>variable.language, variable.other</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#318495</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>String</string>
<key>scope</key>
<string>string</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#036A07</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>String interpolation</string>
<key>scope</key>
<string>constant.character.escape, string meta.embedded</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#26B31A</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Preprocessor line</string>
<key>scope</key>
<string>meta.preprocessor</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#1A921C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Preprocessor directive</string>
<key>scope</key>
<string>keyword.control.import</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#0C450D</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Function name</string>
<key>scope</key>
<string>entity.name.function, support.function.any-method</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#0000A2</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Type name</string>
<key>scope</key>
<string>entity.name.type</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>underline</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Inherited class name</string>
<key>scope</key>
<string>entity.other.inherited-class</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Function parameter</string>
<key>scope</key>
<string>variable.parameter</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Function argument and result types</string>
<key>scope</key>
<string>storage.type.method</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#70727E</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Section</string>
<key>scope</key>
<string>meta.section entity.name.section, declaration.section entity.name.section</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Library function</string>
<key>scope</key>
<string>support.function</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#3C4C72</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Library object</string>
<key>scope</key>
<string>support.class, support.type</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#6D79DE</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Library constant</string>
<key>scope</key>
<string>support.constant</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#06960E</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Library variable</string>
<key>scope</key>
<string>support.variable</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#21439C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>JS: Operator</string>
<key>scope</key>
<string>keyword.operator.js</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#687687</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Invalid</string>
<key>scope</key>
<string>invalid</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#990000</string>
<key>caret</key>
<string>#FFFFFF</string>
<key>foreground</key>
<string>#FFFFFF</string>
<key>selection</key>
<string>#4D97FF</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Invalid trailing whitespace</string>
<key>scope</key>
<string>invalid.deprecated.trailing-whitespace</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#FFD0D0</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Embedded source</string>
<key>scope</key>
<string>text source, string.unquoted, meta.embedded</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#0000000D</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Embedded embedded source</string>
<key>scope</key>
<string>text source string.unquoted, text source text source</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#0000000F</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup XML declaration</string>
<key>scope</key>
<string>meta.tag.preprocessor.xml</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#68685B</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup DOCTYPE</string>
<key>scope</key>
<string>meta.tag.metadata.doctype, meta.tag.metadata.doctype entity, meta.tag.metadata.doctype string, meta.tag.metadata.processing.xml, meta.tag.metadata.processing.xml entity, meta.tag.metadata.processing.xml string</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#888888</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup DTD</string>
<key>scope</key>
<string>meta.tag.metadata.doctype string.quoted</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup tag</string>
<key>scope</key>
<string>meta.tag, declaration.tag</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#1C02FF</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup name of tag</string>
<key>scope</key>
<string>entity.name.tag</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup tag attribute</string>
<key>scope</key>
<string>entity.other.attribute-name</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup: Heading</string>
<key>scope</key>
<string>markup.heading</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#0C07FF</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup: Quote</string>
<key>scope</key>
<string>markup.quote</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#000000</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup: List</string>
<key>scope</key>
<string>markup.list</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#B90690</string>
</dict>
</dict>
</array>
<key>uuid</key>
<string>71D40D9D-AE48-11D9-920A-000D93589AF6</string>
</dict>
<dict>
<key>name</key>
<string>macOS Classic Light</string>
<key>semanticClass</key>
<string>theme.light.mac-classic</string>
<key>settings</key>
<array>
<!-- Editor UI -->
<dict>
<key>settings</key>
<dict>
<key>background</key>
<string>#FFFFFF</string> <!-- style.background -->
<key>caret</key>
<string>#000000</string> <!-- text -->
<key>foreground</key>
<string>#000000</string> <!-- editor.foreground -->
<key>invisibles</key>
<string>#ACAFB1FF</string> <!-- editor.invisible -->
<key>lineHighlight</key>
<string>#F0F0F0</string> <!-- editor.active_line.background -->
<key>selection</key>
<string>#3B9EE53D</string> <!-- players[0].selection -->
</dict>
</dict>
<!-- Syntax tokens -->
<!-- Attribute -->
<dict>
<key>name</key>
<string>Attribute</string>
<key>scope</key>
<string>entity.other.attribute-name</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#957931</string> <!-- syntax.attribute.color -->
</dict>
</dict>
<!-- Boolean -->
<dict>
<key>name</key>
<string>Boolean</string>
<key>scope</key>
<string>constant.language.boolean, constant.numeric.boolean</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#C5060B</string> <!-- syntax.boolean.color -->
</dict>
</dict>
<!-- Comment -->
<dict>
<key>name</key>
<string>Comment</string>
<key>scope</key>
<string>comment, comment.block.documentation</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#007FFF</string> <!-- syntax.comment.color -->
</dict>
</dict>
<!-- Constant -->
<dict>
<key>name</key>
<string>Constant</string>
<key>scope</key>
<string>constant, constant.other</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#C5060B</string> <!-- syntax.constant.color -->
</dict>
</dict>
<!-- Constructor -->
<dict>
<key>name</key>
<string>Constructor</string>
<key>scope</key>
<string>entity.name.function.constructor</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#0433ff</string> <!-- syntax.constructor.color -->
</dict>
</dict>
<!-- Embedded -->
<dict>
<key>name</key>
<string>Embedded</string>
<key>scope</key>
<string>meta.embedded, text source</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#333333</string> <!-- syntax.embedded.color -->
</dict>
</dict>
<!-- Function -->
<dict>
<key>name</key>
<string>Function Name</string>
<key>scope</key>
<string>entity.name.function, support.function</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#0000A2</string> <!-- syntax.function.color -->
</dict>
</dict>
<!-- Keyword -->
<dict>
<key>name</key>
<string>Keyword</string>
<key>scope</key>
<string>keyword, storage</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#0433FF</string> <!-- syntax.keyword.color -->
</dict>
</dict>
<dict>
<key>name</key>
<string>Class</string>
<key>scope</key>
<string>support.class, support.type, entity.name.class, entity.name.type.class, meta.class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#6f42c1</string>
</dict>
</dict>
<!-- Link text -->
<dict>
<key>name</key>
<string>Link Text</string>
<key>scope</key>
<string>markup.underline.link, string.other.link</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#0000A2</string> <!-- syntax.link_text.color -->
</dict>
</dict>
<!-- Link URI -->
<dict>
<key>name</key>
<string>Link URI</string>
<key>scope</key>
<string>string.other.link.title, string.other.link.description</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#6A7293</string> <!-- syntax.link_uri.color -->
</dict>
</dict>
<!-- Number -->
<dict>
<key>name</key>
<string>Number</string>
<key>scope</key>
<string>constant.numeric</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#0433FF</string> <!-- syntax.number.color -->
</dict>
</dict>
<!-- String -->
<dict>
<key>name</key>
<string>String</string>
<key>scope</key>
<string>string, string.quoted</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#036A07</string> <!-- syntax.string.color -->
</dict>
</dict>
<!-- String Escape / Regex -->
<dict>
<key>name</key>
<string>String Escape / Regex</string>
<key>scope</key>
<string>string.escape, string.regex</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#036A07</string> <!-- syntax.string.escape & regex -->
</dict>
</dict>
<!-- String Special -->
<dict>
<key>name</key>
<string>String Special</string>
<key>scope</key>
<string>string.special, string.special.symbol</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#D21F07</string> <!-- syntax.string.special & symbol -->
</dict>
</dict>
<!-- Tag -->
<dict>
<key>name</key>
<string>Tag</string>
<key>scope</key>
<string>meta.tag, declaration.tag</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#0433FF</string> <!-- syntax.tag.color -->
</dict>
</dict>
<!-- Text Literal -->
<dict>
<key>name</key>
<string>Text Literal</string>
<key>scope</key>
<string>text.literal</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#6F42C1</string> <!-- syntax.text.literal.color -->
</dict>
</dict>
<!-- Title -->
<dict>
<key>name</key>
<string>Title</string>
<key>scope</key>
<string>entity.name.section, entity.name.title</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#0433FF</string> <!-- syntax.title.color -->
</dict>
</dict>
<!-- Type -->
<dict>
<key>name</key>
<string>Type</string>
<key>scope</key>
<string>entity.name.type</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>underline</string>
<key>foreground</key>
<string>#6F42C1</string> <!-- syntax.type.color -->
</dict>
</dict>
<!-- Property -->
<dict>
<key>name</key>
<string>Property</string>
<key>scope</key>
<string>variable.other.property</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#333333</string> <!-- syntax.property.color -->
</dict>
</dict>
<!-- Variable -->
<dict>
<key>name</key>
<string>Variable</string>
<key>scope</key>
<string>variable.language, variable.other</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#333333</string> <!-- syntax.variable.color -->
</dict>
</dict>
<!-- Variable Special -->
<dict>
<key>name</key>
<string>Variable Special</string>
<key>scope</key>
<string>variable.other.readwrite, variable.other.other</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#C5060B</string> <!-- syntax.variable.special.color -->
</dict>
</dict>
</array>
<key>uuid</key>
<string>511e2b3a-2aa0-4bb1-b076-e2692581380e</string>
</dict>
</plist>

View file

@ -0,0 +1,77 @@
use std::{collections::HashMap, ops::Range, rc::Rc};
use gpui::{App, HighlightStyle, SharedString, TextRun, TextStyle};
use crate::highlighter::Highlighter;
#[derive(Debug, Clone)]
pub(crate) struct LineHighlightStyle {
pub(crate) styles: Rc<Vec<(Range<usize>, HighlightStyle)>>,
}
impl LineHighlightStyle {
pub(super) fn to_run(&self, text_style: &TextStyle) -> Vec<TextRun> {
self.styles
.iter()
.map(|(range, style)| text_style.clone().highlight(*style).to_run(range.len()))
// Add last `\n` Run with len 1
.chain(std::iter::once(text_style.clone().to_run(1)))
.collect()
}
}
#[derive(Clone)]
pub(super) struct CodeHighlighter {
highlighter: Rc<Highlighter<'static>>,
pub(super) text: SharedString,
/// The lines by split \n
pub(super) lines: Vec<LineHighlightStyle>,
pub(super) cache: HashMap<u64, LineHighlightStyle>,
}
impl CodeHighlighter {
pub(super) fn new(highlighter: Rc<Highlighter<'static>>) -> Self {
Self {
highlighter,
text: SharedString::default(),
lines: vec![],
cache: HashMap::new(),
}
}
pub fn set_highlighter(&mut self, highlighter: Rc<Highlighter<'static>>, cx: &mut App) {
self.highlighter = highlighter;
self.lines.clear();
self.cache.clear();
self.update(self.text.clone(), true, cx);
}
pub fn update(&mut self, text: SharedString, force: bool, _: &mut App) {
if self.text == text && !force {
return;
}
let mut lines = vec![];
let mut new_cache = HashMap::new();
for line in text.lines() {
let cache_key = gpui::hash(&line);
// cache hit
if let Some(line_style) = self.cache.get(&cache_key) {
new_cache.insert(cache_key, line_style.clone());
lines.push(line_style.clone());
} else {
// cache miss
let styles = Rc::new(self.highlighter.highlight(line));
let line_style = LineHighlightStyle { styles };
new_cache.insert(cache_key, line_style.clone());
lines.push(line_style);
}
}
// Ensure to recreate cache to remove unused caches.
self.cache = new_cache;
self.lines = lines;
self.text = text;
}
}

View file

@ -1,16 +1,13 @@
use std::ops::Range;
use gpui::{
fill, hash, point, px, relative, size, App, Bounds, Corners, Element, ElementId,
ElementInputHandler, Entity, GlobalElementId, HighlightStyle, IntoElement, LayoutId,
MouseButton, MouseMoveEvent, PaintQuad, Path, Pixels, Point, SharedString, Style, TextAlign,
TextRun, UnderlineStyle, Window, WrappedLine,
fill, point, px, relative, size, App, Bounds, Corners, Element, ElementId, ElementInputHandler,
Entity, GlobalElementId, IntoElement, LayoutId, MouseButton, MouseMoveEvent, PaintQuad, Path,
Pixels, Point, SharedString, Style, TextAlign, TextRun, UnderlineStyle, Window, WrappedLine,
};
use smallvec::SmallVec;
use crate::{ActiveTheme as _, Root};
use super::{mode::InputMode, InputState};
use super::{code_highlighter::LineHighlightStyle, mode::InputMode, InputState};
const RIGHT_MARGIN: Pixels = px(5.);
const BOTTOM_MARGIN_ROWS: usize = 1;
@ -310,35 +307,14 @@ impl TextElement {
builder.build().ok()
}
fn highlight_text(&self, cx: &mut App) -> Option<Vec<(Range<usize>, HighlightStyle)>> {
let input = self.input.read(cx);
let text = input.text.as_ref();
let cache_key = hash(&text);
match &input.mode {
InputMode::CodeEditor {
highlighter, cache, ..
} => {
if cache.0 == cache_key {
return Some(cache.1.clone());
}
if let Some(highlighter) = highlighter {
let styles = highlighter.highlight(&text);
self.input.update(cx, |input, _cx| {
input
.mode
.set_code_editor_cache((cache_key, styles.clone()));
});
Some(styles)
} else {
None
}
fn highlight_lines(&mut self, cx: &mut App) -> Option<Vec<LineHighlightStyle>> {
self.input.update(cx, |state, cx| match &mut state.mode {
InputMode::CodeEditor { highlighter, .. } => {
highlighter.update(state.text.clone(), false, cx);
Some(highlighter.lines.clone())
}
_ => None,
}
})
}
}
@ -432,17 +408,18 @@ impl Element for TextElement {
window: &mut Window,
cx: &mut App,
) -> Self::PrepaintState {
let highlights = self.highlight_text(cx);
let highlight_lines = self.highlight_lines(cx);
let multi_line = self.input.read(cx).is_multi_line();
let line_height = window.line_height();
let input = self.input.read(cx);
let text = input.text.clone();
let is_empty = text.is_empty();
let placeholder = self.placeholder.clone();
let style = window.text_style();
let font_size = style.font_size.to_pixels(window.rem_size());
let mut bounds = bounds;
let (display_text, text_color) = if text.is_empty() {
let (display_text, text_color) = if is_empty {
(placeholder, cx.theme().muted_foreground)
} else if input.masked {
(
@ -531,22 +508,18 @@ impl Element for TextElement {
.into_iter()
.filter(|run| run.len > 0)
.collect()
} else {
if let Some(highlights) = highlights {
} else if !is_empty {
if let Some(highlight_lines) = highlight_lines {
let mut runs = vec![];
for (range, style) in highlights {
let run = text_style
.clone()
.highlight(style)
.to_run(range.end - range.start);
if run.len > 0 {
runs.push(run);
}
for style in highlight_lines {
runs.extend(style.to_run(&text_style));
}
runs
runs.into_iter().filter(|run| run.len > 0).collect()
} else {
vec![run]
}
} else {
vec![run]
};
let wrap_width = if multi_line {

View file

@ -1,6 +1,7 @@
mod blink_cursor;
mod change;
mod clear_button;
mod code_highlighter;
mod element;
mod mask_pattern;
mod mode;

View file

@ -1,10 +1,7 @@
use gpui::{DefiniteLength, HighlightStyle, SharedString};
use std::ops::Range;
use std::rc::Rc;
use gpui::{DefiniteLength, SharedString};
use super::code_highlighter::CodeHighlighter;
use super::text_wrapper::TextWrapper;
use crate::highlighter::Highlighter;
#[derive(Debug, Copy, Clone)]
pub struct TabSize {
@ -48,8 +45,7 @@ pub enum InputMode {
height: Option<DefiniteLength>,
/// Show line number
line_number: bool,
highlighter: Option<Rc<Highlighter<'static>>>,
cache: (u64, Vec<(Range<usize>, HighlightStyle)>),
highlighter: CodeHighlighter,
},
AutoGrow {
rows: usize,
@ -134,15 +130,6 @@ impl InputMode {
}
}
pub(super) fn set_code_editor_cache(
&mut self,
cache: (u64, Vec<(Range<usize>, HighlightStyle)>),
) {
if let InputMode::CodeEditor { cache: c, .. } = self {
*c = cache;
}
}
/// Return false if the mode is not [`InputMode::CodeEditor`].
#[allow(unused)]
#[inline]

View file

@ -25,6 +25,7 @@ use gpui::{
use super::{
blink_cursor::BlinkCursor,
change::Change,
code_highlighter::CodeHighlighter,
element::TextElement,
mask_pattern::MaskPattern,
mode::{InputMode, TabSize},
@ -362,12 +363,11 @@ impl InputState {
/// - Auto Indent
/// - Line Number
pub fn code_editor(mut self, language: Option<&str>, theme: &'static HighlightTheme) -> Self {
let highlighter = Highlighter::new(language, theme);
let highlighter = Rc::new(Highlighter::new(language, theme));
self.mode = InputMode::CodeEditor {
rows: 2,
tab: TabSize::default(),
highlighter: Some(Rc::new(highlighter)),
cache: (0, vec![]),
highlighter: CodeHighlighter::new(highlighter),
line_number: true,
height: Some(relative(1.)),
};
@ -433,11 +433,8 @@ impl InputState {
pub fn set_highlighter(&mut self, highlighter: Highlighter<'static>, cx: &mut Context<Self>) {
let new_highlighter = Rc::new(highlighter);
match &mut self.mode {
InputMode::CodeEditor {
highlighter, cache, ..
} => {
*highlighter = Some(new_highlighter);
*cache = (0, vec![]);
InputMode::CodeEditor { highlighter, .. } => {
highlighter.set_highlighter(new_highlighter, cx);
}
_ => {}
}

View file

@ -468,7 +468,9 @@ fn parse_paragraph(
0..text.len(),
InlineTextStyle {
link: Some(LinkMark {
url: attr_value(&attrs, local_name!("href")).unwrap().into(),
url: attr_value(&attrs, local_name!("href"))
.unwrap_or_default()
.into(),
title: attr_value(&attrs, local_name!("title")).map(Into::into),
}),
..Default::default()