prefig 0.4.6.dev20250928053207__py3-none-any.whl → 0.4.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- prefig/core/arrow.py +6 -0
- prefig/core/diagram.py +30 -0
- prefig/core/repeat.py +34 -3
- prefig/resources/schema/pf_schema.rnc +4 -2
- prefig/resources/schema/pf_schema.rng +2250 -787
- {prefig-0.4.6.dev20250928053207.dist-info → prefig-0.4.7.dist-info}/METADATA +4 -4
- {prefig-0.4.6.dev20250928053207.dist-info → prefig-0.4.7.dist-info}/RECORD +10 -10
- {prefig-0.4.6.dev20250928053207.dist-info → prefig-0.4.7.dist-info}/LICENSE +0 -0
- {prefig-0.4.6.dev20250928053207.dist-info → prefig-0.4.7.dist-info}/WHEEL +0 -0
- {prefig-0.4.6.dev20250928053207.dist-info → prefig-0.4.7.dist-info}/entry_points.txt +0 -0
prefig/core/arrow.py
CHANGED
|
@@ -5,6 +5,7 @@ import numpy as np
|
|
|
5
5
|
from . import utilities as util
|
|
6
6
|
from . import CTM
|
|
7
7
|
from . import user_namespace as un
|
|
8
|
+
from . import repeat
|
|
8
9
|
|
|
9
10
|
log = logging.getLogger('prefigure')
|
|
10
11
|
|
|
@@ -189,6 +190,11 @@ def add_arrowhead_marker(diagram,
|
|
|
189
190
|
arrow_width = 13/3
|
|
190
191
|
dims = (1, arrow_width) #11/3)
|
|
191
192
|
|
|
193
|
+
# EPUB does not allow some characters to appear in @id
|
|
194
|
+
# There is a possibility that we have # or . so we will
|
|
195
|
+
# replace them with this function call
|
|
196
|
+
id = repeat.epub_clean(id)
|
|
197
|
+
|
|
192
198
|
# If we've already created this one, we'll just move on
|
|
193
199
|
if diagram.has_reusable(id):
|
|
194
200
|
return id
|
prefig/core/diagram.py
CHANGED
|
@@ -3,6 +3,7 @@ import lxml.etree as ET
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
import logging
|
|
5
5
|
import copy
|
|
6
|
+
import re
|
|
6
7
|
from . import tags
|
|
7
8
|
from . import user_namespace as un
|
|
8
9
|
from . import utilities as util
|
|
@@ -10,9 +11,13 @@ from . import CTM
|
|
|
10
11
|
from . import label
|
|
11
12
|
from . import math_utilities as math_util
|
|
12
13
|
from . import annotations
|
|
14
|
+
from . import repeat
|
|
13
15
|
|
|
14
16
|
log = logging.getLogger('prefigure')
|
|
15
17
|
|
|
18
|
+
# regular expression to check if id is EPUB compliant
|
|
19
|
+
epub_id_check = re.compile('^[A-Za-z0-9_-]+$')
|
|
20
|
+
|
|
16
21
|
class Diagram:
|
|
17
22
|
def __init__(self,
|
|
18
23
|
diagram_element,
|
|
@@ -129,9 +134,25 @@ class Diagram:
|
|
|
129
134
|
for child in templates_element:
|
|
130
135
|
self.defaults[child.tag] = child
|
|
131
136
|
|
|
137
|
+
annotations = self.diagram_element.xpath('.//annotations')
|
|
138
|
+
if len(annotations) > 0:
|
|
139
|
+
self.check_annotation_ref(annotations[0])
|
|
140
|
+
|
|
132
141
|
if self.defaults.get('macros', None) is not None:
|
|
133
142
|
label.add_macros(self.defaults.get('macros').text)
|
|
134
143
|
|
|
144
|
+
def check_annotation_ref(self, element):
|
|
145
|
+
ref = element.get('ref', None)
|
|
146
|
+
if ref is not None:
|
|
147
|
+
if not bool(epub_id_check.fullmatch(ref)):
|
|
148
|
+
log.error(f"@ref {ref} in an annotation has characters disallowed by EPUB")
|
|
149
|
+
log.error(" We will replace these characters but there may be unexpected behavior")
|
|
150
|
+
log.error(" Search for EPUB in the PreFigure documentation https://prefigure.org")
|
|
151
|
+
ref = repeat.epub_clean(ref)
|
|
152
|
+
element.set('ref', ref)
|
|
153
|
+
for child in element:
|
|
154
|
+
self.check_annotation_ref(child)
|
|
155
|
+
|
|
135
156
|
def add_legend(self, legend):
|
|
136
157
|
self.legends.append(legend)
|
|
137
158
|
|
|
@@ -436,6 +457,15 @@ class Diagram:
|
|
|
436
457
|
# we're publicly using 'at' rather than 'id' for handles
|
|
437
458
|
if child.get('at') is not None:
|
|
438
459
|
child.set('id', child.get('at'))
|
|
460
|
+
|
|
461
|
+
child_id = child.get('id', None)
|
|
462
|
+
if child_id is not None:
|
|
463
|
+
if not bool(epub_id_check.fullmatch(child_id)):
|
|
464
|
+
log.error(f"The id {child_id} has characters disallowed by EPUB")
|
|
465
|
+
log.error(" We will substitute disallowed characters to make the id EPUB compliant")
|
|
466
|
+
log.error(" Search for EPUB in the PreFigure documentation at https://prefigure.org")
|
|
467
|
+
child.set('id', repeat.epub_clean(child_id))
|
|
468
|
+
|
|
439
469
|
# see if the publication flie has any defaults
|
|
440
470
|
defaults = self.defaults.get(child.tag, None)
|
|
441
471
|
if defaults is not None:
|
prefig/core/repeat.py
CHANGED
|
@@ -2,6 +2,7 @@ import lxml.etree as ET
|
|
|
2
2
|
import logging
|
|
3
3
|
from . import user_namespace as un
|
|
4
4
|
import copy
|
|
5
|
+
import re
|
|
5
6
|
import numpy as np
|
|
6
7
|
from . import group
|
|
7
8
|
from . import label
|
|
@@ -9,6 +10,25 @@ from . import utilities
|
|
|
9
10
|
|
|
10
11
|
log = logging.getLogger('prefigure')
|
|
11
12
|
|
|
13
|
+
# EPUB restricts the characters that can appear in an id to
|
|
14
|
+
# a-z|A-Z|0-9|_|-
|
|
15
|
+
# This is an issue here since <repeat> elements can create id's
|
|
16
|
+
# This regular expression checks characters to see if they are allowed
|
|
17
|
+
epub_check = re.compile(r'[A-Za-z0-9_-]')
|
|
18
|
+
|
|
19
|
+
# We also define substitutions for the most common disallowed characters
|
|
20
|
+
epub_dict = {'(': 'p',
|
|
21
|
+
')': 'q',
|
|
22
|
+
'[': 'p',
|
|
23
|
+
']': 'q',
|
|
24
|
+
'{': 'p',
|
|
25
|
+
'}': 'q',
|
|
26
|
+
',': 'c',
|
|
27
|
+
'.': 'd',
|
|
28
|
+
'=': '_',
|
|
29
|
+
r'#': 'h'}
|
|
30
|
+
|
|
31
|
+
|
|
12
32
|
# Allows a block of XML to repeat with a changing parameter
|
|
13
33
|
|
|
14
34
|
def repeat(element, diagram, parent, outline_status):
|
|
@@ -48,11 +68,12 @@ def repeat(element, diagram, parent, outline_status):
|
|
|
48
68
|
else:
|
|
49
69
|
k_str = str(k)
|
|
50
70
|
|
|
51
|
-
|
|
71
|
+
k_str_clean = epub_clean(k_str)
|
|
72
|
+
# This is a change since we use the syntax "var_str" for the id suffix
|
|
52
73
|
if count:
|
|
53
|
-
suffix_str = var + "
|
|
74
|
+
suffix_str = var + "_" + k_str_clean
|
|
54
75
|
else:
|
|
55
|
-
suffix_str = var + "
|
|
76
|
+
suffix_str = var + "_" + str(num)
|
|
56
77
|
|
|
57
78
|
definition = ET.SubElement(element, 'definition')
|
|
58
79
|
definition.text = var + '=' + k_str
|
|
@@ -78,3 +99,13 @@ def repeat(element, diagram, parent, outline_status):
|
|
|
78
99
|
|
|
79
100
|
if annotation is not None:
|
|
80
101
|
diagram.pop_from_annotation_branch()
|
|
102
|
+
|
|
103
|
+
def epub_clean(s):
|
|
104
|
+
epub_clean = [bool(epub_check.fullmatch(ch)) for ch in s]
|
|
105
|
+
chars = []
|
|
106
|
+
for index, ch in enumerate(s):
|
|
107
|
+
if epub_clean[index]:
|
|
108
|
+
chars.append(ch)
|
|
109
|
+
continue
|
|
110
|
+
chars.append(epub_dict.get(ch, '_'))
|
|
111
|
+
return "".join(chars)
|
|
@@ -48,7 +48,7 @@ DefinitionElements =
|
|
|
48
48
|
Derivative?,
|
|
49
49
|
DE-Solution?,
|
|
50
50
|
Define-Shapes?,
|
|
51
|
-
Read
|
|
51
|
+
Read?
|
|
52
52
|
|
|
53
53
|
Definition = element definition {
|
|
54
54
|
text,
|
|
@@ -177,7 +177,9 @@ LabelAttributes =
|
|
|
177
177
|
attribute rotate {text}?,
|
|
178
178
|
attribute clear-background {"yes"|"no"}?,
|
|
179
179
|
attribute background-margin {text}?,
|
|
180
|
-
attribute color {text}
|
|
180
|
+
attribute color {text}?,
|
|
181
|
+
attribute font {text}?,
|
|
182
|
+
attribute font-size {text}?
|
|
181
183
|
|
|
182
184
|
Math = element m {attribute color {text}? & text}
|
|
183
185
|
Bold = element b {attribute color {text}? & text & Italic*}
|