From 3bd6c8fc8baff09e93f51c48ec4d36ab883de453 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 6 Feb 2024 11:33:32 +0700 Subject: [PATCH] Fix markdown to pango parse #239 --- .config/ags/lib/md2pango.js | 248 ++++++++---------------------------- 1 file changed, 51 insertions(+), 197 deletions(-) diff --git a/.config/ags/lib/md2pango.js b/.config/ags/lib/md2pango.js index f218d2b9f..dbf66505d 100644 --- a/.config/ags/lib/md2pango.js +++ b/.config/ags/lib/md2pango.js @@ -1,209 +1,62 @@ -// SPDX-FileCopyrightText: 2021 Uwe Jugel -// SPDX-License-Identifier: MIT -// This file is part of md2pango (https://github.com/ubunatic/md2pango). -// -- Modified btw -- +// Converts from Markdown to Pango. This does not support code blocks. +// For illogical-impulse, code blocks are treated separately, in their own GtkSourceView widgets. +// Partly inherited from https://github.com/ubunatic/md2pango -const monospaceFonts = 'JetBrains Mono NF, JetBrains Mono Nerd Font, JetBrains Mono NL, SpaceMono NF, SpaceMono Nerd Font, monospace' +const monospaceFonts = 'JetBrains Mono NF, JetBrains Mono Nerd Font, JetBrains Mono NL, SpaceMono NF, SpaceMono Nerd Font, monospace'; -const H1 = "H1", H2 = "H2", H3 = "H3", H4 = "H4", H5 = "H5", BULLET = "BULLET", NUMBERING = "NUMBERING", CODE = "CODE" -const BOLD = "BOLD", EMPH = "EMPH", INLCODE = "INLCODE", LINK = "LINK", HEXCOLOR = "HEXCOLOR", UND = "UND" - -let sub_h1, sub_h2, sub_h3, sub_h4, sub_h5 - -// m2p_sections defines how to detect special markdown sections. -// These expressions scan the full line to detect headings, lists, and code. -const m2p_sections = [ - sub_h1 = { name: H1, re: /^(#\s+)(.*)(\s*)$/, sub: "$2" }, - sub_h2 = { name: H2, re: /^(##\s+)(.*)(\s*)$/, sub: "$2" }, - sub_h3 = { name: H3, re: /^(###\s+)(.*)(\s*)$/, sub: "$2" }, - sub_h4 = { name: H4, re: /^(####\s+)(.*)(\s*)$/, sub: "$2" }, - sub_h5 = { name: H5, re: /^(#####\s+)(.*)(\s*)$/, sub: "$2" }, - { name: BULLET, re: /^(\s*)([\*\-]\s)(.*)(\s*)$/, sub: "$1- $3" }, - { name: NUMBERING, re: /^(\s*[0-9]+\.\s)(.*)(\s*)$/, sub: " $1- $2" }, -] - -// m2p_styles defines how to replace inline styled text -const m2p_styles = [ - { name: BOLD, re: /(\*\*)(\S[\s\S]*?\S)(\*\*)/g, sub: "$2" }, - { name: UND, re: /(__)(\S[\s\S]*?\S)(__)/g, sub: "$2" }, - { name: EMPH, re: /\*(\S.*?\S)\*/g, sub: "$1" }, - // { name: EMPH, re: /_(\S.*?\S)_/g, sub: "$1" }, - { name: HEXCOLOR, re: /#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/g, sub: ` #$1 ` }, - { name: INLCODE, re: /(`)([^`]*)(`)/g, sub: ` $2 ` }, - // { name: UND, re: /(__|\*\*)(\S[\s\S]*?\S)(__|\*\*)/g, sub: "$2" }, -] - -const re_comment = /^\s*\s*$/ -const re_color = /^(\s*\s*)$/ -const re_reset = /()/ -const re_uri = /http[s]?:\/\/[^\s']*/ -const re_href = "/href='(http[s]?:\\/\\/[^\\s]*)'" -const re_atag = ".*(http[s]?:\\/\\/[^\\s]*).*/" -const re_h1line = /^===+\s*$/ -const re_h2line = /^---+\s*$/ - -const m2p_escapes = [ - [//, ''], - [/&/g, '&'], - [//g, '>'], -] - -const code_color_span = "" - -const escape_line = (line) => m2p_escapes.reduce((l, esc) => l.replace(...esc), line) - -const pad = (lines, start = 1, end = 1) => { - let len = lines.reduce((n, l) => l.length > n ? l.length : n, 0) - return lines.map((l) => l.padEnd(len + end, ' ').padStart(len + end + start, ' ')) +const replacements = { + 'indents': [ + { name: 'BULLET', re: /^(\s*)([\*\-]\s)(.*)(\s*)$/, sub: ' $1- $3' }, + { name: 'NUMBERING', re: /^(\s*[0-9]+\.\s)(.*)(\s*)$/, sub: ' $1- $2' }, + ], + 'escapes': [ + { name: 'COMMENT', re: //, sub: '' }, + { name: 'AMPERSTAND', re: /&/g, sub: '&' }, + { name: 'LESSTHAN', re: //g, sub: '>' }, + ], + 'sections': [ + { name: 'H1', re: /^(#\s+)(.*)(\s*)$/, sub: '$2' }, + { name: 'H2', re: /^(##\s+)(.*)(\s*)$/, sub: '$2' }, + { name: 'H3', re: /^(###\s+)(.*)(\s*)$/, sub: '$2' }, + { name: 'H4', re: /^(####\s+)(.*)(\s*)$/, sub: '$2' }, + { name: 'H5', re: /^(#####\s+)(.*)(\s*)$/, sub: '$2' }, + ], + 'styles': [ + { name: 'BOLD', re: /(\*\*)(\S[\s\S]*?\S)(\*\*)/g, sub: "$2" }, + { name: 'UND', re: /(__)(\S[\s\S]*?\S)(__)/g, sub: "$2" }, + { name: 'EMPH', re: /\*(\S.*?\S)\*/g, sub: "$1" }, + // { name: 'EMPH', re: /_(\S.*?\S)_/g, sub: "$1" }, + { name: 'HEXCOLOR', re: /#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/g, sub: '#$1' }, + { name: 'INLCODE', re: /(`)([^`]*)(`)/g, sub: '$2' }, + // { name: 'UND', re: /(__|\*\*)(\S[\s\S]*?\S)(__|\*\*)/g, sub: "$2" }, + ], } +const replaceCategory = (text, replaces) => { + for (const type of replaces) { + text = text.replace(type.re, type.sub); + } + return text; +} + +// Main function + export default (text) => { let lines = text.split('\n') - - // Indicates if the current line is within a code block - let is_code = false - let code_lines = [] - - let output = [] - let color_span_open = false - let tt_must_close = false - - const try_close_span = () => { - if (color_span_open) { - output.push('') - color_span_open = false - } - } - - const try_open_span = () => { - if (!color_span_open) { - output.push('') - color_span_open = false - } - } - + let output = []; + // Replace for (const line of lines) { - // first parse color macros in non-code texts - if (!is_code) { - let colors = line.match(re_color) - if (colors || line.match(re_reset)) { - try_close_span() - } - - if (colors) { - try_close_span() - if (color_span_open) { - close_span() - } - - let fg = colors[2] == 'fg' ? colors[3] : colors[5] == 'fg' ? colors[6] : '' - let bg = colors[2] == 'bg' ? colors[3] : colors[5] == 'bg' ? colors[6] : '' - let attrs = '' - - if (fg != '') { - attrs += ` foreground='${fg}'` - } - - if (bg != '') { - attrs += ` background='${bg}'` - } - - if (attrs != '') { - output.push(``) - color_span_open = true - } - } - } - - // all macros processed, let's remove remaining comments - if (line.match(re_comment)) { - continue - } - - // is this line an opening statement of a code block - let code_start = false - - // escape all non-verbatim text - let result = is_code ? line : escape_line(line) - - for (const { name, re, sub } of m2p_sections) { - if (line.match(re)) { - if (name === CODE) { - if (!is_code) { - // haven't been inside a code block, so ``` indicates - // that it is starting now - code_start = true - is_code = true - - if (color_span_open) { - // cannot color - result = '' - tt_must_close = false - } else { - result = code_color_span + '' - tt_must_close = true - } - } else { - // the code block ends now - is_code = false - output.push(...pad(code_lines).map(escape_line)) - code_lines = [] - result = '' - if (tt_must_close) { - result += '' - tt_must_close = false - } - } - } else { - if (is_code) { - result = line - } else { - result = line.replace(re, sub) - } - } - } - } - - if (is_code && !code_start) { - code_lines.push(result) - continue - } - - if (line.match(re_h1line)) { - output.push(`# ${output.pop()}`.replace(sub_h1.re, sub_h1.sub)) - continue - } - - if (line.match(re_h2line)) { - output.push(`## ${output.pop()}`.replace(sub_h2.re, sub_h2.sub)) - continue - } - - // all other text can be styled - for (const style of m2p_styles) { - result = result.replace(style.re, style.sub) - } - - // all raw urls can be linked if possible - let uri = result.match(re_uri) // look for any URI - let href = result.match(re_href) // and for URIs in href='' - let atag = result.match(re_atag) // and for URIs in - href = href && href[1] == uri - atag = href && atag[1] == uri - if (uri && (href || atag)) { - result = result.replace(uri, `${uri}`) - } - + let result = line; + result = replaceCategory(result, replacements.indents); + result = replaceCategory(result, replacements.escapes); + result = replaceCategory(result, replacements.sections); + result = replaceCategory(result, replacements.styles); output.push(result) } - - try_close_span() - - // remove trailing whitespaces + // Remove trailing whitespaces output = output.map(line => line.replace(/ +$/, '')) - - return output.join('\n') + return output.join('\n'); } export const markdownTest = `# Heading 1 @@ -228,5 +81,6 @@ export const markdownTest = `# Heading 1 myArray = [23, 123, 43, 54, '6969']; console.log('uwu'); \`\`\` -To update arch lincox, run \`sudo pacman -Syu\` +- Random instruction thing + - To update arch lincox, run \`sudo pacman -Syu\` `; \ No newline at end of file