Initial commit: Odoo 18.0-20251222 extra-addons
Some checks failed
pre-commit / pre-commit (push) Has been cancelled
tests / Detect unreleased dependencies (push) Has been cancelled
tests / test with OCB (push) Has been cancelled
tests / test with Odoo (push) Has been cancelled

This commit is contained in:
tocmo0nlord
2026-03-13 20:43:25 +00:00
parent 36e847a7df
commit adbe430761
9472 changed files with 1265727 additions and 0 deletions

131
html_text/README.rst Executable file
View File

@@ -0,0 +1,131 @@
====================
Text from HTML field
====================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:6309273dc63ea41c703631efbfd5636c9eabeb563ce385c0c65e5a451fe41de9
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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%2Fserver--tools-lightgray.png?logo=github
:target: https://github.com/OCA/server-tools/tree/18.0/html_text
:alt: OCA/server-tools
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/server-tools-18-0/server-tools-18-0-html_text
: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/server-tools&target_branch=18.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module provides some technical features that allow to extract text
from any chunk of HTML, without HTML tags or attributes. You can chose
either:
- To truncate the result by amount of words or characters.
- To append an ellipsis (or any character(s)) at the end of the result.
It can be used to easily generate excerpts.
**Table of contents**
.. contents::
:local:
Usage
=====
This module just adds a technical utility, but nothing for the end user.
If you are a developer and need this utility for your module, see these
examples and read the docs inside the code.
Python example:
::
def some_method(self):
# Get truncated text from an HTML field. It will 40 words and 100
# characters at most, and will have "..." appended at the end if it
# gets truncated.
truncated_text = self.env["ir.fields.converter"].text_from_html(
self.html_field, 40, 100, "...")
QWeb example:
::
<t t-esc="env['ir.fields.converter'].text_from_html(doc.html_field)"/>
|Try me on Runbot|
.. |Try me on Runbot| image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:target: https://runbot.odoo-community.org/runbot/149/11.0
Known issues / Roadmap
======================
- An option could be added to try to respect the basic HTML tags inside
the excerpt (``<b>``, ``<i>``, ``<p>``, etc.).
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-tools/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/server-tools/issues/new?body=module:%20html_text%0Aversion:%2018.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
-------
* Grupo ESOC Ingeniería de Servicios
* Tecnativa
* Onestein
Contributors
------------
- Dennis Sluijk <d.sluijk@onestein.nl>
- `Tecnativa <https://www.tecnativa.com>`__:",
- Helly kapatel <helly.kapatel@initos.com>
- Mantas Šniukas <mantas@vialaurea.lt>
- Dhara Solanki <dhara.solanki@initos.com>
- Jairo Llopis
- Vicent Cubells
- Víctor Martínez
- Chau Le <chaulb@trobz.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/server-tools <https://github.com/OCA/server-tools/tree/18.0/html_text>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

3
html_text/__init__.py Executable file
View File

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

18
html_text/__manifest__.py Executable file
View File

@@ -0,0 +1,18 @@
# Copyright 2016-2017 Jairo Llopis <jairo.llopis@tecnativa.com>
# Copyright 2016 Tecnativa - Vicent Cubells
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
"name": "Text from HTML field",
"summary": "Generate excerpts from any HTML field",
"version": "18.0.1.0.0",
"category": "Tools",
"website": "https://github.com/OCA/server-tools",
"author": "Grupo ESOC Ingeniería de Servicios, "
"Tecnativa, "
"Onestein, "
"Odoo Community Association (OCA)",
"license": "AGPL-3",
"application": False,
"installable": True,
"depends": ["base"],
}

25
html_text/i18n/ca.po Executable file
View File

@@ -0,0 +1,25 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * html_text
#
# Translators:
# Marc Tormo i Bochaca <mtbochaca@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0c\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-04-19 18:00+0000\n"
"PO-Revision-Date: 2017-04-19 18:00+0000\n"
"Last-Translator: Marc Tormo i Bochaca <mtbochaca@gmail.com>, 2017\n"
"Language-Team: Catalan (https://www.transifex.com/oca/teams/23907/ca/)\n"
"Language: ca\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: html_text
#: model:ir.model,name:html_text.model_ir_fields_converter
#, fuzzy
msgid "Fields Converter"
msgstr "ir.fields.converter"

25
html_text/i18n/de.po Executable file
View File

