[evolution] Add a simple EMarkdownEditor widget
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] Add a simple EMarkdownEditor widget
- Date: Tue, 25 Jan 2022 17:32:58 +0000 (UTC)
commit 4c25b2ebdeaf772357ab9464b24d3a1ede2a6162
Author: Milan Crha <mcrha redhat com>
Date: Tue Jan 25 18:31:27 2022 +0100
Add a simple EMarkdownEditor widget
Related to https://gitlab.gnome.org/GNOME/evolution/-/issues/449
data/icons/CMakeLists.txt | 18 +
...hicolor_actions_scalable_markdown-bold-dark.svg | 19 +
.../hicolor_actions_scalable_markdown-bold.svg | 18 +
...olor_actions_scalable_markdown-bullets-dark.svg | 31 ++
.../hicolor_actions_scalable_markdown-bullets.svg | 31 ++
...hicolor_actions_scalable_markdown-code-dark.svg | 28 +
.../hicolor_actions_scalable_markdown-code.svg | 26 +
...color_actions_scalable_markdown-header-dark.svg | 23 +
.../hicolor_actions_scalable_markdown-header.svg | 22 +
...hicolor_actions_scalable_markdown-help-dark.svg | 34 ++
.../hicolor_actions_scalable_markdown-help.svg | 33 ++
...color_actions_scalable_markdown-italic-dark.svg | 16 +
.../hicolor_actions_scalable_markdown-italic.svg | 16 +
...hicolor_actions_scalable_markdown-link-dark.svg | 30 ++
.../hicolor_actions_scalable_markdown-link.svg | 27 +
...olor_actions_scalable_markdown-numbers-dark.svg | 40 ++
.../hicolor_actions_scalable_markdown-numbers.svg | 40 ++
...icolor_actions_scalable_markdown-quote-dark.svg | 25 +
.../hicolor_actions_scalable_markdown-quote.svg | 25 +
.../evolution-mail-composer-docs.sgml.in | 4 +
.../evolution-util/evolution-util-docs.sgml.in | 5 +
po/POTFILES.in | 1 +
src/e-util/CMakeLists.txt | 5 +
src/e-util/e-markdown-editor.c | 585 +++++++++++++++++++++
src/e-util/e-markdown-editor.h | 57 ++
src/e-util/e-util.h | 1 +
src/e-util/test-markdown-editor.c | 81 +++
27 files changed, 1241 insertions(+)
---
diff --git a/data/icons/CMakeLists.txt b/data/icons/CMakeLists.txt
index 2d445c9695..d6cbfb2b3f 100644
--- a/data/icons/CMakeLists.txt
+++ b/data/icons/CMakeLists.txt
@@ -92,6 +92,24 @@ set(private_icons
hicolor_actions_32x32_view-calendar-month.png
hicolor_actions_32x32_view-calendar-week.png
hicolor_actions_32x32_view-calendar-workweek.png
+ hicolor_actions_scalable_markdown-bold.svg
+ hicolor_actions_scalable_markdown-bold-dark.svg
+ hicolor_actions_scalable_markdown-bullets.svg
+ hicolor_actions_scalable_markdown-bullets-dark.svg
+ hicolor_actions_scalable_markdown-code.svg
+ hicolor_actions_scalable_markdown-code-dark.svg
+ hicolor_actions_scalable_markdown-header.svg
+ hicolor_actions_scalable_markdown-header-dark.svg
+ hicolor_actions_scalable_markdown-help.svg
+ hicolor_actions_scalable_markdown-help-dark.svg
+ hicolor_actions_scalable_markdown-italic.svg
+ hicolor_actions_scalable_markdown-italic-dark.svg
+ hicolor_actions_scalable_markdown-link.svg
+ hicolor_actions_scalable_markdown-link-dark.svg
+ hicolor_actions_scalable_markdown-numbers.svg
+ hicolor_actions_scalable_markdown-numbers-dark.svg
+ hicolor_actions_scalable_markdown-quote.svg
+ hicolor_actions_scalable_markdown-quote-dark.svg
hicolor_actions_scalable_view-calendar-day.svg
hicolor_actions_scalable_view-calendar-list.svg
hicolor_actions_scalable_view-calendar-month.svg
diff --git a/data/icons/hicolor_actions_scalable_markdown-bold-dark.svg
b/data/icons/hicolor_actions_scalable_markdown-bold-dark.svg
new file mode 100644
index 0000000000..e56fb34935
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_markdown-bold-dark.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ version="1.1"
+ id="svg33406"
+ xml:space="preserve"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
+ id="defs33410" /><g
+ id="g33418"
+ transform="matrix(1.3333333,0,0,1.3333333,-0.4184891,-0.76629467)"
+ style="fill:#e6e6e6;stroke:#e6e6e6"><path
+ d="m 3.7098313,15.21086 h 5.5434688 c 3.0378319,0 4.8709559,-1.203315 4.8709559,-3.185358 0,-1.364885
-0.924079,-2.4066304 -2.615885,-2.8913388 1.456277,-0.3522586 2.207967,-1.1591661 2.207967,-2.3925413
0,-1.8345634 -1.690803,-2.8030402 -4.8539172,-2.8030402 H 3.771971 L 3.709831,4.5989496 C 4.258064,4.7605188
4.5868035,4.9361785 4.8062972,5.1268679 V 14.007545 C 4.4775581,14.315654 4.2269945,14.433074
3.7719711,14.520434 Z M 7.452249,8.7377548 V 5.0395077 c 0.3608114,-0.059179 0.7045847,-0.07327
1.174642,-0.07327 1.456276,0 2.286141,0.645338 2.286141,1.804504 0,1.3066452 -0.829865,1.9670129
-2.4585287,1.9670129 z m 1.2377841,5.4304202 c -0.3918814,0 -0.7677269,-0.02912 -1.2377841,-0.05824 V
9.794534 h 0.9711844 c 1.8631896,0 2.8193406,0.763697 2.8193406,2.260092 0,1.453185 -0.798796,2.113552
-2.5527409,2.113552 z"
+
style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:#e6e6e6;stroke-width:0.727722;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path33420" /></g></svg>
diff --git a/data/icons/hicolor_actions_scalable_markdown-bold.svg
b/data/icons/hicolor_actions_scalable_markdown-bold.svg
new file mode 100644
index 0000000000..39a46d8331
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_markdown-bold.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ version="1.1"
+ id="svg33406"
+ xml:space="preserve"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
+ id="defs33410" /><g
+ id="g33418"
+ transform="matrix(1.3333333,0,0,1.3333333,-0.4184891,-0.76629467)"><path
+ d="m 3.7098313,15.21086 h 5.5434688 c 3.0378319,0 4.8709559,-1.203315 4.8709559,-3.185358 0,-1.364885
-0.924079,-2.4066304 -2.615885,-2.8913388 1.456277,-0.3522586 2.207967,-1.1591661 2.207967,-2.3925413
0,-1.8345634 -1.690803,-2.8030402 -4.8539172,-2.8030402 H 3.771971 L 3.709831,4.5989496 C 4.258064,4.7605188
4.5868035,4.9361785 4.8062972,5.1268679 V 14.007545 C 4.4775581,14.315654 4.2269945,14.433074
3.7719711,14.520434 Z M 7.452249,8.7377548 V 5.0395077 c 0.3608114,-0.059179 0.7045847,-0.07327
1.174642,-0.07327 1.456276,0 2.286141,0.645338 2.286141,1.804504 0,1.3066452 -0.829865,1.9670129
-2.4585287,1.9670129 z m 1.2377841,5.4304202 c -0.3918814,0 -0.7677269,-0.02912 -1.2377841,-0.05824 V
9.794534 h 0.9711844 c 1.8631896,0 2.8193406,0.763697 2.8193406,2.260092 0,1.453185 -0.798796,2.113552
-2.5527409,2.113552 z"
+
style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:0.727722;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path33420" /></g></svg>
diff --git a/data/icons/hicolor_actions_scalable_markdown-bullets-dark.svg
b/data/icons/hicolor_actions_scalable_markdown-bullets-dark.svg
new file mode 100644
index 0000000000..fa2bf472e6
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_markdown-bullets-dark.svg
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ version="1.1"
+ id="svg33406"
+ xml:space="preserve"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
+ id="defs33410" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#e6e6e6;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 7,6 H 21"
+ id="path33702" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#e6e6e6;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 3,6 H 5"
+ id="path33702-9" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#e6e6e6;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 3,12 H 5"
+ id="path33702-9-1" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#e6e6e6;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 3,18 H 5"
+ id="path33702-9-7" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#e6e6e6;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 7,12 H 20.99999"
+ id="path33704" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#e6e6e6;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 7,18 H 21"
+ id="path33706" /></svg>
diff --git a/data/icons/hicolor_actions_scalable_markdown-bullets.svg
b/data/icons/hicolor_actions_scalable_markdown-bullets.svg
new file mode 100644
index 0000000000..fe13db36e8
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_markdown-bullets.svg
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ version="1.1"
+ id="svg33406"
+ xml:space="preserve"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
+ id="defs33410" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#1a1a1a;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 7,6 H 21"
+ id="path33702" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#1a1a1a;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 3,6 H 5"
+ id="path33702-9" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#1a1a1a;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 3,12 H 5"
+ id="path33702-9-1" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#1a1a1a;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 3,18 H 5"
+ id="path33702-9-7" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#1a1a1a;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 7,12 H 20.99999"
+ id="path33704" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#1a1a1a;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 7,18 H 21"
+ id="path33706" /></svg>
diff --git a/data/icons/hicolor_actions_scalable_markdown-code-dark.svg
b/data/icons/hicolor_actions_scalable_markdown-code-dark.svg
new file mode 100644
index 0000000000..23b6dcf3ff
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_markdown-code-dark.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ version="1.1"
+ id="svg51326"
+ xml:space="preserve"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
+ id="defs51330" /><g
+ id="g51332"
+ transform="scale(1.3333333)"
+ style="fill:#e6e6e6"><g
+ id="g51334"
+ transform="translate(-0.12899983,0.66800028)"
+ style="fill:#e6e6e6"><path
+ d="M 6.879,5.004 2.035,7.879 v 0.812 l 4.844,2.985 V 10.582 L 3.035,8.285 6.879,6.004 Z"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path51336" /><path
+ d="M 7.48,13.395 H 8.371 L 10.934,3.145 H 9.98 Z"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path51338" /><path
+ d="M 11.551,11.613 16.395,8.738 V 7.91 L 11.551,4.941 v 1.094 l 3.828,2.281 -3.828,2.282 z"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path51340" /></g></g></svg>
diff --git a/data/icons/hicolor_actions_scalable_markdown-code.svg
b/data/icons/hicolor_actions_scalable_markdown-code.svg
new file mode 100644
index 0000000000..ad3aa41fd4
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_markdown-code.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ version="1.1"
+ id="svg51326"
+ xml:space="preserve"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
+ id="defs51330" /><g
+ id="g51332"
+ transform="scale(1.3333333)"><g
+ id="g51334"
+ transform="translate(-0.12899983,0.66800028)"><path
+ d="M 6.879,5.004 2.035,7.879 v 0.812 l 4.844,2.985 V 10.582 L 3.035,8.285 6.879,6.004 Z"
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path51336" /><path
+ d="M 7.48,13.395 H 8.371 L 10.934,3.145 H 9.98 Z"
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path51338" /><path
+ d="M 11.551,11.613 16.395,8.738 V 7.91 L 11.551,4.941 v 1.094 l 3.828,2.281 -3.828,2.282 z"
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path51340" /></g></g></svg>
diff --git a/data/icons/hicolor_actions_scalable_markdown-header-dark.svg
b/data/icons/hicolor_actions_scalable_markdown-header-dark.svg
new file mode 100644
index 0000000000..d5dcf32db1
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_markdown-header-dark.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ version="1.1"
+ id="svg4631"
+ xml:space="preserve"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
+ id="defs4635" /><g
+ id="g4637"
+ transform="scale(1.3333333)"
+ style="stroke:none"><g
+ id="g4639"
+ style="stroke:none"><g
+ id="g4641"
+ style="stroke:none"><path
+ d="m 4.902,3.543 h 1.485 v 4.484 h 5.375 V 3.543 h 1.484 V 14.48 H 11.762 V 9.277 H 6.387 V 14.48
H 4.902 Z"
+
style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path4643" /></g></g></g></svg>
diff --git a/data/icons/hicolor_actions_scalable_markdown-header.svg
b/data/icons/hicolor_actions_scalable_markdown-header.svg
new file mode 100644
index 0000000000..e509013d69
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_markdown-header.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ version="1.1"
+ id="svg4631"
+ xml:space="preserve"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
+ id="defs4635" /><g
+ id="g4637"
+ transform="scale(1.3333333)"><g
+ id="g4639"
+ style="stroke:none;fill:#1a1a1a"><g
+ id="g4641"
+ style="stroke:none;fill:#1a1a1a"><path
+ d="m 4.902,3.543 h 1.485 v 4.484 h 5.375 V 3.543 h 1.484 V 14.48 H 11.762 V 9.277 H 6.387 V 14.48
H 4.902 Z"
+
style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path4643" /></g></g></g></svg>
diff --git a/data/icons/hicolor_actions_scalable_markdown-help-dark.svg
b/data/icons/hicolor_actions_scalable_markdown-help-dark.svg
new file mode 100644
index 0000000000..fcd2864596
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_markdown-help-dark.svg
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ version="1.1"
+ id="svg11209"
+ xml:space="preserve"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
+ id="defs11213" /><path
+ d="m 7.5679998,11.765333 h 3.1453332 v -0.478667 c 0,-1 2.313333,-1.5839996 2.313333,-4.1253328
0,-2.0826667 -1.542666,-3.2493333 -4.2719996,-3.2493333 -1.3333333,0 -2.6866666,0.2906667 -3.8333332,0.812 l
0.7093333,2.3546666 c 0.7493333,-0.3333333 1.5413333,-0.48 2.3333333,-0.48 1.1866666,0 1.8333333,0.3546667
1.8333333,1 0,1.2079999 -2.2293333,1.9999999 -2.2293333,3.6879995 z m 1.5413333,5 c 1.1039999,0
1.8959999,-0.792 1.8959999,-1.916 0,-1.166667 -0.770667,-1.98 -1.8959999,-1.98 -1.1453333,0
-1.9159999,0.813333 -1.9159999,1.98 0,1.124 0.7906666,1.916 1.9159999,1.916 z"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.33333"
+ id="path11219" /><g
+ id="g11221"
+ transform="matrix(1.3333333,1.23672,-1.23672,1.3333333,0,0)"
+ style="stroke:#e6e6e6"><path
+ d="M 12.671,-3.092 12.67,0.205"
+
style="fill:none;stroke:#e6e6e6;stroke-width:0.549878;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path11223" /></g><g
+ id="g11225"
+ transform="matrix(1.3333333,1.23672,-1.23672,1.3333333,0,0)"
+ style="stroke:#e6e6e6"><path
+ d="m 11.571,-1.444 1.1,-2.2 1.099,2.2"
+
style="fill:none;stroke:#e6e6e6;stroke-width:0.549878;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path11227" /></g><g
+ id="g11229"
+ transform="scale(1.3333333)"
+ style="stroke:#e6e6e6"><path
+ d="m 12.75,10.5 h -3 v 3 h 4.5 v -2.25"
+
style="fill:none;stroke:#e6e6e6;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path11231" /></g></svg>
diff --git a/data/icons/hicolor_actions_scalable_markdown-help.svg
b/data/icons/hicolor_actions_scalable_markdown-help.svg
new file mode 100644
index 0000000000..6be86d3402
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_markdown-help.svg
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ version="1.1"
+ id="svg11209"
+ xml:space="preserve"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
+ id="defs11213" /><g
+ id="g11215"
+ transform="scale(1.3333333)"><g
+ id="g11217"><path
+ d="M 5.676,8.824 H 8.035 V 8.465 c 0,-0.75 1.735,-1.188 1.735,-3.094 0,-1.562 -1.157,-2.437
-3.204,-2.437 -1,0 -2.015,0.218 -2.875,0.609 l 0.532,1.766 c 0.562,-0.25 1.156,-0.36 1.75,-0.36 0.89,0
1.375,0.266 1.375,0.75 0,0.906 -1.672,1.5 -1.672,2.766 z m 1.156,3.75 c 0.828,0 1.422,-0.594 1.422,-1.437
0,-0.875 -0.578,-1.485 -1.422,-1.485 -0.859,0 -1.437,0.61 -1.437,1.485 0,0.843 0.593,1.437 1.437,1.437 z"
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path11219" /><g
+ id="g11221"
+ transform="matrix(1,0.92754,-0.92754,1,0,0)"><path
+ d="M 12.671,-3.092 12.67,0.205"
+
style="fill:none;stroke:#1a1a1a;stroke-width:0.549878;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path11223" /></g><g
+ id="g11225"
+ transform="matrix(1,0.92754,-0.92754,1,0,0)"><path
+ d="m 11.571,-1.444 1.1,-2.2 1.099,2.2"
+
style="fill:none;stroke:#1a1a1a;stroke-width:0.549878;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path11227" /></g><g
+ id="g11229"><path
+ d="m 12.75,10.5 h -3 v 3 h 4.5 v -2.25"
+
style="fill:none;stroke:#1a1a1a;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path11231" /></g></g></g></svg>
diff --git a/data/icons/hicolor_actions_scalable_markdown-italic-dark.svg
b/data/icons/hicolor_actions_scalable_markdown-italic-dark.svg
new file mode 100644
index 0000000000..87e0445fae
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_markdown-italic-dark.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ version="1.1"
+ id="svg33406"
+ xml:space="preserve"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
+ id="defs33410" /><path
+ d="m 8.0000001,20 h 5.9658889 l 0.09764,-0.894667 C 13.340012,19.021333 12.655299,18.876
12.049447,18.48 L 13.98592,5.5 C 14.611801,5.1253333 15.178848,4.98 15.902365,4.876 L 16.000005,4 h -5.828201
l -0.117665,0.876 c 0.743546,0.104 1.388202,0.2706667 1.936473,0.624 l -1.936473,12.98 c -0.6258802,0.416
-1.2129558,0.541333 -1.9364732,0.625333 z"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.2919"
+ id="path33416" /></svg>
diff --git a/data/icons/hicolor_actions_scalable_markdown-italic.svg
b/data/icons/hicolor_actions_scalable_markdown-italic.svg
new file mode 100644
index 0000000000..3b64797ad3
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_markdown-italic.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ version="1.1"
+ id="svg33406"
+ xml:space="preserve"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
+ id="defs33410" /><path
+ d="m 8.0000001,20 h 5.9658889 l 0.09764,-0.894667 C 13.340012,19.021333 12.655299,18.876
12.049447,18.48 L 13.98592,5.5 C 14.611801,5.1253333 15.178848,4.98 15.902365,4.876 L 16.000005,4 h -5.828201
l -0.117665,0.876 c 0.743546,0.104 1.388202,0.2706667 1.936473,0.624 l -1.936473,12.98 c -0.6258802,0.416
-1.2129558,0.541333 -1.9364732,0.625333 z"
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.2919"
+ id="path33416" /></svg>
diff --git a/data/icons/hicolor_actions_scalable_markdown-link-dark.svg
b/data/icons/hicolor_actions_scalable_markdown-link-dark.svg
new file mode 100644
index 0000000000..5cafddcdf8
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_markdown-link-dark.svg
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ version="1.1"
+ id="svg51326"
+ xml:space="preserve"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
+ id="defs51330" /><g
+ id="g51332"
+ transform="matrix(1.2391158,0.4923106,-0.4923106,1.2391158,5.1915138,-3.3935698)"
+ style="stroke:#e6e6e6"><g
+ id="g54244"
+ transform="rotate(38.936484,7.400522,4.6312859)"
+ style="stroke:#e6e6e6"><path
+
style="fill:none;fill-rule:evenodd;stroke:#e6e6e6;stroke-width:0.75px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 8.226042,6.6881392 c -0.250375,-1 -0.250375,-2.5 -3.7e-4,-3.5003801 0.2500051,-1.00038
0.749995,-1.50037 1.2503751,-1.75037 0.50038,-0.25 1.0003699,-0.25 1.5003749,3.8e-4 0.500005,0.25038
0.999995,0.75037 1.24962,1.7503851 0.249625,1.000015 0.249625,2.499985 -3.8e-4,3.4996149 -0.250005,0.99963
-0.749995,1.4996199 -1.237528,1.7496199 -0.487533,0.25 -1.0117169,0.25 -1.5117219,3.7e-4 C 8.976407,8.1881291
8.476417,7.6881391 8.226042,6.6881392 Z"
+ id="path53269" /><g
+ id="g53872"
+ style="stroke:#e6e6e6"><path
+
style="fill:none;fill-rule:evenodd;stroke:#e6e6e6;stroke-width:0.75px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 9.5279035,9.4814178 c 0.031913,0.432314 0.063768,0.8638272 0.1454647,1.2909192
0.081697,0.427092 0.2183089,0.866695 0.4123258,1.219544 0.194017,0.35285 0.455937,0.636559 0.735758,0.83268
0.279821,0.19612 0.581495,0.309578 0.900979,0.327199 0.319483,0.01762 0.645557,-0.05746 0.932875,-0.233203
0.287317,-0.175739 0.530677,-0.450964 0.727124,-0.786131 0.196448,-0.335166 0.346086,-0.730613
0.436312,-1.189182 0.09023,-0.458568 0.120921,-0.980524 0.125016,-1.4233537 0.0041,-0.4428297
-0.0185,-0.806597 -0.05852,-1.1349214 -0.04003,-0.3283244 -0.09759,-0.6212587 -0.21279,-0.914902 C
13.55725,7.1764236 13.384075,6.8820681 13.210376,6.586821"
+ id="path53746" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#e6e6e6;stroke-width:0.75px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 9.7374115,7.5753467 c 0.077527,-0.2420881 0.1552029,-0.4846389 0.2831265,-0.6976481
0.127924,-0.2130092 0.316247,-0.406603 0.524908,-0.5641978 0.208661,-0.1575949 0.442518,-0.2843205
0.610091,-0.3612449 0.167572,-0.076924 0.277147,-0.1063432 0.381942,-0.134479"
+ id="path53750" /></g></g></g></svg>
diff --git a/data/icons/hicolor_actions_scalable_markdown-link.svg
b/data/icons/hicolor_actions_scalable_markdown-link.svg
new file mode 100644
index 0000000000..e7bfbbbb9f
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_markdown-link.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ version="1.1"
+ id="svg51326"
+ xml:space="preserve"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
+ id="defs51330" /><g
+ id="g51332"
+ transform="matrix(1.2391158,0.4923106,-0.4923106,1.2391158,5.1915138,-3.3935698)"><g
+ id="g54244"
+ transform="rotate(38.936484,7.400522,4.6312859)"><path
+
style="fill:none;fill-rule:evenodd;stroke:#1a1a1a;stroke-width:0.75px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 8.226042,6.6881392 c -0.250375,-1 -0.250375,-2.5 -3.7e-4,-3.5003801 0.2500051,-1.00038
0.749995,-1.50037 1.2503751,-1.75037 0.50038,-0.25 1.0003699,-0.25 1.5003749,3.8e-4 0.500005,0.25038
0.999995,0.75037 1.24962,1.7503851 0.249625,1.000015 0.249625,2.499985 -3.8e-4,3.4996149 -0.250005,0.99963
-0.749995,1.4996199 -1.237528,1.7496199 -0.487533,0.25 -1.0117169,0.25 -1.5117219,3.7e-4 C 8.976407,8.1881291
8.476417,7.6881391 8.226042,6.6881392 Z"
+ id="path53269" /><g
+ id="g53872"><path
+
style="fill:none;fill-rule:evenodd;stroke:#1a1a1a;stroke-width:0.75px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 9.5279035,9.4814178 c 0.031913,0.432314 0.063768,0.8638272 0.1454647,1.2909192
0.081697,0.427092 0.2183089,0.866695 0.4123258,1.219544 0.194017,0.35285 0.455937,0.636559 0.735758,0.83268
0.279821,0.19612 0.581495,0.309578 0.900979,0.327199 0.319483,0.01762 0.645557,-0.05746 0.932875,-0.233203
0.287317,-0.175739 0.530677,-0.450964 0.727124,-0.786131 0.196448,-0.335166 0.346086,-0.730613
0.436312,-1.189182 0.09023,-0.458568 0.120921,-0.980524 0.125016,-1.4233537 0.0041,-0.4428297
-0.0185,-0.806597 -0.05852,-1.1349214 -0.04003,-0.3283244 -0.09759,-0.6212587 -0.21279,-0.914902 C
13.55725,7.1764236 13.384075,6.8820681 13.210376,6.586821"
+ id="path53746" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#1a1a1a;stroke-width:0.75px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 9.7374115,7.5753467 c 0.077527,-0.2420881 0.1552029,-0.4846389 0.2831265,-0.6976481
0.127924,-0.2130092 0.316247,-0.406603 0.524908,-0.5641978 0.208661,-0.1575949 0.442518,-0.2843205
0.610091,-0.3612449 0.167572,-0.076924 0.277147,-0.1063432 0.381942,-0.134479"
+ id="path53750" /></g></g></g></svg>
diff --git a/data/icons/hicolor_actions_scalable_markdown-numbers-dark.svg
b/data/icons/hicolor_actions_scalable_markdown-numbers-dark.svg
new file mode 100644
index 0000000000..f79f5f551d
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_markdown-numbers-dark.svg
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ version="1.1"
+ id="svg824"
+ xml:space="preserve"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
+ id="defs828" /><g
+ id="g834"
+ transform="matrix(1.3333333,0,0,1.3333333,-0.56799981,-0.08799955)"
+ style="stroke:#e6e6e6;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none"><path
+ d="m 5.676,4.566 h 10.5"
+
style="fill:none;stroke:#e6e6e6;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path836" /></g><g
+ id="g838"
+ transform="matrix(1.3333333,0,0,1.3333333,-0.56799981,-0.08799955)"
+ style="stroke:#e6e6e6;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none"><path
+ d="m 5.676,9.066 h 10.5"
+
style="fill:none;stroke:#e6e6e6;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path840" /></g><g
+ id="g842"
+ transform="matrix(1.3333333,0,0,1.3333333,-0.56799981,-0.08799955)"
+ style="stroke:#e6e6e6;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none"><path
+ d="m 5.676,13.566 h 10.5"
+
style="fill:none;stroke:#e6e6e6;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path844" /></g><path
+ d="M 4.4932328,7.9143159 H 5.1385661 V 4.4356494 H 4.7438995 l -1.3133333,0.6866666 0.2506666,0.4386667
0.812,-0.3546667 z"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.33333"
+ id="path846" /><path
+ d="m 3.5726414,13.833474 h 2.3333333 v -0.562666 h -1.396 c 0.896,-0.792 1.2706666,-1.354666
1.2706666,-1.937333 0,-0.625333 -0.4586666,-1.021333 -1.1666666,-1.021333 -0.4373333,0 -0.8333333,0.146666
-1.1453333,0.396 l 0.1866666,0.48 c 0.272,-0.209334 0.5626667,-0.313334 0.8333334,-0.313334 0.3959999,0
0.6253333,0.229334 0.6253333,0.562667 0,0.478667 -0.4786667,1 -1.5413333,1.958666 z"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.33333"
+ id="path848" /><path
+ d="m 4.7419027,20.015858 c 0.8533333,0 1.4159999,-0.396 1.4159999,-1 0,-0.437333 -0.2919999,-0.770666
-0.7706666,-0.854666 0.3546667,-0.104 0.5826667,-0.396 0.5826667,-0.790667 0,-0.562667 -0.4573334,-0.917333
-1.1453334,-0.917333 -0.3959999,0 -0.8119999,0.104 -1.1453333,0.292 l 0.1453334,0.478666 c 0.312,-0.125333
0.604,-0.208 0.8546666,-0.208 0.396,0 0.6453333,0.166667 0.6453333,0.437334 0,0.312 -0.312,0.521333
-0.7506666,0.521333 H 4.3245694 v 0.5 h 0.292 c 0.5413333,0 0.8746666,0.208 0.8746666,0.541333 0,0.292
-0.2706667,0.458667 -0.7293333,0.458667 -0.292,0 -0.6666667,-0.084 -0.9786667,-0.209333 l -0.1466666,0.5 c
0.3546666,0.166666 0.7293333,0.250666 1.1053333,0.250666 z"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.33333"
+ id="path850" /></svg>
diff --git a/data/icons/hicolor_actions_scalable_markdown-numbers.svg
b/data/icons/hicolor_actions_scalable_markdown-numbers.svg
new file mode 100644
index 0000000000..7ca25fb951
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_markdown-numbers.svg
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ version="1.1"
+ id="svg824"
+ xml:space="preserve"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
+ id="defs828" /><g
+ id="g834"
+ transform="matrix(1.3333333,0,0,1.3333333,-0.56799981,-0.08799955)"
+ style="stroke:#1a1a1a;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none"><path
+ d="m 5.676,4.566 h 10.5"
+
style="fill:none;stroke:#1a1a1a;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path836" /></g><g
+ id="g838"
+ transform="matrix(1.3333333,0,0,1.3333333,-0.56799981,-0.08799955)"
+ style="stroke:#1a1a1a;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none"><path
+ d="m 5.676,9.066 h 10.5"
+
style="fill:none;stroke:#1a1a1a;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path840" /></g><g
+ id="g842"
+ transform="matrix(1.3333333,0,0,1.3333333,-0.56799981,-0.08799955)"
+ style="stroke:#1a1a1a;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none"><path
+ d="m 5.676,13.566 h 10.5"
+
style="fill:none;stroke:#1a1a1a;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path844" /></g><path
+ d="M 4.4932328,7.9143159 H 5.1385661 V 4.4356494 H 4.7438995 l -1.3133333,0.6866666 0.2506666,0.4386667
0.812,-0.3546667 z"
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.33333"
+ id="path846" /><path
+ d="m 3.5726414,13.833474 h 2.3333333 v -0.562666 h -1.396 c 0.896,-0.792 1.2706666,-1.354666
1.2706666,-1.937333 0,-0.625333 -0.4586666,-1.021333 -1.1666666,-1.021333 -0.4373333,0 -0.8333333,0.146666
-1.1453333,0.396 l 0.1866666,0.48 c 0.272,-0.209334 0.5626667,-0.313334 0.8333334,-0.313334 0.3959999,0
0.6253333,0.229334 0.6253333,0.562667 0,0.478667 -0.4786667,1 -1.5413333,1.958666 z"
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.33333"
+ id="path848" /><path
+ d="m 4.7419027,20.015858 c 0.8533333,0 1.4159999,-0.396 1.4159999,-1 0,-0.437333 -0.2919999,-0.770666
-0.7706666,-0.854666 0.3546667,-0.104 0.5826667,-0.396 0.5826667,-0.790667 0,-0.562667 -0.4573334,-0.917333
-1.1453334,-0.917333 -0.3959999,0 -0.8119999,0.104 -1.1453333,0.292 l 0.1453334,0.478666 c 0.312,-0.125333
0.604,-0.208 0.8546666,-0.208 0.396,0 0.6453333,0.166667 0.6453333,0.437334 0,0.312 -0.312,0.521333
-0.7506666,0.521333 H 4.3245694 v 0.5 h 0.292 c 0.5413333,0 0.8746666,0.208 0.8746666,0.541333 0,0.292
-0.2706667,0.458667 -0.7293333,0.458667 -0.292,0 -0.6666667,-0.084 -0.9786667,-0.209333 l -0.1466666,0.5 c
0.3546666,0.166666 0.7293333,0.250666 1.1053333,0.250666 z"
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.33333"
+ id="path850" /></svg>
diff --git a/data/icons/hicolor_actions_scalable_markdown-quote-dark.svg
b/data/icons/hicolor_actions_scalable_markdown-quote-dark.svg
new file mode 100644
index 0000000000..2b57fc1e60
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_markdown-quote-dark.svg
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ version="1.1"
+ id="svg33406"
+ xml:space="preserve"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
+ id="defs33410" /><path
+
style="fill:#1a1a1a;fill-rule:evenodd;stroke:#e6e6e6;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 4,3.0000001 V 20.999999"
+ id="path33601" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#e6e6e6;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 7.0000095,6.0000002 15,6"
+ id="path33702-3" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#e6e6e6;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 7.0000095,12 H 20.999999"
+ id="path33704-6" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#e6e6e6;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 7.0000095,18 H 15"
+ id="path33706-7" /></svg>
diff --git a/data/icons/hicolor_actions_scalable_markdown-quote.svg
b/data/icons/hicolor_actions_scalable_markdown-quote.svg
new file mode 100644
index 0000000000..3b301881d3
--- /dev/null
+++ b/data/icons/hicolor_actions_scalable_markdown-quote.svg
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ version="1.1"
+ id="svg33406"
+ xml:space="preserve"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><defs
+ id="defs33410" /><path
+
style="fill:#1a1a1a;fill-rule:evenodd;stroke:#1a1a1a;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 4,3.0000001 V 20.999999"
+ id="path33601" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#1a1a1a;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 7.0000095,6.0000002 15,6"
+ id="path33702-3" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#1a1a1a;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 7.0000095,12 H 20.999999"
+ id="path33704-6" /><path
+
style="fill:none;fill-rule:evenodd;stroke:#1a1a1a;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 7.0000095,18 H 15"
+ id="path33706-7" /></svg>
diff --git a/docs/reference/evolution-mail-composer/evolution-mail-composer-docs.sgml.in
b/docs/reference/evolution-mail-composer/evolution-mail-composer-docs.sgml.in
index ea4fca7cd8..82059231af 100644
--- a/docs/reference/evolution-mail-composer/evolution-mail-composer-docs.sgml.in
+++ b/docs/reference/evolution-mail-composer/evolution-mail-composer-docs.sgml.in
@@ -29,6 +29,10 @@
<title>API Index</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
</index>
+ <index id="api-index-3-44" role="3.44">
+ <title>Index of new symbols in 3.44</title>
+ <xi:include href="xml/api-index-3.44.xml"><xi:fallback /></xi:include>
+ </index>
<index id="api-index-3-42" role="3.42">
<title>Index of new symbols in 3.42</title>
<xi:include href="xml/api-index-3.42.xml"><xi:fallback /></xi:include>
diff --git a/docs/reference/evolution-util/evolution-util-docs.sgml.in
b/docs/reference/evolution-util/evolution-util-docs.sgml.in
index 779f3ae6c4..7f7b3bb5ab 100644
--- a/docs/reference/evolution-util/evolution-util-docs.sgml.in
+++ b/docs/reference/evolution-util/evolution-util-docs.sgml.in
@@ -280,6 +280,7 @@
<xi:include href="xml/e-interval-chooser.xml"/>
<xi:include href="xml/e-mail-identity-combo-box.xml"/>
<xi:include href="xml/e-map.xml"/>
+ <xi:include href="xml/e-markdown-editor.xml"/>
<xi:include href="xml/e-menu-tool-action.xml"/>
<xi:include href="xml/e-menu-tool-button.xml"/>
<xi:include href="xml/e-mktemp.xml"/>
@@ -326,6 +327,10 @@
<title>Index</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
</index>
+ <index id="api-index-3-44" role="3.44">
+ <title>Index of new symbols in 3.44</title>
+ <xi:include href="xml/api-index-3.44.xml"><xi:fallback /></xi:include>
+ </index>
<index id="api-index-3-42" role="3.42">
<title>Index of new symbols in 3.42</title>
<xi:include href="xml/api-index-3.42.xml"><xi:fallback /></xi:include>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6faa645e63..b003bb2dad 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -237,6 +237,7 @@ src/e-util/e-mail-signature-editor.c
src/e-util/e-mail-signature-manager.c
src/e-util/e-mail-signature-script-dialog.c
src/e-util/e-map.c
+src/e-util/e-markdown-editor.c
src/e-util/e-misc-utils.c
src/e-util/e-name-selector-dialog.c
src/e-util/e-name-selector-entry.c
diff --git a/src/e-util/CMakeLists.txt b/src/e-util/CMakeLists.txt
index 7048adf146..e81570ad3c 100644
--- a/src/e-util/CMakeLists.txt
+++ b/src/e-util/CMakeLists.txt
@@ -168,6 +168,7 @@ set(SOURCES
e-mail-signature-script-dialog.c
e-mail-signature-tree-view.c
e-map.c
+ e-markdown-editor.c
e-marshal.c
e-menu-tool-action.c
e-menu-tool-button.c
@@ -443,6 +444,7 @@ set(HEADERS
e-mail-signature-script-dialog.h
e-mail-signature-tree-view.h
e-map.h
+ e-markdown-editor.h
e-menu-tool-action.h
e-menu-tool-button.h
e-misc-utils.h
@@ -651,6 +653,7 @@ target_include_directories(evolution-util PUBLIC
${GEO_INCLUDE_DIRS}
${GNOME_PLATFORM_INCLUDE_DIRS}
${GSPELL_INCLUDE_DIRS}
+ ${MARKDOWN_INCLUDE_DIRS}
)
target_link_libraries(evolution-util
@@ -663,6 +666,7 @@ target_link_libraries(evolution-util
${GSPELL_LDFLAGS}
${ICONV_LIBS}
${MATH_LDFLAGS}
+ ${MARKDOWN_LDFLAGS}
)
if(HAVE_LDAP)
@@ -816,6 +820,7 @@ add_private_programs_simple(
test-dateedit
test-html-editor
test-mail-signatures
+ test-markdown-editor
test-name-selector
test-preferences-window
test-proxy-preferences
diff --git a/src/e-util/e-markdown-editor.c b/src/e-util/e-markdown-editor.c
new file mode 100644
index 0000000000..3325ea6395
--- /dev/null
+++ b/src/e-util/e-markdown-editor.c
@@ -0,0 +1,585 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * SPDX-FileCopyrightText: (C) 2022 Red Hat (www.redhat.com)
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "evolution-config.h"
+
+#ifdef HAVE_MARKDOWN
+#include <cmark.h>
+#endif
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+
+#include <libedataserverui/libedataserverui.h>
+
+#include "e-misc-utils.h"
+#include "e-spell-text-view.h"
+#include "e-web-view.h"
+
+#include "e-markdown-editor.h"
+
+struct _EMarkdownEditorPrivate {
+ GtkTextView *text_view;
+ EWebView *web_view;
+ GtkToolbar *action_toolbar;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (EMarkdownEditor, e_markdown_editor, GTK_TYPE_BOX)
+
+static void
+e_markdown_editor_get_selection (EMarkdownEditor *self,
+ GtkTextIter *out_start,
+ GtkTextIter *out_end,
+ gchar **out_selected_text)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+
+ buffer = gtk_text_view_get_buffer (self->priv->text_view);
+
+ if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end) && out_selected_text) {
+ *out_selected_text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+ } else if (out_selected_text) {
+ *out_selected_text = NULL;
+ }
+
+ if (out_start)
+ *out_start = start;
+
+ if (out_end)
+ *out_end = end;
+}
+
+static void
+e_markdown_editor_surround_selection (EMarkdownEditor *self,
+ gboolean whole_lines,
+ const gchar *prefix,
+ const gchar *suffix)
+{
+ GtkTextIter start, end;
+ GtkTextBuffer *buffer;
+
+ e_markdown_editor_get_selection (self, &start, &end, NULL);
+
+ buffer = gtk_text_view_get_buffer (self->priv->text_view);
+
+ gtk_text_buffer_begin_user_action (buffer);
+
+ if (whole_lines) {
+ gint to_line, ii;
+
+ to_line = gtk_text_iter_get_line (&end);
+
+ for (ii = gtk_text_iter_get_line (&start); ii <= to_line; ii++) {
+ GtkTextIter iter;
+
+ gtk_text_buffer_get_iter_at_line (buffer, &iter, ii);
+
+ if (prefix && *prefix)
+ gtk_text_buffer_insert (buffer, &iter, prefix, -1);
+
+ if (suffix && *suffix) {
+ gtk_text_iter_forward_to_line_end (&iter);
+ gtk_text_buffer_insert (buffer, &iter, suffix, -1);
+ }
+ }
+ } else {
+ gint end_offset = gtk_text_iter_get_offset (&end);
+
+ if (prefix && *prefix) {
+ gtk_text_buffer_insert (buffer, &start, prefix, -1);
+ /* Keep the cursor where it is, move it only when the suffix is used */
+ end_offset += strlen (prefix);
+ gtk_text_buffer_get_iter_at_offset (buffer, &end, end_offset);
+ }
+
+ if (suffix && *suffix) {
+ gtk_text_buffer_insert (buffer, &end, suffix, -1);
+ /* Place the cursor before the suffix */
+ gtk_text_buffer_get_iter_at_offset (buffer, &end, end_offset);
+ gtk_text_buffer_select_range (buffer, &end, &end);
+ }
+ }
+
+ gtk_text_buffer_end_user_action (buffer);
+}
+
+static void
+e_markdown_editor_add_bold_text_cb (GtkToolButton *button,
+ gpointer user_data)
+{
+ EMarkdownEditor *self = user_data;
+
+ g_return_if_fail (E_IS_MARKDOWN_EDITOR (self));
+
+ e_markdown_editor_surround_selection (self, FALSE, "**", "**");
+}
+
+static void
+e_markdown_editor_add_italic_text_cb (GtkToolButton *button,
+ gpointer user_data)
+{
+ EMarkdownEditor *self = user_data;
+
+ g_return_if_fail (E_IS_MARKDOWN_EDITOR (self));
+
+ e_markdown_editor_surround_selection (self, FALSE, "*", "*");
+}
+
+static void
+e_markdown_editor_insert_quote_cb (GtkToolButton *button,
+ gpointer user_data)
+{
+ EMarkdownEditor *self = user_data;
+
+ g_return_if_fail (E_IS_MARKDOWN_EDITOR (self));
+
+ e_markdown_editor_surround_selection (self, TRUE, "> ", NULL);
+}
+
+static void
+e_markdown_editor_insert_code_cb (GtkToolButton *button,
+ gpointer user_data)
+{
+ EMarkdownEditor *self = user_data;
+ GtkTextIter start, end;
+ gchar *selection = NULL;
+
+ g_return_if_fail (E_IS_MARKDOWN_EDITOR (self));
+
+ e_markdown_editor_get_selection (self, &start, &end, &selection);
+
+ if (selection && strchr (selection, '\n')) {
+ GtkTextBuffer *buffer;
+ GtkTextIter iter;
+ gint start_line, end_line;
+
+ buffer = gtk_text_view_get_buffer (self->priv->text_view);
+
+ gtk_text_buffer_begin_user_action (buffer);
+
+ start_line = gtk_text_iter_get_line (&start);
+ end_line = gtk_text_iter_get_line (&end);
+
+ gtk_text_buffer_get_iter_at_line (buffer, &iter, start_line);
+ gtk_text_buffer_insert (buffer, &iter, "```\n", -1);
+
+ /* One line added above + 1 for the end line itself */
+ end_line = end_line + 2;
+ gtk_text_buffer_get_iter_at_line (buffer, &iter, end_line);
+ if (gtk_text_iter_is_end (&iter) && gtk_text_iter_get_line_offset (&iter) > 0) {
+ gtk_text_buffer_insert (buffer, &iter, "\n```\n", -1);
+ } else {
+ if (gtk_text_iter_is_end (&iter))
+ end_line--;
+ gtk_text_buffer_insert (buffer, &iter, "```\n", -1);
+ }
+
+ /* Place the cursor before the suffix */
+ gtk_text_buffer_get_iter_at_line (buffer, &iter, end_line);
+ gtk_text_buffer_select_range (buffer, &iter, &iter);
+
+ gtk_text_buffer_end_user_action (buffer);
+ } else {
+ e_markdown_editor_surround_selection (self, FALSE, "`", "`");
+ }
+
+ g_free (selection);
+}
+
+static void
+e_markdown_editor_add_link_cb (GtkToolButton *button,
+ gpointer user_data)
+{
+ EMarkdownEditor *self = user_data;
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+ gchar *selection = NULL;
+ gint offset;
+
+ g_return_if_fail (E_IS_MARKDOWN_EDITOR (self));
+
+ e_markdown_editor_get_selection (self, &start, &end, &selection);
+
+ buffer = gtk_text_view_get_buffer (self->priv->text_view);
+ offset = gtk_text_iter_get_offset (&start);
+
+ gtk_text_buffer_begin_user_action (buffer);
+
+ if (selection && *selection) {
+ gint end_offset = gtk_text_iter_get_offset (&end);
+
+ if (g_ascii_strncasecmp (selection, "http:", 5) == 0 ||
+ g_ascii_strncasecmp (selection, "https:", 6) == 0) {
+ gtk_text_buffer_insert (buffer, &start, "[](", -1);
+ gtk_text_buffer_get_iter_at_offset (buffer, &end, end_offset + 3);
+ gtk_text_buffer_insert (buffer, &end, ")", -1);
+ gtk_text_buffer_get_iter_at_offset (buffer, &start, offset + 1);
+ end = start;
+ } else {
+ gtk_text_buffer_insert (buffer, &start, "[", -1);
+ gtk_text_buffer_get_iter_at_offset (buffer, &end, end_offset + 1);
+ gtk_text_buffer_insert (buffer, &end, "](https://)", -1);
+ gtk_text_buffer_get_iter_at_offset (buffer, &start, end_offset + 1 + 2);
+ gtk_text_buffer_get_iter_at_offset (buffer, &end, end_offset + 1 + 10);
+ }
+
+ gtk_text_buffer_select_range (buffer, &start, &end);
+ } else {
+ gtk_text_buffer_insert (buffer, &start, "[](https://)", -1);
+
+ /* skip "[](" */
+ offset += 3;
+
+ gtk_text_buffer_get_iter_at_offset (buffer, &start, offset);
+
+ /* after the "https://" text */
+ gtk_text_buffer_get_iter_at_offset (buffer, &end, offset + 8);
+
+ gtk_text_buffer_select_range (buffer, &start, &end);
+ }
+
+ gtk_text_buffer_end_user_action (buffer);
+}
+
+static void
+e_markdown_editor_add_bullet_list_cb (GtkToolButton *button,
+ gpointer user_data)
+{
+ EMarkdownEditor *self = user_data;
+
+ g_return_if_fail (E_IS_MARKDOWN_EDITOR (self));
+
+ e_markdown_editor_surround_selection (self, TRUE, "- ", NULL);
+}
+
+static void
+e_markdown_editor_add_numbered_list_cb (GtkToolButton *button,
+ gpointer user_data)
+{
+ EMarkdownEditor *self = user_data;
+
+ g_return_if_fail (E_IS_MARKDOWN_EDITOR (self));
+
+ e_markdown_editor_surround_selection (self, TRUE, "1. ", NULL);
+}
+
+static void
+e_markdown_editor_add_header_cb (GtkToolButton *button,
+ gpointer user_data)
+{
+ EMarkdownEditor *self = user_data;
+
+ g_return_if_fail (E_IS_MARKDOWN_EDITOR (self));
+
+ e_markdown_editor_surround_selection (self, TRUE, "# ", NULL);
+}
+
+static void
+e_markdown_editor_markdown_syntax_cb (GtkToolButton *button,
+ gpointer user_data)
+{
+ EMarkdownEditor *self = user_data;
+ GtkWidget *toplevel;
+
+ g_return_if_fail (E_IS_MARKDOWN_EDITOR (self));
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
+
+ e_show_uri (GTK_IS_WINDOW (toplevel) ? GTK_WINDOW (toplevel) : NULL, "https://commonmark.org/help/");
+}
+
+#ifdef HAVE_MARKDOWN
+static void
+e_markdown_editor_switch_page_cb (GtkNotebook *notebook,
+ GtkWidget *page,
+ guint page_num,
+ gpointer user_data)
+{
+ EMarkdownEditor *self = user_data;
+ gchar *converted;
+ gchar *html;
+
+ g_return_if_fail (E_IS_MARKDOWN_EDITOR (self));
+
+ gtk_widget_set_visible (GTK_WIDGET (self->priv->action_toolbar), page_num != 1);
+
+ /* Not the Preview page */
+ if (page_num != 1)
+ return;
+
+ converted = e_markdown_editor_dup_html (self);
+
+ html = g_strconcat ("<div class=\"-e-web-view-background-color -e-web-view-text-color\"
style=\"border: none; padding: 0px; margin: 0;\">",
+ converted ? converted : "",
+ "</div>",
+ NULL);
+
+ e_web_view_load_string (self->priv->web_view, html);
+
+ g_free (converted);
+ g_free (html);
+}
+#endif /* HAVE_MARKDOWN */
+
+static gboolean
+e_markdown_editor_is_dark_theme (EMarkdownEditor *self)
+{
+ GdkRGBA rgba;
+ gdouble brightness;
+
+ e_utils_get_theme_color (GTK_WIDGET (self), "theme_text_color,theme_fg_color",
E_UTILS_DEFAULT_THEME_TEXT_COLOR, &rgba);
+
+ brightness =
+ (0.2109 * 255.0 * rgba.red) +
+ (0.5870 * 255.0 * rgba.green) +
+ (0.1021 * 255.0 * rgba.blue);
+
+ return brightness > 140;
+}
+
+static void
+e_markdown_editor_constructed (GObject *object)
+{
+ struct _items {
+ const gchar *label;
+ const gchar *icon_name;
+ const gchar *icon_name_dark;
+ GCallback callback;
+ } items[] = {
+ #define ITEM(lbl, icn, cbk) { lbl, icn, icn "-dark", G_CALLBACK (cbk) }
+ ITEM (N_("Add bold text"), "markdown-bold", e_markdown_editor_add_bold_text_cb),
+ ITEM (N_("Add italic text"), "markdown-italic", e_markdown_editor_add_italic_text_cb),
+ ITEM (N_("Insert a quote"), "markdown-quote", e_markdown_editor_insert_quote_cb),
+ ITEM (N_("Insert code"), "markdown-code", e_markdown_editor_insert_code_cb),
+ ITEM (N_("Add a link"), "markdown-link", e_markdown_editor_add_link_cb),
+ ITEM (N_("Add a bullet list"), "markdown-bullets", e_markdown_editor_add_bullet_list_cb),
+ ITEM (N_("Add a numbered list"), "markdown-numbers", e_markdown_editor_add_numbered_list_cb),
+ ITEM (N_("Add a header"), "markdown-header", e_markdown_editor_add_header_cb),
+ ITEM (NULL, "", NULL),
+ ITEM (N_("Open online common mark documentation"), "markdown-help", G_CALLBACK
(e_markdown_editor_markdown_syntax_cb))
+ #undef ITEM
+ };
+ EMarkdownEditor *self = E_MARKDOWN_EDITOR (object);
+ GtkWidget *widget;
+ GtkNotebook *notebook;
+ GtkScrolledWindow *scrolled_window;
+ gboolean is_dark_theme;
+ guint ii;
+
+ /* Chain up to parent's method. */
+ G_OBJECT_CLASS (e_markdown_editor_parent_class)->constructed (object);
+
+ widget = gtk_notebook_new ();
+ g_object_set (G_OBJECT (widget),
+ "halign", GTK_ALIGN_FILL,
+ "hexpand", TRUE,
+ "valign", GTK_ALIGN_FILL,
+ "vexpand", TRUE,
+ "visible", TRUE,
+ "show-border", FALSE,
+ "show-tabs", TRUE,
+ NULL);
+ gtk_box_pack_start (GTK_BOX (self), widget, TRUE, TRUE, 0);
+
+ notebook = GTK_NOTEBOOK (widget);
+
+ widget = gtk_scrolled_window_new (NULL, NULL);
+ g_object_set (G_OBJECT (widget),
+ "halign", GTK_ALIGN_FILL,
+ "hexpand", TRUE,
+ "valign", GTK_ALIGN_FILL,
+ "vexpand", TRUE,
+ "visible", TRUE,
+ "hscrollbar-policy", GTK_POLICY_AUTOMATIC,
+ "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
+ NULL);
+
+ gtk_notebook_append_page (notebook, widget, gtk_label_new_with_mnemonic (_("_Write")));
+
+ scrolled_window = GTK_SCROLLED_WINDOW (widget);
+
+ widget = gtk_text_view_new ();
+ g_object_set (G_OBJECT (widget),
+ "halign", GTK_ALIGN_FILL,
+ "hexpand", TRUE,
+ "valign", GTK_ALIGN_FILL,
+ "vexpand", TRUE,
+ "visible", TRUE,
+ "margin", 4,
+ "monospace", TRUE,
+ "wrap-mode", GTK_WRAP_WORD_CHAR,
+ NULL);
+
+ gtk_container_add (GTK_CONTAINER (scrolled_window), widget);
+
+ self->priv->text_view = GTK_TEXT_VIEW (widget);
+
+ e_buffer_tagger_connect (self->priv->text_view);
+ e_spell_text_view_attach (self->priv->text_view);
+
+ #ifdef HAVE_MARKDOWN
+ widget = gtk_scrolled_window_new (NULL, NULL);
+ g_object_set (G_OBJECT (widget),
+ "halign", GTK_ALIGN_FILL,
+ "hexpand", TRUE,
+ "valign", GTK_ALIGN_FILL,
+ "vexpand", TRUE,
+ "visible", TRUE,
+ "hscrollbar-policy", GTK_POLICY_AUTOMATIC,
+ "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
+ NULL);
+
+ gtk_notebook_append_page (notebook, widget, gtk_label_new_with_mnemonic (_("_Preview")));
+
+ scrolled_window = GTK_SCROLLED_WINDOW (widget);
+
+ widget = e_web_view_new ();
+ g_object_set (G_OBJECT (widget),
+ "halign", GTK_ALIGN_FILL,
+ "hexpand", TRUE,
+ "valign", GTK_ALIGN_FILL,
+ "vexpand", TRUE,
+ "visible", TRUE,
+ "margin", 4,
+ NULL);
+
+ gtk_container_add (GTK_CONTAINER (scrolled_window), widget);
+
+ self->priv->web_view = E_WEB_VIEW (widget);
+ #endif /* HAVE_MARKDOWN */
+
+ widget = gtk_toolbar_new ();
+ gtk_widget_show (widget);
+ gtk_notebook_set_action_widget (notebook, widget, GTK_PACK_END);
+
+ self->priv->action_toolbar = GTK_TOOLBAR (widget);
+
+ is_dark_theme = e_markdown_editor_is_dark_theme (self);
+
+ for (ii = 0; ii < G_N_ELEMENTS (items); ii++) {
+ GtkToolItem *item;
+
+ if (items[ii].callback) {
+ GtkWidget *icon;
+ const gchar *icon_name;
+
+ icon_name = is_dark_theme ? items[ii].icon_name_dark : items[ii].icon_name;
+ icon = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_LARGE_TOOLBAR);
+ gtk_widget_show (GTK_WIDGET (icon));
+ item = gtk_tool_button_new (icon, _(items[ii].label));
+ gtk_tool_item_set_tooltip_text (item, _(items[ii].label));
+ g_signal_connect_object (item, "clicked", items[ii].callback, self, 0);
+ } else {
+ item = gtk_separator_tool_item_new ();
+ }
+
+ gtk_widget_show (GTK_WIDGET (item));
+ gtk_toolbar_insert (self->priv->action_toolbar, item, -1);
+ }
+
+ #ifdef HAVE_MARKDOWN
+ g_signal_connect_object (notebook, "switch-page", G_CALLBACK (e_markdown_editor_switch_page_cb),
self, 0);
+ #endif
+}
+
+static void
+e_markdown_editor_class_init (EMarkdownEditorClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->constructed = e_markdown_editor_constructed;
+}
+
+static void
+e_markdown_editor_init (EMarkdownEditor *self)
+{
+ self->priv = e_markdown_editor_get_instance_private (self);
+}
+
+/**
+ * e_markdown_editor_new:
+ *
+ * Creates a new #EMarkdownEditor
+ *
+ * Returns: (transfer full): a new #EMarkdownEditor
+ *
+ * Since: 3.44
+ */
+GtkWidget *
+e_markdown_editor_new (void)
+{
+ return g_object_new (E_TYPE_MARKDOWN_EDITOR, NULL);
+}
+
+/**
+ * e_markdown_editor_dup_text:
+ * @self: an #EMarkdownEditor
+ *
+ * Get the markdown text entered in the @self. To get
+ * the HTML version of it use e_markdown_editor_dup_html().
+ * Free the returned string with g_free(), when no longer needed.
+ *
+ * Returns: (transfer full): the markdown text
+ *
+ * Since: 3.44
+ **/
+gchar *
+e_markdown_editor_dup_text (EMarkdownEditor *self)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+
+ g_return_val_if_fail (E_IS_MARKDOWN_EDITOR (self), NULL);
+
+ buffer = gtk_text_view_get_buffer (self->priv->text_view);
+ gtk_text_buffer_get_bounds (buffer, &start, &end);
+
+ return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+}
+
+/**
+ * e_markdown_editor_dup_html:
+ * @self: an #EMarkdownEditor
+ *
+ * Get the HTML version of the markdown text entered in the @self.
+ * To get the markdown text use e_markdown_editor_dup_text().
+ * Free the returned string with g_free(), when no longer needed.
+ *
+ * Note: The function can return %NULL when was not built
+ * with the markdown support.
+ *
+ * Returns: (transfer full) (nullable): the markdown text converted
+ * into HTML, or %NULL, when was not built with the markdown support
+ *
+ * Since: 3.44
+ **/
+gchar *
+e_markdown_editor_dup_html (EMarkdownEditor *self)
+{
+ #ifdef HAVE_MARKDOWN
+ GString *html;
+ gchar *text, *converted;
+ #endif
+
+ g_return_val_if_fail (E_IS_MARKDOWN_EDITOR (self), NULL);
+
+ #ifdef HAVE_MARKDOWN
+ text = e_markdown_editor_dup_text (self);
+ converted = cmark_markdown_to_html (text ? text : "", text ? strlen (text) : 0,
+ CMARK_OPT_VALIDATE_UTF8 | CMARK_OPT_UNSAFE);
+
+ html = e_str_replace_string (converted, "<blockquote>", "<blockquote type=\"cite\">");
+
+ g_free (converted);
+ g_free (text);
+
+ return g_string_free (html, FALSE);
+ #else
+ return NULL;
+ #endif
+}
diff --git a/src/e-util/e-markdown-editor.h b/src/e-util/e-markdown-editor.h
new file mode 100644
index 0000000000..bdc429c8b9
--- /dev/null
+++ b/src/e-util/e-markdown-editor.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * SPDX-FileCopyrightText: (C) 2022 Red Hat (www.redhat.com)
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#if !defined (__E_UTIL_H_INSIDE__) && !defined (LIBEUTIL_COMPILATION)
+#error "Only <e-util/e-util.h> should be included directly."
+#endif
+
+#ifndef E_MARKDOWN_EDITOR_H
+#define E_MARKDOWN_EDITOR_H
+
+#include <gtk/gtk.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MARKDOWN_EDITOR \
+ (e_markdown_editor_get_type ())
+#define E_MARKDOWN_EDITOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MARKDOWN_EDITOR, EMarkdownEditor))
+#define E_MARKDOWN_EDITOR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MARKDOWN_EDITOR, EMarkdownEditorClass))
+#define E_IS_MARKDOWN_EDITOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MARKDOWN_EDITOR))
+#define E_IS_MARKDOWN_EDITOR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MARKDOWN_EDITOR))
+#define E_MARKDOWN_EDITOR_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MARKDOWN_EDITOR, EMarkdownEditorClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMarkdownEditor EMarkdownEditor;
+typedef struct _EMarkdownEditorClass EMarkdownEditorClass;
+typedef struct _EMarkdownEditorPrivate EMarkdownEditorPrivate;
+
+struct _EMarkdownEditor {
+ GtkBox parent;
+ EMarkdownEditorPrivate *priv;
+};
+
+struct _EMarkdownEditorClass {
+ GtkBoxClass parent_class;
+};
+
+GType e_markdown_editor_get_type (void) G_GNUC_CONST;
+GtkWidget * e_markdown_editor_new (void);
+gchar * e_markdown_editor_dup_text (EMarkdownEditor *self);
+gchar * e_markdown_editor_dup_html (EMarkdownEditor *self);
+
+G_END_DECLS
+
+#endif /* E_MARKDOWN_EDITOR_H */
diff --git a/src/e-util/e-util.h b/src/e-util/e-util.h
index c430fed8bd..666363e9e8 100644
--- a/src/e-util/e-util.h
+++ b/src/e-util/e-util.h
@@ -152,6 +152,7 @@
#include <e-util/e-mail-signature-script-dialog.h>
#include <e-util/e-mail-signature-tree-view.h>
#include <e-util/e-map.h>
+#include <e-util/e-markdown-editor.h>
#include <e-util/e-menu-tool-action.h>
#include <e-util/e-menu-tool-button.h>
#include <e-util/e-misc-utils.h>
diff --git a/src/e-util/test-markdown-editor.c b/src/e-util/test-markdown-editor.c
new file mode 100644
index 0000000000..88d439dd7e
--- /dev/null
+++ b/src/e-util/test-markdown-editor.c
@@ -0,0 +1,81 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * SPDX-FileCopyrightText: (C) 2022 Red Hat (www.redhat.com)
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "evolution-config.h"
+
+#include <glib/gi18n-lib.h>
+#include <e-util/e-util.h>
+
+static gboolean
+window_delete_event_cb (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ gtk_main_quit ();
+
+ return FALSE;
+}
+
+static gint
+on_idle_create_widget (gpointer user_data)
+{
+ GtkWidget *window, *editor;
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_default_size (GTK_WINDOW (window), 640, 480);
+
+ g_signal_connect (
+ window, "delete-event",
+ G_CALLBACK (window_delete_event_cb), NULL);
+
+ editor = e_markdown_editor_new ();
+
+ g_object_set (G_OBJECT (editor),
+ "halign", GTK_ALIGN_FILL,
+ "hexpand", TRUE,
+ "valign", GTK_ALIGN_FILL,
+ "vexpand", TRUE,
+ "visible", TRUE,
+ NULL);
+
+ gtk_container_add (GTK_CONTAINER (window), editor);
+
+ gtk_widget_show (window);
+
+ return FALSE;
+}
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+ GList *modules;
+
+ bindtextdomain (GETTEXT_PACKAGE, EVOLUTION_LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ gtk_init (&argc, &argv);
+
+ e_util_init_main_thread (NULL);
+ e_passwords_init ();
+
+ g_setenv ("EVOLUTION_SOURCE_WEBKITDATADIR", EVOLUTION_SOURCE_WEBKITDATADIR, FALSE);
+
+ gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), EVOLUTION_ICONDIR);
+ gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), E_DATA_SERVER_ICONDIR);
+
+ modules = e_module_load_all_in_directory (EVOLUTION_MODULEDIR);
+ g_list_free_full (modules, (GDestroyNotify) g_type_module_unuse);
+
+ g_idle_add ((GSourceFunc) on_idle_create_widget, NULL);
+
+ gtk_main ();
+
+ e_misc_util_free_global_memory ();
+
+ return 0;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]