From 3cc5e4cc7a18c2bed102629c5dce71c8247d03d9 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 21 Oct 2024 18:54:19 +0200 Subject: [PATCH 01/10] Handle text justify in Tokenizer instead --- novelwriter/formats/todocx.py | 11 +- novelwriter/formats/tohtml.py | 2 +- novelwriter/formats/tokenizer.py | 10 +- novelwriter/formats/toodt.py | 13 +- novelwriter/formats/toqdoc.py | 2 +- .../mBuildDocBuild_HTML5_Lorem_Ipsum.htm | 84 ++++----- .../mBuildDocBuild_HTML5_Lorem_Ipsum.json | 88 ++++----- ...uildDocBuild_OpenDocument_Lorem_Ipsum.fodt | 173 +++++++++--------- tests/test_formats/test_fmt_tohtml.py | 4 - tests/test_formats/test_fmt_toodt.py | 25 +-- 10 files changed, 194 insertions(+), 218 deletions(-) diff --git a/novelwriter/formats/todocx.py b/novelwriter/formats/todocx.py index e417d0ae6..274a218bc 100644 --- a/novelwriter/formats/todocx.py +++ b/novelwriter/formats/todocx.py @@ -255,8 +255,6 @@ def doConvert(self) -> None: # Process Text Types if tType == self.T_TEXT: - if self._doJustify and "\n" in tText: - par.overrideJustify(self._defaultAlign) self._processFragments(par, S_NORM, tText, tFormat) elif tType == self.T_TITLE: @@ -544,7 +542,6 @@ def _generateStyles(self) -> None: fSz2 = (nwStyles.H_SIZES[2] * fSz) if hScale else fSz fSz3 = (nwStyles.H_SIZES[3] * fSz) if hScale else fSz fSz4 = (nwStyles.H_SIZES[4] * fSz) if hScale else fSz - align = "both" if self._doJustify else "left" # Add Normal Style styles.append(DocXParStyle( @@ -556,7 +553,7 @@ def _generateStyles(self) -> None: after=fSz * self._marginText[1], line=fSz * self._lineHeight, indentFirst=fSz * self._firstWidth, - align=align, + align=self._defaultAlign, )) # Add Title @@ -1085,12 +1082,6 @@ def setPageBreakAfter(self, state: bool) -> None: # Methods ## - def overrideJustify(self, default: str) -> None: - """Override inherited justify setting if None is set.""" - if self._textAlign is None: - self.setAlignment(default) - return - def addContent(self, run: ET.Element) -> None: """Add a run segment to the paragraph.""" self._content.append(run) diff --git a/novelwriter/formats/tohtml.py b/novelwriter/formats/tohtml.py index 54827a2a1..9012e24cf 100644 --- a/novelwriter/formats/tohtml.py +++ b/novelwriter/formats/tohtml.py @@ -372,7 +372,7 @@ def getStyleSheet(self) -> list[str]: "margin-top: {2:.2f}em; margin-bottom: {3:.2f}em;" "}}" ).format( - "justify" if self._doJustify else self._defaultAlign, + self._defaultAlign, round(100 * self._lineHeight), mScale * self._marginText[0], mScale * self._marginText[1], diff --git a/novelwriter/formats/tokenizer.py b/novelwriter/formats/tokenizer.py index 04ce876af..a7af39a91 100644 --- a/novelwriter/formats/tokenizer.py +++ b/novelwriter/formats/tokenizer.py @@ -622,6 +622,9 @@ def tokenizeText(self) -> None: if aLine.startswith("%~"): continue + if self._doJustify and not sAlign & self.M_ALIGNED: + sAlign |= self.A_JUSTIFY + cStyle, cKey, cText, _, _ = processComment(aLine) if cStyle == nwComment.SYNOPSIS: tLine, tFmt = self._extractFormats(cText) @@ -935,8 +938,11 @@ def tokenizeText(self) -> None: cStyle |= self.A_IND_T if nLines == 1: - # The paragraph contains a single line, so we just - # save that directly to the token list + # The paragraph contains a single line, so we just save + # that directly to the token list. If justify is + # enabled, and there is no alignment, we apply it. + if self._doJustify and not cStyle & self.M_ALIGNED: + cStyle |= self.A_JUSTIFY self._tokens.append(( self.T_TEXT, pLines[0][1], pLines[0][2], pLines[0][3], cStyle )) diff --git a/novelwriter/formats/toodt.py b/novelwriter/formats/toodt.py index fdacf287e..d39d5e12c 100644 --- a/novelwriter/formats/toodt.py +++ b/novelwriter/formats/toodt.py @@ -183,7 +183,6 @@ def __init__(self, project: NWProject, isFlat: bool) -> None: self._fLineHeight = "115%" self._fBlockIndent = "1.693cm" self._fTextIndent = "0.499cm" - self._textAlign = "left" self._dLanguage = "en" self._dCountry = "GB" @@ -327,7 +326,6 @@ def initDocument(self) -> None: self._fLineHeight = f"{round(100 * self._lineHeight):d}%" self._fBlockIndent = self._emToCm(self._blockIndent) self._fTextIndent = self._emToCm(self._firstWidth) - self._textAlign = "justify" if self._doJustify else self._defaultAlign # Clear Errors self._errData = [] @@ -457,9 +455,6 @@ def doConvert(self) -> None: # Process Text Types if tType == self.T_TEXT: - if self._doJustify and "\n" in tText: - oStyle.overrideJustify(self._defaultAlign) - # Text indentation is processed here because there is a # dedicated pre-defined style for it if tStyle & self.A_IND_T: @@ -906,7 +901,7 @@ def _useableStyles(self) -> None: style.setMarginTop(self._mTopText) style.setMarginBottom(self._mBotText) style.setLineHeight(self._fLineHeight) - style.setTextAlign(self._textAlign) + style.setTextAlign(self._defaultAlign) style.setFontName(self._fontFamily) style.setFontFamily(self._fontFamily) style.setFontSize(self._fSizeText) @@ -1316,12 +1311,6 @@ def setOpacity(self, value: str | None) -> None: # Methods ## - def overrideJustify(self, default: str) -> None: - """Override inherited justify setting if None is set.""" - if self._pAttr["text-align"][1] is None: - self.setTextAlign(default) - return - def checkNew(self, style: ODTParagraphStyle) -> bool: """Check if there are new settings in style that differ from those in this object. Unset styles are ignored as they can be diff --git a/novelwriter/formats/toqdoc.py b/novelwriter/formats/toqdoc.py index 627b47223..ef4508f95 100644 --- a/novelwriter/formats/toqdoc.py +++ b/novelwriter/formats/toqdoc.py @@ -170,7 +170,7 @@ def initDocument(self) -> None: self._blockFmt = QTextBlockFormat() self._blockFmt.setTopMargin(self._mText[0]) self._blockFmt.setBottomMargin(self._mText[1]) - self._blockFmt.setAlignment(QtAlignJustify if self._doJustify else QtAlignAbsolute) + self._blockFmt.setAlignment(QtAlignAbsolute) self._blockFmt.setLineHeight( 100*self._lineHeight, QTextBlockFormat.LineHeightTypes.ProportionalHeight ) diff --git a/tests/reference/mBuildDocBuild_HTML5_Lorem_Ipsum.htm b/tests/reference/mBuildDocBuild_HTML5_Lorem_Ipsum.htm index 565158a19..794071e85 100644 --- a/tests/reference/mBuildDocBuild_HTML5_Lorem_Ipsum.htm +++ b/tests/reference/mBuildDocBuild_HTML5_Lorem_Ipsum.htm @@ -6,7 +6,7 @@
@@ -28,11 +23,11 @@

Lorem Ipsum

By lipsum.com

“Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit…”

“There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain…”

-

Comment: Exctracted from the lipsum.com website.

+

Comment: Exctracted from the lipsum.com website.

Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.

The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.

Prologue

-

Synopsis: Explanation from the lipsum.com website.

+

Synopsis: Explanation from the lipsum.com website.

Lorem Ipsum is simply dummy text1 of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Part: Act One

“Fusce maximus felis libero”

@@ -40,13 +35,13 @@

Chapter: Chapter One

Point of View: Bod

Plot: Main

Locations: Europe

-

Synopsis: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam.

+

Synopsis: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam. Praesent magna nunc, lacinia sit amet quam eget, aliquet ultrices justo. Morbi ornare enim et lorem rutrum finibus ut eu dolor. Aliquam a orci odio. Ut ultrices sem quis massa placerat, eget mollis nisl cursus. Cras vel sagittis justo. Ut non ultricies leo. Maecenas rutrum velit in est varius, et egestas massa pulvinar.

Scene: Scene One

Point of View: Bod

Plot: Main

Locations: Europe

-

Synopsis: Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur.

+

Synopsis: Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur.

Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur. Donec quis ante nunc. Mauris ut leo ipsum. Vestibulum est neque, hendrerit nec neque a, ullamcorper lobortis tellus. Fusce sollicitudin purus quis congue bibendum. Aliquam condimentum ipsum tristique blandit tristique. Donec pulvinar neque ac suscipit malesuada.

Aliquam ut nisl arcu. Ut ultricies, lorem dignissim rutrum convallis, risus orci tempus lectus, congue feugiat sem lectus vitae odio. Duis sit amet justo finibus, hendrerit nulla at, ullamcorper enim. Praesent vel tellus sit amet tellus vulputate bibendum. Morbi eleifend sagittis sem, ac volutpat ante congue non. In hac habitasse platea dictumst. Morbi lobortis fermentum elit, dignissim sagittis ligula volutpat lacinia. Vestibulum eu interdum odio. Integer ac purus commodo metus congue tempor non at urna. Sed eget tortor vel quam viverra egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec non convallis mauris, ac feugiat ex.

Section: Scene One, Section Two

@@ -56,7 +51,7 @@

Scene: Scene Two

Point of View: Bod

Plot: Main

Locations: Europe

-

Synopsis: Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci.

+

Synopsis: Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci.

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci. Vestibulum facilisis bibendum aliquam. Aliquam posuere, turpis ac bibendum varius, sem tellus venenatis risus, in elementum massa enim ac lorem. Integer in sem ac diam blandit ultricies ut in nulla. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam sit amet erat est. Curabitur vitae cursus justo, sit amet placerat dolor. Vivamus eu felis hendrerit, tincidunt massa rutrum, maximus arcu. Pellentesque commodo justo odio, vel rutrum nulla tincidunt eu. Integer non neque condimentum, convallis diam non, varius ligula. Aliquam eget sapien mauris. Aenean pharetra nunc nisi, vel maximus ante tristique sit amet. Aliquam risus metus, interdum non odio eu, consectetur lacinia sapien.

Proin vitae gravida nisl. Integer viverra orci turpis, sit amet pretium ligula facilisis consequat. Nulla interdum commodo metus, mollis consequat dui tincidunt et. Proin consequat bibendum justo id commodo. Fusce fermentum nunc turpis, eu vestibulum risus feugiat ut. Sed scelerisque vel ligula ut interdum. Suspendisse ac blandit ligula, sagittis fringilla dolor. In tincidunt convallis diam et ornare. Aenean id dignissim est, ut rhoncus quam. Donec vitae nisl velit. In convallis nibh ut augue dignissim, eu elementum quam cursus. Phasellus in lectus lorem. Curabitur in pellentesque nisi, at gravida sapien. Sed cursus justo volutpat lacus placerat, sit amet dignissim turpis commodo. Aliquam vitae orci eget nulla posuere condimentum in ut felis.

Nulla accumsan ante in pulvinar efficitur. Nulla non velit quis urna hendrerit bibendum. Suspendisse ultrices ante eu justo malesuada, sed fermentum enim rutrum. Nunc fermentum pharetra felis, vitae sollicitudin quam rutrum porta. Aliquam fringilla velit a mi laoreet, et luctus est rutrum. In gravida non ipsum sit amet tempus. Curabitur et eleifend purus. Nulla facilisi.

@@ -65,7 +60,7 @@

Section: Scene Two, Section Two

Vivamus ut venenatis lectus. Phasellus nec elit id sem dictum ornare. Quisque feugiat, diam eget sagittis ultricies, orci turpis efficitur nisi, et fringilla justo odio nec nibh. In hac habitasse platea dictumst. Sed tempus bibendum feugiat. Etiam luctus mauris arcu, non interdum ipsum ultrices id. Vivamus blandit urna sit amet scelerisque vulputate. Quisque in metus eget massa rutrum dictum sit amet sed nulla. Vivamus vel efficitur dolor.

Ut et consequat enim, quis ornare nibh. In lectus neque, mollis et suscipit et, vestibulum vitae augue. Praesent id ante sit amet odio venenatis placerat a at erat. Sed sed metus sed nisi dictum varius. Integer tincidunt fermentum purus ac porta. Fusce porttitor non risus eget tristique. Donec augue nunc, maximus at fermentum vel, varius et neque. Ut sed consectetur mauris. Quisque ipsum enim, porttitor vitae imperdiet sit amet, tempor et mauris. Aliquam malesuada tincidunt lectus quis blandit. Sed commodo orci felis, quis ultrices tellus facilisis sed. Nunc vel varius est. Duis ullamcorper eu metus in pulvinar. Morbi at sapien dictum, rutrum mauris eget, interdum tellus.

Why do we use it?

-

Comment: Exctracted from the lipsum.com website.

+

Comment: Exctracted from the lipsum.com website.

        It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.

        The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English.

        Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).

@@ -73,13 +68,13 @@

Chapter: Chapter Two

Point of View: Bod

Plot: Main

Locations: Europe

-

Synopsis: Curabitur a elit posuere, varius ex et, convallis neque. Phasellus sagittis pharetra sem vitae dapibus. Curabitur varius lorem non pulvinar congue.

+

Synopsis: Curabitur a elit posuere, varius ex et, convallis neque. Phasellus sagittis pharetra sem vitae dapibus. Curabitur varius lorem non pulvinar congue.

Curabitur a elit posuere, varius ex et, convallis neque. Phasellus sagittis pharetra sem vitae dapibus. Curabitur varius lorem non pulvinar congue. Vestibulum pharetra fermentum leo, sed faucibus eros placerat quis. In hac habitasse platea dictumst. Donec metus massa, rutrum quis consequat et, tincidunt ac felis. Duis mollis metus ac nunc tincidunt blandit. Ut aliquet velit eu odio pharetra condimentum. Integer rutrum lacus orci, id venenatis libero accumsan at.

Scene: Scene Three

Point of View: Bod

Plot: Main

Locations: Europe

-

Synopsis: Aenean ut libero ut lectus porttitor rhoncus vel et massa. Nam pretium, nibh et varius vehicula, urna metus blandit eros, euismod pharetra diam diam et libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.

+

Synopsis: Aenean ut libero ut lectus porttitor rhoncus vel et massa. Nam pretium, nibh et varius vehicula, urna metus blandit eros, euismod pharetra diam diam et libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.

Aenean ut libero ut lectus porttitor rhoncus vel et massa. Nam pretium, nibh et varius vehicula, urna metus blandit eros, euismod pharetra diam diam et libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean tincidunt lacus vitae nibh elementum eleifend. Sed rutrum condimentum sem quis blandit. Duis imperdiet libero metus, quis convallis quam faucibus a. Nulla ligula est, semper quis sollicitudin et, pretium id justo. Curabitur pharetra risus eget consectetur commodo. Duis mattis arcu non est condimentum, id venenatis risus volutpat. Pellentesque aliquet mauris non mauris porttitor ultrices. Phasellus ut vestibulum mi. Suspendisse malesuada metus lorem, a malesuada orci rhoncus a. Praesent euismod convallis ante, lacinia tincidunt ex egestas id. Praesent sit amet efficitur sapien. Morbi tincidunt volutpat nunc sed dictum. Aliquam ultrices metus id fermentum lobortis.

Pellentesque id sagittis dui. Praesent ut nisi sit amet libero euismod ornare. Vestibulum vehicula, lorem eget aliquet imperdiet, eros nulla iaculis mi, vel bibendum est dui sed orci. Nullam vitae lorem rutrum, euismod lacus id, ullamcorper lectus. Duis nec commodo mi, a fringilla diam. Vestibulum molestie nibh tristique, viverra augue non, aliquet metus. Phasellus a tellus ac nisl tempor aliquet. Nulla vitae sapien rutrum augue ornare ultrices a quis nisi. Sed pulvinar tincidunt ex. Fusce vel sem vitae ante pellentesque lobortis.

Maecenas ullamcorper lacus nec turpis finibus aliquet eget rutrum augue. Integer lorem erat, faucibus non lacus lacinia, pulvinar egestas felis. Proin rutrum nunc eget nulla varius, id blandit mauris tincidunt. Donec sit amet ullamcorper nisi, ut efficitur mi. Aliquam aliquet, nulla eget rhoncus tristique, justo lorem consectetur dui, id ornare leo odio sed tellus. Curabitur interdum velit a turpis condimentum venenatis. Nunc rhoncus sem ac augue auctor, nec malesuada ex fringilla. Vestibulum egestas diam sed leo consectetur vulputate quis eget enim. Nam tincidunt metus sit amet maximus ullamcorper. Sed placerat velit vitae massa efficitur viverra. Etiam eleifend dignissim ante, sed luctus nisl tristique a. In vestibulum pharetra dolor in molestie. Vivamus auctor massa ac magna imperdiet, sit amet iaculis turpis finibus.

@@ -88,7 +83,7 @@

Scene: Scene Four

Point of View: Bod

Plot: Main

Locations: Europe

-

Synopsis: Nam tempor blandit magna laoreet aliquet. Vestibulum auctor posuere leo, ac gravida nisi rhoncus varius. Aenean posuere dolor vitae condimentum volutpat. Donec egestas volutpat risus, quis luctus justo.

+

Synopsis: Nam tempor blandit magna laoreet aliquet. Vestibulum auctor posuere leo, ac gravida nisi rhoncus varius. Aenean posuere dolor vitae condimentum volutpat. Donec egestas volutpat risus, quis luctus justo.

Nam tempor blandit magna laoreet aliquet. Vestibulum auctor posuere leo, ac gravida nisi rhoncus varius. Aenean posuere dolor vitae condimentum volutpat. Donec egestas volutpat risus, quis luctus justo. Nullam viverra dui et auctor pretium. Ut ullamcorper velit urna, sed imperdiet massa convallis a. Suspendisse efficitur, ipsum nec cursus pulvinar, eros urna posuere diam, nec elementum mi felis vitae sapien.

Duis efficitur metus pulvinar, molestie magna eget, feugiat dui. Fusce convallis vehicula ipsum convallis blandit. Duis eros risus, malesuada eu imperdiet in, hendrerit ac metus. Vestibulum id justo gravida, dignissim nibh non, iaculis diam. Fusce accumsan est ut massa porta ultricies. Nulla vitae justo in tortor laoreet mollis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin eu libero justo. Vivamus aliquet placerat est, et auctor eros posuere venenatis. Nunc quam diam, tincidunt ac aliquet in, fermentum sit amet lectus. Proin commodo tincidunt blandit. Quisque erat arcu, semper nec dui non, consectetur gravida ipsum. Nullam pretium consectetur elit at condimentum.

Etiam sagittis, erat vitae accumsan tempor, neque augue scelerisque nulla, ut ultrices justo urna sit amet augue. Interdum et malesuada fames ac ante ipsum primis in faucibus. Aenean at pulvinar tortor. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Cras vel porta quam. Nullam eu mauris mollis, vehicula justo vel, placerat sapien. Phasellus viverra elit et vestibulum pharetra. Vestibulum commodo fermentum leo, eu porta nisi aliquam eget. Nulla tempus porttitor nisi nec mollis. Nam non mollis turpis. Nam finibus leo a bibendum tincidunt. Donec commodo velit magna, ac semper sapien mattis id. Proin sem velit, lobortis quis ultricies id, pharetra et lectus. Vestibulum condimentum neque vitae mi dapibus mollis. Mauris luctus vel sapien vitae hendrerit.

@@ -99,7 +94,7 @@

Scene: Scene Five

Point of View: Bod

Plot: Main

Locations: Europe

-

Synopsis: Praesent eget est porta, dictum ante in, egestas risus. Mauris risus mauris, consequat aliquam mauris et, feugiat iaculis ipsum. Aliquam arcu ipsum, fermentum ut arcu sed, lobortis euismod sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.

+

Synopsis: Praesent eget est porta, dictum ante in, egestas risus. Mauris risus mauris, consequat aliquam mauris et, feugiat iaculis ipsum. Aliquam arcu ipsum, fermentum ut arcu sed, lobortis euismod sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.

Praesent eget est porta, dictum ante in, egestas risus. Mauris risus mauris, consequat aliquam mauris et, feugiat iaculis ipsum. Aliquam arcu ipsum, fermentum ut arcu sed, lobortis euismod sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In sed felis auctor, rhoncus dui ac, consequat dolor. Integer volutpat libero sed nisl aliquet varius. Suspendisse et lorem sapien. Proin id ultrices nibh, ac suscipit diam. Suspendisse placerat varius porttitor. Curabitur elementum sed enim ultrices imperdiet.

In ut lobortis lacus, nec luctus arcu. Vivamus condimentum sapien a ipsum malesuada sodales. Donec et vestibulum risus. Integer dictum euismod eros id tincidunt. Aliquam sagittis leo vitae consequat fermentum. Donec maximus ex eu ex iaculis porta. Praesent pharetra lacinia risus, et eleifend diam commodo non. Sed feugiat ipsum ut orci sagittis, quis faucibus lectus blandit. Sed tellus quam, gravida vitae laoreet quis, tempus lobortis dui. Vivamus semper accumsan ullamcorper. Praesent tempus pretium eros, non elementum risus. Pellentesque odio quam, auctor quis ex non, vulputate egestas dolor. Nunc luctus enim ut justo sodales consectetur. Sed aliquet a mauris vel posuere.

