From: Will Budic Date: Fri, 14 Jul 2023 05:18:19 +0000 (+1000) Subject: upd. to latest CNF. X-Git-Url: https://lifelog.hopto.org/gitweb/?a=commitdiff_plain;h=6720bb35ca0f0d98f8e7a239190908bf9bacf588;p=LifeLog.git upd. to latest CNF. --- diff --git a/htdocs/cgi-bin/system/modules/MarkdownPlugin.pm b/htdocs/cgi-bin/system/modules/MarkdownPlugin.pm index 254a6bd..ddd53fb 100644 --- a/htdocs/cgi-bin/system/modules/MarkdownPlugin.pm +++ b/htdocs/cgi-bin/system/modules/MarkdownPlugin.pm @@ -1,3 +1,15 @@ +### +# Ambitious Markup Script converter from MD scripts to HTML. +# MD scripts can thus be placed in PerlCNF properties for further processing by this plugin. +# Processing of these is placed in the data parsers data. +# Programed by : Will Budic +# Notice - This source file is copied and usually placed in a local directory, outside of its project. +# So it could not be the actual or current version, can vary or has been modiefied for what ever purpose in another project. +# Please leave source of origin in this file for future references. +# Source of Origin : https://github.com/wbudic/PerlCNF.git +# Documentation : Specifications_For_CNF_ReadMe.md +# Open Source Code License -> https://choosealicense.com/licenses/isc/ +# package MarkdownPlugin; use strict; @@ -11,6 +23,17 @@ use Date::Manip; our $TAB = ' 'x4; our $PARSER; +### +# Constances for CSS CNF tag parts. See end of this file for package internal provided defaults CSS. +### +use constant { + C_B => "class='B'", #CNF TAG angle brackets identifiers. + C_PN => "class='pn'", #Prop. name. + C_PI => "class='pi'", #Prop. instruction. + C_PV => "class='pv'", #Prop. value. + C_PA => "class='pa'" #Anon, similar to prop. name. +}; + sub new ($class, $fields={Language=>'English',DateFormat=>'US'}){ @@ -61,7 +84,13 @@ try{ MarkdownPluginException->throw(error=>$e ,show_trace=>1); }} - +### +# Helper package to resolve the output of HTML lists in order of apperance in some MD script. +# It is a very complex part of the parsing algorithm routine. +# This mentioned, here look as the last place to correct any possible translation errors. +# @CREATED 20230709 +# @TODO possible to be extended ot account for CSS specified bullet types then the HTML default. +### package HTMLListItem { sub new{ my $class = shift; @@ -82,22 +111,31 @@ package HTMLListItem { sub toString($self){ my $t = $self->{type}; my $isRootItem = $self -> {spc} == 0 ? 1 : 0; - my $hasItems = $self->hasItems() ? 1 : 0; - my $ret; - if($hasItems&&!$isRootItem){ - $ret = "
  • ".$self -> {item}."<$t>\n" + my $hasItems = $self->hasItems(); + my $hasParent = exists($self->{parent}); + my $ret = ""; + if ($hasItems) { + if($isRootItem){ + $ret = "<$t>\n" + } + if($self->{item}){ + $ret = "
  • ".$self -> {item}."\n<$t>\n" + } }else{ - $ret = "
  • ".$self -> {item}."
  • \n" + return "
  • ".$self -> {item}."
  • \n" } foreach my $item(@{$self->{list}}){ if($item->hasItems()){ - $ret .= $item->toString()."\n" + $ret .= $item->toString(); }else{ - $ret .= '
  • '.$item->{item}."
  • \n" + my $it = $item->{type}; + $it = 'li' if $it eq 'ol' || $it eq 'ul'; + $ret .= "<$it>".$item->{item}."\n"; } } - if($hasItems){ - $ret .= "\n"; + if($hasItems){ + $ret .= "\n"; + $ret .= "\n" if !$isRootItem; } return $ret } @@ -124,8 +162,8 @@ sub setCodeTag($tag, $class){ sub parse ($self, $script){ try{ - my ($buffer, $para, $ol, $lnc); - my @list; my $ltype=0; my $nix=0; my $nplen=0; my $list_item; + my ($buff, $para, $ol, $lnc); + my $list_end; my $ltype=0; my $nix=0; my $nplen=0; my $list_item; my $list_root; my @titels;my $code = 0; my ($tag, $class); my $pml_val = 0; my ($bqte, $bqte_nested,$bqte_tag); $script =~ s/^\s*|\s*$//; foreach my $ln(split(/\n/,$script)){ @@ -134,7 +172,7 @@ try{ $tag = $1; $ln = $2; my @code_tag = @{ setCodeTag($tag, "") }; - $buffer .= qq(<$code_tag[1] class='$code_tag[0]'>$ln\n); + $buff .= qq(<$code_tag[1] class='$code_tag[0]'>$ln\n); next }elsif($ln =~ /^\s*```(\w*)/){ my $bfCode; @@ -144,65 +182,67 @@ try{ $tag = $code_tag[1] if !$tag; } if($code){ - if($para){ + if($para){ $bfCode .= "$para\n" } - $bfCode .= "
    "; undef $para; + $bfCode .= ""; undef $para; $code = 0; undef $tag; - if($list_item){ - $bfCode = $list_item -> {item} . $bfCode; - $list_item -> {item} = "$bfCode\n"; + if($list_item){ + $list_item -> {item} = $list_item -> {item} . $bfCode.'
    '; + $list_item = $list_item -> parent(); next; } }else{ $bfCode .= "<$tag class='$class'>"; if($class eq 'perl'){ - $bfCode .= qq(

    $class

    ); + $bfCode .= qq(

    Perl

    ); $code = 2; }else{ if($class eq 'cnf' or $class eq 'html'){ - $bfCode .= '

    Perl '.uc $class.'

    ' + $bfCode .= '

    '.uc($class).'

    ' } $code = 1 } } - if($list_item){ - $list_item -> {item} = $list_item -> {item}.'

    '.$bfCode; - + if($list_item){ + my $new = HTMLListItem->new('dt', "
    $bfCode", $list_item ->{spc}); + $list_item -> add($new); + $list_item = $new; + $list_end=0; }else{ - $buffer .= "$bfCode\n"; + $buff .= "$bfCode\n"; } }elsif(!$code && $ln =~ /^\s*(#+)\s*(.*)/){ my $h = 'h'.length($1); my $title = $2; $titels[@titels] = {$lnc,$title}; - $buffer .= qq(<$h>$title\n" + $buff .= qq(<$h>$title\n" } elsif(!$code && ($ln =~ /^(\s*)(\d+)\.\s(.*)/ || $ln =~ /^(\s*)([-+*])\s(.*)/)){ my $spc = length($1); my $val = $3 ? ${style($3)} : ""; - my $new = HTMLListItem->new((/[-+*]/?'ul':'ol'), $val, $spc); - - if(!$list_item){ - $list_item = $new; - $list[@list] = $list_item; - $nplen = $spc; - - }elsif($spc>$nplen){ + my $new = HTMLListItem->new(($2=~/[-+*]/?'ul':'ol'), $val, $spc); + if(!$list_root){ + $list_end = 0; + $list_root = HTMLListItem->new($new->{type}); + $list_root -> add($new); + $list_item = $new + }elsif($spc>$nplen){ $list_item -> add($new); $list_item = $new; $nplen = $spc; - - }else{ - while($list_item->{spc}>=$spc && $list_item -> parent()){ + $list_end = 0; + }else{ + my $isEq = $list_item->{spc} == $spc; + while($list_item->{spc} >= $spc && $list_item -> parent()){ $list_item = $list_item -> parent(); + last if $isEq } - if ( !$list_item ){$list_item = $new}else{ - $list_item -> add($new); - $list_item = $new; - } - } + $list_item = $list_root if !$list_item; + $list_item -> add($new); + $list_item = $new; + } }elsif(!$code && $ln =~ /(^|\\G)[ ]{0,3}(>+) ?/){ my $nested = length($2); $ln =~ s/^\s*\>+//; @@ -238,9 +278,9 @@ try{ } elsif(!$code && $ln =~ /^\s*\*\*\*/){ if($para){ - $para .= qq(
    \n) + $para .= qq(
    \n) }else{ - $buffer .= qq(
    \n) + $buff .= qq(
    \n) } } elsif($ln =~ /^\s*(.*)/ && length($1)>0){ @@ -250,8 +290,13 @@ try{ $v =~ s//>/g; $para .= "$v\n"; - }elsif($code == 2){ - $para .= code2HTML($v)."
    \n"; + }elsif($code == 2){ + if($ln =~/^\s*\<+.*>+$/){ + $para .= inlineCNF($v)."
    \n" + + }else{ + $para .= code2HTML($v)."
    \n" + } }else{ $v = inlineCNF($v); if(length($v) > length($ln)){ @@ -268,14 +313,13 @@ try{ my $t = $1; my $i = $2; $t =~ s/$t$i
    ); + $para .= "$t$i
    "; $pml_val = 1; - next; - + next; }elsif($3){ my $t = $3; $t =~ s/>/>/g; - $para .= "$t
    \n"; + $para .= "$t
    \n"; $pml_val = 0; next; }elsif($4&&$5&&6){ @@ -283,11 +327,10 @@ try{ my $v = $5; my $i = $6; $t =~ s/$t$v - <$i>
    ); + $para .= "$t$v". + "<$i
    "; $pml_val = 1; next; - } $v =~ m/ ^(<<) ([@%]<) ([\$@%]?\w+) ([<>]) @@ -306,38 +349,34 @@ try{ $t =~ s//>/g; $pml_val = 1; - $para .= qq($t$v<$i$c
    ); + $para .= "$t
    $v<$i$c
    "; }elsif($5&&$6){ my $t = $5; my $i = $6; $t =~ s/$t$i
    ); - - }elsif($1 && $2 && $3){ - + $para .= "$t$i
    "; + }elsif($1 && $2 && $3){ $pml_val = 1; - $para .= qq(<<$2<\/span>$3><\/span>
    ); - + $para .= "<<$2<\/span>$3>
    "; }elsif($8){ my $t = $8; $t =~ s/>/>/g; $pml_val = 0; - $para .= "$t
    \n"; + $para .= "$t
    \n"; } else{ if($pml_val){ $v =~ m/(.*)([=:])(.*)/gs; if($1&&$2&&$3){ - $para .= "$1 $2 $3
    \n"; + $para .= "$1$2$3
    \n"; }else{ - $para .= " $v
    \n"; + $para .= " $v
    \n"; } }else{ $para .= "$v
    \n"; } } - } - + } }else{ if($bqte){ while($bqte_nested-->0){$bqte .="\n"} @@ -346,167 +385,129 @@ try{ } $para .= ${style($1)}."\n" } - }else{ - - if(@list){ - $buffer .= "<".$list[0]->{type}.">\n"; #This is the root list type, it can only be one per item entry. - foreach (@list){ - $buffer .= $_->toString()."\n"; - } - $buffer .= "{type}.">\n"; - undef @list; undef $list_item; + }else{ + if($list_root && ++$list_end>1){ + $buff .= $list_root -> toString(); + undef $list_root; } elsif($para){ if($code){ - $buffer .= $para; + $buff .= $para; }else{ - $buffer .= qq(

    $para


    \n); + $buff .= qq(

    $para


    \n); } $para="" } } } - if($bqte){ - while($bqte_nested-->0){$bqte .="\n\n"} - $buffer .= $bqte; - } - - if(@list){ - $buffer .= "<".$list[0]->{type}.">\n"; #This is the root list type, it can only be one per item entry. - foreach my$item(@list){ - $buffer .= $item->toString()."\n"; - } - $buffer .= "{type}.">\n"; + while($bqte_nested-->0){$bqte .="\n\n"} + $buff .= $bqte; + } + if($list_root){ + $buff .= $list_root-> toString(); } - $buffer .= qq(

    $para

    \n) if $para; + $buff .= qq(

    $para

    \n) if $para; -return [\$buffer,\@titels] +return [\$buff,\@titels] }catch($e){ MarkdownPluginException->throw(error=>$e ,show_trace=>1); }} -sub code2HTML($v){ - $v =~ s/([,;=\(\)\{\}\[\]]|->)/$1<\/span>/g; - $v =~ s/(['"].*['"])/$1<\/span>/g; - $v =~ s/(my|our|local|use|lib|require|new|while|for|foreach|while|if|else|elsif)/$1<\/span>/g; - $v =~ s/(\$\w+)/$1<\/span>/g; +sub code2HTML($val){ + my $v=$val; + my @strs = ($v =~ m/(['"].*?['"])/g); + foreach(0..$#strs){ + my $r = $strs[$_]; + my $w = "\f$_\f"; + $v =~ s/$r/$w/ge; + } + + $v =~ s/([,;=\-\+]+)/$1<\/span>/gx; + $v =~ s/(my|our|local|use|lib|require|new|while|for|foreach|while|if|else|elsif|eval)/$1<\/span>/g; + $v =~ s/(\$\w+)/$1<\/span>/g; + $v =~ s/([\(\)\{\}\[\]] | ->)/$1<\/span>/gx; + foreach(0..$#strs){ + my $w = $strs[$_]; + $w =~ s/(^['"])(.*)(['"]$)/$1<\/span>$2<\/span>$3<\/span>/g; + my $r = "\f$_\f"; + $v =~ s/$r/$w/ge; + } + return $v } sub inlineCNF($v){ - # $v =~ m/ ^(<<) ([@%]<) ([\$@%]?\w+) ([<>]) - # |^(<{2,3}) - # ([^>]+) - # ( (<|>\w*>) | [<|>] (\w*) | (>{2,3})\s*)$ - # /gmx; - + $v =~ m/ (<{2,3})(.*?)(>{2,3}) (.*) /gmx; + my $oo = $1; + my $body = $2; + my $cc = $3; + my $restIfAny = $4; + return $v if !$1 || !$2 || !$3; + + $oo =~ s//>/g; + + $body =~ m/ ([@%]<) ([\$@%]?\w+) ([<>]) | + ([^<>]+) ([><])? (.*) + /gmx; + + if($4&&$5&&$6){ + my ($o,$var,$val, $prop); + $var = $4; $o=$5; $val=$6; + if($PARSER->isReservedWord($var)){ + $var = "$var" + }else{ + $var =~ s/(\w+)(\$+)/$1<\/span>$2<\/span>/g; + $var = "$var" if !$2; + } + my $r = "<"; + $o =~ s/^>"; + $o =~ s/^>/$r/ge; + $val =~ s//>/g; - $v =~ m/ ^(<<) ([@%]<) ([\$@%]?\w+) ([<>]) - |^(<{2,3}) - ([^>]+) - ( - (<|>\w*>?) | [<|>] (\w*) - ) - |(>{2,3})$ - /gmx; + $prop = "$var$o$val"; - if($5&&$6&&$7){ - my ($o,$oo,$i,$isVar,$sep,$var,$prop,$c,$cc); - $oo = $5; $var = $6; $cc = $7; - - if($cc=~/^([<|>])([\w ]*)(>+)/){ - $o = $1; - $i = $2; - $c = $3; - if($i && $i ne $c){ - $o =~ s//>/g; - my $iv = $i; - if($var=~/^(\w+)([<|>])(\w+)/){ - $var = $1; - $sep = $2; - $i = $3; - $sep =~ s//>/g; - $prop = qq($var$sep$i>$iv); - $cc =~ s/$iv//; - }elsif($PARSER->isReservedWord($i)){ - $prop = qq($var$o$i$c); - }else{ - $prop = qq($var$o$i); - $cc =~ s/$i//; - } - }elsif($var=~/^(\w+)([<|>])(\w+)/){ - $var = $1; - $sep = $2; - $i = $3; - $sep =~ s//>/g; - $prop = qq($var$sep$i); - }else{ - $cc .='>' if length($oo) != length($cc) - } - } - $oo =~ s//>/g; - - if(!$prop){ - $v = $var; - $v =~ m/^(\w+\$*)\s*([<|>])*([^>]+)*/; - $var = $1; - $isVar = $2; - $i = $3 if $3; - $prop = $v; - if($isVar){ - $isVar =~ s//>/g; - if($i){ - $v =~ s/^\w+\s*\s*(<|>)*([^>]*)*/$var<\/span>$isVar<\/span>$i<\/span>/; - }else{ - $v =~ s/^\w+\s*\s*(<|>)*/$var$isVar<\/span><\/span>/; - } - $prop = $v + $v = "$oo$prop$cc"; + } + elsif($4){ + my $t = $4; + if(!$6){ + $t =~ /(\w+)\s+(.*)/; + my $i = $1; + if($PARSER->isReservedWord($i)){ + $i = "$i" }else{ - if($PARSER->isReservedWord($var)){ - $prop = propValCNF($i); - $v =~ s/\s$i$/$prop/; - $v =~ s/^\w+/$var<\/span>/; - $prop = $v; - }else{ - $prop = propValCNF($i); - $v =~ s/\s$i$/$prop/; - $v =~ s/^\w+/$var<\/span>/; - $prop = $v; - } - + $i = "$i" } + my $prop = propValCNF($2); + $v = "$oo$i$prop$cc" + }else{ + my $i = $6; + my $c = $7; $c = $8 if !$c; + $t =~ s//>/g if $c; + $v = "$t$i$c"; } - - $v = qq($oo$prop$cc); - } - elsif($5&&$6){ - my $t = $5; - my $i = $6; - my $c = $7; $c = $8 if !$c; - $t =~ s//>/g if $c; - $v = qq($t$i$c); } elsif($1 && $2 && $3){ my $ins = $2; my $prop = propValCNF($3); - $v = qq(<<$ins<\/span>$prop><\/span>); + $v = "$oo$ins<\/span>$prop$cc" } - return $v + return $v.$restIfAny } + + sub propValCNF($v){ $v =~ m/(.*)([=:])(.*)/gs; if($1&&$2&&$3){ - $v = " $1$2$3"; + $v = " $1$2$3"; }else{ - $v = " $v"; + $v = " $v"; } return $v; } @@ -515,16 +516,11 @@ sub style ($script){ MarkdownPluginException->throw(error=>"Invalid argument passed as script!",show_trace=>1) if !$script; #Links $script =~ s/<(http[:\/\w.]*)>/$1<\/a>/g; - - my @result = map { - s/\*\*(.*)\*\*/\$1<\/em\>/; - s/\*(.*)\*/\$1<\/strong\>/; - s/__(.*)__/\$1<\/del\>/; - s/~~(.*)~~/\$1<\/strike\>/; - $_ - } split(/\s/,$script); - my $ret = join(' ',@result); - + $script =~ s/(\*\*([^\*]*)\*\*)/\$2<\/em\>/gs; + $script =~ s/(\*([^\*]*)\*)/\$2<\/strong\>/gs; + $script =~ s/__(.*)__/\$1<\/del\>/gs; + $script =~ s/~~(.*)~~/\$1<\/strike\>/gs; + my $ret = $script; #Inline code $ret =~ m/```(.*)```/g; if($1){ @@ -540,8 +536,8 @@ sub style ($script){ } ### -# Style sheet used for HTML conversion. -# Link with <**> in a TREE instructed property. +# Style sheet used for HTML conversion. NOTICE - Style sheets overide sequentionaly in order of apperance. +# Link with: <**> in a TREE instructed property. ### use constant CSS => q/ @@ -552,38 +548,59 @@ div .cnf { color:#05b361; background: aliceblue; } - .B { - color: #c60000; - padding: 2px; - } - - .Q { - color: #b7ae21; - font-weight: bold; - } - - .pn { - color: #6800ff; - } - - .pv { - color: #883ac8; - } - - .pi { - color: #18a7c8;; - font-weight: bold; - } +.B { + color: rgb(247, 55, 55); + padding: 2px; +} +.Q { + color: #b217ea; + font-weight: bold; +} +.pa { + color: rgb(52, 52, 130); + font-weight: bold; +} +.pn { + color: rgb(62, 173, 34); +} +.ps { + color: rgb(128, 0, 0); +} +.pv { + color: rgb(136, 58, 200); +} +.pi { + color: rgb(81, 160, 177); + ; + font-weight: bold; +} - .opr { - color: yellow; - } +.kw { + color: maroon; + padding: 2px; +} +.bra {color:rgb(247, 55, 55);} +.var { + color: blue; +} +.opr { + color: darkgreen; +} +.val { + color: gray; +} +.str { + color: orange; + font-style:italic; + font-weight: bold; +} +.inst { + color: green; + font-weight: bold; +} - .str { - color: red; - font-weight: bold; - } /; + 1; \ No newline at end of file