From 1da80d4d8ff4295a5f35cbf0130eef1d89a46b44 Mon Sep 17 00:00:00 2001 From: Juergen Spitzmueller Date: Sat, 12 Feb 2022 17:10:34 +0100 Subject: [PATCH] Add basic support for \DeclareMetadata File format change --- development/FORMAT | 6 + lib/chkconfig.ltx | 2 + lib/doc/UserGuide.lyx | 364 ++++++++++++++++++++++++-- lib/doc/de/UserGuide.lyx | 167 ++++++++---- lib/lyx2lyx/lyx_2_4.py | 28 +- src/BufferParams.cpp | 71 +++++ src/BufferParams.h | 4 + src/frontends/qt/GuiDocument.cpp | 22 +- src/frontends/qt/LaTeXHighlighter.cpp | 45 +++- src/frontends/qt/LaTeXHighlighter.h | 8 +- src/frontends/qt/ui/PDFSupportUi.ui | 106 ++++---- src/tex2lyx/Preamble.cpp | 10 + src/tex2lyx/Preamble.h | 1 + src/version.h | 4 +- 14 files changed, 680 insertions(+), 158 deletions(-) diff --git a/development/FORMAT b/development/FORMAT index 28014eef9b..dd95edf75e 100644 --- a/development/FORMAT +++ b/development/FORMAT @@ -7,6 +7,12 @@ changes happened in particular if possible. A good example would be ----------------------- +2022-02-11 Jürgen Spitzmüller + * Format incremented to 609: \\begin_metadata ... \\end_metadata buffer param. + This takes a list of keyvals for the new \\DocumentMetadata command + (introduced in LaTeX 06/2022) which must be output at the very begin + of the document (before \\documentclass). + 2021-03-23 Thibaut Cuvelier * Format incremented to 608: DocBook MathML-namespace prefix with the \docbook_mathml_prefix buffer parameter (enumerated value: diff --git a/lib/chkconfig.ltx b/lib/chkconfig.ltx index 660710b1e7..d2613e9c49 100644 --- a/lib/chkconfig.ltx +++ b/lib/chkconfig.ltx @@ -242,6 +242,8 @@ \TestLaTeXVersion{2020/10/01} % This robustifies LaTeX commands \TestLaTeXVersion{2021/06/01} +% Introduction of \\DocumentMetadata +\TestLaTeXVersion{2022/06/01} %%% And now, the list of available languages % The trick is to know that \the\everyjob contains something like diff --git a/lib/doc/UserGuide.lyx b/lib/doc/UserGuide.lyx index 123c09a52e..f5d5648989 100644 --- a/lib/doc/UserGuide.lyx +++ b/lib/doc/UserGuide.lyx @@ -1,5 +1,5 @@ #LyX 2.4 created this file. For more info see https://www.lyx.org/ -\lyxformat 608 +\lyxformat 609 \begin_document \begin_header \save_transient_properties true @@ -8973,12 +8973,14 @@ Verbatim \end_layout \begin_layout Verbatim + This is Verbatim. \end_layout \begin_layout Verbatim \noindent \align block + The following 2 lines are empty: \end_layout @@ -8991,6 +8993,7 @@ The following 2 lines are empty: \end_layout \begin_layout Verbatim + Almost everything is allowed in Verbatim:"%&$§#~'` \backslash }][{| @@ -9014,6 +9017,7 @@ Verbatim \end_layout \begin_layout Verbatim* + This is Verbatim*. \end_layout @@ -35811,16 +35815,61 @@ PDF properties \end_layout \begin_layout Standard + +\change_deleted -712698321 1644655914 The +\change_unchanged + \family sans Document\SpecialChar menuseparator Settings\SpecialChar menuseparator PDF Properties \family default - dialog allows you to set up special options for the PDF output of your - document. - All these options are provided by the \SpecialChar LaTeX --package + +\change_deleted -712698321 1644655917 +dialog +\change_unchanged +allows you to set up +\change_deleted -712698321 1644651900 +special options +\change_inserted -712698321 1644651929 +specifics +\change_unchanged + +\change_deleted -712698321 1644651937 +for +\change_inserted -712698321 1644651944 +of your document's +\change_unchanged + +\change_deleted -712698321 1644655939 +the +\change_unchanged +PDF output +\change_deleted -712698321 1644651948 + of your document +\change_unchanged +. + +\change_deleted -712698321 1644651614 +All +\change_inserted -712698321 1644651616 +Most of +\change_unchanged + these +\change_deleted -712698321 1644651959 +options +\change_inserted -712698321 1644651961 +specifics +\change_unchanged + are provided by the \SpecialChar LaTeX + +\change_deleted -712698321 1644651813 +- +\change_inserted -712698321 1644651814 + +\change_unchanged +package \series bold hyperref \series default @@ -35835,10 +35884,63 @@ status collapsed \end_inset - which will link all cross-references in the DVI- and PDF-output. + +\change_inserted -712698321 1644653717 + which you need to enable by clicking +\family sans +Use Hyperref Support +\family default + in order to set the PDF properties (if the package is already loaded by + your document class or another package, the checkbox you need to click + is labeled +\family sans +Customize Hyperref Options +\family default + instead). + Among other things, hyperref +\change_deleted -712698321 1644651887 + which +\change_unchanged + +\change_deleted -712698321 1644653821 +will +\change_inserted -712698321 1644653851 + hyper +\change_unchanged +link +\change_inserted -712698321 1644653826 +s +\change_unchanged + all +\change_inserted -712698321 1644653859 +URLs and +\change_unchanged +cross-references in the +\change_deleted -712698321 1644653786 +DVI- and +\change_unchanged +PDF +\change_inserted -712698321 1644653751 + +\change_deleted -712698321 1644653751 +- +\change_unchanged +output. This means that the reader of your document will be able to click on a - table of contents entry or on a reference to move to the cross-referenced - part of the document. +\change_inserted -712698321 1644653878 +n URL, a +\change_unchanged + table of contents entry or on a reference to +\change_inserted -712698321 1644653918 +open a website or to +\change_unchanged +move to the cross-referenced part of the document. + +\change_inserted -712698321 1644653971 + Furthermore, you can set PDF metadata (such as document author and title), + or determine how the PDF is being opened by the reader program. +\change_unchanged + \end_layout \begin_layout Standard @@ -35847,8 +35949,11 @@ The header information in the dialog tab General \family default is saved together with the PDF as file properties. - Many programs are able to extract this information, for example, automatically - to recognize who the author is and what the PDF is about. + Many programs are able to extract this information, for example, +\change_deleted -712698321 1644656745 +automatically +\change_unchanged +to recognize who the author is and what the PDF is about. This is very useful to sort, classify or use PDFs for bibliography issues. When the option \family sans @@ -35862,9 +35967,15 @@ fill header \family default - is set, \SpecialChar LyX - tries to extract the header information from your document title - and author entries. + is set, +\change_deleted -712698321 1644654039 +\SpecialChar LyX + +\change_inserted -712698321 1644654041 +hyperref +\change_unchanged + tries to extract the header information from your document title and author + entries. The option \family sans Load @@ -35885,12 +35996,51 @@ mode \end_layout \begin_layout Standard -You can specify in the dialog tab + +\change_deleted -712698321 1644654066 +You can specify i +\change_inserted -712698321 1644654066 +I +\change_unchanged +n the dialog tab \family sans Hyperlinks \family default - how the links will look and if links for bibliographical backreferences - are created. + +\change_inserted -712698321 1644654103 +you can customize the +\change_deleted -712698321 1644654105 +how +\change_inserted -712698321 1644654109 + look of +\change_unchanged + +\change_deleted -712698321 1644654087 +the +\change_inserted -712698321 1644654087 +such +\change_unchanged + links +\change_inserted -712698321 1644654147 +, and you can specify +\change_unchanged + +\change_inserted -712698321 1644654275 +if and which +\change_deleted -712698321 1644654283 +will look and if links for +\change_unchanged +bibliographical backreferences are created +\change_inserted -712698321 1644654335 +. + +\family sans +Backreferences +\family default + are links inserted at the end of bibliographic entries pointing to either + sections, pages or slides on which these entries are being cited +\change_unchanged +. The \family sans Break @@ -35971,21 +36121,47 @@ green \end_layout \begin_layout Standard -but you can change these in the field +but you can change these in the +\change_deleted -712698321 1644651692 +field +\change_inserted -712698321 1644651692 +tab +\change_unchanged + \family sans -Additional options +Additional +\change_deleted -712698321 1644656056 +o +\change_inserted -712698321 1644656056 +O +\change_unchanged +ptions \family default . - For example, in this document they were changed with the additional options: + For example, in this document they were changed with the +\change_inserted -712698321 1644651709 +se +\change_unchanged + additional options +\change_inserted -712698321 1644651730 + added to +\family sans +Hypersetup +\change_unchanged + +\family default +: \end_layout -\begin_layout Standard +\begin_layout Quote \series bold linkcolor=black, citecolor=black, urlcolor=blue, filecolor=blue \end_layout \begin_layout Standard + +\change_deleted -712698321 1644654422 If the option \family sans Backreferences @@ -35993,6 +36169,8 @@ Backreferences is set, the hyperlinks will appear in the bibliography after the different entries, showing, depending on the option selected, the number of the section, slide or page where the entry is referenced. +\change_unchanged + \end_layout \begin_layout Standard @@ -36000,20 +36178,56 @@ In the dialog tab \family sans Bookmarks \family default - you can specify if PDF-bookmarks should be created for every section of - your document to make it easier for readers to navigate through the document. + you can specify if PDF +\change_inserted -712698321 1644654456 + +\change_deleted -712698321 1644654456 +- +\change_unchanged +bookmarks +\change_inserted -712698321 1644654511 +(shown as a collapsible outline in the PDF reader) +\change_unchanged +should be created for every section of your document to make it easier for + readers to navigate through the document. You can decide if the bookmarks should be numbered like your document sections or not. - With the + +\change_deleted -712698321 1644654607 +With +\change_inserted -712698321 1644654609 +By checking +\change_unchanged + +\change_deleted -712698321 1644654594 +the +\change_unchanged + \family sans -Open bookmarks +Open bookmark +\change_inserted -712698321 1644654550 + tree +\change_deleted -712698321 1644654551 +s +\change_inserted -712698321 1644654802 + \family default +you can instruct the PDF reader to uncollapse the outliner when opening + the PDF. + +\change_unchanged \family sans Level \family default - you can specify what sectioning level should be displayed in the bookmarks + +\change_inserted -712698321 1644654838 +determines up to which level this uncollapsing is done. +\change_deleted -712698321 1644654687 +you can specify what sectioning level should be displayed in the bookmarks when opening the PDF. + +\change_unchanged For example level \begin_inset space ~ \end_inset @@ -36022,10 +36236,106 @@ Level \begin_inset space ~ \end_inset -1 will only display the sections. +1 will only display the sections +\change_inserted -712698321 1644654724 + (collapsing the rest) +\change_unchanged +. +\change_inserted -712698321 1644656154 + \end_layout \begin_layout Standard + +\change_inserted -712698321 1644657105 +In the +\family sans +Additional Options +\family default + dialog tab you can insert hyperref options which are not among the ones + described above as a comma-separated list (please refer to the hyperref + manual +\begin_inset CommandInset citation +LatexCommand cite +key "hyperref" +literal "true" + +\end_inset + + for a full list and documentation of possible options). + Note that these options will be passed to hyperref via +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout + +\change_inserted -712698321 1644656321 + +\backslash +hypersetup +\change_unchanged + +\end_layout + +\end_inset + +, not via the package options. + This will exclude some options that can only be specified via the latter. + If you need to use one of those options, you can set them by adding +\end_layout + +\begin_layout Quote + +\change_inserted -712698321 1644656496 + +\series bold +PackageOptions hyperref option1,option1 +\change_unchanged + +\end_layout + +\begin_layout Standard + +\change_inserted -712698321 1644656431 +in +\family sans +Document\SpecialChar menuseparator +Settings\SpecialChar menuseparator +Local Layout +\family default + (but only if hyperref is not loaded by your document class). +\change_unchanged + +\end_layout + +\begin_layout Standard + +\change_inserted -712698321 1644657160 +The +\family sans +Document Metadata +\family default + input widget allows you to insert PDF properties that are independent of + the hyperref package and rely on some (rather new) \SpecialChar LaTeX + core features. + This requires \SpecialChar LaTeX + version 06/2022 at least (with earlier versions, input is + simply ignored). + The widget expects a comma-separated list of key-value options (such as + +\series bold +pdfversion=1.7, lang=de-DE +\series default +). + At the point of writing this, the list of options is still rather small + and not very well documented, but it is expected that in the future, rather + fundamental PDF properties (such as structure tagging for accessibility + reasons and different PDF standards such as PDF/A) can be set this way. +\end_layout + +\begin_layout Standard + +\change_deleted -712698321 1644656978 PDF properties are also used in this document. When you look in its document settings, you can see that some additional @@ -36042,6 +36352,8 @@ literal "true" \end_inset . +\change_unchanged + \end_layout \begin_layout Section diff --git a/lib/doc/de/UserGuide.lyx b/lib/doc/de/UserGuide.lyx index 2c819dda5d..0f1c9b0944 100644 --- a/lib/doc/de/UserGuide.lyx +++ b/lib/doc/de/UserGuide.lyx @@ -1,5 +1,5 @@ #LyX 2.4 created this file. For more info see https://www.lyx.org/ -\lyxformat 608 +\lyxformat 609 \begin_document \begin_header \save_transient_properties true @@ -8752,10 +8752,12 @@ Unformatiert \end_layout \begin_layout Verbatim + Dies ist Unformatiert. \end_layout \begin_layout Verbatim + Die folgenden 2 Zeilen sind leer: \end_layout @@ -8768,6 +8770,7 @@ Die folgenden 2 Zeilen sind leer: \end_layout \begin_layout Verbatim + Fast alles ist in Unformatiert erlaubt:"%&$§#~'` \backslash }][{| @@ -8791,6 +8794,7 @@ Unformatiert \end_layout \begin_layout Verbatim* + Dies ist Unformatiert*. \end_layout @@ -33204,9 +33208,9 @@ Dokument-Einstellungen \family sans PDF-Eigenschaften \family default - spezielle Optionen für die PDF-Ausgabe eines Dokuments setzen. - Alle Optionen stammen vom \SpecialChar LaTeX --Paket + Spezifika für die PDF-Ausgabe eines Dokuments bestimmen. + Die meisten Spezifika werden mithilfe des \SpecialChar LaTeX +-Pakets \series bold hyperref \series default @@ -33221,18 +33225,29 @@ status collapsed \end_inset -. + gesetzt, das Sie durch anklicken von +\family sans +Hyperref-Unterstützung verwenden +\family default + zunächst aktivieren müssen (falls das Paket bereits durch die Dokumentklasse + oder ein anderes Paket geladen wurde, klicken Sie statt dessen +\family sans +Hyperref-Optionen anpassen +\family default +). \end_layout \begin_layout Standard \series bold -hyperref +Hyperref \series default - wird in der DVI- oder PDF-Ausgabe alle Querverweise verlinken, so dass - ein Leser, der die DVI- oder PDF-Ausgabe auf seinem PC liest, einen Querverweis - anklicken kann und so zur entsprechenden Stelle gelangt, wie es auch im - Internet passiert. + verlinkt unter anderem alle URLs und Querverweise in der PDF-Ausgabe, so + dass Leser:innen eine URL oder einen Querverweis anklicken und so zur entsprech +enden Webseite oder Stelle im Dokument gelangt können. + Weiterhin können Sie etwa PDF-Metadaten (wie Autor:in oder Titel des Dokuments) + eingeben oder festlegen, wie ein PDF-Reader die Datei öffnet. + \end_layout \begin_layout Standard @@ -33259,9 +33274,8 @@ automatisch eintragen \family default - angekreuzt, versucht \SpecialChar LyX -, diese Informationen aus dem Titel und dem Autor - des Dokuments zu gewinnen. + angekreuzt, versucht hyperref, diese Informationen aus dem Titel und den + Autorangaben des Dokuments zu gewinnen. Die Option \family sans Im @@ -33283,12 +33297,12 @@ Auf der Karteikarte \family sans Hyperlinks \family default - können Sie festlegen, wie die Querverweise aussehen sollen, und ob bibliografis -che Rückverweise angelegt werden sollen. -\end_layout - -\begin_layout Standard -Mit die Option + können Sie festlegen, wie Querverweise aussehen sollen, und ob bzw. + welche bibliografischen Rückverweise angelegt werden sollen. + Rückverweise sind Verweise, die am Ende eines Literatureintrags eingefügt + werden und die entweder auf Abschnitte, Seiten oder Folien verlinken, auf + denen ein entsprechender Eintrag zitiert wurde. + Mit die Option \family sans Links am Zeilenende umbrechen \family default @@ -33357,7 +33371,7 @@ grün \end_layout \begin_layout Standard -die aber im Feld +die aber in der Karteikarte \family sans Zusätzliche Optionen \family default @@ -33370,7 +33384,7 @@ B. in diesem Dokument mit den Optionen \end_layout -\begin_layout Standard +\begin_layout Quote \series bold linkcolor=black, citecolor=black, urlcolor=blue, filecolor=blue @@ -33380,53 +33394,40 @@ linkcolor=black, citecolor=black, urlcolor=blue, filecolor=blue getan. \end_layout -\begin_layout Standard -Wenn die Option -\family sans -Rückverweise -\family default - ausgewählt ist, erscheinen die Hyperlinks im Literaturverzeichnis hinter - den Einträgen, je nach Einstellung, als Nummer des Abschnitts, der Folie - oder Seite in/auf der sie referenziert sind. -\end_layout - \begin_layout Standard In der Karteikarte \family sans Lesezeichen \family default - können Sie festlegen, ob welche erzeugt und auch nummeriert werden sollen. - Das erleichtert es Lesern, durch die PDF-Ausgabe des Dokuments zu navigieren. + können Sie festlegen, ob eine Navigationsstruktur (die als einklappbare + hierarchische Liste von Kapiteln, Abschnitten usw. + im PDF-Reader angezeigt wird) angelegt werden soll. + Dies erleichtert es Leser:innen, durch die PDF-Ausgabe des Dokuments zu + navigieren. + Sie können festlegen, ob die Einträge dieser Liste, analog zu den Kapiteln + und Abschnitten, nummeriert werden soll oder nicht. Mit \family sans +Lesezeichen-Strukturbaum öffnen +\family default + können Sie den PDF-Reader instruieren, diese Navigationsstruktur beim öffnen + auszuklappen, mit +\family sans Ebene \family default - legen Sie fest, welche Lesezeichen angezeigt werden sollen. - 2 zum Beispiel zeigt die Lesezeichen aller Abschnitte und Unterabschnitte, - während 1 nur Abschnitte berücksichtigt. + legen Sie fest, bis zu welcher Ebene ausgeklappt werden soll. + 2 zum Beispiel öffnet die Lesezeichen aller Abschnitte und Unterabschnitte, + während 1 nur Abschnitte ausklappt. \end_layout \begin_layout Standard -Auch in diesem Handbuch werden PDF-Eigenschaften benutzt, wie Sie im Dialogfenst -er -\family sans -Dokument-Einstellungen -\family default - sehen können. - Dort sehen Sie auch, dass +In der Karteikarte \family sans -Zusätzliche -\begin_inset space \space{} -\end_inset - -Optionen +Zusätzliche Optionen \family default - benutzt werden. - Genaueres dazu finden Sie im -\series bold -hyperref -\series default --Handbuch + können Sie eine durch Kommata getrennte Liste von weiteren Hyperref-Optionen + eingeben, die oben nicht beschrieben sind (eine vollständige Liste und + Beschreibung finden Sie im Hyperref-Handbuch \begin_inset CommandInset citation LatexCommand cite key "hyperref" @@ -33434,7 +33435,63 @@ literal "true" \end_inset -. +). + Beachten Sie, dass diese Optionen über das Makro +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout + +\backslash +hypersetup +\end_layout + +\end_inset + + an Hyperref übergeben werden, nicht in Form von Paket-Optionen. + Das ist deshalb wichtig, weil manche Optionen nur in letzterer Form funktionier +en. + Wenn Sie eine von diesen brauchen, können Sie sie mittels +\end_layout + +\begin_layout Quote + +\series bold +PackageOptions hyperref option1,option1 +\end_layout + +\begin_layout Standard +in +\family sans +Dokument\SpecialChar menuseparator +Einstellungen\SpecialChar menuseparator +Lokales Format +\family default + übergeben (was aber nur funktioniert, wenn hyperref nicht von Ihrer Dokumentkla +sse geladen wird). +\end_layout + +\begin_layout Standard +Das Eingabefeld +\family sans +Metadaten des Dokuments +\family default + erlaubt es Ihnen, PDF-Eigenschaften unabhängig von hyperref festzulegen. + Dies greift auf eine Kernfunktion von \SpecialChar LaTeX + zurück, die allerdings erst seit + der Version 06/2022 verfügbar ist (wenn Sie eine ältere Version haben, + werden Eingaben in dieses Feld schlicht ignoriert). + Das Eingabefeld erwartet durch Kommata getrennte Schlüssel-Wert-Optionen + (wie +\series bold +pdfversion=1.7, lang=de-DE +\series default +). + Zum Zeitpunkt, als dies hier geschrieben wurde, ist die Liste möglicher + Optionen noch klein und schlecht dokumentiert. + Es ist aber zu erwarten, dass zukünftig sehr fundamentale PDF-Eigenschaften + (wie etwa strukturiertes Tagging für barrierefreie Dokumente oder verschiedene + PDF-Standards wie PDF/A) auf diese Weise eingestellt werden können. \end_layout \begin_layout Section diff --git a/lib/lyx2lyx/lyx_2_4.py b/lib/lyx2lyx/lyx_2_4.py index 3fed7eebd6..9dfaeaea47 100644 --- a/lib/lyx2lyx/lyx_2_4.py +++ b/lib/lyx2lyx/lyx_2_4.py @@ -27,11 +27,12 @@ from datetime import (datetime, date, time) # Uncomment only what you need to import, please. from parser_tools import (count_pars_in_inset, del_complete_lines, del_token, - find_end_of_inset, find_end_of_layout, find_token, find_token_backwards, - find_token_exact, find_re, get_bool_value, get_containing_inset, - get_containing_layout, get_option_value, get_value, get_quoted_value) + find_end_of, find_end_of_inset, find_end_of_layout, find_token, + find_token_backwards, find_token_exact, find_re, get_bool_value, + get_containing_inset, get_containing_layout, get_option_value, get_value, + get_quoted_value) # del_value, -# find_complete_lines, find_end_of, +# find_complete_lines, # find_re, find_substring, # is_in_inset, set_bool_value # find_tokens, check_token @@ -4413,6 +4414,19 @@ def revert_docbook_mathml_prefix(document): return del document.header[i] +def revert_document_metadata(document): + """Revert document metadata""" + i = 0 + while True: + i = find_token(document.header, "\\begin_metadata", i) + if i == -1: + return + j = find_end_of(document.header, i, "\\begin_metadata", "\\end_metadata") + if j == -1: + # this should not happen + break + document.header[i : j + 1] = [] + ## # Conversion hub # @@ -4482,10 +4496,12 @@ convert = [ [605, [convert_vcolumns2]], [606, [convert_koma_frontispiece]], [607, []], - [608, []] + [608, []], + [609, []] ] -revert = [[607, [revert_docbook_mathml_prefix]], +revert = [[608, [revert_document_metadata]], + [607, [revert_docbook_mathml_prefix]], [606, [revert_spellchecker_ignore]], [605, [revert_koma_frontispiece]], [604, [revert_vcolumns2]], diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp index fc559a4848..95aa9136d2 100644 --- a/src/BufferParams.cpp +++ b/src/BufferParams.cpp @@ -807,6 +807,8 @@ string BufferParams::readToken(Lexer & lex, string const & token, origin.replace(0, sysdirprefix.length() - 1, package().system_support().absFileName()); } + } else if (token == "\\begin_metadata") { + readDocumentMetadata(lex); } else if (token == "\\begin_preamble") { readPreamble(lex); } else if (token == "\\begin_local_layout") { @@ -1255,6 +1257,15 @@ void BufferParams::writeFile(ostream & os, Buffer const * buf) const baseClass()->name()), "layout")) << '\n'; + // then document metadata + if (!document_metadata.empty()) { + // remove '\n' from the end of document_metadata + docstring const tmpmd = rtrim(document_metadata, "\n"); + os << "\\begin_metadata\n" + << to_utf8(tmpmd) + << "\n\\end_metadata\n"; + } + // then the preamble if (!preamble.empty()) { // remove '\n' from the end of preamble @@ -1688,6 +1699,56 @@ void BufferParams::validate(LaTeXFeatures & features) const bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, FileName const & filepath) const { + // DocumentMetadata must come before anything else + if (features.isAvailable("LaTeX-2022/06/01") + && !containsOnly(document_metadata, " \n\t")) { + // Check if the user preamble contains uncodable glyphs + odocstringstream doc_metadata; + docstring uncodable_glyphs; + Encoding const * const enc = features.runparams().encoding; + if (enc) { + for (char_type c : document_metadata) { + if (!enc->encodable(c)) { + docstring const glyph(1, c); + LYXERR0("Uncodable character '" + << glyph + << "' in document metadata!"); + uncodable_glyphs += glyph; + if (features.runparams().dryrun) { + doc_metadata << "<" << _("LyX Warning: ") + << _("uncodable character") << " '"; + doc_metadata.put(c); + doc_metadata << "'>"; + } + } else + doc_metadata.put(c); + } + } else + doc_metadata << document_metadata; + + // On BUFFER_VIEW|UPDATE, warn user if we found uncodable glyphs + if (!features.runparams().dryrun && !uncodable_glyphs.empty()) { + frontend::Alert::warning( + _("Uncodable character in document metadata"), + support::bformat( + _("The metadata of your document contains glyphs " + "that are unknown in the current document encoding " + "(namely %1$s).\nThese glyphs are omitted " + " from the output, which may result in " + "incomplete output." + "\n\nPlease select an appropriate " + "document encoding\n" + "(such as utf8) or change the " + "preamble code accordingly."), + uncodable_glyphs)); + } + if (!doc_metadata.str().empty()) { + os << "\\DocumentMetadata{\n" + << doc_metadata.str() + << "}\n"; + } + } + // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf // !! To use the Fix-cm package, load it before \documentclass, and use the command // \RequirePackage to do so, rather than the normal \usepackage @@ -2881,6 +2942,16 @@ void BufferParams::readPreamble(Lexer & lex) } +void BufferParams::readDocumentMetadata(Lexer & lex) +{ + if (lex.getString() != "\\begin_metadata") + lyxerr << "Error (BufferParams::readDocumentMetadata):" + "consistency check failed." << endl; + + document_metadata = lex.getLongString(from_ascii("\\end_metadata")); +} + + void BufferParams::readLocalLayout(Lexer & lex, bool forced) { string const expected = forced ? "\\begin_forced_local_layout" : diff --git a/src/BufferParams.h b/src/BufferParams.h index 38649e7c2f..890d8843a7 100644 --- a/src/BufferParams.h +++ b/src/BufferParams.h @@ -367,6 +367,8 @@ public: std::string origin; /// docstring preamble; + /// DocumentMetadata as introduced by LaTeX 2022/06 + docstring document_metadata; /// std::string options; /// use the class options defined in the layout? @@ -620,6 +622,8 @@ private: /// void readPreamble(Lexer &); /// + void readDocumentMetadata(Lexer &); + /// void readLocalLayout(Lexer &, bool); /// void readLanguage(Lexer &); diff --git a/src/frontends/qt/GuiDocument.cpp b/src/frontends/qt/GuiDocument.cpp index 812b8e2cbe..714953c0b6 100644 --- a/src/frontends/qt/GuiDocument.cpp +++ b/src/frontends/qt/GuiDocument.cpp @@ -1722,7 +1722,9 @@ GuiDocument::GuiDocument(GuiView & lv) this, SLOT(change_adaptor())); connect(pdfSupportModule->fullscreenCB, SIGNAL(toggled(bool)), this, SLOT(change_adaptor())); - connect(pdfSupportModule->optionsLE, SIGNAL(textChanged(QString)), + connect(pdfSupportModule->optionsTE, SIGNAL(textChanged()), + this, SLOT(change_adaptor())); + connect(pdfSupportModule->metadataTE, SIGNAL(textChanged()), this, SLOT(change_adaptor())); pdfSupportModule->titleLE->setValidator(new NoNewLineValidator( @@ -1733,8 +1735,8 @@ GuiDocument::GuiDocument(GuiView & lv) pdfSupportModule->subjectLE)); pdfSupportModule->keywordsLE->setValidator(new NoNewLineValidator( pdfSupportModule->keywordsLE)); - pdfSupportModule->optionsLE->setValidator(new NoNewLineValidator( - pdfSupportModule->optionsLE)); + (void) new LaTeXHighlighter(pdfSupportModule->optionsTE->document(), true, true); + (void) new LaTeXHighlighter(pdfSupportModule->metadataTE->document(), true, true); for (int i = 0; backref_opts[i][0]; ++i) pdfSupportModule->backrefCO->addItem(qt_(backref_opts_gui[i])); @@ -3911,7 +3913,14 @@ void GuiDocument::applyView() else pdf.pagemode.clear(); pdf.quoted_options = pdf.quoted_options_check( - fromqstr(pdfSupportModule->optionsLE->text())); + fromqstr(pdfSupportModule->optionsTE->toPlainText())); +#if QT_VERSION < 0x060000 + bp_.document_metadata = qstring_to_ucs4(pdfSupportModule->metadataTE->toPlainText() + .trimmed().replace(QRegExp("\n+"), "\n")); +#else + bp_.document_metadata = qstring_to_ucs4(pdfSupportModule->metadataTE->toPlainText() + .trimmed().replace(QRegularExpression("\n+"), "\n")); +#endif // change tracking bp_.track_changes = changesModule->trackChangesCB->isChecked(); @@ -4519,9 +4528,12 @@ void GuiDocument::paramsToDialog() pdfSupportModule->fullscreenCB->setChecked (pdf.pagemode == pdf.pagemode_fullscreen); - pdfSupportModule->optionsLE->setText( + pdfSupportModule->optionsTE->setPlainText( toqstr(pdf.quoted_options)); + pdfSupportModule->metadataTE->setPlainText( + toqstr(bp_.document_metadata)); + // change tracking changesModule->trackChangesCB->setChecked(bp_.track_changes); changesModule->outputChangesCB->setChecked(bp_.output_changes); diff --git a/src/frontends/qt/LaTeXHighlighter.cpp b/src/frontends/qt/LaTeXHighlighter.cpp index f33db5dd59..80e7a09cbd 100644 --- a/src/frontends/qt/LaTeXHighlighter.cpp +++ b/src/frontends/qt/LaTeXHighlighter.cpp @@ -20,8 +20,8 @@ namespace lyx { namespace frontend { -LaTeXHighlighter::LaTeXHighlighter(QTextDocument * parent, bool at_letter) - : QSyntaxHighlighter(parent), at_letter_(at_letter) +LaTeXHighlighter::LaTeXHighlighter(QTextDocument * parent, bool at_letter, bool keyval) + : QSyntaxHighlighter(parent), at_letter_(at_letter), keyval_(keyval) { auto blend = [](QColor color1, QColor color2) { int r = 0.5 * (color1.red() + color2.red()); @@ -38,12 +38,32 @@ LaTeXHighlighter::LaTeXHighlighter(QTextDocument * parent, bool at_letter) mathFormat.setForeground(blend(Qt::red, text_color)); warningFormat.setForeground(Qt::red); warningFormat.setFontWeight(QFont::Bold); + keyFormat.setForeground(blend(Qt::darkRed, text_color)); + keyFormat.setFontWeight(QFont::Bold); + valFormat.setForeground(blend(Qt::darkGreen, text_color)); } void LaTeXHighlighter::highlightBlock(QString const & text) { #if QT_VERSION < 0x060000 + // keyval + if (keyval_) { + // Highlight key-val options. Used in some option widgets. + static const QRegExp exprKeyvalkey("[^=,]+"); + static const QRegExp exprKeyvalval("[^,]+"); + int kvindex = exprKeyvalkey.indexIn(text); + while (kvindex >= 0) { + int length = exprKeyvalkey.matchedLength(); + setFormat(kvindex, length, keyFormat); + int kvvindex = exprKeyvalval.indexIn(text, kvindex + length); + if (kvvindex > 0) { + length += exprKeyvalval.matchedLength(); + setFormat(kvvindex, length, valFormat); + } + kvindex = exprKeyvalkey.indexIn(text, kvindex + length); + } + } // $ $ static const QRegExp exprMath("\\$[^\\$]*\\$"); int index = exprMath.indexIn(text); @@ -129,6 +149,27 @@ void LaTeXHighlighter::highlightBlock(QString const & text) index = exprWarning.indexIn(text, index + length); } #else + // keyval + if (keyval_) { + // Highlight key-val options. Used in some option widgets. + static const QRegularExpression exprKeyvalkey("[^=,]+"); + static const QRegularExpression exprKeyvalval("[^,]+"); + QRegularExpressionMatch matchkey = exprKeyvalkey.match(text); + int kvindex = matchkey.capturedStart(0); + while (kvindex >= 0) { + int length = matchkey.capturedLength(0); + setFormat(kvindex, length, keyFormat); + QRegularExpressionMatch matchval = + exprKeyvalval.match(text, kvindex + length); + int kvvindex = matchval.capturedStart(0); + if (kvvindex > 0) { + length += matchval.capturedLength(0); + setFormat(kvvindex, length, valFormat); + } + matchkey = exprKeyvalkey.match(text, kvindex + length); + kvindex = matchkey.capturedStart(0); + } + } // $ $ static const QRegularExpression exprMath("\\$[^\\$]*\\$"); QRegularExpressionMatch match = exprMath.match(text); diff --git a/src/frontends/qt/LaTeXHighlighter.h b/src/frontends/qt/LaTeXHighlighter.h index 47df8b9ad2..7a80d1fa26 100644 --- a/src/frontends/qt/LaTeXHighlighter.h +++ b/src/frontends/qt/LaTeXHighlighter.h @@ -25,7 +25,9 @@ namespace frontend { class LaTeXHighlighter : public QSyntaxHighlighter { public: - explicit LaTeXHighlighter(QTextDocument * parent, bool at_letter = false); + explicit LaTeXHighlighter(QTextDocument * parent, + bool at_letter = false, + bool keyval = false); protected: void highlightBlock(QString const & text) override; @@ -35,8 +37,12 @@ private: QTextCharFormat keywordFormat; QTextCharFormat mathFormat; QTextCharFormat warningFormat; + QTextCharFormat keyFormat; + QTextCharFormat valFormat; // is at a letter? (as in the preamble) bool const at_letter_; + // highlight keyval options? + bool const keyval_; }; } // namespace frontend diff --git a/src/frontends/qt/ui/PDFSupportUi.ui b/src/frontends/qt/ui/PDFSupportUi.ui index 1e45f211bc..51a144c7f8 100644 --- a/src/frontends/qt/ui/PDFSupportUi.ui +++ b/src/frontends/qt/ui/PDFSupportUi.ui @@ -6,29 +6,14 @@ 0 0 - 437 - 488 + 485 + 530 Form - - - 9 - - - 9 - - - 9 - - - 9 - - - 6 - + @@ -465,58 +450,57 @@ + + + Additional O&ptions + + + + + + Document metadata and PDF settings (as specified in LaTeX 06/2022 and later) + + + Hyperse&tup + + + + + + false + + + + + + + + - - - - Additional O&ptions - - - true - - - false - - + + + + + + + Document metadata and PDF settings (as specified in LaTeX 06/2022 and later) + + + Document &Metadata + + + + + false - - - 9 - - - 9 - - - 9 - - - 9 - - - 6 - - - - - - 0 - 0 - - - - e.g.: pdfstartview=XYZ, plainpages=false, pdfpagelabels - - - - - + Qt::Vertical diff --git a/src/tex2lyx/Preamble.cpp b/src/tex2lyx/Preamble.cpp index e14176e874..3588086cfa 100644 --- a/src/tex2lyx/Preamble.cpp +++ b/src/tex2lyx/Preamble.cpp @@ -1950,6 +1950,11 @@ bool Preamble::writeLyXHeader(ostream & os, bool subdoc, string const & outfiled << "\\save_transient_properties " << h_save_transient_properties << "\n" << "\\origin " << origin << "\n" << "\\textclass " << h_textclass << "\n"; + if (!h_doc_metadata.empty()) { + os << "\\begin_metadata\n" + << h_doc_metadata + << "\n\\end_metadata\n"; + } string const raw = subdoc ? empty_string() : h_preamble.str(); if (!raw.empty()) { os << "\\begin_preamble\n"; @@ -2793,6 +2798,11 @@ void Preamble::parse(Parser & p, string const & forceclass, continue; } + if (t.cs() == "DocumentMetadata") { + h_doc_metadata = trimSpaceAndEol(p.getArg('{', '}')); + continue; + } + if (t.cs() == "usepackage") { string const options = p.getArg('[', ']'); string const name = p.getArg('{', '}'); diff --git a/src/tex2lyx/Preamble.h b/src/tex2lyx/Preamble.h index 8bdb358112..1a03ae3406 100644 --- a/src/tex2lyx/Preamble.h +++ b/src/tex2lyx/Preamble.h @@ -148,6 +148,7 @@ private: int index_number; std::ostringstream h_preamble; + std::string h_doc_metadata; std::string h_backgroundcolor; std::string h_multibib; std::string h_biblio_style; diff --git a/src/version.h b/src/version.h index aba9db0b70..bdf6ceed49 100644 --- a/src/version.h +++ b/src/version.h @@ -32,8 +32,8 @@ extern char const * const lyx_version_info; // Do not remove the comment below, so we get merge conflict in // independent branches. Instead add your own. -#define LYX_FORMAT_LYX 608 // tcuvelier: \\docbook_mathml_prefix -#define LYX_FORMAT_TEX2LYX 608 +#define LYX_FORMAT_LYX 609 // spitz: document metadata +#define LYX_FORMAT_TEX2LYX 609 #if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX #ifndef _MSC_VER -- 2.39.2