Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
S
Scripts
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Specification Tools
Scripts
Commits
62a4c4a4
Commit
62a4c4a4
authored
4 months ago
by
Andreas Kraft
Browse files
Options
Downloads
Patches
Plain Diff
Adapted debug output. Corrections in the main script. Renamed wrong filename
parent
06c05a87
No related branches found
No related tags found
1 merge request
!1
Restructuring and cleaning scripts for Mkdocs
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
.gitignore
+1
-0
1 addition, 0 deletions
.gitignore
toMkdocs/gridTableTools.py
+123
-106
123 additions, 106 deletions
toMkdocs/gridTableTools.py
toMkdocs/markdownTools.py
+37
-21
37 additions, 21 deletions
toMkdocs/markdownTools.py
toMkdocs/toMkdocs.py
+47
-12
47 additions, 12 deletions
toMkdocs/toMkdocs.py
with
208 additions
and
139 deletions
.gitignore
+
1
−
0
View file @
62a4c4a4
...
...
@@ -3,3 +3,4 @@
*/ts-*
*/.python-version
.python-version
toMkdocs/__pycache__
This diff is collapsed.
Click to expand it.
toMkdocs/gridTableTools.py
+
123
−
106
View file @
62a4c4a4
...
...
@@ -6,10 +6,25 @@
#
"""
Tools for working with grid tables in markdown files.
"""
from
typing
import
Optional
from
typing
import
Optional
,
Callable
from
regexMatches
import
*
_alignLeft
=
'
align=
"
left
"'
_alignRight
=
'
align=
"
right
"'
_alignCenter
=
'
align=
"
center
"'
printInfo
=
print
printDebug
=
print
printError
=
print
def
setLoggers
(
info
:
Callable
=
print
,
debug
:
Callable
=
print
,
error
:
Callable
=
print
)
->
None
:
global
printInfo
,
printDebug
,
printError
printInfo
=
info
printDebug
=
debug
printError
=
error
class
GridCell
:
"""
Represents a grid table cell.
"""
...
...
@@ -27,8 +42,18 @@ class GridCell:
self
.
auxiliarIndex
:
int
=
0
def
calculateAndSetAlignment
(
self
,
headerDelimiterPositions
:
list
[
int
],
delimiterPositions
:
list
[
int
],
defaultAlignments
:
list
[
str
],
hasHeader
:
bool
)
->
None
:
def
calculateAndSetAlignment
(
self
,
headerDelimiterPositions
:
list
[
int
],
delimiterPositions
:
list
[
int
],
defaultAlignments
:
list
[
str
],
hasHeader
:
bool
)
->
None
:
"""
Set the alignment of the cell based on the position of the delimiter.
Args:
headerDelimiterPositions: The positions of the header delimiters.
delimiterPositions: The positions of the delimiters.
defaultAlignments: The default alignments.
hasHeader: True if the table has a header, False otherwise.
"""
if
self
.
position
is
None
:
raise
ValueError
(
'
Cell position must be set before calculating alignment.
'
)
...
...
@@ -46,17 +71,17 @@ class GridCell:
else
:
raise
ValueError
(
'
Invalid table formatting
'
)
else
:
body
_d
elimiter
_i
ndex
=
0
while
body
_d
elimiter
_i
ndex
in
range
(
len
(
defaultAlignments
)
)
and
self
.
position
>
delimiterPositions
[
body
_d
elimiter
_i
ndex
]:
body
_d
elimiter
_i
ndex
+=
1
if
body
_d
elimiter
_i
ndex
in
range
(
len
(
defaultAlignments
)
)
:
if
self
.
position
<
delimiterPositions
[
body
_d
elimiter
_i
ndex
]:
self
.
alignment
=
defaultAlignments
[
body
_d
elimiter
_i
ndex
]
elif
self
.
position
==
delimiterPositions
[
body
_d
elimiter
_i
ndex
]:
self
.
alignment
=
defaultAlignments
[
body
_d
elimiter
_i
ndex
]
body
_d
elimiter
_i
ndex
+=
1
body
D
elimiter
I
ndex
=
0
while
body
D
elimiter
I
ndex
<
len
(
defaultAlignments
)
and
self
.
position
>
delimiterPositions
[
body
D
elimiter
I
ndex
]:
body
D
elimiter
I
ndex
+=
1
if
body
D
elimiter
I
ndex
<
len
(
defaultAlignments
):
if
self
.
position
<
delimiterPositions
[
body
D
elimiter
I
ndex
]:
self
.
alignment
=
defaultAlignments
[
body
D
elimiter
I
ndex
]
elif
self
.
position
==
delimiterPositions
[
body
D
elimiter
I
ndex
]:
self
.
alignment
=
defaultAlignments
[
body
D
elimiter
I
ndex
]
body
D
elimiter
I
ndex
+=
1
else
:
raise
ValueError
(
"
Invalid table formatting
"
)
raise
ValueError
(
'
Invalid table formatting
'
)
def
__str__
(
self
):
...
...
@@ -91,6 +116,7 @@ class GridRow():
def
__repr__
(
self
):
return
self
.
__str__
()
class
GridRowsTracker
():
"""
Represents the document object.
"""
def
__init__
(
self
,
size
:
int
)
->
None
:
...
...
@@ -155,9 +181,10 @@ def parseGridTableWithSpans(gridTable:str) -> tuple[GridTableRowList, GridTableR
cell
.
content
=
_c
+
nextListElementMark
# Add list element end mark to know when the list element ends
elif
cell
.
listFlag
and
len
(
_c
)
>
0
:
# any other content when handling list is concatenated to the last list element
_c
=
re
.
sub
(
r
'
\\\s*$
'
,
'
\n
'
,
_c
)
cell
.
content
+=
_c
+
nextListElementMark
#add the list element end mark
elif
not
_c
:
# separation between list and other paragraph
cell
.
content
+=
'
\n
'
if
not
cell
[
'
content
'
].
endswith
(
'
\n
'
)
else
""
cell
.
content
=
_c
+
nextListElementMark
#add the list element end mark
elif
not
_c
:
# empty line. separation between list and other paragraph
# cell.content = '\n' if not cell.content.endswith('\n') else ""
cell
.
content
=
'
\n
'
# cell content is always empty / None here.
else
:
cell
.
content
=
re
.
sub
(
r
'
\\\s*$
'
,
'
\n
'
,
_c
)
else
:
# Cell has content
...
...
@@ -173,8 +200,8 @@ def parseGridTableWithSpans(gridTable:str) -> tuple[GridTableRowList, GridTableR
_c
=
re
.
sub
(
r
'
\\\s*$
'
,
'
\n
'
,
_c
)
cell
.
content
+=
"
"
+
_c
+
nextListElementMark
#add list element end mark
elif
len
(
_c
)
==
0
:
# separation between list and other paragraph
if
cell
.
list
_f
lag
:
cell
.
list
_f
lag
=
False
if
cell
.
list
F
lag
:
cell
.
list
F
lag
=
False
cell
.
content
+=
'
\n\n
'
#end list by \n
#content = re.sub(r'\\\s*$', "\n", content.strip())
cell
.
content
+=
'
\n
'
if
not
cell
.
content
.
endswith
(
'
\n
'
)
else
''
...
...
@@ -205,7 +232,8 @@ def parseGridTableWithSpans(gridTable:str) -> tuple[GridTableRowList, GridTableR
row
[
columnIndex
].
colspanAdjusted
=
True
# Mark cell as adjusted
def
check_delimiter_alignment
(
line
:
str
,
delimiterPositions
:
list
[
int
],
delimiters
:
str
=
"
|+
"
)
->
bool
:
def
checkDelimiterAlignment
(
line
:
str
,
delimiterPositions
:
list
[
int
],
delimiters
:
str
=
"
|+
"
)
->
bool
:
"""
Check if delimiters in a row align with expected positions.
...
...
@@ -220,33 +248,29 @@ def parseGridTableWithSpans(gridTable:str) -> tuple[GridTableRowList, GridTableR
if
not
line
or
not
delimiterPositions
:
return
False
print
(
f
"
\n
Checking line:
'
{
line
}
'
"
)
print
(
f
"
Expected delimiter positions:
{
delimiterPositions
}
"
)
print
Debug
(
f
'
\n
Checking line:
"
{
line
}
"
'
)
print
Debug
(
f
'
Expected delimiter positions:
{
delimiterPositions
}
'
)
# For full separator lines (only +)
if
'
+
'
in
line
and
'
|
'
not
in
line
:
currentPositions
=
[
i
for
i
,
char
in
enumerate
(
line
)
if
(
char
==
'
+
'
and
i
!=
0
)]
print
(
f
"
Full separator line - Found + at positions:
{
currentPositions
}
"
)
return
all
(
delimiterPositions
[
-
1
]
in
currentPositions
and
line
.
startswith
(
"
+
"
)
and
pos
in
delimiterPositions
for
pos
in
currentPositions
)
currentPositions
=
[
i
for
i
,
char
in
enumerate
(
line
)
if
(
char
==
'
+
'
and
i
>
0
)]
printDebug
(
f
'
Full separator line - Found + at positions:
{
currentPositions
}
'
)
return
all
(
delimiterPositions
[
-
1
]
in
currentPositions
and
line
.
startswith
(
'
+
'
)
and
pos
in
delimiterPositions
for
pos
in
currentPositions
)
# For data lines (only |)
if
'
|
'
in
line
and
'
+
'
not
in
line
:
currentPositions
=
[
i
for
i
,
char
in
enumerate
(
line
)
if
(
char
==
'
|
'
and
i
!=
0
)]
print
(
f
"
Data line - Found | at positions:
{
currentPositions
}
"
)
return
all
(
delimiterPositions
[
-
1
]
in
currentPositions
and
line
.
startswith
(
"
|
"
)
and
pos
in
delimiterPositions
for
pos
in
currentPositions
)
currentPositions
=
[
i
for
i
,
char
in
enumerate
(
line
)
if
(
char
==
'
|
'
and
i
>
0
)]
printDebug
(
f
'
Data line - Found | at positions:
{
currentPositions
}
'
)
return
all
(
delimiterPositions
[
-
1
]
in
currentPositions
and
line
.
startswith
(
"
|
"
)
and
pos
in
delimiterPositions
for
pos
in
currentPositions
)
# For partial separators (mix of + and |)
currentPositions
=
[
i
for
i
,
char
in
enumerate
(
line
)
if
(
char
in
delimiters
and
i
!=
0
)]
print
(
f
"
Partial separator - Found delimiters at positions:
{
currentPositions
}
"
)
print
(
f
"
Characters at those positions:
{
[
line
[
pos
]
for
pos
in
currentPositions
]
}
"
)
return
all
(
delimiterPositions
[
-
1
]
in
currentPositions
and
(
line
.
startswith
(
"
+
"
)
or
line
.
startswith
(
"
|
"
))
and
pos
in
delimiterPositions
for
pos
in
currentPositions
)
currentPositions
=
[
i
for
i
,
char
in
enumerate
(
line
)
if
(
char
in
delimiters
and
i
>
0
)]
printDebug
(
f
'
Partial separator - Found delimiters at positions:
{
currentPositions
}
'
)
printDebug
(
f
'
Characters at those positions:
{
[
line
[
pos
]
for
pos
in
currentPositions
]
}
'
)
return
all
(
delimiterPositions
[
-
1
]
in
currentPositions
and
line
.
startswith
((
'
+
'
,
'
|
'
))
and
pos
in
delimiterPositions
for
pos
in
currentPositions
)
separatorIndices
=
[
i
for
i
,
line
in
enumerate
(
lines
)
if
isSeparator
(
line
)]
...
...
@@ -254,8 +278,8 @@ def parseGridTableWithSpans(gridTable:str) -> tuple[GridTableRowList, GridTableR
raise
ValueError
(
'
No valid separators found in the provided grid table.
'
)
# Calculate max number of columns
delimiterPositions
:
list
[
int
]
=
[]
numberOfColumns
=
0
delimiterPositions
=
[]
numberOfColumns
:
int
=
0
for
separatorIndex
in
separatorIndices
:
if
(
_cnt
:
=
lines
[
separatorIndex
].
count
(
'
+
'
)
-
1
)
>
numberOfColumns
:
...
...
@@ -263,10 +287,10 @@ def parseGridTableWithSpans(gridTable:str) -> tuple[GridTableRowList, GridTableR
delimiterPositions
=
[]
for
rowIndex
in
range
(
numberOfColumns
):
delimiterPositionsStart
=
delimiterPositions
[
rowIndex
-
1
]
if
rowIndex
!=
0
else
0
delPositions
=
[
lines
[
separatorIndex
].
find
(
delimiter
,
delimiterPositionsStart
+
1
)
for
delimiter
in
'
+
'
if
delimiter
in
lines
[
separatorIndex
][
delimiterPositionsStart
+
1
:]]
delPositions
=
[
lines
[
separatorIndex
].
find
(
delimiter
,
delimiterPositionsStart
+
1
)
for
delimiter
in
'
+
'
if
delimiter
in
lines
[
separatorIndex
][
delimiterPositionsStart
+
1
:]]
delimiterPositions
.
append
(
min
(
delPositions
)
if
delPositions
else
-
1
)
# Determine delimter positions and alignments
headerRows
:
GridTableRowList
=
[]
dataRows
:
GridTableRowList
=
[]
...
...
@@ -278,15 +302,22 @@ def parseGridTableWithSpans(gridTable:str) -> tuple[GridTableRowList, GridTableR
parts
=
re
.
split
(
r
'
\+
'
,
lines
[
index
].
strip
(
'
+
'
))
#Calculate default alignments and positions of delimiters
for
partIndex
in
range
(
len
(
parts
)):
if
parts
[
partIndex
].
startswith
(
'
:
'
)
and
not
parts
[
partIndex
].
endswith
(
'
:
'
):
# Left alignment
defaultAlignments
.
append
(
'
align=
"
left
"'
)
elif
not
parts
[
partIndex
].
startswith
(
'
:
'
)
and
parts
[
partIndex
].
endswith
(
'
:
'
):
# Right alignment
defaultAlignments
.
append
(
'
align=
"
right
"'
)
# Left alignment
if
parts
[
partIndex
].
startswith
(
'
:
'
)
and
not
parts
[
partIndex
].
endswith
(
'
:
'
):
defaultAlignments
.
append
(
_alignLeft
)
# Right alignment
elif
not
parts
[
partIndex
].
startswith
(
'
:
'
)
and
parts
[
partIndex
].
endswith
(
'
:
'
):
defaultAlignments
.
append
(
_alignRight
)
# Center alignment
else
:
defaultAlignments
.
append
(
'
align=
"
center
"'
)
# Center alignment
defaultAlignments
.
append
(
_alignCenter
)
# Delimiter position
delimiterPositionsStart
=
delimiterPositions
[
partIndex
-
1
]
if
partIndex
!=
0
else
0
delPositions
=
[
lines
[
index
].
find
(
delimiter
,
delimiterPositionsStart
+
1
)
for
delimiter
in
'
+
'
if
delimiter
in
lines
[
index
][
delimiterPositionsStart
+
1
:]]
delPositions
=
[
lines
[
index
].
find
(
delimiter
,
delimiterPositionsStart
+
1
)
for
delimiter
in
'
+
'
if
delimiter
in
lines
[
index
][
delimiterPositionsStart
+
1
:]]
headerDelimiterPositions
.
append
(
min
(
delPositions
)
if
delPositions
else
-
1
)
if
not
hasHeader
:
...
...
@@ -296,11 +327,13 @@ def parseGridTableWithSpans(gridTable:str) -> tuple[GridTableRowList, GridTableR
# Calculate default alignments and positions of delimiters
for
part_index
in
range
(
len
(
parts
)):
if
parts
[
part_index
].
startswith
(
'
:
'
)
and
not
parts
[
part_index
].
endswith
(
'
:
'
):
default_alignments
.
append
(
'
align=
"
left
"'
)
default_alignments
.
append
(
_alignLeft
)
elif
not
parts
[
part_index
].
startswith
(
'
:
'
)
and
parts
[
part_index
].
endswith
(
'
:
'
):
default_alignments
.
append
(
'
align=
"
right
"'
)
default_alignments
.
append
(
_alignRight
)
else
:
default_alignments
.
append
(
'
align
=
"
c
enter
"'
)
default_alignments
.
append
(
_
align
C
enter
)
for
rowNumber
in
range
(
len
(
separatorIndices
)
-
1
):
rows
:
list
[
GridRow
]
=
[]
...
...
@@ -314,8 +347,8 @@ def parseGridTableWithSpans(gridTable:str) -> tuple[GridTableRowList, GridTableR
if
isSeparator
(
line
)
and
not
inDataRow
:
inDataRow
=
True
# Add delimiter alignment check for separator lines
if
not
check
_d
elimiter
_a
lignment
(
line
,
delimiterPositions
):
raise
ValueError
(
f
"
Misaligned delimiters in separator row:
{
line
}
"
)
if
not
check
D
elimiter
A
lignment
(
line
,
delimiterPositions
):
raise
ValueError
(
f
'
Misaligned delimiters in separator row:
{
line
}
'
)
parts
=
re
.
split
(
r
'
\s*\+\s*
'
,
line
.
strip
(
'
+
'
))
delimiterIndex
=
0
...
...
@@ -343,17 +376,17 @@ def parseGridTableWithSpans(gridTable:str) -> tuple[GridTableRowList, GridTableR
# Regular data row or partial separator
if
matchGridTableBodySeparator
.
match
(
line
):
# Partial separator
# Add delimiter alignment check for partial separators
if
not
check
_d
elimiter
_a
lignment
(
line
,
delimiterPositions
):
raise
ValueError
(
f
"
Misaligned delimiters in partial separator:
{
line
}
"
)
if
not
check
D
elimiter
A
lignment
(
line
,
delimiterPositions
):
raise
ValueError
(
f
'
Misaligned delimiters in partial separator:
{
line
}
'
)
cellsContent
=
re
.
split
(
r
"
[\|\+]
"
,
line
.
strip
(
'
|
'
).
strip
(
'
+
'
))
# (?<!\\)[\|\+]
cellsContent
=
re
.
split
(
r
'
[\|\+]
'
,
line
.
strip
(
'
|
'
).
strip
(
'
+
'
))
# (?<!\\)[\|\+]
#Add another row, set delimiters for each cell
rows
.
append
(
GridRow
(
numberOfColumns
))
auxDelimiterIndex
=
0
auxiliarCellIndex
=
0
for
columnIndex
,
content
in
enumerate
(
cellsContent
):
if
auxiliarCellIndex
in
range
(
numberOfColumns
)
:
if
auxiliarCellIndex
<
numberOfColumns
:
auxDelimiterIndex
+=
len
(
content
)
+
1
cell
=
rows
[
-
1
][
auxiliarCellIndex
]
cell
.
position
=
auxDelimiterIndex
# Position of cell delimiter +
...
...
@@ -398,15 +431,14 @@ def parseGridTableWithSpans(gridTable:str) -> tuple[GridTableRowList, GridTableR
continue
else
:
raise
ValueError
(
"
More cells than columns found
"
)
raise
ValueError
(
'
More cells than columns found
'
)
else
:
# Data row
cellsContent
=
line
.
strip
()
cellsContent
=
re
.
split
(
r
"
\|
"
,
line
.
strip
(
'
|
'
))
cellsContent
=
re
.
split
(
r
'
\|
'
,
line
.
strip
(
'
|
'
))
# Add delimiter alignment check
if
not
check
_d
elimiter
_a
lignment
(
line
,
delimiterPositions
):
raise
ValueError
(
f
"
Misaligned delimiters in row:
{
line
}
"
)
if
not
check
D
elimiter
A
lignment
(
line
,
delimiterPositions
):
raise
ValueError
(
f
'
Misaligned delimiters in row:
{
line
}
'
)
columnCellIndex
=
0
if
len
(
cellsContent
)
<
numberOfColumns
:
# Colspan: Positions of | with respect to + need to be determined
...
...
@@ -426,9 +458,9 @@ def parseGridTableWithSpans(gridTable:str) -> tuple[GridTableRowList, GridTableR
rowIndex
=
rowsTracker
[
columnIndex
]
handleCellContent
(
rows
[
rowIndex
][
columnIndex
],
content
)
else
:
raise
ValueError
(
"
More cells than columns found
"
)
raise
ValueError
(
'
More cells than columns found
'
)
else
:
raise
ValueError
(
"
No separator line found for row starting
"
)
raise
ValueError
(
'
No separator line found for row starting
'
)
if
hasHeader
and
start
>=
headerSeparatorIndex
:
# table_row and auxiliar_row are part of data_rows
for
row
in
rows
:
...
...
@@ -451,7 +483,7 @@ def parseGridTableWithSpans(gridTable:str) -> tuple[GridTableRowList, GridTableR
for
cell
in
gridRow
:
if
cell
.
content
is
not
None
:
# Replacing "<" by <
cell
.
content
=
cell
.
content
.
replace
(
"
<
"
,
"
<
"
)
cell
.
content
=
cell
.
content
.
replace
(
'
<
'
,
'
<
'
)
# Bold replacements
# Regex to detect markdown bold formatting in cell content
...
...
@@ -463,7 +495,6 @@ def parseGridTableWithSpans(gridTable:str) -> tuple[GridTableRowList, GridTableR
if
cell
.
content
is
not
None
:
cell
.
content
=
matchItalic
.
sub
(
r
'
<i>\g<text></i>
'
,
cell
.
content
)
# Correct newlines characters
for
headerRow
in
headerRows
:
for
cell
in
headerRow
:
...
...
@@ -525,25 +556,11 @@ def generateHtmlTableWithSpans(gridTable:str) -> str:
Returns:
The HTML table in string format.
"""
debug_output
=
[]
def
debug_print
(
msg
):
debug_output
.
append
(
str
(
msg
))
# Convert message to string
try
:
# Redirect print statements to our debug collector
global
print
original_print
=
print
print
=
debug_print
gridHeader
,
gridBody
=
parseGridTableWithSpans
(
gridTable
)
# Restore original print
print
=
original_print
except
Exception
as
e
:
debug_print
(
"
Grid table could not be generated
"
)
debug_text
=
"
<br>
"
.
join
(
debug_output
)
# Now all items are strings
return
f
'
HTML TABLE COULD NOT BE GENERATED FROM MARKDOWN GRID TABLE.<br><pre>
{
debug_text
}
</pre>
'
printDebug
(
'
Grid table could not be generated
'
)
return
f
'
HTML TABLE COULD NOT BE GENERATED FROM MARKDOWN GRID TABLE
'
# Generate table HTML...
html
=
'
<table>
\n
'
...
...
@@ -564,47 +581,47 @@ def generateHtmlTableWithSpans(gridTable:str) -> str:
continue
else
:
# Prepare content, in case there's a list
if
cell
.
content
is
not
None
and
(
matches
:
=
re
.
findall
(
r
"
\s*([-*+]|\s*\d+\.)\s+((?:(?!@).)+)@
"
,
cell
.
content
)):
# Update cell in new row
list
=
"
<ul>
"
if
cell
.
content
is
not
None
and
(
matches
:
=
re
.
findall
(
r
'
\s*([-*+]|\s*\d+\.)\s+((?:(?!@).)+)@
'
,
cell
.
content
)):
# Update cell in new row
list
=
'
<ul>
'
# Build list the matches
for
match
in
matches
:
list
+=
"
<li>
"
+
match
[
1
]
+
"
</li>
"
list
+=
"
</ul>
"
cell
.
content
=
re
.
sub
(
r
"
(\s*([-*+]|\s*\d+\.)\s+(?:(?!@).)+@)+
"
,
list
,
cell
.
content
)
list
+=
'
<li>
'
+
match
[
1
]
+
'
</li>
'
list
+=
'
</ul>
'
cell
.
content
=
re
.
sub
(
r
'
(\s*([-*+]|\s*\d+\.)\s+(?:(?!@).)+@)+
'
,
list
,
cell
.
content
)
# Enforce left alignment if cell contains a list
cell
.
alignment
=
"
align
=
\"
left
\"
"
cell
.
alignment
=
_
align
Left
rowspan
=
f
"
rowspan=
\
"
{
cell
.
rowspan
}
\"
"
if
cell
.
rowspan
>
1
else
""
colspan
=
f
"
colspan=
\
"
{
cell
.
colspan
}
\"
"
if
cell
.
colspan
>
1
else
""
html
+=
f
"
<th
{
rowspan
}{
colspan
}
{
cell
.
alignment
}
>
{
cell
.
content
}
</th>
\n
"
html
+=
"
</tr>
\n
"
html
+=
"
</thead>
\n
"
rowspan
=
f
'
rowspan=
"
{
cell
.
rowspan
}
"
'
if
cell
.
rowspan
>
1
else
''
colspan
=
f
'
colspan=
"
{
cell
.
colspan
}
"
'
if
cell
.
colspan
>
1
else
''
html
+=
f
'
<th
{
rowspan
}{
colspan
}
{
cell
.
alignment
}
>
{
cell
.
content
}
</th>
\n
'
html
+=
'
</tr>
\n
'
html
+=
'
</thead>
\n
'
html
+=
"
<tbody>
\n
"
html
+=
'
<tbody>
\n
'
for
row
in
gridBody
:
html
+=
"
<tr>
\n
"
html
+=
'
<tr>
\n
'
for
cell
in
row
:
if
cell
.
rowspan
==
0
or
cell
.
colspan
==
0
:
continue
else
:
#Prepare content, in case there's a list
if
cell
.
content
is
not
None
and
(
matches
:
=
re
.
findall
(
r
"
\s*([-*+]|\s*\d+\.)\s+((?:(?!@).)+)@
"
,
cell
.
content
)):
# Update cell in new row
list
=
"
<ul>
"
if
cell
.
content
is
not
None
and
(
matches
:
=
re
.
findall
(
r
'
\s*([-*+]|\s*\d+\.)\s+((?:(?!@).)+)@
'
,
cell
.
content
)):
# Update cell in new row
list
=
'
<ul>
'
# Build list the matches
for
match
in
matches
:
list
+=
"
<li>
"
+
match
[
1
]
+
"
</li>
"
list
+=
"
</ul>
"
cell
.
content
=
re
.
sub
(
r
"
(\s*([-*+]|\s*\d+\.)\s+(?:(?!@).)+@)+
"
,
list
,
cell
.
content
)
list
+=
f
'
<li>
{
match
[
1
]
}
</li>
'
list
+=
'
</ul>
'
cell
.
content
=
re
.
sub
(
r
'
(\s*([-*+]|\s*\d+\.)\s+(?:(?!@).)+@)+
'
,
list
,
cell
.
content
)
# Enforce left alignment if cell contains a list
cell
.
alignment
=
"
align
=
\"
left
\"
"
cell
.
alignment
=
_
align
Left
rowspan
=
f
"
rowspan=
\
"
{
cell
.
rowspan
}
\"
"
if
cell
.
rowspan
>
1
else
""
colspan
=
f
"
colspan=
\
"
{
cell
.
colspan
}
\"
"
if
cell
.
colspan
>
1
else
""
html
+=
f
"
<td
{
rowspan
}{
colspan
}
{
cell
.
alignment
}
>
{
cell
.
content
}
</td>
\n
"
html
+=
"
</tr>
\n
"
rowspan
=
f
'
rowspan=
"
{
cell
.
rowspan
}
"
'
if
cell
.
rowspan
>
1
else
''
colspan
=
f
'
colspan=
"
{
cell
.
colspan
}
"
'
if
cell
.
colspan
>
1
else
''
html
+=
f
'
<td
{
rowspan
}{
colspan
}
{
cell
.
alignment
}
>
{
cell
.
content
}
</td>
\n
'
html
+=
'
</tr>
\n
'
html
+=
"
</tbody>
\n
"
html
+=
"
</table>
"
html
+=
'
</tbody>
\n
'
html
+=
'
</table>
'
return
html
This diff is collapsed.
Click to expand it.
toMkdocs/ma
k
rdownTools.py
→
toMkdocs/mar
k
downTools.py
+
37
−
21
View file @
62a4c4a4
...
...
@@ -9,12 +9,13 @@
"""
Various tools for markdown processing
"""
from
__future__
import
annotations
from
typing
import
Callable
from
dataclasses
import
dataclass
import
base64
,
hashlib
from
enum
import
Enum
,
auto
from
gridTableTools
import
generateHtmlTableWithSpans
from
gridTableTools
import
generateHtmlTableWithSpans
,
setLoggers
as
setGridTableLoggers
from
regexMatches
import
*
# TODO use a verbosity level instead
...
...
@@ -23,12 +24,18 @@ veryVerbose = False
printInfo
=
print
printDebug
=
print
printError
=
print
def
set
ScreenPrint
ers
(
info
:
c
allable
=
print
,
debug
:
c
allable
=
print
)
->
None
:
global
printInfo
,
printDebug
def
set
Logg
ers
(
info
:
C
allable
=
print
,
debug
:
C
allable
=
print
,
error
:
Callable
=
print
)
->
None
:
global
printInfo
,
printDebug
,
printError
printInfo
=
info
printDebug
=
debug
printError
=
error
# Set the loggers for the grid table tools
setGridTableLoggers
(
info
,
debug
,
error
)
def
_shortHash
(
value
:
str
,
length
:
int
)
->
str
:
...
...
@@ -365,6 +372,28 @@ def analyseMarkdown(filename:str) -> Document:
The document object.
"""
gridTable
:
str
=
''
def
processGridTable
()
->
None
:
"""
Process a grid table and convert it to an html table.
This function adds the html table to the output clauses and
clears the gridTable variable.
"""
nonlocal
gridTable
htmltable
:
str
=
''
try
:
htmltable
=
generateHtmlTableWithSpans
(
gridTable
)
printDebug
(
htmltable
)
except
Exception
as
e
:
printError
(
f
"
Error:
{
e
}
"
)
# TODO move this outside of the analyseMarkdown function !!!
for
row
in
htmltable
:
outClauses
[
-
1
].
append
(
Line
(
row
,
LineType
.
TABLEROW
))
gridTable
=
''
printInfo
(
f
'
Analyzing
"
{
filename
}
"'
)
# Read the file.
...
...
@@ -381,10 +410,7 @@ def analyseMarkdown(filename:str) -> Document:
inTable
=
False
tableHasSeparator
=
False
inGridTable
=
False
gridTableHasSeparator
=
False
gridTable
=
""
for
line
in
inLines
:
# Detect and handle codefences
# For the moment we support only codefences that start and end
# with 3 backticks. This is the most common way to define codefences.
...
...
@@ -439,18 +465,7 @@ def analyseMarkdown(filename:str) -> Document:
continue
else
:
inGridTable
=
False
# Mark the previous line as the last row in the table
#outClauses[-1].lines[-1].lineType = LineType.TABLELASTROW
# print(gridTable)
try
:
htmltable
=
generateHtmlTableWithSpans
(
gridTable
)
print
(
htmltable
)
except
Exception
as
e
:
print
(
f
"
Error:
{
e
}
"
)
# TODO move this outside of the analyseMarkdown function !!!
for
row
in
htmltable
:
outClauses
[
-
1
].
append
(
Line
(
row
,
LineType
.
TABLEROW
))
gridTable
=
""
processGridTable
()
# continue with other matches
# Detect notes
...
...
@@ -486,9 +501,10 @@ def analyseMarkdown(filename:str) -> Document:
# Just add the line to the current clause as text
outClauses
[
-
1
].
append
(
Line
(
line
,
_lineType
))
return
Document
(
outClauses
,
footnot
es
)
# Process still unfinished cas
es
if
gridTable
:
processGridTable
()
return
Document
(
outClauses
,
footnotes
)
This diff is collapsed.
Click to expand it.
toMkdocs/toMkdocs.py
+
47
−
12
View file @
62a4c4a4
...
...
@@ -12,13 +12,49 @@ from __future__ import annotations
import
argparse
,
os
,
shutil
from
rich
import
print
from
ma
k
rdownTools
import
Line
,
Document
,
analyseMarkdown
,
set
ScreenPrint
ers
from
mar
k
downTools
import
Line
,
Document
,
analyseMarkdown
,
set
Logg
ers
from
regexMatches
import
match2spaceListIndention
verbose
=
False
veryVerbose
=
False
def
printDebug
(
text
:
str
)
->
None
:
"""
Print a debug message.
Args:
text: The text of the debug message.
"""
if
verbose
:
print
(
f
'
[dim]
{
text
}
'
)
def
printInfo
(
text
:
str
)
->
None
:
"""
Print an information message.
Args:
text: The text of the information message.
"""
print
(
f
'
[green]
{
text
}
'
)
def
printWarning
(
text
:
str
)
->
None
:
"""
Print a warning message.
Args:
text: The text of the warning message.
"""
print
(
f
'
[yellow]
{
text
}
'
)
def
printError
(
text
:
str
)
->
None
:
"""
Print an error message.
Args:
text: The text of the error message.
"""
print
(
f
'
[red]
{
text
}
'
)
def
prepareForMkdocs
(
document
:
Document
,
includeHangingParagraphs
:
bool
=
False
)
->
None
:
"""
Prepare the clauses for MkDocs. This includes removing the heading
from the clauses and marking the clauses that are only for navigation.
...
...
@@ -47,7 +83,7 @@ def prepareForMkdocs(document:Document, includeHangingParagraphs:bool = False) -
# Check if there is a sub-clause in the next clause
if
i
+
1
<
len
(
document
.
clauses
)
and
document
.
clauses
[
i
+
1
].
level
>
clause
.
level
:
# This is a hanging paragraph. Remove the text from the current clause.
print
(
f
'
[yellow]
Hanging paragraph in clause
"
{
clause
.
title
}
"
{
"
(removed)
"
if
not
includeHangingParagraphs
else
"
(kept)
"
}
'
)
print
Warning
(
f
'
Hanging paragraph in clause
"
{
clause
.
title
}
"
{
"
(removed)
"
if
not
includeHangingParagraphs
else
"
(kept)
"
}
'
)
if
not
includeHangingParagraphs
:
document
.
clauses
[
i
].
lines
=
[]
else
:
...
...
@@ -72,15 +108,14 @@ def writeClausesMkDocs(document:Document, filename:str, navTitle:str, addNavTitl
addNavTitle: Add the title as an extra navigation level to the navigation file.
"""
print
(
f
'
[green]
Writing clauses to files
'
)
print
Info
(
f
'
Writing clauses to files
'
)
# create directory first
os
.
makedirs
(
f
'
{
os
.
path
.
dirname
(
filename
)
}
/
{
navTitle
}
'
,
exist_ok
=
True
)
# Write the files
for
i
,
f
in
enumerate
(
document
.
clauses
):
# write to single files, even empty ones
if
verbose
:
print
(
f
'
[dim]Writing
"
{
f
.
clauseNumber
}
.md
"
-
"
{
f
.
title
}
"'
)
printDebug
(
f
'
Writing
"
{
f
.
clauseNumber
}
.md
"
-
"
{
f
.
title
}
"'
)
with
open
(
f
'
{
os
.
path
.
dirname
(
filename
)
}
/
{
navTitle
}
/
{
f
.
clauseNumber
}
.md
'
,
'
w
'
)
as
file
:
# Add one empty line before the clause. This is done to avoid
# a bug in MkDocs that does not display the first line of a clause
...
...
@@ -90,11 +125,10 @@ def writeClausesMkDocs(document:Document, filename:str, navTitle:str, addNavTitl
# write nav.yml file
print
(
f
'
[green]
Writing
"
_nav.yml
"'
)
print
Info
(
f
'
Writing
"
_nav.yml
"'
)
indentation
=
'
'
if
addNavTitle
else
''
# TODO make number of spaces configurable
with
open
(
f
'
{
os
.
path
.
dirname
(
filename
)
}
/_nav.yml
'
,
'
w
'
)
as
file
:
if
veryVerbose
:
print
(
f
'
[dim]Writing navigation file
'
)
printDebug
(
f
'
Writing navigation file
'
)
if
addNavTitle
:
file
.
write
(
f
'
{
indentation
}
-
{
navTitle
}
:
\n
'
)
for
i
,
f
in
enumerate
(
document
.
clauses
):
...
...
@@ -130,10 +164,10 @@ def copyMediaFiles(filename:str, navTitle:str, mediaDirectory:str = 'media') ->
targetDirectory
=
f
'
{
os
.
path
.
dirname
(
filename
)
}
/
{
navTitle
}
/
{
mediaDirectory
}
'
if
os
.
path
.
exists
(
sourceDirectory
):
print
(
f
'
[green]
Copying media files from
"
{
sourceDirectory
}
"
to
"
{
targetDirectory
}
"'
)
print
Info
(
f
'
Copying media files from
"
{
sourceDirectory
}
"
to
"
{
targetDirectory
}
"'
)
shutil
.
copytree
(
sourceDirectory
,
targetDirectory
,
dirs_exist_ok
=
True
)
else
:
print
(
f
'
[red]
Media directory
"
{
sourceDirectory
}
"
does not exist
'
)
print
Error
(
f
'
Media directory
"
{
sourceDirectory
}
"
does not exist
'
)
def
processDocument
(
args
:
argparse
.
Namespace
)
->
None
:
...
...
@@ -177,8 +211,9 @@ def main() -> None:
parser
.
add_argument
(
'
document
'
,
type
=
str
,
help
=
'
a oneM2M markdown specification document to process
'
)
args
=
parser
.
parse_args
()
setScreenPrinters
(
info
=
lambda
text
:
print
(
f
'
[green]
{
text
}
'
),
debug
=
lambda
text
:
print
(
f
'
[dim]
{
text
}
'
))
setLoggers
(
info
=
printInfo
,
debug
=
printDebug
,
error
=
printError
)
processDocument
(
args
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment