11. Constants are usually scripted at the beginning of the file, or parsed first in a separate file.
12. The instruction processor can use them if signifier $ surrounds the constant name. Therefore, replacing it with the constants value if further found in the file.
- ```HTML
+ ```CNF
<<<CONST $APP_PATH=~/MyApplication>>>
<<app_path<$APP_PATH$/module/main>>>
```
26. Anon value is in best practice and in general synchronized, from script to a database configuration store. It is up to the implementation.
27. Anon value is global to the application and its value can be modified.
- ```HTML
+ ```CNF
<<USE_SWITCH<true>>>
<<DIALOG_TITLE_EN<MyApplication Title>>>
```
2. When querying for an anon value, replacement parameter array can be passed.
3. Numbering is from **\$\$\$1\$\$\$**..**$$$(n...)\$\$\$** to be part of its value. Strategically placed.
- ```HTML
+ ```CNF
<<GET_SUB_URL<https://www.$$$1$$$.acme.com/$$$2$$$>>>
```
28. Listing is an reappearing same name tag postfixed with an **\$\$**.
- ```HTML Example 1:
+ ```CNF Example 1:
<<INS$$>ls -la>
<<INS$$>uname -a>
```
29. Listing is usually a named list of instructions, items grouped and available as individual entries of the listing value.
- ```HTML Example 2:
+ ```CNF Example 2:
<<Animals$$>Cat>
<<Animals$$>Dog>
<<Animals$$>Eagle>
3. It is not recommended to use reserve anons as their value settings, that is; can be modified in scripts for their value.
4. Reserve anon if present is usually a placeholder, lookup setting, that in contrast if not found there, might rise exceptions from the application using CNF.
- ```HTML Example 2:
+ ```CNF Example 2:
Notice to Admin, following please don't modify in any way!
Start --> {
<<^RELEASE>2.3>>
### Property Value Tag
- ```HTML
+ ```CNF
<<{name}<{value}>>>
```
### Instruction Value Tag
- ```HTML
+ ```CNF
<<<{INSTRUCTION}
{value\n...valuen\n}>>>
```
- ```HTML
+ ```CNF
<<{name}<{INSTRUCTION}
{value\n...valuen\n}>>>
```
**Examples:**
-```HTML
+```CNF
<<$HELP<CONST
Sorry help is currently.
Not available.
1. TABLE
- ```HTML
+ ```CNF
<<MyAliasTable<TABLE
ID INT PRIMARY KEY NOT NULL,
ALIAS VCHAR(16) UNIQUE CONSTRAINT,
2. INDEX
- ```HTML
+ ```CNF
<<MyAliasTable<INDEX<idx_alias on MyAliasTable (ALIAS);>>>
```
3. SQL
1. SQL statements are actual full SQL placed in the tag body value.
- ```HTML
+ ```CNF
<<VW_ALIASES>SQL
CREATE VIEW VW_ALIASES AS SELECT ID,ALIAS ORDER BY ALIAS;
>>>
3. Migration is not run on newly created databases. These create the expected latest data structure.
4. SQL Statements a separated by ';' terminator. To be executed one by one.
- ```HTML
+ ```CNF
<<1.6<MIGRATE
ALTER TABLE LOG ADD STICKY BOOL DEFAULT 0;
>>
1. This behavior can be controlled by disabling something like an auto file storage update. i.e. during application upgrades. To prevent user set settings to reset to factory defaults.
2. The result would then be that database already stored data remains, and only new ones are added. This exercise is out of scope of this specification.
- ```HTML
+ ```CNF
<<MyAliasTable<DATA
01`admin`admin@inc.com`Super User~
02`chef`chef@inc.com`Bruno Allinoise~
3. File is to be sequentially buffer read and processed instead as a whole in one go.
4. The same principles apply in the file as to the DATA instruction CNF tag format, that is expected to be contained in it.
- ```HTML
+ ```CNF
<<MyItemsTbl<FILE data_my_app.cnf>
```
3. Requirements are for plugins to work to have the DO_ENABLED=>1 config attribute set.
1. Plugins currently also will require be last specified in the file, to have access to previous anons that are instructed.
- ```HTML
+ ```CNF
/**
* Plugin instructions are the last one setup and processed,
* by placing the actual result into the plugins tag name.
2. This is currently a TREE instruction only inbuilt option in PerlCNF, for the CNFNodes individuals scripts order of processing.
4. Tree Format Example:
- ```HTML
+ ```CNF
<<APP<My Nice Application by ACME Wolf PTY>>
<<doc<TREE>
3. It is recommended to comment out this feature, if never is to be used or found not safe to have such thing enabled.
4. This if named are assigned as anons, with the last processed value as the return. Making them evaluated and processed ever only once.
-```perl
+```CNF
<<<DO
print "Hello form CNF, you have ".(scalar %anons) ." anons so far.\n"
>>>
**~//perl_dev/WB_CNF/db/configuration.cnf** file contents:
-```HTML
+```CNF
# List command anon with the name of 'list'.
<<list<ls -lh dev|sort>>>
set_message(\&handle_errors);
}
-#debug ->
-use lib "/home/will/dev/LifeLog/htdocs/cgi-bin/system/modules";
+
use lib "system/modules";
require CNFParser;
require CNFNode;
$script_path =~ s/\w+.cgi$//;
-exit main();
+exit &HTMLPageBuilderFromCNF;
-sub main {
+sub HTMLPageBuilderFromCNF {
my $html = obtainDirListingHTML('docs');
- my $cnf = CNFParser -> new(
+ my $cnf = CNFParser -> new (
$script_path."index.cnf",{
DO_ENABLED => 1, HAS_EXTENSIONS=>1,
ANONS_ARE_PUBLIC => 1,
- PAGE_HEAD => "<h2>Index Page of Docs</h2>",
+ PAGE_HEAD => "<h2>Index Page of Docs Directory</h2>",
PAGE_CONTENT => $html,
PAGE_FOOT => "<!--Not Defined-->"
}
- );
+ );
my $ptr = $cnf->data();
$ptr = $ptr->{'PAGE'};
say $$ptr if $ptr;
}
sub obtainDirListingHTML {
- my ($dir, $ret) = (shift,"");
- $ret .="<b>$dir →</b><ul>\n";
- $ret .= listFiles($dir,$script_path,"");
- opendir (my $handle, $script_path.$dir) or die "Couldn't open directory, $!";
- while (my $node = readdir $handle) {
- my $file_full_path = "$script_path$dir/$node";
- if($node !~ /^\./ && -d $file_full_path){
- $ret .= obtainDirListingHTML($dir.'/'.$node);
+ my ($dir, $ret) = (shift,"");
+ my $html = listFiles($dir,$script_path,"");
+ if($html){
+ $ret .="<ul><b>$dir →</b>\n";
+ $ret .= $html;
+ opendir (my $handle, $script_path.$dir) or die "Couldn't open directory, $!";
+ while (my $node = readdir $handle) {
+ my $file_full_path = "$script_path$dir/$node";
+ if($node !~ /^\./ && -d $file_full_path){
+ $html = obtainDirListingHTML($dir.'/'.$node);
+ $ret .= $html if $html
+ }
}
+ closedir $handle;
+ $ret .= "</ul>";
}
- closedir $handle;
- $ret .= "</ul>";
return $ret;
}
+
sub listFiles ($){
my ($dir, $script_path, $ret) = @_;
my $path = $script_path.$dir;
my $name = $1;
if($file =~ /\.md$/){
my @title = getDocTitle($file);
- $ret .= qq(\t\t\t<li><a href="$dir/$title[0]">$title[1] - $name</a></li>\n);
+ $ret .= qq(\t\t\t<li><a href="$dir/$title[0]">$title[1]</a> ‐ $name</li>\n);
}else{
$ret .= qq(\t\t\t<li><a href="$dir/$name">$name</a></li>\n);
}
use Exception::Class ('MarkdownPluginException');
use feature qw(signatures);
use Date::Manip;
+##no critic ControlStructures::ProhibitMutatingListFunctions
our $TAB = ' 'x4;
+our $PARSER;
sub new ($class, $fields={Language=>'English',DateFormat=>'US'}){
sub convert ($self, $parser, $property) {
try{
my ($item, $script) = $parser->anon($property);
+ $PARSER = $parser;
die "Property not found [$property]!" if !$item;
my $ref = ref($item); my $escaped = 0;
MarkdownPluginException->throw(error=>$e ,show_trace=>1);
}}
+
+package HTMLListItem {
+ sub new{
+ my $class = shift;
+ my ($type,$item,$spc) = @_;
+ my @array = ();
+ return bless{type=>$type,item=>$item,spc=>$spc,list=>\@array},$class;
+ }
+ sub parent($self) {
+ return exists($self->{parent}) ? $self->{parent} : undef
+ }
+ sub add($self, $item){
+ push @{$self->{list}}, $item;
+ $item ->{parent} = $self;
+ }
+ sub hasItems($self){
+ return @{$self->{list}}>0
+ }
+ sub toString($self){
+ my $t = $self->{type};
+ my $isRootItem = $self -> {spc} == 0 ? 1 : 0;
+ my $hasItems = $self->hasItems() ? 1 : 0;
+ my $ret = "<li>".$self -> {item}."</li>\n";
+ if($hasItems){
+ $ret = "<li>".$self -> {item}."<$t>\n";
+ }
+ foreach my $item(@{$self->{list}}){
+ if($item->hasItems()){
+ $ret .= $item->toString()."\n"
+ }else{
+ $ret .= '<li>'.$item->{item}."</li>\n"
+ }
+ }
+ if($hasItems){
+ $ret .= "</$t></li>\n";
+ }
+ return $ret
+ }
+}
+
sub setCodeTag($tag, $class){
if($tag){
- $tag = $1;
- if($tag eq 'html' or $tag eq 'CNF' or $tag eq 'code' or $tag eq 'perl'){
+ $tag = lc $tag;
+ if($tag eq 'html' or $tag eq 'cnf' or $tag eq 'code' or $tag eq 'perl'){
$class = $tag;
$tag = 'div';
}else{
sub parse ($self, $script){
try{
my ($buffer, $para, $ol, $lnc);
- my @list; my $ltype=0; my $nix=0;my $nplen=0;
- my @titels;my $code = 0; my $tag; my $pml_val = 0; my ($bqte, $bqte_nested,$bqte_tag);
+ my @list; my $ltype=0; my $nix=0; my $nplen=0; my $list_item;
+ 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)){
$ln =~ s/\t/$TAB/gs;
if($ln =~ /^```(\w*)\s(.*)```$/g){
$tag = $1;
$ln = $2;
- my @code_tag = setCodeTag($tag, "");
+ my @code_tag = @{ setCodeTag($tag, "") };
$buffer .= qq(<$code_tag[1] class='$code_tag[0]'>$ln</$code_tag[1]>\n);
next
- }elsif($ln =~ /^```(\w*)/){
- my @code_tag = setCodeTag($tag, $1);
- my $class = $code_tag[0];
- $tag = $code_tag[1];
+ }elsif($ln =~ /^\s*```(\w*)/){
+ if(!$tag){
+ my @code_tag = @{ setCodeTag($1, $1) };
+ $class = $code_tag[0];
+ $tag = $code_tag[1] if !$tag;
+ }
if($code){
if($para){
$buffer .= "$para\n"
}
- $buffer .= "</$tag><br>"; $tag = $para = "";
- $code = 0;
+ $buffer .= "</$tag><br>"; undef $para;
+ $code = 0; undef $tag;
}else{
$buffer .= "<$tag class='$class'>";
if($class eq 'perl'){
$buffer .= qq(<h1><span>$class</span></h1>);
$code = 2;
}else{
- if($class eq 'CNF' or $class eq 'html'){
- $buffer .= qq(<h1><span>$class</span></h1>);
+ if($class eq 'cnf' or $class eq 'html'){
+ $buffer .= '<h1><span>'.uc $class.'</span></h1>'
}
$code = 1
}
$buffer .= qq(<$h>$title</$h><a name=").scalar(@titels)."\"></a>\n"
}
elsif(!$code && ($ln =~ /^(\s*)(\d+)\.\s(.*)/ || $ln =~ /^(\s*)([-+*])\s(.*)/)){
- my @arr;
+
my $spc = length($1);
my $val = $3 ? ${style($3)} : "";
- $ltype = $2 =~ /[-+*]/ ? 1:0;
- if($spc>$nplen){
- $nplen = $spc;
- $list[@list] = \@arr;
- $nix++;
- }elsif($spc<$nplen){
- $nix--;
+ my $new = HTMLListItem->new((/[-+*]/?'ul':'ol'), $val, $spc);
+
+ if(!$list_item){
+ $list_item = $new;
+ $list[@list] = $list_item;
+ $nplen = $spc;
+
+ }elsif($spc>$nplen){
+ $list_item -> add($new);
+ $list_item = $new;
+ $nplen = $spc;
+
+ }else{
+ while($list_item->{spc}>=$spc && $list_item -> parent()){
+ $list_item = $list_item -> parent();
+ }
+ if ( !$list_item ){$list_item = $new}else{
+ $list_item -> add($new);
+ $list_item = $new;
+ }
}
- if($list[$nix-1]){
- @arr = @{$list[$nix-1]};
- $arr[@arr] = $ltype .'|'.$val;
- $list[$nix-1] = \@arr;
- }else{
- $arr[@arr] = $ltype .'|'.$val;
- $list[@list] = \@arr;
- }
}elsif(!$code && $ln =~ /(^|\\G)[ ]{0,3}(>+) ?/){
my $nested = length($2);
$ln =~ s/^\s*\>+//;
}else{
$bqte_tag = "p";
}
-
if(!$bqte_nested){
$bqte_nested = $nested;
$bqte .="<blockquote><$bqte_tag>\n"
}
elsif(!$code && $ln =~ /^\s*\*\*\*/){
if($para){
- $para .= qq(<hr>\n)
+ $para .= qq(<hr>\n)
}else{
$buffer .= qq(<hr>\n)
}
$v =~ s/</</g;
$v =~ s/>/>/g;
$para .= "$v\n";
- }elsif($code == 2){
- $v =~ s/([,;=\(\)\{\}\[\]]|->)/<span class=opr>$1<\/span>/g;
- $v =~ s/(['"].*['"])/<span class='str'>$1<\/span>/g;
- $v =~ s/class=opr/class='opr'/g;
- $v =~ s/(my|our|local|use|lib|require|new|while|for|foreach|while|if|else|elsif)/<span class='bra'>$1<\/span>/g;
- $v =~ s/(\$\w+)/<span class='inst'>$1<\/span>/g;
- $para .= "$v<br>\n";
- }else{
+ }elsif($code == 2){
+ $para .= code2HTML($v)."<br>\n";
+ }else{
+
+
+ $v =~ m/ ^(<{2,3}) ([\$@%]*\w*)$
+ | ^(>{2,3})$
+ | (<<) ([\$@%]*\w*) <(\w+)>
+ /gx;
+
+ if($1&&$2){
+ my $t = $1;
+ my $i = $2;
+ $t =~ s/</</g;
+ $para .= qq(<span class='bra'>$t</span><span class='ins'>$i</span><br>);
+ $pml_val = 1;
+ next;
+
+ }elsif($3){
+ my $t = $3;
+ $t =~ s/>/>/g;
+ $para .= "<span class='bra'>$t</span><br>\n";
+ $pml_val = 0;
+ next;
+ }elsif($4&&$5&&6){
+ my $t = $4;
+ my $v = $5;
+ my $i = $6;
+ $t =~ s/</</g;
+ $para .= qq(<span class='bra'>$t</span><span class='var'>$v</span>
+ <span class='bra'><</span><span class='ins'>$i</span><span class='bra'>></span><br>);
+ $pml_val = 1;
+ next;
+
+ }
$v =~ m/ ^(<<) ([@%]<) ([\$@%]?\w+) ([<>])
|^(<{2,3})
- ([\$@%\w]+)
- (<[\w\ ]*>)*
- |(>{2,3})$
+ ([\$@%\w]+)\s*
+ <*([^>]+)
+ (>{2,3})$
+
/gx;# and my @captured = @{^CAPTURE};
-
- if($5&&$6&&$7){
+
+ if($5&&$6&&$7&&$8){
my $t = $5;
my $v = $6;
my $i = $7;
- $i =~ m/^<([\$@%\w]+?)>$/;
- $i = $1; $pml_val = 1;
- $para .= qq(<span class='bra'><<</span><span class='var'>$v</span><span class='bra'><</span><span class='inst'>$i</span><span class='bra'>></span><br>);
+ my $c = $8;
+ $t =~ s/</</g;
+ $c =~ s/>/>/g;
+ $pml_val = 1;
+ $para .= qq(<span class='bra'>$t</span><span class='var'>$v</span><span class='bra'><</span><span class='inst'>$i</span><span class='bra'>$c</span><br>);
}elsif($5&&$6){
- my $t = $5;
- my $i = $6;
- $t =~ s/</</g; $pml_val = 1;
- $para .= qq(<span class='bra'>$t</span><span class='inst'>$i</span><br>
- );
+ my $t = $5;
+ my $i = $6;
+ $t =~ s/</</g; $pml_val = 1;
+ $para .= qq(<span class='bra'>$t</span><span class='inst'>$i</span><br>);
}elsif($1 && $2 && $3){
$para .= ${style($1)}."\n"
}
}else{
+
if(@list){
- if($para){
- my @arr;
- if($list[$nix-1]){
- @arr = @{$list[$nix-1]};
- $arr[@arr] = '2|'.$para;
- $list[$nix-1] = \@arr;
- }else{
- $arr[@arr] = '2|'.$para;
- $list[@list] = \@arr;
- }
- $para=""
+ $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 .= createList(0,$ltype,\@list);
- undef @list; $nplen = 0
+ $buffer .= "</".$list[0]->{type}.">\n";
+ undef @list
}
elsif($para){
if($code){
while($bqte_nested-->0){$bqte .="\n</$bqte_tag></blockquote>\n"}
$buffer .= $bqte;
}
- $buffer .= createList(0,$ltype,\@list) if(@list);
+
+ 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 .= "</".$list[0]->{type}.">\n";
+ }
$buffer .= qq(<p>$para</p>\n) if $para;
return [\$buffer,\@titels]
MarkdownPluginException->throw(error=>$e ,show_trace=>1);
}}
-my @LIST_ITEM_TYPE = ('ol','ul','blockquote');
-
-sub createList ($nested,$type,@list){
- $nested++;
- my ($bf,$tabs) =("", " "x$nested);
- my $tag = $LIST_ITEM_TYPE[$type];
-
- foreach my $arr(@list){
- $bf .= qq($tabs<$tag>\n) if $nested>1;
- foreach my $li(@$arr){
- if(ref($li) eq 'ARRAY'){
- $bf =~ s/\s<\/($tag)>\s$//gs if $bf;
- my $r = $1;
- my @lst = \@$li;
- my $typ = get_list_type(@lst);
- $bf .= createList($nested,$typ,@lst);
- $bf .= qq($tabs</$tag>\n) if($r)
- }else{
- $li =~ s/^(\d)\|//;
- if($1 == 2){
- $bf .= "$tabs<blockquote>$li</blockquote>\n"
- }else{
- $bf .= "$tabs<li>$li</li>\n"
- }
- }
- }
- $bf .= qq($tabs</$tag>\n) if $nested>1;
- }
- return $bf
+sub code2HTML($v){
+ $v =~ s/([,;=\(\)\{\}\[\]]|->)/<span class='opr'>$1<\/span>/g;
+ $v =~ s/(['"].*['"])/<span class='str'>$1<\/span>/g;
+ $v =~ s/(my|our|local|use|lib|require|new|while|for|foreach|while|if|else|elsif)/<span class='bra'>$1<\/span>/g;
+ $v =~ s/(\$\w+)/<span class='inst'>$1<\/span>/g;
+ return $v
}
-sub get_list_type (@list){
- foreach my $arr(@list){
- foreach my $li(@$arr){
- if($li =~ /^(\d)|/){
- return $1;
- }
- last;
- }
- }
- return 0;
-}
+
sub style ($script){
MarkdownPluginException->throw(error=>"Invalid argument passed as script!",show_trace=>1) if !$script;
#Links <https://duckduckgo.com>
$script =~ s/<(http[:\/\w.]*)>/<a href=\"$1\">$1<\/a>/g;
-
+
my @result = map {
s/\*\*(.*)\*\*/\<em\>$1<\/em\>/;
s/\*(.*)\*/\<strong\>$1<\/strong\>/;
s/__(.*)__/\<del\>$1<\/del\>/;
s/~~(.*)~~/\<strike\>$1<\/strike\>/;
$_
- } split(/\s/,$script);
+ } split(/\s/,$script);
+ my $ret = join(' ',@result);
+
+ #Inline code
+ $ret =~ m/```(.*)```/g;
+ if($1){
+ my $v = $1;
+ $v =~ m/ ^(<<) ([@%]<) ([\$@%]?\w+) ([<>])
+ |^(<{2,3})
+ ([^>]+)
+ ( (<[\W\w ]*>) | (>{2,3})$ )
+ /gx;
+ if($5&&$6&&$7){
+ my $t = $5;
+ $v = $6;
+ my $c = $7;
+ $t =~ s/</</g;
+ $c =~ s/>/>/g;
+ $v=~m/^(\w+)/;
+ my $w = $1;
+
+ if($PARSER->isReservedWord($w)){
+ $v =~ s/^(\w+)/<span class='inst'>$w<\/span>/;
+
+ }
+ $v = qq(<span class='bra'>$t</span><span class='var'>$v</span></span><span class='bra'>$c</span>);
+
+ }elsif($5&&$6){
+ my $t = $5;
+ my $i = $6;
+ my $c = $7; $c = $8 if !$c;
+ $t =~ s/</</g;
+ $c =~ s/>/>/g if $c;
+ $v = qq(<span class='bra'>$t</span><span class='inst'>$i</span>$c);
+ }
+ elsif($1 && $2 && $3){
+ $v = qq(<span class='bra'><<$2<\/span><span class='var'>$3</span><span class='bra'>><\/span>);
+
+ }
+ $ret =~ s/```(.*)```/\<span\>$v<\/span\>/;
+ }
- my $ret = join(' ',@result);
#Images
$ret =~ s/!\[(.*)\]\((.*)\)/\<div class="div_img"><img class="md_img" src=\"$2\"\ alt=\"$1\"\/><\/div>/;
#Links [Duck Duck Go](https://duckduckgo.com)