From bf8ca73c32ffbda8612492bab8c223dae68deb9b Mon Sep 17 00:00:00 2001 From: Stefal Date: Tue, 28 Jan 2025 23:26:49 +0100 Subject: [PATCH] Convert markdown to html in changelog list (inside update modal windows) --- CHANGELOG.md | 1 + web_app/static/lib/snarkdown.js | 2 ++ web_app/static/lib/snarkdown.js.map | 1 + web_app/static/settings.js | 13 ++++++++----- web_app/templates/settings.html | 1 + 5 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 web_app/static/lib/snarkdown.js create mode 100644 web_app/static/lib/snarkdown.js.map diff --git a/CHANGELOG.md b/CHANGELOG.md index a1fd6c03..d36a3e87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Detect Gnss receiver firmware version during receiver detection. [#428](https://github.com/Stefal/rtkbase/issues/428) - GUI -> Logs: Non-zipped files can be convert to rinex. [#348](https://github.com/Stefal/rtkbase/issues/348) - GUI -> Settings: Display network informations. +- GUI -> Settings: Better changelog display (Convert markdown to html). ### Changed - Faster Septentrio Mosaic-X5 detection ### Fixed diff --git a/web_app/static/lib/snarkdown.js b/web_app/static/lib/snarkdown.js new file mode 100644 index 00000000..5da38179 --- /dev/null +++ b/web_app/static/lib/snarkdown.js @@ -0,0 +1,2 @@ +!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):e.snarkdown=n()}(this,function(){function e(e){return e.replace(RegExp("^"+(e.match(/^(\t| )+/)||"")[0],"gm"),"")}function n(e){return(e+"").replace(/"/g,""").replace(//g,">")}function r(o){function c(e){var n=t[e.replace(/\*/g,"_")[1]||""],r=f[f.length-1]==e;return n?n[1]?(f[r?"pop":"push"](e),n[0|r]):n[0]:e}function a(){for(var e="";f.length;)e+=c(f[f.length-1]);return e}var l,u,p,s,g,i=/((?:^|\n+)(?:\n---+|\* \*(?: \*)+)\n)|(?:^```(\w*)\n([\s\S]*?)\n```$)|((?:(?:^|\n+)(?:\t| {2,}).+)+\n*)|((?:(?:^|\n)([>*+-]|\d+\.)\s+.*)+)|(?:\!\[([^\]]*?)\]\(([^\)]+?)\))|(\[)|(\](?:\(([^\)]+?)\))?)|(?:(?:^|\n+)([^\s].*)\n(\-{3,}|={3,})(?:\n+|$))|(?:(?:^|\n+)(#{1,3})\s*(.+)(?:\n+|$))|(?:`([^`].*?)`)|( \n\n*|\n{2,}|__|\*\*|[_*])/gm,f=[],m="",d=0,h={};for(o=o.replace(/^\[(.+?)\]:\s*(.+)$/gm,function(e,n,r){return h[n.toLowerCase()]=r,""}).replace(/^\n+|\n+$/g,"");p=i.exec(o);)u=o.substring(d,p.index),d=i.lastIndex,l=p[0],u.match(/[^\\](\\\\)*\\$/)||(p[3]||p[4]?l='
'+e(n(p[3]||p[4]).replace(/^\n+|\n+$/g,""))+"
":p[6]?(g=p[6],g.match(/\./)&&(p[5]=p[5].replace(/^\d+/gm,"")),s=r(e(p[5].replace(/^\s*[>*+.-]/gm,""))),">"===g?g="blockquote":(g=g.match(/\./)?"ol":"ul",s=s.replace(/^(.*)(\n|$)/gm,"
  • $1
  • ")),l="<"+g+">"+s+""):p[8]?l=''+n(p[7])+'':p[10]?(m=m.replace("",''),l=a()+""):p[9]?l="":p[12]||p[14]?(g="h"+(p[14]?p[14].length:"="===p[13][0]?1:2),l="<"+g+">"+r(p[12]||p[15])+""):p[16]?l=""+n(p[16])+"":(p[17]||p[1])&&(l=c(p[17]||"--"))),m+=u,m+=l;return(m+o.substring(d)+a()).trim()}var t={"":["",""],_:["",""],"\n":["
    "]," ":["
    "],"-":["
    "]};return r}); +//# sourceMappingURL=snarkdown.umd.js.map \ No newline at end of file diff --git a/web_app/static/lib/snarkdown.js.map b/web_app/static/lib/snarkdown.js.map new file mode 100644 index 00000000..45b0f2bf --- /dev/null +++ b/web_app/static/lib/snarkdown.js.map @@ -0,0 +1 @@ +{"version":3,"file":"snarkdown.umd.js","sources":["../src/index.js"],"sourcesContent":["const TAGS = {\n\t'': ['',''],\n\t_: ['',''],\n\t'*': ['',''],\n\t'~': ['',''],\n\t'\\n': ['
    '],\n\t' ': ['
    '],\n\t'-': ['
    ']\n};\n\n/** Outdent a string based on the first indented line's leading whitespace\n *\t@private\n */\nfunction outdent(str) {\n\treturn str.replace(RegExp('^'+(str.match(/^(\\t| )+/) || '')[0], 'gm'), '');\n}\n\n/** Encode special attribute characters to HTML entities in a String.\n *\t@private\n */\nfunction encodeAttr(str) {\n\treturn (str+'').replace(/\"/g, '"').replace(//g, '>');\n}\n\n/** Parse Markdown into an HTML String. */\nexport default function parse(md, prevLinks) {\n\tlet tokenizer = /((?:^|\\n+)(?:\\n---+|\\* \\*(?: \\*)+)\\n)|(?:^``` *(\\w*)\\n([\\s\\S]*?)\\n```$)|((?:(?:^|\\n+)(?:\\t| {2,}).+)+\\n*)|((?:(?:^|\\n)([>*+-]|\\d+\\.)\\s+.*)+)|(?:!\\[([^\\]]*?)\\]\\(([^)]+?)\\))|(\\[)|(\\](?:\\(([^)]+?)\\))?)|(?:(?:^|\\n+)([^\\s].*)\\n(-{3,}|={3,})(?:\\n+|$))|(?:(?:^|\\n+)(#{1,6})\\s*(.+)(?:\\n+|$))|(?:`([^`].*?)`)|( \\n\\n*|\\n{2,}|__|\\*\\*|[_*]|~~)/gm,\n\t\tcontext = [],\n\t\tout = '',\n\t\tlinks = prevLinks || {},\n\t\tlast = 0,\n\t\tchunk, prev, token, inner, t;\n\n\tfunction tag(token) {\n\t\tlet desc = TAGS[token[1] || ''];\n\t\tlet end = context[context.length-1] == token;\n\t\tif (!desc) return token;\n\t\tif (!desc[1]) return desc[0];\n\t\tif (end) context.pop();\n\t\telse context.push(token);\n\t\treturn desc[end|0];\n\t}\n\n\tfunction flush() {\n\t\tlet str = '';\n\t\twhile (context.length) str += tag(context[context.length-1]);\n\t\treturn str;\n\t}\n\n\tmd = md.replace(/^\\[(.+?)\\]:\\s*(.+)$/gm, (s, name, url) => {\n\t\tlinks[name.toLowerCase()] = url;\n\t\treturn '';\n\t}).replace(/^\\n+|\\n+$/g, '');\n\n\twhile ( (token=tokenizer.exec(md)) ) {\n\t\tprev = md.substring(last, token.index);\n\t\tlast = tokenizer.lastIndex;\n\t\tchunk = token[0];\n\t\tif (prev.match(/[^\\\\](\\\\\\\\)*\\\\$/)) {\n\t\t\t// escaped\n\t\t}\n\t\t// Code/Indent blocks:\n\t\telse if (t = (token[3] || token[4])) {\n\t\t\tchunk = '
    '+outdent(encodeAttr(t).replace(/^\\n+|\\n+$/g, ''))+'
    ';\n\t\t}\n\t\t// > Quotes, -* lists:\n\t\telse if (t = token[6]) {\n\t\t\tif (t.match(/\\./)) {\n\t\t\t\ttoken[5] = token[5].replace(/^\\d+/gm, '');\n\t\t\t}\n\t\t\tinner = parse(outdent(token[5].replace(/^\\s*[>*+.-]/gm, '')));\n\t\t\tif (t=='>') t = 'blockquote';\n\t\t\telse {\n\t\t\t\tt = t.match(/\\./) ? 'ol' : 'ul';\n\t\t\t\tinner = inner.replace(/^(.*)(\\n|$)/gm, '
  • $1
  • ');\n\t\t\t}\n\t\t\tchunk = '<'+t+'>' + inner + '';\n\t\t}\n\t\t// Images:\n\t\telse if (token[8]) {\n\t\t\tchunk = `\"${encodeAttr(token[7])}\"`;\n\t\t}\n\t\t// Links:\n\t\telse if (token[10]) {\n\t\t\tout = out.replace('
    ', ``);\n\t\t\tchunk = flush() + '';\n\t\t}\n\t\telse if (token[9]) {\n\t\t\tchunk = '';\n\t\t}\n\t\t// Headings:\n\t\telse if (token[12] || token[14]) {\n\t\t\tt = 'h' + (token[14] ? token[14].length : (token[13]>'=' ? 1 : 2));\n\t\t\tchunk = '<'+t+'>' + parse(token[12] || token[15], links) + '';\n\t\t}\n\t\t// `code`:\n\t\telse if (token[16]) {\n\t\t\tchunk = ''+encodeAttr(token[16])+'';\n\t\t}\n\t\t// Inline formatting: *em*, **strong** & friends\n\t\telse if (token[17] || token[1]) {\n\t\t\tchunk = tag(token[17] || '--');\n\t\t}\n\t\tout += prev;\n\t\tout += chunk;\n\t}\n\n\treturn (out + md.substring(last) + flush()).replace(/^\\n+|\\n+$/g, '');\n}\n"],"names":["TAGS","_","*","~","\n"," ","-","outdent","str","replace","RegExp","match","encodeAttr","parse","md","prevLinks","chunk","prev","token","inner","t","tokenizer","context","out","links","last","tag","desc","end","length","pop","push","flush","s","name","url","toLowerCase","exec","substring","index","lastIndex"],"mappings":"kLAAA,IAAMA,EAAO,CACZ,GAAI,CAAC,OAAO,SACZC,EAAG,CAAC,WAAW,aACfC,IAAK,CAAC,WAAW,aACjBC,IAAK,CAAC,MAAM,QACZC,KAAM,CAAC,UACPC,IAAK,CAAC,UACNC,IAAK,CAAC,WAMP,SAASC,EAAQC,GAChB,OAAOA,EAAIC,QAAQC,OAAO,KAAKF,EAAIG,MAAM,aAAe,IAAI,GAAI,MAAO,IAMxE,SAASC,EAAWJ,GACnB,OAAQA,EAAI,IAAIC,QAAQ,KAAM,UAAUA,QAAQ,KAAM,QAAQA,QAAQ,KAAM,wBAIrDI,EAAMC,EAAIC,GACjC,IAKCC,EAAOC,EAAMC,EAAOC,EAAOC,EALxBC,EAAY,kVACfC,EAAU,GACVC,EAAM,GACNC,EAAQT,GAAa,GACrBU,EAAO,EAGR,SAASC,EAAIR,GACZ,IAAIS,EAAO3B,EAAKkB,EAAM,IAAM,IACxBU,EAAMN,EAAQA,EAAQO,OAAO,IAAMX,EACvC,OAAKS,EACAA,EAAK,IACNC,EAAKN,EAAQQ,MACZR,EAAQS,KAAKb,GACXS,EAAS,EAAJC,IAHSD,EAAK,GADRT,EAOnB,SAASc,IAER,IADA,IAAIxB,EAAM,GACHc,EAAQO,QAAQrB,GAAOkB,EAAIJ,EAAQA,EAAQO,OAAO,IACzD,OAAOrB,EAQR,IALAM,EAAKA,EAAGL,QAAQ,wBAAyB,SAACwB,EAAGC,EAAMC,GAElD,OADAX,EAAMU,EAAKE,eAAiBD,EACrB,KACL1B,QAAQ,aAAc,IAEhBS,EAAMG,EAAUgB,KAAKvB,IAC7BG,EAAOH,EAAGwB,UAAUb,EAAMP,EAAMqB,OAChCd,EAAOJ,EAAUmB,UACjBxB,EAAQE,EAAM,GACVD,EAAKN,MAAM,sBAINS,EAAKF,EAAM,IAAMA,EAAM,IAC/BF,EAAQ,qBAAqBE,EAAM,GAAG,SAASA,EAAM,GAAGkB,eAAe,WAAWlB,EAAM,uBAAyBA,EAAM,GAAGkB,kBAAmB,IAAI,IAAI7B,EAAQK,EAAWQ,GAAGX,QAAQ,aAAc,KAAK,iBAG9LW,EAAIF,EAAM,KACdE,EAAET,MAAM,QACXO,EAAM,GAAKA,EAAM,GAAGT,QAAQ,SAAU,KAEvCU,EAAQN,EAAMN,EAAQW,EAAM,GAAGT,QAAQ,gBAAiB,MACjD,KAAHW,EAAQA,EAAI,cAEfA,EAAIA,EAAET,MAAM,MAAQ,KAAO,KAC3BQ,EAAQA,EAAMV,QAAQ,gBAAiB,gBAExCO,EAAQ,IAAII,EAAE,IAAMD,EAAQ,KAAKC,EAAE,KAG3BF,EAAM,GACdF,eAAqBJ,EAAWM,EAAM,cAAaN,EAAWM,EAAM,SAG5DA,EAAM,KACdK,EAAMA,EAAId,QAAQ,kBAAmBG,EAAWM,EAAM,KAAOM,EAAMP,EAAKmB,sBACxEpB,EAAQgB,IAAU,QAEVd,EAAM,GACdF,EAAQ,MAGAE,EAAM,KAAOA,EAAM,IAE3BF,EAAQ,KADRI,EAAI,KAAOF,EAAM,IAAMA,EAAM,IAAIW,OAAUX,EAAM,IAAI,IAAM,EAAI,IACjD,IAAML,EAAMK,EAAM,KAAOA,EAAM,IAAKM,GAAS,KAAKJ,EAAE,IAG1DF,EAAM,IACdF,EAAQ,SAASJ,EAAWM,EAAM,KAAK,WAG/BA,EAAM,KAAOA,EAAM,MAC3BF,EAAQU,EAAIR,EAAM,KAAO,QAE1BK,GAAON,EACPM,GAAOP,EAGR,OAAQO,EAAMT,EAAGwB,UAAUb,GAAQO,KAASvB,QAAQ,aAAc"} \ No newline at end of file diff --git a/web_app/static/settings.js b/web_app/static/settings.js index 27739b67..9c33cb56 100644 --- a/web_app/static/settings.js +++ b/web_app/static/settings.js @@ -426,11 +426,14 @@ $(document).ready(function () { }else if (response.new_release) { $("#updateModal .modal-title").text("Update available!"); $("#updateModal .modal-body").append('

    Do you want to install RTKBase ' + response['new_release'] +'?
    It will take a few minutes.

    '); - var newFeaturesArray = response['comment'].split('\r\n'); - $("#updateModal .modal-body").append('

    '); - $.each( newFeaturesArray, function( index, value ){ - $("#newFeatures").append("
  • " + value.replace(/^\+ /g, "") + "
  • "); - }); + $("#updateModal .modal-body").append('

    '); + var markdwnHtml = snarkdown(response['comment']); + //lower title tags values + markdwnHtml= markdwnHtml.replace(/(.*?)<\/h\1>/gi, (match, p1, p2, p3) => { + const newHtag = Math.min(parseInt(p1) + 3, 6); + return `${p3}`; + }); + $("#newFeatures").append('

    ' + markdwnHtml + '

    '); $("#start-update-button").removeAttr("disabled"); $("#updateModal").modal(); } else { diff --git a/web_app/templates/settings.html b/web_app/templates/settings.html index 83450e7e..3226d8de 100644 --- a/web_app/templates/settings.html +++ b/web_app/templates/settings.html @@ -790,5 +790,6 @@ {% block scripts %} {{super()}} + {% endblock %} \ No newline at end of file