Donec luctus lectus efficitur, blandit nisi vitae, dignissim tellus. Pellentesque euismod pharetra augue gravida hendrerit. Quisque nisi mi, mattis ac nisi non, maximus malesuada ante. Nulla lobortis, diam eu ornare ornare, tellus enim feugiat arcu, non vestibulum tortor nunc eu justo. Integer blandit felis justo, eu semper est scelerisque vel. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nam ultricies, nisi vel elementum commodo, nisl dolor tincidunt magna, sed varius est nunc at lectus. Aliquam dolor tortor, sodales placerat ultricies quis, sodales quis sapien. Duis ullamcorper sollicitudin risus at mattis. Integer consequat et nunc at condimentum. Pellentesque cursus congue augue, non suscipit lectus sodales ut. Nam a mi bibendum, blandit nisl eu, accumsan nunc. Aliquam a ex mauris. Sed nec sem quis arcu dignissim tempus eget et turpis. Ut sed ex nec ipsum ultrices lobortis.

diff --git a/tests/reference/mBuildDocBuild_HTML5_Lorem_Ipsum.json b/tests/reference/mBuildDocBuild_HTML5_Lorem_Ipsum.json index 74b96ce22..916f32721 100644 --- a/tests/reference/mBuildDocBuild_HTML5_Lorem_Ipsum.json +++ b/tests/reference/mBuildDocBuild_HTML5_Lorem_Ipsum.json @@ -2,8 +2,8 @@ "meta": { "projectName": "Lorem Ipsum", "novelAuthor": "lipsum.com", - "buildTime": 1729590078, - "buildTimeStr": "2024-10-22 11:41:18" + "buildTime": 1729614520, + "buildTimeStr": "2024-10-22 18:28:40" }, "text": { "css": [ @@ -17,12 +17,7 @@ ".sep, .skip {text-align: center; margin-top: 1.30em; margin-bottom: 1.30em;}", "a {color: rgb(66, 113, 174);}", "mark {background: rgb(255, 255, 166);}", - ".keyword {color: rgb(245, 135, 31); font-weight: bold;}", - ".break {text-align: left;}", - ".synopsis {font-style: italic;}", - ".comment {font-style: italic; color: rgb(100, 100, 100);}", - ".dialog {color: rgb(66, 113, 174);}", - ".altdialog {color: rgb(129, 55, 9);}" + ".keyword {color: rgb(245, 135, 31); font-weight: bold;}" ], "html": [ [ @@ -32,13 +27,13 @@ "

\u201cThere is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain\u2026\u201d

" ], [ - "

Comment: Exctracted from the lipsum.com website.

", + "

Comment: Exctracted from the lipsum.com website.

", "

Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of \u201cde Finibus Bonorum et Malorum\u201d (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, \u201cLorem ipsum dolor sit amet..\u201d, comes from a line in section 1.10.32.

", "

The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from \u201cde Finibus Bonorum et Malorum\u201d by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.

" ], [ "

Prologue

", - "

Synopsis: Explanation from the lipsum.com website.

", + "

Synopsis: Explanation from the lipsum.com website.

", "

Lorem Ipsum is simply dummy text1 of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

" ], [ @@ -50,7 +45,7 @@ "

Point of View: Bod

", "

Plot: Main

", "

Locations: Europe

", - "

Synopsis: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam.

", + "

Synopsis: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam.

", "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam. Praesent magna nunc, lacinia sit amet quam eget, aliquet ultrices justo. Morbi ornare enim et lorem rutrum finibus ut eu dolor. Aliquam a orci odio. Ut ultrices sem quis massa placerat, eget mollis nisl cursus. Cras vel sagittis justo. Ut non ultricies leo. Maecenas rutrum velit in est varius, et egestas massa pulvinar.

" ], [ @@ -58,7 +53,7 @@ "

Point of View: Bod

", "

Plot: Main

", "

Locations: Europe

", - "

Synopsis: Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur.

", + "

Synopsis: Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur.

", "

Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur. Donec quis ante nunc. Mauris ut leo ipsum. Vestibulum est neque, hendrerit nec neque a, ullamcorper lobortis tellus. Fusce sollicitudin purus quis congue bibendum. Aliquam condimentum ipsum tristique blandit tristique. Donec pulvinar neque ac suscipit malesuada.

", "

Aliquam ut nisl arcu. Ut ultricies, lorem dignissim rutrum convallis, risus orci tempus lectus, congue feugiat sem lectus vitae odio. Duis sit amet justo finibus, hendrerit nulla at, ullamcorper enim. Praesent vel tellus sit amet tellus vulputate bibendum. Morbi eleifend sagittis sem, ac volutpat ante congue non. In hac habitasse platea dictumst. Morbi lobortis fermentum elit, dignissim sagittis ligula volutpat lacinia. Vestibulum eu interdum odio. Integer ac purus commodo metus congue tempor non at urna. Sed eget tortor vel quam viverra egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec non convallis mauris, ac feugiat ex.

", "

Section: Scene One, Section Two

", @@ -70,7 +65,7 @@ "

Point of View: Bod

", "

Plot: Main

", "

Locations: Europe

", - "

Synopsis: Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci.

", + "

Synopsis: Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci.

", "

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci. Vestibulum facilisis bibendum aliquam. Aliquam posuere, turpis ac bibendum varius, sem tellus venenatis risus, in elementum massa enim ac lorem. Integer in sem ac diam blandit ultricies ut in nulla. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam sit amet erat est. Curabitur vitae cursus justo, sit amet placerat dolor. Vivamus eu felis hendrerit, tincidunt massa rutrum, maximus arcu. Pellentesque commodo justo odio, vel rutrum nulla tincidunt eu. Integer non neque condimentum, convallis diam non, varius ligula. Aliquam eget sapien mauris. Aenean pharetra nunc nisi, vel maximus ante tristique sit amet. Aliquam risus metus, interdum non odio eu, consectetur lacinia sapien.

", "

Proin vitae gravida nisl. Integer viverra orci turpis, sit amet pretium ligula facilisis consequat. Nulla interdum commodo metus, mollis consequat dui tincidunt et. Proin consequat bibendum justo id commodo. Fusce fermentum nunc turpis, eu vestibulum risus feugiat ut. Sed scelerisque vel ligula ut interdum. Suspendisse ac blandit ligula, sagittis fringilla dolor. In tincidunt convallis diam et ornare. Aenean id dignissim est, ut rhoncus quam. Donec vitae nisl velit. In convallis nibh ut augue dignissim, eu elementum quam cursus. Phasellus in lectus lorem. Curabitur in pellentesque nisi, at gravida sapien. Sed cursus justo volutpat lacus placerat, sit amet dignissim turpis commodo. Aliquam vitae orci eget nulla posuere condimentum in ut felis.

", "

Nulla accumsan ante in pulvinar efficitur. Nulla non velit quis urna hendrerit bibendum. Suspendisse ultrices ante eu justo malesuada, sed fermentum enim rutrum. Nunc fermentum pharetra felis, vitae sollicitudin quam rutrum porta. Aliquam fringilla velit a mi laoreet, et luctus est rutrum. In gravida non ipsum sit amet tempus. Curabitur et eleifend purus. Nulla facilisi.

", @@ -81,7 +76,7 @@ ], [ "

Why do we use it?

", - "

Comment: Exctracted from the lipsum.com website.

", + "

Comment: Exctracted from the lipsum.com website.

", "

        It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.

", "

        The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English.

", "

        Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).

" @@ -91,7 +86,7 @@ "

Point of View: Bod

", "

Plot: Main

", "

Locations: Europe

", - "

Synopsis: Curabitur a elit posuere, varius ex et, convallis neque. Phasellus sagittis pharetra sem vitae dapibus. Curabitur varius lorem non pulvinar congue.

", + "

Synopsis: Curabitur a elit posuere, varius ex et, convallis neque. Phasellus sagittis pharetra sem vitae dapibus. Curabitur varius lorem non pulvinar congue.

", "

Curabitur a elit posuere, varius ex et, convallis neque. Phasellus sagittis pharetra sem vitae dapibus. Curabitur varius lorem non pulvinar congue. Vestibulum pharetra fermentum leo, sed faucibus eros placerat quis. In hac habitasse platea dictumst. Donec metus massa, rutrum quis consequat et, tincidunt ac felis. Duis mollis metus ac nunc tincidunt blandit. Ut aliquet velit eu odio pharetra condimentum. Integer rutrum lacus orci, id venenatis libero accumsan at.

" ], [ @@ -99,7 +94,7 @@ "

Point of View: Bod

", "

Plot: Main

", "

Locations: Europe

", - "

Synopsis: Aenean ut libero ut lectus porttitor rhoncus vel et massa. Nam pretium, nibh et varius vehicula, urna metus blandit eros, euismod pharetra diam diam et libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.

", + "

Synopsis: Aenean ut libero ut lectus porttitor rhoncus vel et massa. Nam pretium, nibh et varius vehicula, urna metus blandit eros, euismod pharetra diam diam et libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.

", "

Aenean ut libero ut lectus porttitor rhoncus vel et massa. Nam pretium, nibh et varius vehicula, urna metus blandit eros, euismod pharetra diam diam et libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean tincidunt lacus vitae nibh elementum eleifend. Sed rutrum condimentum sem quis blandit. Duis imperdiet libero metus, quis convallis quam faucibus a. Nulla ligula est, semper quis sollicitudin et, pretium id justo. Curabitur pharetra risus eget consectetur commodo. Duis mattis arcu non est condimentum, id venenatis risus volutpat. Pellentesque aliquet mauris non mauris porttitor ultrices. Phasellus ut vestibulum mi. Suspendisse malesuada metus lorem, a malesuada orci rhoncus a. Praesent euismod convallis ante, lacinia tincidunt ex egestas id. Praesent sit amet efficitur sapien. Morbi tincidunt volutpat nunc sed dictum. Aliquam ultrices metus id fermentum lobortis.

", "

Pellentesque id sagittis dui. Praesent ut nisi sit amet libero euismod ornare. Vestibulum vehicula, lorem eget aliquet imperdiet, eros nulla iaculis mi, vel bibendum est dui sed orci. Nullam vitae lorem rutrum, euismod lacus id, ullamcorper lectus. Duis nec commodo mi, a fringilla diam. Vestibulum molestie nibh tristique, viverra augue non, aliquet metus. Phasellus a tellus ac nisl tempor aliquet. Nulla vitae sapien rutrum augue ornare ultrices a quis nisi. Sed pulvinar tincidunt ex. Fusce vel sem vitae ante pellentesque lobortis.

", "

Maecenas ullamcorper lacus nec turpis finibus aliquet eget rutrum augue. Integer lorem erat, faucibus non lacus lacinia, pulvinar egestas felis. Proin rutrum nunc eget nulla varius, id blandit mauris tincidunt. Donec sit amet ullamcorper nisi, ut efficitur mi. Aliquam aliquet, nulla eget rhoncus tristique, justo lorem consectetur dui, id ornare leo odio sed tellus. Curabitur interdum velit a turpis condimentum venenatis. Nunc rhoncus sem ac augue auctor, nec malesuada ex fringilla. Vestibulum egestas diam sed leo consectetur vulputate quis eget enim. Nam tincidunt metus sit amet maximus ullamcorper. Sed placerat velit vitae massa efficitur viverra. Etiam eleifend dignissim ante, sed luctus nisl tristique a. In vestibulum pharetra dolor in molestie. Vivamus auctor massa ac magna imperdiet, sit amet iaculis turpis finibus.

", @@ -110,7 +105,7 @@ "

Point of View: Bod

", "

Plot: Main

", "

Locations: Europe

", - "

Synopsis: Nam tempor blandit magna laoreet aliquet. Vestibulum auctor posuere leo, ac gravida nisi rhoncus varius. Aenean posuere dolor vitae condimentum volutpat. Donec egestas volutpat risus, quis luctus justo.

", + "

Synopsis: Nam tempor blandit magna laoreet aliquet. Vestibulum auctor posuere leo, ac gravida nisi rhoncus varius. Aenean posuere dolor vitae condimentum volutpat. Donec egestas volutpat risus, quis luctus justo.

", "

Nam tempor blandit magna laoreet aliquet. Vestibulum auctor posuere leo, ac gravida nisi rhoncus varius. Aenean posuere dolor vitae condimentum volutpat. Donec egestas volutpat risus, quis luctus justo. Nullam viverra dui et auctor pretium. Ut ullamcorper velit urna, sed imperdiet massa convallis a. Suspendisse efficitur, ipsum nec cursus pulvinar, eros urna posuere diam, nec elementum mi felis vitae sapien.

", "

Duis efficitur metus pulvinar, molestie magna eget, feugiat dui. Fusce convallis vehicula ipsum convallis blandit. Duis eros risus, malesuada eu imperdiet in, hendrerit ac metus. Vestibulum id justo gravida, dignissim nibh non, iaculis diam. Fusce accumsan est ut massa porta ultricies. Nulla vitae justo in tortor laoreet mollis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin eu libero justo. Vivamus aliquet placerat est, et auctor eros posuere venenatis. Nunc quam diam, tincidunt ac aliquet in, fermentum sit amet lectus. Proin commodo tincidunt blandit. Quisque erat arcu, semper nec dui non, consectetur gravida ipsum. Nullam pretium consectetur elit at condimentum.

", "

Etiam sagittis, erat vitae accumsan tempor, neque augue scelerisque nulla, ut ultrices justo urna sit amet augue. Interdum et malesuada fames ac ante ipsum primis in faucibus. Aenean at pulvinar tortor. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Cras vel porta quam. Nullam eu mauris mollis, vehicula justo vel, placerat sapien. Phasellus viverra elit et vestibulum pharetra. Vestibulum commodo fermentum leo, eu porta nisi aliquam eget. Nulla tempus porttitor nisi nec mollis. Nam non mollis turpis. Nam finibus leo a bibendum tincidunt. Donec commodo velit magna, ac semper sapien mattis id. Proin sem velit, lobortis quis ultricies id, pharetra et lectus. Vestibulum condimentum neque vitae mi dapibus mollis. Mauris luctus vel sapien vitae hendrerit.

", @@ -123,7 +118,7 @@ "

Point of View: Bod

", "

Plot: Main

", "

Locations: Europe

", - "

Synopsis: Praesent eget est porta, dictum ante in, egestas risus. Mauris risus mauris, consequat aliquam mauris et, feugiat iaculis ipsum. Aliquam arcu ipsum, fermentum ut arcu sed, lobortis euismod sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.

", + "

Synopsis: Praesent eget est porta, dictum ante in, egestas risus. Mauris risus mauris, consequat aliquam mauris et, feugiat iaculis ipsum. Aliquam arcu ipsum, fermentum ut arcu sed, lobortis euismod sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.

", "

Praesent eget est porta, dictum ante in, egestas risus. Mauris risus mauris, consequat aliquam mauris et, feugiat iaculis ipsum. Aliquam arcu ipsum, fermentum ut arcu sed, lobortis euismod sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In sed felis auctor, rhoncus dui ac, consequat dolor. Integer volutpat libero sed nisl aliquet varius. Suspendisse et lorem sapien. Proin id ultrices nibh, ac suscipit diam. Suspendisse placerat varius porttitor. Curabitur elementum sed enim ultrices imperdiet.

", "

In ut lobortis lacus, nec luctus arcu. Vivamus condimentum sapien a ipsum malesuada sodales. Donec et vestibulum risus. Integer dictum euismod eros id tincidunt. Aliquam sagittis leo vitae consequat fermentum. Donec maximus ex eu ex iaculis porta. Praesent pharetra lacinia risus, et eleifend diam commodo non. Sed feugiat ipsum ut orci sagittis, quis faucibus lectus blandit. Sed tellus quam, gravida vitae laoreet quis, tempus lobortis dui. Vivamus semper accumsan ullamcorper. Praesent tempus pretium eros, non elementum risus. Pellentesque odio quam, auctor quis ex non, vulputate egestas dolor. Nunc luctus enim ut justo sodales consectetur. Sed aliquet a mauris vel posuere.

", "

Donec luctus lectus efficitur, blandit nisi vitae, dignissim tellus. Pellentesque euismod pharetra augue gravida hendrerit. Quisque nisi mi, mattis ac nisi non, maximus malesuada ante. Nulla lobortis, diam eu ornare ornare, tellus enim feugiat arcu, non vestibulum tortor nunc eu justo. Integer blandit felis justo, eu semper est scelerisque vel. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nam ultricies, nisi vel elementum commodo, nisl dolor tincidunt magna, sed varius est nunc at lectus. Aliquam dolor tortor, sodales placerat ultricies quis, sodales quis sapien. Duis ullamcorper sollicitudin risus at mattis. Integer consequat et nunc at condimentum. Pellentesque cursus congue augue, non suscipit lectus sodales ut. Nam a mi bibendum, blandit nisl eu, accumsan nunc. Aliquam a ex mauris. Sed nec sem quis arcu dignissim tempus eget et turpis. Ut sed ex nec ipsum ultrices lobortis.

", diff --git a/tests/test_formats/test_fmt_tohtml.py b/tests/test_formats/test_fmt_tohtml.py index 891f6aa3a..9b59c366e 100644 --- a/tests/test_formats/test_fmt_tohtml.py +++ b/tests/test_formats/test_fmt_tohtml.py @@ -35,6 +35,7 @@ def testFmtToHtml_ConvertHeaders(mockGUI): """Test header formats in the ToHtml class.""" project = NWProject() html = ToHtml(project) + html.initDocument() # Novel Files Headers # =================== @@ -137,6 +138,7 @@ def testFmtToHtml_ConvertParagraphs(mockGUI): """Test paragraph formats in the ToHtml class.""" project = NWProject() html = ToHtml(project) + html.initDocument() html._isNovel = True html._isFirst = True @@ -185,7 +187,10 @@ def testFmtToHtml_ConvertParagraphs(mockGUI): html.tokenizeText() html.doConvert() assert html.result == ( - "

Synopsis: The synopsis ...

\n" + "

" + "Synopsis: " + "The synopsis ..." + "

\n" ) html.setSynopsis(True) @@ -193,7 +198,10 @@ def testFmtToHtml_ConvertParagraphs(mockGUI): html.tokenizeText() html.doConvert() assert html.result == ( - "

Short Description: A short description ...

\n" + "

" + "Short Description: " + "A short description ..." + "

\n" ) # Comment @@ -207,7 +215,10 @@ def testFmtToHtml_ConvertParagraphs(mockGUI): html.tokenizeText() html.doConvert() assert html.result == ( - "

Comment: A comment ...

\n" + "

" + "Comment: " + "A comment ..." + "

\n" ) # Keywords @@ -269,7 +280,7 @@ def testFmtToHtml_ConvertParagraphs(mockGUI): html.doConvert() assert html.result == ( "

Chapter

\n" - "

This text \u201chas dialogue\u201d in it.

\n" + "

This text “has dialogue” in it.

\n" ) # Alt. Dialogue @@ -281,7 +292,7 @@ def testFmtToHtml_ConvertParagraphs(mockGUI): html.doConvert() assert html.result == ( "

Chapter

\n" - "

This text ::has alt dialogue:: in it.

\n" + "

This text ::has alt dialogue:: in it.

\n" ) # Footnotes @@ -314,6 +325,7 @@ def testFmtToHtml_CloseTags(mockGUI): """Test automatic closing of HTML tags for shortcodes.""" project = NWProject() html = ToHtml(project) + html.initDocument() html._isNovel = True html._isFirst = True @@ -350,6 +362,7 @@ def testFmtToHtml_ConvertDirect(mockGUI): """Test the converter directly using the ToHtml class.""" project = NWProject() html = ToHtml(project) + html.initDocument() html._isNovel = True html._handle = "0000000000000" @@ -497,6 +510,7 @@ def testFmtToHtml_SpecialCases(mockGUI): """Test some special cases that have caused errors in the past.""" project = NWProject() html = ToHtml(project) + html.initDocument() html._isNovel = True # Greater/Lesser than symbols @@ -540,7 +554,9 @@ def testFmtToHtml_SpecialCases(mockGUI): html.doConvert() assert html.result == ( "

" - "Comment: Test > text <bold> and more." + "Comment: " + "Test > text <bold> " + "and more." "

\n" ) @@ -569,6 +585,7 @@ def testFmtToHtml_Save(mockGUI, fncPath): """Test the save method of the ToHtml class.""" project = NWProject() html = ToHtml(project) + html.initDocument() html._isNovel = True # Build Project @@ -665,6 +682,7 @@ def testFmtToHtml_Methods(mockGUI): """Test all the other methods of the ToHtml class.""" project = NWProject() html = ToHtml(project) + html.initDocument() # Auto-Replace, keep Unicode docText = "Text with & short–dash, long—dash …\n" @@ -707,6 +725,7 @@ def testFmtToHtml_Format(mockGUI): """Test all the formatters for the ToHtml class.""" project = NWProject() html = ToHtml(project) + html.initDocument() assert html._formatKeywords("") == ("", "") assert html._formatKeywords("tag: Jane") == ( diff --git a/tests/test_formats/test_fmt_tokenizer.py b/tests/test_formats/test_fmt_tokenizer.py index 2ac1e6723..8f917924d 100644 --- a/tests/test_formats/test_fmt_tokenizer.py +++ b/tests/test_formats/test_fmt_tokenizer.py @@ -736,7 +736,7 @@ def testFmtToken_MetaFormat(mockGUI): tokens._text = "% synopsis: The synopsis\n" tokens.tokenizeText() assert tokens._blocks == [( - BlockTyp.SUMMARY, 0, "Synopsis: The synopsis", [ + BlockTyp.COMMENT, 0, "Synopsis: The synopsis", [ (0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "modifier"), (9, TextFmt.B_E, ""), (9, TextFmt.COL_E, ""), (10, TextFmt.COL_B, "synopsis"), (22, TextFmt.COL_E, "") ], BlockFmt.NONE @@ -754,7 +754,7 @@ def testFmtToken_MetaFormat(mockGUI): tokens._text = "% short: A short description\n" tokens.tokenizeText() assert tokens._blocks == [( - BlockTyp.SUMMARY, 0, "Short Description: A short description", [ + BlockTyp.COMMENT, 0, "Short Description: A short description", [ (0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "modifier"), (18, TextFmt.B_E, ""), (18, TextFmt.COL_E, ""), (19, TextFmt.COL_B, "synopsis"), (38, TextFmt.COL_E, ""), ], BlockFmt.NONE @@ -1129,10 +1129,10 @@ def testFmtToken_Dialogue(mockGUI): BlockTyp.TEXT, 0, "Text with \u2018dialogue one,\u2019 and \u2018dialogue two.\u2019", [ - (10, TextFmt.DL_B, ""), - (25, TextFmt.DL_E, ""), - (30, TextFmt.DL_B, ""), - (45, TextFmt.DL_E, ""), + (10, TextFmt.COL_B, "dialog"), + (25, TextFmt.COL_E, ""), + (30, TextFmt.COL_B, "dialog"), + (45, TextFmt.COL_E, ""), ], BlockFmt.NONE )] @@ -1144,10 +1144,10 @@ def testFmtToken_Dialogue(mockGUI): BlockTyp.TEXT, 0, "Text with \u201cdialogue one,\u201d and \u201cdialogue two.\u201d", [ - (10, TextFmt.DL_B, ""), - (25, TextFmt.DL_E, ""), - (30, TextFmt.DL_B, ""), - (45, TextFmt.DL_E, ""), + (10, TextFmt.COL_B, "dialog"), + (25, TextFmt.COL_E, ""), + (30, TextFmt.COL_B, "dialog"), + (45, TextFmt.COL_E, ""), ], BlockFmt.NONE )] @@ -1159,10 +1159,10 @@ def testFmtToken_Dialogue(mockGUI): BlockTyp.TEXT, 0, "Text with ::dialogue one,:: and ::dialogue two.::", [ - (10, TextFmt.ADL_B, ""), - (27, TextFmt.ADL_E, ""), - (32, TextFmt.ADL_B, ""), - (49, TextFmt.ADL_E, ""), + (10, TextFmt.COL_B, "altdialog"), + (27, TextFmt.COL_E, ""), + (32, TextFmt.COL_B, "altdialog"), + (49, TextFmt.COL_E, ""), ], BlockFmt.NONE )] @@ -1174,10 +1174,10 @@ def testFmtToken_Dialogue(mockGUI): BlockTyp.TEXT, 0, "\u2013 Dialogue with a narrator break, \u2013he said,\u2013 see?", [ - (0, TextFmt.DL_B, ""), - (34, TextFmt.DL_E, ""), - (44, TextFmt.DL_B, ""), - (49, TextFmt.DL_E, ""), + (0, TextFmt.COL_B, "dialog"), + (34, TextFmt.COL_E, ""), + (44, TextFmt.COL_B, "dialog"), + (49, TextFmt.COL_E, ""), ], BlockFmt.NONE )] @@ -1193,9 +1193,9 @@ def testFmtToken_Dialogue(mockGUI): "\u201cDialogue text.\u201d", [ (0, TextFmt.I_B, ""), - (0, TextFmt.DL_B, ""), + (0, TextFmt.COL_B, "dialog"), (16, TextFmt.I_E, ""), - (16, TextFmt.DL_E, ""), + (16, TextFmt.COL_E, ""), ], BlockFmt.NONE )] @@ -1407,8 +1407,8 @@ def testFmtToken_TextIndent(mockGUI): (9, TextFmt.COL_E, ""), (10, TextFmt.COL_B, "synopsis"), (24, TextFmt.COL_E, ""), ] assert tokens._blocks == [ - (BlockTyp.HEAD3, 1, "Scene Two", [], BlockFmt.NONE), - (BlockTyp.SUMMARY, 1, "Synopsis: Stuff happens.", tFmt, BlockFmt.NONE), + (BlockTyp.HEAD3, 1, "Scene Two", [], BlockFmt.NONE), + (BlockTyp.COMMENT, 1, "Synopsis: Stuff happens.", tFmt, BlockFmt.NONE), ] assert tokens._noIndent is True diff --git a/tests/test_formats/test_fmt_toodt.py b/tests/test_formats/test_fmt_toodt.py index c9abd3b61..0d0664032 100644 --- a/tests/test_formats/test_fmt_toodt.py +++ b/tests/test_formats/test_fmt_toodt.py @@ -248,7 +248,7 @@ def testFmtToOdt_DialogueFormatting(mockGUI): # Regular dialogue text = "Text with 'dialogue in it.'" - fmt = [(10, TextFmt.DL_B, ""), (27, TextFmt.DL_E, "")] + fmt = [(10, TextFmt.COL_B, "dialog"), (27, TextFmt.COL_E, "")] xTest = ET.Element(_mkTag("office", "text")) odt._addTextPar(xTest, "Standard", oStyle, text, tFmt=fmt) assert odt.errData == [] @@ -261,7 +261,7 @@ def testFmtToOdt_DialogueFormatting(mockGUI): # Alternative dialogue text = "Text with ::dialogue in it.::" - fmt = [(10, TextFmt.ADL_B, ""), (29, TextFmt.ADL_E, "")] + fmt = [(10, TextFmt.COL_B, "altdialog"), (29, TextFmt.COL_E, "")] xTest = ET.Element(_mkTag("office", "text")) odt._addTextPar(xTest, "Standard", oStyle, text, tFmt=fmt) assert odt.errData == [] From c7554f2b8d51c3916b4f325c3054a92dc13bcdbd Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 22 Oct 2024 19:33:05 +0200 Subject: [PATCH 09/10] Process keyword flag in Tokenizer --- novelwriter/formats/todocx.py | 2 +- novelwriter/formats/tohtml.py | 2 +- novelwriter/formats/tokenizer.py | 25 ++++++++++++++++++++---- novelwriter/formats/tomarkdown.py | 2 +- novelwriter/formats/toodt.py | 2 +- novelwriter/formats/toqdoc.py | 2 +- tests/test_formats/test_fmt_tokenizer.py | 12 +++++++----- 7 files changed, 33 insertions(+), 14 deletions(-) diff --git a/novelwriter/formats/todocx.py b/novelwriter/formats/todocx.py index 9dbf8966b..ac867edeb 100644 --- a/novelwriter/formats/todocx.py +++ b/novelwriter/formats/todocx.py @@ -291,7 +291,7 @@ def doConvert(self) -> None: elif tType == BlockTyp.COMMENT: self._processFragments(par, S_META, tText, tFormat) - elif tType == BlockTyp.KEYWORD and self._doKeywords: + elif tType == BlockTyp.KEYWORD: tTemp, tFmt = self._formatKeywords(tText) self._processFragments(par, S_META, tTemp, tFmt) diff --git a/novelwriter/formats/tohtml.py b/novelwriter/formats/tohtml.py index 17547ca9e..c467fedbd 100644 --- a/novelwriter/formats/tohtml.py +++ b/novelwriter/formats/tohtml.py @@ -252,7 +252,7 @@ def doConvert(self) -> None: elif tType == BlockTyp.COMMENT: lines.append(f"

{self._formatText(tText, tFormat)}

\n") - elif tType == BlockTyp.KEYWORD and self._doKeywords: + elif tType == BlockTyp.KEYWORD: tag, text = self._formatKeywords(tText) kClass = f" class='meta meta-{tag}'" if tag else "" tTemp = f"{text}

\n" diff --git a/novelwriter/formats/tokenizer.py b/novelwriter/formats/tokenizer.py index a4850fbdf..fb447df2b 100644 --- a/novelwriter/formats/tokenizer.py +++ b/novelwriter/formats/tokenizer.py @@ -613,7 +613,7 @@ def tokenizeText(self) -> None: if cStyle in (nwComment.SYNOPSIS, nwComment.SHORT, nwComment.PLAIN): bStyle = COMMENT_STYLE[cStyle] - tLine, tFmt = self._formatNote(bStyle, cKey, cText) + tLine, tFmt = self._formatComment(bStyle, cKey, cText) blocks.append((BlockTyp.COMMENT, nHead, tLine, tFmt, sAlign)) if self._keepRaw: tmpMarkdown.append(f"{aLine}\n") @@ -630,6 +630,9 @@ def tokenizeText(self) -> None: # Only valid keyword lines are parsed, and any ignored keywords # are automatically skipped. + if not self._doKeywords: + continue + valid, bits, _ = self._project.index.scanThis(aLine) if ( valid and bits and bits[0] in nwLabels.KEY_NAME @@ -638,9 +641,23 @@ def tokenizeText(self) -> None: blocks.append(( BlockTyp.KEYWORD, nHead, aLine[1:].strip(), [], sAlign )) - if self._doKeywords and self._keepRaw: + if self._keepRaw: tmpMarkdown.append(f"{aLine}\n") + # valid, bits, _ = self._project.index.scanThis("@"+text) + # if not valid or not bits or bits[0] not in nwLabels.KEY_NAME: + # return "", [] + + # rTxt = f"{self._localLookup(nwLabels.KEY_NAME[bits[0]])}: " + # rFmt: T_Formats = [(0, TextFmt.B_B, ""), (len(rTxt) - 1, TextFmt.B_E, "")] + # if len(bits) > 1: + # if bits[0] == nwKeyWords.TAG_KEY: + # rTxt += bits[1] + # else: + # rTxt += ", ".join(bits[1:]) + + # return rTxt, rFmt + elif aLine.startswith(("# ", "#! ")): # Title or Partition Headings # =========================== @@ -1022,7 +1039,7 @@ def countStats(self) -> None: allChars += len(tText) allWordChars += len("".join(words)) - elif tType == BlockTyp.KEYWORD and self._doKeywords: + elif tType == BlockTyp.KEYWORD: valid, bits, _ = self._project.index.scanThis("@"+tText) if valid and bits: key = self._localLookup(nwLabels.KEY_NAME[bits[0]]) @@ -1080,7 +1097,7 @@ def saveRawDocument(self, path: str | Path, asJson: bool = False) -> None: # Internal Functions ## - def _formatNote(self, style: ComStyle, key: str, text: str) -> tuple[str, T_Formats]: + def _formatComment(self, style: ComStyle, key: str, text: str) -> tuple[str, T_Formats]: """Apply formatting to comments and notes.""" tTxt, tFmt = self._extractFormats(text) tFmt.insert(0, (0, TextFmt.COL_B, style.textClass)) diff --git a/novelwriter/formats/tomarkdown.py b/novelwriter/formats/tomarkdown.py index 599e7b0f1..09e33eb04 100644 --- a/novelwriter/formats/tomarkdown.py +++ b/novelwriter/formats/tomarkdown.py @@ -153,7 +153,7 @@ def doConvert(self) -> None: elif tType == BlockTyp.COMMENT: lines.append(f"{self._formatText(tText, tFormat, mTags)}\n\n") - elif tType == BlockTyp.KEYWORD and self._doKeywords: + elif tType == BlockTyp.KEYWORD: lines.append(self._formatKeywords(tText, tStyle)) self._result = "".join(lines) diff --git a/novelwriter/formats/toodt.py b/novelwriter/formats/toodt.py index 85aefb038..9802ce4b0 100644 --- a/novelwriter/formats/toodt.py +++ b/novelwriter/formats/toodt.py @@ -483,7 +483,7 @@ def doConvert(self) -> None: elif tType == BlockTyp.COMMENT: self._addTextPar(xText, S_META, oStyle, tText, tFmt=tFormat) - elif tType == BlockTyp.KEYWORD and self._doKeywords: + elif tType == BlockTyp.KEYWORD: tTemp, tFmt = self._formatKeywords(tText) self._addTextPar(xText, S_META, oStyle, tTemp, tFmt=tFmt) diff --git a/novelwriter/formats/toqdoc.py b/novelwriter/formats/toqdoc.py index ea4912eba..e0b1faf55 100644 --- a/novelwriter/formats/toqdoc.py +++ b/novelwriter/formats/toqdoc.py @@ -244,7 +244,7 @@ def doConvert(self) -> None: newBlock(cursor, bFmt) self._insertFragments(tText, tFormat, cursor, self._cText) - elif tType == BlockTyp.KEYWORD and self._doKeywords: + elif tType == BlockTyp.KEYWORD: newBlock(cursor, bFmt) self._insertKeywords(tText, cursor) diff --git a/tests/test_formats/test_fmt_tokenizer.py b/tests/test_formats/test_fmt_tokenizer.py index 8f917924d..cf236348a 100644 --- a/tests/test_formats/test_fmt_tokenizer.py +++ b/tests/test_formats/test_fmt_tokenizer.py @@ -762,15 +762,17 @@ def testFmtToken_MetaFormat(mockGUI): assert tokens.allMarkdown[-1] == "% short: A short description\n\n" # Keyword + tokens.setKeywords(False) tokens._text = "@char: Bod\n" tokens.tokenizeText() - assert tokens._blocks == [ - (BlockTyp.KEYWORD, 0, "char: Bod", [], BlockFmt.NONE), - ] + assert tokens._blocks == [] assert tokens.allMarkdown[-1] == "\n" tokens.setKeywords(True) tokens.tokenizeText() + assert tokens._blocks == [ + (BlockTyp.KEYWORD, 0, "char: Bod", [], BlockFmt.NONE), + ] assert tokens.allMarkdown[-1] == "@char: Bod\n\n" tokens._text = "@pov: Bod\n@plot: Main\n@location: Europe\n" @@ -1650,7 +1652,7 @@ def testFmtToken_FormatNote(mockGUI, ipsumText): # Comment, No Formatting style = COMMENT_STYLE[nwComment.PLAIN] - assert tokens._formatNote(style, "", "Hello world!") == ( + assert tokens._formatComment(style, "", "Hello world!") == ( "Comment: Hello world!", [ (0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "comment"), (8, TextFmt.B_E, ""), (8, TextFmt.COL_E, ""), @@ -1660,7 +1662,7 @@ def testFmtToken_FormatNote(mockGUI, ipsumText): # Synopsis, No Formatting style = COMMENT_STYLE[nwComment.SYNOPSIS] - assert tokens._formatNote(style, "", "Hello world!") == ( + assert tokens._formatComment(style, "", "Hello world!") == ( "Synopsis: Hello world!", [ (0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "modifier"), (9, TextFmt.B_E, ""), (9, TextFmt.COL_E, ""), From bd5442c9e57500165323d1c7244e8f6146b73216 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 22 Oct 2024 21:37:18 +0200 Subject: [PATCH 10/10] Process tags and references in Tokenizer --- novelwriter/formats/shared.py | 8 +- novelwriter/formats/todocx.py | 29 +-- novelwriter/formats/tohtml.py | 50 ++-- novelwriter/formats/tokenizer.py | 94 ++++--- novelwriter/formats/tomarkdown.py | 21 +- novelwriter/formats/toodt.py | 54 +--- novelwriter/formats/toqdoc.py | 104 +++----- .../fmtToDocX_SaveDocument_document.xml | 245 ++++++++++++++++-- .../mBuildDocBuild_HTML5_Lorem_Ipsum.htm | 75 +++--- .../mBuildDocBuild_HTML5_Lorem_Ipsum.json | 79 +++--- ...uildDocBuild_OpenDocument_Lorem_Ipsum.fodt | 63 +++-- tests/test_formats/test_fmt_todocx.py | 27 +- tests/test_formats/test_fmt_tohtml.py | 52 ++-- tests/test_formats/test_fmt_tokenizer.py | 86 ++++-- tests/test_formats/test_fmt_tomarkdown.py | 12 - tests/test_formats/test_fmt_toodt.py | 54 ++-- 16 files changed, 588 insertions(+), 465 deletions(-) diff --git a/novelwriter/formats/shared.py b/novelwriter/formats/shared.py index 3e624e211..ef36e9555 100644 --- a/novelwriter/formats/shared.py +++ b/novelwriter/formats/shared.py @@ -86,8 +86,12 @@ class TextFmt(IntEnum): SUB_E = 14 # End subscript COL_B = 15 # Begin colour COL_E = 16 # End colour - FNOTE = 17 # Footnote marker - STRIP = 18 # Strip the format code + ANM_B = 17 # Begin anchor name + ANM_E = 18 # End anchor name + HRF_B = 19 # Begin href link + HRF_E = 20 # End href link + FNOTE = 21 # Footnote marker + STRIP = 22 # Strip the format code class BlockTyp(IntEnum): diff --git a/novelwriter/formats/todocx.py b/novelwriter/formats/todocx.py index ac867edeb..16772d7ad 100644 --- a/novelwriter/formats/todocx.py +++ b/novelwriter/formats/todocx.py @@ -38,7 +38,7 @@ from novelwriter import __version__ from novelwriter.common import firstFloat, xmlSubElem -from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels, nwStyles +from novelwriter.constants import nwHeadFmt, nwStyles from novelwriter.core.project import NWProject from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt from novelwriter.formats.tokenizer import Tokenizer @@ -119,12 +119,6 @@ def _docXCol(color: QColor) -> str: S_HEAD = "Header" S_FNOTE = "FootnoteText" -# Colours -COL_DIALOG_M = "2a6099" -COL_DIALOG_A = "813709" -COL_META_TXT = "813709" -COL_MARK_TXT = "ffffa6" - class DocXXmlFile(NamedTuple): @@ -292,8 +286,7 @@ def doConvert(self) -> None: self._processFragments(par, S_META, tText, tFormat) elif tType == BlockTyp.KEYWORD: - tTemp, tFmt = self._formatKeywords(tText) - self._processFragments(par, S_META, tTemp, tFmt) + self._processFragments(par, S_META, tText, tFormat) return @@ -369,22 +362,6 @@ def xmlToZip(name: str, xObj: ET.Element, zipObj: ZipFile) -> None: # Internal Functions ## - def _formatKeywords(self, text: str) -> tuple[str, T_Formats]: - """Apply formatting to keywords.""" - valid, bits, _ = self._project.index.scanThis("@"+text) - if not valid or not bits or bits[0] not in nwLabels.KEY_NAME: - return "", [] - - rTxt = f"{self._localLookup(nwLabels.KEY_NAME[bits[0]])}: " - rFmt: T_Formats = [(0, TextFmt.B_B, ""), (len(rTxt) - 1, TextFmt.B_E, "")] - if len(bits) > 1: - if bits[0] == nwKeyWords.TAG_KEY: - rTxt += bits[1] - else: - rTxt += ", ".join(bits[1:]) - - return rTxt, rFmt - def _processFragments( self, par: DocXParagraph, pStyle: str, text: str, tFmt: T_Formats | None = None ) -> None: @@ -465,7 +442,7 @@ def _textRunToXml(self, text: str, fmt: int, fClass: str = "") -> ET.Element: xmlSubElem(rPr, _wTag("u"), attrib={_wTag("val"): "single"}) if fmt & X_MRK: xmlSubElem(rPr, _wTag("shd"), attrib={ - _wTag("fill"): COL_MARK_TXT, _wTag("val"): "clear", + _wTag("fill"): _docXCol(self._theme.highlight), _wTag("val"): "clear", }) if fmt & X_DEL: xmlSubElem(rPr, _wTag("strike")) diff --git a/novelwriter/formats/tohtml.py b/novelwriter/formats/tohtml.py index c467fedbd..af46ee289 100644 --- a/novelwriter/formats/tohtml.py +++ b/novelwriter/formats/tohtml.py @@ -30,7 +30,7 @@ from time import time from novelwriter.common import formatTimeStamp -from novelwriter.constants import nwHeadFmt, nwHtmlUnicode, nwKeyWords, nwLabels +from novelwriter.constants import nwHeadFmt, nwHtmlUnicode from novelwriter.core.project import NWProject from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt, stripEscape from novelwriter.formats.tokenizer import Tokenizer @@ -48,6 +48,8 @@ TextFmt.SUP_B: (TextFmt.SUP_E, ""), TextFmt.SUB_B: (TextFmt.SUB_E, ""), TextFmt.COL_B: (TextFmt.COL_E, ""), + TextFmt.ANM_B: (TextFmt.ANM_E, ""), + TextFmt.HRF_B: (TextFmt.HRF_E, ""), } # Each closer tag, with the id of its corresponding opener and tag format @@ -60,6 +62,8 @@ TextFmt.SUP_E: (TextFmt.SUP_B, ""), TextFmt.SUB_E: (TextFmt.SUB_B, ""), TextFmt.COL_E: (TextFmt.COL_B, ""), + TextFmt.ANM_E: (TextFmt.ANM_B, ""), + TextFmt.HRF_E: (TextFmt.HRF_B, ""), } # Empty HTML tag record @@ -155,21 +159,21 @@ def doConvert(self) -> None: lines = [] tHandle = self._handle - for tType, nHead, tText, tFormat, tStyle in self._blocks: + for tType, nHead, tText, tFmt, tStyle in self._blocks: # Replace < and > with HTML entities - if tFormat: + if tFmt: # If we have formatting, we must recompute the locations cText = [] i = 0 for c in tText: if c == "<": cText.append("<") - tFormat = [(p + 3 if p > i else p, f, k) for p, f, k in tFormat] + tFmt = [(p + 3 if p > i else p, f, k) for p, f, k in tFmt] i += 4 elif c == ">": cText.append(">") - tFormat = [(p + 3 if p > i else p, f, k) for p, f, k in tFormat] + tFmt = [(p + 3 if p > i else p, f, k) for p, f, k in tFmt] i += 4 else: cText.append(c) @@ -221,7 +225,7 @@ def doConvert(self) -> None: # Process Text Type if tType == BlockTyp.TEXT: - lines.append(f"{self._formatText(tText, tFormat)}

\n") + lines.append(f"{self._formatText(tText, tFmt)}

\n") elif tType == BlockTyp.TITLE: tHead = tText.replace(nwHeadFmt.BR, "
") @@ -250,13 +254,10 @@ def doConvert(self) -> None: lines.append(f"

 

\n") elif tType == BlockTyp.COMMENT: - lines.append(f"

{self._formatText(tText, tFormat)}

\n") + lines.append(f"

{self._formatText(tText, tFmt)}

\n") elif tType == BlockTyp.KEYWORD: - tag, text = self._formatKeywords(tText) - kClass = f" class='meta meta-{tag}'" if tag else "" - tTemp = f"{text}

\n" - lines.append(tTemp) + lines.append(f"

{self._formatText(tText, tFmt)}

\n") self._result = "".join(lines) self._fullHTML.append(self._result) @@ -431,9 +432,8 @@ def getStyleSheet(self) -> list[str]: mScale, mScale )) - styles.append("a {color: rgb(66, 113, 174);}") - styles.append("mark {background: rgb(255, 255, 166);}") - styles.append(".keyword {color: rgb(245, 135, 31); font-weight: bold;}") + styles.append("a {{color: {0:s};}}".format(self._theme.head.name(QtHexRgb))) + styles.append("mark {{background: {0:s};}}".format(self._theme.highlight.name(QtHexRgb))) return styles @@ -455,6 +455,8 @@ def _formatText(self, text: str, tFmt: T_Formats) -> str: if not state.get(fmt, True): if fmt == TextFmt.COL_B and (color := self._classes.get(data)): tags.append((pos, m[1].format(color.name(QtHexRgb)))) + elif fmt in (TextFmt.ANM_B, TextFmt.HRF_B): + tags.append((pos, m[1].format(data or "#"))) else: tags.append((pos, m[1])) state[fmt] = True @@ -488,23 +490,3 @@ def _formatText(self, text: str, tFmt: T_Formats) -> str: temp = temp.replace("\n", "
") return stripEscape(temp) - - def _formatKeywords(self, text: str) -> tuple[str, str]: - """Apply HTML formatting to keywords.""" - valid, bits, _ = self._project.index.scanThis("@"+text) - if not valid or not bits or bits[0] not in nwLabels.KEY_NAME: - return "", "" - - result = f"{self._localLookup(nwLabels.KEY_NAME[bits[0]])}: " - if len(bits) > 1: - if bits[0] == nwKeyWords.TAG_KEY: - one, two = self._project.index.parseValue(bits[1]) - result += f"{one}" - if two: - result += f" | {two}" - else: - result += ", ".join( - f"{t}" for t in bits[1:] - ) - - return bits[0][1:], result diff --git a/novelwriter/formats/tokenizer.py b/novelwriter/formats/tokenizer.py index fb447df2b..a6f67783d 100644 --- a/novelwriter/formats/tokenizer.py +++ b/novelwriter/formats/tokenizer.py @@ -127,10 +127,11 @@ def __init__(self, project: NWProject) -> None: self._doSynopsis = False # Also process synopsis comments self._doComments = False # Also process comments self._doKeywords = False # Also process keywords like tags and references - self._skipKeywords = set() # Keywords to ignore self._keepBreaks = True # Keep line breaks in paragraphs self._defaultAlign = "left" # The default text alignment + self._skipKeywords: set[str] = set() # Keywords to ignore + # Other Setting self._theme = TextDocumentTheme() self._classes: dict[str, QColor] = {} @@ -464,6 +465,9 @@ def initDocument(self) -> None: self._classes["comment"] = self._theme.comment self._classes["dialog"] = self._theme.dialog self._classes["altdialog"] = self._theme.altdialog + self._classes["tag"] = self._theme.tag + self._classes["keyword"] = self._theme.keyword + self._classes["optional"] = self._theme.optional return def addRootHeading(self, tHandle: str) -> None: @@ -614,7 +618,9 @@ def tokenizeText(self) -> None: if cStyle in (nwComment.SYNOPSIS, nwComment.SHORT, nwComment.PLAIN): bStyle = COMMENT_STYLE[cStyle] tLine, tFmt = self._formatComment(bStyle, cKey, cText) - blocks.append((BlockTyp.COMMENT, nHead, tLine, tFmt, sAlign)) + blocks.append(( + BlockTyp.COMMENT, nHead, tLine, tFmt, sAlign + )) if self._keepRaw: tmpMarkdown.append(f"{aLine}\n") @@ -633,31 +639,14 @@ def tokenizeText(self) -> None: if not self._doKeywords: continue - valid, bits, _ = self._project.index.scanThis(aLine) - if ( - valid and bits and bits[0] in nwLabels.KEY_NAME - and bits[0] not in self._skipKeywords - ): + tLine, tFmt = self._formatMeta(aLine) + if tLine: blocks.append(( - BlockTyp.KEYWORD, nHead, aLine[1:].strip(), [], sAlign + BlockTyp.KEYWORD, nHead, tLine, tFmt, sAlign )) if self._keepRaw: tmpMarkdown.append(f"{aLine}\n") - # valid, bits, _ = self._project.index.scanThis("@"+text) - # if not valid or not bits or bits[0] not in nwLabels.KEY_NAME: - # return "", [] - - # rTxt = f"{self._localLookup(nwLabels.KEY_NAME[bits[0]])}: " - # rFmt: T_Formats = [(0, TextFmt.B_B, ""), (len(rTxt) - 1, TextFmt.B_E, "")] - # if len(bits) > 1: - # if bits[0] == nwKeyWords.TAG_KEY: - # rTxt += bits[1] - # else: - # rTxt += ", ".join(bits[1:]) - - # return rTxt, rFmt - elif aLine.startswith(("# ", "#! ")): # Title or Partition Headings # =========================== @@ -1033,22 +1022,12 @@ def countStats(self) -> None: allChars += nChars allWordChars += nWChars - elif tType == BlockTyp.COMMENT: + elif tType in (BlockTyp.COMMENT, BlockTyp.KEYWORD): words = tText.split() allWords += len(words) allChars += len(tText) allWordChars += len("".join(words)) - elif tType == BlockTyp.KEYWORD: - valid, bits, _ = self._project.index.scanThis("@"+tText) - if valid and bits: - key = self._localLookup(nwLabels.KEY_NAME[bits[0]]) - text = "{0}: {1}".format(key, ", ".join(bits[1:])) - words = text.split() - allWords += len(words) - allChars += len(text) - allWordChars += len("".join(words)) - self._counts["titleCount"] = titleCount self._counts["paragraphCount"] = paragraphCount @@ -1112,6 +1091,55 @@ def _formatComment(self, style: ComStyle, key: str, text: str) -> tuple[str, T_F rFmt.extend((p + shift, f, d) for p, f, d in tFmt) return tTxt, rFmt + def _formatMeta(self, text: str) -> tuple[str, T_Formats]: + """Parse a meta line into a """ + txt = [] + fmt = [] + valid, bits, _ = self._project.index.scanThis(text) + if valid and bits and bits[0] in nwLabels.KEY_NAME and bits[0] not in self._skipKeywords: + pos = 0 + lbl = f"{self._localLookup(nwLabels.KEY_NAME[bits[0]])}:" + end = len(lbl) + fmt = [ + (pos, TextFmt.B_B, ""), (pos, TextFmt.COL_B, "keyword"), + (end, TextFmt.B_E, ""), (end, TextFmt.COL_E, ""), + ] + txt = [lbl, " "] + pos = end + 1 + + if (num := len(bits)) > 1: + if bits[0] == nwKeyWords.TAG_KEY: + one, two = self._project.index.parseValue(bits[1]) + end = pos + len(one) + fmt.append((pos, TextFmt.COL_B, "tag")) + fmt.append((pos, TextFmt.ANM_B, f"tag_{one}".lower())) + fmt.append((end, TextFmt.ANM_E, "")) + fmt.append((end, TextFmt.COL_E, "")) + txt.append(one) + pos = end + if two: + txt.append(" | ") + pos += 3 + end = pos + len(two) + fmt.append((pos, TextFmt.COL_B, "optional")) + fmt.append((end, TextFmt.COL_E, "")) + txt.append(two) + pos = end + else: + for n, bit in enumerate(bits[1:], 2): + end = pos + len(bit) + fmt.append((pos, TextFmt.COL_B, "tag")) + fmt.append((pos, TextFmt.HRF_B, f"#tag_{bit}".lower())) + fmt.append((end, TextFmt.HRF_E, "")) + fmt.append((end, TextFmt.COL_E, "")) + txt.append(bit) + pos = end + if n < num: + txt.append(", ") + pos += 2 + + return "".join(txt), fmt + def _extractFormats( self, text: str, skip: int = 0, hDialog: bool = False ) -> tuple[str, T_Formats]: diff --git a/novelwriter/formats/tomarkdown.py b/novelwriter/formats/tomarkdown.py index 09e33eb04..e4e30ac34 100644 --- a/novelwriter/formats/tomarkdown.py +++ b/novelwriter/formats/tomarkdown.py @@ -27,7 +27,7 @@ from pathlib import Path -from novelwriter.constants import nwHeadFmt, nwLabels, nwUnicode +from novelwriter.constants import nwHeadFmt, nwUnicode from novelwriter.core.project import NWProject from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt from novelwriter.formats.tokenizer import Tokenizer @@ -154,7 +154,8 @@ def doConvert(self) -> None: lines.append(f"{self._formatText(tText, tFormat, mTags)}\n\n") elif tType == BlockTyp.KEYWORD: - lines.append(self._formatKeywords(tText, tStyle)) + end = " \n" if tStyle & BlockFmt.Z_BTMMRG else "\n\n" + lines.append(f"{self._formatText(tText, tFormat, mTags)}{end}") self._result = "".join(lines) self._fullMD.append(self._result) @@ -215,19 +216,3 @@ def _formatText(self, text: str, tFmt: T_Formats, tags: dict[TextFmt, str]) -> s md = tags.get(fmt, "") temp = f"{temp[:pos]}{md}{temp[pos:]}" return temp - - def _formatKeywords(self, text: str, style: BlockFmt) -> str: - """Apply Markdown formatting to keywords.""" - valid, bits, _ = self._project.index.scanThis("@"+text) - if not valid or not bits: - return "" - - result = "" - if bits[0] in nwLabels.KEY_NAME: - result += f"**{self._localLookup(nwLabels.KEY_NAME[bits[0]])}:** " - if len(bits) > 1: - result += ", ".join(bits[1:]) - - result += " \n" if style & BlockFmt.Z_BTMMRG else "\n\n" - - return result diff --git a/novelwriter/formats/toodt.py b/novelwriter/formats/toodt.py index 9802ce4b0..a6d7f000d 100644 --- a/novelwriter/formats/toodt.py +++ b/novelwriter/formats/toodt.py @@ -39,11 +39,11 @@ from novelwriter import __version__ from novelwriter.common import xmlIndent, xmlSubElem -from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels, nwStyles +from novelwriter.constants import nwHeadFmt, nwStyles from novelwriter.core.project import NWProject -from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt, stripEscape +from novelwriter.formats.shared import BlockFmt, BlockTyp, TextFmt, stripEscape from novelwriter.formats.tokenizer import Tokenizer -from novelwriter.types import FONT_STYLE, FONT_WEIGHTS +from novelwriter.types import FONT_STYLE, FONT_WEIGHTS, QtHexRgb logger = logging.getLogger(__name__) @@ -217,13 +217,6 @@ def __init__(self, project: NWProject, isFlat: bool) -> None: self._mDocLeft = "2.000cm" self._mDocRight = "2.000cm" - # Colour - self._colDialogM = "#2a6099" - self._colDialogA = "#813709" - self._colMetaTx = "#813709" - self._opaMetaTx = "100%" - self._markText = "#ffffa6" - return ## @@ -484,8 +477,7 @@ def doConvert(self) -> None: self._addTextPar(xText, S_META, oStyle, tText, tFmt=tFormat) elif tType == BlockTyp.KEYWORD: - tTemp, tFmt = self._formatKeywords(tText) - self._addTextPar(xText, S_META, oStyle, tTemp, tFmt=tFmt) + self._addTextPar(xText, S_META, oStyle, tText, tFmt=tFormat) return @@ -553,22 +545,6 @@ def xmlToZip(name: str, xObj: ET.Element, zipObj: ZipFile) -> None: # Internal Functions ## - def _formatKeywords(self, text: str) -> tuple[str, T_Formats]: - """Apply formatting to keywords.""" - valid, bits, _ = self._project.index.scanThis("@"+text) - if not valid or not bits or bits[0] not in nwLabels.KEY_NAME: - return "", [] - - rTxt = f"{self._localLookup(nwLabels.KEY_NAME[bits[0]])}: " - rFmt: T_Formats = [(0, TextFmt.B_B, ""), (len(rTxt) - 1, TextFmt.B_E, "")] - if len(bits) > 1: - if bits[0] == nwKeyWords.TAG_KEY: - rTxt += bits[1] - else: - rTxt += ", ".join(bits[1:]) - - return rTxt, rFmt - def _addTextPar( self, xParent: ET.Element, @@ -598,7 +574,6 @@ def _addTextPar( parProc = XMLParagraph(xElem) - pErr = 0 xFmt = 0x00 tFrag = "" fLast = 0 @@ -657,8 +632,6 @@ def _addTextPar( xNode = self._generateFootnote(fData) elif fFmt == TextFmt.STRIP: pass - else: - pErr += 1 fLast = fPos @@ -671,9 +644,6 @@ def _addTextPar( else: parProc.appendSpan(tFrag, self._textStyle(xFmt, fClass)) - if pErr > 0: - self._errData.append("Unknown format tag encountered") - nErr, errMsg = parProc.checkError() if nErr > 0: # pragma: no cover # This one should only capture bugs @@ -725,17 +695,13 @@ def _textStyle(self, hFmt: int, fClass: str = "") -> str: style.setUnderlineWidth("auto") style.setUnderlineColor("font-color") if hFmt & X_MRK: - style.setBackgroundColor(self._markText) + style.setBackgroundColor(self._theme.highlight) if hFmt & X_SUP: style.setTextPosition("super") if hFmt & X_SUB: style.setTextPosition("sub") if hFmt & X_COL and color: style.setColor(color) - # if hFmt & X_DLG: - # style.setColour(self._colDialogM) - # if hFmt & X_DLA: - # style.setColour(self._colDialogA) self._autoText[tKey] = style return style.name @@ -1265,7 +1231,7 @@ def setFontWeight(self, value: str | None) -> None: def setColor(self, value: QColor | None) -> None: """Set text colour.""" if isinstance(value, QColor): - self._tAttr["color"][1] = value.name(QColor.NameFormat.HexRgb) + self._tAttr["color"][1] = value.name(QtHexRgb) self._tAttr["opacity"][1] = f"{int(100.0 * value.alphaF())}%" else: self._tAttr["color"][1] = None @@ -1373,15 +1339,15 @@ def setFontStyle(self, value: str | None) -> None: def setColor(self, value: QColor | None) -> None: """Set text colour.""" if isinstance(value, QColor): - self._tAttr["color"][1] = value.name(QColor.NameFormat.HexRgb) + self._tAttr["color"][1] = value.name(QtHexRgb) else: self._tAttr["color"][1] = None return - def setBackgroundColor(self, value: str | None) -> None: + def setBackgroundColor(self, value: QColor | None) -> None: """Set text background colour.""" - if value and len(value) == 7 and value[0] == "#": - self._tAttr["background-color"][1] = value + if isinstance(value, QColor): + self._tAttr["background-color"][1] = value.name(QtHexRgb) else: self._tAttr["background-color"][1] = None return diff --git a/novelwriter/formats/toqdoc.py b/novelwriter/formats/toqdoc.py index e0b1faf55..30ee93370 100644 --- a/novelwriter/formats/toqdoc.py +++ b/novelwriter/formats/toqdoc.py @@ -34,7 +34,7 @@ ) from PyQt5.QtPrintSupport import QPrinter -from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels, nwStyles, nwUnicode +from novelwriter.constants import nwHeadFmt, nwStyles, nwUnicode from novelwriter.core.project import NWProject from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt from novelwriter.formats.tokenizer import Tokenizer @@ -146,7 +146,7 @@ def initDocument(self) -> None: self._mIndent = mPx * 2.0 self._tIndent = mPx * self._firstWidth - # Block Format + # Text Formats # ============ self._blockFmt = QTextBlockFormat() @@ -157,24 +157,9 @@ def initDocument(self) -> None: 100*self._lineHeight, QTextBlockFormat.LineHeightTypes.ProportionalHeight ) - # Character Formats - # ================= - - self._cText = QTextCharFormat() - self._cText.setBackground(QtTransparent) - self._cText.setForeground(self._theme.text) - - self._cCode = QTextCharFormat(self._cText) - self._cCode.setForeground(self._theme.code) - - self._cKeyword = QTextCharFormat(self._cText) - self._cKeyword.setForeground(self._theme.keyword) - - self._cTag = QTextCharFormat(self._cText) - self._cTag.setForeground(self._theme.tag) - - self._cOptional = QTextCharFormat(self._cText) - self._cOptional.setForeground(self._theme.optional) + self._charFmt = QTextCharFormat() + self._charFmt.setBackground(QtTransparent) + self._charFmt.setForeground(self._theme.text) self._init = True @@ -193,6 +178,13 @@ def doConvert(self) -> None: # Styles bFmt = QTextBlockFormat(self._blockFmt) + if tType in (BlockTyp.COMMENT, BlockTyp.KEYWORD): + bFmt.setTopMargin(self._mMeta[0]) + bFmt.setBottomMargin(self._mMeta[1]) + elif tType == BlockTyp.SEP: + bFmt.setTopMargin(self._mSep[0]) + bFmt.setBottomMargin(self._mSep[1]) + if tStyle is not None: if tStyle & BlockFmt.LEFT: bFmt.setAlignment(QtAlignLeft) @@ -220,9 +212,9 @@ def doConvert(self) -> None: if tStyle & BlockFmt.IND_T: bFmt.setTextIndent(self._tIndent) - if tType == BlockTyp.TEXT: + if tType in (BlockTyp.TEXT, BlockTyp.COMMENT, BlockTyp.KEYWORD): newBlock(cursor, bFmt) - self._insertFragments(tText, tFormat, cursor, self._cText) + self._insertFragments(tText, tFormat, cursor, self._charFmt) elif tType in self.L_HEADINGS: bFmt, cFmt = self._genHeadStyle(tType, nHead, bFmt) @@ -230,23 +222,12 @@ def doConvert(self) -> None: cursor.insertText(tText.replace(nwHeadFmt.BR, "\n"), cFmt) elif tType == BlockTyp.SEP: - sFmt = QTextBlockFormat(bFmt) - sFmt.setTopMargin(self._mSep[0]) - sFmt.setBottomMargin(self._mSep[1]) - newBlock(cursor, sFmt) - cursor.insertText(tText, self._cText) - - elif tType == BlockTyp.SKIP: newBlock(cursor, bFmt) - cursor.insertText(nwUnicode.U_NBSP, self._cText) + cursor.insertText(tText, self._charFmt) - elif tType == BlockTyp.COMMENT: - newBlock(cursor, bFmt) - self._insertFragments(tText, tFormat, cursor, self._cText) - - elif tType == BlockTyp.KEYWORD: + elif tType == BlockTyp.SKIP: newBlock(cursor, bFmt) - self._insertKeywords(tText, cursor) + cursor.insertText(nwUnicode.U_NBSP, self._charFmt) self._document.blockSignals(False) @@ -281,12 +262,13 @@ def appendFootnotes(self) -> None: for key, index in self._usedNotes.items(): if content := self._footnotes.get(key): - cFmt = QTextCharFormat(self._cCode) + cFmt = QTextCharFormat(self._charFmt) + cFmt.setForeground(self._theme.code) cFmt.setAnchor(True) cFmt.setAnchorNames([f"footnote_{index}"]) newBlock(cursor, self._blockFmt) cursor.insertText(f"{index}. ", cFmt) - self._insertFragments(*content, cursor, self._cText) + self._insertFragments(*content, cursor, self._charFmt) self._document.blockSignals(False) @@ -342,8 +324,21 @@ def _insertFragments( cFmt.setForeground(color) elif fmt == TextFmt.COL_E: cFmt.setForeground(self._theme.text) + elif fmt == TextFmt.ANM_B: + cFmt.setAnchor(True) + cFmt.setAnchorNames([data]) + elif fmt == TextFmt.ANM_E: + cFmt.setAnchor(False) + elif fmt == TextFmt.HRF_B: + cFmt.setFontUnderline(True) + cFmt.setAnchor(True) + cFmt.setAnchorHref(data) + elif fmt == TextFmt.HRF_E: + cFmt.setFontUnderline(False) + cFmt.setAnchor(False) elif fmt == TextFmt.FNOTE: - xFmt = QTextCharFormat(self._cCode) + xFmt = QTextCharFormat(self._charFmt) + xFmt.setForeground(self._theme.code) xFmt.setVerticalAlignment(QtVAlignSuper) if data in self._footnotes: index = len(self._usedNotes) + 1 @@ -363,33 +358,6 @@ def _insertFragments( return - def _insertKeywords(self, text: str, cursor: QTextCursor) -> None: - """Apply Markdown formatting to keywords.""" - valid, bits, _ = self._project.index.scanThis("@"+text) - if valid and bits: - key = f"{self._localLookup(nwLabels.KEY_NAME[bits[0]])}: " - cursor.insertText(key, self._cKeyword) - if (num := len(bits)) > 1: - if bits[0] == nwKeyWords.TAG_KEY: - one, two = self._project.index.parseValue(bits[1]) - cFmt = QTextCharFormat(self._cTag) - cFmt.setAnchor(True) - cFmt.setAnchorNames([f"tag_{one}".lower()]) - cursor.insertText(one, cFmt) - if two: - cursor.insertText(" | ", self._cText) - cursor.insertText(two, self._cOptional) - else: - for n, bit in enumerate(bits[1:], 2): - cFmt = QTextCharFormat(self._cTag) - cFmt.setFontUnderline(True) - cFmt.setAnchor(True) - cFmt.setAnchorHref(f"#tag_{bit}".lower()) - cursor.insertText(bit, cFmt) - if n < num: - cursor.insertText(", ", self._cText) - return - def _genHeadStyle(self, hType: BlockTyp, nHead: int, rFmt: QTextBlockFormat) -> T_TextStyle: """Generate a heading style set.""" mTop, mBottom = self._mHead.get(hType, (0.0, 0.0)) @@ -398,11 +366,11 @@ def _genHeadStyle(self, hType: BlockTyp, nHead: int, rFmt: QTextBlockFormat) -> bFmt.setTopMargin(mTop) bFmt.setBottomMargin(mBottom) - self._cTitle = QTextCharFormat(self._cText) + self._cTitle = QTextCharFormat(self._charFmt) self._cTitle.setFontWeight(self._bold if self._boldHeads else self._normal) hCol = self._colorHeads and hType != BlockTyp.TITLE - cFmt = QTextCharFormat(self._cText) + cFmt = QTextCharFormat(self._charFmt) cFmt.setForeground(self._theme.head if hCol else self._theme.text) cFmt.setFontWeight(self._bold if self._boldHeads else self._normal) cFmt.setFontPointSize(self._sHead.get(hType, 1.0)) diff --git a/tests/reference/fmtToDocX_SaveDocument_document.xml b/tests/reference/fmtToDocX_SaveDocument_document.xml index 0ec28de52..1ab3dbc87 100644 --- a/tests/reference/fmtToDocX_SaveDocument_document.xml +++ b/tests/reference/fmtToDocX_SaveDocument_document.xml @@ -190,12 +190,19 @@ + Point of View: - Bod + + + + + + + Bod @@ -206,12 +213,19 @@ + Plot: - Main + + + + + + + Main @@ -222,12 +236,19 @@ + Locations: - Europe + + + + + + + Europe @@ -269,12 +290,19 @@ + Point of View: - Bod + + + + + + + Bod @@ -285,12 +313,19 @@ + Plot: - Main + + + + + + + Main @@ -301,12 +336,19 @@ + Locations: - Europe + + + + + + + Europe @@ -389,12 +431,19 @@ + Point of View: - Bod + + + + + + + Bod @@ -405,12 +454,19 @@ + Plot: - Main + + + + + + + Main @@ -421,12 +477,19 @@ + Locations: - Europe + + + + + + + Europe @@ -530,12 +593,19 @@ + Point of View: - Bod + + + + + + + Bod @@ -546,12 +616,19 @@ + Plot: - Main + + + + + + + Main @@ -562,12 +639,19 @@ + Locations: - Europe + + + + + + + Europe @@ -609,12 +693,19 @@ + Point of View: - Bod + + + + + + + Bod @@ -625,12 +716,19 @@ + Plot: - Main + + + + + + + Main @@ -641,12 +739,19 @@ + Locations: - Europe + + + + + + + Europe @@ -729,12 +834,19 @@ + Point of View: - Bod + + + + + + + Bod @@ -745,12 +857,19 @@ + Plot: - Main + + + + + + + Main @@ -761,12 +880,19 @@ + Locations: - Europe + + + + + + + Europe @@ -868,12 +994,19 @@ + Point of View: - Bod + + + + + + + Bod @@ -884,12 +1017,19 @@ + Plot: - Main + + + + + + + Main @@ -900,12 +1040,19 @@ + Locations: - Europe + + + + + + + Europe @@ -1009,12 +1156,29 @@ + Tag: - Bod | Nobody Owens + + + + + + + Bod + + + + | + + + + + + Nobody Owens @@ -1025,12 +1189,19 @@ + Plot: - Main + + + + + + + Main @@ -1091,12 +1262,19 @@ + Tag: - Main + + + + + + + Main @@ -1147,12 +1325,29 @@ + Tag: - Europe | Ancient Europe + + + + + + + Europe + + + + | + + + + + + Ancient Europe diff --git a/tests/reference/mBuildDocBuild_HTML5_Lorem_Ipsum.htm b/tests/reference/mBuildDocBuild_HTML5_Lorem_Ipsum.htm index 5cf21e0a8..2f4b9a3cf 100644 --- a/tests/reference/mBuildDocBuild_HTML5_Lorem_Ipsum.htm +++ b/tests/reference/mBuildDocBuild_HTML5_Lorem_Ipsum.htm @@ -13,9 +13,8 @@ h4 {color: #4271ae; page-break-after: avoid; margin-top: 1.53em; margin-bottom: 0.65em;} .title {font-size: 2.5em; margin-top: 1.85em; margin-bottom: 0.65em;} .sep, .skip {text-align: center; margin-top: 1.30em; margin-bottom: 1.30em;} -a {color: rgb(66, 113, 174);} -mark {background: rgb(255, 255, 166);} -.keyword {color: rgb(245, 135, 31); font-weight: bold;} +a {color: #4271ae;} +mark {background: #ffffa6;}
@@ -23,35 +22,35 @@

Lorem Ipsum

By lipsum.com

“Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit…”

“There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain…”

-

Comment: Exctracted from the lipsum.com website.

+

Comment: Exctracted from the lipsum.com website.

Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.

The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.

Prologue

-

Synopsis: Explanation from the lipsum.com website.

+

Synopsis: Explanation from the lipsum.com website.

Lorem Ipsum is simply dummy text1 of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Part: Act One

“Fusce maximus felis libero”

Chapter: Chapter One

-

Point of View: Bod

-

Plot: Main

-

Locations: Europe

-

Synopsis: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam.

+

Point of View: Bod

+

Plot: Main

+

Locations: Europe

+

Synopsis: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam. Praesent magna nunc, lacinia sit amet quam eget, aliquet ultrices justo. Morbi ornare enim et lorem rutrum finibus ut eu dolor. Aliquam a orci odio. Ut ultrices sem quis massa placerat, eget mollis nisl cursus. Cras vel sagittis justo. Ut non ultricies leo. Maecenas rutrum velit in est varius, et egestas massa pulvinar.

Scene: Scene One

-

Point of View: Bod

-

Plot: Main

-

Locations: Europe

-

Synopsis: Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur.

+

Point of View: Bod

+

Plot: Main

+

Locations: Europe

+

Synopsis: Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur.

Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur. Donec quis ante nunc. Mauris ut leo ipsum. Vestibulum est neque, hendrerit nec neque a, ullamcorper lobortis tellus. Fusce sollicitudin purus quis congue bibendum. Aliquam condimentum ipsum tristique blandit tristique. Donec pulvinar neque ac suscipit malesuada.

Aliquam ut nisl arcu. Ut ultricies, lorem dignissim rutrum convallis, risus orci tempus lectus, congue feugiat sem lectus vitae odio. Duis sit amet justo finibus, hendrerit nulla at, ullamcorper enim. Praesent vel tellus sit amet tellus vulputate bibendum. Morbi eleifend sagittis sem, ac volutpat ante congue non. In hac habitasse platea dictumst. Morbi lobortis fermentum elit, dignissim sagittis ligula volutpat lacinia. Vestibulum eu interdum odio. Integer ac purus commodo metus congue tempor non at urna. Sed eget tortor vel quam viverra egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec non convallis mauris, ac feugiat ex.

Section: Scene One, Section Two

Integer vel libero ipsum. Donec varius aliquam libero, sit amet commodo urna hendrerit non. Nullam quis erat mollis nunc viverra volutpat tincidunt in odio. Nam vitae quam sem. Aliquam suscipit nulla non lorem pharetra semper. Ut suscipit erat eu ligula accumsan ultrices. Phasellus nisl tellus, placerat sed laoreet id, consectetur nec dolor. Sed fringilla ipsum id dapibus posuere. Aenean finibus pharetra tincidunt. Ut molestie malesuada nulla, id posuere lorem tincidunt eu. Aliquam tempor eros a est vulputate, scelerisque pulvinar ipsum fermentum. In hac habitasse platea dictumst.

Curabitur congue, justo quis interdum fermentum, tellus nulla imperdiet sapien, eu interdum enim tellus condimentum metus. Vivamus nunc velit, dignissim ut ultrices sit amet, ultricies quis enim. Donec ut vestibulum neque. Vivamus semper neque id ex ullamcorper varius. Fusce mattis nibh viverra lorem sagittis, et tempor arcu congue. Suspendisse sit amet felis sed urna facilisis mattis eget vitae arcu. Proin eu magna hendrerit, tristique sem maximus, placerat diam. Nulla tristique sed velit sit amet varius. Etiam vel ornare magna, in vulputate arcu. Cras velit orci, tincidunt sed volutpat cursus, bibendum vel sem. Nunc vulputate pharetra tortor, ac consectetur neque tincidunt sit amet. Nulla ornare mi sed mi dignissim ultricies. Ut tincidunt bibendum mauris, sed elementum ex vulputate vel. Mauris fermentum, felis nec vehicula congue, felis lorem facilisis erat, a dictum dolor augue vitae quam. Maecenas rutrum tortor nec consequat eleifend.

Scene: Scene Two

-

Point of View: Bod

-

Plot: Main

-

Locations: Europe

-

Synopsis: Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci.

+

Point of View: Bod

+

Plot: Main

+

Locations: Europe

+

Synopsis: Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci.

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci. Vestibulum facilisis bibendum aliquam. Aliquam posuere, turpis ac bibendum varius, sem tellus venenatis risus, in elementum massa enim ac lorem. Integer in sem ac diam blandit ultricies ut in nulla. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam sit amet erat est. Curabitur vitae cursus justo, sit amet placerat dolor. Vivamus eu felis hendrerit, tincidunt massa rutrum, maximus arcu. Pellentesque commodo justo odio, vel rutrum nulla tincidunt eu. Integer non neque condimentum, convallis diam non, varius ligula. Aliquam eget sapien mauris. Aenean pharetra nunc nisi, vel maximus ante tristique sit amet. Aliquam risus metus, interdum non odio eu, consectetur lacinia sapien.

Proin vitae gravida nisl. Integer viverra orci turpis, sit amet pretium ligula facilisis consequat. Nulla interdum commodo metus, mollis consequat dui tincidunt et. Proin consequat bibendum justo id commodo. Fusce fermentum nunc turpis, eu vestibulum risus feugiat ut. Sed scelerisque vel ligula ut interdum. Suspendisse ac blandit ligula, sagittis fringilla dolor. In tincidunt convallis diam et ornare. Aenean id dignissim est, ut rhoncus quam. Donec vitae nisl velit. In convallis nibh ut augue dignissim, eu elementum quam cursus. Phasellus in lectus lorem. Curabitur in pellentesque nisi, at gravida sapien. Sed cursus justo volutpat lacus placerat, sit amet dignissim turpis commodo. Aliquam vitae orci eget nulla posuere condimentum in ut felis.

Nulla accumsan ante in pulvinar efficitur. Nulla non velit quis urna hendrerit bibendum. Suspendisse ultrices ante eu justo malesuada, sed fermentum enim rutrum. Nunc fermentum pharetra felis, vitae sollicitudin quam rutrum porta. Aliquam fringilla velit a mi laoreet, et luctus est rutrum. In gravida non ipsum sit amet tempus. Curabitur et eleifend purus. Nulla facilisi.

@@ -60,30 +59,30 @@

Section: Scene Two, Section Two

Vivamus ut venenatis lectus. Phasellus nec elit id sem dictum ornare. Quisque feugiat, diam eget sagittis ultricies, orci turpis efficitur nisi, et fringilla justo odio nec nibh. In hac habitasse platea dictumst. Sed tempus bibendum feugiat. Etiam luctus mauris arcu, non interdum ipsum ultrices id. Vivamus blandit urna sit amet scelerisque vulputate. Quisque in metus eget massa rutrum dictum sit amet sed nulla. Vivamus vel efficitur dolor.

Ut et consequat enim, quis ornare nibh. In lectus neque, mollis et suscipit et, vestibulum vitae augue. Praesent id ante sit amet odio venenatis placerat a at erat. Sed sed metus sed nisi dictum varius. Integer tincidunt fermentum purus ac porta. Fusce porttitor non risus eget tristique. Donec augue nunc, maximus at fermentum vel, varius et neque. Ut sed consectetur mauris. Quisque ipsum enim, porttitor vitae imperdiet sit amet, tempor et mauris. Aliquam malesuada tincidunt lectus quis blandit. Sed commodo orci felis, quis ultrices tellus facilisis sed. Nunc vel varius est. Duis ullamcorper eu metus in pulvinar. Morbi at sapien dictum, rutrum mauris eget, interdum tellus.

Why do we use it?

-

Comment: Exctracted from the lipsum.com website.

+

Comment: Exctracted from the lipsum.com website.

        It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.

        The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English.

        Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).

Chapter: Chapter Two

-

Point of View: Bod

-

Plot: Main

-

Locations: Europe

-

Synopsis: Curabitur a elit posuere, varius ex et, convallis neque. Phasellus sagittis pharetra sem vitae dapibus. Curabitur varius lorem non pulvinar congue.

+

Point of View: Bod

+

Plot: Main

+

Locations: Europe

+

Synopsis: Curabitur a elit posuere, varius ex et, convallis neque. Phasellus sagittis pharetra sem vitae dapibus. Curabitur varius lorem non pulvinar congue.

Curabitur a elit posuere, varius ex et, convallis neque. Phasellus sagittis pharetra sem vitae dapibus. Curabitur varius lorem non pulvinar congue. Vestibulum pharetra fermentum leo, sed faucibus eros placerat quis. In hac habitasse platea dictumst. Donec metus massa, rutrum quis consequat et, tincidunt ac felis. Duis mollis metus ac nunc tincidunt blandit. Ut aliquet velit eu odio pharetra condimentum. Integer rutrum lacus orci, id venenatis libero accumsan at.

Scene: Scene Three

-

Point of View: Bod

-

Plot: Main

-

Locations: Europe

-

Synopsis: Aenean ut libero ut lectus porttitor rhoncus vel et massa. Nam pretium, nibh et varius vehicula, urna metus blandit eros, euismod pharetra diam diam et libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.

+

Point of View: Bod

+

Plot: Main

+

Locations: Europe

+

Synopsis: Aenean ut libero ut lectus porttitor rhoncus vel et massa. Nam pretium, nibh et varius vehicula, urna metus blandit eros, euismod pharetra diam diam et libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.

Aenean ut libero ut lectus porttitor rhoncus vel et massa. Nam pretium, nibh et varius vehicula, urna metus blandit eros, euismod pharetra diam diam et libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean tincidunt lacus vitae nibh elementum eleifend. Sed rutrum condimentum sem quis blandit. Duis imperdiet libero metus, quis convallis quam faucibus a. Nulla ligula est, semper quis sollicitudin et, pretium id justo. Curabitur pharetra risus eget consectetur commodo. Duis mattis arcu non est condimentum, id venenatis risus volutpat. Pellentesque aliquet mauris non mauris porttitor ultrices. Phasellus ut vestibulum mi. Suspendisse malesuada metus lorem, a malesuada orci rhoncus a. Praesent euismod convallis ante, lacinia tincidunt ex egestas id. Praesent sit amet efficitur sapien. Morbi tincidunt volutpat nunc sed dictum. Aliquam ultrices metus id fermentum lobortis.

Pellentesque id sagittis dui. Praesent ut nisi sit amet libero euismod ornare. Vestibulum vehicula, lorem eget aliquet imperdiet, eros nulla iaculis mi, vel bibendum est dui sed orci. Nullam vitae lorem rutrum, euismod lacus id, ullamcorper lectus. Duis nec commodo mi, a fringilla diam. Vestibulum molestie nibh tristique, viverra augue non, aliquet metus. Phasellus a tellus ac nisl tempor aliquet. Nulla vitae sapien rutrum augue ornare ultrices a quis nisi. Sed pulvinar tincidunt ex. Fusce vel sem vitae ante pellentesque lobortis.

Maecenas ullamcorper lacus nec turpis finibus aliquet eget rutrum augue. Integer lorem erat, faucibus non lacus lacinia, pulvinar egestas felis. Proin rutrum nunc eget nulla varius, id blandit mauris tincidunt. Donec sit amet ullamcorper nisi, ut efficitur mi. Aliquam aliquet, nulla eget rhoncus tristique, justo lorem consectetur dui, id ornare leo odio sed tellus. Curabitur interdum velit a turpis condimentum venenatis. Nunc rhoncus sem ac augue auctor, nec malesuada ex fringilla. Vestibulum egestas diam sed leo consectetur vulputate quis eget enim. Nam tincidunt metus sit amet maximus ullamcorper. Sed placerat velit vitae massa efficitur viverra. Etiam eleifend dignissim ante, sed luctus nisl tristique a. In vestibulum pharetra dolor in molestie. Vivamus auctor massa ac magna imperdiet, sit amet iaculis turpis finibus.

Aenean dapibus vulputate purus, sit amet tempor nunc suscipit consequat. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris auctor congue eros, non pellentesque neque dapibus ac. Vestibulum non leo nec urna lacinia eleifend quis et diam. Praesent eu nisi magna. Nulla at magna massa. Suspendisse porta varius scelerisque. Duis at auctor dolor, non dapibus urna. Nunc venenatis feugiat magna non molestie. Aliquam non ornare ex. Quisque eu ultrices velit, quis pellentesque eros. Phasellus eleifend, elit id imperdiet aliquam, nulla quam molestie turpis, at egestas odio ante et tortor. Suspendisse fringilla condimentum justo, at aliquet odio aliquam ac.

Scene: Scene Four

-

Point of View: Bod

-

Plot: Main

-

Locations: Europe

-

Synopsis: Nam tempor blandit magna laoreet aliquet. Vestibulum auctor posuere leo, ac gravida nisi rhoncus varius. Aenean posuere dolor vitae condimentum volutpat. Donec egestas volutpat risus, quis luctus justo.

+

Point of View: Bod

+

Plot: Main

+

Locations: Europe

+

Synopsis: Nam tempor blandit magna laoreet aliquet. Vestibulum auctor posuere leo, ac gravida nisi rhoncus varius. Aenean posuere dolor vitae condimentum volutpat. Donec egestas volutpat risus, quis luctus justo.

Nam tempor blandit magna laoreet aliquet. Vestibulum auctor posuere leo, ac gravida nisi rhoncus varius. Aenean posuere dolor vitae condimentum volutpat. Donec egestas volutpat risus, quis luctus justo. Nullam viverra dui et auctor pretium. Ut ullamcorper velit urna, sed imperdiet massa convallis a. Suspendisse efficitur, ipsum nec cursus pulvinar, eros urna posuere diam, nec elementum mi felis vitae sapien.

Duis efficitur metus pulvinar, molestie magna eget, feugiat dui. Fusce convallis vehicula ipsum convallis blandit. Duis eros risus, malesuada eu imperdiet in, hendrerit ac metus. Vestibulum id justo gravida, dignissim nibh non, iaculis diam. Fusce accumsan est ut massa porta ultricies. Nulla vitae justo in tortor laoreet mollis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin eu libero justo. Vivamus aliquet placerat est, et auctor eros posuere venenatis. Nunc quam diam, tincidunt ac aliquet in, fermentum sit amet lectus. Proin commodo tincidunt blandit. Quisque erat arcu, semper nec dui non, consectetur gravida ipsum. Nullam pretium consectetur elit at condimentum.

Etiam sagittis, erat vitae accumsan tempor, neque augue scelerisque nulla, ut ultrices justo urna sit amet augue. Interdum et malesuada fames ac ante ipsum primis in faucibus. Aenean at pulvinar tortor. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Cras vel porta quam. Nullam eu mauris mollis, vehicula justo vel, placerat sapien. Phasellus viverra elit et vestibulum pharetra. Vestibulum commodo fermentum leo, eu porta nisi aliquam eget. Nulla tempus porttitor nisi nec mollis. Nam non mollis turpis. Nam finibus leo a bibendum tincidunt. Donec commodo velit magna, ac semper sapien mattis id. Proin sem velit, lobortis quis ultricies id, pharetra et lectus. Vestibulum condimentum neque vitae mi dapibus mollis. Mauris luctus vel sapien vitae hendrerit.

@@ -91,10 +90,10 @@

Scene: Scene Four

Donec ipsum eros, vestibulum sit amet cursus eget, iaculis quis dolor. Pellentesque magna augue, tristique dapibus mi vitae, molestie venenatis enim. Nam malesuada, turpis volutpat rhoncus ullamcorper, justo est eleifend orci, ut luctus risus ex rutrum arcu. Sed mi elit, feugiat rhoncus ornare sed, porta id leo. Pellentesque feugiat nulla tincidunt erat suscipit, eu congue lacus hendrerit. Morbi pulvinar enim sed consequat auctor. Ut eleifend enim sem, vitae euismod ex ultricies sit amet. Curabitur eu efficitur nisi, suscipit finibus sapien. In sodales blandit erat, vestibulum pulvinar ante volutpat nec. Vivamus dictum non libero at molestie. Donec sit amet neque in ante convallis pretium. Nunc vel iaculis dui.

Phasellus eu nunc ut nunc faucibus laoreet. Aliquam at magna risus. Praesent lobortis, risus finibus semper varius, magna purus vestibulum eros, at pulvinar sapien enim a ex. In scelerisque malesuada ex, sit amet egestas neque condimentum sed. Praesent vulputate efficitur massa. Cras at accumsan ligula. In elementum lectus eget blandit dictum. Nam vitae libero ut justo eleifend rutrum ac nec arcu. Aliquam sodales in quam congue vestibulum. Aliquam in accumsan sapien. Quisque lobortis nisl nisi, vitae bibendum turpis efficitur sed. Vestibulum tempor nulla eget nisi convallis, blandit sagittis ipsum convallis. Donec odio nibh, ultrices quis odio in, mollis euismod libero.

Scene: Scene Five

-

Point of View: Bod

-

Plot: Main

-

Locations: Europe

-

Synopsis: Praesent eget est porta, dictum ante in, egestas risus. Mauris risus mauris, consequat aliquam mauris et, feugiat iaculis ipsum. Aliquam arcu ipsum, fermentum ut arcu sed, lobortis euismod sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.

+

Point of View: Bod

+

Plot: Main

+

Locations: Europe

+

Synopsis: Praesent eget est porta, dictum ante in, egestas risus. Mauris risus mauris, consequat aliquam mauris et, feugiat iaculis ipsum. Aliquam arcu ipsum, fermentum ut arcu sed, lobortis euismod sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.

Praesent eget est porta, dictum ante in, egestas risus. Mauris risus mauris, consequat aliquam mauris et, feugiat iaculis ipsum. Aliquam arcu ipsum, fermentum ut arcu sed, lobortis euismod sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In sed felis auctor, rhoncus dui ac, consequat dolor. Integer volutpat libero sed nisl aliquet varius. Suspendisse et lorem sapien. Proin id ultrices nibh, ac suscipit diam. Suspendisse placerat varius porttitor. Curabitur elementum sed enim ultrices imperdiet.

In ut lobortis lacus, nec luctus arcu. Vivamus condimentum sapien a ipsum malesuada sodales. Donec et vestibulum risus. Integer dictum euismod eros id tincidunt. Aliquam sagittis leo vitae consequat fermentum. Donec maximus ex eu ex iaculis porta. Praesent pharetra lacinia risus, et eleifend diam commodo non. Sed feugiat ipsum ut orci sagittis, quis faucibus lectus blandit. Sed tellus quam, gravida vitae laoreet quis, tempus lobortis dui. Vivamus semper accumsan ullamcorper. Praesent tempus pretium eros, non elementum risus. Pellentesque odio quam, auctor quis ex non, vulputate egestas dolor. Nunc luctus enim ut justo sodales consectetur. Sed aliquet a mauris vel posuere.

Donec luctus lectus efficitur, blandit nisi vitae, dignissim tellus. Pellentesque euismod pharetra augue gravida hendrerit. Quisque nisi mi, mattis ac nisi non, maximus malesuada ante. Nulla lobortis, diam eu ornare ornare, tellus enim feugiat arcu, non vestibulum tortor nunc eu justo. Integer blandit felis justo, eu semper est scelerisque vel. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nam ultricies, nisi vel elementum commodo, nisl dolor tincidunt magna, sed varius est nunc at lectus. Aliquam dolor tortor, sodales placerat ultricies quis, sodales quis sapien. Duis ullamcorper sollicitudin risus at mattis. Integer consequat et nunc at condimentum. Pellentesque cursus congue augue, non suscipit lectus sodales ut. Nam a mi bibendum, blandit nisl eu, accumsan nunc. Aliquam a ex mauris. Sed nec sem quis arcu dignissim tempus eget et turpis. Ut sed ex nec ipsum ultrices lobortis.

@@ -102,19 +101,19 @@

Scene: Scene Five

Integer egestas maximus leo eu facilisis. Nunc rhoncus dignissim lectus eu lacinia. Praesent lacinia urna porttitor aliquam condimentum. Nulla eu eros dictum, dictum nunc vitae, sagittis nibh. Integer ante neque, consequat nec sollicitudin id, consectetur vitae dolor. Nullam volutpat sem orci, quis viverra magna auctor a. Suspendisse potenti. Maecenas commodo sed neque pellentesque vehicula. Sed luctus nisl risus, elementum semper purus interdum vel. Ut pulvinar, massa sit amet venenatis placerat, nunc lacus hendrerit odio, non aliquet nunc risus eu lectus. Maecenas feugiat semper ligula, id lobortis sem porta eu. Integer posuere elit magna, at mollis eros bibendum et. Ut imperdiet purus vel nulla aliquam maximus. Morbi sodales purus tellus, a rhoncus sem rutrum sit amet. Quisque risus sem, laoreet nec convallis nec, rutrum vitae justo.

Notes: Characters

Nobody Owens

-

Tag: Bod | Nobody Owens

-

Plot: Main

+

Tag: Bod | Nobody Owens

+

Plot: Main

Pellentesque nec erat ut nulla posuere commodo. Curabitur nisi augue, imperdiet et porta imperdiet, efficitur id leo. Cras finibus arcu at nibh commodo congue. Proin suscipit placerat condimentum. Aenean ante enim, cursus id lorem a, blandit venenatis nibh. Maecenas suscipit porta elit, sit amet porta felis porttitor eu. Sed a dui nibh. Phasellus sed faucibus dui. Pellentesque felis nulla, ultrices non efficitur quis, rutrum id mi. Mauris tempus auctor nisl, in bibendum enim pellentesque sit amet. Proin nunc lacus, imperdiet nec posuere ac, interdum non lectus.

Suspendisse faucibus est auctor orci mollis luctus. Praesent quis sodales neque. Interdum et malesuada fames ac ante ipsum primis in faucibus. Donec sodales rutrum mattis. In in sem ornare, consequat nulla ac, convallis arcu. Duis ac metus id felis commodo commodo sit amet eget diam. Curabitur rhoncus lacinia leo at sodales. Etiam finibus porta diam a viverra. Praesent nisi urna, volutpat sit amet odio at, vehicula vehicula leo. In non enim eget nisl luctus commodo. Pellentesque pellentesque at lectus at luctus. Quisque nec felis bibendum, lacinia libero ut, lacinia eros. Integer finibus ultricies nibh sit amet placerat.

Nullam scelerisque velit et tortor congue vestibulum a at nisi. Vivamus sodales ut turpis a convallis. In dignissim nibh at luctus sodales. Etiam sit amet rhoncus massa. Phasellus ligula magna, sollicitudin non imperdiet sit amet, volutpat vel magna. Nunc vestibulum tempor lectus, sit amet porta nunc hendrerit in. Curabitur non odio sit amet massa tincidunt facilisis. Integer et luctus nunc, eget euismod leo. Praesent faucibus metus sed purus convallis scelerisque. Fusce viverra lorem et placerat malesuada. In at elit malesuada, ullamcorper risus vitae, sodales dolor. Donec quis elementum lectus. Quisque eu eros at dui imperdiet euismod ut id neque.

Notes: Plot

Main Plot

-

Tag: Main

+

Tag: Main

Suspendisse vulputate malesuada pellentesque. Aenean sollicitudin cursus mi, vitae ultricies felis ullamcorper eu. Duis luctus risus mi, in accumsan velit cursus ut. Vestibulum eleifend leo in magna eleifend fermentum. Proin nec ornare elit. Phasellus nec interdum risus. In a volutpat augue, quis egestas justo. Morbi porta mauris mattis bibendum imperdiet.

Mauris ut erat eu lorem malesuada egestas vel vel urna. Maecenas ac semper quam. Maecenas aliquet metus non interdum mattis. Proin consectetur molestie ligula. Aliquam sollicitudin pulvinar urna a pellentesque. Suspendisse ultrices, est mattis scelerisque porta, nisi nisi laoreet nisl, non condimentum quam ante a velit. Proin scelerisque justo augue, nec laoreet ligula egestas at. Etiam enim quam, ultrices non accumsan hendrerit, elementum vel ligula. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nam efficitur odio libero, in vestibulum arcu aliquam at. Cras non vehicula augue. Integer lobortis, est vitae aliquam facilisis, metus ligula aliquet eros, at porttitor sem tortor eget massa. Aliquam varius scelerisque neque sed gravida. Aenean eleifend lorem id ante elementum sollicitudin. Proin commodo massa a quam volutpat, mollis fermentum turpis efficitur.

Notes: World

Ancient Europe

-

Tag: Europe | Ancient Europe

+

Tag: Europe | Ancient Europe

Vivamus sodales risus ac accumsan posuere. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nunc vel enim felis. Vestibulum dignissim massa nunc, a auctor magna eleifend et. Proin dignissim sodales erat vitae convallis. Aliquam id tellus dui. Curabitur sollicitudin scelerisque ex sit amet posuere. Nam rutrum felis id rhoncus feugiat. Duis sagittis quam quis purus efficitur, quis rutrum odio iaculis. Maecenas semper ante turpis, at vulputate mi consectetur non. Sed rutrum nibh turpis, quis rhoncus purus ornare quis. Vestibulum at rutrum mauris. Integer dolor nisi, tincidunt eget vehicula ac, ultricies at ligula.

Aenean semper turpis quis varius rhoncus. Vivamus ac mi eget felis euismod vulputate. Nam eu tempus velit. Etiam ut est porta, finibus erat sit amet, consectetur felis. Nullam consequat felis ut lacus pharetra, in lobortis urna mollis. Nulla varius eros nec lorem rhoncus, sed venenatis risus ultrices. Phasellus pellentesque laoreet neque, ut ultricies lacus vulputate quis. In malesuada dui sit amet est interdum, eget consectetur mi gravida. Cras vel bibendum purus. Quisque commodo tempor arcu, non lacinia sem blandit eleifend. Quisque at neque gravida, porttitor metus a, suscipit diam. Quisque convallis sodales lacus et condimentum. Donec a suscipit diam. Pellentesque eget cursus neque.

Nunc ullamcorper magna quis elit condimentum rhoncus. Aenean dictum pulvinar dolor suscipit interdum. Aliquam elit massa, elementum nec cursus eu, maximus nec ipsum. Donec ullamcorper iaculis dolor eu commodo. Nunc eget tortor quis turpis consectetur varius. Vestibulum nec justo vel tellus venenatis condimentum. Duis auctor iaculis massa. Nunc risus magna, rutrum vitae eros non, tristique mollis enim.

diff --git a/tests/reference/mBuildDocBuild_HTML5_Lorem_Ipsum.json b/tests/reference/mBuildDocBuild_HTML5_Lorem_Ipsum.json index 916f32721..e6e167e90 100644 --- a/tests/reference/mBuildDocBuild_HTML5_Lorem_Ipsum.json +++ b/tests/reference/mBuildDocBuild_HTML5_Lorem_Ipsum.json @@ -2,8 +2,8 @@ "meta": { "projectName": "Lorem Ipsum", "novelAuthor": "lipsum.com", - "buildTime": 1729614520, - "buildTimeStr": "2024-10-22 18:28:40" + "buildTime": 1729624698, + "buildTimeStr": "2024-10-22 21:18:18" }, "text": { "css": [ @@ -15,9 +15,8 @@ "h4 {color: #4271ae; page-break-after: avoid; margin-top: 1.53em; margin-bottom: 0.65em;}", ".title {font-size: 2.5em; margin-top: 1.85em; margin-bottom: 0.65em;}", ".sep, .skip {text-align: center; margin-top: 1.30em; margin-bottom: 1.30em;}", - "a {color: rgb(66, 113, 174);}", - "mark {background: rgb(255, 255, 166);}", - ".keyword {color: rgb(245, 135, 31); font-weight: bold;}" + "a {color: #4271ae;}", + "mark {background: #ffffa6;}" ], "html": [ [ @@ -27,13 +26,13 @@ "

\u201cThere is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain\u2026\u201d

" ], [ - "

Comment: Exctracted from the lipsum.com website.

", + "

Comment: Exctracted from the lipsum.com website.

", "

Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of \u201cde Finibus Bonorum et Malorum\u201d (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, \u201cLorem ipsum dolor sit amet..\u201d, comes from a line in section 1.10.32.

", "

The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from \u201cde Finibus Bonorum et Malorum\u201d by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.

" ], [ "

Prologue

", - "

Synopsis: Explanation from the lipsum.com website.

", + "

Synopsis: Explanation from the lipsum.com website.

", "

Lorem Ipsum is simply dummy text1 of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

" ], [ @@ -42,18 +41,18 @@ ], [ "

Chapter: Chapter One

", - "

Point of View: Bod

", - "

Plot: Main

", - "

Locations: Europe

", - "

Synopsis: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam.

", + "

Point of View: Bod

", + "

Plot: Main

", + "

Locations: Europe

", + "

Synopsis: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam.

", "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam. Praesent magna nunc, lacinia sit amet quam eget, aliquet ultrices justo. Morbi ornare enim et lorem rutrum finibus ut eu dolor. Aliquam a orci odio. Ut ultrices sem quis massa placerat, eget mollis nisl cursus. Cras vel sagittis justo. Ut non ultricies leo. Maecenas rutrum velit in est varius, et egestas massa pulvinar.

" ], [ "

Scene: Scene One

", - "

Point of View: Bod

", - "

Plot: Main

", - "

Locations: Europe

", - "

Synopsis: Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur.

", + "

Point of View: Bod

", + "

Plot: Main

", + "

Locations: Europe

", + "

Synopsis: Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur.

", "

Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur. Donec quis ante nunc. Mauris ut leo ipsum. Vestibulum est neque, hendrerit nec neque a, ullamcorper lobortis tellus. Fusce sollicitudin purus quis congue bibendum. Aliquam condimentum ipsum tristique blandit tristique. Donec pulvinar neque ac suscipit malesuada.

", "

Aliquam ut nisl arcu. Ut ultricies, lorem dignissim rutrum convallis, risus orci tempus lectus, congue feugiat sem lectus vitae odio. Duis sit amet justo finibus, hendrerit nulla at, ullamcorper enim. Praesent vel tellus sit amet tellus vulputate bibendum. Morbi eleifend sagittis sem, ac volutpat ante congue non. In hac habitasse platea dictumst. Morbi lobortis fermentum elit, dignissim sagittis ligula volutpat lacinia. Vestibulum eu interdum odio. Integer ac purus commodo metus congue tempor non at urna. Sed eget tortor vel quam viverra egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec non convallis mauris, ac feugiat ex.

", "

Section: Scene One, Section Two

", @@ -62,10 +61,10 @@ ], [ "

Scene: Scene Two

", - "

Point of View: Bod

", - "

Plot: Main

", - "

Locations: Europe

", - "

Synopsis: Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci.

", + "

Point of View: Bod

", + "

Plot: Main

", + "

Locations: Europe

", + "

Synopsis: Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci.

", "

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci. Vestibulum facilisis bibendum aliquam. Aliquam posuere, turpis ac bibendum varius, sem tellus venenatis risus, in elementum massa enim ac lorem. Integer in sem ac diam blandit ultricies ut in nulla. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam sit amet erat est. Curabitur vitae cursus justo, sit amet placerat dolor. Vivamus eu felis hendrerit, tincidunt massa rutrum, maximus arcu. Pellentesque commodo justo odio, vel rutrum nulla tincidunt eu. Integer non neque condimentum, convallis diam non, varius ligula. Aliquam eget sapien mauris. Aenean pharetra nunc nisi, vel maximus ante tristique sit amet. Aliquam risus metus, interdum non odio eu, consectetur lacinia sapien.

", "

Proin vitae gravida nisl. Integer viverra orci turpis, sit amet pretium ligula facilisis consequat. Nulla interdum commodo metus, mollis consequat dui tincidunt et. Proin consequat bibendum justo id commodo. Fusce fermentum nunc turpis, eu vestibulum risus feugiat ut. Sed scelerisque vel ligula ut interdum. Suspendisse ac blandit ligula, sagittis fringilla dolor. In tincidunt convallis diam et ornare. Aenean id dignissim est, ut rhoncus quam. Donec vitae nisl velit. In convallis nibh ut augue dignissim, eu elementum quam cursus. Phasellus in lectus lorem. Curabitur in pellentesque nisi, at gravida sapien. Sed cursus justo volutpat lacus placerat, sit amet dignissim turpis commodo. Aliquam vitae orci eget nulla posuere condimentum in ut felis.

", "

Nulla accumsan ante in pulvinar efficitur. Nulla non velit quis urna hendrerit bibendum. Suspendisse ultrices ante eu justo malesuada, sed fermentum enim rutrum. Nunc fermentum pharetra felis, vitae sollicitudin quam rutrum porta. Aliquam fringilla velit a mi laoreet, et luctus est rutrum. In gravida non ipsum sit amet tempus. Curabitur et eleifend purus. Nulla facilisi.

", @@ -76,25 +75,25 @@ ], [ "

Why do we use it?

", - "

Comment: Exctracted from the lipsum.com website.

", + "

Comment: Exctracted from the lipsum.com website.

", "

        It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.

", "

        The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English.

", "

        Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).

" ], [ "

Chapter: Chapter Two

", - "

Point of View: Bod

", - "

Plot: Main

", - "

Locations: Europe

", - "

Synopsis: Curabitur a elit posuere, varius ex et, convallis neque. Phasellus sagittis pharetra sem vitae dapibus. Curabitur varius lorem non pulvinar congue.

", + "

Point of View: Bod

", + "

Plot: Main

", + "

Locations: Europe

", + "

Synopsis: Curabitur a elit posuere, varius ex et, convallis neque. Phasellus sagittis pharetra sem vitae dapibus. Curabitur varius lorem non pulvinar congue.

", "

Curabitur a elit posuere, varius ex et, convallis neque. Phasellus sagittis pharetra sem vitae dapibus. Curabitur varius lorem non pulvinar congue. Vestibulum pharetra fermentum leo, sed faucibus eros placerat quis. In hac habitasse platea dictumst. Donec metus massa, rutrum quis consequat et, tincidunt ac felis. Duis mollis metus ac nunc tincidunt blandit. Ut aliquet velit eu odio pharetra condimentum. Integer rutrum lacus orci, id venenatis libero accumsan at.

" ], [ "

Scene: Scene Three

", - "

Point of View: Bod

", - "

Plot: Main

", - "

Locations: Europe

", - "

Synopsis: Aenean ut libero ut lectus porttitor rhoncus vel et massa. Nam pretium, nibh et varius vehicula, urna metus blandit eros, euismod pharetra diam diam et libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.

", + "

Point of View: Bod

", + "

Plot: Main

", + "

Locations: Europe

", + "

Synopsis: Aenean ut libero ut lectus porttitor rhoncus vel et massa. Nam pretium, nibh et varius vehicula, urna metus blandit eros, euismod pharetra diam diam et libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.

", "

Aenean ut libero ut lectus porttitor rhoncus vel et massa. Nam pretium, nibh et varius vehicula, urna metus blandit eros, euismod pharetra diam diam et libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean tincidunt lacus vitae nibh elementum eleifend. Sed rutrum condimentum sem quis blandit. Duis imperdiet libero metus, quis convallis quam faucibus a. Nulla ligula est, semper quis sollicitudin et, pretium id justo. Curabitur pharetra risus eget consectetur commodo. Duis mattis arcu non est condimentum, id venenatis risus volutpat. Pellentesque aliquet mauris non mauris porttitor ultrices. Phasellus ut vestibulum mi. Suspendisse malesuada metus lorem, a malesuada orci rhoncus a. Praesent euismod convallis ante, lacinia tincidunt ex egestas id. Praesent sit amet efficitur sapien. Morbi tincidunt volutpat nunc sed dictum. Aliquam ultrices metus id fermentum lobortis.

", "

Pellentesque id sagittis dui. Praesent ut nisi sit amet libero euismod ornare. Vestibulum vehicula, lorem eget aliquet imperdiet, eros nulla iaculis mi, vel bibendum est dui sed orci. Nullam vitae lorem rutrum, euismod lacus id, ullamcorper lectus. Duis nec commodo mi, a fringilla diam. Vestibulum molestie nibh tristique, viverra augue non, aliquet metus. Phasellus a tellus ac nisl tempor aliquet. Nulla vitae sapien rutrum augue ornare ultrices a quis nisi. Sed pulvinar tincidunt ex. Fusce vel sem vitae ante pellentesque lobortis.

", "

Maecenas ullamcorper lacus nec turpis finibus aliquet eget rutrum augue. Integer lorem erat, faucibus non lacus lacinia, pulvinar egestas felis. Proin rutrum nunc eget nulla varius, id blandit mauris tincidunt. Donec sit amet ullamcorper nisi, ut efficitur mi. Aliquam aliquet, nulla eget rhoncus tristique, justo lorem consectetur dui, id ornare leo odio sed tellus. Curabitur interdum velit a turpis condimentum venenatis. Nunc rhoncus sem ac augue auctor, nec malesuada ex fringilla. Vestibulum egestas diam sed leo consectetur vulputate quis eget enim. Nam tincidunt metus sit amet maximus ullamcorper. Sed placerat velit vitae massa efficitur viverra. Etiam eleifend dignissim ante, sed luctus nisl tristique a. In vestibulum pharetra dolor in molestie. Vivamus auctor massa ac magna imperdiet, sit amet iaculis turpis finibus.

", @@ -102,10 +101,10 @@ ], [ "

Scene: Scene Four

", - "

Point of View: Bod

", - "

Plot: Main

", - "

Locations: Europe

", - "

Synopsis: Nam tempor blandit magna laoreet aliquet. Vestibulum auctor posuere leo, ac gravida nisi rhoncus varius. Aenean posuere dolor vitae condimentum volutpat. Donec egestas volutpat risus, quis luctus justo.

", + "

Point of View: Bod

", + "

Plot: Main

", + "

Locations: Europe

", + "

Synopsis: Nam tempor blandit magna laoreet aliquet. Vestibulum auctor posuere leo, ac gravida nisi rhoncus varius. Aenean posuere dolor vitae condimentum volutpat. Donec egestas volutpat risus, quis luctus justo.

", "

Nam tempor blandit magna laoreet aliquet. Vestibulum auctor posuere leo, ac gravida nisi rhoncus varius. Aenean posuere dolor vitae condimentum volutpat. Donec egestas volutpat risus, quis luctus justo. Nullam viverra dui et auctor pretium. Ut ullamcorper velit urna, sed imperdiet massa convallis a. Suspendisse efficitur, ipsum nec cursus pulvinar, eros urna posuere diam, nec elementum mi felis vitae sapien.

", "

Duis efficitur metus pulvinar, molestie magna eget, feugiat dui. Fusce convallis vehicula ipsum convallis blandit. Duis eros risus, malesuada eu imperdiet in, hendrerit ac metus. Vestibulum id justo gravida, dignissim nibh non, iaculis diam. Fusce accumsan est ut massa porta ultricies. Nulla vitae justo in tortor laoreet mollis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin eu libero justo. Vivamus aliquet placerat est, et auctor eros posuere venenatis. Nunc quam diam, tincidunt ac aliquet in, fermentum sit amet lectus. Proin commodo tincidunt blandit. Quisque erat arcu, semper nec dui non, consectetur gravida ipsum. Nullam pretium consectetur elit at condimentum.

", "

Etiam sagittis, erat vitae accumsan tempor, neque augue scelerisque nulla, ut ultrices justo urna sit amet augue. Interdum et malesuada fames ac ante ipsum primis in faucibus. Aenean at pulvinar tortor. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Cras vel porta quam. Nullam eu mauris mollis, vehicula justo vel, placerat sapien. Phasellus viverra elit et vestibulum pharetra. Vestibulum commodo fermentum leo, eu porta nisi aliquam eget. Nulla tempus porttitor nisi nec mollis. Nam non mollis turpis. Nam finibus leo a bibendum tincidunt. Donec commodo velit magna, ac semper sapien mattis id. Proin sem velit, lobortis quis ultricies id, pharetra et lectus. Vestibulum condimentum neque vitae mi dapibus mollis. Mauris luctus vel sapien vitae hendrerit.

", @@ -115,10 +114,10 @@ ], [ "

Scene: Scene Five

", - "

Point of View: Bod

", - "

Plot: Main

", - "

Locations: Europe

", - "

Synopsis: Praesent eget est porta, dictum ante in, egestas risus. Mauris risus mauris, consequat aliquam mauris et, feugiat iaculis ipsum. Aliquam arcu ipsum, fermentum ut arcu sed, lobortis euismod sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.

", + "

Point of View: Bod

", + "

Plot: Main

", + "

Locations: Europe

", + "

Synopsis: Praesent eget est porta, dictum ante in, egestas risus. Mauris risus mauris, consequat aliquam mauris et, feugiat iaculis ipsum. Aliquam arcu ipsum, fermentum ut arcu sed, lobortis euismod sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.

", "

Praesent eget est porta, dictum ante in, egestas risus. Mauris risus mauris, consequat aliquam mauris et, feugiat iaculis ipsum. Aliquam arcu ipsum, fermentum ut arcu sed, lobortis euismod sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In sed felis auctor, rhoncus dui ac, consequat dolor. Integer volutpat libero sed nisl aliquet varius. Suspendisse et lorem sapien. Proin id ultrices nibh, ac suscipit diam. Suspendisse placerat varius porttitor. Curabitur elementum sed enim ultrices imperdiet.

", "

In ut lobortis lacus, nec luctus arcu. Vivamus condimentum sapien a ipsum malesuada sodales. Donec et vestibulum risus. Integer dictum euismod eros id tincidunt. Aliquam sagittis leo vitae consequat fermentum. Donec maximus ex eu ex iaculis porta. Praesent pharetra lacinia risus, et eleifend diam commodo non. Sed feugiat ipsum ut orci sagittis, quis faucibus lectus blandit. Sed tellus quam, gravida vitae laoreet quis, tempus lobortis dui. Vivamus semper accumsan ullamcorper. Praesent tempus pretium eros, non elementum risus. Pellentesque odio quam, auctor quis ex non, vulputate egestas dolor. Nunc luctus enim ut justo sodales consectetur. Sed aliquet a mauris vel posuere.

", "

Donec luctus lectus efficitur, blandit nisi vitae, dignissim tellus. Pellentesque euismod pharetra augue gravida hendrerit. Quisque nisi mi, mattis ac nisi non, maximus malesuada ante. Nulla lobortis, diam eu ornare ornare, tellus enim feugiat arcu, non vestibulum tortor nunc eu justo. Integer blandit felis justo, eu semper est scelerisque vel. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nam ultricies, nisi vel elementum commodo, nisl dolor tincidunt magna, sed varius est nunc at lectus. Aliquam dolor tortor, sodales placerat ultricies quis, sodales quis sapien. Duis ullamcorper sollicitudin risus at mattis. Integer consequat et nunc at condimentum. Pellentesque cursus congue augue, non suscipit lectus sodales ut. Nam a mi bibendum, blandit nisl eu, accumsan nunc. Aliquam a ex mauris. Sed nec sem quis arcu dignissim tempus eget et turpis. Ut sed ex nec ipsum ultrices lobortis.

", @@ -130,8 +129,8 @@ ], [ "

Nobody Owens

", - "

Tag: Bod | Nobody Owens

", - "

Plot: Main

", + "

Tag: Bod | Nobody Owens

", + "

Plot: Main

", "

Pellentesque nec erat ut nulla posuere commodo. Curabitur nisi augue, imperdiet et porta imperdiet, efficitur id leo. Cras finibus arcu at nibh commodo congue. Proin suscipit placerat condimentum. Aenean ante enim, cursus id lorem a, blandit venenatis nibh. Maecenas suscipit porta elit, sit amet porta felis porttitor eu. Sed a dui nibh. Phasellus sed faucibus dui. Pellentesque felis nulla, ultrices non efficitur quis, rutrum id mi. Mauris tempus auctor nisl, in bibendum enim pellentesque sit amet. Proin nunc lacus, imperdiet nec posuere ac, interdum non lectus.

", "

Suspendisse faucibus est auctor orci mollis luctus. Praesent quis sodales neque. Interdum et malesuada fames ac ante ipsum primis in faucibus. Donec sodales rutrum mattis. In in sem ornare, consequat nulla ac, convallis arcu. Duis ac metus id felis commodo commodo sit amet eget diam. Curabitur rhoncus lacinia leo at sodales. Etiam finibus porta diam a viverra. Praesent nisi urna, volutpat sit amet odio at, vehicula vehicula leo. In non enim eget nisl luctus commodo. Pellentesque pellentesque at lectus at luctus. Quisque nec felis bibendum, lacinia libero ut, lacinia eros. Integer finibus ultricies nibh sit amet placerat.

", "

Nullam scelerisque velit et tortor congue vestibulum a at nisi. Vivamus sodales ut turpis a convallis. In dignissim nibh at luctus sodales. Etiam sit amet rhoncus massa. Phasellus ligula magna, sollicitudin non imperdiet sit amet, volutpat vel magna. Nunc vestibulum tempor lectus, sit amet porta nunc hendrerit in. Curabitur non odio sit amet massa tincidunt facilisis. Integer et luctus nunc, eget euismod leo. Praesent faucibus metus sed purus convallis scelerisque. Fusce viverra lorem et placerat malesuada. In at elit malesuada, ullamcorper risus vitae, sodales dolor. Donec quis elementum lectus. Quisque eu eros at dui imperdiet euismod ut id neque.

" @@ -141,7 +140,7 @@ ], [ "

Main Plot

", - "

Tag: Main

", + "

Tag: Main

", "

Suspendisse vulputate malesuada pellentesque. Aenean sollicitudin cursus mi, vitae ultricies felis ullamcorper eu. Duis luctus risus mi, in accumsan velit cursus ut. Vestibulum eleifend leo in magna eleifend fermentum. Proin nec ornare elit. Phasellus nec interdum risus. In a volutpat augue, quis egestas justo. Morbi porta mauris mattis bibendum imperdiet.

", "

Mauris ut erat eu lorem malesuada egestas vel vel urna. Maecenas ac semper quam. Maecenas aliquet metus non interdum mattis. Proin consectetur molestie ligula. Aliquam sollicitudin pulvinar urna a pellentesque. Suspendisse ultrices, est mattis scelerisque porta, nisi nisi laoreet nisl, non condimentum quam ante a velit. Proin scelerisque justo augue, nec laoreet ligula egestas at. Etiam enim quam, ultrices non accumsan hendrerit, elementum vel ligula. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nam efficitur odio libero, in vestibulum arcu aliquam at. Cras non vehicula augue. Integer lobortis, est vitae aliquam facilisis, metus ligula aliquet eros, at porttitor sem tortor eget massa. Aliquam varius scelerisque neque sed gravida. Aenean eleifend lorem id ante elementum sollicitudin. Proin commodo massa a quam volutpat, mollis fermentum turpis efficitur.

" ], @@ -150,7 +149,7 @@ ], [ "

Ancient Europe

", - "

Tag: Europe | Ancient Europe

", + "

Tag: Europe | Ancient Europe

", "

Vivamus sodales risus ac accumsan posuere. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nunc vel enim felis. Vestibulum dignissim massa nunc, a auctor magna eleifend et. Proin dignissim sodales erat vitae convallis. Aliquam id tellus dui. Curabitur sollicitudin scelerisque ex sit amet posuere. Nam rutrum felis id rhoncus feugiat. Duis sagittis quam quis purus efficitur, quis rutrum odio iaculis. Maecenas semper ante turpis, at vulputate mi consectetur non. Sed rutrum nibh turpis, quis rhoncus purus ornare quis. Vestibulum at rutrum mauris. Integer dolor nisi, tincidunt eget vehicula ac, ultricies at ligula.

", "

Aenean semper turpis quis varius rhoncus. Vivamus ac mi eget felis euismod vulputate. Nam eu tempus velit. Etiam ut est porta, finibus erat sit amet, consectetur felis. Nullam consequat felis ut lacus pharetra, in lobortis urna mollis. Nulla varius eros nec lorem rhoncus, sed venenatis risus ultrices. Phasellus pellentesque laoreet neque, ut ultricies lacus vulputate quis. In malesuada dui sit amet est interdum, eget consectetur mi gravida. Cras vel bibendum purus. Quisque commodo tempor arcu, non lacinia sem blandit eleifend. Quisque at neque gravida, porttitor metus a, suscipit diam. Quisque convallis sodales lacus et condimentum. Donec a suscipit diam. Pellentesque eget cursus neque.

", "

Nunc ullamcorper magna quis elit condimentum rhoncus. Aenean dictum pulvinar dolor suscipit interdum. Aliquam elit massa, elementum nec cursus eu, maximus nec ipsum. Donec ullamcorper iaculis dolor eu commodo. Nunc eget tortor quis turpis consectetur varius. Vestibulum nec justo vel tellus venenatis condimentum. Duis auctor iaculis massa. Nunc risus magna, rutrum vitae eros non, tristique mollis enim.

" diff --git a/tests/reference/mBuildDocBuild_OpenDocument_Lorem_Ipsum.fodt b/tests/reference/mBuildDocBuild_OpenDocument_Lorem_Ipsum.fodt index e76458fc7..7c6c1f237 100644 --- a/tests/reference/mBuildDocBuild_OpenDocument_Lorem_Ipsum.fodt +++ b/tests/reference/mBuildDocBuild_OpenDocument_Lorem_Ipsum.fodt @@ -1,13 +1,13 @@ - 2024-10-22T17:00:59 + 2024-10-22T21:00:03 novelWriter/2.6a1 lipsum.com 45 P0DT0H36M8S Lorem Ipsum - 2024-10-22T17:00:59 + 2024-10-22T21:00:03 lipsum.com @@ -124,6 +124,15 @@ + + + + + + + + + @@ -168,15 +177,15 @@ Part: Act One “Fusce maximus felis libero” Chapter: Chapter One - Point of View: Bod - Plot: Main - Locations: Europe + Point of View: Bod + Plot: Main + Locations: Europe Synopsis: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam. Praesent magna nunc, lacinia sit amet quam eget, aliquet ultrices justo. Morbi ornare enim et lorem rutrum finibus ut eu dolor. Aliquam a orci odio. Ut ultrices sem quis massa placerat, eget mollis nisl cursus. Cras vel sagittis justo. Ut non ultricies leo. Maecenas rutrum velit in est varius, et egestas massa pulvinar. Scene: Scene One - Point of View: Bod - Plot: Main - Locations: Europe + Point of View: Bod + Plot: Main + Locations: Europe Synopsis: Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur. Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur. Donec quis ante nunc. Mauris ut leo ipsum. Vestibulum est neque, hendrerit nec neque a, ullamcorper lobortis tellus. Fusce sollicitudin purus quis congue bibendum. Aliquam condimentum ipsum tristique blandit tristique. Donec pulvinar neque ac suscipit malesuada. Aliquam ut nisl arcu. Ut ultricies, lorem dignissim rutrum convallis, risus orci tempus lectus, congue feugiat sem lectus vitae odio. Duis sit amet justo finibus, hendrerit nulla at, ullamcorper enim. Praesent vel tellus sit amet tellus vulputate bibendum. Morbi eleifend sagittis sem, ac volutpat ante congue non. In hac habitasse platea dictumst. Morbi lobortis fermentum elit, dignissim sagittis ligula volutpat lacinia. Vestibulum eu interdum odio. Integer ac purus commodo metus congue tempor non at urna. Sed eget tortor vel quam viverra egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec non convallis mauris, ac feugiat ex. @@ -184,9 +193,9 @@ Integer vel libero ipsum. Donec varius aliquam libero, sit amet commodo urna hendrerit non. Nullam quis erat mollis nunc viverra volutpat tincidunt in odio. Nam vitae quam sem. Aliquam suscipit nulla non lorem pharetra semper. Ut suscipit erat eu ligula accumsan ultrices. Phasellus nisl tellus, placerat sed laoreet id, consectetur nec dolor. Sed fringilla ipsum id dapibus posuere. Aenean finibus pharetra tincidunt. Ut molestie malesuada nulla, id posuere lorem tincidunt eu. Aliquam tempor eros a est vulputate, scelerisque pulvinar ipsum fermentum. In hac habitasse platea dictumst. Curabitur congue, justo quis interdum fermentum, tellus nulla imperdiet sapien, eu interdum enim tellus condimentum metus. Vivamus nunc velit, dignissim ut ultrices sit amet, ultricies quis enim. Donec ut vestibulum neque. Vivamus semper neque id ex ullamcorper varius. Fusce mattis nibh viverra lorem sagittis, et tempor arcu congue. Suspendisse sit amet felis sed urna facilisis mattis eget vitae arcu. Proin eu magna hendrerit, tristique sem maximus, placerat diam. Nulla tristique sed velit sit amet varius. Etiam vel ornare magna, in vulputate arcu. Cras velit orci, tincidunt sed volutpat cursus, bibendum vel sem. Nunc vulputate pharetra tortor, ac consectetur neque tincidunt sit amet. Nulla ornare mi sed mi dignissim ultricies. Ut tincidunt bibendum mauris, sed elementum ex vulputate vel. Mauris fermentum, felis nec vehicula congue, felis lorem facilisis erat, a dictum dolor augue vitae quam. Maecenas rutrum tortor nec consequat eleifend. Scene: Scene Two - Point of View: Bod - Plot: Main - Locations: Europe + Point of View: Bod + Plot: Main + Locations: Europe Synopsis: Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci. Vestibulum facilisis bibendum aliquam. Aliquam posuere, turpis ac bibendum varius, sem tellus venenatis risus, in elementum massa enim ac lorem. Integer in sem ac diam blandit ultricies ut in nulla. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam sit amet erat est. Curabitur vitae cursus justo, sit amet placerat dolor. Vivamus eu felis hendrerit, tincidunt massa rutrum, maximus arcu. Pellentesque commodo justo odio, vel rutrum nulla tincidunt eu. Integer non neque condimentum, convallis diam non, varius ligula. Aliquam eget sapien mauris. Aenean pharetra nunc nisi, vel maximus ante tristique sit amet. Aliquam risus metus, interdum non odio eu, consectetur lacinia sapien. Proin vitae gravida nisl. Integer viverra orci turpis, sit amet pretium ligula facilisis consequat. Nulla interdum commodo metus, mollis consequat dui tincidunt et. Proin consequat bibendum justo id commodo. Fusce fermentum nunc turpis, eu vestibulum risus feugiat ut. Sed scelerisque vel ligula ut interdum. Suspendisse ac blandit ligula, sagittis fringilla dolor. In tincidunt convallis diam et ornare. Aenean id dignissim est, ut rhoncus quam. Donec vitae nisl velit. In convallis nibh ut augue dignissim, eu elementum quam cursus. Phasellus in lectus lorem. Curabitur in pellentesque nisi, at gravida sapien. Sed cursus justo volutpat lacus placerat, sit amet dignissim turpis commodo. Aliquam vitae orci eget nulla posuere condimentum in ut felis. @@ -201,24 +210,24 @@ The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like). Chapter: Chapter Two - Point of View: Bod - Plot: Main - Locations: Europe + Point of View: Bod + Plot: Main + Locations: Europe Synopsis: Curabitur a elit posuere, varius ex et, convallis neque. Phasellus sagittis pharetra sem vitae dapibus. Curabitur varius lorem non pulvinar congue. Curabitur a elit posuere, varius ex et, convallis neque. Phasellus sagittis pharetra sem vitae dapibus. Curabitur varius lorem non pulvinar congue. Vestibulum pharetra fermentum leo, sed faucibus eros placerat quis. In hac habitasse platea dictumst. Donec metus massa, rutrum quis consequat et, tincidunt ac felis. Duis mollis metus ac nunc tincidunt blandit. Ut aliquet velit eu odio pharetra condimentum. Integer rutrum lacus orci, id venenatis libero accumsan at. Scene: Scene Three - Point of View: Bod - Plot: Main - Locations: Europe + Point of View: Bod + Plot: Main + Locations: Europe Synopsis: Aenean ut libero ut lectus porttitor rhoncus vel et massa. Nam pretium, nibh et varius vehicula, urna metus blandit eros, euismod pharetra diam diam et libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean ut libero ut lectus porttitor rhoncus vel et massa. Nam pretium, nibh et varius vehicula, urna metus blandit eros, euismod pharetra diam diam et libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean tincidunt lacus vitae nibh elementum eleifend. Sed rutrum condimentum sem quis blandit. Duis imperdiet libero metus, quis convallis quam faucibus a. Nulla ligula est, semper quis sollicitudin et, pretium id justo. Curabitur pharetra risus eget consectetur commodo. Duis mattis arcu non est condimentum, id venenatis risus volutpat. Pellentesque aliquet mauris non mauris porttitor ultrices. Phasellus ut vestibulum mi. Suspendisse malesuada metus lorem, a malesuada orci rhoncus a. Praesent euismod convallis ante, lacinia tincidunt ex egestas id. Praesent sit amet efficitur sapien. Morbi tincidunt volutpat nunc sed dictum. Aliquam ultrices metus id fermentum lobortis. Pellentesque id sagittis dui. Praesent ut nisi sit amet libero euismod ornare. Vestibulum vehicula, lorem eget aliquet imperdiet, eros nulla iaculis mi, vel bibendum est dui sed orci. Nullam vitae lorem rutrum, euismod lacus id, ullamcorper lectus. Duis nec commodo mi, a fringilla diam. Vestibulum molestie nibh tristique, viverra augue non, aliquet metus. Phasellus a tellus ac nisl tempor aliquet. Nulla vitae sapien rutrum augue ornare ultrices a quis nisi. Sed pulvinar tincidunt ex. Fusce vel sem vitae ante pellentesque lobortis. Maecenas ullamcorper lacus nec turpis finibus aliquet eget rutrum augue. Integer lorem erat, faucibus non lacus lacinia, pulvinar egestas felis. Proin rutrum nunc eget nulla varius, id blandit mauris tincidunt. Donec sit amet ullamcorper nisi, ut efficitur mi. Aliquam aliquet, nulla eget rhoncus tristique, justo lorem consectetur dui, id ornare leo odio sed tellus. Curabitur interdum velit a turpis condimentum venenatis. Nunc rhoncus sem ac augue auctor, nec malesuada ex fringilla. Vestibulum egestas diam sed leo consectetur vulputate quis eget enim. Nam tincidunt metus sit amet maximus ullamcorper. Sed placerat velit vitae massa efficitur viverra. Etiam eleifend dignissim ante, sed luctus nisl tristique a. In vestibulum pharetra dolor in molestie. Vivamus auctor massa ac magna imperdiet, sit amet iaculis turpis finibus. Aenean dapibus vulputate purus, sit amet tempor nunc suscipit consequat. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris auctor congue eros, non pellentesque neque dapibus ac. Vestibulum non leo nec urna lacinia eleifend quis et diam. Praesent eu nisi magna. Nulla at magna massa. Suspendisse porta varius scelerisque. Duis at auctor dolor, non dapibus urna. Nunc venenatis feugiat magna non molestie. Aliquam non ornare ex. Quisque eu ultrices velit, quis pellentesque eros. Phasellus eleifend, elit id imperdiet aliquam, nulla quam molestie turpis, at egestas odio ante et tortor. Suspendisse fringilla condimentum justo, at aliquet odio aliquam ac. Scene: Scene Four - Point of View: Bod - Plot: Main - Locations: Europe + Point of View: Bod + Plot: Main + Locations: Europe Synopsis: Nam tempor blandit magna laoreet aliquet. Vestibulum auctor posuere leo, ac gravida nisi rhoncus varius. Aenean posuere dolor vitae condimentum volutpat. Donec egestas volutpat risus, quis luctus justo. Nam tempor blandit magna laoreet aliquet. Vestibulum auctor posuere leo, ac gravida nisi rhoncus varius. Aenean posuere dolor vitae condimentum volutpat. Donec egestas volutpat risus, quis luctus justo. Nullam viverra dui et auctor pretium. Ut ullamcorper velit urna, sed imperdiet massa convallis a. Suspendisse efficitur, ipsum nec cursus pulvinar, eros urna posuere diam, nec elementum mi felis vitae sapien. Duis efficitur metus pulvinar, molestie magna eget, feugiat dui. Fusce convallis vehicula ipsum convallis blandit. Duis eros risus, malesuada eu imperdiet in, hendrerit ac metus. Vestibulum id justo gravida, dignissim nibh non, iaculis diam. Fusce accumsan est ut massa porta ultricies. Nulla vitae justo in tortor laoreet mollis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin eu libero justo. Vivamus aliquet placerat est, et auctor eros posuere venenatis. Nunc quam diam, tincidunt ac aliquet in, fermentum sit amet lectus. Proin commodo tincidunt blandit. Quisque erat arcu, semper nec dui non, consectetur gravida ipsum. Nullam pretium consectetur elit at condimentum. @@ -227,9 +236,9 @@ Donec ipsum eros, vestibulum sit amet cursus eget, iaculis quis dolor. Pellentesque magna augue, tristique dapibus mi vitae, molestie venenatis enim. Nam malesuada, turpis volutpat rhoncus ullamcorper, justo est eleifend orci, ut luctus risus ex rutrum arcu. Sed mi elit, feugiat rhoncus ornare sed, porta id leo. Pellentesque feugiat nulla tincidunt erat suscipit, eu congue lacus hendrerit. Morbi pulvinar enim sed consequat auctor. Ut eleifend enim sem, vitae euismod ex ultricies sit amet. Curabitur eu efficitur nisi, suscipit finibus sapien. In sodales blandit erat, vestibulum pulvinar ante volutpat nec. Vivamus dictum non libero at molestie. Donec sit amet neque in ante convallis pretium. Nunc vel iaculis dui. Phasellus eu nunc ut nunc faucibus laoreet. Aliquam at magna risus. Praesent lobortis, risus finibus semper varius, magna purus vestibulum eros, at pulvinar sapien enim a ex. In scelerisque malesuada ex, sit amet egestas neque condimentum sed. Praesent vulputate efficitur massa. Cras at accumsan ligula. In elementum lectus eget blandit dictum. Nam vitae libero ut justo eleifend rutrum ac nec arcu. Aliquam sodales in quam congue vestibulum. Aliquam in accumsan sapien. Quisque lobortis nisl nisi, vitae bibendum turpis efficitur sed. Vestibulum tempor nulla eget nisi convallis, blandit sagittis ipsum convallis. Donec odio nibh, ultrices quis odio in, mollis euismod libero. Scene: Scene Five - Point of View: Bod - Plot: Main - Locations: Europe + Point of View: Bod + Plot: Main + Locations: Europe Synopsis: Praesent eget est porta, dictum ante in, egestas risus. Mauris risus mauris, consequat aliquam mauris et, feugiat iaculis ipsum. Aliquam arcu ipsum, fermentum ut arcu sed, lobortis euismod sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent eget est porta, dictum ante in, egestas risus. Mauris risus mauris, consequat aliquam mauris et, feugiat iaculis ipsum. Aliquam arcu ipsum, fermentum ut arcu sed, lobortis euismod sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In sed felis auctor, rhoncus dui ac, consequat dolor. Integer volutpat libero sed nisl aliquet varius. Suspendisse et lorem sapien. Proin id ultrices nibh, ac suscipit diam. Suspendisse placerat varius porttitor. Curabitur elementum sed enim ultrices imperdiet. In ut lobortis lacus, nec luctus arcu. Vivamus condimentum sapien a ipsum malesuada sodales. Donec et vestibulum risus. Integer dictum euismod eros id tincidunt. Aliquam sagittis leo vitae consequat fermentum. Donec maximus ex eu ex iaculis porta. Praesent pharetra lacinia risus, et eleifend diam commodo non. Sed feugiat ipsum ut orci sagittis, quis faucibus lectus blandit. Sed tellus quam, gravida vitae laoreet quis, tempus lobortis dui. Vivamus semper accumsan ullamcorper. Praesent tempus pretium eros, non elementum risus. Pellentesque odio quam, auctor quis ex non, vulputate egestas dolor. Nunc luctus enim ut justo sodales consectetur. Sed aliquet a mauris vel posuere. @@ -238,19 +247,19 @@ Integer egestas maximus leo eu facilisis. Nunc rhoncus dignissim lectus eu lacinia. Praesent lacinia urna porttitor aliquam condimentum. Nulla eu eros dictum, dictum nunc vitae, sagittis nibh. Integer ante neque, consequat nec sollicitudin id, consectetur vitae dolor. Nullam volutpat sem orci, quis viverra magna auctor a. Suspendisse potenti. Maecenas commodo sed neque pellentesque vehicula. Sed luctus nisl risus, elementum semper purus interdum vel. Ut pulvinar, massa sit amet venenatis placerat, nunc lacus hendrerit odio, non aliquet nunc risus eu lectus. Maecenas feugiat semper ligula, id lobortis sem porta eu. Integer posuere elit magna, at mollis eros bibendum et. Ut imperdiet purus vel nulla aliquam maximus. Morbi sodales purus tellus, a rhoncus sem rutrum sit amet. Quisque risus sem, laoreet nec convallis nec, rutrum vitae justo. Notes: Characters Nobody Owens - Tag: Bod | Nobody Owens - Plot: Main + Tag: Bod | Nobody Owens + Plot: Main Pellentesque nec erat ut nulla posuere commodo. Curabitur nisi augue, imperdiet et porta imperdiet, efficitur id leo. Cras finibus arcu at nibh commodo congue. Proin suscipit placerat condimentum. Aenean ante enim, cursus id lorem a, blandit venenatis nibh. Maecenas suscipit porta elit, sit amet porta felis porttitor eu. Sed a dui nibh. Phasellus sed faucibus dui. Pellentesque felis nulla, ultrices non efficitur quis, rutrum id mi. Mauris tempus auctor nisl, in bibendum enim pellentesque sit amet. Proin nunc lacus, imperdiet nec posuere ac, interdum non lectus. Suspendisse faucibus est auctor orci mollis luctus. Praesent quis sodales neque. Interdum et malesuada fames ac ante ipsum primis in faucibus. Donec sodales rutrum mattis. In in sem ornare, consequat nulla ac, convallis arcu. Duis ac metus id felis commodo commodo sit amet eget diam. Curabitur rhoncus lacinia leo at sodales. Etiam finibus porta diam a viverra. Praesent nisi urna, volutpat sit amet odio at, vehicula vehicula leo. In non enim eget nisl luctus commodo. Pellentesque pellentesque at lectus at luctus. Quisque nec felis bibendum, lacinia libero ut, lacinia eros. Integer finibus ultricies nibh sit amet placerat. Nullam scelerisque velit et tortor congue vestibulum a at nisi. Vivamus sodales ut turpis a convallis. In dignissim nibh at luctus sodales. Etiam sit amet rhoncus massa. Phasellus ligula magna, sollicitudin non imperdiet sit amet, volutpat vel magna. Nunc vestibulum tempor lectus, sit amet porta nunc hendrerit in. Curabitur non odio sit amet massa tincidunt facilisis. Integer et luctus nunc, eget euismod leo. Praesent faucibus metus sed purus convallis scelerisque. Fusce viverra lorem et placerat malesuada. In at elit malesuada, ullamcorper risus vitae, sodales dolor. Donec quis elementum lectus. Quisque eu eros at dui imperdiet euismod ut id neque. Notes: Plot Main Plot - Tag: Main + Tag: Main Suspendisse vulputate malesuada pellentesque. Aenean sollicitudin cursus mi, vitae ultricies felis ullamcorper eu. Duis luctus risus mi, in accumsan velit cursus ut. Vestibulum eleifend leo in magna eleifend fermentum. Proin nec ornare elit. Phasellus nec interdum risus. In a volutpat augue, quis egestas justo. Morbi porta mauris mattis bibendum imperdiet. Mauris ut erat eu lorem malesuada egestas vel vel urna. Maecenas ac semper quam. Maecenas aliquet metus non interdum mattis. Proin consectetur molestie ligula. Aliquam sollicitudin pulvinar urna a pellentesque. Suspendisse ultrices, est mattis scelerisque porta, nisi nisi laoreet nisl, non condimentum quam ante a velit. Proin scelerisque justo augue, nec laoreet ligula egestas at. Etiam enim quam, ultrices non accumsan hendrerit, elementum vel ligula. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nam efficitur odio libero, in vestibulum arcu aliquam at. Cras non vehicula augue. Integer lobortis, est vitae aliquam facilisis, metus ligula aliquet eros, at porttitor sem tortor eget massa. Aliquam varius scelerisque neque sed gravida. Aenean eleifend lorem id ante elementum sollicitudin. Proin commodo massa a quam volutpat, mollis fermentum turpis efficitur. Notes: World Ancient Europe - Tag: Europe | Ancient Europe + Tag: Europe | Ancient Europe Vivamus sodales risus ac accumsan posuere. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nunc vel enim felis. Vestibulum dignissim massa nunc, a auctor magna eleifend et. Proin dignissim sodales erat vitae convallis. Aliquam id tellus dui. Curabitur sollicitudin scelerisque ex sit amet posuere. Nam rutrum felis id rhoncus feugiat. Duis sagittis quam quis purus efficitur, quis rutrum odio iaculis. Maecenas semper ante turpis, at vulputate mi consectetur non. Sed rutrum nibh turpis, quis rhoncus purus ornare quis. Vestibulum at rutrum mauris. Integer dolor nisi, tincidunt eget vehicula ac, ultricies at ligula. Aenean semper turpis quis varius rhoncus. Vivamus ac mi eget felis euismod vulputate. Nam eu tempus velit. Etiam ut est porta, finibus erat sit amet, consectetur felis. Nullam consequat felis ut lacus pharetra, in lobortis urna mollis. Nulla varius eros nec lorem rhoncus, sed venenatis risus ultrices. Phasellus pellentesque laoreet neque, ut ultricies lacus vulputate quis. In malesuada dui sit amet est interdum, eget consectetur mi gravida. Cras vel bibendum purus. Quisque commodo tempor arcu, non lacinia sem blandit eleifend. Quisque at neque gravida, porttitor metus a, suscipit diam. Quisque convallis sodales lacus et condimentum. Donec a suscipit diam. Pellentesque eget cursus neque. Nunc ullamcorper magna quis elit condimentum rhoncus. Aenean dictum pulvinar dolor suscipit interdum. Aliquam elit massa, elementum nec cursus eu, maximus nec ipsum. Donec ullamcorper iaculis dolor eu commodo. Nunc eget tortor quis turpis consectetur varius. Vestibulum nec justo vel tellus venenatis condimentum. Duis auctor iaculis massa. Nunc risus magna, rutrum vitae eros non, tristique mollis enim. diff --git a/tests/test_formats/test_fmt_todocx.py b/tests/test_formats/test_fmt_todocx.py index 357b9a763..22df9e1c2 100644 --- a/tests/test_formats/test_fmt_todocx.py +++ b/tests/test_formats/test_fmt_todocx.py @@ -192,36 +192,41 @@ def testFmtToDocX_ParagraphStyles(mockGUI): # Tags and References (Single) xTest = ET.Element(_wTag("body")) - doc._blocks = [(BlockTyp.KEYWORD, 0, "tag: Stuff", [], BlockFmt.NONE)] + doc._text = "@tag: Stuff" + doc.tokenizeText() doc.doConvert() doc._pars[-1].toXml(xTest) assert xmlToText(xTest) == ( f'' - 'Tag:' - ' Stuff' + 'Tag:' + ' ' + 'Stuff' '' ) # Tags and References (Multiple) xTest = ET.Element(_wTag("body")) - doc._blocks = [(BlockTyp.KEYWORD, 0, "char: Jane, John", [], BlockFmt.NONE)] + doc._text = "@char: Jane, John" + doc.tokenizeText() doc.doConvert() doc._pars[-1].toXml(xTest) assert xmlToText(xTest) == ( f'' - 'Characters:' - ' Jane, John' + 'Characters:' + ' ' + 'Jane' + ', ' + 'John' '' ) # Tags and References (Invalid) xTest = ET.Element(_wTag("body")) - doc._blocks = [(BlockTyp.KEYWORD, 0, "stuff: Stuff", [], BlockFmt.NONE)] + doc._text = "@stuff: Stuff" + doc._pars = [] + doc.tokenizeText() doc.doConvert() - doc._pars[-1].toXml(xTest) - assert xmlToText(xTest) == ( - f'' - ) + assert doc._pars == [] @pytest.mark.core diff --git a/tests/test_formats/test_fmt_tohtml.py b/tests/test_formats/test_fmt_tohtml.py index 9b59c366e..246545919 100644 --- a/tests/test_formats/test_fmt_tohtml.py +++ b/tests/test_formats/test_fmt_tohtml.py @@ -232,9 +232,9 @@ def testFmtToHtml_ConvertParagraphs(mockGUI): html.tokenizeText() html.doConvert() assert html.result == ( - "

Characters: " - "Bod, " - "Jane

\n" + "

Characters: " + "Bod, " + "Jane

\n" ) # Tags @@ -242,16 +242,17 @@ def testFmtToHtml_ConvertParagraphs(mockGUI): html.tokenizeText() html.doConvert() assert html.result == ( - "

Tag: " - "Bod

\n" + "

Tag: " + "Bod

\n" ) html._text = "@tag: Bod | Nobody Owens\n" html.tokenizeText() html.doConvert() assert html.result == ( - "

Tag: " - "Bod | Nobody Owens

\n" + "

Tag: " + "Bod | " + "Nobody Owens

\n" ) # Multiple Keywords @@ -262,15 +263,15 @@ def testFmtToHtml_ConvertParagraphs(mockGUI): html.doConvert() assert html.result == ( "

Chapter

\n" - "

" - "Point of View: " - "Bod

\n" - "

" - "Plot: " - "Main

\n" - "

" - "Locations: " - "Europe

\n" + "

" + "Point of View: " + "Bod

\n" + "

" + "Plot: " + "Main

\n" + "

" + "Locations: " + "Europe

\n" ) # Dialogue @@ -718,22 +719,3 @@ def testFmtToHtml_Methods(mockGUI): html.setStyles(False) assert html.getStyleSheet() == [] - - -@pytest.mark.core -def testFmtToHtml_Format(mockGUI): - """Test all the formatters for the ToHtml class.""" - project = NWProject() - html = ToHtml(project) - html.initDocument() - - assert html._formatKeywords("") == ("", "") - assert html._formatKeywords("tag: Jane") == ( - "tag", "Tag: Jane" - ) - assert html._formatKeywords("char: Bod, Jane") == ( - "char", - "Characters: " - "Bod, " - "Jane" - ) diff --git a/tests/test_formats/test_fmt_tokenizer.py b/tests/test_formats/test_fmt_tokenizer.py index cf236348a..2b4944989 100644 --- a/tests/test_formats/test_fmt_tokenizer.py +++ b/tests/test_formats/test_fmt_tokenizer.py @@ -770,30 +770,54 @@ def testFmtToken_MetaFormat(mockGUI): tokens.setKeywords(True) tokens.tokenizeText() - assert tokens._blocks == [ - (BlockTyp.KEYWORD, 0, "char: Bod", [], BlockFmt.NONE), - ] + assert tokens._blocks == [( + BlockTyp.KEYWORD, 0, "Characters: Bod", [ + (0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"), + (11, TextFmt.B_E, ""), (11, TextFmt.COL_E, ""), + (12, TextFmt.COL_B, "tag"), (12, TextFmt.HRF_B, "#tag_bod"), + (15, TextFmt.HRF_E, ""), (15, TextFmt.COL_E, ""), + ], BlockFmt.NONE + )] assert tokens.allMarkdown[-1] == "@char: Bod\n\n" tokens._text = "@pov: Bod\n@plot: Main\n@location: Europe\n" tokens.tokenizeText() - styTop = BlockFmt.NONE | BlockFmt.Z_BTMMRG - styMid = BlockFmt.NONE | BlockFmt.Z_BTMMRG | BlockFmt.Z_TOPMRG - styBtm = BlockFmt.NONE | BlockFmt.Z_TOPMRG - assert tokens._blocks == [ - (BlockTyp.KEYWORD, 0, "pov: Bod", [], styTop), - (BlockTyp.KEYWORD, 0, "plot: Main", [], styMid), - (BlockTyp.KEYWORD, 0, "location: Europe", [], styBtm), - ] + assert tokens._blocks == [( + BlockTyp.KEYWORD, 0, "Point of View: Bod", [ + (0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"), + (14, TextFmt.B_E, ""), (14, TextFmt.COL_E, ""), + (15, TextFmt.COL_B, "tag"), (15, TextFmt.HRF_B, "#tag_bod"), + (18, TextFmt.HRF_E, ""), (18, TextFmt.COL_E, ""), + ], BlockFmt.Z_BTMMRG + ), ( + BlockTyp.KEYWORD, 0, "Plot: Main", [ + (0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"), + (5, TextFmt.B_E, ""), (5, TextFmt.COL_E, ""), + (6, TextFmt.COL_B, "tag"), (6, TextFmt.HRF_B, "#tag_main"), + (10, TextFmt.HRF_E, ""), (10, TextFmt.COL_E, ""), + ], BlockFmt.Z_TOPMRG | BlockFmt.Z_BTMMRG + ), ( + BlockTyp.KEYWORD, 0, "Locations: Europe", [ + (0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"), + (10, TextFmt.B_E, ""), (10, TextFmt.COL_E, ""), + (11, TextFmt.COL_B, "tag"), (11, TextFmt.HRF_B, "#tag_europe"), + (17, TextFmt.HRF_E, ""), (17, TextFmt.COL_E, ""), + ], BlockFmt.Z_TOPMRG + )] assert tokens.allMarkdown[-1] == "@pov: Bod\n@plot: Main\n@location: Europe\n\n" # Ignored keywords tokens._text = "@pov: Bod\n@plot: Main\n@location: Europe\n" tokens.setIgnoredKeywords("@plot, @location") tokens.tokenizeText() - assert tokens._blocks == [ - (BlockTyp.KEYWORD, 0, "pov: Bod", [], BlockFmt.NONE), - ] + assert tokens._blocks == [( + BlockTyp.KEYWORD, 0, "Point of View: Bod", [ + (0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"), + (14, TextFmt.B_E, ""), (14, TextFmt.COL_E, ""), + (15, TextFmt.COL_B, "tag"), (15, TextFmt.HRF_B, "#tag_bod"), + (18, TextFmt.HRF_E, ""), (18, TextFmt.COL_E, ""), + ], BlockFmt.NONE + )] @pytest.mark.core @@ -1643,7 +1667,7 @@ def testFmtToken_ProcessHeaders(mockGUI): @pytest.mark.core -def testFmtToken_FormatNote(mockGUI, ipsumText): +def testFmtToken_FormatComment(mockGUI): """Test note and comment formatting.""" project = NWProject() project.data.setLanguage("en") @@ -1671,6 +1695,36 @@ def testFmtToken_FormatNote(mockGUI, ipsumText): ) +@pytest.mark.core +def testFmtToken_FormatMeta(mockGUI): + """Test meta formatting.""" + project = NWProject() + project.data.setLanguage("en") + project._loadProjectLocalisation() + tokens = BareTokenizer(project) + + assert tokens._formatMeta("@tag: Jane | Jane Smith") == ( + "Tag: Jane | Jane Smith", [ + (0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"), + (4, TextFmt.B_E, ""), (4, TextFmt.COL_E, ""), + (5, TextFmt.COL_B, "tag"), (5, TextFmt.ANM_B, "tag_jane"), + (9, TextFmt.ANM_E, ""), (9, TextFmt.COL_E, ""), + (12, TextFmt.COL_B, "optional"), (22, TextFmt.COL_E, ""), + ] + ) + + assert tokens._formatMeta("@char: Jane, John") == ( + "Characters: Jane, John", [ + (0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"), + (11, TextFmt.B_E, ""), (11, TextFmt.COL_E, ""), + (12, TextFmt.COL_B, "tag"), (12, TextFmt.HRF_B, "#tag_jane"), + (16, TextFmt.HRF_E, ""), (16, TextFmt.COL_E, ""), + (18, TextFmt.COL_B, "tag"), (18, TextFmt.HRF_B, "#tag_john"), + (22, TextFmt.HRF_E, ""), (22, TextFmt.COL_E, ""), + ] + ) + + @pytest.mark.core def testFmtToken_BuildOutline(mockGUI, ipsumText): """Test stats counter of the Tokenizer class.""" @@ -1863,7 +1917,7 @@ def testFmtToken_CountStats(mockGUI, ipsumText): tokens.setKeywords(True) tokens.tokenizeText() tokens.countStats() - assert [t[2] for t in tokens._blocks] == ["Chapter", "pov: Jane", "Text"] + assert [t[2] for t in tokens._blocks] == ["Chapter", "Point of View: Jane", "Text"] assert tokens.textStats == { "titleCount": 1, "paragraphCount": 1, "allWords": 6, "textWords": 1, "titleWords": 1, diff --git a/tests/test_formats/test_fmt_tomarkdown.py b/tests/test_formats/test_fmt_tomarkdown.py index fffcd3c2c..6d9a2e35b 100644 --- a/tests/test_formats/test_fmt_tomarkdown.py +++ b/tests/test_formats/test_fmt_tomarkdown.py @@ -293,15 +293,3 @@ def testFmtToMarkdown_Save(mockGUI, fncPath): saveFile = fncPath / "outFile.md" toMD.saveDocument(saveFile) assert saveFile.read_text(encoding="utf-8") == "".join(resText) - - -@pytest.mark.core -def testFmtToMarkdown_Format(mockGUI): - """Test all the formatters for the ToMarkdown class.""" - project = NWProject() - toMD = ToMarkdown(project, False) - - assert toMD._formatKeywords("", BlockFmt.NONE) == "" - assert toMD._formatKeywords("tag: Jane", BlockFmt.NONE) == "**Tag:** Jane\n\n" - assert toMD._formatKeywords("tag: Jane, John", BlockFmt.NONE) == "**Tag:** Jane, John\n\n" - assert toMD._formatKeywords("tag: Jane", BlockFmt.Z_BTMMRG) == "**Tag:** Jane \n" diff --git a/tests/test_formats/test_fmt_toodt.py b/tests/test_formats/test_fmt_toodt.py index 0d0664032..ba7946b66 100644 --- a/tests/test_formats/test_fmt_toodt.py +++ b/tests/test_formats/test_fmt_toodt.py @@ -202,7 +202,6 @@ def testFmtToOdt_TextFormatting(mockGUI): fmt = [(2, TextFmt.B_B, ""), (5, TextFmt.B_E, ""), (7, 99999, "")] xTest = ET.Element(_mkTag("office", "text")) odt._addTextPar(xTest, "Standard", oStyle, text, tFmt=fmt) - assert odt.errData == ["Unknown format tag encountered"] assert xmlToText(xTest) == ( '' 'A few ' @@ -521,17 +520,17 @@ def getStyle(styleName): assert xmlToText(odt._xText) == ( '' 'Scene' - '' - 'Point of View: Jane' '' + 'Point of View: Jane' + '' 'Synopsis: ' - 'So it begins' - '' - 'Short Description: ' - 'Then what' + 'So it begins' '' + 'Short Description: ' + 'Then what' + '' 'Comment: ' - 'A plain comment' + 'A plain comment' '' ) @@ -591,12 +590,12 @@ def getStyle(styleName): assert xmlToText(odt._xText) == ( '' 'Scene' - '' - 'Point of View: Jane' - '' - 'Characters: John' - '' - 'Plot: Main' + '' + 'Point of View: Jane' + '' + 'Characters: John' + '' + 'Plot: Main' 'Right align' 'Left Align' 'Centered' @@ -706,7 +705,7 @@ def getStyle(styleName): assert odt.errData == [] assert xmlToText(odt._xText) == ( '' - 'Test text **' + 'Test text **' 'bold** and more.' '' ) @@ -894,21 +893,6 @@ def prettifyXml(inFile, outFile): assert cmpFiles(stylFile, stylComp) -@pytest.mark.core -def testFmtToOdt_SpecialFormats(mockGUI): - """Test the special formatters for the ToOdt class.""" - project = NWProject() - odt = ToOdt(project, isFlat=True) - - assert odt._formatKeywords("") == ("", []) - assert odt._formatKeywords("tag: Jane") == ( - "Tag: Jane", [(0, TextFmt.B_B, ""), (4, TextFmt.B_E, "")] - ) - assert odt._formatKeywords("char: Bod, Jane") == ( - "Characters: Bod, Jane", [(0, TextFmt.B_B, ""), (11, TextFmt.B_E, "")] - ) - - @pytest.mark.core def testFmtToOdt_ODTParagraphStyle(): """Test the ODTParagraphStyle class.""" @@ -1208,13 +1192,11 @@ def testFmtToOdt_ODTTextStyle(): # Background Color assert txtStyle._tAttr["background-color"] == ["fo", None] - txtStyle.setBackgroundColor("stuff") - assert txtStyle._tAttr["background-color"] == ["fo", None] - txtStyle.setBackgroundColor("012345") + txtStyle.setBackgroundColor("#012345") # type: ignore assert txtStyle._tAttr["background-color"] == ["fo", None] - txtStyle.setBackgroundColor("#012345") - assert txtStyle._tAttr["background-color"] == ["fo", "#012345"] - txtStyle.setBackgroundColor("stuff") + txtStyle.setBackgroundColor(QColor(255, 128, 0)) + assert txtStyle._tAttr["background-color"] == ["fo", "#ff8000"] + txtStyle.setBackgroundColor(None) assert txtStyle._tAttr["background-color"] == ["fo", None] # Text Position