Add working meta data blocks

This commit is contained in:
Veronica Berglyd Olsen
2024-05-23 20:48:42 +02:00
parent c8017a1f42
commit e998cb634e
3 changed files with 79 additions and 38 deletions
+4 -1
View File
@@ -597,7 +597,10 @@ class Tokenizer(ABC):
# are automatically skipped.
valid, bits, _ = self._project.index.scanThis(aLine)
if valid and bits and bits[0] not in self._skipKeywords:
if (
valid and bits and bits[0] in nwLabels.KEY_NAME
and bits[0] not in self._skipKeywords
):
tokens.append((
self.T_KEYWORD, nHead, aLine[1:].strip(), [], sAlign
))
+68 -30
View File
@@ -26,12 +26,12 @@ from __future__ import annotations
import logging
from PyQt5.QtGui import (
QColor, QFont, QFontMetrics, QTextBlockFormat, QTextCharFormat,
QTextCursor, QTextDocument
QFont, QFontMetrics, QTextBlockFormat, QTextCharFormat, QTextCursor,
QTextDocument
)
from novelwriter import SHARED
from novelwriter.constants import nwHeaders
from novelwriter.constants import nwHeaders, nwHeadFmt, nwKeyWords, nwLabels, nwUnicode
from novelwriter.core.project import NWProject
from novelwriter.core.tokenizer import T_Formats, Tokenizer
from novelwriter.types import (
@@ -99,6 +99,24 @@ class ToQTextDocument(Tokenizer):
self._defaultChar = QTextCharFormat()
self._defaultChar.setForeground(SHARED.theme.colText)
self._comChar = QTextCharFormat()
self._comChar.setForeground(SHARED.theme.colHidden)
self._noteChar = QTextCharFormat()
self._noteChar.setForeground(SHARED.theme.colNote)
self._modChar = QTextCharFormat()
self._modChar.setForeground(SHARED.theme.colMod)
self._keyChar = QTextCharFormat()
self._keyChar.setForeground(SHARED.theme.colKey)
self._tagChar = QTextCharFormat()
self._tagChar.setForeground(SHARED.theme.colTag)
self._optChar = QTextCharFormat()
self._optChar.setForeground(SHARED.theme.colOpt)
self._defaultBlock = QTextBlockFormat()
self._defaultBlock.setTopMargin(self._mText[0])
self._defaultBlock.setBottomMargin(self._mText[1])
@@ -139,7 +157,7 @@ class ToQTextDocument(Tokenizer):
else:
cursor.setBlockFormat(bFmt)
for tType, _, tText, tFormat, tStyle in self._tokens:
for tType, nHead, tText, tFormat, tStyle in self._tokens:
# Styles
bFmt = QTextBlockFormat(self._defaultBlock)
@@ -173,9 +191,9 @@ class ToQTextDocument(Tokenizer):
self._insertFragments(tText, tFormat, cursor, self._defaultChar)
elif tType in self.L_HEADINGS:
bFmt, cFmt = self._genHeadStyle(tType, bFmt)
bFmt, cFmt = self._genHeadStyle(tType, nHead, bFmt)
newBlock(bFmt)
cursor.insertText(tText, cFmt)
cursor.insertText(tText.replace(nwHeadFmt.BR, "\n"), cFmt)
elif tType == self.T_SEP:
newBlock(bFmt)
@@ -183,20 +201,30 @@ class ToQTextDocument(Tokenizer):
elif tType == self.T_SKIP:
newBlock(bFmt)
cursor.insertText(nwUnicode.U_NBSP, self._defaultChar)
elif tType == self.T_SYNOPSIS and self._doSynopsis:
pass
newBlock(bFmt)
prefix = self._localLookup("Synopsis")
cursor.insertText(f"{prefix}: ", self._modChar)
self._insertFragments(tText, tFormat, cursor, self._noteChar)
elif tType == self.T_SHORT and self._doSynopsis:
pass
newBlock(bFmt)
prefix = self._localLookup("Short Description")
cursor.insertText(f"{prefix}: ", self._modChar)
self._insertFragments(tText, tFormat, cursor, self._noteChar)
elif tType == self.T_COMMENT and self._doComments:
pass
newBlock(bFmt)
self._insertFragments(tText, tFormat, cursor, self._comChar)
elif tType == self.T_KEYWORD and self._doKeywords:
pass
newBlock(bFmt)
self._insertKeywords(tText, cursor)
self._document.blockSignals(False)
print(self._document.toHtml())
return
@@ -226,16 +254,16 @@ class ToQTextDocument(Tokenizer):
##
def _insertFragments(
self, text: str, tFmt: T_Formats, cursor: QTextCursor,
dFmt: QTextCharFormat, bgCol: QColor = QtTransparent
self, text: str, tFmt: T_Formats, cursor: QTextCursor, dFmt: QTextCharFormat
) -> None:
"""Apply formatting tags to text."""
cFmt = QTextCharFormat(dFmt)
start = 0
temp = text.replace("\n", nwUnicode.U_LSEP)
for pos, fmt, data in tFmt:
# Insert buffer with previous format
cursor.insertText(text[start:pos], cFmt)
cursor.insertText(temp[start:pos], cFmt)
# Construct next format
if fmt == self.FMT_B_B:
@@ -257,7 +285,7 @@ class ToQTextDocument(Tokenizer):
elif fmt == self.FMT_M_B:
cFmt.setBackground(SHARED.theme.colMark)
elif fmt == self.FMT_M_E:
cFmt.setBackground(bgCol)
cFmt.setBackground(QtTransparent)
elif fmt == self.FMT_SUP_B:
cFmt.setVerticalAlignment(QtVAlignSuper)
elif fmt == self.FMT_SUP_E:
@@ -280,27 +308,35 @@ class ToQTextDocument(Tokenizer):
start = pos
# Insert whatever is left in the buffer
cursor.insertText(text[start:], cFmt)
cursor.insertText(temp[start:], cFmt)
return
def _formatKeywords(self, text: str, style: int) -> str:
def _insertKeywords(self, text: str, cursor: QTextCursor) -> None:
"""Apply Markdown formatting to keywords."""
# valid, bits, _ = self._project.index.scanThis("@"+text)
# if not valid or not bits:
# return ""
valid, bits, _ = self._project.index.scanThis("@"+text)
if valid and bits:
key = f"{self._localLookup(nwLabels.KEY_NAME[bits[0]])}: "
cursor.insertText(key, self._keyChar)
if (num := len(bits)) > 1:
if bits[0] == nwKeyWords.TAG_KEY:
one, two = self._project.index.parseValue(bits[1])
cursor.insertText(one, self._tagChar)
if two:
cursor.insertText(" | ", self._defaultChar)
cursor.insertText(two, self._optChar)
else:
for n, bit in enumerate(bits[1:], 2):
cFmt = QTextCharFormat(self._tagChar)
cFmt.setFontUnderline(True)
cFmt.setAnchor(True)
cFmt.setAnchorHref(f"#{bits[0][1:]}={bit}")
cursor.insertText(bit, cFmt)
if n < num:
cursor.insertText(", ", self._defaultChar)
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 & self.A_Z_BTMMRG else "\n\n"
return result
def _genHeadStyle(self, level: int, rFmt: QTextBlockFormat) -> T_TextStyle:
def _genHeadStyle(self, level: int, nHead: int, rFmt: QTextBlockFormat) -> T_TextStyle:
"""Generate a heading style set."""
mTop, mBottom = self._mHead.get(level, (0.0, 0.0))
@@ -312,5 +348,7 @@ class ToQTextDocument(Tokenizer):
cFmt.setForeground(SHARED.theme.colHead)
cFmt.setFontWeight(QFont.Weight.Bold)
cFmt.setFontPointSize(self._sHead.get(level, 1.0))
cFmt.setAnchorNames([f"{self._handle}:T{nHead:04d}"])
cFmt.setAnchor(True)
return bFmt, cFmt
+7 -7
View File
@@ -27,7 +27,7 @@ from PyQt5.QtGui import QMouseEvent, QTextCursor
from PyQt5.QtWidgets import QAction, QApplication, QMenu
from novelwriter import CONFIG, SHARED
from novelwriter.core.tohtml import ToHtml
from novelwriter.core.toqdoc import ToQTextDocument
from novelwriter.enum import nwDocAction
from novelwriter.gui.docviewer import GuiDocViewer
from novelwriter.types import QtModeNone, QtMouseLeft
@@ -119,7 +119,7 @@ def testGuiViewer_Main(qtbot, monkeypatch, nwGUI, prjLipsum):
# Select All
assert docViewer.docAction(nwDocAction.SEL_ALL) is True
cursor = docViewer.textCursor()
assert len(cursor.selectedText()) == 3061
assert len(cursor.selectedText()) == 3060
# Other actions
assert docViewer.docAction(nwDocAction.NO_ACTION) is False
@@ -196,19 +196,19 @@ def testGuiViewer_Main(qtbot, monkeypatch, nwGUI, prjLipsum):
# Document footer show/hide synopsis
assert nwGUI.viewDocument("f96ec11c6a3da") is True
assert len(docViewer.toPlainText()) == 4315
assert len(docViewer.toPlainText()) == 4314
docViewer.docFooter._doToggleSynopsis(False)
assert len(docViewer.toPlainText()) == 4099
assert len(docViewer.toPlainText()) == 4098
# Document footer show/hide comments
assert nwGUI.viewDocument("846352075de7d") is True
assert len(docViewer.toPlainText()) == 675
assert len(docViewer.toPlainText()) == 674
docViewer.docFooter._doToggleComments(False)
assert len(docViewer.toPlainText()) == 635
assert len(docViewer.toPlainText()) == 634
# Crash the HTML rendering
with monkeypatch.context() as mp:
mp.setattr(ToHtml, "doConvert", causeException)
mp.setattr(ToQTextDocument, "doConvert", causeException)
assert docViewer.loadText("846352075de7d") is False
assert docViewer.toPlainText() == "An error occurred while generating the preview."