--- /dev/null
+
+package PageHTMLPlugin;
+use lib::relative '.';
+use PerlCNFWebServerBase;
+
+
+
+our %TEMPLATES;
+
+sub new { bless {params=>{}}, shift }
+
+sub loadTemplate ($self, $parser, $path) {
+ if(-e $path){
+ if(not exists $TEMPLATES{$path}){
+ my $template = CNFGlobalFile -> new($path);
+ my %props = %{$parser->collections()};
+ $TEMPLATES{$path} = \$template;
+ $props{templates} = \%TEMPLATES;
+ $self -> {content} = $template -> content();
+ $parser -> log("Loaded template: $path")
+ }else{
+ my $template = $TEMPLATES{$path};
+ if($$template -> changed()){
+ $self -> {content} = $$template -> content();
+ $parser -> log("Reloaded changed template: $path")
+ }else{
+ $self -> {content} = $$template -> {content};
+ $parser -> log("Using cached template: $path")
+ }
+ }
+ return 1
+ }else{
+ PageHTMLPluginException->throw(error=>"Template not found:$path", show_trace=>1)
+ }
+}
+
+###
+# If (cgi) parameters are set the Pagelet value has to be reprocessed.
+###
+sub setParameters ($self, $parser, $prp, $params){
+ if(defined $params){
+ my %parameters;
+ foreach (keys %$params){
+ $parameters{$_} = $params->{$_}
+ }
+ $self -> {parameters} = %parameters;
+ process ($self, $parser, $prp)
+ }
+}
+
+sub resolvePropVal($parser, $property){
+ my $ref = ref($property);
+ if($ref eq 'Pagelet'){
+ return $property->{html_body}
+ }
+ elsif($ref eq 'PropertyValueStyle'){
+ if(exists $property->{plugin}) {
+ my $plugin = $property->{plugin};
+ if(ref($$plugin) eq 'PageHTMLPlugin'){
+ return $$plugin -> {content} if exists $$plugin -> {content}
+ }
+ # What ever this is in the CNF repository as a plugin other than this.
+ # Convention is to store in value field.
+ return $$plugin -> {value}
+ }
+ }
+ return $parser->{$property} if exists $parser->{$property};
+ return $parser -> anon($property)
+}
+
+sub process ($self, $parser, $prp) { my ($config, $meta);
+ try{
+ my $app_tree = 'App';
+ my $property = $parser -> property($prp);
+ $property = $prp if not $property;
+ if (exists $self -> {parameters}) {
+ $property = $property -> {cnf_property};
+ $app_tree = $self -> {parameters} -> {app} if $self -> {parameters} -> {app}
+ }
+ if (my $val = resolvePropVal($parser, $property)) {
+ $val = $$val if ref($val) eq 'SCALAR';
+ if ($config = $parser->anon($app_tree)) {
+ if ( $meta = $config->node('header/meta') ) {
+ foreach my $node (@{$meta->list()}) {
+ if ( $node->{data} ) {
+ $val = dataPropertyToHTMLParagraphs($parser->data()->{$node->{data}});
+ } else {
+ $val = processNodeWithProperty($parser, $node, $val );
+ }
+ }
+ my @template = ($val =~ m/^(.*)\s*
+ <![-]+\s*PerlCNF\s*Template\s*Start\s*[-]+>*\s*
+ (.*)
+ <\![-]+\s*PerlCNF\s*Template\s*End\s*[-]+>*\s*(.*)/mxsi);
+ $val = $template[1];
+ $parser->collections()->{$prp} = \Pagelet ->new({plugin => $self ,
+ property => $prp,
+ subroutine => 'process',
+ cnf_property => $parser -> property($prp),
+ html_head => \$template[0],
+ html_body => \$val,
+ html_foot => \$template[2],
+ });
+ return 1;
+ }
+ else {die "Where is meta node in [$app_tree] property?"}
+ }
+ else {die "Where is the [$app_tree] property?"}
+ }
+ else {die "Unable to resolve CNF property -> $prp"}
+ }catch($e){
+ PageHTMLPluginException->throw(error=>$e, show_trace=>1)
+ }
+}
+
+sub processNodeWithProperty($parser, $node, $val) {
+ my ($tag,$rep);
+ my @nodes = $node->nodes();
+ if(@nodes){
+ foreach my $sub(@nodes){
+ my $bf;
+ foreach($sub->nodes()){
+ $bf .= "<".$_->name();
+ foreach($_->attributes()){
+ my @pair = @$_;
+ $bf .= qq( $pair[0] = "$pair[1]");
+ }
+ $bf .= ">\n";
+ }
+ $tag ='<\![-]+\s*<@<\s*' . $sub->name() . '\s*>@>\s*[-]+>';
+ if(!$bf){
+ $rep = qq([\$\$\$[ ). $sub->name() .' is UNDEFINED in subnodes! ]$$$]';
+ $val =~ s/$tag/$rep/xg if defined $rep;
+ }else{
+ $val =~ s/$tag/$bf/xg;
+ }
+ }
+ return $val;
+ }elsif($node->{property} ){
+ $rep = $node->{property}
+ }else{
+ $rep = $node->val()
+ }
+
+ $tag = '<\![-]+\s*<@<\s*' . $node -> {tag} . '\s*>@>\s*[-]+>';
+ if(!$rep){
+ $rep = '[$$$[ '. $node -> {tag} .' is UNDEFINED! ]$$$]';
+ }else{
+ my $ref = ref($rep);
+ if($ref eq 'SCALAR'){
+ $rep = $$rep
+ }elsif($ref eq 'PropertyValueStyle'){
+ my $value = $rep -> {value};
+ if(!$value){
+ $rep = ${$parser -> data() -> {$rep->{property}}}
+ }else{
+ $rep = $value;
+ }
+ }elsif($ref eq "Pagelet"){
+ $rep = $rep -> {html_body};
+ }elsif($ref ne ''){
+ $rep = $rep -> val()
+ }
+ }
+
+ $val = $$val if ref($val) eq 'SCALAR';
+ $rep =~ s/^\s*|\s*$//gs;
+
+ $rep = $node->{title} . $rep if $node->{title};
+ $rep = $node->{head} . $rep if $node->{head};
+ $rep .= $node->{foot} if $node->{foot};
+
+ $val =~ s/$tag/$rep/xg;
+
+ return $val;
+}
+
+sub dataPropertyToHTMLParagraphs($data_struct) {
+ my $ret = "";
+ foreach my $record (@{$$data_struct->{data}}) {
+
+ my $p = qq(<div class = 'cnf_data_rec'>
+ <h2>@$record[1]</h2>
+ <p>@$record[2]</p>
+ </div>);
+ $ret .= $p ."\n";
+
+ }
+ return $ret;
+}
+
+
+
+
+1;
+=begin copyright
+Programed by : Will Budić
+EContactHash : 990MWWLWM8C2MI8K (https://github.com/wbudic/EContactHash.md)
+Source : https://github.com/wbudic/LifeLog
+Open Source Code License -> https://github.com/wbudic/PerlCNF/blob/master/ISC_License.md
+=cut copyright
--- /dev/null
+package PageletArticlePlugin;
+use PluginBase;
+
+ sub new { bless {params=>{}}, shift }
+
+ sub resolvePropVal($parser, $property){
+ my $ref = ref($property);
+ if($ref eq 'Pagelet'){
+ return $property->{html_body}
+ }
+ elsif($ref eq 'PropertyValueStyle'){
+ if(exists $property->{plugin}) {
+ my $plugin = $property->{plugin};
+ if(ref($$plugin) eq 'PageHTMLPlugin'){
+ return $$plugin -> {content} if exists $$plugin -> {content}
+ }
+ # What ever this is in the CNF repository as a plugin other than this.
+ # Convention is to store in value field.
+ return $$plugin -> {value}
+ }
+ }
+ return $parser->{$property} if exists $parser->{$property};
+ return $parser -> anon($property)
+ }
+
+ sub publish ($self, $parser, $prp_name) {
+ my ($cnf_property, $buffer);
+ if($prp_name =~ m/(\w*)\*$/){
+ $prp_name = $1;
+ my @list = $parser->list($prp_name);
+ foreach my $ins(@list){
+ $cnf_property = $parser -> anon($ins->{ele}.$ins->{aid});
+ $buffer .= $self->publish_item ($parser, $cnf_property);
+ }
+ }else{
+ $cnf_property = resolvePropVal($parser, $prp_name);
+ $buffer = $self->publish_item ($parser, $cnf_property);
+ }
+ $parser->collections()->{$prp_name} = \ Pagelet -> new ({plugin => $self ,
+ property => $prp_name,
+ subroutine => 'process',
+ cnf_property => $cnf_property,
+ html_body => $buffer,
+ }) ;
+ return 1;
+ }
+
+ sub publish_item ($self, $parser, $item) {
+ try{
+ my $result;
+ my $ref = ref($item);
+ if($ref eq 'CNFNode'){
+ foreach my $node($item->nodes()){
+ if($node ->name() eq 'article'){
+ my $nd_img = $node -> node('img');
+ my $nd_txt = $node -> node('text');
+ if($nd_img ne CNFNode::EMPTY()){
+
+ my $title = $nd_img->{title};
+ my $alt = $nd_img->{alt};
+ if($alt){
+ $alt = 'alt="'. $alt . '"'
+ }else{
+ $alt = 'alt'
+ }
+ $nd_txt = $nd_txt ->val();
+ my $nd_url = $nd_img -> {url};
+ my $nd_url_low = $nd_img -> {url_high};
+ my $nd_url_high = $nd_img -> {url_low};
+ my $nd_siz = $nd_img -> node('sizes');
+ $nd_siz = "(min-width: 800px) 480px" if $nd_siz eq CNFNode::EMPTY();
+
+
+ $result .=
+qq(<div class="article">
+ <div class="img">
+ <div class="title"> $title </div>
+ <img src="$nd_url"
+ srcset="$nd_url_low, $nd_url_high"
+ sizes="$nd_siz"
+ $alt>
+ </div>
+ <div class="text">
+ $nd_txt
+ </div>
+</div>)
+ }
+ }
+ }
+ }
+ $result =~ s/^\s*//gs;
+ return $result
+ }catch($e){
+ PageHTMLPluginException->throw(error=>$e, show_trace=>1)
+ }
+ }
+
+
+
+1;
+=begin copyright
+Programed by : Will Budić
+EContactHash : 990MWWLWM8C2MI8K (https://github.com/wbudic/EContactHash.md)
+Source : https://github.com/wbudic/LifeLog
+Open Source Code License -> https://github.com/wbudic/PerlCNF/blob/master/ISC_License.md
+=cut copyright
--- /dev/null
+package PerlCNFWebServerBase;
+use v5.36; #For younger Perl rebases change only here version, and bellow line 23. And brace for warnings in logs.
+use Syntax::Keyword::Try; no warnings qw(experimental::signatures);
+use feature qw(signatures);
+use Exception::Class ('PageHTMLPluginException');
+use Module::Load;
+ autoload CNFGlobalFile;
+ autoload CNFParser;
+
+package Pagelet {
+
+ sub new($class, $args){
+ return bless $args, $class;
+ }
+
+ sub val($self){
+ return $self -> {html_body} if exists $self -> {html_body}
+ }
+}
+
+
+sub import {
+ feature->import(':5.36');
+ feature->import('signatures');
+ warnings->import;
+ strict->import;
+ Module::Load->import;
+ Syntax::Keyword::Try->import;
+ Exception::Class->import('PageHTMLPluginException');
+ CNFGlobalFile->import;
+
+ my $caller = caller(0);
+ do {
+ no strict 'refs';
+ *{"$caller\:\:Pagelet"} = *{Pagelet};
+ *{"$caller\:\:isTrue"} = *{CNFParser::_isTrue};
+ };
+
+
+}
+
+
+
+1;
\ No newline at end of file
--- /dev/null
+!CNF3.3
+
+<<<CONST DEBUG=1>>>
+<<<INCLUDE apps/app_defaults.cnf>>>
+<<property <VAR>
+ Please <@< meta_1 >@>, this line is a paragraph.
+ <@< dynamic_paragraphs >@>
+>>
+###
+# In CNF Nodes shorthand format assigned are all template substitutions here.
+# The geeky shortifes are faster then normal CNF node tags, and use less recursion.
+##
+<<App <TREE>__IN_SHORTIFE__ __PRIORITY_8__
+header __\
+<#<TEST_VALUE>#>
+meta __\
+ @@ __\
+ tag: page_title
+ Document Viewer App
+ __/
+ @@ __\
+ header __\
+ link __|
+ rel = manifest
+ href = manifest.json
+ __~
+ __/
+ link __|
+ rel = stylesheet
+ href = ../web_sources/root.css
+ __~
+ __/
+ link __|
+ rel = stylesheet
+ href = ../web_sources/app.css
+ __~
+ __/
+ __/
+ __/
+ @@__\
+ tag: css_style
+ property: <*<MarkdownPlugin::CSS>*>
+ __/
+ @@__\
+ tag: css_style_articles
+ property: <*<ArticleSample_CSS>*>
+ __/
+ @@__\
+ tag : col_left
+ title: <span class="page_title"> Document Viewer App </span>
+ head: <dt class="page_title"><a href="/">Back To Main Page</a></dt><hr noshade/>
+ property: <*<MD1_headings>*>
+ foot: <hr noshade/>
+ __/
+ @@__\
+ tag : col_main
+ property: <*<MD1>*>
+ __/
+ @@__\
+ tag : col_right
+ <#< Test 2 >#>
+ __/
+__/
+>>
+
+<<PAGE_CONTENT <PLUGIN> __PRIORITY_7___
+ package : PageHTMLPlugin
+ subroutine : loadTemplate
+ property : apps/app.html
+>>
+
+<< Processor <PLUGIN> __PRIORITY_9__
+ package : PageHTMLPlugin
+ subroutine : process
+ property : PAGE_CONTENT
+>>
+
+<<<MD1
+# Main Heading
+
+ Introduction paragraph here.
+
+## First Chapter
+
+The story here, etc, goes on and on.
+If we have links CNF MarkupInstructions they macro translates this -> [$$$[ some_web_site_1 ]$$$]
+
+If not stays in macro format, like this -> [$$$[ This link doesn't exist ]$$$]
+
+## Second Chapter
+
+[$$$[MarkupInstructions]$$$]
+
+## Third Chapter
+
+[$$$[ArticleSample]$$$]
+
+>>>
+
+<< MarkupDocument <PLUGIN> __PRIORITY_6__
+ package : MarkdownPlugin
+ subroutine : convert
+ property : MD1
+ instructions : MarkupInstructions
+>>
+
+<< MarkupInstructions <TREE> __PRIORITY_3_
+
+[links[
+ [some_web_site_1[
+ desc : desc_website_1_desc.html
+ url : https://somewebsite.com
+ ]some_web_site_1]
+]links]
+[particulars[
+ <@@<
+ tag: ArticleSample
+ >@@>
+]particulars]
+<#<
+ This property holds further instructions on what actions and data is returned to client.
+ Including atomic descriptions and links that can be text rich and more informative.
+
+ So this whole script is both markup to render HTML and to prove configuration, to an web service app.
+ The page might render differently for other markup script processor if is read as an md file.
+
+### HTTP compression
+
+ HTTP compression is a capability that can be built into web servers and web clients to improve transfer speed and bandwidth utilization.[1]
+
+ HTTP data is compressed before it is sent from the server: compliant browsers will announce what methods are supported to the server before downloading the correct format; browsers that do not support compliant compression method will download uncompressed data. The most common compression schemes include gzip and Brotli; a full list of available schemes is maintained by the IANA.[2]
+
+ There are two different ways compression can be done in HTTP. At a lower level, a Transfer-Encoding header field may indicate the payload of an HTTP message is compressed. At a higher level, a Content-Encoding header field may indicate that a resource being transferred, cached, or otherwise referenced is compressed. Compression using Content-Encoding is more widely supported than Transfer-Encoding, and some browsers do not advertise support for Transfer-Encoding compression to avoid triggering bugs in servers.[3]
+
+>#>
+
+>>
+
+
+
+<<GenericInstructionHandler<INSTRUCTOR>PROPERTY>>
+<<ArticleSample_CSS <PROPERTY>
+
+
+
+.article{
+ display: grid;
+ grid-template-columns: .5fr 1fr;
+ column-gap: 1px;
+ border: 1px solid rgb(133, 133, 233);
+ background-color: rgba(0, 0, 0, 0);
+ margin-bottom: 5px;
+}
+.img{
+ display: grid;
+ grid-template-columns: 1fr;
+ padding: 5px;
+ # border: solid black 1px;
+ min-width: min-content;
+
+ .title{
+ text-align: left;
+ font-kerning: auto;
+ font-weight: bolder;
+ font-size: x-large;
+ padding-bottom: 5px;
+ }
+ img{
+ max-width:380px;
+ }
+}
+.text{
+ font-size: 20px;
+ padding-top: 20px;
+ text-align: left;
+ p{
+ font-size: x-large;
+ }
+}
+
+@layer base {
+
+ @media (width > 599px) {
+
+ .content>*:nth-child(1) {
+ flex: 1 2 0;
+ margin-left: .2rem;
+ }
+
+ .content>*:nth-child(2) {
+ flex: 0 1 80%;
+ text-align: justify;
+ display: inline-block;
+ overflow: scroll;
+ border-radius: 10px;
+ }
+
+ .content>*:nth-child(3) {
+ flex: 1 2 0;
+ margin-left: .2rem;
+ display: none;
+ }
+ }
+
+
+
+ @media (width > 1440px) {
+
+ .content>*:nth-child(1) {
+ flex: 1 2 .1%;
+ margin-left: .5rem;
+ }
+ .content>*:nth-child(2) {
+ flex: 0 1 90%;
+ margin-left: .1rem;
+ }
+ .content>*:nth-child(3) {
+ flex: 1 2 18%;
+ margin-left: .5rem;
+ display: none;
+ }
+ }
+
+ }
+
+>>
+
+
+<<ArticleSample$$ <TREE> __IN_SHORTIFE__ __PRIORITY_2__
+article __\
+ img __\
+ title: Cat Deva
+ alt: Cat Diva Artistic Image
+ url: images/cat_deva_2.jpeg
+ url_high: images/cat_deva_2.jpeg 480w
+ url_low: images/cat_deva_2-240.jpeg 240w
+ sizes: 380px
+
+ __/
+ text __\
+ <p>This is a beautiful picture.</p> __~
+ __/
+__/
+>>
+<<ArticleSample$$ <TREE> __IN_SHORTIFE__ __PRIORITY_2__
+article __\
+ img __\
+ title: Cica
+ alt: Cica
+ url: images/cica_1.jpeg
+ url_high: images/cica_1.jpeg 480w
+ url_low: images/cica_1_240x240.jpeg 240w
+ sizes: 380px
+
+ __/
+ text __\
+ <p>This is a beautiful picture two.</p> __~
+ __/
+__/
+>>
+
+
+<<ArticleSample$$ <TREE> __IN_SHORTIFE__ __PRIORITY_2__
+article __\
+ img __\
+ title: Flowers In Spring
+ alt: Flowers Picture
+ url: images/flowers_1.jpeg
+ url_high: images/flowers_1.jpeg 480w
+ url_low: images/flowers_1_450x250.jpeg 450w
+ sizes: 480px
+
+ __/
+ text __\
+ <p>This is a beautiful picture three.</p> __~
+ __/
+__/
+>>
+
+<< ArticlePagelet <PLUGIN> __PRIORITY_5__
+ package : PageletArticlePlugin
+ subroutine : publish
+ property : ArticleSample*
+>>
+
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="description" content="">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <!--<@< header >@>-->
+ <title><!--<@< page_title >@>--></title>
+</head>
+
+<body>
+<!--PerlCNF Template Start-->
+<style><!--<@< css_style >@>--></style>
+<style><!--<@< css_style_articles >@>--></style>
+<!-- img src="wsrc/images/Sun-Rotating.gif" -->
+<div class="content">
+ <div class="col" role="navigation">
+ <div class="toc"><strong>TOC</strong>
+ <span class="scrolling">
+ <!--<@< col_left >@>-->
+ </span>
+ </div>
+ </div>
+ <div class="col_main" role="main">
+ <!--<@< col_main >@>-->
+ </div>
+ <div class="col" role="contentinfo">
+ <!--<@< col_right >@>-->
+ </div>
+</div>
+<!--PerlCNF Template End-->
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+!CNF3.3
+
+<<<CONST
+APP_VERSION = 1.0
+>>>
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env perl
+#
+use v5.30;
+use strict;
+use warnings;
+use Exception::Class ('LifeLogException');
+use Syntax::Keyword::Try;
+##
+# We use dynamic perl compilations. The following ONLY HERE required to carp to browser on
+# system requirments or/and unexpected perl compiler errors.
+##
+use CGI::Carp qw(fatalsToBrowser set_message);
+
+BEGIN {
+ sub handle_errors {
+ my $err = shift;
+ say "<html><body><h2>Server Error</h2><pre>Error: $err</pre></body></html>";
+ }
+ set_message(\&handle_errors);
+}
+
+use lib "/home/will/dev_new/LifeLog/htdocs/cgi-bin/system/modules";
+#use lib "system/modules";
+require CNFParser; require CNFNode; require CNFDateTime;
+
+exit &HTMLPageBuilderFromCNF;
+
+sub HTMLPageBuilderFromCNF {
+
+ my $template = $0; $template =~ s/\.pl$|\.cgi$|\.perl/.html/g;
+ open( my $fh, "<:perlio", $template )
+ or LifeLogException->throw("Can't open $template: $!");
+ read $fh, my $content, -s $fh;
+ close $fh;
+ my $cnf = CNFParser::_configure ({
+ DO_ENABLED => 1, HAS_EXTENSIONS => 1, ANONS_ARE_PUBLIC => 1, DEBUG => 1,
+ PAGE_CONTENT => \$content,
+ PAGE_HEAD => "<!--Not Defined-->",
+ PAGE_FOOT => "<!--Not Defined-->"
+ },$0);
+ my $ptr = $cnf->data();
+ $ptr = $ptr->{'PAGE'};
+ say $$ptr if $ptr;
+ return 0
+}
+
+use feature qw(signatures);
+package PageHTMLPlugin {
+ sub new { bless {}, shift }
+
+ sub resolvePropVal($parser,$prp){
+ return exists $parser->{$prp} ? $parser->{$prp} : $parser -> anon($prp)
+ }
+
+ sub process {
+ my ( $class, $parser, $prp, $config, $meta ) = @_;
+ if ( my $val = resolvePropVal($parser ,$prp) ) {
+ if ( $config = $parser->anon('App') ) {
+ if ( $meta = $config->node('meta') ) {
+ foreach my $node ( @{ $meta->list() } ) {
+ if ( $node->{data} ) {
+ $val = dataPropertyToHTMLParagraphs($parser->data()->{$node->{data}});
+ } else {
+ # Notice DEBUG constance is not an app package required CNF default.
+ # Not declaring it init of an instance of parser, the following will fail.
+ # The{DEBUG=>1} is required, be set to 1 or 0.
+ print $node->toScript() if $parser->{DEBUG};
+ $val = processNodeWithProperty( $node, $val );
+ }
+ $parser->anon()->{$prp} = $val;
+ }
+ return 1;
+ }
+ else { die "Where is meta node in App property?" }
+ }
+ else { die "Where is App property?" }
+ }
+ else { die "Don't do that!" }
+ }
+
+
+ sub processNodeWithProperty( $node, $val ) {
+ my $tag = '<@<\s*' . $node->{tag} . '\s*>@>';
+ my $rep = $node->{property} ? $node->{property} : $node->val();
+ $rep =~ s/^\s*|\s*$//gs;
+ $val =~ s/$tag/$rep/xg;
+ return $val;
+ }
+
+ sub dataPropertyToHTMLParagraphs($data_struct) {
+ my $ret = "";
+ foreach my $record (@{$$data_struct->{data}}) {
+
+ my $p = qq(<div class = 'cnf_data_rec'>
+ <h2>@$record[1]</h2>
+ <p>@$record[2]</p>
+</div>);
+ $ret .= $p ."\n";
+
+ }
+ return $ret;
+ }
+}
+
+
+
+1;
+=begin copyright
+Programed by : Will Budić
+EContactHash : 990MWWLWM8C2MI8K (https://github.com/wbudic/EContactHash.md)
+Source : https://github.com/wbudic/LifeLog
+Open Source Code License -> https://github.com/wbudic/PerlCNF/blob/master/ISC_License.md
+=cut copyright
--- /dev/null
+!CNF3.3
+
+<<property <VAR>
+ Please <@< meta_1 >@>, this line is a paragraph.
+
+ <@< dynamic_paragraphs >@>
+>>
+<<App <TREE>
+[meta[
+ <@@<
+ tag : col_left
+ <#< Dear Visitor >#>
+ >@@>
+ <@@<
+ tag : col_main
+ property: <*<Markup Document>*>
+ >@@>
+ <@@<
+ tag : col_right
+ <#< Test 2 >#>
+ >@@>
+]meta]
+>>
+<< Processor <PLUGIN>
+ package : main::PageHTMLPlugin
+ subroutine : process
+ property : PAGE_CONTENT
+>>
+
+<<< Markup Document
+
+# Main Heading
+
+ Introduction paragraph here.
+
+## First Chapter
+
+The story hear, etc, on and on.
+If we have link CNF we macro as follow [$$$[ some_web_site_1 ]$$$]
+
+## Second Chapter
+>>>
+
+<< MarkupInstructions <TREE>
+
+[links[
+ [some_web_site_1[
+ provide : desc_website_1_desc.html
+ <#<https://somewebsite.com>#>
+ ]some_web_site_1]
+]links]
+
+<#<
+
+ This property holds further instructions on what actions and data is returned to client.
+ Including atomic descriptions and links that can be text rich and more informative.
+
+ So this whole script is both markup to render HTML and to prove configuration, to an web service app.
+ The page might render differently for other markup script processor if is read as an md file.
+
+>#>
+
+>>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <title></title>
+ <meta name="description" content="">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <link rel="stylesheet" href="wsrc/main.css">
+</head>
+
+<body>
+ <style>
+ @font-face {
+ font-family: "LeagueMono";
+ src: url(wsrc/fonts/LeagueMono-VF.woff2);
+ }
+
+ @font-face {
+ font-family: "Lato";
+ src: url(wsrc/fonts/Lato/Lato-Regular.ttf);
+
+
+ }
+
+ body {
+ font-family: Lato;
+ display: flow-root;
+ padding: 0.5em;
+ }
+ p{
+ padding-bottom: .5em;
+ }
+
+
+ .content {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border: 2px dotted rgb(96 139 168);
+ }
+
+ .col {
+ border: 2px solid blue;
+ text-wrap: wrap;
+ }
+ .scrolling{
+ display: block;
+ height: 100%;
+ overflow-x: scroll !important;
+ text-wrap: wrap;
+ border: red;
+ width: 2em;
+ margin-right: 1rem;
+ }
+ .col_main {
+
+ border: 2px solid blue;
+ min-width: 70%;
+ }
+
+ .content>*:nth-child(1) {
+ flex: 1 2 10ch;
+ min-width: 10ch;
+ max-width: 150px;
+ margin-left: 5em;
+ }
+
+ .content>*:nth-child(2) {
+ flex: 0 2 85%;
+ padding: 2dvi;
+ text-align: justify;
+ }
+
+ .content>*:nth-child(3) {
+ flex: 1 2 10ch;
+ min-width: 10ch;
+ max-width: 150px;
+ margin-right: 5em;
+ }
+ </style>
+
+ <div class="content">
+
+ <div class="scrolling"><!--<@< col_left >@>-->
+
+ <ul>
+ <li>Item One</li>
+ <li>Item Two</li>
+ </ul>
+
+ </div>
+ <div class="col_main"><!--<@< col_main >@>-->
+ <p>
+ MaryLou wore the tiara with real pride.
+ There was something that made doing anything she didn't really want to do a bit easier when she wore it.
+ She really didn't care what those staring through the window were thinking as she vacuumed her
+ apartment.
+ <p>Bljat</p>
+ </p>
+ </div>
+ <div class="col"> <!--<@< col_right >@>-->
+ Test Right
+ </div>
+ </div>
+
+</body>
+
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="description" content="">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title><!--<@< page_title >@>--></title>
+ <link rel="manifest" href="apps/manifest.json" />
+ <link rel="stylesheet" href="../web_sources/root.css" />
+ <link rel="stylesheet" href="../web_sources/app.css" />
+</head>
+
+
+<style>
+
+
+
+.col_section {
+ display: grid;
+ border: solid salmon 1px;
+ border-radius: 10px;
+ overflow-block: scroll;
+
+ align-content: start;
+ align-items: start;
+ justify-items: start;
+ text-align: start;
+
+}
+
+.content>*:nth-child(1) {
+ flex: 1 2 10%;
+ margin-left: .5rem;
+}
+
+.content>*:nth-child(2) {
+ flex: 0 1 85%;
+ text-align: justify;
+ display: inline-block;
+ overflow: scroll;
+ border-radius: 10px;
+}
+
+.content>*:nth-child(3) {
+ flex: 1 2 10%;
+ margin-left: .5rem;
+ /* display: none; */
+}
+
+</style>
+
+<body>
+ <!--PerlCNF Template Start-->
+ <div class="content">
+ <div class="col" role="navigation">
+ <div class="toc"><strong>TOC</strong>
+ <span class="scrolling">
+ <!--<@< col_left >@>-->
+ PerlCNFWebServer
+ </span>
+ </div>
+ </div>
+ <div class="col_main" role="main">
+ <!--<@< col_main >@>-->
+ <h1>Main</h1>
+ <p>Main paragraph sample text.</p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.
+ Facilis perferendis eius fuga dignissimos tempore repellendus aliquid eligendi iste, esse a quidem cum
+ totam deserunt
+ harum accusantium modi similique officiis? Nemo?</p>
+ <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusamus repudiandae, saepe, veritatis eveniet repellat qui ipsa quas possimus iure quae illo! Tenetur libero error dicta non illo, sint porro nihil?</p>
+ <div class="col_section">
+ <h2>Test</h2>
+ <div>
+ <h3>Lorem I</h3>
+ <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Iure, sint facere officia aliquid iste amet vel
+ iusto nulla tenetur error porro modi voluptatum reprehenderit! Maiores quidem debitis ex consequuntur
+ aspernatur?</p>
+ </div>
+
+ <div>
+ <h3>Lorem II</h3>
+ <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Iure, sint facere officia aliquid iste amet vel
+ iusto nulla tenetur error porro modi voluptatum reprehenderit! Maiores quidem debitis ex consequuntur
+ aspernatur?</p>
+
+ <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab similique quisquam distinctio ut nemo
+ culpa, esse fuga fugit eveniet sint, illum provident consequuntur expedita voluptate veritatis, tenetur quod
+ delectus error?</p>
+ </div>
+
+ <div>
+ <h3>Lorem III</h3>
+ <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Iure, sint facere officia aliquid iste amet vel
+ iusto nulla tenetur error porro modi voluptatum reprehenderit! Maiores quidem debitis ex consequuntur
+ aspernatur?</p>
+
+ <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab similique quisquam distinctio ut nemo
+ culpa, esse fuga fugit eveniet sint, illum provident consequuntur expedita voluptate veritatis, tenetur quod
+ delectus error?</p>
+ <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Fuga maiores eveniet quaerat maxime aspernatur mollitia
+ modi itaque dolore quis nihil! Hic facilis eum laborum ipsam fugiat reiciendis sunt odio ratione?</p>
+ <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Fuga maiores eveniet quaerat maxime aspernatur mollitia
+ modi itaque dolore quis nihil! Hic facilis eum laborum ipsam fugiat reiciendis sunt odio ratione?</p>
+ <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Fuga maiores eveniet quaerat maxime aspernatur mollitia
+ modi itaque dolore quis nihil! Hic facilis eum laborum ipsam fugiat reiciendis sunt odio ratione?</p>
+ <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Fuga maiores eveniet quaerat maxime aspernatur mollitia
+ modi itaque dolore quis nihil! Hic facilis eum laborum ipsam fugiat reiciendis sunt odio ratione?</p>
+
+ </div>
+ </div>
+
+ <div class="col_section">
+ <h2>Test</h2>
+ <div>
+ <h3>Lorem II</h3>
+ <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Repellat vero accusantium at illo accusamus molestiae
+ numquam eos optio odio quasi esse placeat eveniet, maxime deleniti vel earum mollitia rem quod?</p>
+ </div>
+ </div>
+
+
+
+
+ </div>
+
+ <div class="col" role="contentinfo">
+ <!--<@< col_right >@>-->
+ <p>Right Column!</p>
+ </div>
+ </div>
+ <!--PerlCNF Template End-->
+
+</body>
+
+</html>
\ No newline at end of file
--- /dev/null
+{
+ "short_name": "PerlCNFWEB",
+ "name": "PerlCNFWEBServer App",
+ "icons": [
+ {
+ "src": "images/favicons/PerlCNFEagle_192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "images/favicons/PerlCNFEagle_512x512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ],
+ "start_url": ".",
+ "display": "standalone",
+ "theme_color": "#000000",
+ "background_color": "#ffffff"
+ }
+
\ No newline at end of file