Tokenize dialogue with colour tag

This commit is contained in:
Veronica Berglyd Olsen
2024-10-22 18:41:34 +02:00
parent c537d0f396
commit 63f9cd0bac
13 changed files with 107 additions and 146 deletions
+1
View File
@@ -160,6 +160,7 @@ class NWBuildDocument:
elif bFormat in (nwBuildFmt.HTML, nwBuildFmt.J_HTML):
makeObj = ToHtml(self._project)
filtered = self._setupBuild(makeObj)
makeObj.initDocument()
yield from self._iterBuild(makeObj, filtered)
+2 -6
View File
@@ -86,12 +86,8 @@ class TextFmt(IntEnum):
SUB_E = 14 # End subscript
COL_B = 15 # Begin colour
COL_E = 16 # End colour
DL_B = 17 # Begin dialogue
DL_E = 18 # End dialogue
ADL_B = 19 # Begin alt dialogue
ADL_E = 20 # End alt dialogue
FNOTE = 21 # Footnote marker
STRIP = 22 # Strip the format code
FNOTE = 17 # Footnote marker
STRIP = 18 # Strip the format code
class BlockTyp(IntEnum):
+1 -17
View File
@@ -96,8 +96,6 @@ X_MRK = 0x010 # Marked format
X_SUP = 0x020 # Superscript
X_SUB = 0x040 # Subscript
X_COL = 0x080 # Coloured text
X_DLG = 0x100 # Dialogue
X_DLA = 0x200 # Alt. Dialogue
# Formatting Masks
M_BLD = ~X_BLD
@@ -108,8 +106,6 @@ M_MRK = ~X_MRK
M_SUP = ~X_SUP
M_SUB = ~X_SUB
M_COL = ~X_COL
M_DLG = ~X_DLG
M_DLA = ~X_DLA
# DocX Styles
S_NORM = "Normal"
@@ -292,7 +288,7 @@ class ToDocX(Tokenizer):
elif tType == BlockTyp.SKIP:
self._processFragments(par, S_NORM, "")
elif tType in self.L_NOTES:
elif tType == BlockTyp.COMMENT:
self._processFragments(par, S_META, tText, tFormat)
elif tType == BlockTyp.KEYWORD and self._doKeywords:
@@ -441,14 +437,6 @@ class ToDocX(Tokenizer):
elif fFmt == TextFmt.COL_E:
xFmt &= M_COL
fClass = ""
elif fFmt == TextFmt.DL_B:
xFmt |= X_DLG
elif fFmt == TextFmt.DL_E:
xFmt &= M_DLG
elif fFmt == TextFmt.ADL_B:
xFmt |= X_DLA
elif fFmt == TextFmt.ADL_E:
xFmt &= M_DLA
elif fFmt == TextFmt.FNOTE:
xNode = self._generateFootnote(fData)
elif fFmt == TextFmt.STRIP:
@@ -487,10 +475,6 @@ class ToDocX(Tokenizer):
xmlSubElem(rPr, _wTag("vertAlign"), attrib={_wTag("val"): "subscript"})
if fmt & X_COL and (color := self._classes.get(fClass)):
xmlSubElem(rPr, _wTag("color"), attrib={_wTag("val"): _docXCol(color)})
if fmt & X_DLG:
xmlSubElem(rPr, _wTag("color"), attrib={_wTag("val"): COL_DIALOG_M})
if fmt & X_DLA:
xmlSubElem(rPr, _wTag("color"), attrib={_wTag("val"): COL_DIALOG_A})
for segment in RX_TEXT.split(text):
if segment == "\n":
+7 -14
View File
@@ -47,8 +47,7 @@ HTML_OPENER: dict[int, tuple[int, str]] = {
TextFmt.M_B: (TextFmt.M_E, "<mark>"),
TextFmt.SUP_B: (TextFmt.SUP_E, "<sup>"),
TextFmt.SUB_B: (TextFmt.SUB_E, "<sub>"),
TextFmt.DL_B: (TextFmt.DL_E, "<span class='dialog'>"),
TextFmt.ADL_B: (TextFmt.ADL_E, "<span class='altdialog'>"),
TextFmt.COL_B: (TextFmt.COL_E, "<span style='color: {0}'>"),
}
# Each closer tag, with the id of its corresponding opener and tag format
@@ -60,8 +59,7 @@ HTML_CLOSER: dict[int, tuple[int, str]] = {
TextFmt.M_E: (TextFmt.M_B, "</mark>"),
TextFmt.SUP_E: (TextFmt.SUP_B, "</sup>"),
TextFmt.SUB_E: (TextFmt.SUB_B, "</sub>"),
TextFmt.DL_E: (TextFmt.DL_B, "</span>"),
TextFmt.ADL_E: (TextFmt.ADL_B, "</span>"),
TextFmt.COL_E: (TextFmt.COL_B, "</span>"),
}
# Empty HTML tag record
@@ -251,10 +249,7 @@ class ToHtml(Tokenizer):
elif tType == BlockTyp.SKIP:
lines.append(f"<p class='skip'{hStyle}>&nbsp;</p>\n")
elif tType == BlockTyp.SUMMARY:
lines.append(f"<p class='synopsis'>{self._formatText(tText, tFormat)}</p>\n")
elif tType == BlockTyp.COMMENT and self._doComments:
elif tType == BlockTyp.COMMENT:
lines.append(f"<p class='comment'>{self._formatText(tText, tFormat)}</p>\n")
elif tType == BlockTyp.KEYWORD and self._doKeywords:
@@ -439,11 +434,6 @@ class ToHtml(Tokenizer):
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(".break {text-align: left;}")
styles.append(".synopsis {font-style: italic;}")
styles.append(".comment {font-style: italic; color: rgb(100, 100, 100);}")
styles.append(".dialog {color: rgb(66, 113, 174);}")
styles.append(".altdialog {color: rgb(129, 55, 9);}")
return styles
@@ -463,7 +453,10 @@ class ToHtml(Tokenizer):
for pos, fmt, data in tFmt:
if m := HTML_OPENER.get(fmt):
if not state.get(fmt, True):
tags.append((pos, m[1]))
if fmt == TextFmt.COL_B and (color := self._classes.get(data)):
tags.append((pos, m[1].format(color.name(QtHexRgb))))
else:
tags.append((pos, m[1]))
state[fmt] = True
elif m := HTML_CLOSER.get(fmt):
if state.get(m[0], False):
+21 -19
View File
@@ -58,18 +58,17 @@ class ComStyle(NamedTuple):
label: str = ""
labelClass: str = ""
textClass: str = ""
blockType: BlockTyp = BlockTyp.TEXT
COMMENT_STYLE = {
nwComment.PLAIN: ComStyle("Comment", "comment", "comment", BlockTyp.COMMENT),
nwComment.PLAIN: ComStyle("Comment", "comment", "comment"),
nwComment.IGNORE: ComStyle(),
nwComment.SYNOPSIS: ComStyle("Synopsis", "modifier", "synopsis", BlockTyp.SUMMARY),
nwComment.SHORT: ComStyle("Short Description", "modifier", "synopsis", BlockTyp.SUMMARY),
nwComment.NOTE: ComStyle("Note", "modifier", "note", BlockTyp.NOTE),
nwComment.SYNOPSIS: ComStyle("Synopsis", "modifier", "synopsis"),
nwComment.SHORT: ComStyle("Short Description", "modifier", "synopsis"),
nwComment.NOTE: ComStyle("Note", "modifier", "note"),
nwComment.FOOTNOTE: ComStyle("", "modifier", "note"),
nwComment.COMMENT: ComStyle(),
nwComment.STORY: ComStyle("", "modifier", "note", BlockTyp.NOTE),
nwComment.STORY: ComStyle("", "modifier", "note"),
}
@@ -93,7 +92,6 @@ class Tokenizer(ABC):
BlockTyp.TITLE, BlockTyp.HEAD1, BlockTyp.HEAD2, BlockTyp.HEAD2, BlockTyp.HEAD3,
BlockTyp.HEAD4, BlockTyp.SEP, BlockTyp.SKIP,
]
L_NOTES = [BlockTyp.SUMMARY, BlockTyp.NOTE, BlockTyp.COMMENT]
def __init__(self, project: NWProject) -> None:
@@ -208,7 +206,7 @@ class Tokenizer(ABC):
nwShortcode.FOOTNOTE_B: TextFmt.FNOTE,
}
self._rxDialogue: list[tuple[re.Pattern, int, int]] = []
self._rxDialogue: list[tuple[re.Pattern, tuple[int, str], tuple[int, str]]] = []
return
@@ -352,19 +350,23 @@ class Tokenizer(ABC):
if state:
if CONFIG.dialogStyle > 0:
self._rxDialogue.append((
REGEX_PATTERNS.dialogStyle, TextFmt.DL_B, TextFmt.DL_E
REGEX_PATTERNS.dialogStyle,
(TextFmt.COL_B, "dialog"), (TextFmt.COL_E, ""),
))
if CONFIG.dialogLine:
self._rxDialogue.append((
REGEX_PATTERNS.dialogLine, TextFmt.DL_B, TextFmt.DL_E
REGEX_PATTERNS.dialogLine,
(TextFmt.COL_B, "dialog"), (TextFmt.COL_E, ""),
))
if CONFIG.narratorBreak:
self._rxDialogue.append((
REGEX_PATTERNS.narratorBreak, TextFmt.DL_E, TextFmt.DL_B
REGEX_PATTERNS.narratorBreak,
(TextFmt.COL_E, ""), (TextFmt.COL_B, "dialog"),
))
if CONFIG.altDialogOpen and CONFIG.altDialogClose:
self._rxDialogue.append((
REGEX_PATTERNS.altDialogStyle, TextFmt.ADL_B, TextFmt.ADL_E
REGEX_PATTERNS.altDialogStyle,
(TextFmt.COL_B, "altdialog"), (TextFmt.COL_E, ""),
))
return
@@ -460,6 +462,8 @@ class Tokenizer(ABC):
self._classes["modifier"] = self._theme.modifier
self._classes["synopsis"] = self._theme.note
self._classes["comment"] = self._theme.comment
self._classes["dialog"] = self._theme.dialog
self._classes["altdialog"] = self._theme.altdialog
return
def addRootHeading(self, tHandle: str) -> None:
@@ -610,7 +614,7 @@ class Tokenizer(ABC):
if cStyle in (nwComment.SYNOPSIS, nwComment.SHORT, nwComment.PLAIN):
bStyle = COMMENT_STYLE[cStyle]
tLine, tFmt = self._formatNote(bStyle, cKey, cText)
blocks.append((bStyle.blockType, nHead, tLine, tFmt, sAlign))
blocks.append((BlockTyp.COMMENT, nHead, tLine, tFmt, sAlign))
if self._keepRaw:
tmpMarkdown.append(f"{aLine}\n")
@@ -619,8 +623,6 @@ class Tokenizer(ABC):
self._footnotes[f"{tHandle}:{cKey}"] = (tLine, tFmt)
if self._keepRaw:
tmpMarkdown.append(f"{aLine}\n")
else:
continue
elif aLine.startswith("@"):
# Keywords
@@ -1014,7 +1016,7 @@ class Tokenizer(ABC):
allChars += nChars
allWordChars += nWChars
elif tType in self.L_NOTES:
elif tType == BlockTyp.COMMENT:
words = tText.split()
allWords += len(words)
allChars += len(tText)
@@ -1130,10 +1132,10 @@ class Tokenizer(ABC):
# Match Dialogue
if self._rxDialogue and hDialog:
for regEx, fmtB, fmtE in self._rxDialogue:
for regEx, (fmtB, clsB), (fmtE, clsE) in self._rxDialogue:
for res in regEx.finditer(text):
temp.append((res.start(0), 0, fmtB, ""))
temp.append((res.end(0), 0, fmtE, ""))
temp.append((res.start(0), 0, fmtB, clsB))
temp.append((res.end(0), 0, fmtE, clsE))
# Post-process text and format
result = text
+1 -1
View File
@@ -150,7 +150,7 @@ class ToMarkdown(Tokenizer):
elif tType == BlockTyp.SKIP:
lines.append(f"{cSkip}\n\n")
elif tType in self.L_NOTES:
elif tType == BlockTyp.COMMENT:
lines.append(f"{self._formatText(tText, tFormat, mTags)}\n\n")
elif tType == BlockTyp.KEYWORD and self._doKeywords:
+1 -13
View File
@@ -91,8 +91,6 @@ X_MRK = 0x010 # Marked format
X_SUP = 0x020 # Superscript
X_SUB = 0x040 # Subscript
X_COL = 0x080 # Coloured text
X_DLG = 0x100 # Dialogue
X_DLA = 0x200 # Alt. Dialogue
# Formatting Masks
M_BLD = ~X_BLD
@@ -103,8 +101,6 @@ M_MRK = ~X_MRK
M_SUP = ~X_SUP
M_SUB = ~X_SUB
M_COL = ~X_COL
M_DLG = ~X_DLG
M_DLA = ~X_DLA
# ODT Styles
S_TITLE = "Title"
@@ -484,7 +480,7 @@ class ToOdt(Tokenizer):
elif tType == BlockTyp.SKIP:
self._addTextPar(xText, S_TEXT, oStyle, "")
elif tType in self.L_NOTES:
elif tType == BlockTyp.COMMENT:
self._addTextPar(xText, S_META, oStyle, tText, tFmt=tFormat)
elif tType == BlockTyp.KEYWORD and self._doKeywords:
@@ -657,14 +653,6 @@ class ToOdt(Tokenizer):
elif fFmt == TextFmt.COL_E:
xFmt &= M_COL
fClass = ""
elif fFmt == TextFmt.DL_B:
xFmt |= X_DLG
elif fFmt == TextFmt.DL_E:
xFmt &= M_DLG
elif fFmt == TextFmt.ADL_B:
xFmt |= X_DLA
elif fFmt == TextFmt.ADL_E:
xFmt &= M_DLA
elif fFmt == TextFmt.FNOTE:
xNode = self._generateFootnote(fData)
elif fFmt == TextFmt.STRIP:
+1 -13
View File
@@ -240,7 +240,7 @@ class ToQTextDocument(Tokenizer):
newBlock(cursor, bFmt)
cursor.insertText(nwUnicode.U_NBSP, self._cText)
elif tType in self.L_NOTES:
elif tType == BlockTyp.COMMENT:
newBlock(cursor, bFmt)
self._insertFragments(tText, tFormat, cursor, self._cText)
@@ -337,23 +337,11 @@ class ToQTextDocument(Tokenizer):
cFmt.setVerticalAlignment(QtVAlignSub)
elif fmt == TextFmt.SUB_E:
cFmt.setVerticalAlignment(QtVAlignNormal)
elif fmt == TextFmt.SUB_B:
cFmt.setVerticalAlignment(QtVAlignSub)
elif fmt == TextFmt.SUB_E:
cFmt.setVerticalAlignment(QtVAlignNormal)
elif fmt == TextFmt.COL_B:
if color := self._classes.get(data):
cFmt.setForeground(color)
elif fmt == TextFmt.COL_E:
cFmt.setForeground(self._theme.text)
elif fmt == TextFmt.DL_B:
cFmt.setForeground(self._theme.dialog)
elif fmt == TextFmt.DL_E:
cFmt.setForeground(self._theme.text)
elif fmt == TextFmt.ADL_B:
cFmt.setForeground(self._theme.altdialog)
elif fmt == TextFmt.ADL_E:
cFmt.setForeground(self._theme.text)
elif fmt == TextFmt.FNOTE:
xFmt = QTextCharFormat(self._cCode)
xFmt.setVerticalAlignment(QtVAlignSuper)