Make dashboard updateable
This commit is contained in:
182
markdown_editor_highlight.go
Normal file
182
markdown_editor_highlight.go
Normal file
@@ -0,0 +1,182 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/alecthomas/chroma/v2"
|
||||
"github.com/alecthomas/chroma/v2/lexers"
|
||||
)
|
||||
|
||||
type editorMarkdownStyle uint8
|
||||
|
||||
const (
|
||||
editorMarkdownPlain editorMarkdownStyle = iota
|
||||
editorMarkdownHeading
|
||||
editorMarkdownStrong
|
||||
editorMarkdownEmphasis
|
||||
editorMarkdownCode
|
||||
editorMarkdownLink
|
||||
editorMarkdownDestination
|
||||
editorMarkdownQuote
|
||||
editorMarkdownComment
|
||||
)
|
||||
|
||||
func editorMarkdownStyles(value string) []editorMarkdownStyle {
|
||||
runes := []rune(value)
|
||||
styles := make([]editorMarkdownStyle, len(runes))
|
||||
lexer := lexers.Get("markdown")
|
||||
if lexer == nil {
|
||||
highlightEditorHTMLComments(runes, styles)
|
||||
return styles
|
||||
}
|
||||
tokens, err := chroma.Tokenise(lexer, nil, value)
|
||||
if err != nil {
|
||||
highlightEditorHTMLComments(runes, styles)
|
||||
return styles
|
||||
}
|
||||
offset := 0
|
||||
for _, token := range tokens {
|
||||
style := editorMarkdownStyleForToken(token.Type)
|
||||
for range []rune(token.Value) {
|
||||
if offset >= len(styles) {
|
||||
return styles
|
||||
}
|
||||
styles[offset] = style
|
||||
offset++
|
||||
}
|
||||
}
|
||||
highlightEditorHTMLComments(runes, styles)
|
||||
return styles
|
||||
}
|
||||
|
||||
func highlightEditorHTMLComments(runes []rune, styles []editorMarkdownStyle) {
|
||||
startMarker, endMarker := []rune("<!--"), []rune("-->")
|
||||
for offset := 0; offset < len(runes); {
|
||||
start := findEditorRunes(runes, startMarker, offset)
|
||||
if start < 0 {
|
||||
return
|
||||
}
|
||||
end := findEditorRunes(runes, endMarker, start+len(startMarker))
|
||||
if end < 0 {
|
||||
end = len(runes)
|
||||
} else {
|
||||
end += len(endMarker)
|
||||
}
|
||||
for index := start; index < end; index++ {
|
||||
styles[index] = editorMarkdownComment
|
||||
}
|
||||
offset = end
|
||||
}
|
||||
}
|
||||
|
||||
func findEditorRunes(value, target []rune, offset int) int {
|
||||
for index := max(0, offset); index+len(target) <= len(value); index++ {
|
||||
matches := true
|
||||
for targetIndex := range target {
|
||||
if value[index+targetIndex] != target[targetIndex] {
|
||||
matches = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if matches {
|
||||
return index
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func editorMarkdownStyleForToken(token chroma.TokenType) editorMarkdownStyle {
|
||||
switch {
|
||||
case token == chroma.GenericHeading || token == chroma.GenericSubheading:
|
||||
return editorMarkdownHeading
|
||||
case token == chroma.GenericStrong:
|
||||
return editorMarkdownStrong
|
||||
case token == chroma.GenericEmph:
|
||||
return editorMarkdownEmphasis
|
||||
case token == chroma.LiteralStringBacktick:
|
||||
return editorMarkdownCode
|
||||
case token == chroma.NameTag:
|
||||
return editorMarkdownLink
|
||||
case token == chroma.NameAttribute:
|
||||
return editorMarkdownDestination
|
||||
case token == chroma.Keyword:
|
||||
return editorMarkdownQuote
|
||||
case token.InSubCategory(chroma.Comment):
|
||||
return editorMarkdownComment
|
||||
default:
|
||||
return editorMarkdownPlain
|
||||
}
|
||||
}
|
||||
|
||||
func editorMarkdownStyleStart(style editorMarkdownStyle) string {
|
||||
if style == editorMarkdownPlain {
|
||||
return ""
|
||||
}
|
||||
if currentThemeName == "no-color" {
|
||||
switch style {
|
||||
case editorMarkdownHeading, editorMarkdownStrong:
|
||||
return "\x1b[1m"
|
||||
case editorMarkdownEmphasis:
|
||||
return "\x1b[3m"
|
||||
case editorMarkdownLink:
|
||||
return "\x1b[4m"
|
||||
case editorMarkdownComment:
|
||||
return "\x1b[2m"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
if currentThemeName == "light" {
|
||||
switch style {
|
||||
case editorMarkdownHeading:
|
||||
return "\x1b[1;38;2;154;103;0m"
|
||||
case editorMarkdownStrong:
|
||||
return "\x1b[1;38;2;130;80;223m"
|
||||
case editorMarkdownEmphasis:
|
||||
return "\x1b[3;38;2;87;96;106m"
|
||||
case editorMarkdownCode:
|
||||
return "\x1b[38;2;17;99;41m"
|
||||
case editorMarkdownLink:
|
||||
return "\x1b[4;38;2;9;105;218m"
|
||||
case editorMarkdownDestination:
|
||||
return "\x1b[38;2;10;112;111m"
|
||||
case editorMarkdownQuote:
|
||||
return "\x1b[38;2;154;103;0m"
|
||||
case editorMarkdownComment:
|
||||
return "\x1b[2;38;2;101;109;118m"
|
||||
}
|
||||
}
|
||||
switch style {
|
||||
case editorMarkdownHeading:
|
||||
return "\x1b[1;38;2;240;183;47m"
|
||||
case editorMarkdownStrong:
|
||||
return "\x1b[1;38;2;198;120;221m"
|
||||
case editorMarkdownEmphasis:
|
||||
return "\x1b[3;38;2;215;218;232m"
|
||||
case editorMarkdownCode:
|
||||
return "\x1b[38;2;152;195;121m"
|
||||
case editorMarkdownLink:
|
||||
return "\x1b[4;38;2;97;175;239m"
|
||||
case editorMarkdownDestination:
|
||||
return "\x1b[38;2;86;182;194m"
|
||||
case editorMarkdownQuote:
|
||||
return "\x1b[38;2;229;192;123m"
|
||||
case editorMarkdownComment:
|
||||
return "\x1b[2;38;2;119;119;119m"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func editorMarkdownStyleEnd(active bool) string {
|
||||
foreground := "\x1b[39m"
|
||||
if active {
|
||||
switch currentThemeName {
|
||||
case "dark":
|
||||
foreground = "\x1b[38;2;215;218;232m"
|
||||
case "light":
|
||||
foreground = "\x1b[38;2;36;41;47m"
|
||||
case "high-contrast":
|
||||
foreground = "\x1b[38;2;255;255;255m"
|
||||
}
|
||||
}
|
||||
return "\x1b[22;23;24m" + foreground
|
||||
}
|
||||
Reference in New Issue
Block a user