From e5ee24df3e228db8fe8c0c51a6f384bad4cf301c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 20 Sep 2021 14:26:10 +0200 Subject: PySide6: Add the markdowneditor example Task-number: PYSIDE-1663 Task-number: PYSIDE-841 Change-Id: I921008a51c074ee01a937df309573067f2272f16 Reviewed-by: Cristian Maureira-Fredes --- .../webenginewidgets/markdowneditor/document.py | 61 + examples/webenginewidgets/markdowneditor/main.py | 57 + .../webenginewidgets/markdowneditor/mainwindow.py | 173 +++ .../webenginewidgets/markdowneditor/mainwindow.ui | 107 ++ .../markdowneditor/markdowneditor.pyproject | 9 + .../webenginewidgets/markdowneditor/previewpage.py | 55 + .../markdowneditor/rc_markdowneditor.py | 852 +++++++++++ .../resources/3rdparty/MARKDOWN-LICENSE.txt | 16 + .../resources/3rdparty/MARKED-LICENSE.txt | 19 + .../markdowneditor/resources/3rdparty/markdown.css | 260 ++++ .../markdowneditor/resources/3rdparty/marked.js | 1514 ++++++++++++++++++++ .../resources/3rdparty/qt_attribution.json | 35 + .../markdowneditor/resources/default.md | 12 + .../markdowneditor/resources/index.html | 32 + .../markdowneditor/resources/markdowneditor.qrc | 8 + .../markdowneditor/ui_mainwindow.py | 115 ++ 16 files changed, 3325 insertions(+) create mode 100644 examples/webenginewidgets/markdowneditor/document.py create mode 100644 examples/webenginewidgets/markdowneditor/main.py create mode 100644 examples/webenginewidgets/markdowneditor/mainwindow.py create mode 100644 examples/webenginewidgets/markdowneditor/mainwindow.ui create mode 100644 examples/webenginewidgets/markdowneditor/markdowneditor.pyproject create mode 100644 examples/webenginewidgets/markdowneditor/previewpage.py create mode 100644 examples/webenginewidgets/markdowneditor/rc_markdowneditor.py create mode 100644 examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKDOWN-LICENSE.txt create mode 100644 examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKED-LICENSE.txt create mode 100644 examples/webenginewidgets/markdowneditor/resources/3rdparty/markdown.css create mode 100644 examples/webenginewidgets/markdowneditor/resources/3rdparty/marked.js create mode 100644 examples/webenginewidgets/markdowneditor/resources/3rdparty/qt_attribution.json create mode 100644 examples/webenginewidgets/markdowneditor/resources/default.md create mode 100644 examples/webenginewidgets/markdowneditor/resources/index.html create mode 100644 examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc create mode 100644 examples/webenginewidgets/markdowneditor/ui_mainwindow.py (limited to 'examples') diff --git a/examples/webenginewidgets/markdowneditor/document.py b/examples/webenginewidgets/markdowneditor/document.py new file mode 100644 index 000000000..348323704 --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/document.py @@ -0,0 +1,61 @@ +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + + +from PySide6.QtCore import QObject, Property, Signal + + +class Document(QObject): + + textChanged = Signal(str) + + def __init__(self, parent=None): + super().__init__(parent) + self._text = '' + + def text(self): + return self._text + + def setText(self, t): + if t != self._text: + self._text = t + self.textChanged.emit(t) + + text = Property(str, text, setText, notify=textChanged) diff --git a/examples/webenginewidgets/markdowneditor/main.py b/examples/webenginewidgets/markdowneditor/main.py new file mode 100644 index 000000000..08d07a036 --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/main.py @@ -0,0 +1,57 @@ +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + +"""PySide6 Markdown Editor Example""" + +import sys + +from PySide6.QtCore import QCoreApplication +from PySide6.QtWidgets import QApplication + +from mainwindow import MainWindow +import rc_markdowneditor + + +if __name__ == '__main__': + app = QApplication(sys.argv) + QCoreApplication.setOrganizationName("QtExamples") + window = MainWindow() + window.show() + sys.exit(app.exec()) diff --git a/examples/webenginewidgets/markdowneditor/mainwindow.py b/examples/webenginewidgets/markdowneditor/mainwindow.py new file mode 100644 index 000000000..4f19f4323 --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/mainwindow.py @@ -0,0 +1,173 @@ +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + + +from PySide6.QtCore import QDir, QFile, QIODevice, QUrl, Qt, Slot +from PySide6.QtGui import QFontDatabase +from PySide6.QtWebChannel import QWebChannel +from PySide6.QtWidgets import QDialog, QFileDialog, QMainWindow, QMessageBox + +from ui_mainwindow import Ui_MainWindow +from document import Document +from previewpage import PreviewPage + + +class MainWindow(QMainWindow): + + def __init__(self, parent=None): + super().__init__(parent) + self.m_file_path = '' + self.m_content = Document() + self._ui = Ui_MainWindow() + self._ui.setupUi(self) + font = QFontDatabase.systemFont(QFontDatabase.FixedFont) + self._ui.editor.setFont(font) + self._ui.preview.setContextMenuPolicy(Qt.NoContextMenu) + self._page = PreviewPage(self) + self._ui.preview.setPage(self._page) + + self._ui.editor.textChanged.connect(self.plainTextEditChanged) + + self._channel = QWebChannel(self) + self._channel.registerObject("content", self.m_content) + self._page.setWebChannel(self._channel) + + self._ui.preview.setUrl(QUrl("qrc:/index.html")) + + self._ui.actionNew.triggered.connect(self.onFileNew) + self._ui.actionOpen.triggered.connect(self.onFileOpen) + self._ui.actionSave.triggered.connect(self.onFileSave) + self._ui.actionSaveAs.triggered.connect(self.onFileSaveAs) + self._ui.actionExit.triggered.connect(self.close) + + self._ui.editor.document().modificationChanged.connect(self._ui.actionSave.setEnabled) + + defaultTextFile = QFile(":/default.md") + defaultTextFile.open(QIODevice.ReadOnly) + data = defaultTextFile.readAll() + self._ui.editor.setPlainText(data.data().decode('utf8')) + + @Slot(str) + def plainTextEditChanged(self): + self.m_content.setText(self._ui.editor.toPlainText()) + + @Slot(str) + def openFile(self, path): + f = QFile(path) + name = QDir.toNativeSeparators(path) + if not f.open(QIODevice.ReadOnly): + error = f.errorString() + QMessageBox.warning(self, self.windowTitle(), + f"Could not open file {name}: {error}") + return + self.m_file_path = path + data = f.readAll() + self._ui.editor.setPlainText(data.data().decode('utf8')) + self.statusBar().showMessage(f"Opened {name}") + + def isModified(self): + return self._ui.editor.document().isModified() + + @Slot() + def onFileNew(self): + if self.isModified(): + m = "You have unsaved changes. Do you want to create a new document anyway?" + button = QMessageBox.question(self, self.windowTitle(), m) + if button != QMessageBox.Yes: + return + + self.m_file_path = '' + self._ui.editor.setPlainText(tr("## New document")) + self._ui.editor.document().setModified(False) + + @Slot() + def onFileOpen(self): + if self.isModified(): + m = "You have unsaved changes. Do you want to open a new document anyway?" + button = QMessageBox.question(self, self.windowTitle(), m) + if button != QMessageBox.Yes: + return + dialog = QFileDialog(self) + dialog.setWindowTitle("Open MarkDown File") + dialog.setMimeTypeFilters(["text/markdown"]) + dialog.setAcceptMode(QFileDialog.AcceptOpen) + if dialog.exec() == QDialog.Accepted: + self.openFile(dialog.selectedFiles()[0]) + + @Slot() + def onFileSave(self): + if not self.m_file_path: + self.onFileSaveAs() + if not self.m_file_path: + return + + f = QFile(self.m_file_path) + name = QDir.toNativeSeparators(self.m_file_path) + if not f.open(QIODevice.WriteOnly | QIODevice.Text): + error = f.errorString() + QMessageBox.warning(self, windowTitle(), + f"Could not write to file {name}: {error}") + return + text = self._ui.editor.toPlainText() + f.write(bytes(text, encoding='utf8')) + f.close() + self.statusBar().showMessage(f"Wrote {name}") + + @Slot() + def onFileSaveAs(self): + dialog = QFileDialog(self) + dialog.setWindowTitle("Open MarkDown File") + dialog.setMimeTypeFilters(["text/markdown"]) + dialog.setAcceptMode(QFileDialog.AcceptSave) + dialog.setDefaultSuffix("md") + if dialog.exec() != QDialog.Accepted: + return + path = dialog.selectedFiles()[0] + self.m_file_path = path + self.onFileSave() + + def closeEvent(self, event): + if self.isModified(): + m = "You have unsaved changes. Do you want to exit anyway?" + button = QMessageBox.question(self, self.windowTitle(), m) + if button != QMessageBox.Yes: + event.ignore() + else: + event.accept() diff --git a/examples/webenginewidgets/markdowneditor/mainwindow.ui b/examples/webenginewidgets/markdowneditor/mainwindow.ui new file mode 100644 index 000000000..f4e29ad95 --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/mainwindow.ui @@ -0,0 +1,107 @@ + + + MainWindow + + + + 0 + 0 + 800 + 600 + + + + MarkDown Editor + + + + + + + Qt::Horizontal + + + + + + + + + + + 0 + 0 + 800 + 26 + + + + + &File + + + + + + + + + + + + + + &Open... + + + Open document + + + Ctrl+O + + + + + &Save + + + Save current document + + + Ctrl+S + + + + + E&xit + + + Exit editor + + + Ctrl+Q + + + + + Save &As... + + + Save document under different name + + + + + &New + + + Create new document + + + Ctrl+N + + + + + + diff --git a/examples/webenginewidgets/markdowneditor/markdowneditor.pyproject b/examples/webenginewidgets/markdowneditor/markdowneditor.pyproject new file mode 100644 index 000000000..b10b12512 --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/markdowneditor.pyproject @@ -0,0 +1,9 @@ +{ + "files": ["document.py", + "main.py", + "mainwindow.py", + "mainwindow.ui", + "previewpage.py", + "resources/markdowneditor.qrc", + "ui_mainwindow.py"] +} diff --git a/examples/webenginewidgets/markdowneditor/previewpage.py b/examples/webenginewidgets/markdowneditor/previewpage.py new file mode 100644 index 000000000..e28af5b1a --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/previewpage.py @@ -0,0 +1,55 @@ +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + +from PySide6.QtGui import QDesktopServices +from PySide6.QtWebEngineCore import QWebEnginePage + + +class PreviewPage(QWebEnginePage): + + def __init__(self, parent=None): + super().__init__(parent) + + def acceptNavigationRequest(self, url, type, isMainFrame): + # Only allow qrc:/index.html. + if url.scheme() == "qrc": + return True + QDesktopServices.openUrl(url) + return False diff --git a/examples/webenginewidgets/markdowneditor/rc_markdowneditor.py b/examples/webenginewidgets/markdowneditor/rc_markdowneditor.py new file mode 100644 index 000000000..aa4f38a45 --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/rc_markdowneditor.py @@ -0,0 +1,852 @@ +# Resource object code (Python 3) +# Created by: object code +# Created by: The Resource Compiler for Qt version 6.2.0 +# WARNING! All changes made in this file will be lost! + +from PySide6 import QtCore + +qt_resource_data = b"\ +\x00\x00\x01\xdd\ +#\ +# WebEngine Mark\ +down Editor Exam\ +ple\x0a\x0aThis exampl\ +e uses [QWebEngi\ +neView](http://d\ +oc.qt.io/qt-5/qw\ +ebengineview.htm\ +l)\x0ato preview te\ +xt written using\ + the [Markdown](\ +https://en.wikip\ +edia.org/wiki/Ma\ +rkdown)\x0asyntax.\x0a\ +\x0a### Acknowledgm\ +ents\x0a\x0aThe conver\ +sion from Markdo\ +wn to HTML is do\ +ne with the help\ + of the\x0a[marked \ +JavaScript libra\ +ry](https://gith\ +ub.com/chjj/mark\ +ed) by _Christop\ +her Jeffrey_.\x0aTh\ +e [style sheet](\ +https://kevinbur\ +ke.bitbucket.io/\ +markdowncss/)\x0awa\ +s created by _Ke\ +vin Burke_.\x0a\ +\x00\x00\x02\xb2\ +<\ +!doctype html>\x0a<\ +html lang=\x22en\x22>\x0a\ +\x0a\x0a \ +\x0a \x0a\x0a\x0a \x0a \x0a 'use str\ +ict';\x0a\x0a var pla\ +ceholder = docum\ +ent.getElementBy\ +Id('placeholder'\ +);\x0a\x0a var update\ +Text = function(\ +text) {\x0a pl\ +aceholder.innerH\ +TML = marked(tex\ +t);\x0a }\x0a\x0a new Q\ +WebChannel(qt.we\ +bChannelTranspor\ +t,\x0a function(\ +channel) {\x0a \ + var content = c\ +hannel.objects.c\ +ontent;\x0a up\ +dateText(content\ +.text);\x0a co\ +ntent.textChange\ +d.connect(update\ +Text);\x0a }\x0a )\ +;\x0a \x0a\x0a\x0a\x0a\x0a\ +\x0a\ +\x00\x00\x06V\ +\x00\ +\x00\x17ex\x9c\xb5XKs\xdb6\x10\xbe\xfbW\xec\ +\xd8\x93\xc6\xce\x90\x0e%Q\xb2DM\x0f\x99\x1c\xda\x1c\ +\xda\xe9!\xb7\xc6\x07\x90\x04E\x8c)\x82\x05!\xcbN\ +\xc6\xff\xbd\x8b\x07)\xf0\xa1D\x89\x12\xd9z\x10\x0b\xec\ +.\xbe\xdd\xfd\x16d\xcc\xd3\xe7/\x17\x80\xaf-\x11\x1b\ +VF\x10\x00\xd9I\xbe\xd6c\x19/\xa5\x9f\x91-+\ +\x9e#\xf8\x83r\x9cA<\xf8\x87\x14D\xb2\x92{P\ +S\xc1235\xe1\x05\x17\x11\x5c\x85\xfae\xc6\x0aV\ +R?\xa7l\x93\xcb\x08&kk\xe6\xc9\xdf\xb3T\xe6\ +\x11\xac\x16A\xf5dF+\x92\xa6\xac\xdcD0\xd3C\ +/\x17\xf9\xc4\x83|\x8a\xef\x19\xbeC\xf8\xd2\xb11\xd1\ +/\xc7\xc5\xbd\xb5\x11\x06\xc1p1\xbe\xe7\x1eT\xe0n\ +\xd3\x8f\xb9\x94|\x1b\xc14\x1c\xb8`U\xd8\xf9Z\x7f\ +\xcd>S\xd4\xbe\xb4\xbeM\x87\xb2\xd9\xa2\xd1\xf3\xf6\x0d\ +|\xcc)\x18\x03\xd6\x1c\xb0\x1a\xea-)\x8a[\xf8 \ +_\xd7\x90\xd2\x9amJ\x9a\x82\xe4\x10S\xd8\xd5\xf8s\ +\xcfd\x0e\x1bA\x9eaK%\x01I\x9f\xa4\xd6\x07o\ +pJ\xc1\xf7@\xa0\xe2\xb5\x04\xc9dAo\xe1\xcd\xdb\ +N\xd4\xd4>0t\x0b\xeb\xe1l\xe8\xa1\xd9)\xca\xc2\ +\x11\xd9\xc4\xca\xe6C\xd9\xc4\xee\x9a\xf4\x82\x10\x04\xabU\ +\x96\xad\xbb\xb93\x84R]?R!YB\x0a\x9f\x14\ +\xb8\xed\x08bRS\x95\x1bZm\x94s\x94[\xe5j\ +\xd7~J\x13.0\xc38N-\xb9\x9a\xe6\xda\xcd\xb2\ +\xc5\xc2\x84\x99D\x8f\xacf\x12\xb1\xebxV\xedDU\ +h\xdd\xbb\xc2\x03^Xi\xdf)\xc7\xe7\x97\x8b\x82\xd9\ +Y\x9d\x94m C\xa9R\xa5\xbf\xbaiT\xd0\xcc\x99\ +Wy\xd01\xe9\xa2\xd8\xe6\xc7\x88\x85^]\xccC[\ +\x04\x95\xa0\x03\xe71\xcc\xa3\x8b\x96A[L\xfb\x1cA\ +\xf1\xeb\x8a$h\x18u\xf8{A*\xa5/\xe1)u\ +]k*\xfb=/k^\x90\xda\x83\xbfxI\x12,\ +\xecweJ\x0a\xaa.\xf1b\x8b\x9fZ\xdbXU\xdf\ +\xce\xd7\x83\xbd\xcel\xc6\xd4\xac\xb5\x97\xb2\xba*\x08\xda\ +\x8a\x0b\x9e<\xd8%\x05'\xa8B(M\xd6s\xb3\x97\ +\xd9\xca\x02\xa0'\xff\xb7\xe3\xb2Q\x13s\x91Ra`\ +\xbf\x9d\xd3-\xa0\xdf,\x85+Ji?\xf5`J\xb7\ +\xebA\xac\x82\x01p\xe1\xddb`\x0c\x12&\xe9 \x88\ +\x93p,\x86\xd3\x16w\x93\x7fWq\xa6\xfez\x1a\x95\ +\xc2(\xa6\x19oC\x9a\xa0^Z\xe2\xfe_\x7f\x9a\x06\ +\x93\x10>\x05\xc1\xbb\xe0\xb5Z\xe6\xae\xabzU\xb7X\ +,\x86;X4\xa4\xd9\x94Q7\x91\xda\xc2\xb2\xe5\xa7\ +\x80\xe8\xd5\x80\xe6|\xfc\x0a\xba\xb5\xb6Z\xad\xb4C\xc8\ +i\xefU\xee\x18\x22\x929\xd2\x99\x82@\xd1Z\xc2\xab\ +g\x1dA\xf8\x88\x0c&\xb1\x92?\x94\x89\xa6\xa7\x8bx\ +\x87\x14Xz\x17\xac\xacv\xd2\xbb\xc0\x9a\xa7\x09~+\ +W\x88\xa0\x86O\xdc\xb4\x09\x82W\xca|\x87L\x8eS\ +\x07\x12c_\xb8eij*\xdf\x9a\x06mZ\x1b\xea\ +dm\xc9\x05\xb2\xb1\xd6\xa1\xc8\x07\x13q\x1f\x81\x22\x93\ +\xd8]\x1eE\xfe\x96\x7f\xf63\x9e\xecj\x9f\x95%\x15\ +V\xe1P\xa0M\x98\xe4\xb4\x8ew\xdbI\x07\x8a\x7f\xe5\ +sE\x7f\xbf4c\x97\xf7\xddQAk*\xfb\x83\xf5\ +.\xde2\x1c\xd5f\x92\x9d\xa85\xcfq\x86\x19$\x94\ +1l\x80\xf1\x03\xc3\x00W\x15%\x82\x94\xaa\xf0\x8dz\ +e\xdc\xd1\x94\xe44y\x88\xf9\xd3\xbd\xdd\x89\x19\x15$\ +e\xfc\x88\xf2\x17\x15|\x05\x92P\xc5\x9c\xd2\x8c\xec\x0a\ +\x09I.\xf8\x96\xc2o\x901\x81I\xfd\x84'\x01\x89\ +G\x82M\xad\x02o0*\xb9\xbc\xb6\xee\xb3-\xd9\xd0\ +\xcb\xfb\x1b\x0f:\xb1o\xbcF\x7fT\x0ah\xb4lU\ +\xa81\xbd1\x85\xf3W\xe4GE\x98\xb4\x1d\x00\x11\x96\ +$\xb7\x00\x8e\xa1\xa5\x1c\xcb\x18-\xd2\xf5/wl\xcc\ +/\xcc(k\xd3\x8c8=\xf0\xa8\xcb\xa65bw\x22\ +X\x96'TY\xc3\xf6\x97\x7f\xd2\xe2\x91\xaa\xc2\x81\xbf\ +\xe9\x8e^z\xd0\x0e \xf1\x0bF\xb0\x85\xd5\xa4\xac\xfd\ +\xf6t7\xe0\xf6\xde\xb1\xebPNG\xaa\xacw\xe8j\ +\x8e\x14g%\xe6@k\xd0S\xa9\x10\xe8\xd6QE\xea\ +z\x8fEz\x7f\x80\xa7\x01L\xdbh\x9b\x14+\xf5F\ +\xda^e\xf9t:\xb1|\xda\x16w\xe8\xa0\xf1\xfd\x00\ +\x19\x1c\x00\xfa\xd7\x0d\xfd.\x03\xf5\xb7v\xa8\x05\xcfi\ +M\xcbK\x92\xa4\x9b\xab\xba3*\xc4v5\xb6\xd0\xca\ +M\xd31\xd1\xd8\xe8K\x93>n\x102VP\x13\x83\ +\xf6\xd4rgTt\x8f2wFC'\xf1\x1a\xa1\xb9\ +\xa50\x9dd#\xe83p\xa4e\xc4:\xa19/\xd0\ +\x0d\xcd\x1b\x86U\x9dQ\x13x\x0b\xc6\xa1\xad\x1e\x8aE\ +{y\xc2\x8a\x93\xd3b\xb4z\x1ak\x12\x0b\x0f\xcf\x9b\ +\xfa\x5cj\xd0\xd3\x08\x10\x01\xc1\xed\x14\x0fO\xba\xe6s\ +\x92b\x8bt\xc6\xdb0\xfc\xf8\xf23\x0c\xbbL\xa6g\ +\xa8\xe4F\xb2\xc6^\xafr\x09\xa3\x0eb\x13\x93\xeb\xc0\ +\x03\xfb\x7f;\xb9\xe9\x12\xdcw-\xfb\xde\x15\xc3\x8a\x8d\ +t[\xedd`\x1b\xa0F\xd6\x84\xc7\x5c\xeb aB\ +\xa9\xbd\x1f\xee\x18l~\xdbd\xd0\xb6\x97xO8Y\ +,=\x98\xce\x16\xca\x81\xe5\xcd\x8fc\xe4\xa9\xd3\x12,\ +\x1bY_\xf5\xe2GA\xce8N\ +\xe5\xa8\xca\xd6r\xbf\xdf\xf7\x8a\xd4\x22lS\xa2\x16Y\x97yH&L\xc9\ +\xd9\x5c\xe6[4OnKRQeA\x1c*\x16e\ +\x81\x03(\x8b\x15\xfc\x1f\xe9\xa4\x95Q\x16\x99DVd\ +\xc1\xfcc\xb9\x8d\x1d\xb5\xb8\xc5\x0e\x88\xf2\x7f\x0az\x04\ +\x84\xbdO;KN\xaa\xb8\xdf?W\xb2\x8e#\xb5\xa5\ +\x12K@\x1a\xa2\x8a\x90\x08\x94z}\x8a\x82\xca\x1a\x0e\ +\x96\xc6\x0a\x06Mg\xd5\xaa\xcd\x08`\x86\xac\x8b\x1b\x07\ +l\xad\xa3K\xd8=\xae\x07\xa3>-M\xd69c\x9d\ +\x03TD\xb0(\x0fJ\xfa*\x95\x91\xc3\xbf\xa2\xe2?\ +p\xceN\xcf\xdf\x83N\x1a\x0f\xdb\xc4R\xe9i{|\ +\xaa\xb8aa\x09\x0ed\x95*\xae\xc8u=\xff^\xd1\ +oU\xa8\xb8\x11\xac\xc6 \xdc\x09\xd1zf\xf3 a\ +\xb3\x10L#\x10\xd5l\xbb)\xc0\xc4\x9e\xdd\xb2\xe2v\ +\x13\xe2\xb6O\x16\x15o\x97\xb7\xe9D\xb5\xb4\xec\x01\xeb\ +r\x9b\x14\xc5\x08E\x90\xcd\x1a\xab\x0baL\xff\x1d\x96\ +\x10\xd8odS\xdb\xd64\xc7\x90\xf0\xfa3\xb6\x0e\xb3\ +e\xe8\xde\xdd\x0b\xd4\x06\x8a\xbf\xfe\xeb\xcf\xed\xed\x97W\ +\xebzc\x81\xb5GV\xba\xb4\xba\xc9H~Oz\xee\ +3\xe9\xb7\x09\xf3\x07h\xed\xfd\xda\xc5-\x1f4\xbc\x14\ +w\x8f\xcc\x02\xffh\xe7>\xbe\xc3\x02\xef\x1a\x16\xf8\xb3\ +\x8e\x89e\xef^s\x1f(\x7f\xa2\xc4\xc1\xaaD\xb5\x8b\ +\xff\x08\xdbGc\xe2\xa3\x14\xdaW7\x01\x85\xcf5\xf5\ +\xb1\xe3\xd1\xd2\xb7[\xe2\x86\xd2\xde\xe6\x85l\xd3:\xbb\ +85]\xf6\x0e\x95O\xde>G\x05\xaf\xafO\x13\x10\ +\xce\xe7H\x1dH\x88\x8f\x93\x0b\xb0t\xd8t\xd0\xf1\xcb\ +A\x87\x9bV\x93\xfeh\x0a\x07\x19\xbf\x9c\xf4K6\x92\ +\xe7\x10<4\x0d`u\x9fspu6\xe9\xd0\xe1\xc2\ +\xb6\xde\x10\xb3_\xba\x03n\xab\xf9\xe5\x18\xb6y\xc2Z\ +\xc3\xc8va\xe43(\x86\xff6\x5c\x04\x09l]l\ +Y\x1f\xf4F\xd6\xed\x96N~\xee\xa1\xb9\xa7\x99q.\ +H^\xa4>\xee\xf0M\xb8\xf4\xe9\xa4$'\x0fmy\ +T\x05\xd2X\xee\x8e\xf91G\x82\x93\xd1,\x9a\xa0\xba\ +@\xa3\x19\xb4\x83e\x99\xc3\x174\xe4@o\xa2\xd6\xf4\ +Ac\xfa\x0e\x98h\x0e\xb6\xc3\xcf\x07C8\x83\xe4h\ +\xe6\x8c\xc1\xe4l\xc0\xcc\xb7\xf7\xc7j|\xd3h\x81\xae\ +\xd1fAA\xc6\x83\x1e\xd5\x12UA\x09\xbb\x22\x9c\xc7\ +S0\x82s`Q\x5c\xe6\xe5\x1c\xb6\xca\xf2\x9f\xe5\xe2\ +*)\x83\xd9\x0c\xb6\xf1\x006\xcd\x22\x82-\x19\xcf\xda\ +%\x9c\xc9\xcb \xac\ +\xfd\xba\xd1p\x94\xa2\xce\x10\x87\xbbo\xefMyx`\ +\x5cbTH\x8e\xd3\xd3\xa5\xe4\x90\xd9oT\x91\x06K\ +\xc6\xd8\xbd\xb1*\x12\x10E\xea\xd8\x80\x19!\x8cd\x91\ +&\x1e\xce\xccQ\xb2\x0dO*L\xe3\xf6!sQ\x91\ +\xb63OX\x91_\xc5\xbe'\xf3$\x0e\xd0\x82Fd\ +\xc7\xd3*\xa7\xb0\xf4\xc5\x14\xb7\x22\xc7y\xf4X\x85U\ +\xde>L\x01\xf0{\x8fS\x1d\xf0T\xc5\x22\xdc\x14+\ +>\xaa#\x89\xb0i\xc8\xc7\xd3G\x0f\x96\xb66\x96\xa4\ +\xb0\x01Pol\x13\xe1\x01\xd0\x9agPs\xec\xf9\xf3\ +\xa6\xd5\xcf\xedn\x83\x11\x9a\x13\xc2\xa9U\x1b\x15\xb50\ +\xc6\xc4\x9d #PkqT\xbc\x0a\xe38w\xc5\xf8\ +\x8c\xb5CNV\xf8\xef\x1bR\xed\x8e\xe7\xe9\xf6A\x1c\ +-\x139l\xbb\x8d\xd9b@\xf8\xdd!\xc734\x10\ +\xcc\xb1O%*c\xf1\xc1\x5c=b\xf1\x08\x14\xb4\xb3\ +\xc0\xf2\x99(&\x9f\xec\x19\x8a\x0c\xc7=\xe0\x83\x92\xda\ +\xec\xec\xec\x8c\xd81 Z\xa5 \x18\xacy\x8c\xd4(\ +\xe0\xab4\x83^\x00\xfe\xf0\x84E\xec\xb4\x8e\x19\x8a\xbb\ +]\x13='\x0cY\xd2\xef\x8e\x90%\x83\x22\xcc\x0bW\ +7\x9cDS\xcfn\xc0\x98U\x8b\xde6\xbadsN\ +\x0c \xc3\xdaB\xe4\xa3\xaf\xc1\xce\x1dq\x0f\xa0\xffb\ +\xecqx\xd5H\xfa\xeef\x09l\xc5V#\xbd\xbb<\ +0\x1d$S;\xa6C\xc1\xf0\x8e\x0c\xd9\xb7\xaaz\xac\ +.M\xdeI\x13\x155m\x82\x0dM\xa9\xb1\xd7\x7f}\ +W\x5ce;\xf4]\xf6\xbb\xab\xba\xec\xf1\xeaY\xbb\x97\ +\xda)\xd60_J\xf9\xa3I\xd7]]\x82u\x95\x15\ +\xe6@\x1e\xb0\x08:\xe7l\xacM\x02\x01\x0c#|\x1b\ +\xe49{\x0fZ\xf7=X\x98\xecc\x18n\x80\x8e\x90\ +\xcd\xb7Y\x06\xabD\xc3\x1d\x00H\x8c\xf7\xcc\x07\x0c\xba\ +\x86\xb1\xb2w@.\xd8u,\xbc\x09\xe6E|\xabA\ +W\xe9\xb5\xba<\x1flbv\x9df\x1f\xf3Am\x90\ +\xc8\x06n\xd6~\x19\x07\xc2d\xd14\xfe\x96\x99D\xf7\ +Q\xfb\x1c\x92s\xe9\xab\xe4\x8e\xae[\xce\xc4\xd6\xa0\x8c\ +Mi\x14\xe3Q\x0b\x00\x0c\x93\xf3\x09cF\xe2\xc4|\ +\xeb\x9dD \x1e\xd5\x0do\xc6\x08\xd6\xa8\x81\x8d\xa6K\ +\xf4\x8dl\xd3DO\xd9_\xc3\x82\x85\xc1|\x85\xd3\xd1\ +\xa7i\xe6\xda\xa0I\xa8\xd6A1_\xb9\x06\xf3\xec\xe5\ +\x8f\xe7\x0e<\xbc\x04\xa0\xf3$\x1f\x04g\xa4\x92\x92\xdc\ +!E&\xdb\x91n\xe3j-\xae\xa91\xb1\xc1#\x05\ +\xd1\xd4\xd04@\xfa/\xe1:\xfd\x14\x92\xd0\xd2-\x14\ +\x82:9\xe3\xf7K&`\x9eB\x1d\x0al\x1e\xc2\xf1\ +*\xc8\xa9\x09QK\xdc\x1fh\xf6\xa1u\xcf\xc46j\ +\x93\xac(\xa1:sy\xb9\xe6E\x1d\xeb\x0e\xed\x85F\ +\x04\xbc\xd9\x16\x18\x19\x00\xa7\x1fX?\x9f\xe0\x98\x0c\x04\ +\x98\xf5\x8a|\x12\xe2 \x02\x81`\x7f\x0b\xe6\x1fo5\ +i(\xbc\x9f\xa9o\x8c2\xb8ys\x85\x16\x02\x1cM\ +m\x95\xcf\x07\xd0o\x19\x81\x1a\xc3\x83\xa6=\x1a\xf7\xd6\ +@\xf1T\xffK\xb8\xfc\xcb\xcd\xc6\xc5\xf0\x87\xa3\x1e\xde\ +\xa7\xf1\xde\xba\xcc\xb9w\xc45b\xd5\xfc\xc7\x03@\x95\ +a\xd0\xb8~F\xb1\xb6\x19\xe0\xc8\x8f!\xec\xd3k8\ +\xf3\x01\xcf\xc2b\xc5Y\xc6\xe7L3k\x16\xc6i\xb2\ +\xcc\xc1\xb8\xcb\xc2\x81\xd9\xfa\xcf\xc0;\x1cU\x8cl\x83\ +\xa9_\xa4p\xaaH\xd2B\xb4`\x11?\xa8\x13*\x9b\ +\xc5\x16cr\xd0e\xc5k\x80\xc9\xd10\x8d\xd8>X\ +X1\xeb\xdb\xa7FP\x00\xca'\xc3E\x8f\xab\x13\x92\ +X`\xce\xd1\xd4\x83\xb5cM\x02\xf4C\x8b\x12\xf1\xcd\ +\x10\xf5\xbe[\xd1\x11X83\x8f\xa9U\xdb\x83\xab'\ +\x5cYy\x1c\x01_\xa9'o\xf0!\x8d\x12a:v\ +\x11\xe6\xc4j\x84\xcb\x8e\xe8\x7f\xd0\xdch\x9c\x01\xe29\ +r\x0d}\x0a\xa0\x86\x90\xa3\x16\xdb\xff\x91\xa3\x0b\xdbE\ +\xc7\xb8G\x8142\xb6\x88_LS\x18\x8d\x09\x8f\x0b\ +\x7f\x11\xe5\xf3t\x9b\xe0\xd4\xac\x82OQ\x9ai\x8c\xbc\ +\x9f3>\xebp\xb8\x1aZ\x88\xb4\x85f\x08\x11\x99\xc6\ +m\xf3$\xf4\x13\xb7}VA\xf6\x830\xf0\x04\x9b\x09\ +\x1e\x8dh\xe4_u\xbe\xf6\x89\x18\xcf\xa2\xa9Mv_\ +\xa1\xbf\x83\x06\x87~\x10-\xaf\xb9&\x93<$t\x8f\ +\xefO&\xec\xe6\xdf\xa7\xfe\x94\xb5\x8cH\xbaO\x00z\ +\x0b+\xff\x0afdQ\x190a\xab\xd8~F3\xc4\ +\x08'\x1db\x8b\xc3\x9c\x06}PY\xa2\x9a&\xa5\xcd\ +\x1aF\xfa\x08w\x09q\xab\xa2V\x1c*\xbc\xc4.m\ +S\x86\xff\x91\xbb\x9eQ\xdf3\xf1\xc2HG\x15\x0f\x13\ +\xfe\x11\xa3\x1d\xe9\x81k\x92\xbd\xea\xb6\x01&Nn(\ +\x0c\xc30\xe1\x11\x11\xb4\x83\x99\xad\x1e\xe3\x19\xd2T\x1b\ +\xe6\x89\xed!z\xda\xbe\xff4+\x07\xafhv\xd8\xd6\ +P\xfb;[\xd7\xb6\xe6\x0c\x92\xa8\x88\xfe\xcb\x9c{\x98\ +y}5k\x94\xa3]\x0e\xd4\x19\xb3\xbc\xc9\xc2\xaa\xf7\ +I\xe2\xcb\x8c\x86\xc2W\x80\x92M\xab\x16\x9a9\xa8&\ +\xcc2\x1e~T/\xc6P$\xc7krj\x1c>\xde\ +\xa9\x01\x8bQq\xbc\xd5y\x81\xd1&M\x8e\x8b\xa7\xfb\ +-_L=\xe9>8\x93\xee\x03\xdd\xf6\xa8'\xcb\x0c\ +u\xa6&\x8f\x22Y\x84\xc3\xa3H_\xa7\xd7a\xf6*\ +\xc8C\xd73\x1c\x10yW\xba\xbb\xcd\x9e\xf7k72\ +\x13\xc06m\xf3\x9bj\x08\xcb+\x83a\xa4x\xdfT\ +\xf5\x9fAc\x8c\xfa\x90~\x11\xbdj\xec\x03\xe4C\x8e\ +\xa5G:\x92\xfe\x0f\xb8\x91\xe8f\x18\x1by\xe3\xff\xf7\ +(\xfd\xbfGI4j\xda\xbe\x7fc\x8fR\x9d \x09\ +g\x899\x8afey\xf4\xeaM\xff'\x5cQ\xf1\x83\ +\x0e\xf8\xf8\x7f\x83\x07\xfeXlYg\x0e\xac\xf6#X\ +\xbe\xc7M\xbb\xd6\xd1\x13\x5c\xf1\xea\x9c\xaf\xb6\xe3\x875\ +\xa7\x02\xfd\xca\xbd\xecaf\x18\xe1[\x8d\xe3\x94\x96\xbb\ +u;a\xdb\xee\x96\xd1!\xe0\xf8)\xe9\xb0\xc7\xfaG\ +\xb5\xeb\xa9'q\x0fHi\x97\x18\xacm\x92\x16h\xf8\ +N\xb1=_\xa5\xdbx\x01'\x08t\x04d\xe4{1\ +\x0f\xb0\xbf%3\x91\x9eF>>\xd6\xca\xc1Q\x1aw\ +\xb5\xd8g\x96^\xd3\x1d\xff_\xb2,\xcd\x5c\xe7\xa7\x04\ +N$\xb0\xf6\xd0\xd6\xdf\xb04a\xb3[\xcc\xcfp\xf8\ +\xf9\x93f\xebU\xba\x08a\xc6\x0e=\xcf\x0cX\xd8k\ +\xb83\xcf\xad\x9b\xf2\x9f\x12\xbc\xf4m\xcbq\x89\xa8V\ +l\xdaa\x0e\xa3\xe29.\xbe;\xd9?x\xf6\xcd\x1f\ +\x9e;\xae\xd7\xe9\xf6\xfc\xfe`8:9=;\x1f\x7f\ +\x8f\xc1\xe2\xbe\x7fq\xf9\xfe\xae\xbc\xff<\xe5qW\xc1\ +\xb6H\xd1f\xc1\xa6\x98\xab\xb1\x0a\xd7\xe1\x08\xe3_\xfc\ +\x9b\xc3\xc3\xbe\x7fstuz>\xed\x94\xe1:\x88b\ +\xef\x9c\x9al\xb3X\x87\xd9\x83\xa5\x83\x09!2\xa8\x88\ +\xc6\x87Q=\x17\xa7C\x11\x07J9\x04#\x99D@\ +\x91Ny\x18_\xf5\x1br\x04\xa0\x95\xd9\x88G\x8e\x9a\ +\xa9\x0e\x88b8>\x17Y'\x954\x86\x8bz\xe6\x07\ +\x01\xea\xa8\x0a\xe0\x19\x08\xd4\x96B\x0bz,\x1c,\x07\ +\xect\xbcYm\xd8\xf8\xdc\xc0\xb2/i\xe8b\x90\x95\ +\xce\x0fq\xb8\xcd;\x8fa\x85\x9a\x18\xf6\x7f|\xf3\xea\ +\xdd\x7f\xbc\xfd\x0b\x1dA,D\xbbRG0V\x16\x8e\ +\xcaX\xcdD\xb8\xf0\x1ef\xea\xf0\xa9\xd8\x1f\x1b\xc9\x11\ +\xbe\x8b\xc6#F\x1c\xe5]\x95\xfe\x80\xd9\x00|\x0a\xa1\ +\xae\xb9\xd9D'\x0d\x18Y\x03c\x916\x80\x19\x01\x18\ +\xf2\xc4s\x8dR\x0b\x85\xd5n\x22\xd2\x0c\xa0\xa0\xac\xa5\ +\x1et\x00\x03\x01\x01\xf4\x98P\xf1\xc80DuyI\ +\x91TS\x19\xb1I_<(\x1d\xef_z\xe5\x85\xdf\ +\xf1;M\x00T\x0e\x14t\x00F\xa2hje\x00R\ +\xc7\xe1\x9a:\xad\xa3\xbc\x84\xe6\xa25\xaf\xbd\xac\x92\xa4\ +p\xd7\x1bw\xb0\x1fI\x8e\x00\xe8\xd4(V\xf4\xba\x95\ +\x0eU\x0b\xcf\xa2Ue\xa0\xbd\x87)\xc8;\xae\xc6\xf7\ +~:\xc6\x12\xff\x08\xa0\xdfs\xe0\x99\xc8@;\xee\xdd\ +\x1b\xfe\x1f\x1e\xc3f.E\x99F\xa2R\xbb\xce@\xea\ +@\x0a'\xef;0s\xb3\xcbR\xa0\xe0Qk\xa0g\ +\xb8\x0a\x19\x5cr\xed\x81QQ\xc3'\xa8\x8f\xa5\x81\x81\ ++\x0eD\xa0\x160\xff\xf7\xb0\xff]w\xd0\x9f\xde\x1d\ +\xf5^\x1c\xdd\x0fOt\x97\xa8P\x0cx\x80\x1b\xecS\ +\xb7\x9d\xee\xf0l,z\xe9O\xbb\xee\xf7\x9e\x06AQ\ +\xd3\xdf\x00\xeda\xef\xe5\xd1\xbdQ\xcfs\xe8\x06Oj\ +\xe1a\xd4\xe0\xa4\x0f\x93\xa6\xe9\x93jQF\xfcV\x8a\ +\xed\x88_>xX\xd067l \x1a\xb0\x01\xc35\ +\xea^5dWV+\xadG\x93\x927\x07\xd5\x83 \ +\x9c\xc1\x7f*<\x94\x7f\xc5\xb0z\x0c\xaa\x17_+a\ +\xf5\xba\x0f~(6\x87W\x8b\xec\x7f\x5cv\x80\x19\xff\ +_\xa3\xbf}\x88FnS\xb3\x92\x19\x97\xefq=t\ +\xde\x1b\x1a\xab36\x84\x08\xd5\x22\xe7O\xc7=\xe5*\ +\x0ev+Rp\xf9\xe99\x81\x9f\xf3t\x99\x89\xebA\ +\xb9\xefZ;\x9b\xeb\x01\x08h\xd1\xb2^\x0a\xfd\x18\xd2\ +\xa0\xb3\xaa\x9aR\xaa\xa8\xc8\xc1\x22\x87\x8a0\x95\x8a\xca\ +|\x0f\x0b9:\xdf38\xdf Yu\xa9\x92\x99U\ +\x16\xbb\xaa\xc9\x0d\x94\xe2c\xb2\xa39\xf7\xca\x1aG\xeb\ +\x8c\x88\x8d\xa4B\x99(},q;\xd2\x0b\xb8=c\ +[2\x02AC\x82\x01\xafi\x8a\xe3\xde\x81\xa71\x9e\ +\xdb\xea\x83\x07t[\x9b\xd4\xf8\xcc\xff\xd5S*\x18>\ +\xdb\x9bM\xad\xbae\xdf\xa9\xa3\xd1{@\x03\x0e\x03\x03\ +\xdf{\x89\xe9\xb5\xad\xdf\x1d`\xaa\x837\xac\x86q\xb7\ +\xce@-\xd0Y\xd9\x07\x8d\x1d\xe4*\xfe\x19\xb7\xf2/\ +\xec\xc6\x8a\x81\xc6t\x83\x1dST\xcd\x05i\x98\x1di\ +\xcd\x9ab\xc8\xcb\xb4\xbf\xce\x99zx\xe9\xf6\xb9\x84\x7f\ +\xbd\xca\x88\xc9B\x15\xa3\xc5\xa5xUlJJ@\x1f\ +{#\x7f\xe8\x0f\xcb\xeb\xebk\x7f\xe0Y[\x83\x0f{\ +\x8d?\x80\xcd\x80\x94\x07\x98\xbc\x17\xa4\xa1k\x0ci\xd5\ +\xe35\xbe_\xce\xe4-\xdc\x88\xe73^\x8c\xf7\x07\xbd\ +\xd1I\xe7\xf2\xb3\xeb=\x9fvI\x1dQ\xc2e\xf9\x1c\ +w \xbd'uO\xbe\x01\xa5\xa4\xa0=LD\xddW\ +\xd9\xdc\xb4\xe9\x0f/>\x7f\xaeK\xd5\xe7\xcfFB\xa9\ +\xa5\xd9\xa1\xa4:\x92iI\x0c\x9c\x96\xb5\x14\x01\xaa\x10\ +\x1c\x1b\x0d\x87%\xf0\x0f\xffA\xae\xf9\x83\xb2\xbac\xfb\ +z\xcb\xf6}\xbei\x7f_\xd6c\xeek2\xd2e\xaf\ +QF\xfe\x0cG\xc0\x8f\xf9.\x89\x99q\x88\x06\xa1Q\ +\xa9)h\x22\x99\xe3\x9de\x86\xa4\xa0\xd5\x83#\xea\xd4\ +\x04\xa5\xce(\xcc\xd2!f=\xd4\xdc\x1a\x8e \x9e\xc2\ +\x99\xd9s\xf6*]o\xa2\xb8\x96\x02\xc0\xa1xl8\ +\xf9\x89+Q\xe4O\x8f\xf0\x97\x19\x02\xf4\xaf*\x95!\ +\xee\xd6\xca\xd2\xb5a\x82\xa1\x11\x99<\xb9\xcb+\x06U\ +\x0e\xfd\xf1\xdbn\xfe\xdd\xf5jM\x0d\x22M\x14*\xb7\ +`_\x13\xa73\x0a*\xe7\xe6w<\xef!\xc8\xb2\xe0\ +\x16T\xd4?\xb7Q\x06D\x07\xec=5{\x8f\xa7\xb6\ +M\x98\x15\xb7\x03\xee\x8e\xbf\x7fz\xdeBeK ,\ +_\x90\xb8\xc0\xa5\xaf%q\xc1\x92Pq\xba\xdf\x91\xb9\ +\xa0\x85\xcc\xf4\x04\xd4R\x17\x848\x19\xb9\x0b\x86\xe8T\ +\x905\xa50\xc0Qw\xc8e\x10\x0f\xbdf>\x83\x89\ +'\xdd\x16\x9bmQ\x8b\xb6o\x92L\xcb\xdf\x80\x93\xb8\ +C\x94O\xb4cC\x0c\x97wT\xcfx\xa8RZ'\ +Qg\x064\x12\xab\x89K\xa9\xceQ\xbe\x1e\xa4I\xc5\ +\xec\x1b\xe9\x00h\x22\xa9r4\x86\x8c\xd4\x80\xf6\xf8|\ +\xbe\xf7\xb4\xbb\xbdx\xfd\xd7\xb9Iq\x04]yG\xf5\ +\x90\x17N\x9eC\xdaI\x92\x10\xbfM\xca\x80t\xc2~\ +\xefX\xf7^<\x9e\x80\x8f\x9e/\x9au\x90,\xe3P\ +8'=\xc3s-Lu\x07w\xcb\x22\x1d\xa1{\xac\ +0B\x08jn}\x1b\xb7\xc0WCg\xa1\xb0\x19i\ ++,d\x05yQzt9\xd0\xa3\x96\x0f:;\xc1\ +\x8e\xa8\x5c\xadq\xcd\x16%\xaf\xd1Nn\xf4\x14C\x9b\ +F\x1f1g\xb0\x0d\xab-\x04\x1d2sh\x85\xcb\xfc\ +>S%\xfa\xf9-g\xc7B'i\x91\xd7\xcd`8\ +\x0c\x1c\xfb&E\xf6\x88F\x06\xd8\x16\xd5\x1e\x1b/z\ +\x1a&]O\xfb\xef0\xfd\xd2\xb9\xd8\xec\xea\x0e\x1a\xef\ +E\x9a\x84dxq\x1a\xb0a\xc4/\xc0\x04\xb3j\xf7\ +\xc7\x02\xfc\x8c2\xa6*\x8cW{\x92\x85\xd3\x1f\x06\xe7\ +\x8f\xc6j\x05%\xde?Y\xbaL\xae\xb6\xc68\x8c\x9b\ +\xeb\xcd\x98\x856\x109\x00\x03tT\x11\xaf=]a\ +y\xf0\xdb\xc3^w\xe9\xc7\xaf\xd7\x8d\xed\xb3&\xe4\xb4\ +\x12\x10\xfb\x90\xed\x82\x7f\xc4\xf1\x9b\xde\x9fq\x0e\xa6\x1d\ +\xe1^\xcc\xbb\xee\x04\xbez.&Z\x1f\x0f9\xddt\ +\xda7\xee\xfb\xb0\x03:\xa87\xad\x19\xac0\xf6\x15\xa2\ +_\xf84\xa8\xea\xc5t\xe7\xca\x93\xb0\x8e\xd3\xb0\xf0j\ +\xcaA\x00W\xef\xe8\xf9\x15\xd4\x11]AQ\xd3C\xad\xee\ +^<\x0e]\xbc\x0e4n?\xa9p\xff\x04k\x92Y\ +j:\xaa4\x8d\xd6\xc12\xb4\xdb\xda\xc7g\xdb\xfb\xf2\ +\xab\x96(\xf6.\x0b\x92\x1c\xdfQ\xa3\xc0\x86\x06\x9f\x93\ +f\xa4!\x88\xcd\x13\xacO@V\x1a\x09o\xe2\x99\xf3\ +\x7fb\x8b\x83\xdeJ\xfa\x8b _\x85<]@\xdb\x1b\ +\xfd~\x9f?9\xb1\xc5\x97g\x85\x83\x19\xe1\x936x\ +\x0d\xfeB\x83c\xdc\x08\xba\xc50 $\xae5r/\ +\xcaI\x9f\xf70t\xfd\xc9\xdd\x01\x1a\xe0\x0e!\xfa\xe6\ +\x88\xca\xff\xa4Q\xc9\x10\x16\x81\x8a=g\xc1&\xc5-\ +vS\xa7\xc6\xd1\xc4|W'f\x91ng\x0f\x13\xc3\ +\xfbG\x8a\x0eL\x8a\xe6u\x8a\x9a\xf1\x1dh\x1a\x16\x06\ +\xff\xe28\xda\xe45`\x7fp\xf7\xe2^58~\xe9\ +\xd8\xe2\xf33yzh\xdd\xed\x94\x17\xee\x11z\xac\xa8\ +p\xe8\x9a\x944\xba\xf8\x84+\xa0\x92\xa0O\x11\x9d\xca\ +\xab\xb7\xa2\x85\xd8\x9a`7_I$\x86\xb2\x8b\x84\xae\ +C\xea~\x0e\x8a\xd5\x00\x16\xc7\x22\x85}\x97\x9d\xb3\xc3\ +\xc1\x1f\x0d\x97\x0e\xb6vnP_\xceW`\xe4\xfe*\ +\x8c\xcf\x97\x86\xb2T\xfa\xddy\xfe\x8c\x03bp\xd0\x89\ +\xa3|\xdaUE*\xd8+\xbd\xef\x95+\x04\xe5\x94\xff\ +\xd2\x8b\x03\xe8S\xe20&\x09\xcd\x0dK/\xc2\xf7\x1e\ +=\xf9 u\xc8B\xcf\x985a\xabh\xb9\x8a1\xc0\ +X\xb2EOU3\x9c\x81\xdb\xe03\xb6\xd8\xe7\x81\xbb\ +\xe8\xdd\xe0_\xcf\xc8\xf6\xd2\xfc\x16\x94T\xectA;\ +1\xd0\xda\xa2\xf8\xf9\x02\xfb\x11\x18\x04\xab\x9d\xd3M\x16\ +\x9e\x9fb\xbbs\xfd\x84\x94+\xb1\x8f9F\xed~ \ +z\xb9\xc5\xa5\xa0\x9d\xd3!\xb5?\x1d\x22\xae\xdal\x1a\ +]\xc0\x92\x0c\xf2\xfc\xec@\x86\xc6Y\x5cA\xea\xde\x82\ +\xc2\x8enD\xad\xdcP\x88\xf3\xd4\xa7\xa8p\x0e\xce%\ +\x86\xc7SZ\xa5\x93\xf2\xbaP\xc8\x1aD\xc0zfP\ +\x09\x02\x7f_\xd0\xdc\xb8\x9dS\x0d\x89\x08\xa1\x13\xde\x8a\ +:\xb3\xebZ;\x13\xcfS\xaan\xf0\xbb\xd5\x0b\x16\xb4\ +\xb7\x16ohTt\x0a\x08\x15FJ\xf6X\x16\x5c\xb7\ +I+\xc5U\xff\xb4\xc8k\x22\xb1\xd2\x92@X\xf4L\ +\xb3h!g\xaf6\x7f\x1c\x9f1\x83\x08\x01\xdd\xb7\xe5\ +\x98L.\xfc\xeb)?5\xf7\x1dC\x9a\x0e\x0cAT\ +[\xa1\x98\xbfv\xca\xceE\x9e\x1eJ<\xe8\xf1h\x99\ +\xa4Y\xc8~\xfa1\xdf\xb3\x06&\x1bR\x13\xe9h\x95\ +\xb8\xad\xca\x9dS\x96\x99\xfc\xb6m9\x93%74\xb7\ +c\xec9\x1b\x92\x80\x8c\xe8\xf3N\xe4\xe2\x11]\x85\x1e\ +_H\xed\xc9D\xef\x1e\xcf\xea\xd6&\x1a=\x9ey\xc6\ +t\x8a\xb7\x93\xc6\xd4\xcdVgQQ\x93\xa0@\xac\xae\ +\x04\x04\xc5B\xc5\xa4Z\x8e\xcd\x1e\x04\xc1\ +G\x5cU\xf5\x03t\xdc7\xf1\x12\x9f\x87\xffGF\x16\ +\xfd~\x9aE\xcb(\xf9\x09poB\xfa\x99\x10\xa8\xe0\ +w\x97\x9c]\x02\xbdp\xbfda\x9e\xc6\x9f\xb0q#\ +\xc6\x1e\x13\xb7_\xbcc=G\xa2y\x98\x88\xd9\xe1\xc8\ +\xf5\x0c\xfc\xe1\xf8\x8f\xc4\xfe?\x88\xa8\xa2\x1a\x9b+\x83\ +\xbb\xb7\x0f\x9f\xa7\x01\xf5\xc0\xd5\x929\xdb\xdcj8\x91\ +L\xe0\xae\xa0;\xeb\xfc\xc7e\x8f7\xe5\xfe#\xd5\x06\ +{\x91`\x15!\x0f,\xad\xa6N\x89\x0d\x02O\xee\x9f\ +/\x91\xf8\xff\xa9Y2\xf9\x18\xad\x97\xe8c\xe4\xdc \ +l\xc8\x0cP\xfa\xc2\x14\x93\x0c\xf8Mx\xda\xac\x9a\x84\ +^z4\x7fE\xcc\xc3n\x97\xa6u\x86\x7f\x07\x05\xc6\ +9^\xc0\xe5,M\xe2[z\xce\x05[l\x03JD\ +,Xz\xc5\xcb0.\xaer\xea7\x11\xa1\xd6\xbd\xa7\ +m+IY\x12\x82\xbd\x86\xde\x0d\xfe\x83G\xf6\x1e\x96\ +\xef\xed\x99\x0d\x1bv\xb2\xb6z\xdc\x8e\xda\xea\xf4\xde\xd2\ +\x06A\xba\xbc\xad\xb2\xc2E\xd6\xca\xc6V\xe2\xb9bo\ +\xab}\xec*\x90\xfb\x8a\x0e\xd2\ +w\xc4\x02\x90\xdc\x1f\xc4\x7f\x82\xc5\xf0}H\xa76\xcd\ +\xd5H\xb3\x1f\xe7\xb7\x07;j\xec\x19F8\xdad\xf0\ +\xb7\xd1\xc3\xa7@\xbd\xa3\xa7\xab\xad\xf0\xb4\x0b\x7f2\xf5\ +\xfc\x0b\x11\x8e\xa63\x01l\x9a\xd5+\xda\xaa\xdb\x93\xfa\ +\xb2\x16L\xe2\xdb\xb8L\xb4\x1eU\x8f\x81\xe6\x9c\xea7\ +\xb9\x0d\x96\x19\x0b\xdf\xe6\xad\xe1\xadF\x07\xb5\xf0N\xeb\ +@4\xe1\xb5\xce'\x0e\x85\xc0\xe2W\xf5\xcc'\xac\x9a\ +\xeb\x90~\xcbSDY\xa0\xe3\xe3\x16\xa8\xe6\x8fi#\ +,\x0b\xae\x0a\xf1Lw\x1c\xe4\x05\xcb\xe1\xef\x15zu\ +\xa3\x22\x07e\x0c\xc7\xfe\xb9\xbc*\xeaI\x9c\xb3m\x81\ +x\xd7\x18\x18\xc5\x9d\xb9E\xca\x82\xc5\x82]\x16\xab\xa0\ +\xb8\x94`\x94\x89?\x1a\x0e\x8b4\x05\xc3;\x0a\x8b+\ +\xb0y\x96C\x5c\x87\xc3\xecj\xfe\xe2\xbb?\xbd|&\ +\xde\x90\xea\xbfP\xcb\x02\x7fPz4\xed\x8e\xfcag\ +r1\x9c\xaa'\x18\x91X#R\xb9i\xd80q4\ +\xa4.s\x86\xf2\xe8l\xa7\xf9\xeche\xdewQ\xb7\ +\xc6\x13\xca\xf2\xaa\x88\xb0\x9f5bQY\xe4\x94\x07\xa4\ +\xde\xad;\x16\xebv8T\x8b[\x88\x81\xdd\xe7H\xa4\ +\x09a\xaf#z\x06\x1c\xf1\xf0\xcb\x1e\x95LG\xa8+\ +J\xe3\x01\xbc\xae\xe2\xa3g\xf4@Q\xc9\xb5.jh\ +L\x10\x90Ir\xd3\x88\xa13\xfe\xfb~\xdc\xb8\xad_\ +\xbeP6\xd87\xe5\x05\xff5v\xf8K<\xa8\xd4\x19\ +A\xd9\xf8\xd9t\x18\x9d\x18\x22\x8eOA\xf1\x0b\x02\xfc\ +Dq\xe9\xa8[\xe1\xb3\x09\xc5\xdd\x80\xe9\xec\x83\x91\xdc\ +\x0d`G\xfaG\xce\xa0^\x1d\xf6?\x86\xb7\xd5 J\ +\xa8\xdf\xe23@\x8d\x87@\xde\x1a\xf0)(:\xfca\ +\x15\xa1\x00|\xf4\xfe<\x81\xd9\x89\x93of\x1f@\x8a\ +\xcd\xa0\xa3 \x7fs\x9d\xbc\x95O\x01\xcc\x038\xdc\x09\ +\xea\x90.+\xdf\x11\xc63\x812J\xb1%\x10\xfaf\ +\x9f\xb1j\xe1\xeb\xb3\x0f\xb6\x8e0\x1e\xf4\xa4\x83\xd7/\ +\xe9u\x8f\xd1\xfb\xec\x9aWt\xa0\xa5^8\x80!#\ +\xf8\xcb\x93\xa0\x0eK\xa1\x0eYi\ +?\xfa,\xc2\xca\xeb\x09\xa2\xf3~_J\x1d\x8c\xd8\x1c\ +\x0c\x1fP\x05Z\x87\xe0\x1b\x1e}f8\xf1-\xd1\xec\ +U\x82\xef-!5\x07o\xca\x9c\x04\xe21\xf9\x22\x9e\ +\x1fs-\xf9w\xb16\x06\xfa\x1a\xfeiC2\x07\xc5\ +\x0c\x5c\x8cg\x0a\x9c\xd4*\x9b3\x06\xf0\xcfn\xd6i\ +\xb1\xf7\xc4j@\x9f\xbc%(\x9c^\xa9\xfe\xf5\x9a\xa2\ +l\x06<\xb9=F\xed\x09\x94b\xec\xd6\x22lPM\ +\xbaI}5\x86\x83u\x98\xe7\x18\xfb\xc0o\xed\xde\xc6\ +!\xee\x95\xb0W\xa7YA\xc7+p\xab\xd8)\x83j\xbc\xe212\x1e8\x98c\ +\xe4W\xc8\xc9\x17&\x81\xb4\xa5\xa5\x81\xf1fc\xa4\xae\ +\x09\x8aU$\x82,\xc8\xc3\xe2\x8d\x8aNP\xd2\xae\x0e\ +\xda|\xb2Z'J\x0c\x93\xd7\xf3\xabM\x01\x0b\xd6\xe6\ +\x8f\x02\xdc\x0an\xb1\x9cH\x9c[\xc2\xee\xe7i\x82|\ +\xab\xe2\xafG\xc9{\x07~\xfc\xbdZ\x8b\xdb\x1e\xfa\xaa\ +\xf2\x16\xea\x85<\xf9`\xa4n\xc8\xd4*7{\xd0y\ +&\xf8\xe3*\xf0e\x0b<\xef\x8b\x16<\xe7\xca\xc4,\ +\x9f\xa6\xb0H\xb2c\x04t|\x00\xaf\x95a\x93V\x13\ +\xf5\xbc\x87I\x0b\x17\x1e\x1bN\xfd\xceT\xbd\x98\xe7\x0d\ +Z\xe5\xfcw\xc2M\x82)\xa8K\xc0\xec\xc9\x83\x7fe\ +\x1eq1\xd6f\xcb|\xa5\x92?\xbee\x09\xd0[\x19\ +a\xc2?\x9c\xc8\xf2\x8d]\xce\xbfkqP\xd1\x1bg\ +\x8aO\xaa\xa9\x15\xddqf\xc5Zh\x04\xaf\xc5o\x89\ +\xd3\xbf\xaail\x96\xe27\xdd\xc0\x0c#93\xe3@\ +T\xe3\xa8\x0dB\xb8d5.\x19\xf0\x22\xe5|\xcf\xb0\ +m\xd7\xe9b\x1b\x8b}\xc9\xb0\xae\x9f?\x97\xa6$\x18\ +\x9d\xa0prnN\xa6d\xb1\x8a\xbd\x8b7\x1d(\x00\ +\xbd\x8e\x8cGn8\x12\x8e\xb7b\x92b'\xbcb\x10\ +\xacE*\x03\xff\xee\x9a.\xa2\xca*\xe5\x1e6}T\ +\xca\xd2\xb4\x18\xf0:\x93\x84=T\xf4\xa8$\xf1E\x0d\ +A\xc5u\x94,@\xd3T\xc7:\x96\x15#\xb6\x8c\xd3\ +Y\x10\xa3{\xef\xbf\x01\x9e\xed\xc5)\ +" + +qt_resource_name = b"\ +\x00\x0a\ +\x08\xce\x22\xb4\ +\x00d\ +\x00e\x00f\x00a\x00u\x00l\x00t\x00.\x00m\x00d\ +\x00\x08\ +\x08\xb6\x8e\xf9\ +\x003\ +\x00r\x00d\x00p\x00a\x00r\x00t\x00y\ +\x00\x0a\ +\x0c\xba\xf2|\ +\x00i\ +\x00n\x00d\x00e\x00x\x00.\x00h\x00t\x00m\x00l\ +\x00\x0c\ +\x08\xd0i\xc3\ +\x00m\ +\x00a\x00r\x00k\x00d\x00o\x00w\x00n\x00.\x00c\x00s\x00s\ +\x00\x09\ +\x09\x1b\x92\x13\ +\x00m\ +\x00a\x00r\x00k\x00e\x00d\x00.\x00j\x00s\ +" + +qt_resource_struct = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x1a\x00\x02\x00\x00\x00\x02\x00\x00\x00\x04\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x01z.[\x95V\ +\x00\x00\x000\x00\x00\x00\x00\x00\x01\x00\x00\x01\xe1\ +\x00\x00\x01z.[\x95V\ +\x00\x00\x00J\x00\x01\x00\x00\x00\x01\x00\x00\x04\x97\ +\x00\x00\x01z.[\x95V\ +\x00\x00\x00h\x00\x01\x00\x00\x00\x01\x00\x00\x0a\xf1\ +\x00\x00\x01z.[\x95V\ +" + +def qInitResources(): + QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data) + +def qCleanupResources(): + QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data) + +qInitResources() diff --git a/examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKDOWN-LICENSE.txt b/examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKDOWN-LICENSE.txt new file mode 100644 index 000000000..23c52cc43 --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKDOWN-LICENSE.txt @@ -0,0 +1,16 @@ +Copyright 2011 Kevin Burke unless otherwise noted. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Some content is copyrighted by Twitter, Inc., and also released under an +Apache License; these sections are noted in the source. diff --git a/examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKED-LICENSE.txt b/examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKED-LICENSE.txt new file mode 100644 index 000000000..8e3ba0e0a --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKED-LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2011-2018, Christopher Jeffrey (https://github.com/chjj/) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/examples/webenginewidgets/markdowneditor/resources/3rdparty/markdown.css b/examples/webenginewidgets/markdowneditor/resources/3rdparty/markdown.css new file mode 100644 index 000000000..24fc2ffe2 --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/resources/3rdparty/markdown.css @@ -0,0 +1,260 @@ +body{ + margin: 0 auto; + font-family: Georgia, Palatino, serif; + color: #444444; + line-height: 1; + max-width: 960px; + padding: 30px; +} +h1, h2, h3, h4 { + color: #111111; + font-weight: 400; +} +h1, h2, h3, h4, h5, p { + margin-bottom: 24px; + padding: 0; +} +h1 { + font-size: 48px; +} +h2 { + font-size: 36px; + /* The bottom margin is small. It's designed to be used with gray meta text + * below a post title. */ + margin: 24px 0 6px; +} +h3 { + font-size: 24px; +} +h4 { + font-size: 21px; +} +h5 { + font-size: 18px; +} +a { + color: #0099ff; + margin: 0; + padding: 0; + vertical-align: baseline; +} +a:hover { + text-decoration: none; + color: #ff6600; +} +a:visited { + color: purple; +} +ul, ol { + padding: 0; + margin: 0; +} +li { + line-height: 24px; +} +li ul, li ul { + margin-left: 24px; +} +p, ul, ol { + font-size: 16px; + line-height: 24px; + max-width: 540px; +} +pre { + padding: 0px 24px; + max-width: 800px; + white-space: pre-wrap; +} +code { + font-family: Consolas, Monaco, Andale Mono, monospace; + line-height: 1.5; + font-size: 13px; +} +aside { + display: block; + float: right; + width: 390px; +} +blockquote { + border-left:.5em solid #eee; + padding: 0 2em; + margin-left:0; + max-width: 476px; +} +blockquote cite { + font-size:14px; + line-height:20px; + color:#bfbfbf; +} +blockquote cite:before { + content: '\2014 \00A0'; +} + +blockquote p { + color: #666; + max-width: 460px; +} +hr { + width: 540px; + text-align: left; + margin: 0 auto 0 0; + color: #999; +} + +/* Code below this line is copyright Twitter Inc. */ + +button, +input, +select, +textarea { + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle; +} +button, input { + line-height: normal; + *overflow: visible; +} +button::-moz-focus-inner, input::-moz-focus-inner { + border: 0; + padding: 0; +} +button, +input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; +} +input[type=checkbox], input[type=radio] { + cursor: pointer; +} +/* override default chrome & firefox settings */ +input:not([type="image"]), textarea { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} + +input[type="search"] { + -webkit-appearance: textfield; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +label, +input, +select, +textarea { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: normal; + margin-bottom: 18px; +} +input[type=checkbox], input[type=radio] { + cursor: pointer; + margin-bottom: 0; +} +input[type=text], +input[type=password], +textarea, +select { + display: inline-block; + width: 210px; + padding: 4px; + font-size: 13px; + font-weight: normal; + line-height: 18px; + height: 18px; + color: #808080; + border: 1px solid #ccc; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +select, input[type=file] { + height: 27px; + line-height: 27px; +} +textarea { + height: auto; +} + +/* grey out placeholders */ +:-moz-placeholder { + color: #bfbfbf; +} +::-webkit-input-placeholder { + color: #bfbfbf; +} + +input[type=text], +input[type=password], +select, +textarea { + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -moz-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); +} +input[type=text]:focus, input[type=password]:focus, textarea:focus { + outline: none; + border-color: rgba(82, 168, 236, 0.8); + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); + -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); +} + +/* buttons */ +button { + display: inline-block; + padding: 4px 14px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + line-height: 18px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + background-color: #0064cd; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd)); + background-image: -moz-linear-gradient(top, #049cdb, #0064cd); + background-image: -ms-linear-gradient(top, #049cdb, #0064cd); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd)); + background-image: -webkit-linear-gradient(top, #049cdb, #0064cd); + background-image: -o-linear-gradient(top, #049cdb, #0064cd); + background-image: linear-gradient(top, #049cdb, #0064cd); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border: 1px solid #004b9a; + border-bottom-color: #003f81; + -webkit-transition: 0.1s linear all; + -moz-transition: 0.1s linear all; + transition: 0.1s linear all; + border-color: #0064cd #0064cd #003f81; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +button:hover { + color: #fff; + background-position: 0 -15px; + text-decoration: none; +} +button:active { + -webkit-box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); +} +button::-moz-focus-inner { + padding: 0; + border: 0; +} diff --git a/examples/webenginewidgets/markdowneditor/resources/3rdparty/marked.js b/examples/webenginewidgets/markdowneditor/resources/3rdparty/marked.js new file mode 100644 index 000000000..33c02d9cf --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/resources/3rdparty/marked.js @@ -0,0 +1,1514 @@ +/** + * marked - a markdown parser + * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) + * https://github.com/markedjs/marked + */ + +;(function(root) { +'use strict'; + +/** + * Block-Level Grammar + */ + +var block = { + newline: /^\n+/, + code: /^( {4}[^\n]+\n*)+/, + fences: noop, + hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/, + heading: /^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/, + nptable: noop, + blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/, + list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, + html: '^ {0,3}(?:' // optional indentation + + '<(script|pre|style)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)' // (1) + + '|comment[^\\n]*(\\n+|$)' // (2) + + '|<\\?[\\s\\S]*?\\?>\\n*' // (3) + + '|\\n*' // (4) + + '|\\n*' // (5) + + '|)[\\s\\S]*?(?:\\n{2,}|$)' // (6) + + '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$)' // (7) open tag + + '|(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$)' // (7) closing tag + + ')', + def: /^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/, + table: noop, + lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/, + paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading| {0,3}>|<\/?(?:tag)(?: +|\n|\/?>)|<(?:script|pre|style|!--))[^\n]+)*)/, + text: /^[^\n]+/ +}; + +block._label = /(?!\s*\])(?:\\[\[\]]|[^\[\]])+/; +block._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/; +block.def = edit(block.def) + .replace('label', block._label) + .replace('title', block._title) + .getRegex(); + +block.bullet = /(?:[*+-]|\d+\.)/; +block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/; +block.item = edit(block.item, 'gm') + .replace(/bull/g, block.bullet) + .getRegex(); + +block.list = edit(block.list) + .replace(/bull/g, block.bullet) + .replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))') + .replace('def', '\\n+(?=' + block.def.source + ')') + .getRegex(); + +block._tag = 'address|article|aside|base|basefont|blockquote|body|caption' + + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption' + + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe' + + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option' + + '|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr' + + '|track|ul'; +block._comment = //; +block.html = edit(block.html, 'i') + .replace('comment', block._comment) + .replace('tag', block._tag) + .replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/) + .getRegex(); + +block.paragraph = edit(block.paragraph) + .replace('hr', block.hr) + .replace('heading', block.heading) + .replace('lheading', block.lheading) + .replace('tag', block._tag) // pars can be interrupted by type (6) html blocks + .getRegex(); + +block.blockquote = edit(block.blockquote) + .replace('paragraph', block.paragraph) + .getRegex(); + +/** + * Normal Block Grammar + */ + +block.normal = merge({}, block); + +/** + * GFM Block Grammar + */ + +block.gfm = merge({}, block.normal, { + fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\n? *\1 *(?:\n+|$)/, + paragraph: /^/, + heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/ +}); + +block.gfm.paragraph = edit(block.paragraph) + .replace('(?!', '(?!' + + block.gfm.fences.source.replace('\\1', '\\2') + '|' + + block.list.source.replace('\\1', '\\3') + '|') + .getRegex(); + +/** + * GFM + Tables Block Grammar + */ + +block.tables = merge({}, block.gfm, { + nptable: /^ *([^|\n ].*\|.*)\n *([-:]+ *\|[-| :]*)(?:\n((?:.*[^>\n ].*(?:\n|$))*)\n*|$)/, + table: /^ *\|(.+)\n *\|?( *[-:]+[-| :]*)(?:\n((?: *[^>\n ].*(?:\n|$))*)\n*|$)/ +}); + +/** + * Pedantic grammar + */ + +block.pedantic = merge({}, block.normal, { + html: edit( + '^ *(?:comment *(?:\\n|\\s*$)' + + '|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)' // closed tag + + '|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))') + .replace('comment', block._comment) + .replace(/tag/g, '(?!(?:' + + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub' + + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)' + + '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b') + .getRegex(), + def: /^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/ +}); + +/** + * Block Lexer + */ + +function Lexer(options) { + this.tokens = []; + this.tokens.links = {}; + this.options = options || marked.defaults; + this.rules = block.normal; + + if (this.options.pedantic) { + this.rules = block.pedantic; + } else if (this.options.gfm) { + if (this.options.tables) { + this.rules = block.tables; + } else { + this.rules = block.gfm; + } + } +} + +/** + * Expose Block Rules + */ + +Lexer.rules = block; + +/** + * Static Lex Method + */ + +Lexer.lex = function(src, options) { + var lexer = new Lexer(options); + return lexer.lex(src); +}; + +/** + * Preprocessing + */ + +Lexer.prototype.lex = function(src) { + src = src + .replace(/\r\n|\r/g, '\n') + .replace(/\t/g, ' ') + .replace(/\u00a0/g, ' ') + .replace(/\u2424/g, '\n'); + + return this.token(src, true); +}; + +/** + * Lexing + */ + +Lexer.prototype.token = function(src, top) { + src = src.replace(/^ +$/gm, ''); + var next, + loose, + cap, + bull, + b, + item, + space, + i, + tag, + l, + isordered, + istask, + ischecked; + + while (src) { + // newline + if (cap = this.rules.newline.exec(src)) { + src = src.substring(cap[0].length); + if (cap[0].length > 1) { + this.tokens.push({ + type: 'space' + }); + } + } + + // code + if (cap = this.rules.code.exec(src)) { + src = src.substring(cap[0].length); + cap = cap[0].replace(/^ {4}/gm, ''); + this.tokens.push({ + type: 'code', + text: !this.options.pedantic + ? cap.replace(/\n+$/, '') + : cap + }); + continue; + } + + // fences (gfm) + if (cap = this.rules.fences.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'code', + lang: cap[2], + text: cap[3] || '' + }); + continue; + } + + // heading + if (cap = this.rules.heading.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'heading', + depth: cap[1].length, + text: cap[2] + }); + continue; + } + + // table no leading pipe (gfm) + if (top && (cap = this.rules.nptable.exec(src))) { + item = { + type: 'table', + header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : [] + }; + + if (item.header.length === item.align.length) { + src = src.substring(cap[0].length); + + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = splitCells(item.cells[i], item.header.length); + } + + this.tokens.push(item); + + continue; + } + } + + // hr + if (cap = this.rules.hr.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'hr' + }); + continue; + } + + // blockquote + if (cap = this.rules.blockquote.exec(src)) { + src = src.substring(cap[0].length); + + this.tokens.push({ + type: 'blockquote_start' + }); + + cap = cap[0].replace(/^ *> ?/gm, ''); + + // Pass `top` to keep the current + // "toplevel" state. This is exactly + // how markdown.pl works. + this.token(cap, top); + + this.tokens.push({ + type: 'blockquote_end' + }); + + continue; + } + + // list + if (cap = this.rules.list.exec(src)) { + src = src.substring(cap[0].length); + bull = cap[2]; + isordered = bull.length > 1; + + this.tokens.push({ + type: 'list_start', + ordered: isordered, + start: isordered ? +bull : '' + }); + + // Get each top-level item. + cap = cap[0].match(this.rules.item); + + next = false; + l = cap.length; + i = 0; + + for (; i < l; i++) { + item = cap[i]; + + // Remove the list item's bullet + // so it is seen as the next token. + space = item.length; + item = item.replace(/^ *([*+-]|\d+\.) +/, ''); + + // Outdent whatever the + // list item contains. Hacky. + if (~item.indexOf('\n ')) { + space -= item.length; + item = !this.options.pedantic + ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') + : item.replace(/^ {1,4}/gm, ''); + } + + // Determine whether the next list item belongs here. + // Backpedal if it does not belong in this list. + if (this.options.smartLists && i !== l - 1) { + b = block.bullet.exec(cap[i + 1])[0]; + if (bull !== b && !(bull.length > 1 && b.length > 1)) { + src = cap.slice(i + 1).join('\n') + src; + i = l - 1; + } + } + + // Determine whether item is loose or not. + // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/ + // for discount behavior. + loose = next || /\n\n(?!\s*$)/.test(item); + if (i !== l - 1) { + next = item.charAt(item.length - 1) === '\n'; + if (!loose) loose = next; + } + + // Check for task list items + istask = /^\[[ xX]\] /.test(item); + ischecked = undefined; + if (istask) { + ischecked = item[1] !== ' '; + item = item.replace(/^\[[ xX]\] +/, ''); + } + + this.tokens.push({ + type: loose + ? 'loose_item_start' + : 'list_item_start', + task: istask, + checked: ischecked + }); + + // Recurse. + this.token(item, false); + + this.tokens.push({ + type: 'list_item_end' + }); + } + + this.tokens.push({ + type: 'list_end' + }); + + continue; + } + + // html + if (cap = this.rules.html.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: this.options.sanitize + ? 'paragraph' + : 'html', + pre: !this.options.sanitizer + && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'), + text: cap[0] + }); + continue; + } + + // def + if (top && (cap = this.rules.def.exec(src))) { + src = src.substring(cap[0].length); + if (cap[3]) cap[3] = cap[3].substring(1, cap[3].length - 1); + tag = cap[1].toLowerCase().replace(/\s+/g, ' '); + if (!this.tokens.links[tag]) { + this.tokens.links[tag] = { + href: cap[2], + title: cap[3] + }; + } + continue; + } + + // table (gfm) + if (top && (cap = this.rules.table.exec(src))) { + item = { + type: 'table', + header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3] ? cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') : [] + }; + + if (item.header.length === item.align.length) { + src = src.substring(cap[0].length); + + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = splitCells( + item.cells[i].replace(/^ *\| *| *\| *$/g, ''), + item.header.length); + } + + this.tokens.push(item); + + continue; + } + } + + // lheading + if (cap = this.rules.lheading.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'heading', + depth: cap[2] === '=' ? 1 : 2, + text: cap[1] + }); + continue; + } + + // top-level paragraph + if (top && (cap = this.rules.paragraph.exec(src))) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'paragraph', + text: cap[1].charAt(cap[1].length - 1) === '\n' + ? cap[1].slice(0, -1) + : cap[1] + }); + continue; + } + + // text + if (cap = this.rules.text.exec(src)) { + // Top-level should never reach here. + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'text', + text: cap[0] + }); + continue; + } + + if (src) { + throw new Error('Infinite loop on byte: ' + src.charCodeAt(0)); + } + } + + return this.tokens; +}; + +/** + * Inline-Level Grammar + */ + +var inline = { + escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/, + autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/, + url: noop, + tag: '^comment' + + '|^' // self-closing tag + + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag + + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. + + '|^' // declaration, e.g. + + '|^', // CDATA section + link: /^!?\[(label)\]\(href(?:\s+(title))?\s*\)/, + reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/, + nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/, + strong: /^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)|^__([^\s])__(?!_)|^\*\*([^\s])\*\*(?!\*)/, + em: /^_([^\s][\s\S]*?[^\s_])_(?!_)|^_([^\s_][\s\S]*?[^\s])_(?!_)|^\*([^\s][\s\S]*?[^\s*])\*(?!\*)|^\*([^\s*][\s\S]*?[^\s])\*(?!\*)|^_([^\s_])_(?!_)|^\*([^\s*])\*(?!\*)/, + code: /^(`+)\s*([\s\S]*?[^`]?)\s*\1(?!`)/, + br: /^ {2,}\n(?!\s*$)/, + del: noop, + text: /^[\s\S]+?(?=[\\?@\[\]\\^_`{|}~])/g; + +inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/; +inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/; +inline.autolink = edit(inline.autolink) + .replace('scheme', inline._scheme) + .replace('email', inline._email) + .getRegex(); + +inline._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/; + +inline.tag = edit(inline.tag) + .replace('comment', block._comment) + .replace('attribute', inline._attribute) + .getRegex(); + +inline._label = /(?:\[[^\[\]]*\]|\\[\[\]]?|`[^`]*`|[^\[\]\\])*?/; +inline._href = /\s*(<(?:\\[<>]?|[^\s<>\\])*>|(?:\\[()]?|\([^\s\x00-\x1f()\\]*\)|[^\s\x00-\x1f()\\])*?)/; +inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/; + +inline.link = edit(inline.link) + .replace('label', inline._label) + .replace('href', inline._href) + .replace('title', inline._title) + .getRegex(); + +inline.reflink = edit(inline.reflink) + .replace('label', inline._label) + .getRegex(); + +/** + * Normal Inline Grammar + */ + +inline.normal = merge({}, inline); + +/** + * Pedantic Inline Grammar + */ + +inline.pedantic = merge({}, inline.normal, { + strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, + em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/, + link: edit(/^!?\[(label)\]\((.*?)\)/) + .replace('label', inline._label) + .getRegex(), + reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/) + .replace('label', inline._label) + .getRegex() +}); + +/** + * GFM Inline Grammar + */ + +inline.gfm = merge({}, inline.normal, { + escape: edit(inline.escape).replace('])', '~|])').getRegex(), + url: edit(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/) + .replace('email', inline._email) + .getRegex(), + _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/, + del: /^~~(?=\S)([\s\S]*?\S)~~/, + text: edit(inline.text) + .replace(']|', '~]|') + .replace('|', '|https?://|ftp://|www\\.|[a-zA-Z0-9.!#$%&\'*+/=?^_`{\\|}~-]+@|') + .getRegex() +}); + +/** + * GFM + Line Breaks Inline Grammar + */ + +inline.breaks = merge({}, inline.gfm, { + br: edit(inline.br).replace('{2,}', '*').getRegex(), + text: edit(inline.gfm.text).replace('{2,}', '*').getRegex() +}); + +/** + * Inline Lexer & Compiler + */ + +function InlineLexer(links, options) { + this.options = options || marked.defaults; + this.links = links; + this.rules = inline.normal; + this.renderer = this.options.renderer || new Renderer(); + this.renderer.options = this.options; + + if (!this.links) { + throw new Error('Tokens array requires a `links` property.'); + } + + if (this.options.pedantic) { + this.rules = inline.pedantic; + } else if (this.options.gfm) { + if (this.options.breaks) { + this.rules = inline.breaks; + } else { + this.rules = inline.gfm; + } + } +} + +/** + * Expose Inline Rules + */ + +InlineLexer.rules = inline; + +/** + * Static Lexing/Compiling Method + */ + +InlineLexer.output = function(src, links, options) { + var inline = new InlineLexer(links, options); + return inline.output(src); +}; + +/** + * Lexing/Compiling + */ + +InlineLexer.prototype.output = function(src) { + var out = '', + link, + text, + href, + title, + cap; + + while (src) { + // escape + if (cap = this.rules.escape.exec(src)) { + src = src.substring(cap[0].length); + out += cap[1]; + continue; + } + + // autolink + if (cap = this.rules.autolink.exec(src)) { + src = src.substring(cap[0].length); + if (cap[2] === '@') { + text = escape(this.mangle(cap[1])); + href = 'mailto:' + text; + } else { + text = escape(cap[1]); + href = text; + } + out += this.renderer.link(href, null, text); + continue; + } + + // url (gfm) + if (!this.inLink && (cap = this.rules.url.exec(src))) { + cap[0] = this.rules._backpedal.exec(cap[0])[0]; + src = src.substring(cap[0].length); + if (cap[2] === '@') { + text = escape(cap[0]); + href = 'mailto:' + text; + } else { + text = escape(cap[0]); + if (cap[1] === 'www.') { + href = 'http://' + text; + } else { + href = text; + } + } + out += this.renderer.link(href, null, text); + continue; + } + + // tag + if (cap = this.rules.tag.exec(src)) { + if (!this.inLink && /^/i.test(cap[0])) { + this.inLink = false; + } + src = src.substring(cap[0].length); + out += this.options.sanitize + ? this.options.sanitizer + ? this.options.sanitizer(cap[0]) + : escape(cap[0]) + : cap[0] + continue; + } + + // link + if (cap = this.rules.link.exec(src)) { + src = src.substring(cap[0].length); + this.inLink = true; + href = cap[2]; + if (this.options.pedantic) { + link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href); + + if (link) { + href = link[1]; + title = link[3]; + } else { + title = ''; + } + } else { + title = cap[3] ? cap[3].slice(1, -1) : ''; + } + href = href.trim().replace(/^<([\s\S]*)>$/, '$1'); + out += this.outputLink(cap, { + href: InlineLexer.escapes(href), + title: InlineLexer.escapes(title) + }); + this.inLink = false; + continue; + } + + // reflink, nolink + if ((cap = this.rules.reflink.exec(src)) + || (cap = this.rules.nolink.exec(src))) { + src = src.substring(cap[0].length); + link = (cap[2] || cap[1]).replace(/\s+/g, ' '); + link = this.links[link.toLowerCase()]; + if (!link || !link.href) { + out += cap[0].charAt(0); + src = cap[0].substring(1) + src; + continue; + } + this.inLink = true; + out += this.outputLink(cap, link); + this.inLink = false; + continue; + } + + // strong + if (cap = this.rules.strong.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.strong(this.output(cap[4] || cap[3] || cap[2] || cap[1])); + continue; + } + + // em + if (cap = this.rules.em.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.em(this.output(cap[6] || cap[5] || cap[4] || cap[3] || cap[2] || cap[1])); + continue; + } + + // code + if (cap = this.rules.code.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.codespan(escape(cap[2].trim(), true)); + continue; + } + + // br + if (cap = this.rules.br.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.br(); + continue; + } + + // del (gfm) + if (cap = this.rules.del.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.del(this.output(cap[1])); + continue; + } + + // text + if (cap = this.rules.text.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.text(escape(this.smartypants(cap[0]))); + continue; + } + + if (src) { + throw new Error('Infinite loop on byte: ' + src.charCodeAt(0)); + } + } + + return out; +}; + +InlineLexer.escapes = function(text) { + return text ? text.replace(InlineLexer.rules._escapes, '$1') : text; +} + +/** + * Compile Link + */ + +InlineLexer.prototype.outputLink = function(cap, link) { + var href = link.href, + title = link.title ? escape(link.title) : null; + + return cap[0].charAt(0) !== '!' + ? this.renderer.link(href, title, this.output(cap[1])) + : this.renderer.image(href, title, escape(cap[1])); +}; + +/** + * Smartypants Transformations + */ + +InlineLexer.prototype.smartypants = function(text) { + if (!this.options.smartypants) return text; + return text + // em-dashes + .replace(/---/g, '\u2014') + // en-dashes + .replace(/--/g, '\u2013') + // opening singles + .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018') + // closing singles & apostrophes + .replace(/'/g, '\u2019') + // opening doubles + .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c') + // closing doubles + .replace(/"/g, '\u201d') + // ellipses + .replace(/\.{3}/g, '\u2026'); +}; + +/** + * Mangle Links + */ + +InlineLexer.prototype.mangle = function(text) { + if (!this.options.mangle) return text; + var out = '', + l = text.length, + i = 0, + ch; + + for (; i < l; i++) { + ch = text.charCodeAt(i); + if (Math.random() > 0.5) { + ch = 'x' + ch.toString(16); + } + out += '&#' + ch + ';'; + } + + return out; +}; + +/** + * Renderer + */ + +function Renderer(options) { + this.options = options || marked.defaults; +} + +Renderer.prototype.code = function(code, lang, escaped) { + if (this.options.highlight) { + var out = this.options.highlight(code, lang); + if (out != null && out !== code) { + escaped = true; + code = out; + } + } + + if (!lang) { + return '
'
+      + (escaped ? code : escape(code, true))
+      + '
'; + } + + return '
'
+    + (escaped ? code : escape(code, true))
+    + '
\n'; +}; + +Renderer.prototype.blockquote = function(quote) { + return '
\n' + quote + '
\n'; +}; + +Renderer.prototype.html = function(html) { + return html; +}; + +Renderer.prototype.heading = function(text, level, raw) { + if (this.options.headerIds) { + return '' + + text + + '\n'; + } + // ignore IDs + return '' + text + '\n'; +}; + +Renderer.prototype.hr = function() { + return this.options.xhtml ? '
\n' : '
\n'; +}; + +Renderer.prototype.list = function(body, ordered, start) { + var type = ordered ? 'ol' : 'ul', + startatt = (ordered && start !== 1) ? (' start="' + start + '"') : ''; + return '<' + type + startatt + '>\n' + body + '\n'; +}; + +Renderer.prototype.listitem = function(text) { + return '
  • ' + text + '
  • \n'; +}; + +Renderer.prototype.checkbox = function(checked) { + return ' '; +} + +Renderer.prototype.paragraph = function(text) { + return '

    ' + text + '

    \n'; +}; + +Renderer.prototype.table = function(header, body) { + if (body) body = '' + body + ''; + + return '\n' + + '\n' + + header + + '\n' + + body + + '
    \n'; +}; + +Renderer.prototype.tablerow = function(content) { + return '\n' + content + '\n'; +}; + +Renderer.prototype.tablecell = function(content, flags) { + var type = flags.header ? 'th' : 'td'; + var tag = flags.align + ? '<' + type + ' align="' + flags.align + '">' + : '<' + type + '>'; + return tag + content + '\n'; +}; + +// span level renderer +Renderer.prototype.strong = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.em = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.codespan = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.br = function() { + return this.options.xhtml ? '
    ' : '
    '; +}; + +Renderer.prototype.del = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.link = function(href, title, text) { + if (this.options.sanitize) { + try { + var prot = decodeURIComponent(unescape(href)) + .replace(/[^\w:]/g, '') + .toLowerCase(); + } catch (e) { + return text; + } + if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) { + return text; + } + } + if (this.options.baseUrl && !originIndependentUrl.test(href)) { + href = resolveUrl(this.options.baseUrl, href); + } + try { + href = encodeURI(href).replace(/%25/g, '%'); + } catch (e) { + return text; + } + var out = '
    '; + return out; +}; + +Renderer.prototype.image = function(href, title, text) { + if (this.options.baseUrl && !originIndependentUrl.test(href)) { + href = resolveUrl(this.options.baseUrl, href); + } + var out = '' + text + '' : '>'; + return out; +}; + +Renderer.prototype.text = function(text) { + return text; +}; + +/** + * TextRenderer + * returns only the textual part of the token + */ + +function TextRenderer() {} + +// no need for block level renderers + +TextRenderer.prototype.strong = +TextRenderer.prototype.em = +TextRenderer.prototype.codespan = +TextRenderer.prototype.del = +TextRenderer.prototype.text = function (text) { + return text; +} + +TextRenderer.prototype.link = +TextRenderer.prototype.image = function(href, title, text) { + return '' + text; +} + +TextRenderer.prototype.br = function() { + return ''; +} + +/** + * Parsing & Compiling + */ + +function Parser(options) { + this.tokens = []; + this.token = null; + this.options = options || marked.defaults; + this.options.renderer = this.options.renderer || new Renderer(); + this.renderer = this.options.renderer; + this.renderer.options = this.options; +} + +/** + * Static Parse Method + */ + +Parser.parse = function(src, options) { + var parser = new Parser(options); + return parser.parse(src); +}; + +/** + * Parse Loop + */ + +Parser.prototype.parse = function(src) { + this.inline = new InlineLexer(src.links, this.options); + // use an InlineLexer with a TextRenderer to extract pure text + this.inlineText = new InlineLexer( + src.links, + merge({}, this.options, {renderer: new TextRenderer()}) + ); + this.tokens = src.reverse(); + + var out = ''; + while (this.next()) { + out += this.tok(); + } + + return out; +}; + +/** + * Next Token + */ + +Parser.prototype.next = function() { + return this.token = this.tokens.pop(); +}; + +/** + * Preview Next Token + */ + +Parser.prototype.peek = function() { + return this.tokens[this.tokens.length - 1] || 0; +}; + +/** + * Parse Text Tokens + */ + +Parser.prototype.parseText = function() { + var body = this.token.text; + + while (this.peek().type === 'text') { + body += '\n' + this.next().text; + } + + return this.inline.output(body); +}; + +/** + * Parse Current Token + */ + +Parser.prototype.tok = function() { + switch (this.token.type) { + case 'space': { + return ''; + } + case 'hr': { + return this.renderer.hr(); + } + case 'heading': { + return this.renderer.heading( + this.inline.output(this.token.text), + this.token.depth, + unescape(this.inlineText.output(this.token.text))); + } + case 'code': { + return this.renderer.code(this.token.text, + this.token.lang, + this.token.escaped); + } + case 'table': { + var header = '', + body = '', + i, + row, + cell, + j; + + // header + cell = ''; + for (i = 0; i < this.token.header.length; i++) { + cell += this.renderer.tablecell( + this.inline.output(this.token.header[i]), + { header: true, align: this.token.align[i] } + ); + } + header += this.renderer.tablerow(cell); + + for (i = 0; i < this.token.cells.length; i++) { + row = this.token.cells[i]; + + cell = ''; + for (j = 0; j < row.length; j++) { + cell += this.renderer.tablecell( + this.inline.output(row[j]), + { header: false, align: this.token.align[j] } + ); + } + + body += this.renderer.tablerow(cell); + } + return this.renderer.table(header, body); + } + case 'blockquote_start': { + body = ''; + + while (this.next().type !== 'blockquote_end') { + body += this.tok(); + } + + return this.renderer.blockquote(body); + } + case 'list_start': { + body = ''; + var ordered = this.token.ordered, + start = this.token.start; + + while (this.next().type !== 'list_end') { + body += this.tok(); + } + + return this.renderer.list(body, ordered, start); + } + case 'list_item_start': { + body = ''; + + if (this.token.task) { + body += this.renderer.checkbox(this.token.checked); + } + + while (this.next().type !== 'list_item_end') { + body += this.token.type === 'text' + ? this.parseText() + : this.tok(); + } + + return this.renderer.listitem(body); + } + case 'loose_item_start': { + body = ''; + + while (this.next().type !== 'list_item_end') { + body += this.tok(); + } + + return this.renderer.listitem(body); + } + case 'html': { + // TODO parse inline content if parameter markdown=1 + return this.renderer.html(this.token.text); + } + case 'paragraph': { + return this.renderer.paragraph(this.inline.output(this.token.text)); + } + case 'text': { + return this.renderer.paragraph(this.parseText()); + } + } +}; + +/** + * Helpers + */ + +function escape(html, encode) { + return html + .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +function unescape(html) { + // explicitly match decimal, hex, and named HTML entities + return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, function(_, n) { + n = n.toLowerCase(); + if (n === 'colon') return ':'; + if (n.charAt(0) === '#') { + return n.charAt(1) === 'x' + ? String.fromCharCode(parseInt(n.substring(2), 16)) + : String.fromCharCode(+n.substring(1)); + } + return ''; + }); +} + +function edit(regex, opt) { + regex = regex.source || regex; + opt = opt || ''; + return { + replace: function(name, val) { + val = val.source || val; + val = val.replace(/(^|[^\[])\^/g, '$1'); + regex = regex.replace(name, val); + return this; + }, + getRegex: function() { + return new RegExp(regex, opt); + } + }; +} + +function resolveUrl(base, href) { + if (!baseUrls[' ' + base]) { + // we can ignore everything in base after the last slash of its path component, + // but we might need to add _that_ + // https://tools.ietf.org/html/rfc3986#section-3 + if (/^[^:]+:\/*[^/]*$/.test(base)) { + baseUrls[' ' + base] = base + '/'; + } else { + baseUrls[' ' + base] = base.replace(/[^/]*$/, ''); + } + } + base = baseUrls[' ' + base]; + + if (href.slice(0, 2) === '//') { + return base.replace(/:[\s\S]*/, ':') + href; + } else if (href.charAt(0) === '/') { + return base.replace(/(:\/*[^/]*)[\s\S]*/, '$1') + href; + } else { + return base + href; + } +} +var baseUrls = {}; +var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i; + +function noop() {} +noop.exec = noop; + +function merge(obj) { + var i = 1, + target, + key; + + for (; i < arguments.length; i++) { + target = arguments[i]; + for (key in target) { + if (Object.prototype.hasOwnProperty.call(target, key)) { + obj[key] = target[key]; + } + } + } + + return obj; +} + +function splitCells(tableRow, count) { + var cells = tableRow.replace(/([^\\])\|/g, '$1 |').split(/ +\| */), + i = 0; + + if (cells.length > count) { + cells.splice(count); + } else { + while (cells.length < count) cells.push(''); + } + + for (; i < cells.length; i++) { + cells[i] = cells[i].replace(/\\\|/g, '|'); + } + return cells; +} + +/** + * Marked + */ + +function marked(src, opt, callback) { + // throw error in case of non string input + if (typeof src === 'undefined' || src === null) { + throw new Error('marked(): input parameter is undefined or null'); + } + if (typeof src !== 'string') { + throw new Error('marked(): input parameter is of type ' + + Object.prototype.toString.call(src) + ', string expected'); + } + + if (callback || typeof opt === 'function') { + if (!callback) { + callback = opt; + opt = null; + } + + opt = merge({}, marked.defaults, opt || {}); + + var highlight = opt.highlight, + tokens, + pending, + i = 0; + + try { + tokens = Lexer.lex(src, opt) + } catch (e) { + return callback(e); + } + + pending = tokens.length; + + var done = function(err) { + if (err) { + opt.highlight = highlight; + return callback(err); + } + + var out; + + try { + out = Parser.parse(tokens, opt); + } catch (e) { + err = e; + } + + opt.highlight = highlight; + + return err + ? callback(err) + : callback(null, out); + }; + + if (!highlight || highlight.length < 3) { + return done(); + } + + delete opt.highlight; + + if (!pending) return done(); + + for (; i < tokens.length; i++) { + (function(token) { + if (token.type !== 'code') { + return --pending || done(); + } + return highlight(token.text, token.lang, function(err, code) { + if (err) return done(err); + if (code == null || code === token.text) { + return --pending || done(); + } + token.text = code; + token.escaped = true; + --pending || done(); + }); + })(tokens[i]); + } + + return; + } + try { + if (opt) opt = merge({}, marked.defaults, opt); + return Parser.parse(Lexer.lex(src, opt), opt); + } catch (e) { + e.message += '\nPlease report this to https://github.com/markedjs/marked.'; + if ((opt || marked.defaults).silent) { + return '

    An error occurred:

    '
    +        + escape(e.message + '', true)
    +        + '
    '; + } + throw e; + } +} + +/** + * Options + */ + +marked.options = +marked.setOptions = function(opt) { + merge(marked.defaults, opt); + return marked; +}; + +marked.getDefaults = function () { + return { + baseUrl: null, + breaks: false, + gfm: true, + headerIds: true, + headerPrefix: '', + highlight: null, + langPrefix: 'language-', + mangle: true, + pedantic: false, + renderer: new Renderer(), + sanitize: false, + sanitizer: null, + silent: false, + smartLists: false, + smartypants: false, + tables: true, + xhtml: false + }; +} + +marked.defaults = marked.getDefaults(); + +/** + * Expose + */ + +marked.Parser = Parser; +marked.parser = Parser.parse; + +marked.Renderer = Renderer; +marked.TextRenderer = TextRenderer; + +marked.Lexer = Lexer; +marked.lexer = Lexer.lex; + +marked.InlineLexer = InlineLexer; +marked.inlineLexer = InlineLexer.output; + +marked.parse = marked; + +if (typeof module !== 'undefined' && typeof exports === 'object') { + module.exports = marked; +} else if (typeof define === 'function' && define.amd) { + define(function() { return marked; }); +} else { + root.marked = marked; +} +})(this || (typeof window !== 'undefined' ? window : global)); diff --git a/examples/webenginewidgets/markdowneditor/resources/3rdparty/qt_attribution.json b/examples/webenginewidgets/markdowneditor/resources/3rdparty/qt_attribution.json new file mode 100644 index 000000000..de5458eff --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/resources/3rdparty/qt_attribution.json @@ -0,0 +1,35 @@ +[ + { + "Id": "markdowneditor-marked", + "Name": "Marked (WebEngine Markdown Editor example)", + "QDocModule": "qtwebengine", + "QtUsage": "Marked is used in the WebEngine MarkDown Editor example", + "QtParts": [ "examples" ], + "Files": "marked.js", + "Description": "A full-featured markdown parser and compiler, written in JavaScript. Built for speed.", + "Homepage": "https://github.com/chjj/marked", + "Version": "0.4.0", + "DownloadLocation": "https://github.com/markedjs/marked/blob/0.4.0/lib/marked.js", + "Copyright": "Copyright (c) 2011-2018, Christopher Jeffrey", + "License": "MIT License", + "LicenseId": "MIT", + "LicenseFile": "MARKED-LICENSE.txt" + }, + { + "Id": "markdowneditor-markdowncss", + "Name": "Markdown.css (WebEngine Markdown Editor example)", + "QDocModule": "qtwebengine", + "QtUsage": "markdown.css is used in the WebEngine MarkDown Editor example", + "QtParts": [ "examples" ], + "Files": "markdown.css", + "Description": "Markdown.css is better default styling for your Markdown files.", + "Homepage": "https://kevinburke.bitbucket.io/markdowncss/", + "Version": "188530e4b5d020d7e237fc6b26be13ebf4a8def3", + "DownloadLocation": "https://bitbucket.org/kevinburke/markdowncss/src/188530e4b5d020d7e237fc6b26be13ebf4a8def3/markdown.css", + "Copyright": "Copyright 2011 Kevin Burke + Copyright Twitter Inc.", + "License": "Apache License 2.0", + "LicenseId": "Apache-2.0", + "LicenseFile": "MARKDOWN-LICENSE.txt" + } +] diff --git a/examples/webenginewidgets/markdowneditor/resources/default.md b/examples/webenginewidgets/markdowneditor/resources/default.md new file mode 100644 index 000000000..af835fa4d --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/resources/default.md @@ -0,0 +1,12 @@ +## WebEngine Markdown Editor Example + +This example uses [QWebEngineView](http://doc.qt.io/qt-5/qwebengineview.html) +to preview text written using the [Markdown](https://en.wikipedia.org/wiki/Markdown) +syntax. + +### Acknowledgments + +The conversion from Markdown to HTML is done with the help of the +[marked JavaScript library](https://github.com/chjj/marked) by _Christopher Jeffrey_. +The [style sheet](https://kevinburke.bitbucket.io/markdowncss/) +was created by _Kevin Burke_. diff --git a/examples/webenginewidgets/markdowneditor/resources/index.html b/examples/webenginewidgets/markdowneditor/resources/index.html new file mode 100644 index 000000000..289a2110b --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/resources/index.html @@ -0,0 +1,32 @@ + + + + + + + + + +
    + + + + + + diff --git a/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc b/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc new file mode 100644 index 000000000..bc738f1cf --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc @@ -0,0 +1,8 @@ + + + default.md + index.html + 3rdparty/markdown.css + 3rdparty/marked.js + + diff --git a/examples/webenginewidgets/markdowneditor/ui_mainwindow.py b/examples/webenginewidgets/markdowneditor/ui_mainwindow.py new file mode 100644 index 000000000..305108324 --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/ui_mainwindow.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'mainwindow.ui' +## +## Created by: Qt User Interface Compiler version 6.2.0 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient, + QCursor, QFont, QFontDatabase, QGradient, + QIcon, QImage, QKeySequence, QLinearGradient, + QPainter, QPalette, QPixmap, QRadialGradient, + QTransform) +from PySide6.QtWebEngineWidgets import QWebEngineView +from PySide6.QtWidgets import (QApplication, QHBoxLayout, QMainWindow, QMenu, + QMenuBar, QPlainTextEdit, QSizePolicy, QSplitter, + QStatusBar, QWidget) + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + if not MainWindow.objectName(): + MainWindow.setObjectName(u"MainWindow") + MainWindow.resize(800, 600) + self.actionOpen = QAction(MainWindow) + self.actionOpen.setObjectName(u"actionOpen") + self.actionSave = QAction(MainWindow) + self.actionSave.setObjectName(u"actionSave") + self.actionExit = QAction(MainWindow) + self.actionExit.setObjectName(u"actionExit") + self.actionSaveAs = QAction(MainWindow) + self.actionSaveAs.setObjectName(u"actionSaveAs") + self.actionNew = QAction(MainWindow) + self.actionNew.setObjectName(u"actionNew") + self.centralwidget = QWidget(MainWindow) + self.centralwidget.setObjectName(u"centralwidget") + self.horizontalLayout = QHBoxLayout(self.centralwidget) + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.splitter = QSplitter(self.centralwidget) + self.splitter.setObjectName(u"splitter") + self.splitter.setOrientation(Qt.Horizontal) + self.editor = QPlainTextEdit(self.splitter) + self.editor.setObjectName(u"editor") + self.splitter.addWidget(self.editor) + self.preview = QWebEngineView(self.splitter) + self.preview.setObjectName(u"preview") + self.splitter.addWidget(self.preview) + + self.horizontalLayout.addWidget(self.splitter) + + MainWindow.setCentralWidget(self.centralwidget) + self.menubar = QMenuBar(MainWindow) + self.menubar.setObjectName(u"menubar") + self.menubar.setGeometry(QRect(0, 0, 800, 26)) + self.menu_File = QMenu(self.menubar) + self.menu_File.setObjectName(u"menu_File") + MainWindow.setMenuBar(self.menubar) + self.statusbar = QStatusBar(MainWindow) + self.statusbar.setObjectName(u"statusbar") + MainWindow.setStatusBar(self.statusbar) + + self.menubar.addAction(self.menu_File.menuAction()) + self.menu_File.addAction(self.actionNew) + self.menu_File.addAction(self.actionOpen) + self.menu_File.addAction(self.actionSave) + self.menu_File.addAction(self.actionSaveAs) + self.menu_File.addSeparator() + self.menu_File.addAction(self.actionExit) + + self.retranslateUi(MainWindow) + + QMetaObject.connectSlotsByName(MainWindow) + # setupUi + + def retranslateUi(self, MainWindow): + MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MarkDown Editor", None)) + self.actionOpen.setText(QCoreApplication.translate("MainWindow", u"&Open...", None)) +#if QT_CONFIG(tooltip) + self.actionOpen.setToolTip(QCoreApplication.translate("MainWindow", u"Open document", None)) +#endif // QT_CONFIG(tooltip) +#if QT_CONFIG(shortcut) + self.actionOpen.setShortcut(QCoreApplication.translate("MainWindow", u"Ctrl+O", None)) +#endif // QT_CONFIG(shortcut) + self.actionSave.setText(QCoreApplication.translate("MainWindow", u"&Save", None)) +#if QT_CONFIG(tooltip) + self.actionSave.setToolTip(QCoreApplication.translate("MainWindow", u"Save current document", None)) +#endif // QT_CONFIG(tooltip) +#if QT_CONFIG(shortcut) + self.actionSave.setShortcut(QCoreApplication.translate("MainWindow", u"Ctrl+S", None)) +#endif // QT_CONFIG(shortcut) + self.actionExit.setText(QCoreApplication.translate("MainWindow", u"E&xit", None)) +#if QT_CONFIG(tooltip) + self.actionExit.setToolTip(QCoreApplication.translate("MainWindow", u"Exit editor", None)) +#endif // QT_CONFIG(tooltip) +#if QT_CONFIG(shortcut) + self.actionExit.setShortcut(QCoreApplication.translate("MainWindow", u"Ctrl+Q", None)) +#endif // QT_CONFIG(shortcut) + self.actionSaveAs.setText(QCoreApplication.translate("MainWindow", u"Save &As...", None)) +#if QT_CONFIG(tooltip) + self.actionSaveAs.setToolTip(QCoreApplication.translate("MainWindow", u"Save document under different name", None)) +#endif // QT_CONFIG(tooltip) + self.actionNew.setText(QCoreApplication.translate("MainWindow", u"&New", None)) +#if QT_CONFIG(tooltip) + self.actionNew.setToolTip(QCoreApplication.translate("MainWindow", u"Create new document", None)) +#endif // QT_CONFIG(tooltip) +#if QT_CONFIG(shortcut) + self.actionNew.setShortcut(QCoreApplication.translate("MainWindow", u"Ctrl+N", None)) +#endif // QT_CONFIG(shortcut) + self.menu_File.setTitle(QCoreApplication.translate("MainWindow", u"&File", None)) + # retranslateUi + -- cgit v1.2.3