@@ -0,0 +1,25 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * html_text
#
# Translators:
# Rudolf Schnapka <rs@techno-flex.de>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0c\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-04-19 18:00+0000\n"
"PO-Revision-Date: 2017-04-19 18:00+0000\n"
"Last-Translator: Rudolf Schnapka <rs@techno-flex.de>, 2017\n"
"Language-Team: German (https://www.transifex.com/oca/teams/23907/de/)\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: html_text
#: model:ir.model,name:html_text.model_ir_fields_converter
#, fuzzy
msgid "Fields Converter"
msgstr "ir.fields.converter"

37
html_text/i18n/es.po Executable file
View File

@@ -0,0 +1,37 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * html_text
#
# Translators:
# Pedro M. Baeza <pedro.baeza@gmail.com>, 2016
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0c\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-12-17 02:07+0000\n"
"PO-Revision-Date: 2023-11-09 20:38+0000\n"
"Last-Translator: Ivorra78 <informatica@totmaterial.es>\n"
"Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.17\n"
#. module: html_text
#: model:ir.model,name:html_text.model_ir_fields_converter
msgid "Fields Converter"
msgstr "Convertidor de Campos"
#~ msgid "Display Name"
#~ msgstr "Mostrar Nombre"
#~ msgid "ID"
#~ msgstr "ID (identificación)"
#~ msgid "Last Modified on"
#~ msgstr "Última Modifiación el"
#~ msgid "Smart Search"
#~ msgstr "Búsqueda Inteligente"

22
html_text/i18n/es_AR.po Executable file
View File

@@ -0,0 +1,22 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * html_text
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2022-09-04 06:07+0000\n"
"Last-Translator: Ignacio Buioli <ibuioli@gmail.com>\n"
"Language-Team: none\n"
"Language: es_AR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.3.2\n"
#. module: html_text
#: model:ir.model,name:html_text.model_ir_fields_converter
msgid "Fields Converter"
msgstr "Convertidor de Campos"

26
html_text/i18n/es_ES.po Executable file
View File

@@ -0,0 +1,26 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * html_text
#
# Translators:
# Fernando Lara <gennesis45@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0c\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-16 10:39+0000\n"
"PO-Revision-Date: 2017-02-16 10:39+0000\n"
"Last-Translator: Fernando Lara <gennesis45@gmail.com>, 2017\n"
"Language-Team: Spanish (Spain) (https://www.transifex.com/oca/teams/23907/"
"es_ES/)\n"
"Language: es_ES\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: html_text
#: model:ir.model,name:html_text.model_ir_fields_converter
#, fuzzy
msgid "Fields Converter"
msgstr "ir.documentos.conversor"

23
html_text/i18n/hr.po Executable file
View File

@@ -0,0 +1,23 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * html_text
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2019-11-13 17:34+0000\n"
"Last-Translator: Bole <bole@dajmi5.com>\n"
"Language-Team: none\n"
"Language: hr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 3.8\n"
#. module: html_text
#: model:ir.model,name:html_text.model_ir_fields_converter
msgid "Fields Converter"
msgstr "Pretvaranje polja"

24
html_text/i18n/html_text.pot Executable file
View File

@@ -0,0 +1,24 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * html_text
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.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: html_text
#: model:ir.model,name:html_text.model_ir_fields_converter
msgid "Fields Converter"
msgstr ""
#. module: html_text
#: model:ir.model.fields,field_description:html_text.field_ir_fields_converter__smart_search
msgid "Smart Search"
msgstr ""

37
html_text/i18n/it.po Executable file
View File

@@ -0,0 +1,37 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * html_text
#
# Translators:
# Paolo Valier <paolo.valier@hotmail.it>, 2018
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-01-06 02:25+0000\n"
"PO-Revision-Date: 2025-07-23 17:25+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
"Language-Team: Italian (https://www.transifex.com/oca/teams/23907/it/)\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.10.4\n"
#. module: html_text
#: model:ir.model,name:html_text.model_ir_fields_converter
msgid "Fields Converter"
msgstr "Convertitore campi"
#~ msgid "Display Name"
#~ msgstr "Nome visualizzato"
#~ msgid "ID"
#~ msgstr "ID"
#~ msgid "Last Modified on"
#~ msgstr "Ultima modifica il"
#~ msgid "Smart Search"
#~ msgstr "Ricerca intelligente"

25
html_text/i18n/tr.po Executable file
View File

@@ -0,0 +1,25 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * html_text
#
# Translators:
# Ahmet Altinisik <aaltinisik@altinkaya.com.tr>, 2016
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0c\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-12-29 03:40+0000\n"
"PO-Revision-Date: 2016-12-29 03:40+0000\n"
"Last-Translator: Ahmet Altinisik <aaltinisik@altinkaya.com.tr>, 2016\n"
"Language-Team: Turkish (https://www.transifex.com/oca/teams/23907/tr/)\n"
"Language: tr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#. module: html_text
#: model:ir.model,name:html_text.model_ir_fields_converter
#, fuzzy
msgid "Fields Converter"
msgstr "ir.fields.converter"

