3
0
Fork 0

Merge PR #2869 into 15.0

Signed-off-by pedrobaeza
15.0-ocabot-merge-pr-2789-by-pedrobaeza-bump-patch
OCA-git-bot 2024-07-09 08:54:07 +00:00
commit f38809a109
24 changed files with 9731 additions and 0 deletions

View File

@ -0,0 +1 @@
../../../../web_widget_text_markdown

View File

@ -0,0 +1,6 @@
import setuptools
setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)

View File

@ -0,0 +1,114 @@
========================
Web Widget Text Markdown
========================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:8e4fa31404e335de7a1e78b7aa8c1530de1e895d5c6d2afe70269e663589c8c3
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github
:target: https://github.com/OCA/web/tree/15.0/web_widget_text_markdown
:alt: OCA/web
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/web-15-0/web-15-0-web_widget_text_markdown
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/web&target_branch=15.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module adds a new widget for text field in form view on Odoo:
- In readonly mode, it uses text contents to parse and render them to html markdown syntax.
- In write mode, use [bootstrap-markdown][1]
[1]: `bootstrap-markdown <https://github.com/toopay/bootstrap-markdown>`_
**Table of contents**
.. contents::
:local:
Usage
=====
Your XML form view definition should contain::
...
<field name="field_name" widget="bootstrap_markdown"/>
...
Known issues / Roadmap
======================
* Can't create attachments on virtual records
* Improve user experience with Odoo specific syntax
* Improve user experience with Github specific syntax
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/web/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/web/issues/new?body=module:%20web_widget_text_markdown%0Aversion:%2015.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* Alexandre Díaz
* Komit
* Sudokeys
* Sunflower IT
Contributors
~~~~~~~~~~~~
* Nicolas Jeudy <nicolas@sudokeys.com>
* Nguyen Tan Phuc <phuc.nt@komit-consulting.com>
* Alexandre Díaz <dev@redneboa.es>
* Tom Blauwendraat <tom@sunflowerweb.nl>
* Kevin Kamau <kevin@sunflowerweb.nl>
* Helly kapatel <helly.kapatel@initos.com>
* [APSL-Nagarro](<https://apsl.tech>):
* Bernat Obrador <bobrador@apsl.net>
* Patryk Pyczko <ppyczko@apsl.net>
Other credits
~~~~~~~~~~~~~
* Komit https://komit-consulting.com
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
This module is part of the `OCA/web <https://github.com/OCA/web/tree/15.0/web_widget_text_markdown>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@ -0,0 +1 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

View File

@ -0,0 +1,31 @@
# Copyright (C) 2014 Sudokeys (<http://www.sudokeys.com>)
# Copyright (C) 2017 Komit (<http://www.komit-consulting.com>)
#
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
"name": "Web Widget Text Markdown",
"version": "15.0.1.0.0",
"author": "Alexandre Díaz, "
"Komit, "
"Sudokeys, "
"Sunflower IT, "
"Odoo Community Association (OCA)",
"category": "Web",
"license": "AGPL-3",
"website": "https://github.com/OCA/web",
"summary": "Widget to text fields that adds markdown support",
"depends": ["web"],
"demo": ["demo/bootstrap_markdown.xml"],
"data": [],
"installable": True,
"auto_install": False,
"application": False,
"assets": {
"web.assets_backend": [
"/web_widget_text_markdown/static/src/js/web_widget_text_markdown.js",
],
"web.qunit_suite": [
"/web_widget_text_markdown/static/tests/js/web_widget_text_markdown.js",
],
},
}

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_groups_form_inherited" model="ir.ui.view">
<field name="model">res.groups</field>
<field name="inherit_id" ref="base.view_groups_form" />
<field name="arch" type="xml">
<field name="comment" position="attributes">
<attribute name="widget">bootstrap_markdown</attribute>
</field>
</field>
</record>
</odoo>

View File

@ -0,0 +1,21 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_widget_text_markdown
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: web_widget_text_markdown
#. openerp-web
#: code:addons/web_widget_text_markdown/static/src/js/web_widget_text_markdown.js:0
#, python-format
msgid "Translate"
msgstr ""

View File

@ -0,0 +1,9 @@
* Nicolas Jeudy <nicolas@sudokeys.com>
* Nguyen Tan Phuc <phuc.nt@komit-consulting.com>
* Alexandre Díaz <dev@redneboa.es>
* Tom Blauwendraat <tom@sunflowerweb.nl>
* Kevin Kamau <kevin@sunflowerweb.nl>
* Helly kapatel <helly.kapatel@initos.com>
* [APSL-Nagarro](<https://apsl.tech>):
* Bernat Obrador <bobrador@apsl.net>
* Patryk Pyczko <ppyczko@apsl.net>

View File

@ -0,0 +1 @@
* Komit https://komit-consulting.com

View File

@ -0,0 +1,6 @@
This module adds a new widget for text field in form view on Odoo:
- In readonly mode, it uses text contents to parse and render them to html markdown syntax.
- In write mode, use [bootstrap-markdown][1]
[1]: `bootstrap-markdown <https://github.com/toopay/bootstrap-markdown>`_

View File

@ -0,0 +1,4 @@
* Can't create attachments on virtual records
* Improve user experience with Odoo specific syntax
* Improve user experience with Github specific syntax

View File

@ -0,0 +1,5 @@
Your XML form view definition should contain::
...
<field name="field_name" widget="bootstrap_markdown"/>
...

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@ -0,0 +1,466 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>Web Widget Text Markdown</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="web-widget-text-markdown">
<h1 class="title">Web Widget Text Markdown</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:8e4fa31404e335de7a1e78b7aa8c1530de1e895d5c6d2afe70269e663589c8c3
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/web/tree/15.0/web_widget_text_markdown"><img alt="OCA/web" src="https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/web-15-0/web-15-0-web_widget_text_markdown"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/web&amp;target_branch=15.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module adds a new widget for text field in form view on Odoo:</p>
<ul class="simple">
<li>In readonly mode, it uses text contents to parse and render them to html markdown syntax.</li>
<li>In write mode, use [bootstrap-markdown][1]</li>
</ul>
<p>[1]: <a class="reference external" href="https://github.com/toopay/bootstrap-markdown">bootstrap-markdown</a></p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#usage" id="toc-entry-1">Usage</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="toc-entry-2">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-6">Contributors</a></li>
<li><a class="reference internal" href="#other-credits" id="toc-entry-7">Other credits</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-8">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-1">Usage</a></h1>
<p>Your XML form view definition should contain:</p>
<pre class="literal-block">
...
&lt;field name=&quot;field_name&quot; widget=&quot;bootstrap_markdown&quot;/&gt;
...
</pre>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#toc-entry-2">Known issues / Roadmap</a></h1>
<ul class="simple">
<li>Cant create attachments on virtual records</li>
<li>Improve user experience with Odoo specific syntax</li>
<li>Improve user experience with Github specific syntax</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/web/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/web/issues/new?body=module:%20web_widget_text_markdown%0Aversion:%2015.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#toc-entry-4">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
<ul class="simple">
<li>Alexandre Díaz</li>
<li>Komit</li>
<li>Sudokeys</li>
<li>Sunflower IT</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
<ul class="simple">
<li>Nicolas Jeudy &lt;<a class="reference external" href="mailto:nicolas&#64;sudokeys.com">nicolas&#64;sudokeys.com</a>&gt;</li>
<li>Nguyen Tan Phuc &lt;<a class="reference external" href="mailto:phuc.nt&#64;komit-consulting.com">phuc.nt&#64;komit-consulting.com</a>&gt;</li>
<li>Alexandre Díaz &lt;<a class="reference external" href="mailto:dev&#64;redneboa.es">dev&#64;redneboa.es</a>&gt;</li>
<li>Tom Blauwendraat &lt;<a class="reference external" href="mailto:tom&#64;sunflowerweb.nl">tom&#64;sunflowerweb.nl</a>&gt;</li>
<li>Kevin Kamau &lt;<a class="reference external" href="mailto:kevin&#64;sunflowerweb.nl">kevin&#64;sunflowerweb.nl</a>&gt;</li>
<li>Helly kapatel &lt;<a class="reference external" href="mailto:helly.kapatel&#64;initos.com">helly.kapatel&#64;initos.com</a>&gt;</li>
<li>[APSL-Nagarro](&lt;<a class="reference external" href="https://apsl.tech">https://apsl.tech</a>&gt;):
* Bernat Obrador &lt;<a class="reference external" href="mailto:bobrador&#64;apsl.net">bobrador&#64;apsl.net</a>&gt;
* Patryk Pyczko &lt;<a class="reference external" href="mailto:ppyczko&#64;apsl.net">ppyczko&#64;apsl.net</a>&gt;</li>
</ul>
</div>
<div class="section" id="other-credits">
<h2><a class="toc-backref" href="#toc-entry-7">Other credits</a></h2>
<ul class="simple">
<li>Komit <a class="reference external" href="https://komit-consulting.com">https://komit-consulting.com</a></li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-8">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/web/tree/15.0/web_widget_text_markdown">OCA/web</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,7 @@
.o_field_text_markdown blockquote {
background: #f9f9f9;
border-left: 10px solid #ccc;
margin: 1.5em 10px;
padding: 1em 10px 0.1em 10px;
quotes: "\201C""\201D""\2018""\2019";
}

View File

@ -0,0 +1,148 @@
/* global showdown */
/* Copyright 2014 Sudokeys <http://www.sudokeys.com>
* Copyright 2017 Komit - <http:///komit-consulting.com>
* Copyright 2019 Alexandre Díaz - <dev@redneboa.es>
* License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
odoo.define("web_widget_text_markdown.FieldTextMarkDown", function (require) {
"use strict";
var basic_fields = require("web.basic_fields");
var field_registry = require("web.field_registry");
var core = require("web.core");
var _t = core._t;
var LIBS_PATH = "/web_widget_text_markdown/static/src/lib/";
var CUST_LIBS_PATH = "/web_widget_text_markdown/static/src/css/";
var FieldTextMarkDown = basic_fields.FieldText.extend({
className: [
basic_fields.FieldText.prototype.className,
"o_field_text_markdown",
].join(" "),
jsLibs: [
LIBS_PATH + "bootstrap-markdown.js",
LIBS_PATH + "showdown.js",
LIBS_PATH + "showdown-footnotes.js",
LIBS_PATH + "showdown-table.js",
LIBS_PATH + "showdown-toc.js",
],
cssLibs: [
LIBS_PATH + "bootstrap-markdown.min.css",
CUST_LIBS_PATH + "web_widget_text_markdown.css",
],
_getValue: function () {
var $widget = this.attrs.widget;
var $type = this.field.type;
if ($type === "html" && $widget && $widget === "bootstrap_markdown") {
return this._getHtmlValue(this.$input.val());
}
return this.$markdown.getContent();
},
start: function () {
this._super();
this.shw_render_html = new showdown.Converter({
extensions: ["table", "footnotes", "toc"],
emoji: true,
underline: true,
tablesHeaderId: true,
omitExtraWLInCodeBlocks: true,
noHeaderId: true,
prefixHeaderId: true,
rawPrefixHeaderId: true,
ghCompatibleHeaderId: true,
rawHeaderId: true,
headerLevelStart: false,
parseImgDimensions: true,
simplifiedAutoLink: true,
literalMidWordUnderscores: false,
literalMidWordAsterisks: true,
strikethrough: true,
tables: true,
ghCodeBlocks: true,
tasklists: true,
smoothLivePreview: true,
smartIndentationFix: true,
disableForced4SpacesIndentedSublists: true,
simpleLineBreaks: true,
requireSpaceBeforeHeadingText: true,
ghMentions: true,
ghMentionsLink: "https://github.com/{u}",
encodeEmails: true,
openLinksInNewWindow: true,
backslashEscapesHTMLTags: true,
completeHTMLDocument: true,
metadata: true,
splitAdjacentBlockquotes: true,
});
},
_prepareInput: function () {
var $input = this._super.apply(this, arguments);
_.defer(
function ($elm) {
$input.removeClass(this.className);
$input.wrap(
_.str.sprintf("<div class='%s'></div>", this.className)
);
$elm.markdown(this._getMarkdownOptions());
this.$markdown = $elm.data("markdown");
this.$markdown.setContent(this.value || "");
}.bind(this),
$input
);
return $input;
},
_getHtmlValue: function (value) {
return this.shw_render_html.makeHtml(this._formatValue(value));
},
_renderReadonly: function () {
this.$el.html(this._getHtmlValue(this.value));
},
_getMarkdownOptions: function () {
var self = this;
var markdownOpts = {
iconlibrary: "fa",
autofocus: false,
width: "o_field_text_markdown",
savable: false,
language: this.getSession().user_context.lang,
onPreview: function (e) {
var render_val = self._getHtmlValue(e.getContent());
return render_val;
},
};
if (_t.database.multi_lang && this.field.translate) {
markdownOpts.additionalButtons = [
[
{
name: "oTranslate",
data: [
{
name: "cmdTranslate",
title: _t("Translate"),
icon: {fa: "fa fa-flag"},
// eslint-disable-next-line max-len
callback: this._markdownTranslate.bind(self),
},
],
},
],
];
}
return markdownOpts;
},
_markdownTranslate: function () {
// Event is the click event from callback
this._onTranslate(event);
},
});
field_registry.add("bootstrap_markdown", FieldTextMarkDown);
return FieldTextMarkDown;
});

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
.md-editor{display:block;border:1px solid #ddd}.md-editor .md-footer,.md-editor>.md-header{display:block;padding:6px 4px;background:#f5f5f5}.md-editor>.md-header{margin:0}.md-editor>.md-preview{background:#fff;border-top:1px dashed #ddd;border-bottom:1px dashed #ddd;min-height:10px;overflow:auto}.md-editor>textarea{font-family:Menlo,Monaco,Consolas,"Courier New",monospace;font-size:14px;outline:0;margin:0;display:block;padding:0;width:100%;border:0;border-top:1px dashed #ddd;border-bottom:1px dashed #ddd;border-radius:0;box-shadow:none;background:#eee}.md-editor>textarea:focus{box-shadow:none;background:#fff}.md-editor.active{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.md-editor .md-controls{float:right;padding:3px}.md-editor .md-controls .md-control{right:5px;color:#bebebe;padding:3px 3px 3px 10px}.md-editor .md-controls .md-control:hover{color:#333}.md-editor.md-fullscreen-mode{width:100%;height:100%;position:fixed;top:0;left:0;z-index:99999;padding:60px 30px 15px;background:#fff!important;border:0!important}.md-editor.md-fullscreen-mode .md-footer{display:none}.md-editor.md-fullscreen-mode .md-input,.md-editor.md-fullscreen-mode .md-preview{margin:0 auto!important;height:100%!important;font-size:20px!important;padding:20px!important;color:#999;line-height:1.6em!important;resize:none!important;box-shadow:none!important;background:#fff!important;border:0!important}.md-editor.md-fullscreen-mode .md-preview{color:#333;overflow:auto}.md-editor.md-fullscreen-mode .md-input:focus,.md-editor.md-fullscreen-mode .md-input:hover{color:#333;background:#fff!important}.md-editor.md-fullscreen-mode .md-header{background:0 0;text-align:center;position:fixed;width:100%;top:20px}.md-editor.md-fullscreen-mode .btn-group{float:none}.md-editor.md-fullscreen-mode .btn{border:0;background:0 0;color:#b3b3b3}.md-editor.md-fullscreen-mode .btn.active,.md-editor.md-fullscreen-mode .btn:active,.md-editor.md-fullscreen-mode .btn:focus,.md-editor.md-fullscreen-mode .btn:hover{box-shadow:none;color:#333}.md-editor.md-fullscreen-mode .md-fullscreen-controls{position:absolute;top:20px;right:20px;text-align:right;z-index:1002;display:block}.md-editor.md-fullscreen-mode .md-fullscreen-controls a{color:#b3b3b3;clear:right;margin:10px;width:30px;height:30px;text-align:center}.md-editor.md-fullscreen-mode .md-fullscreen-controls a:hover{color:#333;text-decoration:none}.md-editor.md-fullscreen-mode .md-editor{height:100%!important;position:relative}.md-editor .md-fullscreen-controls{display:none}.md-nooverflow{overflow:hidden;position:fixed;width:100%}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
(function () {
var footnotes = function () {
return [{
type: 'lang',
filter: function filter(text) {
return text.replace(/^\[\^([\d\w]+)\]:\s*((\n+(\s{2,4}|\t).+)+)$/mg, function (str, name, rawContent, _, padding) {
var content = converter.makeHtml(rawContent.replace(new RegExp('^' + padding, 'gm'), ''));
return '<div class="footnote" id="footnote-' + name + '"><a href="#footnote-' + name + '"><sup>[' + name + ']</sup></a>:' + content + '</div>';
});
}},
{
type: 'lang',
filter: function filter(text) {
return text.replace(/^\[\^([\d\w]+)\]:( |\n)((.+\n)*.+)$/mg, function (str, name, _, content) {
return '<small class="footnote" id="footnote-' + name + '"><a href="#footnote-' + name + '"><sup>[' + name + ']</sup></a>: ' + content + '</small>';
});
}
},
{
type: 'lang',
filter: function filter(text) {
return text.replace(/\[\^([\d\w]+)\]/m, function (str, name) {
return '<a href="#footnote-' + name + '"><sup>[' + name + ']</sup></a>';
});
}
}];
};
// Client-side export
if (typeof window !== 'undefined' && window.showdown && window.showdown.extensions) {
window.showdown.extensions.footnotes = footnotes;
}
if (typeof module !== 'undefined') {
module.exports = footnotes;
}
}());

View File

@ -0,0 +1,112 @@
/*! showdown-table 17-06-2015 */
/*
* Basic table support with re-entrant parsing, where cell content
* can also specify markdown.
*
* Tables
* ======
*
* | Col 1 | Col 2 |
* |======== |====================================================|
* |**bold** | ![Valid XHTML] (http://w3.org/Icons/valid-xhtml10) |
* | Plain | Value |
*
*/
(function () {
'use strict';
var table = function (converter) {
var tables = {}, style = 'text-align:left;', filter;
tables.th = function (header) {
if (header.trim() === '') {
return '';
}
var id = header.trim().replace(/ /g, '_').toLowerCase();
return '<th id="' + id + '" style="' + style + '">' + header + '</th>';
};
tables.td = function (cell) {
return '<td style="' + style + '">' + converter.makeHtml(cell) + '</td>';
};
tables.ths = function () {
var out = '',
i = 0,
hs = [].slice.apply(arguments);
for (i; i < hs.length; i += 1) {
out += tables.th(hs[i]) + '\n';
}
return out;
};
tables.tds = function () {
var out = '', i = 0, ds = [].slice.apply(arguments);
for (i; i < ds.length; i += 1) {
out += tables.td(ds[i]) + '\n';
}
return out;
};
tables.thead = function () {
var out,
hs = [].slice.apply(arguments);
out = '<thead>\n';
out += '<tr>\n';
out += tables.ths.apply(this, hs);
out += '</tr>\n';
out += '</thead>\n';
return out;
};
tables.tr = function () {
var out,
cs = [].slice.apply(arguments);
out = '<tr>\n';
out += tables.tds.apply(this, cs);
out += '</tr>\n';
return out;
};
filter = function (text) {
var i = 0, lines = text.split('\n'), line, hs, out = [];
for (i; i < lines.length; i += 1) {
line = lines[i];
if (line.trim().match(/^[|].*[|]$/)) {
line = line.trim();
var tbl = [];
tbl.push('<table class="table table-bordered">');
hs = line.substring(1, line.length - 1).split('|');
tbl.push(tables.thead.apply(this, hs));
line = lines[++i];
if (!line.trim().match(/^[|][-=|: ]+[|]$/)) {
line = lines[--i];
} else {
line = lines[++i];
tbl.push('<tbody>');
while (line.trim().match(/^[|].*[|]$/)) {
line = line.trim();
tbl.push(tables.tr.apply(this, line.substring(1, line.length - 1).split('|')));
line = lines[++i];
}
tbl.push('</tbody>');
tbl.push('</table>');
out.push(tbl.join('\n'));
continue;
}
}
out.push(line);
}
return out.join('\n');
};
return [
{
type: 'lang',
filter: filter
}
];
};
if (typeof window !== 'undefined' && window.showdown && window.showdown.extensions) {
window.showdown.extensions.table = table;
}
if (typeof module !== 'undefined') {
module.exports = table;
}
}());
//# sourceMappingURL=showdown-table.js.map

View File

@ -0,0 +1,156 @@
(function(){
var toc = function(converter) {
return [
{
type: 'output',
filter: function(source) {
var elements = $(source);
var output = [];
var headingLevel = null;
var tocId = null;
for (var i=0; i<elements.length; i++) {
var element = $(elements[i]);
var results = null;
// Does the element consist only of [toc]?
// If so, we can replace this element with out list.
if (element.text().trim()=='[toc]') {
element = $('<ol>',{'class':'showdown-toc'});
headingLevel = null;
tocId = output.length;
}
// Does this item contain a [toc] with other stuff?
// If so, we'll split the element into two
else if (results = element.text().trim().match(/^([\s\S]*?)((?:\\)?\[toc\])([\s\S]*)$/)) {
// If there was a \ before the [toc] they're trying to escape it,
// so return the [toc] string without the \ and carry on. For
// some reason (I'm guessing a bug in showdown) you actually
// appear to need two \ (\\) in order to get this to show up for
// the filter. Leaving this code here anyway for now because it's
// "the right thing to do"(tm).
if (results[2][0]=='\\') {
element.text(results[1]+results[2].substr(1)+results[3]);
}
// Otherwise start building a new table of contents.
else {
var before = null;
var after = null;
// Create two of the same element.
if (element.prop('tagName')) {
if (results[1].trim().length>0) {
before = $('<'+element.prop('tagName')+'>').text(results[1]);
}
if (results[3].trim().length>0) {
after = $('<'+element.prop('tagName')+'>').text(results[3]);
}
}
// Otherwise if there's no tagName assume it's a text node
// and create two of those.
else {
if (results[1].trim().length>0) {
before = document.createTextNode(results[1]);
}
if (results[3].trim().length>0) {
after = document.createTextNode(results[3]);
}
}
// Our new table of contents container.
toc = $('<ol>',{'class':'showdown-toc'});
// If there was text before our [toc], add that in
if (before) {
output.push(before);
}
// Keep track of where our current table is in the elements array.
tocId = output.length;
// If there was text after, push the contents onto the array and
// use the after part as our current element.
if (after) {
output.push(toc);
element = after;
}
// Otherwise use the contents as the current element.
else {
element = toc;
}
// Reset the heading level - we're going to start looking for new
// headings again
headingLevel = null;
}
}
// If we've started a table of contents, but have nothing in it yet,
// look for the first header tag we encounter (after the [toc]).
// That's going to be what we use as contents entries for this table
// of contents.
else if (tocId && !headingLevel && element.prop("tagName")) {
switch (element.prop("tagName")) {
case 'H1':
case 'H2':
case 'H3':
case 'H4':
case 'H5':
case 'H6':
headingLevel = parseInt(element.prop('tagName').substr(1));
break;
}
}
// If we know what header level we're looking for (either we just
// found it above, or we're continuing to look for more) then check to
// see if this heading should be added to the contents.
if (tocId && headingLevel) {
switch (element.prop('tagName')) {
case 'H1':
case 'H2':
case 'H3':
case 'H4':
case 'H5':
case 'H6':
var thisLevel = parseInt(element.prop('tagName').substr(1));
if (thisLevel==headingLevel) {
output[tocId] = $(output[tocId]).append($('<li>').append($('<a>',{href:'#'+element.attr('id'),text:element.text()})));
}
// If we move up in what would be the document tree
// (eg: if we're looking for H2 and we suddenly find an
// H1) then we can probably safely assume that we want
// the table of contents to end for this section.
else if (thisLevel<headingLevel) {
toc = null
tocId = null;
headingLevel = null;
}
break;
}
}
// Push whatever element we've been looking at onto the output array.
output.push(element);
}
// Build some HTML to return
// Return it.
return $('<div>').append(output).html();
}
}
];
};
// Client-side export
if (typeof window !== 'undefined' && window.showdown && window.showdown.extensions) { window.showdown.extensions.toc = toc; }
// Server-side export
if (typeof module !== 'undefined') module.exports = toc;
}());

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,79 @@
/* global QUnit */
/* Copyright 2019 Alexandre Díaz - <dev@redneboa.es>
* License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
odoo.define("web_widget_text_markdown.test", function (require) {
"use strict";
var FormView = require("web.FormView");
var testUtils = require("web.test_utils");
var createAsyncView = testUtils.createAsyncView;
QUnit.module(
"web_widget_text_markdown",
{
beforeEach: function () {
this.data = {
partner: {
fields: {comment: {string: "Comment", type: "text"}},
records: [{id: 1, comment: "This is a test\n**Hello**"}],
},
};
this.arch =
"<form><sheet>" +
'<field name="comment"' +
' widget="bootstrap_markdown" />' +
"</sheet></form>";
},
},
function () {
QUnit.module("FieldTextMarkDown");
QUnit.test(
"bootstrap markdown widget are correctly rendered (preview)",
function (assert) {
assert.expect(1);
var done = assert.async();
createAsyncView({
View: FormView,
model: "partner",
data: this.data,
arch: this.arch,
res_id: 1,
}).then(function (form) {
_.defer(function () {
assert.strictEqual(form.$(".md-editor").length, 0);
form.destroy();
done();
});
});
}
);
QUnit.test(
"bootstrap markdown widget are correctly rendered (edit)",
function (assert) {
assert.expect(1);
var done = assert.async();
createAsyncView({
View: FormView,
model: "partner",
data: this.data,
arch: this.arch,
res_id: 1,
viewOptions: {mode: "edit"},
}).then(function (form) {
_.defer(function () {
assert.strictEqual(form.$(".md-editor").length, 1);
form.destroy();
done();
});
});
}
);
}
);
});