Distinguish between anchor ref and href in tokenizer
This commit is contained in:
@@ -87,10 +87,12 @@ class TextFmt(IntEnum):
|
|||||||
COL_E = 16 # End colour
|
COL_E = 16 # End colour
|
||||||
ANM_B = 17 # Begin anchor name
|
ANM_B = 17 # Begin anchor name
|
||||||
ANM_E = 18 # End anchor name
|
ANM_E = 18 # End anchor name
|
||||||
HRF_B = 19 # Begin href link
|
ARF_B = 19 # Begin anchor link
|
||||||
HRF_E = 20 # End href link
|
ARF_E = 20 # End anchor link
|
||||||
FNOTE = 21 # Footnote marker
|
HRF_B = 21 # Begin href link
|
||||||
STRIP = 22 # Strip the format code
|
HRF_E = 22 # End href link
|
||||||
|
FNOTE = 23 # Footnote marker
|
||||||
|
STRIP = 24 # Strip the format code
|
||||||
|
|
||||||
|
|
||||||
class BlockTyp(IntEnum):
|
class BlockTyp(IntEnum):
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ HTML_OPENER: dict[int, tuple[int, str]] = {
|
|||||||
TextFmt.SUB_B: (TextFmt.SUB_E, "<sub>"),
|
TextFmt.SUB_B: (TextFmt.SUB_E, "<sub>"),
|
||||||
TextFmt.COL_B: (TextFmt.COL_E, "<span style='color: {0}'>"),
|
TextFmt.COL_B: (TextFmt.COL_E, "<span style='color: {0}'>"),
|
||||||
TextFmt.ANM_B: (TextFmt.ANM_E, "<a name='{0}'>"),
|
TextFmt.ANM_B: (TextFmt.ANM_E, "<a name='{0}'>"),
|
||||||
|
TextFmt.ARF_B: (TextFmt.ARF_E, "<a href='{0}'>"),
|
||||||
TextFmt.HRF_B: (TextFmt.HRF_E, "<a href='{0}'>"),
|
TextFmt.HRF_B: (TextFmt.HRF_E, "<a href='{0}'>"),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,6 +64,7 @@ HTML_CLOSER: dict[int, tuple[int, str]] = {
|
|||||||
TextFmt.SUB_E: (TextFmt.SUB_B, "</sub>"),
|
TextFmt.SUB_E: (TextFmt.SUB_B, "</sub>"),
|
||||||
TextFmt.COL_E: (TextFmt.COL_B, "</span>"),
|
TextFmt.COL_E: (TextFmt.COL_B, "</span>"),
|
||||||
TextFmt.ANM_E: (TextFmt.ANM_B, "</a>"),
|
TextFmt.ANM_E: (TextFmt.ANM_B, "</a>"),
|
||||||
|
TextFmt.ARF_E: (TextFmt.ARF_B, "</a>"),
|
||||||
TextFmt.HRF_E: (TextFmt.HRF_B, "</a>"),
|
TextFmt.HRF_E: (TextFmt.HRF_B, "</a>"),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,7 +400,7 @@ class ToHtml(Tokenizer):
|
|||||||
if not state.get(fmt, True):
|
if not state.get(fmt, True):
|
||||||
if fmt == TextFmt.COL_B and (color := self._classes.get(data)):
|
if fmt == TextFmt.COL_B and (color := self._classes.get(data)):
|
||||||
tags.append((pos, m[1].format(color.name(QtHexRgb))))
|
tags.append((pos, m[1].format(color.name(QtHexRgb))))
|
||||||
elif fmt in (TextFmt.ANM_B, TextFmt.HRF_B):
|
elif fmt in (TextFmt.ANM_B, TextFmt.ARF_B, TextFmt.HRF_B):
|
||||||
tags.append((pos, m[1].format(data or "#")))
|
tags.append((pos, m[1].format(data or "#")))
|
||||||
else:
|
else:
|
||||||
tags.append((pos, m[1]))
|
tags.append((pos, m[1]))
|
||||||
|
|||||||
@@ -1089,8 +1089,8 @@ class Tokenizer(ABC):
|
|||||||
for n, bit in enumerate(bits[1:], 2):
|
for n, bit in enumerate(bits[1:], 2):
|
||||||
end = pos + len(bit)
|
end = pos + len(bit)
|
||||||
fmt.append((pos, TextFmt.COL_B, "tag"))
|
fmt.append((pos, TextFmt.COL_B, "tag"))
|
||||||
fmt.append((pos, TextFmt.HRF_B, f"#tag_{bit}".lower()))
|
fmt.append((pos, TextFmt.ARF_B, f"#tag_{bit}".lower()))
|
||||||
fmt.append((end, TextFmt.HRF_E, ""))
|
fmt.append((end, TextFmt.ARF_E, ""))
|
||||||
fmt.append((end, TextFmt.COL_E, ""))
|
fmt.append((end, TextFmt.COL_E, ""))
|
||||||
txt.append(bit)
|
txt.append(bit)
|
||||||
pos = end
|
pos = end
|
||||||
|
|||||||
@@ -330,12 +330,12 @@ class ToQTextDocument(Tokenizer):
|
|||||||
cFmt.setAnchorNames([data])
|
cFmt.setAnchorNames([data])
|
||||||
elif fmt == TextFmt.ANM_E:
|
elif fmt == TextFmt.ANM_E:
|
||||||
cFmt.setAnchor(False)
|
cFmt.setAnchor(False)
|
||||||
elif fmt == TextFmt.HRF_B:
|
elif fmt in (TextFmt.HRF_B, TextFmt.ARF_B):
|
||||||
cFmt.setForeground(primary or self._theme.link)
|
cFmt.setForeground(primary or self._theme.link)
|
||||||
cFmt.setFontUnderline(True)
|
cFmt.setFontUnderline(True)
|
||||||
cFmt.setAnchor(True)
|
cFmt.setAnchor(True)
|
||||||
cFmt.setAnchorHref(data)
|
cFmt.setAnchorHref(data)
|
||||||
elif fmt == TextFmt.HRF_E:
|
elif fmt in (TextFmt.HRF_E, TextFmt.ARF_E):
|
||||||
cFmt.setForeground(primary or self._theme.text)
|
cFmt.setForeground(primary or self._theme.text)
|
||||||
cFmt.setFontUnderline(False)
|
cFmt.setFontUnderline(False)
|
||||||
cFmt.setAnchor(False)
|
cFmt.setAnchor(False)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
%%~name: Making a Scene
|
%%~name: Making a Scene
|
||||||
%%~path: 6a2d6d5f4f401/636b6aa9b697b
|
%%~path: 6a2d6d5f4f401/636b6aa9b697b
|
||||||
%%~kind: NOVEL/DOCUMENT
|
%%~kind: NOVEL/DOCUMENT
|
||||||
%%~hash: 349d9ce3d59ad241d63b01380c53a7fb26ce9f19
|
%%~hash: 89d562ae05727028d74bd10cfd6953882d1cd140
|
||||||
%%~date: Unknown/2024-10-24 23:44:27
|
%%~date: Unknown/2024-10-25 12:41:02
|
||||||
### Making a Scene
|
### Making a Scene
|
||||||
|
|
||||||
@pov: Jane
|
@pov: Jane
|
||||||
@@ -20,6 +20,8 @@ In addition, the editor supports automatic formatting of “quotes”, both doub
|
|||||||
|
|
||||||
If you have the need for it, you can also add text that can be automatically replaced by other text when you generate a preview or export the project. Now, let’s auto-replace this A with <A>, and this C with <C>. While <E> is just <E>. Press Ctrl+R to see what this looks like in the view pane. The list of auto-replaced text is set in Project Settings.
|
If you have the need for it, you can also add text that can be automatically replaced by other text when you generate a preview or export the project. Now, let’s auto-replace this A with <A>, and this C with <C>. While <E> is just <E>. Press Ctrl+R to see what this looks like in the view pane. The list of auto-replaced text is set in Project Settings.
|
||||||
|
|
||||||
|
You can also add URLs like http://www.example.com to the text.
|
||||||
|
|
||||||
The editor also supports non breaking spaces, and the spell checker accepts long dashes—like this—as valid word separators. Regular dashes are also supported – and can be automatically inserted when typing two hyphens.
|
The editor also supports non breaking spaces, and the spell checker accepts long dashes—like this—as valid word separators. Regular dashes are also supported – and can be automatically inserted when typing two hyphens.
|
||||||
|
|
||||||
Thin spaces and thin non-breaking spaces are also supported from the Insert menu, and can be used to separate numbers from their units, like: 25 kg.[footnote:f4xr5]
|
Thin spaces and thin non-breaking spaces are also supported from the Insert menu, and can be used to separate numbers from their units, like: 25 kg.[footnote:f4xr5]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<novelWriterXML appVersion="2.6a2" hexVersion="0x020600a2" fileVersion="1.5" fileRevision="4" timeStamp="2024-10-24 23:58:23">
|
<novelWriterXML appVersion="2.6a2" hexVersion="0x020600a2" fileVersion="1.5" fileRevision="4" timeStamp="2024-10-25 23:19:07">
|
||||||
<project id="e2be99af-f9bf-4403-857a-c3d1ac25abea" saveCount="2088" autoCount="280" editTime="93793">
|
<project id="e2be99af-f9bf-4403-857a-c3d1ac25abea" saveCount="2122" autoCount="279" editTime="94855">
|
||||||
<name>Sample Project</name>
|
<name>Sample Project</name>
|
||||||
<author>Jane Smith</author>
|
<author>Jane Smith</author>
|
||||||
</project>
|
</project>
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
<entry key="i56be10" count="1" red="220" green="138" blue="221" shape="BLOCK_4">Main</entry>
|
<entry key="i56be10" count="1" red="220" green="138" blue="221" shape="BLOCK_4">Main</entry>
|
||||||
</importance>
|
</importance>
|
||||||
</settings>
|
</settings>
|
||||||
<content items="31" novelWords="1004" notesWords="416">
|
<content items="31" novelWords="1014" notesWords="416">
|
||||||
<item handle="7031beac91f75" parent="None" root="7031beac91f75" order="0" type="ROOT" class="NOVEL">
|
<item handle="7031beac91f75" parent="None" root="7031beac91f75" order="0" type="ROOT" class="NOVEL">
|
||||||
<meta expanded="yes" />
|
<meta expanded="yes" />
|
||||||
<name status="sc24b8f" import="ia857f0">Novel</name>
|
<name status="sc24b8f" import="ia857f0">Novel</name>
|
||||||
@@ -58,11 +58,11 @@
|
|||||||
<name status="sf24ce6" import="ia857f0" active="yes">Chapter One</name>
|
<name status="sf24ce6" import="ia857f0" active="yes">Chapter One</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="636b6aa9b697b" parent="6a2d6d5f4f401" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="636b6aa9b697b" parent="6a2d6d5f4f401" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
<meta expanded="no" heading="H3" charCount="2937" wordCount="520" paraCount="15" cursorPos="19" />
|
<meta expanded="no" heading="H3" charCount="2999" wordCount="530" paraCount="16" cursorPos="1663" />
|
||||||
<name status="s90e6c9" import="ia857f0" active="yes">Making a Scene</name>
|
<name status="s90e6c9" import="ia857f0" active="yes">Making a Scene</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="bc0cbd2a407f3" parent="6a2d6d5f4f401" root="7031beac91f75" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="bc0cbd2a407f3" parent="6a2d6d5f4f401" root="7031beac91f75" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
<meta expanded="no" heading="H3" charCount="548" wordCount="108" paraCount="3" cursorPos="650" />
|
<meta expanded="no" heading="H3" charCount="548" wordCount="108" paraCount="3" cursorPos="691" />
|
||||||
<name status="s90e6c9" import="ia857f0" active="yes">Another Scene</name>
|
<name status="s90e6c9" import="ia857f0" active="yes">Another Scene</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="ba8a28a246524" parent="7031beac91f75" root="7031beac91f75" order="4" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="ba8a28a246524" parent="7031beac91f75" root="7031beac91f75" order="4" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
<name status="sf12341" import="ia857f0">Main Characters</name>
|
<name status="sf12341" import="ia857f0">Main Characters</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="14298de4d9524" parent="f7e2d9f330615" root="f6622b4617424" order="0" type="FILE" class="CHARACTER" layout="NOTE">
|
<item handle="14298de4d9524" parent="f7e2d9f330615" root="f6622b4617424" order="0" type="FILE" class="CHARACTER" layout="NOTE">
|
||||||
<meta expanded="no" heading="H1" charCount="49" wordCount="9" paraCount="1" cursorPos="15" />
|
<meta expanded="no" heading="H1" charCount="49" wordCount="9" paraCount="1" cursorPos="23" />
|
||||||
<name status="sf12341" import="i2d7a54" active="yes">John Smith</name>
|
<name status="sf12341" import="i2d7a54" active="yes">John Smith</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="bb2c23b3c42cc" parent="f7e2d9f330615" root="f6622b4617424" order="1" type="FILE" class="CHARACTER" layout="NOTE">
|
<item handle="bb2c23b3c42cc" parent="f7e2d9f330615" root="f6622b4617424" order="1" type="FILE" class="CHARACTER" layout="NOTE">
|
||||||
|
|||||||
@@ -834,8 +834,8 @@ def testFmtToken_MetaFormat(mockGUI):
|
|||||||
BlockTyp.KEYWORD, "char", "Characters: Bod", [
|
BlockTyp.KEYWORD, "char", "Characters: Bod", [
|
||||||
(0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"),
|
(0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"),
|
||||||
(11, TextFmt.COL_E, ""), (11, TextFmt.B_E, ""),
|
(11, TextFmt.COL_E, ""), (11, TextFmt.B_E, ""),
|
||||||
(12, TextFmt.COL_B, "tag"), (12, TextFmt.HRF_B, "#tag_bod"),
|
(12, TextFmt.COL_B, "tag"), (12, TextFmt.ARF_B, "#tag_bod"),
|
||||||
(15, TextFmt.HRF_E, ""), (15, TextFmt.COL_E, ""),
|
(15, TextFmt.ARF_E, ""), (15, TextFmt.COL_E, ""),
|
||||||
], BlockFmt.NONE
|
], BlockFmt.NONE
|
||||||
)]
|
)]
|
||||||
assert tokens._raw[-1] == "@char: Bod\n\n"
|
assert tokens._raw[-1] == "@char: Bod\n\n"
|
||||||
@@ -846,22 +846,22 @@ def testFmtToken_MetaFormat(mockGUI):
|
|||||||
BlockTyp.KEYWORD, "pov", "Point of View: Bod", [
|
BlockTyp.KEYWORD, "pov", "Point of View: Bod", [
|
||||||
(0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"),
|
(0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"),
|
||||||
(14, TextFmt.COL_E, ""), (14, TextFmt.B_E, ""),
|
(14, TextFmt.COL_E, ""), (14, TextFmt.B_E, ""),
|
||||||
(15, TextFmt.COL_B, "tag"), (15, TextFmt.HRF_B, "#tag_bod"),
|
(15, TextFmt.COL_B, "tag"), (15, TextFmt.ARF_B, "#tag_bod"),
|
||||||
(18, TextFmt.HRF_E, ""), (18, TextFmt.COL_E, ""),
|
(18, TextFmt.ARF_E, ""), (18, TextFmt.COL_E, ""),
|
||||||
], BlockFmt.Z_BTM
|
], BlockFmt.Z_BTM
|
||||||
), (
|
), (
|
||||||
BlockTyp.KEYWORD, "plot", "Plot: Main", [
|
BlockTyp.KEYWORD, "plot", "Plot: Main", [
|
||||||
(0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"),
|
(0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"),
|
||||||
(5, TextFmt.COL_E, ""), (5, TextFmt.B_E, ""),
|
(5, TextFmt.COL_E, ""), (5, TextFmt.B_E, ""),
|
||||||
(6, TextFmt.COL_B, "tag"), (6, TextFmt.HRF_B, "#tag_main"),
|
(6, TextFmt.COL_B, "tag"), (6, TextFmt.ARF_B, "#tag_main"),
|
||||||
(10, TextFmt.HRF_E, ""), (10, TextFmt.COL_E, ""),
|
(10, TextFmt.ARF_E, ""), (10, TextFmt.COL_E, ""),
|
||||||
], BlockFmt.Z_TOP | BlockFmt.Z_BTM
|
], BlockFmt.Z_TOP | BlockFmt.Z_BTM
|
||||||
), (
|
), (
|
||||||
BlockTyp.KEYWORD, "location", "Locations: Europe", [
|
BlockTyp.KEYWORD, "location", "Locations: Europe", [
|
||||||
(0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"),
|
(0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"),
|
||||||
(10, TextFmt.COL_E, ""), (10, TextFmt.B_E, ""),
|
(10, TextFmt.COL_E, ""), (10, TextFmt.B_E, ""),
|
||||||
(11, TextFmt.COL_B, "tag"), (11, TextFmt.HRF_B, "#tag_europe"),
|
(11, TextFmt.COL_B, "tag"), (11, TextFmt.ARF_B, "#tag_europe"),
|
||||||
(17, TextFmt.HRF_E, ""), (17, TextFmt.COL_E, ""),
|
(17, TextFmt.ARF_E, ""), (17, TextFmt.COL_E, ""),
|
||||||
], BlockFmt.Z_TOP
|
], BlockFmt.Z_TOP
|
||||||
)]
|
)]
|
||||||
assert tokens._raw[-1] == "@pov: Bod\n@plot: Main\n@location: Europe\n\n"
|
assert tokens._raw[-1] == "@pov: Bod\n@plot: Main\n@location: Europe\n\n"
|
||||||
@@ -874,8 +874,8 @@ def testFmtToken_MetaFormat(mockGUI):
|
|||||||
BlockTyp.KEYWORD, "pov", "Point of View: Bod", [
|
BlockTyp.KEYWORD, "pov", "Point of View: Bod", [
|
||||||
(0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"),
|
(0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"),
|
||||||
(14, TextFmt.COL_E, ""), (14, TextFmt.B_E, ""),
|
(14, TextFmt.COL_E, ""), (14, TextFmt.B_E, ""),
|
||||||
(15, TextFmt.COL_B, "tag"), (15, TextFmt.HRF_B, "#tag_bod"),
|
(15, TextFmt.COL_B, "tag"), (15, TextFmt.ARF_B, "#tag_bod"),
|
||||||
(18, TextFmt.HRF_E, ""), (18, TextFmt.COL_E, ""),
|
(18, TextFmt.ARF_E, ""), (18, TextFmt.COL_E, ""),
|
||||||
], BlockFmt.NONE
|
], BlockFmt.NONE
|
||||||
)]
|
)]
|
||||||
|
|
||||||
@@ -1831,10 +1831,10 @@ def testFmtToken_FormatMeta(mockGUI):
|
|||||||
"@char", "Characters: Jane, John", [
|
"@char", "Characters: Jane, John", [
|
||||||
(0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"),
|
(0, TextFmt.B_B, ""), (0, TextFmt.COL_B, "keyword"),
|
||||||
(11, TextFmt.COL_E, ""), (11, TextFmt.B_E, ""),
|
(11, TextFmt.COL_E, ""), (11, TextFmt.B_E, ""),
|
||||||
(12, TextFmt.COL_B, "tag"), (12, TextFmt.HRF_B, "#tag_jane"),
|
(12, TextFmt.COL_B, "tag"), (12, TextFmt.ARF_B, "#tag_jane"),
|
||||||
(16, TextFmt.HRF_E, ""), (16, TextFmt.COL_E, ""),
|
(16, TextFmt.ARF_E, ""), (16, TextFmt.COL_E, ""),
|
||||||
(18, TextFmt.COL_B, "tag"), (18, TextFmt.HRF_B, "#tag_john"),
|
(18, TextFmt.COL_B, "tag"), (18, TextFmt.ARF_B, "#tag_john"),
|
||||||
(22, TextFmt.HRF_E, ""), (22, TextFmt.COL_E, ""),
|
(22, TextFmt.ARF_E, ""), (22, TextFmt.COL_E, ""),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user