summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/webengine/minimal/main.qml2
-rw-r--r--examples/webengine/quicknanobrowser/BrowserWindow.qml5
-rw-r--r--examples/webengine/quicknanobrowser/doc/src/quicknanobrowser.qdoc10
-rw-r--r--examples/webengine/quicknanobrowser/icons/3rdparty/COPYING1
-rw-r--r--examples/webengine/quicknanobrowser/icons/3rdparty/go-next.png (renamed from examples/webengine/quicknanobrowser/icons/go-next.png)bin930 -> 930 bytes
-rw-r--r--examples/webengine/quicknanobrowser/icons/3rdparty/go-previous.png (renamed from examples/webengine/quicknanobrowser/icons/go-previous.png)bin955 -> 955 bytes
-rw-r--r--examples/webengine/quicknanobrowser/icons/3rdparty/process-stop.png (renamed from examples/webengine/quicknanobrowser/icons/process-stop.png)bin1272 -> 1272 bytes
-rw-r--r--examples/webengine/quicknanobrowser/icons/3rdparty/qt_attribution.json24
-rw-r--r--examples/webengine/quicknanobrowser/icons/3rdparty/view-refresh.png (renamed from examples/webengine/quicknanobrowser/icons/view-refresh.png)bin1364 -> 1364 bytes
-rw-r--r--examples/webengine/quicknanobrowser/main.cpp2
-rw-r--r--examples/webengine/quicknanobrowser/resources.qrc8
-rw-r--r--examples/webengine/recipebrowser/resources/pages/assets/3rdparty/MARKED-LICENSE.txt2
-rw-r--r--examples/webengine/recipebrowser/resources/pages/assets/3rdparty/marked.js1514
-rw-r--r--examples/webengine/recipebrowser/resources/pages/assets/3rdparty/marked.min.js6
-rw-r--r--examples/webengine/recipebrowser/resources/pages/assets/3rdparty/qt_attribution.json8
-rw-r--r--examples/webengine/recipebrowser/resources/pages/burger.html2
-rw-r--r--examples/webengine/recipebrowser/resources/pages/cupcakes.html2
-rw-r--r--examples/webengine/recipebrowser/resources/pages/pasta.html2
-rw-r--r--examples/webengine/recipebrowser/resources/pages/pizza.html2
-rw-r--r--examples/webengine/recipebrowser/resources/pages/skewers.html2
-rw-r--r--examples/webengine/recipebrowser/resources/pages/soup.html2
-rw-r--r--examples/webengine/recipebrowser/resources/pages/steak.html2
-rw-r--r--examples/webengine/recipebrowser/resources/resources.qrc2
-rw-r--r--examples/webenginewidgets/cookiebrowser/3rdparty/COPYING1
-rw-r--r--examples/webenginewidgets/cookiebrowser/3rdparty/qt_attribution.json24
-rw-r--r--examples/webenginewidgets/cookiebrowser/3rdparty/view-refresh.png (renamed from examples/webenginewidgets/cookiebrowser/view-refresh.png)bin1364 -> 1364 bytes
-rw-r--r--examples/webenginewidgets/cookiebrowser/cookiebrowser.qrc2
-rw-r--r--examples/webenginewidgets/cookiebrowser/doc/src/cookiebrowser.qdoc10
-rw-r--r--examples/webenginewidgets/markdowneditor/doc/src/markdowneditor.qdoc2
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/3rdparty/marked.js374
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/3rdparty/qt_attribution.json4
-rw-r--r--examples/webenginewidgets/simplebrowser/data/3rdparty/COPYING1
-rw-r--r--examples/webenginewidgets/simplebrowser/data/3rdparty/dialog-error.png (renamed from examples/webenginewidgets/simplebrowser/data/dialog-error.png)bin1645 -> 1645 bytes
-rw-r--r--examples/webenginewidgets/simplebrowser/data/3rdparty/edit-clear.png (renamed from examples/webenginewidgets/simplebrowser/data/edit-clear.png)bin1682 -> 1682 bytes
-rw-r--r--examples/webenginewidgets/simplebrowser/data/3rdparty/go-bottom.png (renamed from examples/webenginewidgets/simplebrowser/data/go-bottom.png)bin1263 -> 1263 bytes
-rw-r--r--examples/webenginewidgets/simplebrowser/data/3rdparty/go-next.png (renamed from examples/webenginewidgets/simplebrowser/data/go-next.png)bin1219 -> 1219 bytes
-rw-r--r--examples/webenginewidgets/simplebrowser/data/3rdparty/go-previous.png (renamed from examples/webenginewidgets/simplebrowser/data/go-previous.png)bin1200 -> 1200 bytes
-rw-r--r--examples/webenginewidgets/simplebrowser/data/3rdparty/process-stop.png (renamed from examples/webenginewidgets/simplebrowser/data/process-stop.png)bin1927 -> 1927 bytes
-rw-r--r--examples/webenginewidgets/simplebrowser/data/3rdparty/qt_attribution.json24
-rw-r--r--examples/webenginewidgets/simplebrowser/data/3rdparty/text-html.png (renamed from examples/webenginewidgets/simplebrowser/data/text-html.png)bin1759 -> 1759 bytes
-rw-r--r--examples/webenginewidgets/simplebrowser/data/3rdparty/view-refresh.png (renamed from examples/webenginewidgets/simplebrowser/data/view-refresh.png)bin2024 -> 2024 bytes
-rw-r--r--examples/webenginewidgets/simplebrowser/data/simplebrowser.qrc18
-rw-r--r--examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc12
-rw-r--r--examples/webenginewidgets/simplebrowser/webpage.cpp2
-rw-r--r--examples/webenginewidgets/simplebrowser/webpage.h2
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/3rdparty/COPYING1
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/3rdparty/qt_attribution.json24
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/3rdparty/view-refresh.png (renamed from examples/webenginewidgets/stylesheetbrowser/view-refresh.png)bin1364 -> 1364 bytes
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/doc/src/stylesheetbrowser.qdoc10
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/stylesheetbrowser.qrc2
-rw-r--r--examples/webenginewidgets/webenginewidgets.pro5
-rw-r--r--examples/webenginewidgets/webui/about.html129
-rw-r--r--examples/webenginewidgets/webui/doc/images/webui-example.pngbin0 -> 28862 bytes
-rw-r--r--examples/webenginewidgets/webui/doc/src/webui.qdoc165
-rw-r--r--examples/webenginewidgets/webui/main.cpp81
-rw-r--r--examples/webenginewidgets/webui/webui.pro16
-rw-r--r--examples/webenginewidgets/webui/webui.qrc5
-rw-r--r--examples/webenginewidgets/webui/webuihandler.cpp98
-rw-r--r--examples/webenginewidgets/webui/webuihandler.h70
59 files changed, 2510 insertions, 170 deletions
diff --git a/examples/webengine/minimal/main.qml b/examples/webengine/minimal/main.qml
index 5abc50069..75082f9c5 100644
--- a/examples/webengine/minimal/main.qml
+++ b/examples/webengine/minimal/main.qml
@@ -58,6 +58,6 @@ Window {
visible: true
WebEngineView {
anchors.fill: parent
- url: "http://www.qt.io"
+ url: "https://www.qt.io"
}
}
diff --git a/examples/webengine/quicknanobrowser/BrowserWindow.qml b/examples/webengine/quicknanobrowser/BrowserWindow.qml
index f60d6ad1f..7b8767b8d 100644
--- a/examples/webengine/quicknanobrowser/BrowserWindow.qml
+++ b/examples/webengine/quicknanobrowser/BrowserWindow.qml
@@ -505,6 +505,11 @@ ApplicationWindow {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
+ onNewViewRequested: function(request) {
+ var tab = tabs.createEmptyTab(currentWebView.profile);
+ tabs.currentIndex = tabs.count - 1;
+ request.openIn(tab.item);
+ }
}
MessageDialog {
id: sslDialog
diff --git a/examples/webengine/quicknanobrowser/doc/src/quicknanobrowser.qdoc b/examples/webengine/quicknanobrowser/doc/src/quicknanobrowser.qdoc
index 190604fc4..3188bb299 100644
--- a/examples/webengine/quicknanobrowser/doc/src/quicknanobrowser.qdoc
+++ b/examples/webengine/quicknanobrowser/doc/src/quicknanobrowser.qdoc
@@ -136,4 +136,14 @@
\printuntil Action
\skipto Escape
\printuntil /^\ {4}\}/
+
+ \section1 Files and Attributions
+
+ The example uses icons from the Tango Icon Library:
+
+ \table
+ \row
+ \li \l{quicknanobrowser-tango}{Tango Icon Library}
+ \li Public Domain
+ \endtable
*/
diff --git a/examples/webengine/quicknanobrowser/icons/3rdparty/COPYING b/examples/webengine/quicknanobrowser/icons/3rdparty/COPYING
new file mode 100644
index 000000000..220881da6
--- /dev/null
+++ b/examples/webengine/quicknanobrowser/icons/3rdparty/COPYING
@@ -0,0 +1 @@
+The icons in this repository are herefore released into the Public Domain.
diff --git a/examples/webengine/quicknanobrowser/icons/go-next.png b/examples/webengine/quicknanobrowser/icons/3rdparty/go-next.png
index 6f3f65d33..6f3f65d33 100644
--- a/examples/webengine/quicknanobrowser/icons/go-next.png
+++ b/examples/webengine/quicknanobrowser/icons/3rdparty/go-next.png
Binary files differ
diff --git a/examples/webengine/quicknanobrowser/icons/go-previous.png b/examples/webengine/quicknanobrowser/icons/3rdparty/go-previous.png
index 93be3d1ee..93be3d1ee 100644
--- a/examples/webengine/quicknanobrowser/icons/go-previous.png
+++ b/examples/webengine/quicknanobrowser/icons/3rdparty/go-previous.png
Binary files differ
diff --git a/examples/webengine/quicknanobrowser/icons/process-stop.png b/examples/webengine/quicknanobrowser/icons/3rdparty/process-stop.png
index b68290bf1..b68290bf1 100644
--- a/examples/webengine/quicknanobrowser/icons/process-stop.png
+++ b/examples/webengine/quicknanobrowser/icons/3rdparty/process-stop.png
Binary files differ
diff --git a/examples/webengine/quicknanobrowser/icons/3rdparty/qt_attribution.json b/examples/webengine/quicknanobrowser/icons/3rdparty/qt_attribution.json
new file mode 100644
index 000000000..4e5a44448
--- /dev/null
+++ b/examples/webengine/quicknanobrowser/icons/3rdparty/qt_attribution.json
@@ -0,0 +1,24 @@
+{
+ "Id": "quicknanobrowser-tango",
+ "Name": "Tango Icon Library",
+ "QDocModule": "qtwebengine",
+ "QtUsage": "Used in WebEngine Quick Nano Browser example.",
+
+ "QtParts": [ "examples" ],
+ "Description": "Selected icons from the Tango Icon Library",
+ "Homepage": "http://tango.freedesktop.org/Tango_Icon_Library",
+ "Version": "0.8.90",
+ "DownloadLocation": "http://tango.freedesktop.org/releases/tango-icon-theme-0.8.90.tar.gz",
+ "LicenseId": "DocumentRef-PublicDomain",
+ "License": "Public Domain",
+ "LicenseFile": "COPYING",
+ "Copyright": "Ulisse Perusin <uli.peru@gmail.com>
+Steven Garrity <sgarrity@silverorange.com>
+Lapo Calamandrei <calamandrei@gmail.com>
+Ryan Collier <rcollier@novell.com>
+Rodney Dawes <dobey@novell.com>
+Andreas Nilsson <nisses.mail@home.se>
+Tuomas Kuosmanen <tigert@tigert.com>
+Garrett LeSage <garrett@novell.com>
+Jakub Steiner <jimmac@novell.com>"
+}
diff --git a/examples/webengine/quicknanobrowser/icons/view-refresh.png b/examples/webengine/quicknanobrowser/icons/3rdparty/view-refresh.png
index cab4d02c7..cab4d02c7 100644
--- a/examples/webengine/quicknanobrowser/icons/view-refresh.png
+++ b/examples/webengine/quicknanobrowser/icons/3rdparty/view-refresh.png
Binary files differ
diff --git a/examples/webengine/quicknanobrowser/main.cpp b/examples/webengine/quicknanobrowser/main.cpp
index b1b80106b..63725d3e2 100644
--- a/examples/webengine/quicknanobrowser/main.cpp
+++ b/examples/webengine/quicknanobrowser/main.cpp
@@ -73,7 +73,7 @@ static QUrl startupUrl()
if (ret.isValid())
return ret;
}
- return QUrl(QStringLiteral("http://qt.io/"));
+ return QUrl(QStringLiteral("https://www.qt.io"));
}
int main(int argc, char **argv)
diff --git a/examples/webengine/quicknanobrowser/resources.qrc b/examples/webengine/quicknanobrowser/resources.qrc
index 694f8d19b..c6270897d 100644
--- a/examples/webengine/quicknanobrowser/resources.qrc
+++ b/examples/webengine/quicknanobrowser/resources.qrc
@@ -7,9 +7,9 @@
<file>FullScreenNotification.qml</file>
</qresource>
<qresource prefix="icons">
- <file alias="go-next.png">icons/go-next.png</file>
- <file alias="go-previous.png">icons/go-previous.png</file>
- <file alias="process-stop.png">icons/process-stop.png</file>
- <file alias="view-refresh.png">icons/view-refresh.png</file>
+ <file alias="go-next.png">icons/3rdparty/go-next.png</file>
+ <file alias="go-previous.png">icons/3rdparty/go-previous.png</file>
+ <file alias="process-stop.png">icons/3rdparty/process-stop.png</file>
+ <file alias="view-refresh.png">icons/3rdparty/view-refresh.png</file>
</qresource>
</RCC>
diff --git a/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/MARKED-LICENSE.txt b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/MARKED-LICENSE.txt
index a7b812ed6..8e3ba0e0a 100644
--- a/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/MARKED-LICENSE.txt
+++ b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/MARKED-LICENSE.txt
@@ -1,4 +1,4 @@
-Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/)
+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
diff --git a/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/marked.js b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/marked.js
new file mode 100644
index 000000000..33c02d9cf
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/assets/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]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
+ + '|comment[^\\n]*(\\n+|$)' // (2)
+ + '|<\\?[\\s\\S]*?\\?>\\n*' // (3)
+ + '|<![A-Z][\\s\\S]*?>\\n*' // (4)
+ + '|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>\\n*' // (5)
+ + '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:\\n{2,}|$)' // (6)
+ + '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$)' // (7) open tag
+ + '|</(?!script|pre|style)[a-z][\\w-]*\\s*>(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$)' // (7) closing tag
+ + ')',
+ def: /^ {0,3}\[(label)\]: *\n? *<?([^\s>]+)>?(?:(?: +\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 = /<!--(?!-?>)[\s\S]*?-->/;
+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]+?</\\1> *(?:\\n{2,}|\\s*$)' // closed tag
+ + '|<tag(?:"[^"]*"|\'[^\']*\'|\\s[^\'"/>\\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: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\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'
+ + '|^</[a-zA-Z][\\w:-]*\\s*>' // self-closing tag
+ + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag
+ + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. <?php ?>
+ + '|^<![a-zA-Z]+\\s[\\s\\S]*?>' // declaration, e.g. <!DOCTYPE html>
+ + '|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>', // 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]+?(?=[\\<!\[`*]|\b_| {2,}\n|$)/
+};
+
+inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/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 && /^<a /i.test(cap[0])) {
+ this.inLink = true;
+ } else if (this.inLink && /^<\/a>/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 '<pre><code>'
+ + (escaped ? code : escape(code, true))
+ + '</code></pre>';
+ }
+
+ return '<pre><code class="'
+ + this.options.langPrefix
+ + escape(lang, true)
+ + '">'
+ + (escaped ? code : escape(code, true))
+ + '</code></pre>\n';
+};
+
+Renderer.prototype.blockquote = function(quote) {
+ return '<blockquote>\n' + quote + '</blockquote>\n';
+};
+
+Renderer.prototype.html = function(html) {
+ return html;
+};
+
+Renderer.prototype.heading = function(text, level, raw) {
+ if (this.options.headerIds) {
+ return '<h'
+ + level
+ + ' id="'
+ + this.options.headerPrefix
+ + raw.toLowerCase().replace(/[^\w]+/g, '-')
+ + '">'
+ + text
+ + '</h'
+ + level
+ + '>\n';
+ }
+ // ignore IDs
+ return '<h' + level + '>' + text + '</h' + level + '>\n';
+};
+
+Renderer.prototype.hr = function() {
+ return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
+};
+
+Renderer.prototype.list = function(body, ordered, start) {
+ var type = ordered ? 'ol' : 'ul',
+ startatt = (ordered && start !== 1) ? (' start="' + start + '"') : '';
+ return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';
+};
+
+Renderer.prototype.listitem = function(text) {
+ return '<li>' + text + '</li>\n';
+};
+
+Renderer.prototype.checkbox = function(checked) {
+ return '<input '
+ + (checked ? 'checked="" ' : '')
+ + 'disabled="" type="checkbox"'
+ + (this.options.xhtml ? ' /' : '')
+ + '> ';
+}
+
+Renderer.prototype.paragraph = function(text) {
+ return '<p>' + text + '</p>\n';
+};
+
+Renderer.prototype.table = function(header, body) {
+ if (body) body = '<tbody>' + body + '</tbody>';
+
+ return '<table>\n'
+ + '<thead>\n'
+ + header
+ + '</thead>\n'
+ + body
+ + '</table>\n';
+};
+
+Renderer.prototype.tablerow = function(content) {
+ return '<tr>\n' + content + '</tr>\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 + '</' + type + '>\n';
+};
+
+// span level renderer
+Renderer.prototype.strong = function(text) {
+ return '<strong>' + text + '</strong>';
+};
+
+Renderer.prototype.em = function(text) {
+ return '<em>' + text + '</em>';
+};
+
+Renderer.prototype.codespan = function(text) {
+ return '<code>' + text + '</code>';
+};
+
+Renderer.prototype.br = function() {
+ return this.options.xhtml ? '<br/>' : '<br>';
+};
+
+Renderer.prototype.del = function(text) {
+ return '<del>' + text + '</del>';
+};
+
+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 = '<a href="' + escape(href) + '"';
+ if (title) {
+ out += ' title="' + title + '"';
+ }
+ out += '>' + text + '</a>';
+ return out;
+};
+
+Renderer.prototype.image = function(href, title, text) {
+ if (this.options.baseUrl && !originIndependentUrl.test(href)) {
+ href = resolveUrl(this.options.baseUrl, href);
+ }
+ var out = '<img src="' + href + '" alt="' + text + '"';
+ if (title) {
+ out += ' title="' + title + '"';
+ }
+ out += this.options.xhtml ? '/>' : '>';
+ 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, '&amp;')
+ .replace(/</g, '&lt;')
+ .replace(/>/g, '&gt;')
+ .replace(/"/g, '&quot;')
+ .replace(/'/g, '&#39;');
+}
+
+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 '<p>An error occurred:</p><pre>'
+ + escape(e.message + '', true)
+ + '</pre>';
+ }
+ 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/webengine/recipebrowser/resources/pages/assets/3rdparty/marked.min.js b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/marked.min.js
deleted file mode 100644
index f679a4776..000000000
--- a/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/marked.min.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * marked - a markdown parser
- * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
- * https://github.com/chjj/marked
- */
-(function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+block.def.source+")")();block.blockquote=replace(block.blockquote)("def",block.def)();block._tag="(?!(?:"+"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";block.html=replace(block.html)("comment",/<!--[\s\S]*?-->/)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1","\\2")+"|"+block.list.source.replace("\\1","\\3")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm){if(this.options.tables){this.rules=block.tables}else{this.rules=block.gfm}}}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)};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)};Lexer.prototype.token=function(src,top,bq){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1){this.tokens.push({type:"space"})}}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}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}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}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};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]=item.cells[i].split(/ *\| */)}this.tokens.push(item);continue}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}if(cap=this.rules.hr.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"hr"});continue}if(cap=this.rules.blockquote.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"blockquote_start"});cap=cap[0].replace(/^ *> ?/gm,"");this.token(cap,top,true);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i<l;i++){item=cap[i];space=item.length;item=item.replace(/^ *([*+-]|\d+\.) +/,"");if(~item.indexOf("\n ")){space-=item.length;item=!this.options.pedantic?item.replace(new RegExp("^ {1,"+space+"}","gm"),""):item.replace(/^ {1,4}/gm,"")}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}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item.charAt(item.length-1)==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false,bq);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}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}if(!bq&&top&&(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};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]=item.cells[i].replace(/^ *\| *| *\| *$/g,"").split(/ *\| */)}this.tokens.push(item);continue}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}if(cap=this.rules.text.exec(src)){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};var inline={escape:/^\\([\\`*{}\[\]()#+\-.!_>])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/};inline._inside=/(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;inline._href=/\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});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.gfm){if(this.options.breaks){this.rules=inline.breaks}else{this.rules=inline.gfm}}else if(this.options.pedantic){this.rules=inline.pedantic}}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length);out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1].charAt(6)===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=this.renderer.link(href,null,text);continue}if(!this.inLink&&(cap=this.rules.url.exec(src))){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=this.renderer.link(href,null,text);continue}if(cap=this.rules.tag.exec(src)){if(!this.inLink&&/^<a /i.test(cap[0])){this.inLink=true}else if(this.inLink&&/^<\/a>/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}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);this.inLink=true;out+=this.outputLink(cap,{href:cap[2],title:cap[3]});this.inLink=false;continue}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}if(cap=this.rules.strong.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.strong(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.em(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.codespan(escape(cap[2],true));continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.br();continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.del(this.output(cap[1]));continue}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.prototype.outputLink=function(cap,link){var href=escape(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]))};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…")};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()>.5){ch="x"+ch.toString(16)}out+="&#"+ch+";"}return out};function Renderer(options){this.options=options||{}}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"<pre><code>"+(escaped?code:escape(code,true))+"\n</code></pre>"}return'<pre><code class="'+this.options.langPrefix+escape(lang,true)+'">'+(escaped?code:escape(code,true))+"\n</code></pre>\n"};Renderer.prototype.blockquote=function(quote){return"<blockquote>\n"+quote+"</blockquote>\n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"<h"+level+' id="'+this.options.headerPrefix+raw.toLowerCase().replace(/[^\w]+/g,"-")+'">'+text+"</h"+level+">\n"};Renderer.prototype.hr=function(){return this.options.xhtml?"<hr/>\n":"<hr>\n"};Renderer.prototype.list=function(body,ordered){var type=ordered?"ol":"ul";return"<"+type+">\n"+body+"</"+type+">\n"};Renderer.prototype.listitem=function(text){return"<li>"+text+"</li>\n"};Renderer.prototype.paragraph=function(text){return"<p>"+text+"</p>\n"};Renderer.prototype.table=function(header,body){return"<table>\n"+"<thead>\n"+header+"</thead>\n"+"<tbody>\n"+body+"</tbody>\n"+"</table>\n"};Renderer.prototype.tablerow=function(content){return"<tr>\n"+content+"</tr>\n"};Renderer.prototype.tablecell=function(content,flags){var type=flags.header?"th":"td";var tag=flags.align?"<"+type+' style="text-align:'+flags.align+'">':"<"+type+">";return tag+content+"</"+type+">\n"};Renderer.prototype.strong=function(text){return"<strong>"+text+"</strong>"};Renderer.prototype.em=function(text){return"<em>"+text+"</em>"};Renderer.prototype.codespan=function(text){return"<code>"+text+"</code>"};Renderer.prototype.br=function(){return this.options.xhtml?"<br/>":"<br>"};Renderer.prototype.del=function(text){return"<del>"+text+"</del>"};Renderer.prototype.link=function(href,title,text){if(this.options.sanitize){try{var prot=decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return""}if(prot.indexOf("javascript:")===0||prot.indexOf("vbscript:")===0){return""}}var out='<a href="'+href+'"';if(title){out+=' title="'+title+'"'}out+=">"+text+"</a>";return out};Renderer.prototype.image=function(href,title,text){var out='<img src="'+href+'" alt="'+text+'"';if(title){out+=' title="'+title+'"'}out+=this.options.xhtml?"/>":">";return out};Renderer.prototype.text=function(text){return text};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}Parser.parse=function(src,options,renderer){var parser=new Parser(options,renderer);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options,this.renderer);this.tokens=src.reverse();var out="";while(this.next()){out+=this.tok()}return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text;while(this.peek().type==="text"){body+="\n"+this.next().text}return this.inline.output(body)};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,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,flags,j;cell="";for(i=0;i<this.token.header.length;i++){flags={header:true,align:this.token.align[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":{var body="";while(this.next().type!=="blockquote_end"){body+=this.tok()}return this.renderer.blockquote(body)}case"list_start":{var body="",ordered=this.token.ordered;while(this.next().type!=="list_end"){body+=this.tok()}return this.renderer.list(body,ordered)}case"list_item_start":{var body="";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":{var body="";while(this.next().type!=="list_item_end"){body+=this.tok()}return this.renderer.listitem(body)}case"html":{var html=!this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;return this.renderer.html(html)}case"paragraph":{return this.renderer.paragraph(this.inline.output(this.token.text))}case"text":{return this.renderer.paragraph(this.parseText())}}};function escape(html,encode){return html.replace(!encode?/&(?!#?\w+;)/g:/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function unescape(html){return html.replace(/&([#\w]+);/g,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 replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}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 marked(src,opt,callback){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/chjj/marked.";if((opt||marked.defaults).silent){return"<p>An error occurred:</p><pre>"+escape(e.message+"",true)+"</pre>"}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,sanitizer:null,mangle:true,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};marked.Parser=Parser;marked.parser=Parser.parse;marked.Renderer=Renderer;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{this.marked=marked}}).call(function(){return this||(typeof window!=="undefined"?window:global)}());
diff --git a/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/qt_attribution.json b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/qt_attribution.json
index 42947ca0b..a6c68f46f 100644
--- a/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/qt_attribution.json
+++ b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/qt_attribution.json
@@ -5,12 +5,12 @@
"QDocModule": "qtwebengine",
"QtUsage": "Marked is used in the WebEngine RecipeBrowser example",
"QtParts": [ "examples" ],
- "Files": "marked.min.js",
+ "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.3.6",
- "DownloadLocation": "https://github.com/chjj/marked/blob/v0.3.6/marked.min.js",
- "Copyright": "Copyright (c) 2011-2014, Christopher Jeffrey",
+ "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"
diff --git a/examples/webengine/recipebrowser/resources/pages/burger.html b/examples/webengine/recipebrowser/resources/pages/burger.html
index 315c0a866..b10170cbd 100644
--- a/examples/webengine/recipebrowser/resources/pages/burger.html
+++ b/examples/webengine/recipebrowser/resources/pages/burger.html
@@ -67,7 +67,7 @@ give it a minute to go gorgeous and sloppy.
</div><!--End of content-->
- <script src="assets/3rdparty/marked.min.js"></script>
+ <script src="assets/3rdparty/marked.js"></script>
<script src="assets/custom.js"></script>
</body>
</html>
diff --git a/examples/webengine/recipebrowser/resources/pages/cupcakes.html b/examples/webengine/recipebrowser/resources/pages/cupcakes.html
index c169196f2..e21247825 100644
--- a/examples/webengine/recipebrowser/resources/pages/cupcakes.html
+++ b/examples/webengine/recipebrowser/resources/pages/cupcakes.html
@@ -45,7 +45,7 @@ Cupcakes
**Enjoy!**
</div><!--End of content-->
- <script src="assets/3rdparty/marked.min.js"></script>
+ <script src="assets/3rdparty/marked.js"></script>
<script src="assets/custom.js"></script>
</body>
</html>
diff --git a/examples/webengine/recipebrowser/resources/pages/pasta.html b/examples/webengine/recipebrowser/resources/pages/pasta.html
index c94b0df0a..4de65292e 100644
--- a/examples/webengine/recipebrowser/resources/pages/pasta.html
+++ b/examples/webengine/recipebrowser/resources/pages/pasta.html
@@ -48,7 +48,7 @@ Pasta
**Enjoy!**
</div><!--End of content-->
- <script src="assets/3rdparty/marked.min.js"></script>
+ <script src="assets/3rdparty/marked.js"></script>
<script src="assets/custom.js"></script>
</body>
</html>
diff --git a/examples/webengine/recipebrowser/resources/pages/pizza.html b/examples/webengine/recipebrowser/resources/pages/pizza.html
index a1ebfa18e..c63102934 100644
--- a/examples/webengine/recipebrowser/resources/pages/pizza.html
+++ b/examples/webengine/recipebrowser/resources/pages/pizza.html
@@ -39,7 +39,7 @@ Pizza Diavola
**Enjoy!**
</div><!--End of content-->
- <script src="assets/3rdparty/marked.min.js"></script>
+ <script src="assets/3rdparty/marked.js"></script>
<script src="assets/custom.js"></script>
</body>
</html>
diff --git a/examples/webengine/recipebrowser/resources/pages/skewers.html b/examples/webengine/recipebrowser/resources/pages/skewers.html
index 63d85f7e1..6fbf90cb4 100644
--- a/examples/webengine/recipebrowser/resources/pages/skewers.html
+++ b/examples/webengine/recipebrowser/resources/pages/skewers.html
@@ -45,7 +45,7 @@ Grilled skewers
</div><!--End of content-->
- <script src="assets/3rdparty/marked.min.js"></script>
+ <script src="assets/3rdparty/marked.js"></script>
<script src="assets/custom.js"></script>
</body>
</html>
diff --git a/examples/webengine/recipebrowser/resources/pages/soup.html b/examples/webengine/recipebrowser/resources/pages/soup.html
index c7537d94c..e99f016cf 100644
--- a/examples/webengine/recipebrowser/resources/pages/soup.html
+++ b/examples/webengine/recipebrowser/resources/pages/soup.html
@@ -33,7 +33,7 @@ Soup
**Enjoy!**
</div><!--End of content-->
- <script src="assets/3rdparty/marked.min.js"></script>
+ <script src="assets/3rdparty/marked.js"></script>
<script src="assets/custom.js"></script>
</body>
</html>
diff --git a/examples/webengine/recipebrowser/resources/pages/steak.html b/examples/webengine/recipebrowser/resources/pages/steak.html
index 1871f0fe8..c58395d10 100644
--- a/examples/webengine/recipebrowser/resources/pages/steak.html
+++ b/examples/webengine/recipebrowser/resources/pages/steak.html
@@ -59,7 +59,7 @@ Grilled steak and rice
</div><!--End of content-->
- <script src="assets/3rdparty/marked.min.js"></script>
+ <script src="assets/3rdparty/marked.js"></script>
<script src="assets/custom.js"></script>
</body>
</html>
diff --git a/examples/webengine/recipebrowser/resources/resources.qrc b/examples/webengine/recipebrowser/resources/resources.qrc
index 88919159b..bd13dcfae 100644
--- a/examples/webengine/recipebrowser/resources/resources.qrc
+++ b/examples/webengine/recipebrowser/resources/resources.qrc
@@ -11,7 +11,7 @@
<file>pages/skewers.html</file>
<file>pages/cupcakes.html</file>
- <file>pages/assets/3rdparty/marked.min.js</file>
+ <file>pages/assets/3rdparty/marked.js</file>
<file>pages/assets/3rdparty/markdown.css</file>
<file>pages/assets/custom.css</file>
<file>pages/assets/custom.js</file>
diff --git a/examples/webenginewidgets/cookiebrowser/3rdparty/COPYING b/examples/webenginewidgets/cookiebrowser/3rdparty/COPYING
new file mode 100644
index 000000000..220881da6
--- /dev/null
+++ b/examples/webenginewidgets/cookiebrowser/3rdparty/COPYING
@@ -0,0 +1 @@
+The icons in this repository are herefore released into the Public Domain.
diff --git a/examples/webenginewidgets/cookiebrowser/3rdparty/qt_attribution.json b/examples/webenginewidgets/cookiebrowser/3rdparty/qt_attribution.json
new file mode 100644
index 000000000..91a0899c6
--- /dev/null
+++ b/examples/webenginewidgets/cookiebrowser/3rdparty/qt_attribution.json
@@ -0,0 +1,24 @@
+{
+ "Id": "cookiebrowser-tango",
+ "Name": "Tango Icon Library",
+ "QDocModule": "qtwebengine",
+ "QtUsage": "Used in WebEngine Cookie Browser example.",
+
+ "QtParts": [ "examples" ],
+ "Description": "Selected icons from the Tango Icon Library",
+ "Homepage": "http://tango.freedesktop.org/Tango_Icon_Library",
+ "Version": "0.8.90",
+ "DownloadLocation": "http://tango.freedesktop.org/releases/tango-icon-theme-0.8.90.tar.gz",
+ "LicenseId": "DocumentRef-PublicDomain",
+ "License": "Public Domain",
+ "LicenseFile": "COPYING",
+ "Copyright": "Ulisse Perusin <uli.peru@gmail.com>
+Steven Garrity <sgarrity@silverorange.com>
+Lapo Calamandrei <calamandrei@gmail.com>
+Ryan Collier <rcollier@novell.com>
+Rodney Dawes <dobey@novell.com>
+Andreas Nilsson <nisses.mail@home.se>
+Tuomas Kuosmanen <tigert@tigert.com>
+Garrett LeSage <garrett@novell.com>
+Jakub Steiner <jimmac@novell.com>"
+}
diff --git a/examples/webenginewidgets/cookiebrowser/view-refresh.png b/examples/webenginewidgets/cookiebrowser/3rdparty/view-refresh.png
index cab4d02c7..cab4d02c7 100644
--- a/examples/webenginewidgets/cookiebrowser/view-refresh.png
+++ b/examples/webenginewidgets/cookiebrowser/3rdparty/view-refresh.png
Binary files differ
diff --git a/examples/webenginewidgets/cookiebrowser/cookiebrowser.qrc b/examples/webenginewidgets/cookiebrowser/cookiebrowser.qrc
index 8805f2c53..a1cebd6a7 100644
--- a/examples/webenginewidgets/cookiebrowser/cookiebrowser.qrc
+++ b/examples/webenginewidgets/cookiebrowser/cookiebrowser.qrc
@@ -1,5 +1,5 @@
<RCC>
<qresource prefix="/">
- <file>view-refresh.png</file>
+ <file alias="view-refresh.png">3rdparty/view-refresh.png</file>
</qresource>
</RCC>
diff --git a/examples/webenginewidgets/cookiebrowser/doc/src/cookiebrowser.qdoc b/examples/webenginewidgets/cookiebrowser/doc/src/cookiebrowser.qdoc
index 55ccd33d5..a1b4eeb18 100644
--- a/examples/webenginewidgets/cookiebrowser/doc/src/cookiebrowser.qdoc
+++ b/examples/webenginewidgets/cookiebrowser/doc/src/cookiebrowser.qdoc
@@ -38,4 +38,14 @@
well as delete cookies and add new cookies.
\include examples-run.qdocinc
+
+ \section1 Files and Attributions
+
+ The example uses icons from the Tango Icon Library:
+
+ \table
+ \row
+ \li \l{cookiebrowser-tango}{Tango Icon Library}
+ \li Public Domain
+ \endtable
*/
diff --git a/examples/webenginewidgets/markdowneditor/doc/src/markdowneditor.qdoc b/examples/webenginewidgets/markdowneditor/doc/src/markdowneditor.qdoc
index b06d4ee84..9ff8f0615 100644
--- a/examples/webenginewidgets/markdowneditor/doc/src/markdowneditor.qdoc
+++ b/examples/webenginewidgets/markdowneditor/doc/src/markdowneditor.qdoc
@@ -154,7 +154,7 @@
In the \e index.html, we load a custom stylesheet and two JavaScript
libraries. \l{http://kevinburke.bitbucket.org/markdowncss/}{markdown.css} is
a markdown-friendly stylesheet created by Kevin Burke.
- \l{https://github.com/chjj/marked}{marked.min.js} is a markdown parser and
+ \l{https://github.com/chjj/marked}{marked.js} is a markdown parser and
compiler designed for speed written by Christopher Jeffrey and
\e qwebchannel.js is part of the \l{QWebChannel} module.
diff --git a/examples/webenginewidgets/markdowneditor/resources/3rdparty/marked.js b/examples/webenginewidgets/markdowneditor/resources/3rdparty/marked.js
index 5552616ea..33c02d9cf 100644
--- a/examples/webenginewidgets/markdowneditor/resources/3rdparty/marked.js
+++ b/examples/webenginewidgets/markdowneditor/resources/3rdparty/marked.js
@@ -16,20 +16,29 @@ var block = {
code: /^( {4}[^\n]+\n*)+/,
fences: noop,
hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,
- heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\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: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
+ html: '^ {0,3}(?:' // optional indentation
+ + '<(script|pre|style)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
+ + '|comment[^\\n]*(\\n+|$)' // (2)
+ + '|<\\?[\\s\\S]*?\\?>\\n*' // (3)
+ + '|<![A-Z][\\s\\S]*?>\\n*' // (4)
+ + '|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>\\n*' // (5)
+ + '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:\\n{2,}|$)' // (6)
+ + '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$)' // (7) open tag
+ + '|</(?!script|pre|style)[a-z][\\w-]*\\s*>(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$)' // (7) closing tag
+ + ')',
def: /^ {0,3}\[(label)\]: *\n? *<?([^\s>]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,
table: noop,
lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
- paragraph: /^([^\n]+(?:\n?(?!hr|heading|lheading| {0,3}>|tag)[^\n]+)+)/,
+ paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading| {0,3}>|<\/?(?:tag)(?: +|\n|\/?>)|<(?:script|pre|style|!--))[^\n]+)*)/,
text: /^[^\n]+/
};
-block._label = /(?:\\[\[\]]|[^\[\]])+/;
-block._title = /(?:"(?:\\"|[^"]|"[^"\n]*")*"|'\n?(?:[^'\n]+\n?)*'|\([^()]*\))/;
+block._label = /(?!\s*\])(?:\\[\[\]]|[^\[\]])+/;
+block._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/;
block.def = edit(block.def)
.replace('label', block._label)
.replace('title', block._title)
@@ -47,23 +56,24 @@ block.list = edit(block.list)
.replace('def', '\\n+(?=' + block.def.source + ')')
.getRegex();
-block._tag = '(?!(?:'
- + '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';
-
-block.html = edit(block.html)
- .replace('comment', /<!--[\s\S]*?-->/)
- .replace('closed', /<(tag)[\s\S]+?<\/\1>/)
- .replace('closing', /<tag(?:"[^"]*"|'[^']*'|\s[^'"\/>\s]*)*?\/?>/)
- .replace(/tag/g, block._tag)
+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 = /<!--(?!-?>)[\s\S]*?-->/;
+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)
+ .replace('tag', block._tag) // pars can be interrupted by type (6) html blocks
.getRegex();
block.blockquote = edit(block.blockquote)
@@ -97,8 +107,26 @@ block.gfm.paragraph = edit(block.paragraph)
*/
block.tables = merge({}, block.gfm, {
- nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
- table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
+ 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]+?</\\1> *(?:\\n{2,}|\\s*$)' // closed tag
+ + '|<tag(?:"[^"]*"|\'[^\']*\'|\\s[^\'"/>\\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: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/
});
/**
@@ -111,7 +139,9 @@ function Lexer(options) {
this.options = options || marked.defaults;
this.rules = block.normal;
- if (this.options.gfm) {
+ if (this.options.pedantic) {
+ this.rules = block.pedantic;
+ } else if (this.options.gfm) {
if (this.options.tables) {
this.rules = block.tables;
} else {
@@ -165,7 +195,9 @@ Lexer.prototype.token = function(src, top) {
i,
tag,
l,
- isordered;
+ isordered,
+ istask,
+ ischecked;
while (src) {
// newline
@@ -215,34 +247,36 @@ Lexer.prototype.token = function(src, top) {
// table no leading pipe (gfm)
if (top && (cap = this.rules.nptable.exec(src))) {
- src = src.substring(cap[0].length);
-
item = {
type: 'table',
- header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
+ header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')),
align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
- cells: cap[3].replace(/\n$/, '').split('\n')
+ cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : []
};
- 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;
+ 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] = item.cells[i].split(/ *\| */);
- }
+ for (i = 0; i < item.cells.length; i++) {
+ item.cells[i] = splitCells(item.cells[i], item.header.length);
+ }
- this.tokens.push(item);
+ this.tokens.push(item);
- continue;
+ continue;
+ }
}
// hr
@@ -331,10 +365,20 @@ Lexer.prototype.token = function(src, top) {
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'
+ : 'list_item_start',
+ task: istask,
+ checked: ischecked
});
// Recurse.
@@ -370,7 +414,7 @@ Lexer.prototype.token = function(src, top) {
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();
+ tag = cap[1].toLowerCase().replace(/\s+/g, ' ');
if (!this.tokens.links[tag]) {
this.tokens.links[tag] = {
href: cap[2],
@@ -382,36 +426,38 @@ Lexer.prototype.token = function(src, top) {
// table (gfm)
if (top && (cap = this.rules.table.exec(src))) {
- src = src.substring(cap[0].length);
-
item = {
type: 'table',
- header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
+ header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')),
align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
- cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
+ cells: cap[3] ? cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') : []
};
- 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;
+ 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] = item.cells[i]
- .replace(/^ *\| *| *\| *$/g, '')
- .split(/ *\| */);
- }
+ for (i = 0; i < item.cells.length; i++) {
+ item.cells[i] = splitCells(
+ item.cells[i].replace(/^ *\| *| *\| *$/g, ''),
+ item.header.length);
+ }
- this.tokens.push(item);
+ this.tokens.push(item);
- continue;
+ continue;
+ }
}
// lheading
@@ -461,39 +507,54 @@ Lexer.prototype.token = function(src, top) {
*/
var inline = {
- escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
+ escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,
autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/,
url: noop,
- tag: /^<!--[\s\S]*?-->|^<\/?[a-zA-Z0-9\-]+(?:"[^"]*"|'[^']*'|\s[^<'">\/\s]*)*?\/?>/,
- link: /^!?\[(inside)\]\(href\)/,
- reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
- nolink: /^!?\[((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\]/,
- strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
- em: /^_([^\s_](?:[^_]|__)+?[^\s_])_\b|^\*((?:\*\*|[^*])+?)\*(?!\*)/,
+ tag: '^comment'
+ + '|^</[a-zA-Z][\\w:-]*\\s*>' // self-closing tag
+ + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag
+ + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. <?php ?>
+ + '|^<![a-zA-Z]+\\s[\\s\\S]*?>' // declaration, e.g. <!DOCTYPE html>
+ + '|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>', // 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]+?(?=[\\<!\[`*]|\b_| {2,}\n|$)/
};
+inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/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()
+ .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._inside = /(?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]]|\](?=[^\[]*\]))*/;
-inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
+inline._label = /(?:\[[^\[\]]*\]|\\[\[\]]?|`[^`]*`|[^\[\]\\])*?/;
+inline._href = /\s*(<(?:\\[<>]?|[^\s<>\\])*>|(?:\\[()]?|\([^\s\x00-\x1f()\\]*\)|[^\s\x00-\x1f()\\])*?)/;
+inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;
inline.link = edit(inline.link)
- .replace('inside', inline._inside)
+ .replace('label', inline._label)
.replace('href', inline._href)
+ .replace('title', inline._title)
.getRegex();
inline.reflink = edit(inline.reflink)
- .replace('inside', inline._inside)
+ .replace('label', inline._label)
.getRegex();
/**
@@ -508,7 +569,13 @@ inline.normal = merge({}, inline);
inline.pedantic = merge({}, inline.normal, {
strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
- em: /^_(?=\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()
});
/**
@@ -552,14 +619,14 @@ function InlineLexer(links, options) {
throw new Error('Tokens array requires a `links` property.');
}
- if (this.options.gfm) {
+ 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;
}
- } else if (this.options.pedantic) {
- this.rules = inline.pedantic;
}
}
@@ -587,6 +654,7 @@ InlineLexer.prototype.output = function(src) {
link,
text,
href,
+ title,
cap;
while (src) {
@@ -650,9 +718,23 @@ InlineLexer.prototype.output = function(src) {
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: cap[2],
- title: cap[3]
+ href: InlineLexer.escapes(href),
+ title: InlineLexer.escapes(title)
});
this.inLink = false;
continue;
@@ -678,14 +760,14 @@ InlineLexer.prototype.output = function(src) {
// strong
if (cap = this.rules.strong.exec(src)) {
src = src.substring(cap[0].length);
- out += this.renderer.strong(this.output(cap[2] || cap[1]));
+ 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[2] || cap[1]));
+ out += this.renderer.em(this.output(cap[6] || cap[5] || cap[4] || cap[3] || cap[2] || cap[1]));
continue;
}
@@ -725,12 +807,16 @@ InlineLexer.prototype.output = function(src) {
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 = escape(link.href),
+ var href = link.href,
title = link.title ? escape(link.title) : null;
return cap[0].charAt(0) !== '!'
@@ -788,7 +874,7 @@ InlineLexer.prototype.mangle = function(text) {
*/
function Renderer(options) {
- this.options = options || {};
+ this.options = options || marked.defaults;
}
Renderer.prototype.code = function(code, lang, escaped) {
@@ -803,7 +889,7 @@ Renderer.prototype.code = function(code, lang, escaped) {
if (!lang) {
return '<pre><code>'
+ (escaped ? code : escape(code, true))
- + '\n</code></pre>';
+ + '</code></pre>';
}
return '<pre><code class="'
@@ -811,7 +897,7 @@ Renderer.prototype.code = function(code, lang, escaped) {
+ escape(lang, true)
+ '">'
+ (escaped ? code : escape(code, true))
- + '\n</code></pre>\n';
+ + '</code></pre>\n';
};
Renderer.prototype.blockquote = function(quote) {
@@ -823,16 +909,20 @@ Renderer.prototype.html = function(html) {
};
Renderer.prototype.heading = function(text, level, raw) {
- return '<h'
- + level
- + ' id="'
- + this.options.headerPrefix
- + raw.toLowerCase().replace(/[^\w]+/g, '-')
- + '">'
- + text
- + '</h'
- + level
- + '>\n';
+ if (this.options.headerIds) {
+ return '<h'
+ + level
+ + ' id="'
+ + this.options.headerPrefix
+ + raw.toLowerCase().replace(/[^\w]+/g, '-')
+ + '">'
+ + text
+ + '</h'
+ + level
+ + '>\n';
+ }
+ // ignore IDs
+ return '<h' + level + '>' + text + '</h' + level + '>\n';
};
Renderer.prototype.hr = function() {
@@ -849,18 +939,26 @@ Renderer.prototype.listitem = function(text) {
return '<li>' + text + '</li>\n';
};
+Renderer.prototype.checkbox = function(checked) {
+ return '<input '
+ + (checked ? 'checked="" ' : '')
+ + 'disabled="" type="checkbox"'
+ + (this.options.xhtml ? ' /' : '')
+ + '> ';
+}
+
Renderer.prototype.paragraph = function(text) {
return '<p>' + text + '</p>\n';
};
Renderer.prototype.table = function(header, body) {
+ if (body) body = '<tbody>' + body + '</tbody>';
+
return '<table>\n'
+ '<thead>\n'
+ header
+ '</thead>\n'
- + '<tbody>\n'
+ body
- + '</tbody>\n'
+ '</table>\n';
};
@@ -871,7 +969,7 @@ Renderer.prototype.tablerow = function(content) {
Renderer.prototype.tablecell = function(content, flags) {
var type = flags.header ? 'th' : 'td';
var tag = flags.align
- ? '<' + type + ' style="text-align:' + flags.align + '">'
+ ? '<' + type + ' align="' + flags.align + '">'
: '<' + type + '>';
return tag + content + '</' + type + '>\n';
};
@@ -913,7 +1011,12 @@ Renderer.prototype.link = function(href, title, text) {
if (this.options.baseUrl && !originIndependentUrl.test(href)) {
href = resolveUrl(this.options.baseUrl, href);
}
- var out = '<a href="' + href + '"';
+ try {
+ href = encodeURI(href).replace(/%25/g, '%');
+ } catch (e) {
+ return text;
+ }
+ var out = '<a href="' + escape(href) + '"';
if (title) {
out += ' title="' + title + '"';
}
@@ -1115,6 +1218,10 @@ Parser.prototype.tok = function() {
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()
@@ -1133,10 +1240,8 @@ Parser.prototype.tok = function() {
return this.renderer.listitem(body);
}
case 'html': {
- var html = !this.token.pre && !this.options.pedantic
- ? this.inline.output(this.token.text)
- : this.token.text;
- return this.renderer.html(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));
@@ -1175,7 +1280,7 @@ function unescape(html) {
}
function edit(regex, opt) {
- regex = regex.source;
+ regex = regex.source || regex;
opt = opt || '';
return {
replace: function(name, val) {
@@ -1234,6 +1339,22 @@ function merge(obj) {
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
*/
@@ -1341,24 +1462,29 @@ marked.setOptions = function(opt) {
return marked;
};
-marked.defaults = {
- gfm: true,
- tables: true,
- breaks: false,
- pedantic: false,
- sanitize: false,
- sanitizer: null,
- mangle: true,
- smartLists: false,
- silent: false,
- highlight: null,
- langPrefix: 'lang-',
- smartypants: false,
- headerPrefix: '',
- renderer: new Renderer(),
- xhtml: false,
- baseUrl: null
-};
+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
diff --git a/examples/webenginewidgets/markdowneditor/resources/3rdparty/qt_attribution.json b/examples/webenginewidgets/markdowneditor/resources/3rdparty/qt_attribution.json
index 70f84b993..de5458eff 100644
--- a/examples/webenginewidgets/markdowneditor/resources/3rdparty/qt_attribution.json
+++ b/examples/webenginewidgets/markdowneditor/resources/3rdparty/qt_attribution.json
@@ -8,8 +8,8 @@
"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.3.19",
- "DownloadLocation": "https://github.com/chjj/marked/blob/v0.3.19/lib/marked.js",
+ "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",
diff --git a/examples/webenginewidgets/simplebrowser/data/3rdparty/COPYING b/examples/webenginewidgets/simplebrowser/data/3rdparty/COPYING
new file mode 100644
index 000000000..220881da6
--- /dev/null
+++ b/examples/webenginewidgets/simplebrowser/data/3rdparty/COPYING
@@ -0,0 +1 @@
+The icons in this repository are herefore released into the Public Domain.
diff --git a/examples/webenginewidgets/simplebrowser/data/dialog-error.png b/examples/webenginewidgets/simplebrowser/data/3rdparty/dialog-error.png
index cdd95bade..cdd95bade 100644
--- a/examples/webenginewidgets/simplebrowser/data/dialog-error.png
+++ b/examples/webenginewidgets/simplebrowser/data/3rdparty/dialog-error.png
Binary files differ
diff --git a/examples/webenginewidgets/simplebrowser/data/edit-clear.png b/examples/webenginewidgets/simplebrowser/data/3rdparty/edit-clear.png
index 5542948bc..5542948bc 100644
--- a/examples/webenginewidgets/simplebrowser/data/edit-clear.png
+++ b/examples/webenginewidgets/simplebrowser/data/3rdparty/edit-clear.png
Binary files differ
diff --git a/examples/webenginewidgets/simplebrowser/data/go-bottom.png b/examples/webenginewidgets/simplebrowser/data/3rdparty/go-bottom.png
index bf973fedc..bf973fedc 100644
--- a/examples/webenginewidgets/simplebrowser/data/go-bottom.png
+++ b/examples/webenginewidgets/simplebrowser/data/3rdparty/go-bottom.png
Binary files differ
diff --git a/examples/webenginewidgets/simplebrowser/data/go-next.png b/examples/webenginewidgets/simplebrowser/data/3rdparty/go-next.png
index a68e2db77..a68e2db77 100644
--- a/examples/webenginewidgets/simplebrowser/data/go-next.png
+++ b/examples/webenginewidgets/simplebrowser/data/3rdparty/go-next.png
Binary files differ
diff --git a/examples/webenginewidgets/simplebrowser/data/go-previous.png b/examples/webenginewidgets/simplebrowser/data/3rdparty/go-previous.png
index c37bc0414..c37bc0414 100644
--- a/examples/webenginewidgets/simplebrowser/data/go-previous.png
+++ b/examples/webenginewidgets/simplebrowser/data/3rdparty/go-previous.png
Binary files differ
diff --git a/examples/webenginewidgets/simplebrowser/data/process-stop.png b/examples/webenginewidgets/simplebrowser/data/3rdparty/process-stop.png
index e7a8d1722..e7a8d1722 100644
--- a/examples/webenginewidgets/simplebrowser/data/process-stop.png
+++ b/examples/webenginewidgets/simplebrowser/data/3rdparty/process-stop.png
Binary files differ
diff --git a/examples/webenginewidgets/simplebrowser/data/3rdparty/qt_attribution.json b/examples/webenginewidgets/simplebrowser/data/3rdparty/qt_attribution.json
new file mode 100644
index 000000000..853adeb20
--- /dev/null
+++ b/examples/webenginewidgets/simplebrowser/data/3rdparty/qt_attribution.json
@@ -0,0 +1,24 @@
+{
+ "Id": "simplebrowser-tango",
+ "Name": "Tango Icon Library",
+ "QDocModule": "qtwebengine",
+ "QtUsage": "Used in WebEngine SimpleBrowser example.",
+
+ "QtParts": [ "examples" ],
+ "Description": "Selected icons from the Tango Icon Library",
+ "Homepage": "http://tango.freedesktop.org/Tango_Icon_Library",
+ "Version": "0.8.90",
+ "DownloadLocation": "http://tango.freedesktop.org/releases/tango-icon-theme-0.8.90.tar.gz",
+ "LicenseId": "DocumentRef-PublicDomain",
+ "License": "Public Domain",
+ "LicenseFile": "COPYING",
+ "Copyright": "Ulisse Perusin <uli.peru@gmail.com>
+Steven Garrity <sgarrity@silverorange.com>
+Lapo Calamandrei <calamandrei@gmail.com>
+Ryan Collier <rcollier@novell.com>
+Rodney Dawes <dobey@novell.com>
+Andreas Nilsson <nisses.mail@home.se>
+Tuomas Kuosmanen <tigert@tigert.com>
+Garrett LeSage <garrett@novell.com>
+Jakub Steiner <jimmac@novell.com>"
+}
diff --git a/examples/webenginewidgets/simplebrowser/data/text-html.png b/examples/webenginewidgets/simplebrowser/data/3rdparty/text-html.png
index a896697d7..a896697d7 100644
--- a/examples/webenginewidgets/simplebrowser/data/text-html.png
+++ b/examples/webenginewidgets/simplebrowser/data/3rdparty/text-html.png
Binary files differ
diff --git a/examples/webenginewidgets/simplebrowser/data/view-refresh.png b/examples/webenginewidgets/simplebrowser/data/3rdparty/view-refresh.png
index 606ea9eba..606ea9eba 100644
--- a/examples/webenginewidgets/simplebrowser/data/view-refresh.png
+++ b/examples/webenginewidgets/simplebrowser/data/3rdparty/view-refresh.png
Binary files differ
diff --git a/examples/webenginewidgets/simplebrowser/data/simplebrowser.qrc b/examples/webenginewidgets/simplebrowser/data/simplebrowser.qrc
index d81b08a64..eda8e3f3d 100644
--- a/examples/webenginewidgets/simplebrowser/data/simplebrowser.qrc
+++ b/examples/webenginewidgets/simplebrowser/data/simplebrowser.qrc
@@ -1,14 +1,16 @@
<RCC>
<qresource prefix="/">
<file>AppLogoColor.png</file>
- <file>dialog-error.png</file>
- <file>edit-clear.png</file>
- <file>go-bottom.png</file>
- <file>go-next.png</file>
- <file>go-previous.png</file>
- <file>process-stop.png</file>
- <file>text-html.png</file>
- <file>view-refresh.png</file>
<file>ninja.png</file>
</qresource>
+ <qresource prefix="/">
+ <file alias="dialog-error.png">3rdparty/dialog-error.png</file>
+ <file alias="edit-clear.png">3rdparty/edit-clear.png</file>
+ <file alias="go-bottom.png">3rdparty/go-bottom.png</file>
+ <file alias="go-next.png">3rdparty/go-next.png</file>
+ <file alias="go-previous.png">3rdparty/go-previous.png</file>
+ <file alias="process-stop.png">3rdparty/process-stop.png</file>
+ <file alias="text-html.png">3rdparty/text-html.png</file>
+ <file alias="view-refresh.png">3rdparty/view-refresh.png</file>
+ </qresource>
</RCC>
diff --git a/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc b/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc
index 2231d9667..b0c426232 100644
--- a/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc
+++ b/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc
@@ -327,9 +327,13 @@
finished or when an error occurs. See \c downloadmanagerwidget.cpp for an
example of how these signals can be handled.
- \section1 Licensing
+ \section1 Files and Attributions
- All icons used in the example, with the exception of \c{AppLogoColor.png},
- originate from the public domain
- \l{http://tango.freedesktop.org/Tango_Icon_Library}{Tango Icon Library}.
+ The example uses icons from the Tango Icon Library:
+
+ \table
+ \row
+ \li \l{simplebrowser-tango}{Tango Icon Library}
+ \li Public Domain
+ \endtable
*/
diff --git a/examples/webenginewidgets/simplebrowser/webpage.cpp b/examples/webenginewidgets/simplebrowser/webpage.cpp
index 1859bad97..ab9dce4b8 100644
--- a/examples/webenginewidgets/simplebrowser/webpage.cpp
+++ b/examples/webenginewidgets/simplebrowser/webpage.cpp
@@ -198,7 +198,7 @@ void WebPage::handleRegisterProtocolHandlerRequested(QWebEngineRegisterProtocolH
//! [registerProtocolHandlerRequested]
#if QT_CONFIG(ssl)
-void WebPage::handleSelectClientCertificate(QWebEngineClientCertSelection selection)
+void WebPage::handleSelectClientCertificate(QWebEngineClientCertificateSelection selection)
{
// Just select one.
selection.select(selection.certificates().at(0));
diff --git a/examples/webenginewidgets/simplebrowser/webpage.h b/examples/webenginewidgets/simplebrowser/webpage.h
index 72cea5304..0b351ab31 100644
--- a/examples/webenginewidgets/simplebrowser/webpage.h
+++ b/examples/webenginewidgets/simplebrowser/webpage.h
@@ -70,7 +70,7 @@ private slots:
void handleProxyAuthenticationRequired(const QUrl &requestUrl, QAuthenticator *auth, const QString &proxyHost);
void handleRegisterProtocolHandlerRequested(QWebEngineRegisterProtocolHandlerRequest request);
#if QT_CONFIG(ssl)
- void handleSelectClientCertificate(QWebEngineClientCertSelection clientCertSelection);
+ void handleSelectClientCertificate(QWebEngineClientCertificateSelection clientCertSelection);
#endif
};
diff --git a/examples/webenginewidgets/stylesheetbrowser/3rdparty/COPYING b/examples/webenginewidgets/stylesheetbrowser/3rdparty/COPYING
new file mode 100644
index 000000000..220881da6
--- /dev/null
+++ b/examples/webenginewidgets/stylesheetbrowser/3rdparty/COPYING
@@ -0,0 +1 @@
+The icons in this repository are herefore released into the Public Domain.
diff --git a/examples/webenginewidgets/stylesheetbrowser/3rdparty/qt_attribution.json b/examples/webenginewidgets/stylesheetbrowser/3rdparty/qt_attribution.json
new file mode 100644
index 000000000..ffca1812b
--- /dev/null
+++ b/examples/webenginewidgets/stylesheetbrowser/3rdparty/qt_attribution.json
@@ -0,0 +1,24 @@
+{
+ "Id": "stylesheetbrowser-tango",
+ "Name": "Tango Icon Library",
+ "QDocModule": "qtwebengine",
+ "QtUsage": "Used in WebEngine StyleSheet Browser example.",
+
+ "QtParts": [ "examples" ],
+ "Description": "Selected icons from the Tango Icon Library",
+ "Homepage": "http://tango.freedesktop.org/Tango_Icon_Library",
+ "Version": "0.8.90",
+ "DownloadLocation": "http://tango.freedesktop.org/releases/tango-icon-theme-0.8.90.tar.gz",
+ "LicenseId": "DocumentRef-PublicDomain",
+ "License": "Public Domain",
+ "LicenseFile": "COPYING",
+ "Copyright": "Ulisse Perusin <uli.peru@gmail.com>
+Steven Garrity <sgarrity@silverorange.com>
+Lapo Calamandrei <calamandrei@gmail.com>
+Ryan Collier <rcollier@novell.com>
+Rodney Dawes <dobey@novell.com>
+Andreas Nilsson <nisses.mail@home.se>
+Tuomas Kuosmanen <tigert@tigert.com>
+Garrett LeSage <garrett@novell.com>
+Jakub Steiner <jimmac@novell.com>"
+}
diff --git a/examples/webenginewidgets/stylesheetbrowser/view-refresh.png b/examples/webenginewidgets/stylesheetbrowser/3rdparty/view-refresh.png
index cab4d02c7..cab4d02c7 100644
--- a/examples/webenginewidgets/stylesheetbrowser/view-refresh.png
+++ b/examples/webenginewidgets/stylesheetbrowser/3rdparty/view-refresh.png
Binary files differ
diff --git a/examples/webenginewidgets/stylesheetbrowser/doc/src/stylesheetbrowser.qdoc b/examples/webenginewidgets/stylesheetbrowser/doc/src/stylesheetbrowser.qdoc
index b4db10836..5b271bafb 100644
--- a/examples/webenginewidgets/stylesheetbrowser/doc/src/stylesheetbrowser.qdoc
+++ b/examples/webenginewidgets/stylesheetbrowser/doc/src/stylesheetbrowser.qdoc
@@ -55,4 +55,14 @@
\quotefromfile webenginewidgets/stylesheetbrowser/mainwindow.cpp
\skipto MainWindow::removeStyleSheet
\printuntil /^\}/
+
+ \section1 Files and Attributions
+
+ The example uses icons from the Tango Icon Library:
+
+ \table
+ \row
+ \li \l{stylesheetbrowser-tango}{Tango Icon Library}
+ \li Public Domain
+ \endtable
*/
diff --git a/examples/webenginewidgets/stylesheetbrowser/stylesheetbrowser.qrc b/examples/webenginewidgets/stylesheetbrowser/stylesheetbrowser.qrc
index 8805f2c53..a1cebd6a7 100644
--- a/examples/webenginewidgets/stylesheetbrowser/stylesheetbrowser.qrc
+++ b/examples/webenginewidgets/stylesheetbrowser/stylesheetbrowser.qrc
@@ -1,5 +1,5 @@
<RCC>
<qresource prefix="/">
- <file>view-refresh.png</file>
+ <file alias="view-refresh.png">3rdparty/view-refresh.png</file>
</qresource>
</RCC>
diff --git a/examples/webenginewidgets/webenginewidgets.pro b/examples/webenginewidgets/webenginewidgets.pro
index e98503e09..20c7ead50 100644
--- a/examples/webenginewidgets/webenginewidgets.pro
+++ b/examples/webenginewidgets/webenginewidgets.pro
@@ -10,10 +10,11 @@ SUBDIRS += \
html2pdf \
simplebrowser \
stylesheetbrowser \
- videoplayer
+ videoplayer \
+ webui
qtConfig(webengine-geolocation): SUBDIRS += maps
-qtCondif(webengine-webchannel): SUBDIRS += markdowneditor
+qtConfig(webengine-webchannel): SUBDIRS += markdowneditor
qtConfig(webengine-spellchecker):!qtConfig(webengine-native-spellchecker):!cross_compile {
SUBDIRS += spellchecker
diff --git a/examples/webenginewidgets/webui/about.html b/examples/webenginewidgets/webui/about.html
new file mode 100644
index 000000000..7b5a58969
--- /dev/null
+++ b/examples/webenginewidgets/webui/about.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Qt WebEngine WebUI Example</title>
+ <style>
+ html {
+ background: #f0f0f0;
+ color: #303030;
+ font: 16px system-ui;
+ height: 100%;
+ }
+
+ body {
+ margin: 0;
+ padding: 0;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ }
+
+ body > * {
+ padding-left: 20px;
+ padding-right: 20px;
+ }
+
+ header {
+ flex: none;
+ display: flex;
+ align-items: center;
+ background: #f0fff0;
+ border-bottom: 1px solid #e0e0e0;
+ padding-top: 20px;
+ padding-bottom: 20px;
+ }
+
+ header > h1 {
+ font: bold 20px system-ui;
+ margin-left: 18px;
+ }
+
+ main {
+ flex: auto;
+ }
+
+ footer {
+ flex: none;
+ display: flex;
+ justify-content: center;
+ padding-bottom: 20px;
+ }
+
+ button {
+ background: #41cd52;
+ color: #f0f0f0;
+ font: 16px system-ui;
+ border: 0;
+ box-shadow: 0px 1px 3px rgb(0,0,0,0.5);
+ cursor: pointer;
+ margin: 0 0 1px;
+ padding: 10px 24px;
+ }
+
+ button:hover {
+ background: #50dc61;
+ }
+
+ button:active {
+ background: #50dc61;
+ box-shadow: 0px 1px 2px rgb(0,0,0,0.5);
+ margin: 1px 0 0;
+ }
+
+ button:focus {
+ outline: 0;
+ }
+
+ </style>
+ </head>
+ <body>
+ <header>
+ <img width="48px" height="48px"
+ src="qrc:/qt-project.org/qmessagebox/images/qtlogo-64.png">
+ <h1>WebEngine Widgets<br>WebUI Example</h1>
+ </header>
+ <main>
+ <p>
+ Aside from the built-in schemes, such as <code>http</code> and
+ <code>qrc</code>, Qt WebEngine may be extended with <em>custom
+ schemes</em> by creating <em>custom scheme handlers</em>.
+ </p>
+
+ <p>
+ This is a simple HTML page loaded from a custom scheme and
+ displayed by a <code>QWebEngineView</code>. Even the Quit button
+ below is a standard HTML <code>&lt;button&gt;</code> element.
+ </p>
+
+ <p>
+ Read the documentation to find out
+ </p>
+ <ul>
+ <li>
+ <p>
+ How to create a custom scheme handler which serves HTML
+ and handles HTML form submissions.
+ </p>
+ </li>
+ <li>
+ <p>
+ How to prevent ordinary web content from accessing the
+ custom scheme.
+ </p>
+ </li>
+ <li>
+ <p>
+ How to prevent any other scheme from submitting HTML
+ form data.
+ </p>
+ </li>
+ </ul>
+ </main>
+ <footer>
+ <form action="" method="post">
+ <button name="quit">Quit</button>
+ </form>
+ </footer>
+ </body>
+</html>
diff --git a/examples/webenginewidgets/webui/doc/images/webui-example.png b/examples/webenginewidgets/webui/doc/images/webui-example.png
new file mode 100644
index 000000000..84e2c7fc3
--- /dev/null
+++ b/examples/webenginewidgets/webui/doc/images/webui-example.png
Binary files differ
diff --git a/examples/webenginewidgets/webui/doc/src/webui.qdoc b/examples/webenginewidgets/webui/doc/src/webui.qdoc
new file mode 100644
index 000000000..47d9fbad1
--- /dev/null
+++ b/examples/webenginewidgets/webui/doc/src/webui.qdoc
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example webenginewidgets/webui
+ \title WebEngine Widgets WebUI Example
+ \ingroup webengine-widgetexamples
+ \brief Displays HTML over a custom scheme.
+
+ \image webui-example.png
+
+ \e {WebUI} demonstrates how to implement a custom scheme in a secure way.
+
+ Aside from the built-in URL schemes, such as \c {http} and \c {qrc}, Qt
+ WebEngine may be extended with \e {custom schemes} by creating \e {custom
+ scheme handlers}. This example shows:
+
+ \list
+ \li How to create a custom scheme handler which serves HTML and handles
+ HTML form submissions.
+ \li How to prevent ordinary web content from accessing the custom scheme.
+ \li How to prevent any other scheme from submitting HTML form data.
+ \endlist
+
+ \include examples-run.qdocinc
+
+ \section1 Overview
+
+ The example program consists of a single \l {QWebEngineView} showing a
+ simple HTML page loaded from the URL \c {webui:about}, over our custom
+ scheme. Pressing the button at the bottom of the page will trigger an HTML
+ form submission via POST to the same URL, at which point our custom scheme
+ handler will cause the application to exit.
+
+ The program is divided into two parts, the \c {main} function for setting
+ everything up, and the \c {WebUiHandler} class for implementing our custom
+ scheme handler. The \c {main} function is quite short:
+
+ \quotefromfile webenginewidgets/webui/main.cpp
+ \skipto int main
+ \printuntil /^\}/
+
+ Aside from the relatively standard setup of widgets, two points are
+ noteworthy. First, we call the static method \c
+ {WebUiHandler::registerUrlScheme()} to register our custom scheme with the
+ web engine. Second, we create and install our custom scheme handler \c
+ {WebUiHandler} using \l
+ {QWebEngineProfile::installUrlSchemeHandler()}{installUrlSchemeHandler()}.
+ The following sections describe these aspects in more detail.
+
+ \section1 Registering the Scheme
+
+ As custom schemes are integrated directly into the web engine, they do not
+ necessarily need to follow the standard security rules which apply to
+ ordinary web content. Depending on the chosen configuration, content served
+ over a custom scheme may be given access to local resources, be set to
+ ignore Content-Security-Policy rules, or conversely, be denied access to any
+ other content entirely.
+
+ In order to take advantage of these possibilities, the custom scheme must
+ first be registered. This means creating and configuring a \l
+ {QWebEngineUrlScheme} object and then handing it over to \l
+ {QWebEngineUrlScheme::registerScheme()}. The example program does exactly this in
+ the static method \c {WebUiHandler::registerUrlScheme()}:
+
+ \quotefromfile webenginewidgets/webui/webuihandler.cpp
+ \skipto void WebUiHandler::registerUrlScheme
+ \printuntil /^\}/
+
+ A custom scheme needs a name, which can be set by passing it to
+ the constructor of \c {QWebEngineUrlScheme} or by calling \l
+ {QWebEngineUrlScheme::setName}. In the above, the name \c {webui} is set
+ through the constructor. Additionally, we activate the flags \l
+ {QWebEngineUrlScheme::SecureScheme}{SecureScheme}, \l
+ {QWebEngineUrlScheme::LocalScheme}{LocalScheme} and \l
+ {QWebEngineUrlScheme::LocalAccessAllowed}{LocalAccessAllowed}. Since our
+ custom scheme handler will not deliver resources received from insecure
+ network connections, we can safely mark it as a \c {SecureScheme}. The \c {LocalScheme}
+ flag prevents content from non-local schemes (such as \c {http}) from
+ interacting with our custom scheme. Without this flag it would be possible,
+ for example, to embed the \c {webui:about} page in an \c <iframe> element on
+ a remotely loaded HTML page, perhaps to attempt a phishing attack. We also
+ need the \c {LocalAccessAllowed} flag without which we would not be able to
+ access the \c {webui} scheme from our \c {webui:about} page.
+
+ Earlier we saw that the call to \c {WebUiHandler::registerUrlScheme()} is
+ made already at the top of the \c {main} function. This is so because custom
+ schemes need to be registered as early as possible so that that they can be
+ passed to all subprocesses. Specifically, custom schemes need to be registered
+ before any other Qt WebEngine classes are instantiated by the application.
+
+ \section1 Handling Requests
+
+ A custom scheme handler is, broadly speaking, similar to a web application
+ served over HTTP. However, because custom schemes are integrated directly
+ into the web engine, they have the advantage in terms of efficiency: there's
+ no need for generating and parsing HTTP messages or for transferring data
+ over sockets.
+
+ Implementing a handler means creating a subclass of \l
+ {QWebEngineUrlSchemeHandler}, which is just what is done by the \c
+ {WebUiHandler} class of the example program:
+
+ \quotefromfile webenginewidgets/webui/webuihandler.h
+ \skipto class WebUiHandler
+ \printuntil /^\}/
+
+ For each request to a \c {webui} URL, the \c
+ {WebUiHandler::requestStarted()} method will be called:
+
+ \quotefromfile webenginewidgets/webui/webuihandler.cpp
+ \skipto void WebUiHandler::requestStarted
+ \printuntil /^\}/
+
+ The \l {QWebEngineUrlRequestJob} object \c {job} contains the request's
+ attributes and provides methods for replying to the request with a response.
+ Responses are generated asynchronously by reading them from the \l
+ {QIODevice} that the application passes to \l
+ {QWebEngineUrlRequestJob::reply()}{reply()}.
+
+ \warning The \c requestStarted() method is not called from the main thread,
+ but from the web engine's IO thread. Care must be taken to synchronize
+ access to any resources on the main thread.
+
+ Aside from the usual fare of \l
+ {QWebEngineUrlRequestJob::requestMethod()}{requestMethod} and \l
+ {QWebEngineUrlRequestJob::requestUrl()}{requestUrl}, there is also the \l
+ {QWebEngineUrlRequestJob::initiator()}{initiator}, holding the origin of the
+ content which initiated the request. An empty \c initiator means the request
+ was initiated directly by the application (via \l
+ {QWebEnginePage::setUrl()}, for example). The special value \c "null"
+ corresponds to an opaque origin (a sandboxed \c {<iframe>} element, for
+ example). Otherwise, the \c initiator will contain the URL scheme, hostname,
+ and port of the content which initiated the request.
+
+ In this example, the \c initiator is used to ensure that \c {POST} requests
+ to \c {webui:about} will only trigger the application's exit if they
+ originate from the \c {webui} scheme. This prevents content loaded over
+ other schemes from triggering the application's exit.
+
+*/
diff --git a/examples/webenginewidgets/webui/main.cpp b/examples/webenginewidgets/webui/main.cpp
new file mode 100644
index 000000000..3e9f61fe4
--- /dev/null
+++ b/examples/webenginewidgets/webui/main.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, 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$
+**
+****************************************************************************/
+
+#include "webuihandler.h"
+
+#include <QApplication>
+#include <QWebEnginePage>
+#include <QWebEngineProfile>
+#include <QWebEngineView>
+
+int main(int argc, char *argv[])
+{
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+
+ WebUiHandler::registerUrlScheme();
+
+ QApplication app(argc, argv);
+
+ QWebEngineProfile profile;
+
+ WebUiHandler handler;
+ profile.installUrlSchemeHandler(WebUiHandler::schemeName, &handler);
+
+ QWebEnginePage page(&profile);
+ page.load(WebUiHandler::aboutUrl);
+
+ QWebEngineView view;
+ view.setPage(&page);
+ view.setContextMenuPolicy(Qt::NoContextMenu);
+ view.resize(500, 600);
+ view.show();
+
+ return app.exec();
+}
diff --git a/examples/webenginewidgets/webui/webui.pro b/examples/webenginewidgets/webui/webui.pro
new file mode 100644
index 000000000..714833587
--- /dev/null
+++ b/examples/webenginewidgets/webui/webui.pro
@@ -0,0 +1,16 @@
+TEMPLATE = app
+
+QT += webenginewidgets
+
+HEADERS += \
+ webuihandler.h
+
+SOURCES += \
+ main.cpp \
+ webuihandler.cpp
+
+RESOURCES += \
+ webui.qrc
+
+target.path = $$[QT_INSTALL_EXAMPLES]/webenginewidgets/webui
+INSTALLS += target
diff --git a/examples/webenginewidgets/webui/webui.qrc b/examples/webenginewidgets/webui/webui.qrc
new file mode 100644
index 000000000..6ddf01fa2
--- /dev/null
+++ b/examples/webenginewidgets/webui/webui.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>about.html</file>
+ </qresource>
+</RCC>
diff --git a/examples/webenginewidgets/webui/webuihandler.cpp b/examples/webenginewidgets/webui/webuihandler.cpp
new file mode 100644
index 000000000..63c249368
--- /dev/null
+++ b/examples/webenginewidgets/webui/webuihandler.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, 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$
+**
+****************************************************************************/
+
+#include "webuihandler.h"
+
+#include <QApplication>
+#include <QFile>
+#include <QWebEngineUrlRequestJob>
+#include <QWebEngineUrlScheme>
+
+#define SCHEMENAME "webui"
+
+const QByteArray WebUiHandler::schemeName = QByteArrayLiteral(SCHEMENAME);
+const QUrl WebUiHandler::aboutUrl = QUrl(QStringLiteral(SCHEMENAME ":about"));
+
+WebUiHandler::WebUiHandler(QObject *parent)
+ : QWebEngineUrlSchemeHandler(parent)
+{
+}
+
+void WebUiHandler::requestStarted(QWebEngineUrlRequestJob *job)
+{
+ static const QUrl webUiOrigin(QStringLiteral(SCHEMENAME ":"));
+ static const QByteArray GET(QByteArrayLiteral("GET"));
+ static const QByteArray POST(QByteArrayLiteral("POST"));
+
+ QByteArray method = job->requestMethod();
+ QUrl url = job->requestUrl();
+ QUrl initiator = job->initiator();
+
+ if (method == GET && url == aboutUrl) {
+ QFile *file = new QFile(QStringLiteral(":/about.html"), job);
+ file->open(QIODevice::ReadOnly);
+ job->reply(QByteArrayLiteral("text/html"), file);
+ } else if (method == POST && url == aboutUrl && initiator == webUiOrigin) {
+ job->fail(QWebEngineUrlRequestJob::RequestAborted);
+ QApplication::exit();
+ } else {
+ job->fail(QWebEngineUrlRequestJob::UrlNotFound);
+ }
+}
+
+// static
+void WebUiHandler::registerUrlScheme()
+{
+ QWebEngineUrlScheme webUiScheme(schemeName);
+ webUiScheme.setFlags(QWebEngineUrlScheme::SecureScheme |
+ QWebEngineUrlScheme::LocalScheme |
+ QWebEngineUrlScheme::LocalAccessAllowed);
+ QWebEngineUrlScheme::registerScheme(webUiScheme);
+}
diff --git a/examples/webenginewidgets/webui/webuihandler.h b/examples/webenginewidgets/webui/webuihandler.h
new file mode 100644
index 000000000..f2ac0dcef
--- /dev/null
+++ b/examples/webenginewidgets/webui/webuihandler.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, 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$
+**
+****************************************************************************/
+
+#ifndef WEBUIHANDLER_H
+#define WEBUIHANDLER_H
+
+#include <QWebEngineUrlSchemeHandler>
+
+class WebUiHandler : public QWebEngineUrlSchemeHandler
+{
+ Q_OBJECT
+public:
+ explicit WebUiHandler(QObject *parent = nullptr);
+
+ void requestStarted(QWebEngineUrlRequestJob *job) override;
+
+ static void registerUrlScheme();
+
+ const static QByteArray schemeName;
+ const static QUrl aboutUrl;
+};
+
+#endif // !WEBUIHANDLER_H