RibbonMarkDownView: improve performance and add mermaid support.

This commit is contained in:
Mentalflow 2024-03-17 03:17:13 +08:00
parent 138b233365
commit 4992e61376
Signed by: Mentalflow
GPG Key ID: 5AE68D4401A2EE71
19 changed files with 224391 additions and 152 deletions

View File

@ -5,7 +5,7 @@
<h1 align="center"> ProtocolParser 协议解析器 V1.0.4</h1> <h1 align="center"> ProtocolParser 协议解析器 V1.0.4</h1>
## 一、介绍 ## 一、介绍
这是一个用于与DKY的THM3682实验箱搭配使用的上位机协议解析器具体如何使用请看[使用说明](#使用说明)。 这是一个用于与DKY的THM3682实验箱搭配使用的上位机协议解析器具体如何使用请看[使用说明](#使用说明)。
<div align="center"> <div align="center">
<div align="center"> <div align="center">
<img src="documents/pictures/home-light.png" alt="主界面(浅色)" style="width:45%; height:auto;"> <img src="documents/pictures/home-light.png" alt="主界面(浅色)" style="width:45%; height:auto;">
@ -14,7 +14,7 @@
<p align="center"> 主界面(浅色/深色模式) </p> <p align="center"> 主界面(浅色/深色模式) </p>
</div> </div>
## 二、使用说明 ## <div id = "使用说明">二、使用说明<div>
## 1. [协议解析](documents/protocol.md) ## 1. [协议解析](documents/protocol.md)
+ 概述 + 概述
+ 密钥 + 密钥

View File

@ -4,6 +4,7 @@ project(ProtocolParser VERSION ${CMAKE_PROJECT_VERSION} LANGUAGES CXX)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(QT_VERSION VERSION_GREATER_EQUAL "6.3") if(QT_VERSION VERSION_GREATER_EQUAL "6.3")
qt_standard_project_setup() qt_standard_project_setup()
qt_policy(SET QTP0001 NEW) qt_policy(SET QTP0001 NEW)
@ -53,12 +54,14 @@ set(
set(js_files js/markdown-it.js js/markdown-it-deflist.js js/markdown-it-emoji.js set(js_files js/markdown-it.js js/markdown-it-deflist.js js/markdown-it-emoji.js
js/markdown-it-sub.js js/markdown-it-abbr.js js/markdown-it-container.js js/markdown-it-footnote.js js/markdown-it-sub.js js/markdown-it-abbr.js js/markdown-it-container.js js/markdown-it-footnote.js
js/markdown-it-ins.js js/markdown-it-mark.js js/markdown-it-sup.js js/prism.js js/markdown-it-ins.js js/markdown-it-mark.js js/markdown-it-sup.js
js/jquery.js js/mermaid.js_packaged js/highlight.js
) )
set(doc_files ${CMAKE_SOURCE_DIR}/documents/menu.md ${CMAKE_SOURCE_DIR}/documents/protocol.md set(doc_files ${CMAKE_SOURCE_DIR}/README.md ${CMAKE_SOURCE_DIR}/documents/protocol.md
${CMAKE_SOURCE_DIR}/documents/serialport.md ${CMAKE_SOURCE_DIR}/documents/zigbee.md ${CMAKE_SOURCE_DIR}/documents/serialport.md ${CMAKE_SOURCE_DIR}/documents/zigbee.md
${CMAKE_SOURCE_DIR}/documents/others.md ${CMAKE_SOURCE_DIR}/documents/others.md ${CMAKE_SOURCE_DIR}/documents/pictures/home-dark.png
${CMAKE_SOURCE_DIR}/documents/pictures/home-light.png ${CMAKE_SOURCE_DIR}/app_source/resources/imgs/icon.png
) )
INCLUDE_DIRECTORIES(dlln3x include) INCLUDE_DIRECTORIES(dlln3x include)
@ -123,7 +126,7 @@ qt_add_qml_module(${PROJECT_NAME}
URI ${PROJECT_NAME} URI ${PROJECT_NAME}
QML_FILES ${qml_files} QML_FILES ${qml_files}
RESOURCE_PREFIX "/qt/qml/" RESOURCE_PREFIX "/qt/qml/"
RESOURCES ${js_files} ${doc_files} resources/theme.css resources/default.css resources/prism-light.css resources/prism-dark.css RESOURCES ${js_files} ${doc_files} resources/theme.css resources/default.css resources/github-light.css resources/github-dark.css
VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR} VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}
) )

