diff --git a/src/calibre/gui2/dialogs/template_general_info.py b/src/calibre/gui2/dialogs/template_general_info.py index f82246bef5..58303898e6 100644 --- a/src/calibre/gui2/dialogs/template_general_info.py +++ b/src/calibre/gui2/dialogs/template_general_info.py @@ -14,6 +14,7 @@ from qt.core import QDialogButtonBox, QVBoxLayout from calibre.constants import iswindows from calibre.gui2.widgets2 import Dialog, HTMLDisplay from calibre.utils.ffml_processor import FFMLProcessor +from calibre.utils.formatter_functions import general_doc, ffml_doc class GeneralInformationDialog(Dialog): @@ -41,112 +42,6 @@ class GeneralInformationDialog(Dialog): e.setHtml(html) -general_doc = r''' -[LIST] -[*]`Functions in Single Function Mode templates` -[LIST] -[*]When using functions in a Single function mode template, -for example ``{title:uppercase()}``, the first parameter ``value`` is omitted. -It is automatically replaced by the value of the specified field. - -In all the other modes the value parameter must be supplied. -[*]Do not use subtemplates "(`{...}`)" as function arguments because they will often not work. -Instead, use Template Program Mode and General Program Mode. -[*]Do not use subtemplates "(`{...}`)" or functions (see below) in the prefix or the suffix -for the same reason as above; they will often not work. -[/LIST] -[*]`Editor for assisting with template function documentation` - -An editor is available for helping write template function documentation. Given a document -in the Formatter Function Markup Language, it show the resulting HTML. The HTML is updated as you edit. - -This editor is available in two ways: -[LIST] -[*]Using the command -[CODE] -calibre-debug -c "from calibre.gui2.dialogs.ff_doc_editor import main; main()"[/CODE] -all on one line. -[*]By defining a keyboard shortcut in calibre for the action `Open the template -documentation editor` in the `Miscellaneous` section. There is no default shortcut. -[/LIST] -[/LIST] -''' - -ffml_doc = r''' -Format Function Markup Language (FFML) is a basic markup language used to -document formatter functions. It is based on a combination of RST used by sphinx -and BBCODE used by many bulletin board systems such as MobileRead. It provides a -way to specify: -[LIST] -[*][B]Inline program code text[/B]: surround this text with \`\` as in \`\`foo\`\`. -Tags inside the text are ignored. if the code text ends with a `\'` character, put -a space before the closing \`\` characters. Trailing blanks in the code text are removed. -[*][B]Italic text[/B]: surround this text with \`. Example: \`foo\` produces `foo`. -[*][B]Bold text[/B]: surround this text with \[B]text\[\B] tags. Example: \[B]foo\[/B] produces [B]foo[/B]. -[*][B]Text intended to reference a calibre GUI action[/B]. This uses RST syntax.\ - Example: \:guilabel\:\`Preferences->Advanced->Template functions\`. For HTML the produced text is in a different font, as in: :guilabel:`Some text` -[*][B]Empty lines[/B], indicated by two newlines in a row. A visible empty line in the FFML -will become an empty line in the output. -[*][B]URLs.[/B] The syntax is similar to BBCODE: ``[URL href="http..."]Link text[/URL]``.\ - Example: ``[URL href="https://en.wikipedia.org/wiki/ISO_8601"]ISO[/URL]`` produces [URL href="https://en.wikipedia.org/wiki/ISO_8601"]ISO[/URL] -[*][B]Internal function reference links[/B]. These are links to formatter function -documentation. The syntax is the same as guilabel. Example: ``:ref:`get_note` ``. -The characters '()' are automatically added to the function name when -displayed. For HTML it generates the same as the inline program code text -operator (\`\`) with no link. Example: ``:ref:`add` `` produces ``add()``. -For RST it generates a ``:ref:`` reference that works only in an RST document -containing formatter function documentation. Example: ``:ref:`get_note` `` -generates \:ref\:\`get_note() \` -[*][B]Example program code text blocks.[/B] Surround the code block with ``[CODE]`` -and ``[/CODE]`` tags. These tags must be first on a line. Example: -[CODE] -[CODE] -program: - get_note('authors', 'Isaac Asimov', 1) -[\/CODE] -[/CODE] -produces -[CODE] -program: - get_note('authors', 'Isaac Asimov', 1) -[/CODE] -If you want the literal text ``[/CODE]`` in a code block then it must be entered as ``[\/CODE]`` -to ensure that the FFML parser doesn't interpret it as the end of the code block. The ``'\'`` -character is removed. -[*][B]Bulleted lists[/B], using BBCODE tags. Surround the list with ``[LIST]`` and -``[/LIST]``. List items are indicated with ``[*]``. All of the tags must be -first on a line. Bulleted lists can be nested and can contain other FFML -elements. - -Example: a two bullet list containing CODE blocks -[CODE] -[LIST] -[*]Return the HTML of the note attached to the tag `Fiction`: -[CODE] -program: - get_note('tags', 'Fiction', '') -[\/CODE] -[*]Return the plain text of the note attached to the author `Isaac Asimov`: -[CODE] -program: - get_note('authors', 'Isaac Asimov', 1) -[\/CODE] -[/LIST] -[/CODE] -[*][B]End of summary marker[/B]. A summary is generated from the first characters of -the documentation. The summary includes text up to a \[\/] tag. There is no -opening tag because the summary starts at the first character. If there is -no \[\/] tag then all the document is used for the summary. The \[\/] tag -is removed, not replaced with white space or any other character. -[*][B]Escaped character[/B]: precede the character with a backslash. This is useful -to escape tags. For example to make the \[CODE] tag not a tag, use \\\[CODE]. -Escaping characters doesn't work in `Inline program code text` or -`Example program code text blocks`. -[/LIST] -Note: HTML output contains no CSS and does not start with a tag such as
or

. -''' - - if __name__ == '__main__': from calibre.gui2 import Application app = Application([]) diff --git a/src/calibre/gui2/preferences/template_functions.py b/src/calibre/gui2/preferences/template_functions.py index c402b4d381..38b21c6a9d 100644 --- a/src/calibre/gui2/preferences/template_functions.py +++ b/src/calibre/gui2/preferences/template_functions.py @@ -13,6 +13,7 @@ from calibre.gui2.dialogs.template_dialog import TemplateDialog from calibre.gui2.preferences import AbortInitialize, ConfigWidgetBase, test_widget from calibre.gui2.preferences.template_functions_ui import Ui_Form from calibre.gui2.widgets import PythonHighlighter +from calibre.utils.ffml_processor import FFMLProcessor from calibre.utils.formatter_functions import ( StoredObjectType, compile_user_function, @@ -31,6 +32,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): def genesis(self, gui): self.gui = gui self.db = gui.library_view.model().db + self.ffml = FFMLProcessor() help_text = _('''

Here you can add and remove functions used in template processing. A @@ -387,7 +389,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): return func = self.funcs[txt] self.argument_count.setValue(func.arg_count) - self.documentation.setText(func.doc) + self.documentation.setHtml(self.ffml.document_to_html(func.doc, txt)) if txt in self.builtins: if hasattr(func, 'program_text') and func.program_text: self.program.setPlainText(func.program_text) diff --git a/src/calibre/utils/ffml_processor.py b/src/calibre/utils/ffml_processor.py index 267e8775f8..d231e39aa4 100644 --- a/src/calibre/utils/ffml_processor.py +++ b/src/calibre/utils/ffml_processor.py @@ -389,8 +389,7 @@ class FFMLProcessor: result += '\\' + tree.text() elif tree.node_kind() == NodeKinds.CODE_TEXT: t = tree.text() - if t.endswith('`'): - t = t + ' ' + t = t + ' ' if t.endswith('`') else t result += f'``{t}``' elif tree.node_kind() == NodeKinds.CODE_BLOCK: result += '\n[CODE]\n' + tree.text().replace('[/CODE]', r'[\/CODE]') + '[/CODE]\n' @@ -407,9 +406,7 @@ class FFMLProcessor: for child in tree.children(): result += '[*]' t = self.tree_to_transifex(child, depth=depth+1) - if t.endswith('\n\n'): - t = t[0:-1] - result += t + result += t[0:-1] if t.endswith('\n\n') else t result += '[/LIST]\n' elif tree.node_kind() == NodeKinds.REF: result += f':ref:`{tree.text()}`' diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index d35e9e98ac..cb6e0964c6 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -3791,3 +3791,111 @@ def load_user_template_functions(library_uuid, funcs, precompiled_user_functions def unload_user_template_functions(library_uuid): formatter_functions().unregister_functions(library_uuid) + + +# These are here so they can be processed before sending them to transifex + +general_doc = r''' +[LIST] +[*]`Functions in Single Function Mode templates` +[LIST] +[*]When using functions in a Single function mode template, +for example ``{title:uppercase()}``, the first parameter ``value`` is omitted. +It is automatically replaced by the value of the specified field. + +In all the other modes the value parameter must be supplied. +[*]Do not use subtemplates "(`{...}`)" as function arguments because they will often not work. +Instead, use Template Program Mode and General Program Mode. +[*]Do not use subtemplates "(`{...}`)" or functions (see below) in the prefix or the suffix +for the same reason as above; they will often not work. +[/LIST] +[*]`Editor for assisting with template function documentation` + +An editor is available for helping write template function documentation. Given a document +in the Formatter Function Markup Language, it show the resulting HTML. The HTML is updated as you edit. + +This editor is available in two ways: +[LIST] +[*]Using the command +[CODE] +calibre-debug -c "from calibre.gui2.dialogs.ff_doc_editor import main; main()"[/CODE] +all on one line. +[*]By defining a keyboard shortcut in calibre for the action `Open the template +documentation editor` in the `Miscellaneous` section. There is no default shortcut. +[/LIST] +[/LIST] +''' + +ffml_doc = r''' +Format Function Markup Language (FFML) is a basic markup language used to +document formatter functions. It is based on a combination of RST used by sphinx +and BBCODE used by many bulletin board systems such as MobileRead. It provides a +way to specify: +[LIST] +[*][B]Inline program code text[/B]: surround this text with \`\` as in \`\`foo\`\`. +Tags inside the text are ignored. if the code text ends with a `\'` character, put +a space before the closing \`\` characters. Trailing blanks in the code text are removed. +[*][B]Italic text[/B]: surround this text with \`. Example: \`foo\` produces `foo`. +[*][B]Bold text[/B]: surround this text with \[B]text\[\B] tags. Example: \[B]foo\[/B] produces [B]foo[/B]. +[*][B]Text intended to reference a calibre GUI action[/B]. This uses RST syntax.\ + Example: \:guilabel\:\`Preferences->Advanced->Template functions\`. For HTML the produced text is in a different font, as in: :guilabel:`Some text` +[*][B]Empty lines[/B], indicated by two newlines in a row. A visible empty line in the FFML +will become an empty line in the output. +[*][B]URLs.[/B] The syntax is similar to BBCODE: ``[URL href="http..."]Link text[/URL]``.\ + Example: ``[URL href="https://en.wikipedia.org/wiki/ISO_8601"]ISO[/URL]`` produces [URL href="https://en.wikipedia.org/wiki/ISO_8601"]ISO[/URL] +[*][B]Internal function reference links[/B]. These are links to formatter function +documentation. The syntax is the same as guilabel. Example: ``:ref:`get_note` ``. +The characters '()' are automatically added to the function name when +displayed. For HTML it generates the same as the inline program code text +operator (\`\`) with no link. Example: ``:ref:`add` `` produces ``add()``. +For RST it generates a ``:ref:`` reference that works only in an RST document +containing formatter function documentation. Example: ``:ref:`get_note` `` +generates \:ref\:\`get_note() \` +[*][B]Example program code text blocks.[/B] Surround the code block with ``[CODE]`` +and ``[/CODE]`` tags. These tags must be first on a line. Example: +[CODE] +[CODE] +program: + get_note('authors', 'Isaac Asimov', 1) +[\/CODE] +[/CODE] +produces +[CODE] +program: + get_note('authors', 'Isaac Asimov', 1) +[/CODE] +If you want the literal text ``[/CODE]`` in a code block then it must be entered as ``[\/CODE]`` +to ensure that the FFML parser doesn't interpret it as the end of the code block. The ``'\'`` +character is removed. +[*][B]Bulleted lists[/B], using BBCODE tags. Surround the list with ``[LIST]`` and +``[/LIST]``. List items are indicated with ``[*]``. All of the tags must be +first on a line. Bulleted lists can be nested and can contain other FFML +elements. + +Example: a two bullet list containing CODE blocks +[CODE] +[LIST] +[*]Return the HTML of the note attached to the tag `Fiction`: +[CODE] +program: + get_note('tags', 'Fiction', '') +[\/CODE] +[*]Return the plain text of the note attached to the author `Isaac Asimov`: +[CODE] +program: + get_note('authors', 'Isaac Asimov', 1) +[\/CODE] +[/LIST] +[/CODE] +[*][B]End of summary marker[/B]. A summary is generated from the first characters of +the documentation. The summary includes text up to a \[\/] tag. There is no +opening tag because the summary starts at the first character. If there is +no \[\/] tag then all the document is used for the summary. The \[\/] tag +is removed, not replaced with white space or any other character. +[*][B]Escaped character[/B]: precede the character with a backslash. This is useful +to escape tags. For example to make the \[CODE] tag not a tag, use \\\[CODE]. +Escaping characters doesn't work in `Inline program code text` or +`Example program code text blocks`. +[/LIST] +Note: HTML output contains no CSS and does not start with a tag such as

or

. +'''