22
html_text/i18n/zh_CN.po Executable file
View File

@@ -0,0 +1,22 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * html_text
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2019-08-31 06:18+0000\n"
"Last-Translator: 黎伟杰 <674416404@qq.com>\n"
"Language-Team: none\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 3.8\n"
#. module: html_text
#: model:ir.model,name:html_text.model_ir_fields_converter
msgid "Fields Converter"
msgstr "字段转换器"

3
html_text/models/__init__.py Executable file
View File

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

View File

@@ -0,0 +1,74 @@
# Copyright 2016-2017 Jairo Llopis <jairo.llopis@tecnativa.com>
# Copyright 2016 Tecnativa - Vicent Cubells
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
import logging
from lxml import etree, html
from odoo import api, models
_logger = logging.getLogger(__name__)
class IrFieldsConverter(models.AbstractModel):
_inherit = "ir.fields.converter"
@api.model
def text_from_html(
self, html_content, max_words=None, max_chars=None, ellipsis="", fail=False
):
"""Extract text from an HTML field in a generator.
:param str html_content:
HTML contents from where to extract the text.
:param int max_words:
Maximum amount of words allowed in the resulting string.
:param int max_chars:
Maximum amount of characters allowed in the resulting string. If
you apply this limit, beware that the last word could get cut in an
unexpected place.
:param str ellipsis:
Character(s) to be appended to the end of the resulting string if
it gets truncated after applying limits set in :param:`max_words`
or :param:`max_chars`. If you want nothing applied, just set an
empty string.
:param bool fail:
If ``True``, exceptions will be raised. Otherwise, an empty string
will be returned on failure.
"""
# Parse HTML
try:
doc = html.fromstring(html_content)
except (TypeError, etree.XMLSyntaxError, etree.ParserError):
if fail:
raise
else:
_logger.exception("Failure parsing this HTML:\n%s", html_content)
return ""
# Get words
words = "".join(doc.xpath("//text()")).split()
# Truncate words
suffix = max_words and len(words) > max_words
if max_words:
words = words[:max_words]
# Get text
text = " ".join(words)
# Truncate text
suffix = suffix or max_chars and len(text) > max_chars
if max_chars:
text = text[: max_chars - (len(ellipsis) if suffix else 0)].strip()
# Append ellipsis if needed
if suffix:
text += ellipsis
return text

3
html_text/pyproject.toml Executable file
View File

@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"

View File

@@ -0,0 +1,9 @@
- Dennis Sluijk \<d.sluijk@onestein.nl\>
- [Tecnativa](https://www.tecnativa.com):",
- Helly kapatel \<helly.kapatel@initos.com\>
- Mantas Šniukas \<mantas@vialaurea.lt\>
- Dhara Solanki \<dhara.solanki@initos.com\>
- Jairo Llopis
- Vicent Cubells
- Víctor Martínez
- Chau Le \<chaulb@trobz.com\>

View File

@@ -0,0 +1,8 @@
This module provides some technical features that allow to extract text
from any chunk of HTML, without HTML tags or attributes. You can chose
either:
- To truncate the result by amount of words or characters.
- To append an ellipsis (or any character(s)) at the end of the result.
It can be used to easily generate excerpts.

2
html_text/readme/ROADMAP.md Executable file
View File

@@ -0,0 +1,2 @@
- An option could be added to try to respect the basic HTML tags inside
the excerpt (`<b>`, `<i>`, `<p>`, etc.).

19
html_text/readme/USAGE.md Executable file
View File

@@ -0,0 +1,19 @@
This module just adds a technical utility, but nothing for the end user.
If you are a developer and need this utility for your module, see these
examples and read the docs inside the code.
Python example:
def some_method(self):
# Get truncated text from an HTML field. It will 40 words and 100
# characters at most, and will have "..." appended at the end if it
# gets truncated.
truncated_text = self.env["ir.fields.converter"].text_from_html(
self.html_field, 40, 100, "...")
QWeb example:
<t t-esc="env['ir.fields.converter'].text_from_html(doc.html_field)"/>
[![Try me on Runbot](https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas)](https://runbot.odoo-community.org/runbot/149/11.0)

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -0,0 +1,471 @@
<!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>Text from HTML field</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="text-from-html-field">
<h1 class="title">Text from HTML field</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:6309273dc63ea41c703631efbfd5636c9eabeb563ce385c0c65e5a451fe41de9
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<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/server-tools/tree/18.0/html_text"><img alt="OCA/server-tools" src="https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/server-tools-18-0/server-tools-18-0-html_text"><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/server-tools&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module provides some technical features that allow to extract text
from any chunk of HTML, without HTML tags or attributes. You can chose
either:</p>
<ul class="simple">
<li>To truncate the result by amount of words or characters.</li>
<li>To append an ellipsis (or any character(s)) at the end of the result.</li>
</ul>
<p>It can be used to easily generate excerpts.</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="#maintainers" id="toc-entry-7">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>This module just adds a technical utility, but nothing for the end user.</p>
<p>If you are a developer and need this utility for your module, see these
examples and read the docs inside the code.</p>
<p>Python example:</p>
<pre class="literal-block">
def some_method(self):
# Get truncated text from an HTML field. It will 40 words and 100
# characters at most, and will have &quot;...&quot; appended at the end if it
# gets truncated.
truncated_text = self.env[&quot;ir.fields.converter&quot;].text_from_html(
self.html_field, 40, 100, &quot;...&quot;)
</pre>
<p>QWeb example:</p>
<pre class="literal-block">
&lt;t t-esc=&quot;env['ir.fields.converter'].text_from_html(doc.html_field)&quot;/&gt;
</pre>
<p><a class="reference external image-reference" href="https://runbot.odoo-community.org/runbot/149/11.0"><img alt="Try me on Runbot" src="https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas" /></a></p>
</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>An option could be added to try to respect the basic HTML tags inside
the excerpt (<tt class="docutils literal">&lt;b&gt;</tt>, <tt class="docutils literal">&lt;i&gt;</tt>, <tt class="docutils literal">&lt;p&gt;</tt>, etc.).</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/server-tools/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/server-tools/issues/new?body=module:%20html_text%0Aversion:%2018.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>Grupo ESOC Ingeniería de Servicios</li>
<li>Tecnativa</li>
<li>Onestein</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
<ul class="simple">
<li>Dennis Sluijk &lt;<a class="reference external" href="mailto:d.sluijk&#64;onestein.nl">d.sluijk&#64;onestein.nl</a>&gt;</li>
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:”,</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>Mantas Šniukas &lt;<a class="reference external" href="mailto:mantas&#64;vialaurea.lt">mantas&#64;vialaurea.lt</a>&gt;</li>
<li>Dhara Solanki &lt;<a class="reference external" href="mailto:dhara.solanki&#64;initos.com">dhara.solanki&#64;initos.com</a>&gt;<ul>
<li>Jairo Llopis</li>
<li>Vicent Cubells</li>
<li>Víctor Martínez</li>
</ul>
</li>
<li>Chau Le &lt;<a class="reference external" href="mailto:chaulb&#64;trobz.com">chaulb&#64;trobz.com</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-7">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/server-tools/tree/18.0/html_text">OCA/server-tools</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>

3
html_text/tests/__init__.py Executable file
View File

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

View File

@@ -0,0 +1,57 @@
# Copyright 2016-2017 Jairo Llopis <jairo.llopis@tecnativa.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from lxml import etree
from odoo.tests.common import TransactionCase
from odoo.tools import mute_logger
class ExtractorCase(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
# Shortcut
cls.text_from_html = cls.env["ir.fields.converter"].text_from_html
def test_excerpts(self):
"""Text gets correctly extracted."""
html = """
<html>
<body>
<div class="this should not appear">
<h1>I'm a title</h1>
<p>I'm a paragraph</p>
<small>¡Pues yo soy español!</small>
</div>
</body>
</html>
"""
self.assertEqual(
self.text_from_html(html),
"I'm a title I'm a paragraph ¡Pues yo soy español!",
)
self.assertEqual(
self.text_from_html(html, 8), "I'm a title I'm a paragraph ¡Pues yo…"
)
self.assertEqual(
self.text_from_html(html, 8, 31), "I'm a title I'm a paragraph ¡P…"
)
self.assertEqual(
self.text_from_html(html, 7, ellipsis=""),
"I'm a title I'm a paragraph ¡Pues",
)
@mute_logger("odoo.addons.html_text.models.ir_fields_converter")
def test_empty_html(self):
"""Empty HTML handled correctly."""
self.assertEqual(self.text_from_html(""), "")
with self.assertRaises(etree.ParserError):
self.text_from_html("", fail=True)
@mute_logger("odoo.addons.html_text.models.ir_fields_converter")
def test_false_html(self):
"""``False`` HTML handled correctly."""
self.assertEqual(self.text_from_html(False), "")
with self.assertRaises(TypeError):
self.text_from_html(False, fail=True)