View File

@ -4,6 +4,7 @@
#include <QObject> #include <QObject>
#include <QQmlEngine> #include <QQmlEngine>
#include <QQuickTextDocument> #include <QQuickTextDocument>
#include "../3rdparty/RibbonUI/lib_source/definitions.h"
class Tools : public QObject class Tools : public QObject
{ {
@ -11,6 +12,7 @@ class Tools : public QObject
QML_ELEMENT QML_ELEMENT
QML_SINGLETON QML_SINGLETON
QML_NAMED_ELEMENT(Tools) QML_NAMED_ELEMENT(Tools)
Q_PROPERTY_RW(QString, baseDir)
public: public:
static Tools* instance(); static Tools* instance();
static Tools* create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return instance();} static Tools* create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return instance();}
@ -19,9 +21,12 @@ public:
Q_INVOKABLE void setBaseUrl(QQuickTextDocument *qd, QUrl url); Q_INVOKABLE void setBaseUrl(QQuickTextDocument *qd, QUrl url);
Q_INVOKABLE QString fileSuffix(const QString &filePath); Q_INVOKABLE QString fileSuffix(const QString &filePath);
Q_INVOKABLE QString fileDir(const QString &filePath); Q_INVOKABLE QString fileDir(const QString &filePath);
Q_INVOKABLE void writeDirtoTempDir(QString path);
Q_INVOKABLE void writeFiletoDir(QString content, QString path, QString name);
private: private:
explicit Tools(QObject *parent = nullptr); explicit Tools(QObject *parent = nullptr);
~Tools();
Q_DISABLE_COPY_MOVE(Tools) Q_DISABLE_COPY_MOVE(Tools)
signals: signals:

17471
app_source/js/highlight.js Normal file

File diff suppressed because it is too large Load Diff

10716
app_source/js/jquery.js vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -56,7 +56,7 @@ RibbonWindow {
anchors{ anchors{
left: parent.left left: parent.left
right: parent.right right: parent.right
bottom: parent.bottom bottom: center_view.bottom
} }
} }

View File

@ -185,7 +185,7 @@ Item {
} }
} }
RibbonToolTip{ RibbonToolTip{
text: qsTr('类型:')+ qsTr(`${bg.type}, `) + qsTr('长度:') + `${bg.data_size}B` text: qsTr('类型:')+ `${bg.type}, ` + qsTr('长度:') + `${bg.data_size}B`
visible: text && mouse.containsMouse visible: text && mouse.containsMouse
} }

View File

