aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Smedegaard <dr@jones.dk>2024-04-01 03:22:12 +0200
committerJonas Smedegaard <dr@jones.dk>2024-04-01 03:22:12 +0200
commit0fd0eaab3b8bfc154b83a3507c3caa9d9ab556c6 (patch)
treed96bea9deadaf86f49d2bf31a30983d042c77aeb
parent29cee1399c977def72f1c8e1e13d83a841b75c89 (diff)
use PlantUML for Gantt diagrams
-rw-r--r--_report.yml2
-rw-r--r--_themes/doubleslash/README.md3
-rw-r--r--_themes/doubleslash/general.puml73
-rw-r--r--_themes/doubleslash/pgantt.puml70
-rwxr-xr-xbin/hedgedoc2quarto200
5 files changed, 345 insertions, 3 deletions
diff --git a/_report.yml b/_report.yml
index 0117bfe..44be2ba 100644
--- a/_report.yml
+++ b/_report.yml
@@ -10,6 +10,8 @@ format:
# links-as-notes: true
colorlinks: false
pdf-engine: lualatex
+# permit preprocessing PlantUML SVG files with inkscape
+ pdf-engine-opt: --shell-escape
documentclass: scrreprt
classoption:
- DIV=calc
diff --git a/_themes/doubleslash/README.md b/_themes/doubleslash/README.md
new file mode 100644
index 0000000..80d3431
--- /dev/null
+++ b/_themes/doubleslash/README.md
@@ -0,0 +1,3 @@
+# PlantUML Theme
+
+Origin: <https://github.com/doubleSlashde/umltheme>
diff --git a/_themes/doubleslash/general.puml b/_themes/doubleslash/general.puml
new file mode 100644
index 0000000..b8941ce
--- /dev/null
+++ b/_themes/doubleslash/general.puml
@@ -0,0 +1,73 @@
+''Define colors in doubleSlash corporate identity
+!define DS_BLUE #00A5E1
+!define DS_LIGHTBLUE #D7E9F4
+!define DS_ORANGE #FF9F00
+!define DS_LIGHTGREY #C6C6C6
+!define DS_GREY #7A7A7A
+!define DS_DARKGREY #515151
+
+!define SUPERLIGHTGREY #F8F8F8
+!define ALICEBLUE #F0F8FF
+!define STEELBLUE25 #374656
+!define STEELBLUE40 #8A9DB3
+!define BLACK50 #7F7F7F
+!define BLACK25 #404040
+!define LIGHTGREEN #D5E8D4
+
+!define TIPBGCOLOR #FFF6E7
+!define TIPBORDERCOLOR #FFD999
+
+!define FONTNAME "Arial"
+
+skinparam Shadowing false
+skinparam Padding 2
+skinparam Roundcorner 16
+skinparam BackgroundColor white
+skinparam DefaultFontName FONTNAME
+skinparam DefaultFontColor black
+skinparam DefaultTextAlignment center
+
+' Title
+'=================================================================
+skinparam TitleFontSize 28
+skinparam TitleFontName FONTNAME
+skinparam TitleFontColor black
+skinparam TitleFontStyle normal
+
+' Note
+'=================================================================
+'skinparam NoteBackgroundColor TIPBGCOLOR
+'skinparam NoteBorderColor TIPBORDERCOLOR
+'skinparam NoteBorderThickness 0.3
+'skinparam NoteShadowing true
+skinparam NoteBackgroundColor transparent
+skinparam NoteBorderColor transparent
+skinparam NoteBorderThickness 0.0
+skinparam NoteFontColor black
+skinparam NoteFontSize 11
+skinparam NoteTextAlignment left
+
+' Rectangle
+'=================================================================
+skinparam RectangleBackgroundColor SUPERLIGHTGREY
+skinparam RectangleBorderColor DS_DARKGREY
+skinparam RectangleBorderColor DS_GREY
+skinparam RectangleBorderThickness 0.5
+skinparam RectangleFontColor black
+skinparam RectangleFontSize 14
+
+
+' Package
+'=================================================================
+skinparam PackageFontColor black
+skinparam PackageBackgroundColor SUPERLIGHTGREY
+skinparam PackageBorderColor DS_DARKGREY
+skinparam PackageFontSize 14
+
+' Arrow
+'=================================================================
+skinparam ArrowColor DS_GREY
+skinparam ArrowThickness 1.5
+skinparam ArrowFontName FONTNAME
+skinparam ArrowFontColor black
+skinparam ArrowFontStyle normal
diff --git a/_themes/doubleslash/pgantt.puml b/_themes/doubleslash/pgantt.puml
new file mode 100644
index 0000000..15a3e1d
--- /dev/null
+++ b/_themes/doubleslash/pgantt.puml
@@ -0,0 +1,70 @@
+!include general.puml
+
+'saturday are closed
+'sunday are closed
+'language de
+
+skinparam Roundcorner 6
+
+saturday are colored in SUPERLIGHTGREY
+sunday are colored in SUPERLIGHTGREY
+printscale weekly zoom 4
+
+<style>
+ganttDiagram {
+ task {
+ FontName FONTNAME
+ FontSize 12
+ FontColor black
+ FontStyle normal
+ BackGroundColor DS_LIGHTBLUE
+ LineColor DS_LIGHTBLUE
+ Padding 3
+ }
+
+ timeline {
+ FontName FONTNAME
+ FontSize 12
+ BackgroundColor SUPERLIGHTGREY
+ }
+
+ milestone {
+ FontColor black
+ FontSize 12
+ FontStyle normal
+ BackGroundColor DS_BLUE
+ LineColor DS_BLUE
+ LineThickness 15.0
+ Margin 5
+ }
+
+ note {
+ FontColor black
+ FontSize 10
+ LineColor DS_LIGHTGREY
+ }
+
+ closed {
+ BackgroundColor #ffdfd4
+ FontColor black
+ }
+
+ Arrow {
+ LineColor DS_GREY
+ LineStyle solid
+ LineThickness 1.5
+ FontName FONTNAME
+ FontColor black
+ FontSize 12
+ }
+
+ Separator {
+ LineColor DS_GREY
+ LineThickness 1.0
+ FontSize 12
+ FontColor black
+ Margin 5
+ Padding 5
+ }
+}
+</style>
diff --git a/bin/hedgedoc2quarto b/bin/hedgedoc2quarto
index c0bde3b..c81ddd5 100755
--- a/bin/hedgedoc2quarto
+++ b/bin/hedgedoc2quarto
@@ -26,7 +26,8 @@ and adapts embedded diagram code.
Both HedgeDoc and Quarto uses Markdown,
but different flavors,
-and they handle different subsets of Mermaid diagrams.
+and whereas both handle (different subsets of) Mermaid diagrams,
+Quarto also (through plugins) handles PlantUML diagrams.
=cut
@@ -43,8 +44,12 @@ $content =~ s/^
(?'code'.*?\n)
\k'fence'
$/
- "{mermaid}\n\%\%| fig-width: 100\%\n"
- . &mmd2mmd( $+{type}, $+{code} )
+
+# FIXME: implement option to choose output diagram language
+# "{mermaid}\n\%\%| fig-width: 100\%\n"
+# . &mmd2mmd( $+{type}, $+{code} )
+ "{.plantuml}\n\%\%| fig-width: 100\%\n"
+ . &mmd2puml( $+{type}, $+{code} )
. $+{fence}
/gsmex;
@@ -65,6 +70,195 @@ sub mmd2mmd ( $type, $code )
return "$type\n$code";
}
+sub mmd2puml ( $type, $code )
+{
+ my @newcode;
+
+ # strip special comment marker '%%QUARTO%%'
+ $code =~ s/^\s*+\K%%QUARTO%%//gm;
+
+ open my $fh, '<', \$code or die $!;
+
+ while (<$fh>) {
+
+ /^\s*+$/
+ and push @newcode, ''
+ and next;
+
+ /^(\s*+)%%PLANTUML%%\K.*/
+ and push @newcode, "$1$&"
+ and next;
+
+ # convert comments markers
+ /^(\s*+)(?:[%]{2,}(?'comment'\s*+))?+\K.*/;
+ my $indent = defined( $+{comment} ) ? "$1'$2" : $1;
+ $_ = $&;
+
+ /^title\s/i
+ and push @newcode, "${indent}$_"
+ and next;
+
+ /^excludes\s+weekends\b/i
+ and push @newcode, "${indent}saturday are closed"
+ and push @newcode, "${indent}sunday are closed"
+ and next;
+ /^weekday\s+\K(?:mon|tues|wednes|thurs|fri|satur|sun)day\b/i
+ and push @newcode, "${indent}weeks start on $&"
+ and next;
+ /^(?:date|axis)Format\s/i
+ and push @newcode, "${indent}'UNSUPPORTED: $_"
+ and next;
+ /^todayMarker\s+(off|on)\b/i
+ and push @newcode, "${indent}'UNSUPPORTED' $_"
+ and next;
+ /^section\s+\K\S+(?:\s+\S+)*/i
+ and push @newcode, "${indent}-- $& --"
+ and next;
+
+ if (/^tickInterval\s+(?'tickAmount'\d+)(?'tickUnit'millisecond|second|minute|hour|day|week|month)\s*$/i
+ )
+ {
+ push @newcode, "${indent}projectscale daily"
+ and next
+ if $+{tickAmount} eq 1
+ and $+{tickUnit} eq 'day';
+ push @newcode, "${indent}projectscale weekly" and next
+ if $+{tickAmount} eq 1 and $+{tickUnit} eq 'week'
+ or $+{tickAmount} eq 7 and $+{tickUnit} eq 'day';
+ push @newcode, "${indent}projectscale monthly"
+ and next
+ if $+{tickAmount} eq 1
+ and $+{tickUnit} eq 'month';
+ push @newcode, "${indent}projectscale quarterly"
+ and next
+ if $+{tickAmount} eq 3
+ and $+{tickUnit} eq 'month';
+ push @newcode, "${indent}projectscale yearly"
+ and next
+ if $+{tickAmount} eq 12
+ and $+{tickUnit} eq 'month';
+ push @newcode, "${indent}'UNSUPPORTED' $&"
+ and next;
+ }
+
+ /^
+ (?'title'[^:\n]+)
+ \s*+:\s*+
+
+ # optional tags
+ (?:
+ (?:
+ (?'active'active)
+ |
+ (?'done'done)
+ |
+ (?'crit'crit)
+ |
+ (?'milestone'milestone)
+ )\s*+
+ ,\s*+
+ )?+
+
+ (?:
+ # optional tertiary item
+ (?:
+ (?'taskID'(?&id))\s*+
+ ,\s*+
+ (?=.*,) # several items must follow
+ )?+
+
+ # optional secondary item
+ (?:
+ (?'startDate'(?&date))
+ |
+ after
+ (?'afterTaskIDs'
+ (?:\s+(?&id))++
+ )
+ )\s*+
+ ,\s*+
+ )?+
+
+ # required main item
+ (?:
+ (?'endDate'(?&date))
+ |
+ until
+ (?'untilTaskIDs'
+ (?:\s+(?&id))++
+ )
+ |
+ (?'duration'\d+)
+ \s*+d
+ )\s*+
+ (?(DEFINE)
+ (?'id'[^\s\d,][^\s,]*+) # assume digit as lead caracter is illegal
+ (?'date'\d\d\d\d(?:-\d\d(?:-\d\d)?+)?+)
+ )
+ $/x
+ or defined( $+{comment} )
+ and push @newcode, "${indent}$_"
+ and next
+ or die "unhandled syntax on line $.: $_";
+
+ defined( $+{active} )
+ or defined( $+{done} )
+ or defined( $+{crit} )
+ and die "unhandled tag on line $.: $_";
+
+ my $task = "${indent}\[$+{title}]";
+ my $taskref = $task;
+
+ # optional 3rd item
+ if ( $+{taskID} ) {
+ $task .= " as [$+{taskID}]";
+ $taskref = "${indent}\[$+{taskID}]";
+ }
+
+ if ( defined( $+{afterTaskIDs} ) ) {
+ my @reqs = split ' ', $+{afterTaskIDs};
+
+ if ( $+{milestone} ) {
+ push @newcode, "$task happens at [$_]'s end" for @reqs;
+ }
+ elsif ( $+{endDate} ) {
+ push @newcode, "$task ends $+{endDate}";
+ push( @newcode, "$taskref starts at [$_]'s end" ) for @reqs;
+ }
+ elsif ( defined( $+{untilTaskIDs} ) ) {
+ my @reqsEnd = split ' ', $+{untilTaskIDs};
+ push @newcode, "$task ends at [$_]'s end" for @reqsEnd;
+ push( @newcode, "$taskref starts at [$_]'s end" ) for @reqs;
+ }
+ else {
+ push @newcode, "$task requires $+{duration} days";
+ push( @newcode, "$taskref starts at [$_]'s end" ) for @reqs;
+ }
+ }
+ else {
+ if ( $+{milestone} ) {
+ push @newcode, "$task happens $+{startDate}";
+ }
+ elsif ( $+{endDate} ) {
+ push @newcode,
+ "$task starts $+{startDate} and ends $+{ednDate}";
+ }
+ elsif ( defined( $+{untilTaskIDs} ) ) {
+ my @reqsEnd = split ' ', $+{untilTaskIDs};
+ push @newcode, "$task starts $+{startDate}";
+ push @newcode, "$task ends at [$_]'s end" for @reqsEnd;
+ }
+ else {
+ push @newcode,
+ "$task starts $+{startDate} and requires $+{duration} days";
+ }
+ }
+ }
+
+ $" = "\n";
+ return "\@start$type\n@newcode\n\@end$type\n";
+}
+
=encoding UTF-8
=head1 AUTHOR