@ -7,9 +7,10 @@ import "."
Item { Item {
id:root id:root
implicitHeight: 500 implicitHeight: 550
implicitWidth: 500 implicitWidth: 550
property string title: qsTr("帮助") property string title: qsTr("帮助")
Component.onCompleted: Tools.writeDirtoTempDir(":/qt/qml/ProtocolParser/")
RibbonButton{ RibbonButton{
anchors{ anchors{
@ -35,8 +36,9 @@ Item {
RibbonMarkDownViewer{ RibbonMarkDownViewer{
id: viewer id: viewer
anchors.fill: parent anchors.fill: parent
text: Tools.readAll(':/qt/qml/ProtocolParser/documents/menu.md') file_name: 'qrc:/qt/qml/ProtocolParser/README.md'
base_url: 'qrc:/qt/qml/ProtocolParser/documents/' base_url: 'qrc:/qt/qml/ProtocolParser/'
resource_dir: Tools.baseDir
} }
RibbonButton{ RibbonButton{

View File

@ -15,13 +15,15 @@ import "qrc:/qt/qml/ProtocolParser/markdown-it-mark.js" as MarkdownItMark
Item { Item {
id:root id:root
property string text: "" property string file_name: ""
property string base_url: "" property string base_url: ""
property string current_path: ""
property string resource_dir: ""
property int page_height: 0 property int page_height: 0
property alias can_goback: viewer.canGoBack property alias can_goback: viewer.canGoBack
property alias can_goforward: viewer.canGoForward property alias can_goforward: viewer.canGoForward
onTextChanged: reload() onFile_nameChanged: reload()
WebView{ WebView{
id: viewer id: viewer
@ -32,6 +34,9 @@ Item {
} }
width: parent.width width: parent.width
height: parent.height height: parent.height
settings.allowFileAccess: true
settings.localStorageEnabled: true
settings.javaScriptEnabled: true
property int pre_height: 0 property int pre_height: 0
onLoadingChanged: function(request){ onLoadingChanged: function(request){
if (request.status === WebView.LoadStartedStatus) if (request.status === WebView.LoadStartedStatus)
@ -43,10 +48,8 @@ Item {
} }
else if (request.url.toString().match(/^qrc?:\/.+/)) else if (request.url.toString().match(/^qrc?:\/.+/))
{ {
console.log(request.url)
text = Tools.readAll(request.url.toString().replace("qrc:/",":/"))
pre_height = 0 pre_height = 0
load() load(request.url.toString())
} }
} }
else if (request.status === WebView.LoadSucceededStatus) else if (request.status === WebView.LoadSucceededStatus)
@ -63,7 +66,7 @@ Item {
Component.onCompleted: { Component.onCompleted: {
load() load(file_name)
} }
Connections{ Connections{
@ -90,56 +93,123 @@ Item {
{ {
viewer.runJavaScript("document.body.scrollTop", function(height) { viewer.runJavaScript("document.body.scrollTop", function(height) {
viewer.pre_height = height viewer.pre_height = height
load() load(current_path)
}); });
} }
function load() function load(file_path)
{ {
var style = Tools.readAll(":/qt/qml/ProtocolParser/resources/theme.css") if(!file_path)
var prism = Tools.readAll(`:/qt/qml/ProtocolParser/resources/prism-${RibbonTheme.dark_mode ? 'dark' : 'light'}.css`) {
var prismjs = Tools.readAll(":/qt/qml/ProtocolParser/prism.js") viewer.url = "about:blank"
var ex = ` return
html {
height:100%;
overflow:hidden;
position:relative;
} }
.markdown-body { current_path = file_path
box-sizing: border-box; let text = Tools.readAll(file_path)
min-width: 200px; var script = `
max-width: 980px; var md;
margin: 0 auto; let base_url = '${base_url}';
padding: 45px; var defaults = {
height:100%;
overflow:auto;
position:relative;
}
@media (max-width: 767px) {
.markdown-body {
padding: 15px;
}
}`
var md = markdownit({
html: true, html: true,
xhtmlOut: false,
breaks: false,
linkify: true, linkify: true,
typographer: true typographer: true,
};
mermaid.initialize({
startOnLoad:true,
darkMode:${RibbonTheme.dark_mode},
theme: "${RibbonTheme.dark_mode ? 'dark' : 'neutral'}",
htmlLabels:true
}); });
md.use(markdownitDeflist) const mermaidChart = (code) => {
md.use(markdownitEmoji) console.log(code)
md.use(markdownitSub) try {
md.use(markdownitSup) return \`<div class=\"mermaid\">\${code}</div>\`
md.use(markdownitAbbr) } catch ({ str, hash }) {
md.use(markdownitContainer) return \`<pre>\${str}</pre>\`
md.use(markdownitFootnote) }
md.use(markdownitIns) }
md.use(markdownitMark) defaults.highlight = function (str, lang) {
var result = md.render(text); var esc = md.utils.escapeHtml;
result = result.replace(new RegExp("href=\"(./)?", "gi"), 'href="'+base_url); if (lang && hljs.getLanguage(lang)) {
viewer.loadHtml(`<html data-theme=${RibbonTheme.dark_mode ? 'dark' : 'light'}>` + '<head><meta charset="UTF-8", name="viewport" content="width=device-width, initial-scale=1">' + try {
"<style>" + ex + prism + style + "</style></head>" + "<body>" + '<script>' + prismjs + '</script>' + return '<pre class="hljs"><code>' +
'<article class="markdown-body">' + result + '</article>' + "</body></html>") hljs.highlight(lang, str, true).value +
'</code></pre>';
} catch (__) {}
}else if(lang == 'mermaid'){
return mermaidChart(str)
}else{
return '<pre class="hljs"><code>' + esc(str) + '</code></pre>';
}
};
md = window.markdownit(defaults);
md.use(markdownitDeflist);
md.use(markdownitEmoji);
md.use(markdownitSub);
md.use(markdownitSup);
md.use(markdownitAbbr);
md.use(markdownitContainer);
md.use(markdownitFootnote);
md.use(markdownitIns);
md.use(markdownitMark);
let result = md.render($('.markdown-source').html());
if (base_url.match(/^qrc?:\\/.+/g))
result = result.replace(/href="(\\.\\/)?(.*?).md"/g, 'href="${base_url}/$2.md"');
result = result.replace(/src=\\"(\\.\\/)?/g, \`src=\"${resource_dir}\`);
$('.markdown-body').html(result);
$('.markdown-source').remove();
`
// var md = markdownit({
// html: true,
// linkify: true,
// typographer: true
// });
// md.use(markdownitDeflist)
// md.use(markdownitEmoji)
// md.use(markdownitSub)
// md.use(markdownitSup)
// md.use(markdownitAbbr)
// md.use(markdownitContainer)
// md.use(markdownitFootnote)
// md.use(markdownitIns)
// md.use(markdownitMark)
// var result = md.render(text);
// if (base_url.match(/^qrc?:\/.+/))
// result = result.replace(new RegExp("href=\"(\.\/)?(.*?).md", "gi"), `href="${base_url}/$2.md"`);
// result = result.replace(new RegExp("src=\"(./)?", "gi"), `src="`+resource_dir);
let parts = file_path.split('/')
let full_file_name = parts[parts.length-1] === '/' ? parts[parts.length-2] : parts[parts.length-1]
let file_name = full_file_name.split('.')
let html_name = `${file_name[0]}.html`
let prefix = `file:${Qt.platform.os === 'windows' ? '///' : '//'}` + Tools.baseDir
let html = `<!DOCTYPE html><html data-theme=${RibbonTheme.dark_mode ? 'dark' : 'light'}>` +
'<head><meta charset="UTF-8", name="viewport" content="width=device-width, initial-scale=1">' +
`<title>${full_file_name}</title>` +
`<link rel="stylesheet" href=${prefix}resources/theme.css></style>` +
`<link rel="stylesheet" href=${prefix}resources/github-${RibbonTheme.dark_mode ? 'dark' : 'light'}.css></style>` +
`<script src=${prefix}jquery.js></script>` +
`<script src=${prefix}markdown-it.js></script>`+
`<script src=${prefix}markdown-it-deflist.js></script>` +
`<script src=${prefix}markdown-it-emoji.js></script>` +
`<script src=${prefix}markdown-it-sub.js></script>` +
`<script src=${prefix}markdown-it-abbr.js></script>` +
`<script src=${prefix}markdown-it-container.js></script>` +
`<script src=${prefix}markdown-it-footnote.js></script>` +
`<script src=${prefix}markdown-it-ins.js></script>` +
`<script src=${prefix}markdown-it-mark.js></script>` +
`<script src=${prefix}markdown-it-sup.js></script>` +
`<script src=${prefix}highlight.js></script>` +
`<script src=${prefix}mermaid.js></script>`+
"</head>" + "<body>" +
'<article class="markdown-body">' + '</article>' +
'<pre class="markdown-source">' + text + '</pre>' +
`<script type="module">${script}</script>` +
"</body></html>"
Tools.writeFiletoDir(html,Tools.baseDir,html_name)
viewer.url = (prefix + html_name)
} }
function go_back() function go_back()

View File

@ -0,0 +1,118 @@
pre code.hljs {
display: block;
overflow-x: auto;
padding: 1em
}
code.hljs {
padding: 3px 5px
}
/*!
Theme: GitHub Dark
Description: Dark theme as seen on github.com
Author: github.com
Maintainer: @Hirse
Updated: 2021-05-15
Outdated base version: https://github.com/primer/github-syntax-dark
Current colors taken from GitHub's CSS
*/
.hljs {
color: #c9d1d9;
background: #0d1117
}
.hljs-doctag,
.hljs-keyword,
.hljs-meta .hljs-keyword,
.hljs-template-tag,
.hljs-template-variable,
.hljs-type,
.hljs-variable.language_ {
/* prettylights-syntax-keyword */
color: #ff7b72
}
.hljs-title,
.hljs-title.class_,
.hljs-title.class_.inherited__,
.hljs-title.function_ {
/* prettylights-syntax-entity */
color: #d2a8ff
}
.hljs-attr,
.hljs-attribute,
.hljs-literal,
.hljs-meta,
.hljs-number,
.hljs-operator,
.hljs-variable,
.hljs-selector-attr,
.hljs-selector-class,
.hljs-selector-id {
/* prettylights-syntax-constant */
color: #79c0ff
}
.hljs-regexp,
.hljs-string,
.hljs-meta .hljs-string {
/* prettylights-syntax-string */
color: #a5d6ff
}
.hljs-built_in,
.hljs-symbol {
/* prettylights-syntax-variable */
color: #ffa657
}
.hljs-comment,
.hljs-code,
.hljs-formula {
/* prettylights-syntax-comment */
color: #8b949e
}
.hljs-name,
.hljs-quote,
.hljs-selector-tag,
.hljs-selector-pseudo {
/* prettylights-syntax-entity-tag */
color: #7ee787
}
.hljs-subst {
/* prettylights-syntax-storage-modifier-import */
color: #c9d1d9
}
.hljs-section {
/* prettylights-syntax-markup-heading */
color: #1f6feb;
font-weight: bold
}
.hljs-bullet {
/* prettylights-syntax-markup-list */
color: #f2cc60
}
.hljs-emphasis {
/* prettylights-syntax-markup-italic */
color: #c9d1d9;
font-style: italic
}
.hljs-strong {
/* prettylights-syntax-markup-bold */
color: #c9d1d9;
font-weight: bold
}
.hljs-addition {
/* prettylights-syntax-markup-inserted */
color: #aff5b4;
background-color: #033a16
}
.hljs-deletion {
/* prettylights-syntax-markup-deleted */
color: #ffdcd7;
background-color: #67060c
}
.hljs-char.escape_,
.hljs-link,
.hljs-params,
.hljs-property,
.hljs-punctuation,
.hljs-tag {
/* purposely ignored */
}

View File

@ -0,0 +1,118 @@
pre code.hljs {
display: block;
overflow-x: auto;
padding: 1em
}
code.hljs {
padding: 3px 5px
}
/*!
Theme: GitHub
Description: Light theme as seen on github.com
Author: github.com
Maintainer: @Hirse
Updated: 2021-05-15
Outdated base version: https://github.com/primer/github-syntax-light
Current colors taken from GitHub's CSS
*/
.hljs {
color: #24292e;
background: #ffffff
}
.hljs-doctag,
.hljs-keyword,
.hljs-meta .hljs-keyword,
.hljs-template-tag,
.hljs-template-variable,
.hljs-type,
.hljs-variable.language_ {
/* prettylights-syntax-keyword */
color: #d73a49
}
.hljs-title,
.hljs-title.class_,
.hljs-title.class_.inherited__,
.hljs-title.function_ {
/* prettylights-syntax-entity */
color: #6f42c1
}
.hljs-attr,
.hljs-attribute,
.hljs-literal,
.hljs-meta,
.hljs-number,
.hljs-operator,
.hljs-variable,
.hljs-selector-attr,
.hljs-selector-class,
.hljs-selector-id {
/* prettylights-syntax-constant */
color: #005cc5
}
.hljs-regexp,
.hljs-string,
.hljs-meta .hljs-string {
/* prettylights-syntax-string */
color: #032f62
}
.hljs-built_in,
.hljs-symbol {
/* prettylights-syntax-variable */
color: #e36209
}
.hljs-comment,
.hljs-code,
.hljs-formula {
/* prettylights-syntax-comment */
color: #6a737d
}
.hljs-name,
.hljs-quote,
.hljs-selector-tag,
.hljs-selector-pseudo {
/* prettylights-syntax-entity-tag */
color: #22863a
}
.hljs-subst {
/* prettylights-syntax-storage-modifier-import */
color: #24292e
}
.hljs-section {
/* prettylights-syntax-markup-heading */
color: #005cc5;
font-weight: bold
}
.hljs-bullet {
/* prettylights-syntax-markup-list */
color: #735c0f
}
.hljs-emphasis {
/* prettylights-syntax-markup-italic */
color: #24292e;
font-style: italic
}
.hljs-strong {
/* prettylights-syntax-markup-bold */
color: #24292e;
font-weight: bold
}
.hljs-addition {
/* prettylights-syntax-markup-inserted */
color: #22863a;
background-color: #f0fff4
}
.hljs-deletion {
/* prettylights-syntax-markup-deleted */
color: #b31d28;
background-color: #ffeef0
}
.hljs-char.escape_,
.hljs-link,
.hljs-params,
.hljs-property,
.hljs-punctuation,
.hljs-tag {
/* purposely ignored */
}

View File

@ -1,5 +0,0 @@
/* PrismJS 1.29.0
https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript+arduino+armasm+bash+c+cpp+docker+git+go+go-module+gradle+http+hpkp+hsts+java+javadoc+javadoclike+jsdoc+js-extras+json+json5+jsonp+jsstacktrace+js-templates+kotlin+latex+log+markup-templating+mermaid+objectivec+perl+php+phpdoc+php-extras+plsql+powerquery+powershell+qml+ruby+rust+shell-session+sql+typescript+wasm+yaml&plugins=line-highlight+line-numbers+highlight-keywords */
code[class*=language-],pre[class*=language-]{color:#ccc;background:0 0;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#161b22}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#999}.token.punctuation{color:#ccc}.token.attr-name,.token.deleted,.token.namespace,.token.tag{color:#e2777a}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#cc99cd}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#7ec699}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green}
pre[data-line]{position:relative;padding:1em 0 1em 3em}.line-highlight{position:absolute;left:0;right:0;padding:inherit 0;margin-top:1em;background:hsla(24,20%,50%,.08);background:linear-gradient(to right,hsla(24,20%,50%,.1) 70%,hsla(24,20%,50%,0));pointer-events:none;line-height:inherit;white-space:pre}@media print{.line-highlight{-webkit-print-color-adjust:exact;color-adjust:exact}}.line-highlight:before,.line-highlight[data-end]:after{content:attr(data-start);position:absolute;top:.4em;left:.6em;min-width:1em;padding:0 .5em;background-color:hsla(24,20%,50%,.4);color:#f4f1ef;font:bold 65%/1.5 sans-serif;text-align:center;vertical-align:.3em;border-radius:999px;text-shadow:none;box-shadow:0 1px #fff}.line-highlight[data-end]:after{content:attr(data-end);top:auto;bottom:.4em}.line-numbers .line-highlight:after,.line-numbers .line-highlight:before{content:none}pre[id].linkable-line-numbers span.line-numbers-rows{pointer-events:all}pre[id].linkable-line-numbers span.line-numbers-rows>span:before{cursor:pointer}pre[id].linkable-line-numbers span.line-numbers-rows>span:hover:before{background-color:rgba(128,128,128,.2)}
pre[class*=language-].line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}pre[class*=language-].line-numbers>code{position:relative;white-space:inherit}.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:0;font-size:100%;left:-3.8em;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.line-numbers-rows>span{display:block;counter-increment:linenumber}.line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right}

View File

@ -1,5 +0,0 @@
/* PrismJS 1.29.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+arduino+armasm+bash+c+cpp+docker+git+go+go-module+gradle+http+hpkp+hsts+java+javadoc+javadoclike+jsdoc+js-extras+json+json5+jsonp+jsstacktrace+js-templates+kotlin+latex+log+markup-templating+mermaid+objectivec+perl+php+phpdoc+php-extras+plsql+powerquery+powershell+qml+ruby+rust+shell-session+sql+typescript+wasm+yaml&plugins=line-highlight+line-numbers+highlight-keywords */
code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f6f8fa}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}
pre[data-line]{position:relative;padding:1em 0 1em 3em}.line-highlight{position:absolute;left:0;right:0;padding:inherit 0;margin-top:1em;background:hsla(24,20%,50%,.08);background:linear-gradient(to right,hsla(24,20%,50%,.1) 70%,hsla(24,20%,50%,0));pointer-events:none;line-height:inherit;white-space:pre}@media print{.line-highlight{-webkit-print-color-adjust:exact;color-adjust:exact}}.line-highlight:before,.line-highlight[data-end]:after{content:attr(data-start);position:absolute;top:.4em;left:.6em;min-width:1em;padding:0 .5em;background-color:hsla(24,20%,50%,.4);color:#f4f1ef;font:bold 65%/1.5 sans-serif;text-align:center;vertical-align:.3em;border-radius:999px;text-shadow:none;box-shadow:0 1px #fff}.line-highlight[data-end]:after{content:attr(data-end);top:auto;bottom:.4em}.line-numbers .line-highlight:after,.line-numbers .line-highlight:before{content:none}pre[id].linkable-line-numbers span.line-numbers-rows{pointer-events:all}pre[id].linkable-line-numbers span.line-numbers-rows>span:before{cursor:pointer}pre[id].linkable-line-numbers span.line-numbers-rows>span:hover:before{background-color:rgba(128,128,128,.2)}
pre[class*=language-].line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}pre[class*=language-].line-numbers>code{position:relative;white-space:inherit}.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:0;font-size:100%;left:-3.8em;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.line-numbers-rows>span{display:block;counter-increment:linenumber}.line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right}

View File

@ -125,6 +125,27 @@
vertical-align: text-bottom; vertical-align: text-bottom;
} }
.markdown-body {
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;
padding: 45px;
height:100%;
}
@media (max-width: 767px) {
.markdown-body {
padding: 15px;
}
.markdown-source{
height: 0;
overflow: hidden;
visibility: hidden;
}
}
.markdown-body h1:hover .anchor .octicon-link:before, .markdown-body h1:hover .anchor .octicon-link:before,
.markdown-body h2:hover .anchor .octicon-link:before, .markdown-body h2:hover .anchor .octicon-link:before,
.markdown-body h3:hover .anchor .octicon-link:before, .markdown-body h3:hover .anchor .octicon-link:before,

View File

@ -2,10 +2,21 @@
#include <QMutex> #include <QMutex>
#include <QFile> #include <QFile>
#include <QFileInfo> #include <QFileInfo>
#include <QStandardPaths>
#include <QDirIterator>
Tools::Tools(QObject *parent) Tools::Tools(QObject *parent)
: QObject{parent} : QObject{parent}
{} {
baseDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + + "/ProtocolParser/");
}
Tools::~Tools()
{
QDirIterator it(baseDir(), QDirIterator::Subdirectories);
while (it.hasNext())
QFile::remove(it.next());
}
Tools* Tools::instance(){ Tools* Tools::instance(){
static QMutex mutex; static QMutex mutex;
@ -26,6 +37,9 @@ void Tools::setDefaultStyleSheet(QQuickTextDocument *qd, QString path)
QString Tools::readAll(QString path) QString Tools::readAll(QString path)
{ {
if (path.startsWith("qrc:/")) {
path.replace(0, 3, "");
}
QFile file(path); QFile file(path);
if(!file.exists()){ if(!file.exists()){
qWarning()<<"File not exist!"; qWarning()<<"File not exist!";
@ -55,3 +69,37 @@ QString Tools::fileDir(const QString &filePath)
QFileInfo info(filePath); QFileInfo info(filePath);
return info.absolutePath(); return info.absolutePath();
} }
void Tools::writeDirtoTempDir(QString path)
{
if (path.startsWith("qrc:/")) {
path.replace(0, 3, "");
}
QDir tmpdir(baseDir());
QDirIterator it(path, QDirIterator::Subdirectories);
while (it.hasNext()) {
QString tmpfile;
tmpfile = it.next();
if (QFileInfo(tmpfile).isFile()) {
QString original_name = tmpfile;
if(tmpfile.endsWith("js_packaged"))
tmpfile.replace("js_packaged","js");
tmpfile.replace(path,"");
QFileInfo file = QFileInfo(tmpdir.absolutePath() + '/' + tmpfile);
file.dir().mkpath("."); // create full path if necessary
QFile::remove(file.absoluteFilePath()); // remove previous file to make sure we have the latest version
QFile::copy(original_name, file.absoluteFilePath());
}
}
}
void Tools::writeFiletoDir(QString content, QString path, QString name)
{
QFile file(path+'/'+name);
if (!file.open(QIODevice::WriteOnly)) {
qDebug() << "File open fail: " + file.fileName();
return;
}
file.write(content.toLocal8Bit());
file.close();
}

View File

@ -1,19 +0,0 @@
## 目录
## 1. [协议解析](protocol.md)
+ 概述
+ 密钥
+ 认证流程
+ 数据结构
+ 接口解析
## 2. [串口使用](serialport.md)
+ 参数配置
+ 串口消息设置
+ 串口助手设置
+ 串口数据流向
## 3. [紫蜂协议](zigbee.md)
+ 设备列表
+ 密钥管理
+ 调试选项
## 4. [其他](others.md)
+ 主题
+ 数据结构自定义