bck_*
dbLifeLog/current_theme
lighttpd.conf
+dump_*
+*.rdf
--- /dev/null
+#!/usr/bin/env perl
+#
+#
+use v5.30;
+use strict;
+use warnings;
+use Exception::Class ('CNFHTMLServiceError');
+use Syntax::Keyword::Try;
+use CGI;
+use CGI::Session '-ip_match';
+use feature qw(signatures);
+##
+# 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><code style='color:crimson; font-weight:bold'>$err<code></body></html>";
+ }
+ set_message(\&handle_errors);
+}
+
+use lib "system/modules";
+require CNFParser;
+require CNFNode;
+
+our $GLOB_HTML_SERVE = "'{}/*.cgi' '{}/*.htm' '{}/*.html' '{}/*.md' '{}/*.txt'";
+our $script_path = $0; $script_path =~ s/\w+.cgi$//;
+
+exit &CNFHTMLService;
+
+sub CNFHTMLService {
+ my ($cgi,$ptr) = (CGI -> new(),undef); $cgi->param('service', 'feeds');
+ my $cnf = CNFParser -> new (undef,{ DO_ENABLED => 1, HAS_EXTENSIONS=>1, ANONS_ARE_PUBLIC => 1, CGI=>$cgi });
+ $cnf->parse(undef,_getServiceScript($cgi));
+ $ptr = $cnf->data();
+ $ptr = $ptr->{'PAGE'};
+ say $$ptr if $ptr;
+ # open my $fh, ">dump_of_output_to_browser.html";
+ # print $fh $$ptr;
+ # close $fh;
+ return 0
+}
+
+sub _getServiceScript($cgi) {
+ my $service = $cgi->param('service'); $service = "undef" if not $service;
+ if($service eq 'feeds'){
+ return _CNF_Script_For_Feeds();
+ }
+ CNFHTMLServiceError->throw(error=>"UNKNOWN SERVICE -> $service", show_trace=>1)
+}
+
+sub _CNF_Script_For_Feeds {
+<<__CNF_IS_COOL__;
+<<PROCESS_RSS_FEEDS<PLUGIN>
+
+ RUN_FEEDS = yes
+ CONVERT_TO_CNF_NODES = yes
+ OUTPUT_TO_CONSOLE = false
+ OUTPUT_TO_MD = no
+ BENCHMARK = no
+ TZ=Australia/Sydney
+ OUTPUT_DIR = "./rss_output"
+
+
+ CONVERT_CNF_HTML = yes
+ CNF_TREE_STORE = true
+
+ package : RSSFeedsPlugin
+ subroutine : process
+ property : RSS_FEEDS
+
+>>
+// Following is a table having a list of details for available RSS feeds to process.
+|| The more rows have here the longer it takes to fetch them, what is it, once a day, week, month?
+<< RSS_FEEDS <DATA>
+ID`Name`URL`Description~
+01`CPAN`http://search.cpan.org/uploads.rdf`CPAN modules news and agenda.~
+>>
+__CNF_IS_COOL__
+}
+
+
+1;
+
+=begin copyright
+Programed by : Will Budic
+EContactHash : 990MWWLWM8C2MI8K (https://github.com/wbudic/EContactHash.md)
+Source : https://github.com/wbudic/LifeLog
+ This source file is copied and usually placed in a local directory, outside of its repository 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.
+Open Source Code License -> https://github.com/wbudic/PerlCNF/blob/master/ISC_License.md
+=cut copyright
\ No newline at end of file
#!/usr/bin/env perl
# A delegated CNFParser processed rendering of the Document Index Web page, a Model-View-Controller Pattern approuch.
-# The index.cnf script contains the structure and page skeleton,
+# The index.cnf script contains the structure and page skeleton,
# all configuration as well as the HTMLIndexProcessorPlugin converting the CNF to final HTML.
# It is very convienient, as both style and script for the page is separated and developed in the index.cnf.
# Which then can be moved to a respective include file over there.
use Exception::Class ('LifeLogException');
use Syntax::Keyword::Try;
##
-# We use dynamic perl compilations. The following ONLY HERE required to carp to browser on
+# 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>";
+ say "<html><body><h2>Server Error</h2><pre>Error: $err</pre></body></html>";
}
set_message(\&handle_errors);
}
exit &HTMLPageBuilderFromCNF;
-sub HTMLPageBuilderFromCNF {
+sub HTMLPageBuilderFromCNF {
my $html = obtainDirListingHTML('docs');
my $cnf = CNFParser -> new (
$script_path."index.cnf",{
DO_ENABLED => 1, HAS_EXTENSIONS=>1,
ANONS_ARE_PUBLIC => 1,
- PAGE_HEAD => "<h1 id=\"index_head\">Index Page of Docs Directory</h1>",
- PAGE_CONTENT => $html,
+ PAGE_HEAD => "<h1 id=\"index_head\">Index Page of Docs Directory</h1>",
+ PAGE_CONTENT => $html,
PAGE_FOOT => "<!--Not Defined-->"
}
);
my $ptr = $cnf->data();
- $ptr = $ptr->{'PAGE'};
- say $$ptr if $ptr;
+ $ptr = $ptr->{'PAGE'};
+ say $$ptr if $ptr;
return 0
}
my ($dir, $ret) = (shift,"");
my $html = listFiles($dir,$script_path,"");
if($html){
- $ret .="<ul><b>$dir →</b>\n";
+ $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 ($dir, $script_path, $ret) = @_;
my $path = $script_path.$dir;
my $spec = $GLOB_HTML_SERVE; $spec =~ s/{}/$path/gp;
- my @files = glob ($spec);
+ my @files = glob ($spec);
foreach my $file(@files){
($file =~ m/(\w+\.\w*)$/g);
my $name = $1;
if($file =~ /\.md$/){
- my @title = getDocTitle($file);
+ my @title = getDocTitle($file);
$ret .= qq(\t\t\t<li><a href="$dir/$title[0]">$title[1]</a> ‐ $name</li>\n);
- }else{
+ }else{
$ret .= qq(\t\t\t<li><a href="$dir/$name">$name</a></li>\n);
}
- }
+ }
return $ret;
}
last;
}
}
- close $fh;
+ close $fh;
($file =~ m/(\w+\.\w*)$/g);
return ($1,$ret)
}
-
-
-
-
-
+1;
+=begin copyright
+Programed by : Will Budic
+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
#!/usr/bin/env perl
#
-# Programed by: Will Budic
-# Open Source License -> https://choosealicense.com/licenses/isc/
-#
use strict;
use warnings;
use experimental qw( switch );
{-type => 'text/javascript', -src => 'wsrc/jquery-ui.js'}],
-style => [ {-type => 'text/css', -src => $css},
{-type => 'text/css', -src => 'wsrc/effects.css'},
+ {-type => 'text/css', -src => 'wsrc/feeds.css'},
{-type => 'text/css', -src => 'wsrc/jquery-ui.css'},
{-type => 'text/css', -src => 'wsrc/jquery-ui.theme.css'},
{-type => 'text/css', -src => 'wsrc/jquery-ui.theme.css'}],
print qq(
<br>
<div id="menu_page" style="margin-left: 85vw;"><span class="menu_head">Menu</span><hr>
- <a class="ui-button ui-corner-all ui-widget" href="index.cgi">Index</a>
+ <a class="ui-button ui-corner-all ui-widget" href="index.cgi">Index</a><hr>
+ <a class="a_" onclick="return fetchFeeds()">Feeds</a><hr>
</div>
<div class="rz login">
$frm
</div>
<br>
</div>
+ <div id="feeds" class="rz" style="width:60% !important;visibility:hidden">RSS</div>
+ <script>
+ function fetchFeeds(){
+ var pnl = \$('#feeds');
+ pnl.html(
+ '<div><span style="border:1px solid Crimson;padding:5px;"><font color="Crimson"><b>P l e a s e W a i t D a r l i n g !</b></font></span><br><img src="images/WelloffHighlevelAlpinegoat.webp" witdht="85" height="85"></div>'
+ );
+ pnl.show();
+ pnl.css('visibility','visible');
+ \$.post('CNFServices.cgi', {service:'feeds',action:'default'}, displayFeeds).fail(
+ function(response) {pnl.html("Service Error: "+response.status,response.responseText);pnl.fadeOut(10000);}
+ );
+ //
+ }
+ function displayFeeds(content){
+ var pnl = \$('#feeds');
+ pnl.html(content);
+ pnl.show();
+ }
+ </script>
);
Settings::printDebugHTML($DBG) if Settings::debug();
exit;
}
+=begin copyright
+Programed by : Will Budic
+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
foreach my $key(@keys){
if($td_itm_cnt>$present_rows_cnt){
$td_cat .= "</ul></td><td><ul>";
- $td_itm_cnt = 0;
+ $td_itm_cnt = 0;
}
$td_cat .= "<li id='".$key."'><a href='#'>".$hshCats{$key}."</a></li>";
$td_itm_cnt++;
if($log =~ m/(.*\s*.*?)<br>/){$h=$1}
elsif($log =~ m/(\s*.*\n)/) {$h=$1}
if($h){
- $log = $h.qq(<input type="hidden" id="h$id" value="$log"/><button id='btnRTF' onclick="return dispFullLog($id);"
+ $log = $h.qq(<input type="hidden" id="h$id" value="$log"/><button id='btnRTF' onclick="return dispFullLog($id);"
class="ui-button ui-corner-all ui-widget"><span>⇳<span></button>);
}
}
<input type="hidden" name="opr" id="opr" value="0"/>
<input type="submit" value="Sum" onclick="return sumSelected()"/>
<span style="border-left: 1px solid black;padding:5px;margin:15px;">
- <button onclick="return selectAllLogs()">Select All</button>
+ <button onclick="return selectAllLogs()">Select All</button>
<input type="reset" value="Unselect All"/>
<input type="submit" value="Date Diff" onclick="return dateDiffSelected()"/>
- <input type="submit" value="Export" onclick="return exportSelected()"/>
+ <input type="submit" value="Export" onclick="return exportSelected()"/>
<input type="submit" value="Print" onclick="return viewSelected()"/>
<input id="del_sel" type="submit" value="Delete" onclick="display('Please Wait!')"/>
</span>
<button type="reset" onclick="setNow();resetDoc(); return true;">Reset</button>
<span id="cat_desc" name="cat_desc">Enter log...</span>
-
+
Category:
-
+
<button data-dropdown="#dropdown-standard" style="margin: 0px; padding: 0;">
<span id="lcat" class="ui-button"> <i><font size=1>--Select --</font> </i></span>
« </button>
<input id="vrtf" name="vrtf" type="hidden" value="0"/>
View RTF Logs: <button id="btn_rtf" onclick="viewRTFLogs(this);">View</button>
-
+
</td>
</tr>
-
+
<tr class="collpsd">
<td align="right">Exclude Category:</td>
<td align="left">
# Final Page Output from here! #
##################################
my $audio = &Settings::audioEnabled ? qq(
- <audio id="au_door_chime" enabled preload="auto"
+ <audio id="au_door_chime" enabled preload="auto"
src="wsrc/Miki-Matsubara-WASH-WASH.mp3">
Your browser does not support the
<code>audio</code> element.
<<FRM>my_cat_simon_frm.png> <<TITLE<Simon The Cat>>
This is my pet, can you hold him for a week while I am on holiday?
- </pre>
+ </pre>
<p>
<b><<LNK<<i>{url to image}</i>>></b><br><br>
Explicitly tag an URL in the log entry.
Otherwise link appears as plain text.
</p><br>
<p><iframe .....</iframe> - Experimental html embedding, useful for youtube shared videos.</p>
- <hr>
+ <hr>
<h3>Log Page Particulars</h3><p> ↟ or ↡ - Jump links to top or bottom of page respectivelly. </p>
</div>
</td></tr></table>)
}
-1;
\ No newline at end of file
+1;
+=begin copyright
+Programed by : Will Budic
+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
\ No newline at end of file
--- /dev/null
+<<CNF_FEED<TREE>
+ Release: 1
+ Version: 1.0
+ <Feed<
+ Expires: 2023-09-27 08:00:00
+ File: ./rss_output/tree_feed_CPAN.cnf
+ Published: 2023-09-16 03:26:12.785 UTC
+ Title: Recent CPAN uploads - MetaCPAN
+ URL: http://search.cpan.org/uploads.rdf
+ [#[
+ CPAN modules news and agenda.
+ ]#]
+ >Feed>
+ <Brew<
+ <Item<
+ Date: 2023-09-16 03:20:02
+ Link: https://metacpan.org/release/TIMLEGGE/Crypt-OpenSSL-AES-0.08
+ Title: Crypt-OpenSSL-AES-0.08
+ <Description<
+ [#[
+ <p>A Perl wrapper around OpenSSL's AES library</p><p>Changes for 0.08</p><ul><li>Detailed Changes</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-16 00:05:19
+ Link: https://metacpan.org/release/PERLANCAR/Bencher-Scenario-Shell-Startup-0.001
+ Title: Bencher-Scenario-Shell-Startup-0.001
+ <Description<
+ [#[
+ <p>Benchmark startup overhead of various Unix shells</p><p>Changes for 0.001 - 2023-07-08</p><ul><li>First release.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-15 20:40:36
+ Link: https://metacpan.org/release/RAWLEYFOW/API-Vultr-0.001
+ Title: API-Vultr-0.001
+ <Description<
+ [#[
+ A simple interface to the Vultr v2 API
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-15 20:06:29
+ Link: https://metacpan.org/release/WATERKIP/WebService-Postex-0.004
+ Title: WebService-Postex-0.004
+ <Description<
+ [#[
+ <p>A Postex WebService implemenation in Perl</p><p>Changes for 0.004 - 2023-09-15T20:05:14Z</p><ul><li>Change to Object::Pad from Moose</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-15 19:08:32
+ Link: https://metacpan.org/release/DJERIUS/CXC-Form-Tiny-OptArgs2-0.01
+ Title: CXC-Form-Tiny-OptArgs2-0.01
+ <Description<
+ [#[
+ <p>a really awesome library</p><p>Changes for 0.01 - 2023-09-15T15:07:02-04:00</p><ul><li>First release upon an unsuspecting world.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-15 18:20:38
+ Link: https://metacpan.org/release/MARKOV/Mail-Box-Parser-C-3.011
+ Title: Mail-Box-Parser-C-3.011
+ <Description<
+ [#[
+ Parse mbox files with XS
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-15 16:22:26
+ Link: https://metacpan.org/release/WATERKIP/Dist-Zilla-PluginBundle-Author-WATERKIP-3.3
+ Title: Dist-Zilla-PluginBundle-Author-WATERKIP-3.3
+ <Description<
+ [#[
+ <p>An plugin bundle for all distributions by WATERKIP</p><p>Changes for 3.3 - 2023-09-15T16:19:02Z</p><ul><li>Add 'use Data::Dumper' to skip for prereqs</li>
+ <li>Include authors to contributors file</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-15 15:45:17
+ Link: https://metacpan.org/release/BPS/GnuPG-Interface-1.03
+ Title: GnuPG-Interface-1.03
+ <Description<
+ [#[
+ <p>supply object methods for interacting with GnuPG</p><p>Changes for 1.03 - 2023-09-14</p><ul><li>Add fix for running in taint mode for Perl 5.38.0(thanks to Andrew Ruthven)</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-15 13:48:51
+ Link: https://metacpan.org/release/CUKEBOT/Gherkin-27.0.0
+ Title: Gherkin-27.0.0
+ <Description<
+ [#[
+ A parser and compiler for the Gherkin language
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-15 11:42:54
+ Link: https://metacpan.org/release/HANJE/Tk-CodeText-0.44
+ Title: Tk-CodeText-0.44
+ <Description<
+ [#[
+ Programmer's Swiss army knife Text widget.
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-15 11:19:47
+ Link: https://metacpan.org/release/HANJE/Tk-CodeText-0.43
+ Title: Tk-CodeText-0.43
+ <Description<
+ [#[
+ Programmer's Swiss army knife Text widget.
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-15 08:16:27
+ Link: https://metacpan.org/release/NERDVANA/CodeGen-Cpppp-0.001_02
+ Title: CodeGen-Cpppp-0.001_02
+ <Description<
+ [#[
+ <p>The C Perl-Powered Pre-Processor</p><p>Changes for 0.001_02 - 2023-09-15</p><ul><li>Fix various glaring documentation mistakes</li>
+ <li>List some ideas for future features</li>
+ <li>Remove debugging output</li>
+ <li>"--help" for command line</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-15 07:52:25
+ Link: https://metacpan.org/release/OODLER/OpenMP-Simple-0.0.2-TRIAL
+ Title: OpenMP-Simple-0.0.2-TRIAL
+ <Description<
+ [#[
+ Provides some DWIM helpers for using OpenMP via Inline::C.
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-15 07:42:08
+ Link: https://metacpan.org/release/TORBIAK/App-Git-Autofixup-0.004001
+ Title: App-Git-Autofixup-0.004001
+ <Description<
+ [#[
+ create fixup commits for topic branches
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-15 07:24:13
+ Link: https://metacpan.org/release/CORION/HTTP-Request-FromCurl-0.52
+ Title: HTTP-Request-FromCurl-0.52
+ <Description<
+ [#[
+ <p>create a HTTP::Request from a curl command line</p><p>Changes for 0.52 - 2023-09-15</p><ul><li>Switch test suite to Test2::V0</li>
+ <li>Suppress trivial Content-Length headers in ->as_curl</li>
+ <li>--disable is a boolean option</li>
+ <li>Add support for --json</li>
+ <li>Add support for --max-filesize The behaviour is slightly different from cURL. --max-filesize looks at the size of the body, not at the Content-Length header.</li>
+ <li>Add support for --interface (only IP addresses, not interface names)</li>
+ <li>Fix Mojolicious snippet generation with local address</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-15 07:15:14
+ Link: https://metacpan.org/release/NERDVANA/CodeGen-Cpppp-0.001_01
+ Title: CodeGen-Cpppp-0.001_01
+ <Description<
+ [#[
+ <p>The C Perl-Powered Pre-Processor</p><p>Changes for 0.001_01 - 2023-09-15</p><ul><li>Basic intermingling of perl variables in C code</li>
+ <li>Arbitrary perl in '##' directives</li>
+ <li>Magic indent adjustment after variable substitution</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-15 00:18:28
+ Link: https://metacpan.org/release/BENNIE/VMware-vCloud-2.404
+ Title: VMware-vCloud-2.404
+ <Description<
+ [#[
+ <p>VMware vCloud API</p><p>Changes for 2.404 - 2023-09-14</p><ul><li>Added: POD test</li>
+ <li>Improved: 'use warnings' on all modules</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-15 00:05:37
+ Link: https://metacpan.org/release/PERLANCAR/Dist-Zilla-Plugin-Acme-CPANModules-Blacklist-0.002
+ Title: Dist-Zilla-Plugin-Acme-CPANModules-Blacklist-0.002
+ <Description<
+ [#[
+ <p>Blacklist prereqs using an Acme::CPANModules module</p><p>Changes for 0.002 - 2023-07-09</p><ul><li>No functional changes.</li>
+ <li>Remove the usage of smartmatch.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-14 21:56:09
+ Link: https://metacpan.org/release/TIMLEGGE/Crypt-OpenSSL-AES-0.07
+ Title: Crypt-OpenSSL-AES-0.07
+ <Description<
+ [#[
+ <p>A Perl wrapper around OpenSSL's AES library</p><p>Changes for 0.07</p><ul><li>Significant updates since 0.02</li>
+ <li>Detailed Changes</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-14 21:45:52
+ Link: https://metacpan.org/release/TORBIAK/App-Git-Autofixup-0.004
+ Title: App-Git-Autofixup-0.004
+ <Description<
+ [#[
+ create fixup commits for topic branches
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-14 20:00:02
+ Link: https://metacpan.org/release/OKURZ/Mojo-IOLoop-ReadWriteProcess-0.34
+ Title: Mojo-IOLoop-ReadWriteProcess-0.34
+ <Description<
+ [#[
+ <p>Execute external programs or internal code blocks as separate process.</p><p>Changes for 0.34 - 2023-09-14T19:55:18Z</p><ul><li>Adapt to deprecation of spurt in upstream Mojolicious</li>
+ <li>Make git work in github workflow</li>
+ <li>Turn warnings "Sleeping inside locked section" into notes</li>
+ <li>Avoid warnings about using undefined value as file handle</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-14 17:55:34
+ Link: https://metacpan.org/release/HANJE/Tk-YANoteBook-0.04
+ Title: Tk-YANoteBook-0.04
+ <Description<
+ [#[
+ <p>Yet another NoteBook widget</p><p>Changes for 0.04</p><ul><li>tidied up documentation. gave the NameTab widget it's own pm file added -autoupdate option added -onlyselect option addid -rigid option added -unselecttabcall option fixed some minor bugs</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-14 16:43:48
+ Link: https://metacpan.org/release/MTYRRELL/Config-Structured-2.004
+ Title: Config-Structured-2.004
+ <Description<
+ [#[
+ <p>Provides generalized and structured configuration value access</p><p>Changes for 2.004</p><ul><li>Switched to Perl6::Junction to avoid smartmatch warnings from Syntax::Keyword::Junction</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-14 12:22:38
+ Link: https://metacpan.org/release/ABRAXXA/Net-Silverpeak-Orchestrator-0.008000
+ Title: Net-Silverpeak-Orchestrator-0.008000
+ <Description<
+ [#[
+ <p>Silverpeak Orchestrator REST API client library</p><p>Changes for 0.008000 - 2023-09-14T14:21:59+02:00</p><ul><li>enable TLS verification by default by requiring HTTP::Tiny 0.088</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-14 08:33:57
+ Link: https://metacpan.org/release/SHLOMIF/XML-GrammarBase-0.2.10
+ Title: XML-GrammarBase-0.2.10
+ <Description<
+ [#[
+ <p>Provide roles and base classes for processors of specialized XML grammars.</p><p>Changes for 0.2.10 - 2023-09-14</p><ul><li>Better compatibility with bleadperl</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-14 08:01:08
+ Link: https://metacpan.org/release/SYP/Net-Curl-0.54_2
+ Title: Net-Curl-0.54_2
+ <Description<
+ [#[
+ Perl interface for libcurl
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-14 03:02:53
+ Link: https://metacpan.org/release/ANATOFUZ/Teng-0.34
+ Title: Teng-0.34
+ <Description<
+ [#[
+ <p>very simple DBI wrapper/ORMapper</p><p>Changes for 0.34 - 2023-09-14T03:02:36Z</p><ul><li>[IMPORTANT] change the minimum supported perl version to 5.16 (#165)</li>
+ <li>FIX: Don't update when set column from null to null (#164 thanks hitode909)</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-14 02:18:56
+ Link: https://metacpan.org/release/KIMOTO/SPVM-0.989042
+ Title: SPVM-0.989042
+ <Description<
+ [#[
+ <p>SPVM Language</p><p>Changes for 0.989042 - 2023-09-12</p><ul><li>Incompatible Changes</li>
+ <li>New Features</li>
+ <li>Document Improvement</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-14 00:05:27
+ Link: https://metacpan.org/release/PERLANCAR/Perinci-To-Doc-0.881
+ Title: Perinci-To-Doc-0.881
+ <Description<
+ [#[
+ <p>Convert Rinci metadata to documentation</p><p>Changes for 0.881 - 2023-07-09</p><ul><li>No functional changes.</li>
+ <li>Remove usage of smartmatch.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 23:57:14
+ Link: https://metacpan.org/release/MARIOROY/MCE-Shared-1.886
+ Title: MCE-Shared-1.886
+ <Description<
+ [#[
+ <p>MCE extension for sharing data supporting threads and processes</p><p>Changes for 1.886</p><ul><li>Add Android support. This required moving MCE::Shared::Base::Common out of MCE::Shared::Base to separate file MCE::Shared::Common.</li>
+ <li>Bump MCE dependency to 1.889.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 23:37:02
+ Link: https://metacpan.org/release/MARIOROY/MCE-1.889
+ Title: MCE-1.889
+ <Description<
+ [#[
+ <p>Many-Core Engine for Perl providing parallel processing capabilities</p><p>Changes for 1.889</p><ul><li>Add Android support. Thank you, Dimitrios Kechagias.</li>
+ <li>Revert defer signal-handling in MCE::Channel (send2 method).</li>
+ <li>Improve mutex synchronize (aka enter) with guard capability. Thank you, José JoaquÃn Atria.</li>
+ <li>Fix mutex re-entrant lock on the Windows platform.</li>
+ <li>Add mutex guard_lock method.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 23:35:35
+ Link: https://metacpan.org/release/MARIOROY/Mutex-1.011
+ Title: Mutex-1.011
+ <Description<
+ [#[
+ <p>Various locking implementations supporting processes and threads</p><p>Changes for 1.011</p><ul><li>Bump version.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 22:40:32
+ Link: https://metacpan.org/release/EXODIST/Test2-Suite-0.000156
+ Title: Test2-Suite-0.000156
+ <Description<
+ [#[
+ <p>Distribution with a rich set of tools built upon the Test2 framework.</p><p>Changes for 0.000156 - 2023-09-13T15:11:52-07:00</p><ul><li>Fix typo in POD for Test2::Util::Importer</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 21:57:38
+ Link: https://metacpan.org/release/PEVANS/Device-AVR-UPDI-0.14
+ Title: Device-AVR-UPDI-0.14
+ <Description<
+ [#[
+ <p>interact with an AVR microcontroller over UPDI</p><p>Changes for 0.14 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 21:30:55
+ Link: https://metacpan.org/release/AJNN/Mac-Finder-Tags-0.02
+ Title: Mac-Finder-Tags-0.02
+ <Description<
+ [#[
+ <p>Access macOS file tags (aka Finder labels)</p><p>Changes for 0.02 - 2023-09-13</p><ul><li>Avoid syntax that causes warnings in Object::Pad 0.801.</li>
+ <li>Tests no longer fail for unexpected warnings, except during author testing.</li>
+ <li>Drop Devel::CheckOS prerequisite (by bundling it).</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 21:00:16
+ Link: https://metacpan.org/release/MICHIELB/GD-Barcode-2.00
+ Title: GD-Barcode-2.00
+ <Description<
+ [#[
+ <p>Create barcode image with GD</p><p>Changes for 2.00 - 2023-09-13</p><ul><li>'Production' release, no changes to 1.99_03</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 20:58:49
+ Link: https://metacpan.org/release/BENNIE/VMware-vCloud-2.403
+ Title: VMware-vCloud-2.403
+ <Description<
+ [#[
+ <p>VMware vCloud API</p><p>Changes for 2.403 - 2023-09-13</p><ul><li>Added: POD test</li>
+ <li>Improved: 'use warnings' on all modules</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 20:44:39
+ Link: https://metacpan.org/release/RKAPL/EAI-Wrap-0.3
+ Title: EAI-Wrap-0.3
+ <Description<
+ [#[
+ framework for easy creation of Enterprise Application Integration tasks
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 20:27:57
+ Link: https://metacpan.org/release/MIYAGAWA/Starman-0.4017
+ Title: Starman-0.4017
+ <Description<
+ [#[
+ <p>High-performance preforking PSGI/Plack web server</p><p>Changes for 0.4017 - 2023-09-13T13:27:02Z</p><ul><li>Handle EINTR when doing sysread calls (Rob Mueller) #148</li>
+ <li>Requires perl 5.14</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 17:41:55
+ Link: https://metacpan.org/release/EXODIST/Term-Table-0.017
+ Title: Term-Table-0.017
+ <Description<
+ [#[
+ <p>Format a header and rows into a table</p><p>Changes for 0.017 - 2023-09-13T10:41:08-07:00</p><ul><li>Remove 'Importer' dependency</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 16:02:42
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-TSL256x-0.09
+ Title: Device-Chip-TSL256x-0.09
+ <Description<
+ [#[
+ <p>chip driver for TSL256x</p><p>Changes for 0.09 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 16:01:19
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-TCS3472x-0.05
+ Title: Device-Chip-TCS3472x-0.05
+ <Description<
+ [#[
+ <p>chip driver for TCS3472x-family</p><p>Changes for 0.05 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 16:01:04
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-SSD1306-0.14
+ Title: Device-Chip-SSD1306-0.14
+ <Description<
+ [#[
+ <p>chip driver for monochrome OLED modules</p><p>Changes for 0.14 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:59:38
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-Si5351-0.02
+ Title: Device-Chip-Si5351-0.02
+ <Description<
+ [#[
+ <p>chip driver for Si5351</p><p>Changes for 0.02 - 2023-09-13</p><ul><li>CHANGES</li>
+ <li>BUGFIXES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:58:10
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-SDCard-0.04
+ Title: Device-Chip-SDCard-0.04
+ <Description<
+ [#[
+ <p>chip driver for SD and MMC cards</p><p>Changes for 0.04 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:56:44
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-PCF8574-0.06
+ Title: Device-Chip-PCF8574-0.06
+ <Description<
+ [#[
+ <p>chip driver for a PCF8574 or PCA8574</p><p>Changes for 0.06 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:56:33
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-PCF8563-0.04
+ Title: Device-Chip-PCF8563-0.04
+ <Description<
+ [#[
+ <p>chip driver for a PCF8563</p><p>Changes for 0.04 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:54:59
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-OPT3001-0.03
+ Title: Device-Chip-OPT3001-0.03
+ <Description<
+ [#[
+ <p>chip driver for OPT3001</p><p>Changes for 0.03 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:53:40
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-nRF24L01P-0.08
+ Title: Device-Chip-nRF24L01P-0.08
+ <Description<
+ [#[
+ <p>chip driver for a nRF24L01+</p><p>Changes for 0.08 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:52:21
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-NoritakeGU_D-0.06
+ Title: Device-Chip-NoritakeGU_D-0.06
+ <Description<
+ [#[
+ <p>chip driver for Noritake GU-D display modules</p><p>Changes for 0.06 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:50:58
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-MPL3115A2-0.13
+ Title: Device-Chip-MPL3115A2-0.13
+ <Description<
+ [#[
+ <p>chip driver for a MPL3115A2</p><p>Changes for 0.13 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:49:37
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-MCP23x17-0.07
+ Title: Device-Chip-MCP23x17-0.07
+ <Description<
+ [#[
+ <p>chip driver for the MCP23x17 family</p><p>Changes for 0.07 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:48:18
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-MAX7219-0.09
+ Title: Device-Chip-MAX7219-0.09
+ <Description<
+ [#[
+ <p>chip driver for a MAX7219</p><p>Changes for 0.09 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:47:00
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-MAX44009-0.05
+ Title: Device-Chip-MAX44009-0.05
+ <Description<
+ [#[
+ <p>chip driver for MAX44009</p><p>Changes for 0.05 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:45:41
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-INA219-0.10
+ Title: Device-Chip-INA219-0.10
+ <Description<
+ [#[
+ <p>chip driver for an INA219</p><p>Changes for 0.10 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:44:22
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-HTU21D-0.10
+ Title: Device-Chip-HTU21D-0.10
+ <Description<
+ [#[
+ <p>chip driver for HTU21D</p><p>Changes for 0.10 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:43:03
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-DS1307-0.08
+ Title: Device-Chip-DS1307-0.08
+ <Description<
+ [#[
+ <p>chip driver for a DS1307</p><p>Changes for 0.08 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:41:44
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-CCS811-0.03
+ Title: Device-Chip-CCS811-0.03
+ <Description<
+ [#[
+ <p>chip driver for CCS811</p><p>Changes for 0.03 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:40:25
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-CC1101-0.09
+ Title: Device-Chip-CC1101-0.09
+ <Description<
+ [#[
+ <p>chip driver for a CC1101</p><p>Changes for 0.09 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:38:58
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-BV4243-0.04
+ Title: Device-Chip-BV4243-0.04
+ <Description<
+ [#[
+ <p>chip driver for a BV4243</p><p>Changes for 0.04 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:37:36
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-BNO055-0.04
+ Title: Device-Chip-BNO055-0.04
+ <Description<
+ [#[
+ <p>chip driver for BNO055</p><p>Changes for 0.04 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:36:09
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-BME280-0.06
+ Title: Device-Chip-BME280-0.06
+ <Description<
+ [#[
+ <p>chip driver for BME280</p><p>Changes for 0.06 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:33:22
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-AVR_HVSP-0.07
+ Title: Device-Chip-AVR_HVSP-0.07
+ <Description<
+ [#[
+ <p>high-voltage serial programming for AVR chips</p><p>Changes for 0.07 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:26:50
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-AS3935-0.04
+ Title: Device-Chip-AS3935-0.04
+ <Description<
+ [#[
+ <p>chip driver for AS3935</p><p>Changes for 0.04 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:25:06
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-AnalogConverters-0.15
+ Title: Device-Chip-AnalogConverters-0.15
+ <Description<
+ [#[
+ <p>a collection of chip drivers</p><p>Changes for 0.15 - 2023-08-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:23:40
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-AD9833-0.05
+ Title: Device-Chip-AD9833-0.05
+ <Description<
+ [#[
+ <p>chip driver for AD9833</p><p>Changes for 0.05 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 14:58:27
+ Link: https://metacpan.org/release/YANICK/Dist-Zilla-Plugin-CoalescePod-1.0.0
+ Title: Dist-Zilla-Plugin-CoalescePod-1.0.0
+ <Description<
+ [#[
+ <p>merge .pod files into their .pm counterparts</p><p>Changes for 1.0.0 - 2023-09-13</p><ul><li>API CHANGES</li>
+ <li>STATISTICS</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 14:57:01
+ Link: https://metacpan.org/release/YANICK/Dist-Zilla-Plugin-CoalescePod-0.3.1
+ Title: Dist-Zilla-Plugin-CoalescePod-0.3.1
+ <Description<
+ [#[
+ <p>merge .pod files into their .pm counterparts</p><p>Changes for 0.3.1 - 2023-09-13</p><ul><li>STATISTICS</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 14:10:21
+ Link: https://metacpan.org/release/PEVANS/App-sdview-Output-Tickit-0.03
+ Title: App-sdview-Output-Tickit-0.03
+ <Description<
+ [#[
+ <p>interactive terminal-based viewer for App::sdview</p><p>Changes for 0.03 - 2023-09-13</p><ul><li>CHANGES</li>
+ <li>BUGFIXES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 11:25:40
+ Link: https://metacpan.org/release/AWNCORP/Venus-4.11
+ Title: Venus-4.11
+ <Description<
+ [#[
+ <p>OO Library for Perl 5</p><p>Changes for 4.11 - 2023-09-13</p><ul><li>[feature] Implement Venus::Assert#includes</li>
+ <li>[feature] Implement Venus::Future</li>
+ <li>[feature] Refactor Venus::Assert, Implement Venus::{Coercion,Constraint}</li>
+ <li>[feature] Implement Venus::Space#{patch,patched,unpatch}</li>
+ <li>[feature] Implement Venus::Sealed</li>
+ <li>[feature] Implement Venus::Atom</li>
+ <li>[feature] Implement Venus::Enum</li>
+ <li>[feature] Implement Venus::Role::Superable</li>
+ <li>[feature] Implement Venus::Role::Patchable</li>
+ <li>[feature] Implement Venus#clone</li>
+ <li>[feature] Implement Venus::Process#future</li>
+ <li>[feature] Implement Venus::Future#wait</li>
+ <li>[update] Refactor Venus::Test</li>
+ <li>[update] Add test and documentation for Venus::Process#is_dyadic</li>
+ <li>[update] Update Venus::Process#await, auto-reap processes</li>
+ <li>[update] Research CPANTS issue with Venus::Process</li>
+ <li>[update] Update Venus::Process, prevent PPID in dyads</li>
+ <li>[update] Use Venus::Check types in all signatures</li>
+ <li>[update] Update Venus#async to return Venus::Future</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 11:00:19
+ Link: https://metacpan.org/release/JBAIER/Pass-OTP-1.6
+ Title: Pass-OTP-1.6
+ <Description<
+ [#[
+ <p>Perl implementation of HOTP / TOTP algorithms</p><p>Changes for 1.6 - 2023-09-13</p><ul><li>fix SHA384 and SHA512 blocksize (#1)</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 10:35:02
+ Link: https://metacpan.org/release/BOD/Image-Square-0.01_4
+ Title: Image-Square-0.01_4
+ <Description<
+ [#[
+ <p>Crop and resize an image to create a square image</p><p>Changes for 0.01_4</p><ul><li>Tests still fail on different builds of GD. Now using PNG as input image and native GD format for output.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 09:13:52
+ Link: https://metacpan.org/release/MRUEDA/Convert-Pheno-0.13
+ Title: Convert-Pheno-0.13
+ <Description<
+ [#[
+ <p>A module to interconvert common data models for phenotypic data</p><p>Changes for 0.13 - 2023-09-12T00:00:00Z</p><ul><li>Pushing new version after passing all tests</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 09:12:25
+ Link: https://metacpan.org/release/TONYC/Imager-zxing-1.001
+ Title: Imager-zxing-1.001
+ <Description<
+ [#[
+ <p>Barcode scanning with libzxing-cpp</p><p>Changes for 1.001</p><ul><li>re-work std::string handling to use the typemap</li>
+ <li>fix "decoder" -> "decode" in the SYNOPSIS</li>
+ <li>support all Imager image layouts</li>
+ <li>require a recent enough ExtUtils::CppGuess and set the required C++ standard</li>
+ <li>allow the zxing-cpp package name for pkg-config, which seems to be what packagers used before upstream decided on "zxing.pc". https://github.com/tonycoz/imager-zxing/issues/1</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 05:55:56
+ Link: https://metacpan.org/release/KIMOTO/SPVM-Sys-0.491
+ Title: SPVM-Sys-0.491
+ <Description<
+ [#[
+ <p>System Calls for File IO, User, Process, Signal, Socket</p><p>Changes for 0.491 - 2023-09-13</p><ul><li>New Features</li>
+ <li>Incompatible Changes</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 04:12:50
+ Link: https://metacpan.org/release/GRYPHON/Log-Dispatch-Email-Mailer-1.13
+ Title: Log-Dispatch-Email-Mailer-1.13
+ <Description<
+ [#[
+ <p>Log::Dispatch::Email subclass that sends mail using Email::Mailer</p><p>Changes for 1.13 - 2023-09-12T21:12:32-07:00</p><ul><li>Require exact v1.23 (resolves issue #5)</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 04:11:27
+ Link: https://metacpan.org/release/GRYPHON/exact-me-1.05
+ Title: exact-me-1.05
+ <Description<
+ [#[
+ <p>Original program path locations extension for exact</p><p>Changes for 1.05 - 2023-09-12T21:10:17-07:00</p><ul><li>Remove redundant strict (since it's provided by exact)</li>
+ <li>New import signature change required by exact v1.23</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 04:10:01
+ Link: https://metacpan.org/release/GRYPHON/exact-lib-1.04
+ Title: exact-lib-1.04
+ <Description<
+ [#[
+ <p>Compile-time @INC manipulation extension for exact</p><p>Changes for 1.04 - 2023-09-12T21:09:28-07:00</p><ul><li>Remove redundant strict (since it's provided by exact)</li>
+ <li>New import signature change required by exact v1.23</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 04:09:57
+ Link: https://metacpan.org/release/GRYPHON/exact-fun-1.01
+ Title: exact-fun-1.01
+ <Description<
+ [#[
+ <p>Functions and methods with parameter lists for exact</p><p>Changes for 1.01 - 2023-09-12T21:08:36-07:00</p><ul><li>Use Import::Into instead of eval to inject/import</li>
+ <li>New import signature change required by exact v1.23</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 04:08:39
+ Link: https://metacpan.org/release/GRYPHON/exact-conf-1.08
+ Title: exact-conf-1.08
+ <Description<
+ [#[
+ <p>Cascading merged application configuration extension for exact</p><p>Changes for 1.08 - 2023-09-12T21:07:37-07:00</p><ul><li>Remove redundant strict (since it's provided by exact)</li>
+ <li>New import signature change required by exact v1.23</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 04:07:18
+ Link: https://metacpan.org/release/GRYPHON/exact-cli-1.07
+ Title: exact-cli-1.07
+ <Description<
+ [#[
+ <p>Command-line interface helper utilities extension for exact</p><p>Changes for 1.07 - 2023-09-12T21:06:47-07:00</p><ul><li>Remove redundant strict (since it's provided by exact)</li>
+ <li>New import signature change required by exact v1.23</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 04:05:52
+ Link: https://metacpan.org/release/GRYPHON/exact-class-1.19
+ Title: exact-class-1.19
+ <Description<
+ [#[
+ <p>Simple class interface extension for exact</p><p>Changes for 1.19 - 2023-09-12T21:05:22-07:00</p><ul><li>New import signature change required by exact v1.23</li>
+ <li>Use Import::Into instead of eval to inject code</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 01:04:01
+ Link: https://metacpan.org/release/MBRADSHAW/Mail-BIMI-3.20230913
+ Title: Mail-BIMI-3.20230913
+ <Description<
+ [#[
+ <p>BIMI object</p><p>Changes for 3.20230913 - 2023-09-13</p><ul><li>Add policy.mark-type to Authentication-Results</li>
+ <li>Add policy.experimental to Authentication-Results</li>
+ <li>Add options to limit which mark types a MBP accepts</li>
+ <li>Add options to limit acceptance of experimental certificates</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 00:06:02
+ Link: https://metacpan.org/release/PERLANCAR/App-rimetadb-0.226
+ Title: App-rimetadb-0.226
+ <Description<
+ [#[
+ <p>Manage a Rinci metadata database</p><p>Changes for 0.226 - 2023-07-09</p><ul><li>No functional changes.</li>
+ <li>Remove the usage of smartmatch.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 23:33:11
+ Link: https://metacpan.org/release/DRCLAW/constant-more-v0.3.0
+ Title: constant-more-v0.3.0
+ <Description<
+ [#[
+ <p>Constants and Enumerations. Assign constant values from the command line</p><p>Changes for v0.3.0 - 2023-09-13</p><ul><li>Features</li>
+ <li>Tests</li>
+ <li>POD</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 23:07:51
+ Link: https://metacpan.org/release/GRYPHON/exact-1.23
+ Title: exact-1.23
+ <Description<
+ [#[
+ <p>Perl pseudo pragma to enable strict, warnings, features, mro, filehandle methods</p><p>Changes for 1.23 - 2023-09-12T16:06:03-07:00</p><ul><li>Improve/fix import of packages into other packages (resolves issue #4)</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 22:14:53
+ Link: https://metacpan.org/release/JIMAVERA/ODF-MailMerge-1.000
+ Title: ODF-MailMerge-1.000
+ <Description<
+ [#[
+ <p>"Mail Merge" or just substitute tokens in ODF documents</p><p>Changes for 1.000</p><ul><li>ODF::MailMerge::Engine->new positional args eliminated; now use proto_elt => $table # specify the object directly context => $context, proto_tag => "tagstring" # search for it Modifier :die ("Delete If Empty") replaces :delempty</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 21:49:07
+ Link: https://metacpan.org/release/SHANCOCK/Perl-Tidy-20230912
+ Title: Perl-Tidy-20230912
+ <Description<
+ [#[
+ indent and reformat perl scripts
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 21:45:10
+ Link: https://metacpan.org/release/BOD/Image-Square-0.01_3
+ Title: Image-Square-0.01_3
+ <Description<
+ [#[
+ Crop and resize an image to create a square image
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 19:38:33
+ Link: https://metacpan.org/release/TURNERJW/StreamFinder-2.19
+ Title: StreamFinder-2.19
+ <Description<
+ [#[
+ <p>Fetch actual raw streamable URLs from various radio-station, video & podcast websites.</p><p>Changes for 2.19 - 2023-09-12</p><ul><li>StreamFinder::Youtube - 1) Fix failure to fetch artist, icon, etc. sometimes on embedded IFRAME urls (slight site changes) and first episode from some channels. 2) Add -youtube-site argument to specify a different default youtube site (default https://www.youtube.com). 3) Add ability to parse youtube channel URLs containing an at-sign, ie.: https://www.youtube.com/@channelID.</li>
+ <li>StreamFinder::Subsplash - Restore as EXPERIMENTAL, as this site seems to now work again, at least for audio streams on some sites.</li>
+ <li>StreamFinder::Anystream - doc. touchups.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 19:00:33
+ Link: https://metacpan.org/release/AWNCORP/Venus-4.10
+ Title: Venus-4.10
+ <Description<
+ [#[
+ <p>OO Library for Perl 5</p><p>Changes for 4.10 - 2023-09-12</p><ul><li>[feature] Implement Venus::Assert#includes</li>
+ <li>[feature] Implement Venus::Future</li>
+ <li>[feature] Refactor Venus::Assert, Implement Venus::{Coercion,Constraint}</li>
+ <li>[feature] Implement Venus::Space#{patch,patched,unpatch}</li>
+ <li>[feature] Implement Venus::Sealed</li>
+ <li>[feature] Implement Venus::Atom</li>
+ <li>[feature] Implement Venus::Enum</li>
+ <li>[feature] Implement Venus::Role::Superable</li>
+ <li>[feature] Implement Venus::Role::Patchable</li>
+ <li>[feature] Implement Venus#clone</li>
+ <li>[feature] Implement Venus::Process#future</li>
+ <li>[feature] Implement Venus::Future#wait</li>
+ <li>[update] Refactor Venus::Test</li>
+ <li>[update] Add test and documentation for Venus::Process#is_dyadic</li>
+ <li>[update] Update Venus::Process#await, auto-reap processes</li>
+ <li>[update] Research CPANTS issue with Venus::Process</li>
+ <li>[update] Update Venus::Process, prevent PPID in dyads</li>
+ <li>[update] Use Venus::Check types in all signatures</li>
+ <li>[update] Update Venus#async to return Venus::Future</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 17:09:39
+ Link: https://metacpan.org/release/DERIV/Net-Async-Blockchain-0.003
+ Title: Net-Async-Blockchain-0.003
+ <Description<
+ [#[
+ <p>base for blockchain subscription clients.</p><p>Changes for 0.003 - 2023-09-12T17:08:09+00:00</p><ul><li>Improvements</li>
+ <li>Breaking changes</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 14:47:38
+ Link: https://metacpan.org/release/OALDERS/Open-This-0.000033
+ Title: Open-This-0.000033
+ <Description<
+ [#[
+ <p>Try to Do the Right Thing when opening files</p><p>Changes for 0.000033 - 2023-09-12T14:46:08Z</p><ul><li>Add support for IntellJ IDEA, VSCode, VSCodium and more. Also fix typo (GH#51) (mcneb10)</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 13:50:33
+ Link: https://metacpan.org/release/NLNETLABS/Net-DNS-SEC-1.22
+ Title: Net-DNS-SEC-1.22
+ <Description<
+ [#[
+ DNSSEC extensions to Net::DNS
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 09:35:41
+ Link: https://metacpan.org/release/MIKIHOSHI/WebService-Mailgun-0.16
+ Title: WebService-Mailgun-0.16
+ <Description<
+ [#[
+ <p>API client for Mailgun (https://mailgun.com/)</p><p>Changes for 0.16 - 2023-09-12T09:33:42Z</p><ul><li>fix document</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 09:29:10
+ Link: https://metacpan.org/release/MIKIHOSHI/WebService-Mailgun-0.15.1
+ Title: WebService-Mailgun-0.15.1
+ <Description<
+ [#[
+ <p>API client for Mailgun (https://mailgun.com/)</p><p>Changes for 0.15.1 - 2023-09-12T09:27:19Z</p><ul><li>fix document</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 09:16:10
+ Link: https://metacpan.org/release/MRUEDA/Convert-Pheno-0.12_4
+ Title: Convert-Pheno-0.12_4
+ <Description<
+ [#[
+ A module to interconvert common data models for phenotypic data
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 08:44:03
+ Link: https://metacpan.org/release/LICHTKIND/Graphics-Toolkit-Color-1.61
+ Title: Graphics-Toolkit-Color-1.61
+ <Description<
+ [#[
+ <p>color palette creation helper</p><p>Changes for 1.61 - 2023-09-12</p><ul><li>= fix tests</li>
+ <li>+ renamed complementary method => complement</li>
+ <li>- deprecated complementary, will be removed at 2.0</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 06:33:21
+ Link: https://metacpan.org/release/MERKYS/Graph-SSSR-0.1.0
+ Title: Graph-SSSR-0.1.0
+ <Description<
+ [#[
+ <p>Find Smallest Set of Smallest Rings in graphs</p><p>Changes for 0.1.0 - 2022-12-15</p><ul><li>Initial release.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 03:59:54
+ Link: https://metacpan.org/release/DJZORT/Net-Proxmox-VE-0.38
+ Title: Net-Proxmox-VE-0.38
+ <Description<
+ [#[
+ <p>Pure perl API for Proxmox virtualisation</p><p>Changes for 0.38 - 2023-09-11</p><ul><li>fix/use correct parameter name for user in tests thanks to MartijnLivaart</li>
+ <li>Feat/check new arguments thanks to MartijnLivaart</li>
+ <li>Fix/test access directory thanks to MartijnLivaart via GH#27</li>
+ <li>feat: check if debug parameter propagates from new() thanks to MartijnLivaart via GH#29</li>
+ <li>Pod corrections thanks to poptix via GH#31</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ >Brew>
+>>
--- /dev/null
+###
+# CNFDateTime objects provide conversions from script to high precision time function not inbuild into perl interpreter.
+# They are lightly initilized, compared to using DateTime directly, so this is not merely a wrapper around DateTime.
+#
+package CNFDateTime;
+use strict;
+use warnings;
+use DateTime;
+use DateTime::Format::DateParse;
+use Time::HiRes qw(time usleep);
+use feature 'signatures';
+
+use constant{
+ FORMAT => '%Y-%m-%d %H:%M:%S',
+ FORMAT_NANO => '%Y-%m-%d %H:%M:%S.%3N %Z',
+ FORMAT_SCHLONG => '%A, %d %B %Y %H:%M:%S %Z',
+ FORMAT_MEDIUM => '%d %b %Y %H:%M:%S',
+ DEFAULT_TIME_ZONE => 'UTC'
+};
+
+sub new {
+ my $class = shift;
+ my %settings;
+ if(ref($_[0]) eq ''){
+ %settings = @_;
+ }else{
+ %settings = %{$_[0]}
+ }
+ $settings{epoch} = time if !$settings{epoch};
+ $settings{TZ} = DEFAULT_TIME_ZONE if !$settings{TZ};
+ return bless \%settings, $class
+}
+
+sub datetime($self) {
+ return $self->{datetime} if exists $self->{datetime};
+ $self->{epoch} = time if not defined $self->{epoch};
+ my $dt = DateTime->from_epoch(epoch=>$self->{epoch},time_zone=>$self->{TZ});
+ $self->{datetime} = $dt;
+ return $dt
+}
+sub toTimestamp($self) {
+ return $self->{timestamp} if exists $self->{timestamp};
+ usleep(1_028_69);
+ $self->{timestamp} = $self->datetime() -> strftime(FORMAT_NANO)
+}
+sub toTimestampShort($self) {
+ return $self->{timestamp} if exists $self->{timestamp};
+ usleep(1_028_69);
+ $self->{timestamp} = $self->datetime() -> strftime(FORMAT)
+}
+sub toSchlong($self){
+ return $self->{long} if exists $self->{long};
+ $self->{long} = $self->datetime() -> strftime(FORMAT_SCHLONG)
+}
+sub _toCNFDate ($formated, $timezone) {
+ my $dt = DateTime::Format::DateParse->parse_datetime($formated, $timezone);
+ return new('CNFDateTime',{epoch => $dt->epoch, datetime=>$dt, TZ=>$timezone});
+}
+sub _listAvailableCountryCodes(){
+ require DateTime::TimeZone;
+ return DateTime::TimeZone->countries();
+}
+sub _listAvailableTZ($country){
+ require DateTime::TimeZone;
+ return length($country)==2?DateTime::TimeZone->names_in_country( $country ):DateTime::TimeZone->names_in_category( $country );
+}
+
+
+1;
+
+=begin copyright
+Programed by : Will Budic
+EContactHash : 990MWWLWM8C2MI8K (https://github.com/wbudic/EContactHash.md)
+Source : https://github.com/wbudic/PerlCNF.git
+Documentation : Specifications_For_CNF_ReadMe.md
+ This source file is copied and usually placed in a local directory, outside of its repository 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.
+Open Source Code License -> https://github.com/wbudic/PerlCNF/blob/master/ISC_License.md
+=cut copyright
+
+=begin history
+Implementing the DateTime module with local libraries, was always problematic at some stages
+as the Perl build or running environment changes.
+
+It is huge and in minimal form usually delivered with default basic or minimal Perl setups.
+It in full provides the most compressive list of world locales and timezones possibilities.
+This means language translations and many other, formats of date outputs based on the locale expected look.
+
+PerlCNF doesn't need it in reality as has its own fixed format to accept and produce.
+PerlCNF must also support world timezones.
+
+Hence it needs DateTime, and some of its modules to provide its timezone string and convert it back and forth.
+Other, DateTime::Format::DateParse, module itself is small, compared to the DateTime module.
+
+Without proper dev. tools and what to look for, it is very hard to figure out what is going on, that things fail.
+For example at the production site. But not on the development setup.
+
+2023-08-23
+
+On occasions DateTime in the past, since 5 eight years to this day, it would lib error crash the whole Perl running environment.
+Something veryhard to find and correct also to forsure test on various installations.
+For these and other reasons, the PerlCNF datetime format was avoided from being implemented or needed.
+
+However, CNFDateTime in its first inclination attempts again to encapsulate this long time due functionality of requirements.
+Came to life in the final of PerlCNF v.2.9, along with the new PerlCNF instruction DATE, of the release.
+
+TestManager has also now been updated to capture any weird and possible Perl underlying connectors to libraries,
+which are of no concern what so ever to the actual local code being tested.
+
+=cut history
\ No newline at end of file
-#
+###
# Represents a tree node CNF object having children and a parent node if it is not the root.
-# 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 CNFNode;
use strict;
use warnings;
sub script {shift -> {'~'}}
sub priority {shift -> {'^'}}
sub evaluate {shift -> {'&'}}
+###
+# Obtains this nodes all public attributes.
+# What you usually only want.
+###
sub attributes {
my $self = shift;
- my @nodes;
+ my @attributes;
my $regex = PRIVATE_FIELDS();
- foreach(sort keys %$self){
- my $node = $self->{$_};
- if($_ !~ /$regex/){
- $nodes[@nodes] = [$_, $node]
+ foreach (sort keys %$self){;
+ if($_ !~ /^$regex/){
+ $attributes[@attributes] = [$_, $self->{$_}]
+ }
+ }
+ return @attributes;
+}
+###
+# Utility arrays any attributes by list requested.
+# $node-> array('Name','#') will return node 'Name' attribute and value if it has it, onderwise undef for either.
+###
+sub array {
+ my $self = shift;
+ my @attributes = @_;
+ my @arr;
+ foreach my $next(@attributes){
+ my $val = $self -> {$next};
+ if(ref($val) eq 'SCALAR'){
+ $val = $$val;
}
+ $arr[@arr] = $val#'['.$next.':'.$val.']';
}
- return @nodes;
+ return @arr;
}
sub nodes {
my $self = shift;
}
return ();
}
-
+###
+# Add another CNFNode to this one, to become a its parent.
+# Returns $self so you can perl them, if you want..
+##
+sub add {
+ my ($self, $node, @nodes) = @_;
+ my $prev = $self->{'@$'};
+ if($prev) {
+ @nodes = @$prev;
+ }else{
+ @nodes = ();
+ }
+ $node->{'@'} = \$self;
+ $nodes[@nodes] = $node;
+ $self -> {'@$'} = \@nodes;
+ return $self;
+}
###
# Convenience method, returns string scalar value dereferenced (a copy) of the property value.
##
if(!$ret && $self->{'@$'}){ #return from subproperties.
my $buf;
my @arr = @{$self->{'@$'}};
- foreach my $node(@arr){
+ foreach my $node(@arr){
$buf .= $node -> val() ."\n";
}
return $buf;
my $meta = meta(SHELL());
sub _evaluate {
- my $value = shift;
+ my $value = shift;
if($value =~ s/($meta)//i){
$value =~ s/^`|`\s*$/""/g; #we strip as a possible monkey copy had now redundant meta in the value.
$value = '`'.$value.'`';
}
- ## no critic BuiltinFunctions::ProhibitStringyEval
+ ## no critic BuiltinFunctions::ProhibitStringyEval
my $ret = eval $value;
- ## use critic
+ ## use critic
if ($ret){
chomp $ret;
return $ret;
#
+sub items(){
+ my $self = shift;
+ return $self -> {'@$'}
+}
+
###
# Search select nodes based on from a path statement.
-# It will always return an array for even a single subproperty.
-# The reason is several subproperties of the same name can be contained by the parent property.
+# It will always return an array for even a single subproperty with a passed path ending with (/*).
+# The reason is several subproperties of the same name can be contained as elements of this node.
# It will return an array of list values with (@@).
-# Or will return an array of its shallow list of child nodes with (@$).
+# Or will return an array of its shallow list of child nodes with (@$).
# Or will return an scalar value of an attribute or an property with (#).
# NOTICE - 20221222 Future versions might provide also for more complex path statements with regular expressions enabled.
###
sub find {
- my ($self, $path, $ret, $prev, $seekArray,$ref)=@_;
- foreach my $name(split(/\//, $path)){
- if(ref($self) eq "ARRAY"){
+ my ($self, $path, $ret, $prev, $seekArray,$ref)=@_; my @arr;
+ foreach my $name(split(/\//, $path)){
+ if( $name eq "*" && @arr){
+ return \@arr # The path instructs to return an array, which is set but return is set to single only found element.
+ }
+ elsif(ref($self) eq "ARRAY"){
if($name eq '#'){
- if(ref($ret) eq "ARRAY"){
+ if(ref($ret) eq "ARRAY"){
next
}else{
return $prev->val()
}elsif($name =~ /\[(\d+)\]/){
$self = $ret = @$ret[$1];
next
-
}else{
- $ret = $prev->{'@$'};
+ $ret = $prev->{'@$'};
}
- }else{
+ }else{
if ($name eq '@@') {
$ret = $self->{'@@'}; $seekArray = 1;
next
}
$ref = ref($ret);
if(!$seekArray && $ref eq 'ARRAY'){ # ret can be an array of parent same name elemenents.
- foreach my$n(@$ret) {
+ foreach my$n(@$ret) {
if ($n->node($name)){
$ret = $n; last
}
}elsif($ref eq "CNFNode" && $seekArray){
$ret = $ret->{$name};
next
- }else{
- $ret = $self->{'@$'} if ! $seekArray; # This will initiate further search in subproperties names.
+ }else{
+ if (!$seekArray){
+ # This will initiate further search in subproperties names.
+ $ret = $self->{'@$'};
+ @arr = ();
+ }
}
}
$ref = ref($ret);
if($ret && $ref eq 'ARRAY'){
my $found = 0;
- my @arr;
- undef $prev;
+ undef $prev;
foreach my $ele(@$ret){
- if($seekArray && exists $ele->{'@$'}){
- foreach my$node(@{$ele->{'@$'}}){
+ if($seekArray && exists $ele->{'@$'}){
+ foreach my$node(@{$ele->{'@$'}}){
if ($node->{'_'} eq $name){
$arr[@arr] = $ele = $node;
- }
+ }
}
if(@arr>1){
$ret = \@arr;
}
}
elsif($name && $ref eq "CNFNode"){
- $ret = $ret -> {$name}
- }
+ $ret = $ret -> {$name}
+ }
}
- return $ret;
+ return !$ret?\@arr:$ret;
}
###
# Similar to find, put simpler node by path routine.
if($ret){
foreach(@$ret){
if ($_->{'_'} eq $path){
- return $_;
+ return $_;
}
}
}
return
}
- foreach my $name(split(/\//, $path)){
+ foreach my $name(split(/\//, $path)){
$ret = $self->{'@$'};
if($ret){
foreach(@$ret){
}
}
}
- return $ret;
+ return $ret;
}
-
###
# Outreached subs list of collected node links found in a property.
my @linked_subs;
###
-# The parsing guts of the CNFNode, that from raw script, recursively creates and tree of nodes from it.
+# The parsing guts of the CNFNode, that from raw script, recursively creates a tree of nodes from it.
###
sub process {
- my ($self, $parser, $script)=@_;
+ my ($self, $parser, $script)=@_;
my ($sub, $val, $isArray,$isShortifeScript,$body) = (undef,0,0,0,"");
my ($tag,$sta,$end)=("","",""); my $meta_shortife = &meta_node_in_shortife;
my ($opening,$closing,$valing)=(0,0,0);
$val = $self->{'#'};
if($val){
$val .= "\n$script";
- }else{
+ }else{
$val = $script;
}
}else{
my @lines = split(/\n/, $script);
foreach my $ln(@lines){
- $ln =~ s/^\s+|\s+$//g;
- if(length ($ln)){
- my $isShortife = ($ln =~ s/($meta_shortife)/""/sexi);
+ $ln =~ s/^\s+|\s+$//g;
+ if(length ($ln)){
+ my $isShortife = ($ln =~ s/($meta_shortife)/""/sexi);
if($ln =~ /^([<>\[\]])(.*)([<>\[\]])$/ && $1 eq $3){
$sta = $1;
$tag = $2;
- $end = $3;
- $isShortifeScript = 1 if $isShortife;
+ $end = $3;
+ $isShortifeScript = 1 if $isShortife;
my $isClosing = ($sta =~ /[>\]]/) ? 1 : 0;
if($tag =~ /^([#\*\@]+)[\[<](.*)[\]>]\/*[#\*\@]+$/){#<- The \/ can sneak in as included in closing tag.
if($1 eq '*'){
my $link = $2;
- my $rval = $self -> obtainLink($parser, $link);
- if($rval){
+ my $rval = $self -> obtainLink($parser, $link);
+ if($rval){
if($opening){
- $body .= qq($ln\n);
+ $body .= qq($ln\n);
}else{
#Is this a child node?
if(exists $self->{'@'}){
if($prev) {
@nodes = @$prev;
}else{
- @nodes = ();
+ @nodes = ();
}
$nodes[@nodes] = CNFNode->new({'_'=>$link, '*'=>$rval,'@' => \$self});
$self->{'@$'} = \@nodes;
else{
#Links scripted in main tree parent are copied main tree attributes.
$self->{$link} = $rval
- }
+ }
}
next
- }else{
+ }else{
if(!$opening){warn "Anon link $link not located with $ln for node ".$self->{'_'}};
}
}elsif($1 eq '@@'){
if($opening==$closing){
- $array[@array] = $2; $val="";
- next
+ $array[@array] = $2; $val="";
+ next
}
- }else{
- $val = $2;
- }
+ }else{
+ $val = $2;
+ }
}elsif($tag =~ /^(.*)[\[<]\/*(.*)[\]>](.*)$/ && $1 eq $3){
if($opening){
$body .= qq($ln\n)
if($prev) {
@nodes = @$prev;
}else{
- @nodes = ();
- }
+ @nodes = ();
+ }
$nodes[@nodes] = $property;
$self->{'@$'} = \@nodes;
}
next
}elsif($isClosing){
$opening--;
- $closing++;
+ $closing++;
}else{
$opening++;
- $closing--;
+ $closing--;
}
- if(!$sub){
+ if(!$sub){
$isArray = $isArray? 0 : 1 if $tag =~ /@@/;
$sub = $tag; $body = "";
next
if($opening==$closing){
if($tag eq '#'){
$body =~ s/\s$//;#cut only one last nl if any.
- if(!$val){
+ if(!$val){
$val = $body;
- }else{
+ }else{
$val .= $body
}
$valing = 0;
$tag ="" if $isClosing
}else{
my $property = CNFNode->new({'_'=>$sub, '@' => \$self});
- my $a = $isArray;
+ my $a = $isArray;
if($isShortifeScript){
- my ($sub,$prev,$cnt_nl,$bck_p);
+ my ($sub,$prev,$cnt_nl,$bck_p);
while ($body =~ / (.*)__+ ([\\\|]|\/*) | (.*)[:=](.*) | (.*)\n/gmx){
- my @sel = @{^CAPTURE};
+ my @sel = @{^CAPTURE};
if(defined $sel[0]){
if ($sel[1]){
my $t = substr $sel[1],0,1;
$sub = $parent; next
}
}
- $sub = CNFNode->new({'_'=>$sel[0], '@' => $parent});
+ $t = $sel[0]; $t=~s/[\s_]*$//g;
+ $sub = CNFNode->new({'_' => $t, '@' => $parent});
my @elements = exists $parent -> {'@$'} ? $parent -> {'@$'} : ();
$elements[@elements] = $sub; $prev = $parent; $cnt_nl = 0;
$parent -> {'@$'} = \@elements;
- }
+ }
}
elsif (defined $sel[2] && defined $sel[3]){
my $attribute = $sel[2]; $attribute =~ s/^\s*|\s*$//g;
elsif (defined $sel[4]){
if ($sel[4] eq ''){
if(++$cnt_nl>1){ #cancel collapse chain and at root of property that is shorted.
- ##$sub = $property ;
+ ##$sub = $property ;
$cnt_nl =0
- }
+ }
next
}elsif($sel[4] !~ /^\s*\#/ ){
my $parent = $sub ? $sub->parent() : $property;
# $sub ="";
}
}
- }#while
+ }#while
$isShortifeScript = 0;
}else{
$property -> process($parser, $body);
$isArray = $a;
if($tag eq '@@'){
$array[@array] = $property;
- if( not exists $property->{'#'} && $body ){
+ if( not exists $property->{'#'} && $body ){
$body =~ s/\n$//; $property->{'#'} = $body
}
}else{
if($prev) {
@nodes = @$prev;
}else{
- @nodes = ();
+ @nodes = ();
}
$nodes[@nodes] = $property;
$self->{'@$'} = \@nodes;
}
undef $sub; $body = $val = "";
}
- next
+ next
}else{
# warn "Tag $sta$tag$sta failed closing -> $body"
- }
- }
+ }
+ }
}elsif($tag eq '#'){
$valing = 1;
}elsif($opening==0 && $isArray){
- $array[@array] = $ln;
- }elsif($opening==0 && $ln =~ /^([<\[])(.+)([<\[])(.*)([>\]])(.+)([>\]])$/ &&
+ $array[@array] = $ln;
+ }elsif($opening==0 && $ln =~ /^([<\[])(.+)([<\[])(.*)([>\]])(.+)([>\]])$/ &&
$1 eq $3 && $5 eq $7 ){ #<- tagged in line
if($2 eq '#') {
if($val){$val = "$val $4"}
- else{$val = $4}
+ else{$val = $4}
}elsif($2 eq '*'){
my $link = $4;
- my $rval = $self -> obtainLink($parser, $link);
+ my $rval = $self -> obtainLink($parser, $link);
if($rval){
#Is this a child node?
if(exists $self->{'@'}){
if($prev) {
@nodes = @$prev;
}else{
- @nodes = ();
+ @nodes = ();
}
$nodes[@nodes] = CNFNode->new({'_'=>$link, '*'=>$rval, '@' => \$self});
$self->{'@$'} = \@nodes;
#Links scripted in main tree parent are copied main tree attributes.
$self->{$link} = $rval
}
- }else{
+ }else{
warn "Anon link $link not located with '$ln' for node ".$self->{'_'} if !$opening;
}
}elsif($2 eq '@@'){
- $array[@array] = CNFNode->new({'_'=>$2, '#'=>$4, '@' => \$self});
+ $array[@array] = CNFNode->new({'_'=>$2, '#'=>$4, '@' => \$self});
}else{
- my $property = CNFNode->new({'_'=>$2, '#'=>$4, '@' => \$self});
+ my $property = CNFNode->new({'_'=>$2, '#'=>$4, '@' => \$self});
my @nodes;
my $prev = $self->{'@$'};
if($prev) {
@nodes = @$prev;
}else{
- @nodes = ();
+ @nodes = ();
}
$nodes[@nodes] = $property;
$self->{'@$'} = \@nodes;
}
- next
+ next
}elsif($val){
$val = $self->{'#'};
if($val){
$self->{'#'} = qq($val\n$ln\n);
- }else{
+ }else{
$self->{'#'} = qq($ln\n);
}
}
my @attr = ($ln =~ m/([\s\w]*?)\s*[=:]\s*(.*)\s*/);
if(@attr>1){
my $n = $attr[0];
- my $v = $attr[1];
+ my $v = $attr[1];
if($v =~ /[<\[]\*[<\[](.*)[]>\]]\*[>\]]/){
- $v = $self-> obtainLink($parser, $1)
- } $v =~ m/^(['"]).*(['"])$/g;
- $v =~ s/^$1|$2$//g if($1 && $2 && $1 eq $2);
- $self->{$n} = $v;
+ $v = $self-> obtainLink($parser, $1)
+ } $v =~ m/^(['"]).*(['"])$/g;
+ $v =~ s/^$1|$2$//g if($1 && $2 && $1 eq $2);
+ $self->{$n} = $v;
next;
- }else{
+ }else{
$val = $ln if $val;
- }
+ }
}
# Very complex rule, allow #comment lines in buffer withing an node value tag, ie [#[..]#]
- $body .= qq($ln\n) #if !$tag && $ln!~/^\#/ || $tag eq '#'
+ $body .= qq($ln\n) #if !$tag && $ln!~/^\#/ || $tag eq '#'
}
elsif($tag eq '#'){
$body .= qq(\n)
}
- }
+ }
}
$self->{'@@'} = \@array if @array;
$self->{'#'} = \$val if $val;
## no critic BuiltinFunctions::ProhibitStringyEval
- no strict 'refs';
+ no strict 'refs';
while(@linked_subs){
- my $entry = pop (@linked_subs);
+ my $entry = pop (@linked_subs);
my $node = $entry->{node};
my $res = &{+$entry->{sub}}($node);
$entry->{node}->{'*'} = \$res;
my ($self,$parser,$link, $ret) = @_;
## no critic BuiltinFunctions::ProhibitStringyEval
no strict 'refs';
- if($link =~/(.*)(\(\.\))$/){
+ if($link =~/(.*)(\(\.\))$/){
push @linked_subs, {node=>$self,link=>$link,sub=>$1};
return 1;
}elsif($link =~/(\w*)::\w+$/){
use Module::Loaded qw(is_loaded);
if(is_loaded($1)){
- $ret = \&{+$link}($self);
+ $ret = \&{+$link}($self);
}
- }
- $ret = $parser->obtainLink($link) if !$ret;
+ }
+ $ret = $parser->obtainLink($link) if !$ret;
return $ret;
}
#
sub validate {
my $self = shift;
- my ($tag,$sta,$end,$lnc,$errors)=("","","",0,0);
+ my ($tag,$sta,$end,$lnc,$errors)=("","","",0,0);
my (@opening,@closing,@singels);
my ($open,$close) = (0,0);
- my @lines = defined $self -> script() ? split(/\n/, $self->script()) :();
+ my @lines = defined $self -> script() ? split(/\n/, $self->script()) :();
foreach my $ln(@lines){
$ln =~ s/^\s+|\s+$//g;
$lnc++;
- #print $ln, "<-","\n";
+ #print $ln, "<-","\n";
if(length ($ln)){
#print $ln, "\n";
if($ln =~ /^([<>\[\]])(.*)([<>\[\]])(.*)/ && $1 eq $3){
$close++;
push @closing, {T=>$tag, idx=>$close, L=>$lnc, N=>($open-$close+1),S=>$sta};
}
- else{
+ else{
push @opening, {T=>$tag, idx=>$open, L=>$lnc, N=>($open-$close),S=>$sta};
$open++;
}
my $c = pop @closing;
if(!$c){
$errors++;
- warn "Error unclosed tag-> [".$o->{T}.'[ @'.$o->{L}
+ warn "Error unclosed tag-> [".$o->{T}.'[ @'.$o->{L}
}
- }
+ }
}else{
my $errors = 0; my $error_tag; my $nesting;
my $cnt = $#opening;
- for my $i (0..$cnt){
- my $o = $opening[$i];
+ for my $i (0..$cnt){
+ my $o = $opening[$i];
my $c = $closing[$cnt - $i];
if($o->{T} ne $c->{T}){
print '['.$o->{T}."[ idx ".$o->{idx}." line ".$o->{L}.
if($o->{T} ne $c->{T}){
my $j = $cnt;
- for ($j = $cnt; $j>-1; $j--){ # TODO 2023-0117 - For now matching by tag name,
+ for ($j = $cnt; $j>-1; $j--){ # TODO 2023-0117 - For now matching by tag name,
$c = $closing[$j];# can't be bothered, to check if this will always be appropriate.
last if $c -> {T} eq $o->{T}
}
- print "\t search [".$o->{T}.'[ idx '.$o->{idx} .' line '.$o->{L}.
+ print "\t search [".$o->{T}.'[ idx '.$o->{idx} .' line '.$o->{L}.
' top found: ]'.$c->{T}."] idx ".$c->{idx}." line ".$c->{N}." loops: $j \n" if $self->{DEBUG};
}else{next}
if($o->{T} ne $c->{T} && $o->{N} ne $c->{N}){
- cluck "Error opening and clossing tags mismatch for ".
+ cluck "Error opening and clossing tags mismatch for ".
_brk($o).' ln: '.$o->{L}.' idx: '.$o->{idx}.
' wrongly matched with '._brk($c).' ln: '.$c->{L}.' idx: '.$c->{idx}."\n";
$errors++;
}
- }
+ }
}
return $errors;
}
# Compare one node with another if is equal in structure.
##
sub equals {
- my ($self, $node, $ref) = @_; $ref = ref($node);
+ my ($self, $node, $ref) = @_; $ref = ref($node);
if (ref($node) eq 'CNFNode'){
my @s = sort keys %$self;
- my @o = sort keys %$node;
+ my @o = sort keys %$node;
my $i=$#o;
foreach (0..$i){
my $n = $o[$i-$_];
if($n eq '~' || $n eq '^'){
- splice @o,$i-$_,1;
- }
+ splice @o,$i-$_,1;
+ }
}
$i=$#s;
foreach (0..$i){
my $n = $s[$i-$_];
if($n eq '~' || $n=~/^CNF_/ || $n=~/^DO_/){
- splice @s,$i-$_,1;
- }
+ splice @s,$i-$_,1;
+ }
}$i=0;
if(@s == @o){
foreach(@s) {
if($_ ne $o[$i++]){
return 0
}
- }
+ }
if($self -> {'@$'} && $node -> {'@$'}){
@s = sort keys @{$self -> {'@$'}};
- @o = sort keys @{$node -> {'@$'}};
+ @o = sort keys @{$node -> {'@$'}};
$i = 0;
foreach(@s) {
if($_ ne $o[$i++]){
return 0
}
- }
+ }
}
return 1;
}
return 0;
}
-1;
\ No newline at end of file
+sub toScript {
+ my($self,$nested,$script)= @_;
+ my($isParent,$tag,$tab); $nested=1 if!$nested; $tab =3*$nested; $tab = ' 'x$tab;
+ if(not exists $self->{'@'}){
+ $script .= "<<".$self->{_}."<TREE>\n"; $isParent = 1;
+ }else{
+ $tag = $self->{_};
+ if($nested){
+ $script .= "$tab<$tag<\n"
+ }else{
+ $script .= "$tab\[$tag\[\n"
+ }
+ }
+ my @attr = $self -> attributes();
+ foreach (@attr){
+ if($nested){
+ if(@$_[0] ne '#' && @$_[0] ne '_'){
+ if(@$_[1]){
+ $script .= "$tab ".@$_[0].": ".@$_[1];
+ }else{
+ $script .= "$tab ".@$_[0]." ";
+ }
+ }
+ }else{
+ if(@$_[0] ne '#' && @$_[0] ne '_'){
+ if(@$_[1]){
+ $script .= "$tab ".@$_[0]."=\"".@$_[1]."\"";
+ }else{
+ $script .= "$tab ".@$_[0]." ";
+ }
+ }
+ }
+ $script .= "\n"
+ }
+ my $list = $self->{'@@'};
+ if($list){
+ foreach(@$list) {
+ $script .= "$tab <@@<$_>@@>\n"
+ }
+ }
+
+ my $nodes = $self->{'@$'};
+ if($nodes){
+ foreach my $nd (@$nodes) {
+ my $ref = ref($nd);
+ $nd = $$nd if ($ref eq 'REF');
+ if (ref($nd) eq 'CNFNode'){
+ $script .= toScript($nd, $nested+1);
+ }
+ }
+ }
+ my $val = $self->{'#'};
+ if($val){
+ if(ref($val) eq 'SCALAR'){
+ $val = $$val;
+ }
+ $val =~ s/\n/\n$tab /gs; $val =~ s/\s*$//;
+ $script .= $tab."[#\[\n$tab $val\n$tab]#]\n"
+ }
+
+ if ($isParent){
+ $script .= ">>\n"
+ }else{
+ if($nested){
+ $script .= "$tab>$tag>\n"
+ }else{
+ $script .= "$tab]$tag]\n"
+ }
+ }
+ return $script;
+}
+
+1;
+
+=begin copyright
+Programed by : Will Budic
+EContactHash : 990MWWLWM8C2MI8K (https://github.com/wbudic/EContactHash.md)
+Source : https://github.com/wbudic/PerlCNF.git
+Documentation : Specifications_For_CNF_ReadMe.md
+ This source file is copied and usually placed in a local directory, outside of its repository 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.
+Open Source Code License -> https://github.com/wbudic/PerlCNF/blob/master/ISC_License.md
+=cut copyright
\ No newline at end of file
+###
# Main Parser for the Configuration Network File Format.
-# 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 CNFParser;
use strict;use warnings;#use warnings::unused;
-use Exception::Class ('CNFParserException');
+use Exception::Class ('CNFParserException');
use Syntax::Keyword::Try;
use Hash::Util qw(lock_hash unlock_hash);
-use Time::HiRes qw(time);
-use DateTime;
require CNFMeta; CNFMeta::import();
require CNFNode;
+require CNFDateTime;
-
-# Do not remove the following no critic, no security or object issues possible.
+# Do not remove the following no critic, no security or object issues possible.
# We can use perls default behaviour on return.
##no critic qw(Subroutines::RequireFinalReturn)
##no critic Perl::Critic::Policy::ControlStructures::ProhibitMutatingListFunctions
-use constant VERSION => '2.9';
+use constant VERSION => '3.0';
our @files;
our %lists;
our %properties;
#private -> Instance fields:
my $anons;
my %includes;
- my %instructs;
+ my %instructs;
###
-# CNF Instruction tag covered reserved words.
-# You probably don't want to use these as your own possible instruction implementation.
+# CNF Instruction tag covered reserved words.
+# You can't use any of these as your own possible instruction implementation, unless in lower case.
###
-our %RESERVED_WORDS = map +($_, 1), qw{ CONST CONSTANT DATA VARIABLE VAR
- FILE TABLE TREE INDEX
- VIEW SQL MIGRATE DO LIB
+our %RESERVED_WORDS = map +($_, 1), qw{ CONST CONSTANT DATA DATE VARIABLE VAR
+ FILE TABLE TREE INDEX
+ VIEW SQL MIGRATE DO LIB PROCESSOR
PLUGIN MACRO %LOG INCLUDE INSTRUCTOR };
sub isReservedWord { my ($self, $word)=@_; return $word ? $RESERVED_WORDS{$word} : undef }
# Create a new CNFParser instance.
# $path - Path to some .cnf_file file, to parse, not compsuluory to add now? Make undef.
# $attrs - is reference to hash of constances and settings to dynamically employ.
-# $del_keys - is a reference to an array of constance attributes to dynamically remove.
-sub new { my ($class, $path, $attrs, $del_keys, $self) = @_;
+# $del_keys - is a reference to an array of constance attributes to dynamically remove.
+sub new { my ($class, $path, $attrs, $del_keys, $self) = @_;
if ($attrs){
- $self = \%$attrs;
+ $self = \%$attrs;
}else{
$self = {
DO_ENABLED => 0, # Enable/Disable DO instruction. Which could evaluated potentially be an doom execute destruction.
ENABLE_WARNINGS => 1, # Disable this one, and you will stare into the void, about errors or operations skipped.
STRICT => 1, # Enable/Disable strict processing to FATAL on errors, this throws and halts parsing on errors.
HAS_EXTENSIONS => 0, # Enable/Disable extension of custom instructions. These is disabled by default and ingored.
- DEBUG => 0, # Not internally used by the parser, but possible a convience bypass setting for code using it.
- CNF_CONTENT => "", # Origin of the script, this wull be set by the parser, usually the path of a script file or is direct content.
- };
- }
+ DEBUG => 0, # Not internally used by the parser, but possible a convienince bypass setting for code using it.
+ CNF_CONTENT => "", # Origin of the script, this will be set by the parser, usually the path of a script file or is direct content.
+ RUN_PROCESSORS => 1, # When enabled post parse processors are run, are these outside of the scope of the parsers executions.
+ };
+ }
$CONSTREQ = $self->{CONSTANT_REQUIRED};
if (!$self->{ANONS_ARE_PUBLIC}){ #Not public, means are private to this object, that is, anons are not static.
$self->{ANONS_ARE_PUBLIC} = 0; #<- Caveat of Perl, if this is not set to zero, it can't be accessed legally in a protected hash.
$self->{__ANONS__} = {};
- }
+ }
if(exists $self->{'%LOG'}){
if(ref($self->{'%LOG'}) ne 'HASH'){
die '%LOG'. "passed attribute is not an hash reference."
$properties{'%LOG'} = $self->{'%LOG'}
}
}
- $self->{STRICT} = 1 if not exists $self->{STRICT}; #make strict by default if missing.
+ $self->{STRICT} = 1 if not exists $self->{STRICT}; #make strict by default if missing.
$self->{ENABLE_WARNINGS} = 1 if not exists $self->{ENABLE_WARNINGS};
$self->{HAS_EXTENSIONS} = 0 if not exists $self->{HAS_EXTENSIONS};
+ $self->{RUN_PROCESSORS} = 1 if not exists $self->{RUN_PROCESSORS}; #Bby default enabled, disable during script dev.
$self->{CNF_VERSION} = VERSION;
$self->{__DATA__} = {};
bless $self, $class; $self->parse($path, undef, $del_keys) if($path);
}
#
-sub import {
+sub import {
my $caller = caller; no strict "refs";
{
*{"${caller}::configDumpENV"} = \&dumpENV;
*{"${caller}::anon"} = \&anon;
- *{"${caller}::SQL"} = \&SQL;
+ *{"${caller}::SQL"} = \&SQL;
+ *{"${caller}::isCNFTrue"} = \&_isTrue;
+ *{"${caller}::now"} = \&now;
}
- return 1;
+ return 1;
}
our $meta_has_priority = meta_has_priority();
our $meta_priority = meta_priority();
our $meta_on_demand = meta_on_demand();
###
-# The metaverse is that further this can be expanded,
+# The metaverse is that further this can be expanded,
# to provide further dynamic meta processing of the property value of an anon.
# When the future becomes life in anonymity, unknown variables best describe the meta state.
##
package META_PROCESS {
sub constance{
- my($class, $set) = @_;
+ my($class, $set) = @_;
if(!$set){
$set = {anonymous=>'*'}
}
bless $set, $class
}
sub process{
- my($self, $property, $val) = @_;
+ my($self, $property, $val) = @_;
if($self->{anonymous} ne '*'){
return $self->{anonymous}($property,$val)
}
{"$property"="$val"}
__JSON
}
-
-
-
+###
+# Check a value if it is CNFPerl boolean true.
+# For isFalse just negate check with not, as undef is concidered false or 0.
+##
+sub _isTrue{
+ my $value = shift;
+ return 0 if(not $value);
+ return ($value =~ /1|true|yes|on/i)
+}
###
# Post parsing instructed special item objects. They have lower priority to Order of apperance and from CNFNodes.
##
package InstructedDataItem {
-
+
our $dataItemCounter = int(0);
sub new { my ($class, $ele, $ins, $val) = @_;
ins => $ins,
val => $val,
'^' => $priority
- }, $class
+ }, $class
}
sub toString {
my $self = shift;
#
###
-# PropertyValueStyle objects must have same rule of how an property body can be scripted for attributes.
+# PropertyValueStyle objects must have same rule of how a property body can be scripted for attributes.
##
-package PropertyValueStyle {
+package PropertyValueStyle {
sub new {
my ($class, $element, $script, $self) = @_;
$self = {} if not $self;
$self->{element}=$element;
if($script){
- my ($p,$v);
+ my ($p,$v);
foreach my $itm($script=~/\s*(\w*)\s*[:=]\s*(.*)\s*/gm){
if($itm){
if(!$p){
$p = $itm;
}else{
+ $itm =~ s/^\s*(['"])(.*)\g{1}$/$2/g if $itm;
$self->{$p}=$itm;
undef $p;
}
- }
+ }
}
}else{
warn "PropertyValue process what?"
sub setPlugin{
my ($self, $obj) = @_;
$self->{plugin} = $obj;
- }
+ }
sub result {
my ($self, $value) = @_;
$self->{value} = $value;
# i.e. ${CNFParser->new()->anon()}{'MyDynamicAnon'} = 'something';
# However a private config instance, will have its own anon's. And could be read only if it exist as a property, via this anon(NAME) method.
# This hasn't been yet fully specified in the PerlCNF specs.
-# i.e. ${CNFParser->new({ANONS_ARE_PUBLIC=>0})->anon('MyDynamicAnon') # <-- Will not be available.
+# i.e. ${CNFParser->new({ANONS_ARE_PUBLIC=>0})->anon('MyDynamicAnon') # <-- Will not be available.
##
sub anon { my ($self, $n, $args)=@_;
my $anechoic = \%ANONS;
if(ref($self) ne 'CNFParser'){
$n = $self;
- }elsif (not $self->{'ANONS_ARE_PUBLIC'}){
- $anechoic = $self->{'__ANONS__'};
+ }elsif (not $self->{'ANONS_ARE_PUBLIC'}){
+ $anechoic = $self->{'__ANONS__'};
}
if($n){
my $ret = %$anechoic{$n};
if($ref eq 'META_PROCESS'){
my @arr = ($ret =~ m/(\$\$\$.+?\$\$\$)/gm);
foreach my $find(@arr) {# <- MACRO TAG translate. ->
- my $s= $find; $s =~ s/^\$\$\$|\$\$\$$//g;#
+ my $s= $find; $s =~ s/^\$\$\$|\$\$\$$//g;#
my $r = %$anechoic{$s};
if(!$r && exists $self->{$s}){#fallback to maybe constant property has been seek'd?
$r = $self->{$s};
}
if(!$r){
- warn "Unable to find property to translate macro expansion: $n -> $find\n"
+ warn "Unable to find property to translate macro expansion: $n -> $find\n"
unless $self and not $self->{ENABLE_WARNINGS}
}else{
- $ret =~ s/\Q$find\E/$r/g;
+ $ret =~ s/\Q$find\E/$r/g;
}
}
$ret = $args->process($n,$ret);
}elsif($ref eq 'HASHREF'){
- foreach my $key(keys %$args){
+ foreach my $key(keys %$args){
if($ret =~ m/\$\$\$$key\$\$\$/g){
my $val = %$args{$key};
$ret =~ s/\$\$\$$key\$\$\$/$val/g;
- }
+ }
}
}elsif($ref eq 'ARRAY'){ #we rather have argument passed as an proper array then a list with perl
my $cnt = 1;
}else{
my $val = %$anechoic{$args};
$ret =~ s/\$\$\$$args\$\$\$/$val/g;
- warn "Scalar argument passed $args, did you mean array to pass? For property $n=$ret\n"
- unless $self and not $self->{ENABLE_WARNINGS}
+ warn "Scalar argument passed $args, did you mean array to pass? For property $n=$ret\n"
+ unless $self and not $self->{ENABLE_WARNINGS}
}
}
- my $ref = ref($ret);
+ my $ref = ref($ret);
return $$ret if $ref eq "REF";
return $ret->val() if $ref eq "CNFNode";
return $ret;
###
# Validates and returns a constant named value as part of this configs instance.
# Returns undef if it doesn't exist, and exception if constance required is set;
-sub const { my ($self,$c)=@_;
+sub const { my ($self,$c)=@_;
if(exists $self->{$c}){
return $self->{$c}
}
###
# Collections are global, Reason for this is that any number of subsequent files parsed,
-# might contain properties that overwrite previous existing ones.
-# Or require ones that don't includes, expecting thm to be there.
+# might contain properties that overwrite previous existing ones.
+# Or require ones that don't include, and expecting them to be there.
# This overwritting can be erronous, but also is not expected to be very common to happen.
# Following method, provides direct access to the properties, this method shouldn't be used in general.
sub collections {\%properties}
-# Collection now returns the contained type dereferenced.
+#@Deprecated use property subroutine instead.
+sub collection {
+return property(@_);
+}
+###
+# Collection now returns the contained type dereferenced and is concidered a property.
# Make sure you use the appropriate Perl type on the receiving end.
# Note, if properties contain any scalar key entry, it sure hasn't been set by this parser.
-sub collection { my($self, $name) = @_;
+#
+sub property { my($self, $name) = @_;
if(exists($properties{$name})){
my $ret = $properties{$name};
- if(ref($ret) eq 'ARRAY'){
+ my $ref = ref($ret);
+ if($ref eq 'ARRAY'){
return @{$ret}
- }else{
+ }elsif($ref eq 'PropertyValueStyle'){
+ return $ret;
+ }
+ else{
return %{$ret}
}
}
return %properties{$name}
}
-sub data {shift->{'__DATA__'}}
-sub listDelimit {
- my ($this, $d , $t)=@_;
+sub data {return shift->{'__DATA__'}}
+
+sub listDelimit {
+ my ($this, $d , $t)=@_;
my @p = @{$lists{$t}};
- if(@p&&$d){
+ if(@p&&$d){
my @ret = ();
foreach (@p){
my @s = split $d, $_;
$lists{$t}=\@ret;
return @{$lists{$t}};
}
- return;
+ return;
}
sub lists {\%lists}
sub list {
- my $t=shift;if(@_ > 0){$t=shift;}
- my $an = $lists{$t};
- return @{$an} if defined $an;
+ my $t=shift;if(@_ > 0){$t=shift;}
+ my $an = $lists{$t};
+ return @{$an} if defined $an;
die "Error: List name '$t' not found!"
}
}return;
}
-
-sub template { my ($self, $property, %macros) = @_;
+###
+# Perform a macro replacement on tagged strings in a property value.
+##
+sub template { my ($self, $property, %macros) = @_;
my $val = $self->anon($property);
- if($val){
+ if($val){
foreach my $m(keys %macros){
my $v = $macros{$m};
$m ="\\\$\\\$\\\$".$m."\\\$\\\$\\\$";
- $val =~ s/$m/$v/gs;
+ $val =~ s/$m/$v/gs;
}
my $prev;
foreach my $m(split(/\$\$\$/,$val)){
}
}
return $val;
- }
+ }
}
#
$t = "" if not defined $t;
if($t eq 'CONST' or $t eq 'CONSTANT'){#Single constant with mulit-line value;
- $v =~ s/^\s//;
- # Not allowed to overwrite constant. i.e. it could be DO_ENABLED which is restricted.
+ # It is NOT allowed to overwrite constant.
if (not $self->{$e}){
- $self->{$e} = $v if not $self->{$e};
+ $v =~ s/^\s//;
+ $self->{$e} = $v;
}else{
warn "Skipped constant detected assignment for '$e'.";
}
}
elsif($t eq 'VAR' or $t eq 'VARIABLE'){
- $v =~ s/^\s//;
- $anons->{$e} = $v;
+ $v =~ s/^\s//;
+ $anons->{$e} = $v;
}
elsif($t eq 'DATA'){
- $v=~ s/^\n//;
+ $v=~ s/^\n//;
foreach(split /~\n/,$v){
my @a;
$_ =~ s/\\`/\\f/g;#We escape to form feed the found 'escaped' backtick so can be used as text.
}
push @a, $v;
}
- else{
+ else{
if($t =~ /^\#(.*)/) {#First is usually ID a number and also '#' signifies number.
$d = $1;#substr $d, 1;
$d=0 if !$d; #default to 0 if not specified.
push @a, $d;
}
}
- }
+ }
my $existing = $self->{'__DATA__'}{$e};
if(defined $existing){
my @rows = @$existing;
- push @rows, [@a] if scalar @a >0;
+ push @rows, [@a] if scalar @a >0;
$self->{'__DATA__'}{$e} = \@rows
}else{
- my @rows; push @rows, [@a];
- $self->{'__DATA__'}{$e} = \@rows if scalar @a >0;
+ my @rows; push @rows, [@a];
+ $self->{'__DATA__'}{$e} = \@rows if scalar @a >0;
}
- }
-
+ }
+
+ }elsif($t eq 'DATE'){
+ if($v && $v !~ /now|today/i){
+ $v =~ s/^\s//;
+ if($self->{STRICT}&&$v!~/^\d\d\d\d-\d\d-\d\d/){
+ $self-> warn("Invalid date format: $v expecting -> YYYY-MM-DD at start as possibility of DD-MM-YYYY or MM-DD-YYYY is ambiguous.")
+ }
+ $v = CNFDateTime::_toCNFDate($v,$self->{'TZ'});
+
+ }else{
+ $v = CNFDateTime->new(TZ=>$self->{'TZ'});
+ }
+ $anons->{$e} = $v;
}elsif($t eq 'FILE'){#@TODO Test case this
my ($i,$path,$cnf_file) = (0,"",$self->{CNF_CONTENT});
$v=~s/\s+//g;
push @a, $d
}
else{
- push @a, $d;
- }
- }
+ push @a, $d;
+ }
+ }
my $existing = $self->{'__DATA__'}{$e};
if(defined $existing){
my @rows = @$existing;
- push @rows, [@a] if scalar @a >0;
+ push @rows, [@a] if scalar @a >0;
$self->{'__DATA__'}{$e} = \@rows
}else{
- my @rows; push @rows, [@a];
- $self->{'__DATA__'}{$e} = \@rows if scalar @a >0;
+ my @rows; push @rows, [@a];
+ $self->{'__DATA__'}{$e} = \@rows if scalar @a >0;
}
- }
+ }
}
- }
- }
+ }
+ }
}elsif($t eq 'INCLUDE'){
$includes{$e} = {loaded=>0,path=>$e,v=>$v};
}elsif($t eq 'TREE'){
my $tree = 0;
- if (!$v){
+ if (!$v){
$v = $e;
$e = 'LAST_DO';
}
if( $v =~ s/$meta_priority/""/sexi){
$priority = $2;
}
- $tree = CNFNode->new({'_'=>$e,'~'=>$v,'^'=>$priority});
+ $tree = CNFNode->new({'_'=>$e,'~'=>$v,'^'=>$priority});
$tree->{DEBUG} = 1 if $self->{DEBUG};
$instructs{$e} = $tree;
- }elsif($t eq 'TABLE'){ # This has now be late bound and send to the CNFSQL package. since v.2.6
- SQL()->createTable($e,$v) } # It is hardly been used. But in future itt might change.
- elsif($t eq 'INDEX'){ SQL()->createIndex($v)}
+ }elsif($t eq 'TABLE'){ # This has now be late bound and send to the CNFSQL package. since v.2.6
+ SQL()->createTable($e,$v) } # It is hardly been used. But in future this might change.
+ elsif($t eq 'INDEX'){ SQL()->createIndex($v)}
elsif($t eq 'VIEW'){ SQL()->createView($e,$v)}
elsif($t eq 'SQL'){ SQL($e,$v)}
elsif($t eq 'MIGRATE'){SQL()->migrate($e, $v)
elsif($t eq 'DO'){
if($DO_ENABLED){
my $ret;
- if (!$v){
+ if (!$v){
$v = $e;
$e = 'LAST_DO';
}
}
if( $v =~ s/($meta_priority)/""/sexi){
$priority = $2;
- }
+ }
if($v=~ s/($meta_on_demand)/""/ei){
$anons->{$e} = CNFNode -> new({'_'=>$e,'&'=>$v,'^'=>$priority});
return;
}
- ## no critic BuiltinFunctions::ProhibitStringyEval
+ ## no critic BuiltinFunctions::ProhibitStringyEval
$ret = eval $v if not $ret;
- ## use critic
+ ## use critic
if ($ret){
chomp $ret;
$anons->{$e} = $ret;
}
}elsif($t eq 'LIB'){
if($DO_ENABLED){
- if (!$v){
- $v = $e;
- $e = 'LAST_LIB';
- }
+ if (!$v){
+ $v = $e;
+ $e = 'LAST_LIB';
+ }
try{
use Module::Load;
autoload $v;
$v =~ s/^(.*\/)*|(\..*)$//g;
- $anons->{$e} = $v;
+ $anons->{$e} = $v;
}catch{
$self->warn("Module DO_ENABLED library failed to load: $v\n");
$anons->{$e} = '<<ERROR>>';
$anons->{$e} = '<<ERROR>>';
}
}
- elsif($t eq 'PLUGIN'){
+ elsif($t eq 'PLUGIN'){
if($DO_ENABLED){
- $instructs{$e} = InstructedDataItem -> new($e, 'PLUGIN', $v);
+ $instructs{$e} = InstructedDataItem -> new($e, 'PLUGIN', $v);
}else{
$self->warn("DO_ENABLED is set to false to process following plugin: $e\n")
- }
+ }
}
- elsif($t eq 'INSTRUCTOR'){
+ elsif($t eq 'PROCESSOR'){
+ if(not $self->registerProcessor($e, $v)){
+ CNFParserException->throw("PostParseProcessor Registration Failed for '<<$e<$t>$v>>'!\t");
+ }
+ }
+ elsif($t eq 'INSTRUCTOR'){
if(not $self->registerInstructor($e, $v) && $self->{STRICT}){
CNFParserException->throw("Instruction Registration Failed for '<<$e<$t>$v>>'!\t");
}
}
+ elsif($t eq 'MACRO'){
+ $instructs{$e}=$v;
+ }
elsif(exists $instructors{$t}){
if(not $instructors{$t}->instruct($e, $v) && $self->{STRICT}){
CNFParserException->throw("Instruction processing failed for '<<$e<$t>>'!\t");
}
}
- elsif($t eq 'MACRO'){
- $instructs{$e}=$v;
- }else{
- #Register application statement as either an anonymous one. Or since v.1.2 a listing type tag.
+ else{
+ #Register application statement as either an anonymous one. Or since v.1.2 a listing type tag.
if($e !~ /\$\$$/){ #<- It is not matching {name}$$ here.
if($self->{'HAS_EXTENSIONS'}){
$anons->{$e} = InstructedDataItem->new($e,$t,$v)
}else{
- $v = $t if not $v;
+ $v = $t if not $v;
if($e=~/^\$/){
$self->{$e} = $v if !$self->{$e}; # Not allowed to overwrite constant.
- }else{
+ }else{
$anons->{$e} = $v
}
}
my $array = $lists{$e};
if(!$array){$array=();$lists{$e} = \@{$array};}
push @{$array}, $v;
- }
- }
+ }
+ }
}
###
sub parse { my ($self, $cnf_file, $content, $del_keys) = @_;
my @tags;
- if($self->{'ANONS_ARE_PUBLIC'}){
+ if($self->{'ANONS_ARE_PUBLIC'}){
$anons = \%ANONS;
- }else{
+ }else{
$anons = $self->{'__ANONS__'};
- }
+ }
#private %includes; for now we keep on possible multiple calls to parse.
#private instructs on this parse call.
%instructs = ();
unlock_hash(%$self);
if(not $content){
- open(my $fh, "<:perlio", $cnf_file ) or die "Can't open $cnf_file -> $!";
- read $fh, $content, -s $fh;
+ open(my $fh, "<:perlio", $cnf_file ) or die "Can't open $cnf_file -> $!";
+ read $fh, $content, -s $fh;
close $fh;
my @stat = stat($cnf_file);
- $self->{CNF_STAT} = \@stat;
- $self->{CNF_CONTENT} = $cnf_file;
+ $self->{CNF_STAT} = \@stat;
+ $self->{CNF_CONTENT} = $cnf_file;
}else{
my $type =Scalar::Util::reftype($content);
if($type && $type eq 'ARRAY'){
my $spc = $content =~ /\n/ ? '(<{2,3}?)(<*.*?>*)(>{2,3})' : '(<{2,3}?)(<*.*?>*?)(>{2,3})$';
- @tags = ($content =~ m/$spc/gms);
+ @tags = ($content =~ m/$spc/gms);
- foreach my $tag (@tags){
+ foreach my $tag (@tags){
next if not $tag;
next if $tag =~ m/^(>+)|^(<<)/;
if($tag =~ m/^<(\w*)\s+(.*?)>*$/gs){ # Original fastest and early format: <<<anon value>>>
my $v = $2;
if(isReservedWord($self,$t)){
my $isVar = ($t eq 'VARIABLE' || $t eq 'VAR');
- if($t eq 'CONST' or $isVar){ #constant multiple properties.
- foreach my $line(split '\n', $v) {
- $line =~ s/^\s+|\s+$//; # strip unwanted spaces
+ if($t eq 'CONST' or $isVar){ #constant multiple properties.
+ foreach my $line(split '\n', $v) {
+ $line =~ s/^\s+|\s+$//; # strip unwanted spaces
$line =~ s/\s*>$//;
- $line =~ m/([\$\w]*)(\s*=\s*)(.*)/g;
+ $line =~ m/([\$\w]*)(\s*=\s*)(.*)/g;
my $name = $1;
- $line = $3;
+ $line = $3; $line =~ s/^\s*(['"])(.*)\g{1}$/$2/;#strip quotes
if(defined $name){
if($isVar){
- $line =~ s/^\s*["']|['"]\s*$//g;#strip qoutes
$anons ->{$name} = $line if $line
}else{
- if($line and not $self->{$name}){# Not allowed to overwrite constant.
- $line =~ s/^\s*["']|['"]\s*$//g;#strip qoutes
- $self->{$name} = $line;
- }else{
+ if($line and not $self->{$name}){# Not allowed to overwrite constant.
+
+ $self->{$name} = $line;
+ }else{
warn "Skipping and keeping previously set constance -> [$name] the new value ".
($line eq $self->{$name})?"matches it":"dosean't match -> $line."
- }
+ }
}
}
}
- }else{
+ }else{
doInstruction($self,$v,$t,undef);
}
}else{
}else{
#vars are e-element,t-token or instruction,v- for value, vv -array of the lot.
my ($e,$t,$v,@vv);
-
+
# Check if very old format and don't parse the data for old code compatibility to (still) do it.
# This is interesting, as a newer format file is expected to use the DATA instruction and final data specified script rules.
if($CNF_VER eq 'CNF2.2' && $tag =~ m/(\w+)\s*(<\d+>\s)\s*(.*\n)/mg){#It is old DATA format annon
}
# Before mauling into possible value types, let us go for the full expected tag specs first:
# <<{$sig}{name}<{INSTRUCTION}>{value\n...value\n}>>
- # Found in -> <https://github.com/wbudic/PerlCNF//CNF_Specs.md>
+ # Found in -> <https://github.com/wbudic/PerlCNF//CNF_Specs.md>
if($tag !~ /\n/ && $tag =~ /^([@%\$\.\/\w]+)\s*([ <>]+)(\w*>)(.*)/) {
$e = $1;
$t = $2;
$t = $3;
$v = $5;
}
- }else{
+ }else{
#############################################################################
$tag =~ m/\s*([@%\$\.\/\w]+)\s* # The name.
([ <>\n]) # begin or close of instruction, where '\n' mark in script as instruction less.
(>$)* # capture above value up to here from buffer, i.e. if comming from a >>> tag.
/gmxs; ###############################################################################
- $e =$1;
+ $e =$1;
if($e eq '@' or $2 eq '<' or ($2 eq '>' and !$4)){
- $t = $3;
+ $t = $3;
}else{
$t = $1;
- $e = $3
+ $e = $3
}
$v= $5;
$v =~ s/>$//m if defined($4) && $4 eq '<' or $6; #value has been crammed into an instruction?
-
+
}
if(!$v && !$RESERVED_WORDS{$t}){
- $v= $t;
- }
+ $v= $t;
+ }
$v =~ s/\\</</g; $v =~ s/\\>/>/g;# escaped brackets from v.2.8.
-
- #Do we have an autonumbered instructed list?
+
+ #Do we have an autonumbered instructed list?
#DATA best instructions are exempted and differently handled by existing to only one uniquely named property.
#So its name can't be autonumbered.
- if ($e =~ /(.*?)\$\$$/){
+ if ($e =~ /(.*?)\$\$$/){
$e = $1;
if($t && $t ne 'DATA'){
my $array = $lists{$e};
- if(!$array){$array=();$lists{$e} = \@{$array};}
+ if(!$array){$array=();$lists{$e} = \@{$array};}
push @{$array}, InstructedDataItem -> new($e, $t, $v);
next
- }
+ }
}elsif ($e eq '@'){#collection processing.
my $isArray = $t=~ m/^@/;
# if(!$v && $t =~ m/(.*)>(\s*.*\s*)/gms){
# $t = $1;
# $v = $2;
- # }
+ # }
my @lst = ($isArray?split(/[,\n]/, $v):split('\n', $v)); $_="";
my @props = map {
s/^\s+|\s+$//; # strip unwanted spaces
$self->warn("ERROR collection is trying to use a reserved property name -> $t.");
next
}else{
- my @arr=();
- foreach (@props){
+ my @arr=();
+ foreach (@props){
push @arr, $_ if($_ && length($_)>0);
}
$properties{$t}=\@arr;
}
}else{
- my %hsh;
- my $macro = 0;
+ my %hsh;
+ my $macro = 0;
if(exists($properties{$t})){
if($self->isReservedWord($t)){
$self->warn("Skipped overwritting reserved property -> $t.");
%hsh = %{$properties{$t}}
}
}else{
- %hsh =();
+ %hsh =();
}
- foreach my $p(@props){
+ foreach my $p(@props){
if($p && $p eq 'MACRO'){$macro=1}
- elsif( $p && length($p)>0 ){
+ elsif( $p && length($p)>0 ){
my @pair = ($p=~/\s*([-+_\w]*)\s*[=:]\s*(.*)/s);#split(/\s*=\s*/, $p);
- next if (@pair != 2 || $pair[0] =~ m/^[#\\\/]+/m);#skip, it is a comment or not '=' delimited line.
- my $name = $pair[0];
+ next if (@pair != 2 || $pair[0] =~ m/^[#\\\/]+/m);#skip, it is a comment or not '=' delimited line.
+ my $name = $pair[0];
my $value = $pair[1]; $value =~ s/^\s*["']|['"]$//g;#strip quotes
if($macro){
my @arr = ($value =~ m/(\$\$\$.+?\$\$\$)/gm);
- foreach my $find(@arr) {
+ foreach my $find(@arr) {
my $s = $find; $s =~ s/^\$\$\$|\$\$\$$//g;
- my $r = $anons->{$s};
+ my $r = $anons->{$s};
$r = $self->{$s} if !$r;
$r = $instructs{$s} if !$r;
CNFParserException->throw(error=>"Unable to find property for $t.$name -> $find\n",show_trace=>1) if !$r;
- $value =~ s/\Q$find\E/$r/g;
+ $value =~ s/\Q$find\E/$r/g;
}
}
$hsh{$name}=$value; $self->log("macro $t.$name->$value\n") if $self->{DEBUG}
my $v = $struct;
my @arr = ($v =~ m/(\$\$\$.+?\$\$\$)/gm);
foreach my $find(@arr) {# <- MACRO TAG translate. ->
- my $s= $find; $s =~ s/^\$\$\$|\$\$\$$//g;#
+ my $s= $find; $s =~ s/^\$\$\$|\$\$\$$//g;#
my $r = %$anons{$s};
- $r = $self->{$s} if !$r;
+ $r = $self->{$s} if !$r;
if(!$r){
$self->warn("Unable to find property to translate macro expansion: $e -> $find\n");
}else{
- $v =~ s/\Q$find\E/$r/g;
+ $v =~ s/\Q$find\E/$r/g;
}
- }
+ }
$anons->{$e}=$v;
- }else{
+ }else{
$items[@items] = $struct;
}
}
for my $idx(0..$#items) {
my $struct = $items[$idx];
- my $type = ref($struct);
+ my $type = ref($struct);
if($type eq 'CNFNode' && $struct-> priority() > 0){
$struct->validate() if $self->{ENABLE_WARNINGS};
- $anons ->{$struct->name()} = $struct->process($self, $struct->script());
+ $anons ->{$struct->name()} = $struct->process($self, $struct->script());
splice @items, $idx, 1
}
}
#Now only what is left instructed data items or plugins, and nodes that have assigned last priority, if any.
for my $idx(0..$#items) {
my $struct = $items[$idx];
- my $type = ref($struct);
- if($type eq 'CNFNode'){
- $struct->validate() if $self->{ENABLE_WARNINGS};
- $anons->{$struct->name()} = $struct->process($self, $struct->script());
- }elsif($type eq 'InstructedDataItem'){
+ my $type = ref($struct);
+ if($type eq 'CNFNode'){
+ $struct->validate() if $self->{ENABLE_WARNINGS};
+ $anons->{$struct->name()} = $struct->process($self, $struct->script());
+ }elsif($type eq 'InstructedDataItem'){
my $t = $struct->{ins};
- if($t eq 'PLUGIN'){
+ if($t eq 'PLUGIN'){
instructPlugin($self,$struct,$anons);
- }
+ }
}else{warn "What is -> $struct type:$type ?"}
}
- undef %instructs;
+ undef %instructs;
}
#Do scripted includes.
- my @inc = sort values %includes;
+ my @inc = sort values %includes;
$includes{$0} = {loaded=>1, path=>$self->{CNF_CONTENT}}; #<- to prevent circular includes.
foreach my $file(@inc){
if(!$file->{loaded} && $file->{path} ne $self->{CNF_CONTENT}){
if(open(my $fh, "<:perlio", $file->{path} )){
read $fh, $content, -s $fh;
- close $fh;
+ close $fh;
if($content){
$file->{loaded} = 1;
$self->parse(undef, $content)
}else{
$self->error("Include content is blank for -> ".$file->{path})
- }
+ }
}else{
CNFParserException->throw("Can't open ".$file->{path}." -> $!") if $self->{STRICT};
$file->{loaded} = 0;
$self->error("Script include not available -> ".$file->{path})
}
}
- }
- foreach my $k(@$del_keys){
+ }
+ foreach my $k(@$del_keys){
delete $self->{$k} if exists $self->{$k}
}
+ my $runProcessors = $self->{RUN_PROCESSORS} ? 1: 0;
lock_hash(%$self);#Make repository finally immutable.
+ runPostParseProcessors($self) if $runProcessors;
+ return $self
}
#
sub instructPlugin {
- my ($self, $struct, $anons) = @_;
- try{
+ my ($self, $struct, $anons) = @_;
+ try{
$properties{$struct->{'ele'}} = doPlugin($self, $struct, $anons);
$self->log("Plugin instructed ->". $struct->{'ele'});
- }catch($e){
+ }catch($e){
if($self->{STRICT}){
- CNFParserException->throw(error=>$e, show_trace=>1);
+ CNFParserException->throw(error=>$e);
}else{
- $self->trace("Error @ Plugin -> ". $struct->toString() ." Error-> $@")
+ $self->trace("Error @ Plugin -> ". $struct->toString() ." Error-> $@")
}
}
}
+#
###
# Register Instructor on tag and value for to be externally processed.
# $body - Contains attribute(s) linking to method(s) to be registered.
# @TODO Current Under development.
###
-sub registerInstructor {
- my ($self, $package, $body) = @_;
- $body =~ s/^\s*|\s*$//g;
- my ($obj, %args, $ins);
- foreach my $ln(split(/\n/,$body)){
- my @pair = $ln =~ /\s*(\w+)[:=](.*)\s*/;
- my $ins = $1; $ins = $ln if !$ins;
- my $mth = $2;
- if($ins =~ /[a-z]/){
- $args{$ins} = $mth;
- next
- }
- if(exists $instructors{$ins}){
- $self -> error("$package<$ins> <- Instruction has been previously registered by: ".ref(${$instructors{$ins}}));
+sub registerInstructor {
+ my ($self, $package, $body) = @_;
+ $body =~ s/^\s*|\s*$//g;
+ my ($obj, %args, $ins, $mth);
+ foreach my $ln(split(/\n/,$body)){
+ my @pair = $ln =~ /\s*(\w+)[:=](.*)\s*/;
+ $ins = $1; $ins = $ln if !$ins;
+ $mth = $2;
+ if($ins =~ /[a-z]/i){
+ $args{$ins} = $mth;
+ }
+ }
+ if(exists $instructors{$ins}){
+ $self -> error("$package<$ins> <- Instruction has been previously registered by: ".ref(${$instructors{$ins}}));
+ return;
+ }else{
+
+ foreach(values %instructors){
+ if(ref($$_) eq $package){
+ $obj = $_; last
+ }
+ }
+
+ if(!$obj){
+ ## no critic (RequireBarewordIncludes)
+ require $package.'.pm';
+ my $methods = Class::Inspector->methods($package, 'full', 'public');
+ my ($has_new,$has_instruct);
+ foreach(@$methods){
+ $has_new = 1 if $_ eq "$package\::new";
+ $has_instruct = 1 if $_ eq "$package\::instruct";
+ }
+ if(!$has_new){
+ $self -> log("ERR $package<$ins> -> new() method not found for package.");
return;
- }else{
- foreach(values %instructors){
- if(ref($$_) eq $package){
- $obj = $_; last
- }
- }
- if(!$obj){
- ## no critic (RequireBarewordIncludes)
- require $package.'.pm';
- my $methods = Class::Inspector->methods($package, 'full', 'public');
- my ($has_new,$has_instruct);
- foreach(@$methods){
- $has_new = 1 if $_ eq "$package\::new";
- $has_instruct = 1 if $_ eq "$package\::instruct";
- }
- if(!$has_new){
- $self -> log("ERR $package<$ins> -> new() method not found for package.");
- return;
- }
- if(!$has_instruct){
- $self -> log("ERR $package<$ins> -> instruct() required method not found for package.");
- return;
- }
- $obj = $package -> new(\%args);
- }
- $instructors{$ins} = \$obj;
- }
- }
- return \$obj;
+ }
+ if(!$has_instruct){
+ $self -> log("ERR $package<$ins> -> instruct() required method not found for package.");
+ return;
+ }
+ $obj = $package -> new(\%args);
+ }
+ $instructors{$ins} = \$obj
+ }
+ return \$obj;
}
+#
+
+###
+# Register PostParseProcessor for further externally processing.
+# $package - Is the anonymouse package name.
+# $body - Contains attribute(s) where function is the most required one.
+###
+sub registerProcessor {
+ my ($self, $package, $body) = @_;
+ $body =~ s/^\s*|\s*$//g if $body;
+ my ($obj, %args, $ins, $mth, $func);
+ foreach my $ln(split(/\n/,$body)){
+ my @pair = $ln =~ /\s*(\w+)[:=](.*)\s*/;
+ $ins = $1; $ins = $ln if !$ins;
+ $mth = $2;
+ if($ins =~ /^func\w*/){
+ $func = $mth
+ }
+ elsif($ins =~ /[a-z]/i){
+ $args{$ins} = $mth
+ }
+ }
+ $func = $ins if !$func;
+ if(!$func){
+ $self -> log("ERR <<$package<$body>> function attribute not found set.");
+ return;
+ }
+ ## no critic (RequireBarewordIncludes)
+ require $package.'.pm';
+ my $methods = Class::Inspector->methods($package, 'full', 'public');
+ my ($has_new,$has_func);
+ foreach(@$methods){
+ $has_new = 1 if $_ eq "$package\::new";
+ $has_func = 1 if $_ eq "$package\::$func";
+ }
+ if(!$has_new){
+ $self -> log("ERR In package $package -> new() method not found for package.");
+ return;
+ }
+ if(!$has_func){
+ $self -> log("ERR In package $package -> $func(\$parser) required method not found for package.");
+ return;
+ }
+ $obj = $package -> new(\%args);
+ $self->addPostParseProcessor($obj,$func);
+ return 1;
+}
+
+sub addPostParseProcessor {
+ my $self = shift;
+ my $processor = shift;
+ my $func = shift;
+ my @arr;
+ my $arf = $self->{POSTParseProcessors} if exists $self->{POSTParseProcessors};
+ @arr = @$arf if $arf;
+ $arr[@arr] = [$processor, $func];
+ $self->{POSTParseProcessors} = \@arr;
+}
+
+sub runPostParseProcessors {
+ my $self = shift;
+ my $arr = $self->{POSTParseProcessors} if exists $self->{POSTParseProcessors};
+ foreach(@$arr){
+ my @objdts =@$_;
+ my $prc = $objdts[0];
+ my $func = $objdts[1];
+ $prc -> $func($self);
+ }
+}
+
+#
###
# Setup and pass to pluging CNF functionality.
my $pck = $plugin->{package};
my $prp = $plugin->{property};
my $sub = $plugin->{subroutine};
- if($pck && $prp && $sub){
+ if($pck && $prp && $sub){
## no critic (RequireBarewordIncludes)
require "$pck.pm";
- my $obj;
- my $settings = $properties{'%Settings'};#Properties are global.
+ #Properties are global, all plugins share a %Settings property if specifed, otherwise the default will be set from here only.
+ my $settings = $properties{'%Settings'};
if($settings){
- $obj = $pck->new(\%$settings);
- }else{
- $obj = $pck->new();
- }
+ foreach(keys %$settings){
+ #We allow for now, the plugin have settings set by its property, do not overwrite if exists as set.
+ $plugin->{$_} = $settings->{$_} unless exists $plugin->{$_}
+ } ;
+ }
+ my $obj = $pck->new($plugin);
my $res = $obj-> $sub($self, $prp);
- if($res){
- $plugin->setPlugin($obj);
- return $plugin;
+ if($res){
+ $plugin->setPlugin($obj);
+ return $plugin;
}else{
die "Sorry, the PLUGIN feature has not been Implemented Yet!"
}
my $meths;
## no critic BuiltinFunctions::ProhibitStringyEval
no strict 'refs';
- if($link =~/(\w*)::\w+$/){
+ if($link =~/(\w*)::\w+$/){
use Module::Loaded qw(is_loaded);
if(is_loaded($1)){
- $ret = \&{+$link}($self);
+ $ret = \&{+$link}($self);
}else{
eval require "$1.pm";
- $ret = &{+$link};
+ $ret = &{+$link};
if(!$ret){
$self->error( qq(Package constance link -> $link is not available (try to place in main:: package with -> 'use $1;')));
$ret = $link
}else{
$ret = $self->anon($link);
$ret = $self-> {$link} if !$ret;
- }
+ }
return $ret;
}
###
# Writes out to a handle an CNF property or this parsers constance's as default property.
# i.e. new CNFParser()->writeOut(*STDOUT);
-sub writeOut { my ($self, $handle, $property) = @_;
+sub writeOut { my ($self, $handle, $property) = @_;
my $buffer;
if(!$property){
- my @keys = sort keys %$self;
+ my @keys = sort keys %$self;
$buffer = "<<<CONST\n";
my $with = 5;
foreach (@keys){
}
elsif($val !~ /^\d+/){
$val = "\"$val\""
- }
- $buffer .= ' 'x$spc. $key . " = $val\n";
+ }
+ $buffer .= ' 'x$spc. $key . " = $val\n";
}
$buffer .= ">>";
return $buffer if !$handle;
$buffer = "<<@<$property>\n";
if(ref $prp eq 'ARRAY') {
my @arr = sort keys @$prp; my $n=0;
- foreach (@arr){
+ foreach (@arr){
$buffer .= "\"$_\"";
if($arr[-1] ne $_){
if($n++>5){
$buffer .= ","
}
}
- }
+ }
}elsif(ref $prp eq 'HASH') {
my %hsh = %$prp;
my @keys = sort keys %hsh;
- foreach my $key(@keys){
- $buffer .= $key . "\t= \"". $hsh{$key} ."\"\n";
+ foreach my $key(@keys){
+ $buffer .= $key . "\t= \"". $hsh{$key} ."\"\n";
}
}
$buffer .= ">>\n";
$prp = $ANONS{$property};
$prp = $self->{$property} if !$prp;
if (!$prp){
- $buffer = "<<ERROR<$property>Property not found!>>>\n"
+ $buffer = "<<ERROR<$property>Property not found!>>>\n"
}else{
$buffer = "<<$property><$prp>>\n";
}
return $buffer if !$handle;
- print $handle $buffer;
+ print $handle $buffer;
return 0;
}
}
my $self = shift;
my $message = shift;
my $type = shift; $type = "" if !$type;
+ my $isWarning = $type eq 'WARNG';
my $attach = join @_; $message .= $attach if $attach;
- my %log = $self -> collection('%LOG');
- my $time = DateTime->from_epoch( epoch => time )->strftime('%Y-%m-%d %H:%M:%S.%3N');
- $message = "$type $message" if 'WARNG';
- if($message =~ /^ERROR/ || $type eq 'WARNG'){
+ my %log = $self -> property('%LOG');
+ my $time = exists $self->{'TZ'} ? CNFDateTime -> new(TZ=>$self->{'TZ'}) -> toTimestamp() :
+ CNFDateTime -> new()-> toTimestamp();
+
+ $message = "$type $message" if $isWarning;
+
+ if($message =~ /^ERROR/ || $isWarning){
warn $time . " " .$message;
}
elsif(%log && $log{console}){
my $logfile = $log{file};
my $tail_cnt = $log{tail};
if($log{tail} && $tail_cnt && int(`tail -n $tail_cnt $logfile | wc -l`)>$tail_cnt-1){
- use File::ReadBackwards;
+use File::ReadBackwards;
my $pos = do {
my $fh = File::ReadBackwards->new($logfile) or die $!;
$fh->readline() for 1..$tail_cnt;
$fh->tell()
- };
+ };
truncate($logfile, $pos) or die $!;
-
+
}
open (my $fh, ">>", $logfile) or die ("$!");
print $fh $time . " - " . $message ."\n";
close $fh;
}
+ return $time . " " .$message;
}
sub error {
my $self = shift;
- my $message = shift;
+ my $message = shift;
$self->log("ERROR $message");
}
use Carp qw(cluck); #what the? I know...
sub warn {
my $self = shift;
- my $message = shift;
+ my $message = shift;
if($self->{ENABLE_WARNINGS}){
- $self -> log($message,'WARNG');
+ $self -> log($message,'WARNG');
}
}
sub trace {
my $self = shift;
- my $message = shift;
- my %log = $self -> collection('%LOG');
+ my $message = shift;
+ my %log = $self -> property('%LOG');
if(%log){
$self -> log($message)
}else{
}
}
+sub now {return CNFDateTime->new(shift)}
+
sub dumpENV{
foreach (keys(%ENV)){print $_,"=", "\'".$ENV{$_}."\'", "\n"}
}
}
our $JSON;
sub JSON {
- my $self = shift;
+ my $self = shift;
if(!$JSON){
- require CNFJSON;
- $JSON = CNFJSON-> new( {CNF_VERSION=>$self->{CNF_VERSION},
+ require CNFJSON;
+ $JSON = CNFJSON-> new({ CNF_VERSION=>$self->{CNF_VERSION},
CNF_CONTENT=>$self->{CNF_CONTENT},
- DO_ENABLED=>$self->{DO_ENABLED}
- } );
- }
+ DO_ENABLED =>$self->{DO_ENABLED}
+ });
+ }
return $JSON;
}
+###
+# CNFNodes are kept as anons by the TREE instruction, but these either could have been futher processed or
+# externaly assigned too as nodes to the parser.
+###
+our %NODES;
+sub addTree {
+ my ($self, $name, $node )= @_;
+ if($name && $node){
+ $NODES{$name} = $node;
+ }
+}
+### Utility way to obtain CNFNodes from a configuration.
+sub getTree {
+ my ($self, $name) = @_;
+ return $NODES{$name} if exists $NODES{$name};
+ my $ret = $self->anon($name);
+ if(ref($ret) eq 'CNFNode'){
+ return \$ret;
+ }
+ return;
+}
sub END {
undef %ANONS;
undef @files;
+undef %properties;
+undef %lists;
+undef %instructors;
}
1;
+=begin copyright
+Programed by : Will Budic
+EContactHash : 990MWWLWM8C2MI8K (https://github.com/wbudic/EContactHash.md)
+Source : https://github.com/wbudic/PerlCNF.git
+Documentation : Specifications_For_CNF_ReadMe.md
+ This source file is copied and usually placed in a local directory, outside of its repository 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.
+Open Source Code License -> https://github.com/wbudic/PerlCNF/blob/master/ISC_License.md
+=cut copyright
__END__
## Instructions & Reserved words
3. Current Reserved words list is.
- CONST - Concentrated list of constances, or individaly tagged name and its value.
- VARIABLE - Concentrated list of anons, or individaly tagged name and its value.
- - DATA - CNF scripted delimited data property, having uniform table data rows.
+ - DATA - CNF scripted delimited data property, having uniform table data rows.
+ - DATE - Translate PerlCNF date representation to DateTime object. Returns now() on empty property value.
- FILE - CNF scripted delimited data property is in a separate file.
- - %LOG - Log settings property, i.e. enabled=1, console=1.
+ - %LOG - Log settings property, i.e. enabled=>1, console=>1.
- TABLE - SQL related.
- TREE - Property is a CNFNode tree containing multiple debth nested children nodes.
- INCLUDE - Include properties from another file to this repository.
- INSTRUCT - Provides custom new anonymous instruction.
- VIEW - SQL related.
- PLUGIN - Provides property type extension for the PerlCNF repository.
+ - PROCESSOR- Registered processor to be called once all parsing is done and repository secured.
- SQL - SQL related.
- MIGRATE - SQL related.
- MACRO
use Exception::Class ('HTMLIndexProcessorPluginException');
use feature qw(signatures);
use Scalar::Util qw(looks_like_number);
-use Date::Manip;
-
+use Clone qw(clone);
use CGI;
use CGI::Session '-ip_match';
our $TAB = ' 'x4;
-sub new ($class, $fields={Language=>'English',DateFormat=>'US'}){
-
- if(ref($fields) eq 'REF'){
- warn "Hash reference required as argument for fields!"
+sub new ($class, $plugin){
+ my $settings;
+ if($plugin){
+ $settings = clone $plugin; #clone otherwise will get hijacked with blessings.
}
- my $lang = $fields->{'Language'};
- my $frmt = $fields->{'DateFormat'};
- Date_Init("Language=$lang","DateFormat=$frmt");
-
- return bless $fields, $class
+ return bless $settings, $class
}
###
# Process config data to contain expected fields and data.
###
-sub convert ($self, $parser, $property) {
+sub convert ($self, $parser, $property) {
my ($buffer,$title, $link, $body_attrs, $body_on_load, $give_me);
my $cgi = CGI -> new();
- my $cgi_action = $cgi-> param('action');
- my $cgi_doc = $cgi-> param('doc');
+ my $cgi_action = $cgi-> param('action');
+ my $cgi_doc = $cgi-> param('doc');
my $tree = $parser-> anon($property);
- die "Tree property '$property' is not available!" if(!$tree or ref($tree) ne 'CNFNode');
-
+ die "Tree property '$property' is not available!" if(!$tree or ref($tree) ne 'CNFNode');
try{
-
-
- if (exists $parser->{'HTTP_HEADER'}){
+ if (exists $parser->{'HTTP_HEADER'}){
$buffer .= $parser-> {'HTTP_HEADER'};
- }else{
+ }else{
if(exists $parser -> collections()->{'%HTTP_HEADER'}){
my %http_hdr = $parser -> collection('%HTTP_HEADER');
$buffer = $cgi->header(%http_hdr);
}
}
-
- if ($cgi_action and $cgi_action eq 'load'){
- $buffer .= $cgi->start_html(); my
+ if ($cgi_action and $cgi_action eq 'load'){
+ $buffer .= $cgi->start_html(); my
$load = loadDocument($parser, $cgi_doc);
if($load){
- $buffer .= $$load if $load;
+ $buffer .= $$load if $load;
}else{
$buffer .= "Document is empty: $cgi_doc\n"
- }
+ }
}else{
$title = $tree -> {'Title'} if exists $tree->{'Title'};
$link = $tree -> {'HEADER'};
if($link){
if(ref($link) eq 'CNFNode'){
my $arr = $link->find('CSS/@@');
- foreach (@$arr){
- push @hhshCSS, {-type => 'text/css', -src => $_->val()};
+ foreach (@$arr){
+ push @hhshCSS, {-type => 'text/css', -src => $_->val()};
}
$arr = $link->find('JS/@@');
- foreach (@$arr){
- push @hhshJS, {-type => 'text/javascript', -src => $_->val()};
- }
+ foreach (@$arr){
+ push @hhshJS, {-type => 'text/javascript', -src => $_->val()};
+ }
$arr = $link -> find('STYLE');
if(ref($arr) eq 'ARRAY'){
foreach (@$arr){
}
$arr = $link -> find('SCRIPT');
if(ref($arr) eq 'ARRAY'){
- foreach (@$arr){
+ foreach (@$arr){
$give_me .= "\n<script>\n".$_ -> val()."\n</script>\n"
}}else{
$give_me .= "\n<script>\n".$arr -> val()."\n</script>\n"
}
- }
- delete $tree -> {'HEADER'};
- }
+ }
+ delete $tree -> {'HEADER'};
+ }
$buffer .= $cgi->start_html(
-title => $title,
-onload => $body_on_load,
- # -BGCOLOR => $colBG,
+ # -BGCOLOR => $colBG,
-style => \@hhshCSS,
-script => \@hhshJS,
-head=>$give_me,
$body_attrs
);
- foreach my $node($tree->nodes()){
+ foreach my $node($tree->nodes()){
$buffer .= build($parser, $node) if $node;
}
$buffer .= $cgi->end_html();
}
$parser->data()->{$property} = \$buffer;
}catch($e){
- HTMLIndexProcessorPluginException->throw(error=>$e ,show_trace=>1);
+ HTMLIndexProcessorPluginException->throw(error=>$e);
}
}
#
sub loadDocument($parser, $doc) {
my $slurp = do {
- open my $fh, '<:encoding(UTF-8)', $doc or HTMLIndexProcessorPluginException->throw("Document not avaliable: $doc");
+ open my $fh, '<:encoding(UTF-8)', $doc or HTMLIndexProcessorPluginException->throw(error=>"Document not avaliable -> \"$doc\" ", show_trace=>1);
local $/;
- <$fh>;
+ <$fh>;
};
if($doc =~/\.md$/){
- require MarkdownPlugin;
- my @r = @{MarkdownPlugin->new()->parse($slurp)};
+ require MarkdownPlugin;
+ my @r = @{MarkdownPlugin->new(undef)->parse($slurp)};
return $r[0];
}
- return \$slurp
+ return \$slurp
}
###
# Builds the html version out of a CNFNode.
-# CNFNode with specific tags here are converted also here,
+# CNFNode with specific tags here are converted also here,
# those that are out of the scope for normal standard HTML tags.
# i.e. HTML doesn't have row and cell tags. Neither has meta links syntax.
###
$bf .= "\t"x$tabs."<div".placeAttributes($node).">\n"."\t"x$tabs."<div>";
foreach my $n($node->nodes()){
if($n->{'_'} ne '#'){
- my $b = build($parser, $n, $tabs+1);
+ my $b = build($parser, $n, $tabs+1);
$bf .= "$b\n" if $b;
}
}
if($node->{'#'}){
my $v = $node->val();
$v =~ s/\n\n+/\<\/br>\n/gs;
- $bf .= "\t<div>\n\t<p>\n".$v."</p>\n\t</div>\n";
+ $bf .= "\t<div>\n\t<p>\n".$v."</p>\n\t</div>\n";
}
$bf .= "\t</div>\t</div>\n"
}elsif( $name eq 'row' || $name eq 'cell' ){
$bf .= "$b\n" if $b;
}
}
- $bf .= $node->val()."\n" if $node->{'#'};
+ $bf .= $node->val()."\n" if $node->{'#'};
$bf .= "\t"x$tabs."</div>"
}elsif( $name eq 'img' ){
$bf .= "\t\t<img".placeAttributes($node)."/>\n";
}elsif($name eq 'list_images'){
my $paths = $node->{'@@'};
- foreach my $ndp (@$paths){
+ foreach my $ndp (@$paths){
my $path = $ndp -> val();
my @ext = split(',',"jpg,jpeg,png,gif");
my $exp = " ".$path."/*.". join (" ".$path."/*.", @ext);
$bf .= qq(\t<div class='row'><div class='cell'>);
$bf .= qq(\t<a href="$enc"><img src="$enc" with='120' height='120'><br>$fn</a>\n</div></div>\n);
}
- }
+ }
}elsif($name eq '!'){
return "<!--".$node->val()."-->\n";
-
+
}elsif($node->{'*'}){ #Links are already captured, in future this might be needed as a relink from here for dynamic stuff?
my $lval = $node->{'*'};
- if($name eq 'file_list_html'){ #Special case where html links are provided.
+ if($name eq 'file_list_html'){ #Special case where html links are provided.
foreach(split(/\n/,$lval)){
$bf .= qq( [ $_ ] |) if $_
}
$bf =~ s/\|$//g;
}else{ #Generic included link value.
#is there property data for it?
- my $prop = $parser->data()->{$node->name()};
+ my $prop = $parser->data()->{$node->name()};
#if not has it been passed as an page constance?
- $prop = $parser -> {$node->name()} if !$prop;
+ $prop = $parser -> {$node->name()} if !$prop;
if ( !$prop ) {
if ( $parser->{STRICT} ) { die "Not found as property link -> " . $node->name()}
else { warn "Not found as property link -> " . $node->name()}
}
else{
my $spaced = 1;
- $bf .= "\t"x$tabs."<".$node->name().placeAttributes($node).">";
- foreach my $n($node->nodes()){
- my $b = build($parser, $n,$tabs+1);
- if ($b){
+ $bf .= "\t"x$tabs."<".$node->name().placeAttributes($node).">";
+ foreach my $n($node->nodes()){
+ my $b = build($parser, $n,$tabs+1);
+ if ($b){
if($b =~/\n/){
$bf =~ s/\n$//gs;
$bf .= "\n$b\n"
}else{
- $spaced=0;
- $bf .= $b;
+ $spaced=0;
+ $bf .= $b;
}
- }
+ }
}
-
+
if ($node->{'#'}){
$bf .= $node->val();
$bf .= "</".$node->name().">";
if(@$_[0] ne '#' && @$_[0] ne '_'){
if(@$_[1]){
$ret .= " ".@$_[0]."=\"".@$_[1]."\"";
- }else{
+ }else{
$ret .= " ".@$_[0]." ";
}
}
return $name eq 'p' || $name eq 'paragraph' ? 1 : 0
}
-1;
\ No newline at end of file
+1;
+
+=begin copyright
+Programed by : Will Budic
+EContactHash : 990MWWLWM8C2MI8K (https://github.com/wbudic/EContactHash.md)
+Source : https://github.com/wbudic/PerlCNF.git
+Documentation : Specifications_For_CNF_ReadMe.md
+ This source file is copied and usually placed in a local directory, outside of its repository 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.
+Open Source Code License -> https://github.com/wbudic/PerlCNF/blob/master/ISC_License.md
+=cut copyright
\ No newline at end of file
use Syntax::Keyword::Try;
use Exception::Class ('MarkdownPluginException');
use feature qw(signatures);
-use Date::Manip;
+use Clone qw(clone);
##no critic ControlStructures::ProhibitMutatingListFunctions
use constant VERSION => '1.0';
};
-sub new ($class, $fields={Language=>'English',DateFormat=>'US'}){
-
- if(ref($fields) eq 'REF'){
- warn "Hash reference required as argument for fields!"
+sub new ($class, $plugin){
+ my $settings;
+ if($plugin){
+ $settings = clone $plugin; #clone otherwise will get hijacked with blessings.
}
- my $lang = $fields->{'Language'};
- my $frmt = $fields->{'DateFormat'};
- Date_Init("Language=$lang","DateFormat=$frmt");
- $fields->{'disk_load'} = 0 if not exists $fields->{'disk_load'};
-
- return bless $fields, $class
+ $settings->{'disk_load'} = 0 if not exists $settings->{'disk_load'};
+ return bless $settings, $class
}
###
my $pret = ""; $pret = $1 if $1;
my $post = ""; $post = $4 if $4;
$tag = 'code'; $tag =$2 if $2;
- my $inline = $3;
+ my $inline = $3;
$inline = inlineCNF($inline,"");
my @code_tag = @{ setCodeTag($tag, "") };
$ln = qq($pret<$code_tag[1] class='$code_tag[0]'>$inline</$code_tag[1]>$post\n);
if($bqte){
while($bqte_nested-->0){$bqte .="</$bqte_tag></blockquote>\n"}
$para .= $bqte; $bqte_nested=0;
- undef $bqte;
+ undef $bqte;
}
- $para .= qq( ${style($v)} \n)
+ $para .= ${style($2)}."\n"
}
}else{
if($list_root && ++$list_end>1){
my $r = "<span ".C_PV.">[#[</span>";
$v =~ s/\[\#\[/$r/g;
if($v =~ m/\]\#\]/){
- $r = "<span ".C_PV.">]#]</span>";
+ $r = "<span ".C_PV.">]#]</span>";
$v =~ s/\]\#\]/$r/g;
}
return "$spc$v"
$v=~/(.*)(>+\s*)$/;
if(!$1 && $2){
$v = $2; $v =~ s/>/>/g;
- return "$spc<span ".C_B.">$v</span>"
+ return "$spc<span ".C_B.">$v</span>"
}else{
$oo =~ s/</</g;
if($v=~m/>>>/){
-1;
\ No newline at end of file
+1;
+
+=begin copyright
+Programed by : Will Budic
+EContactHash : 990MWWLWM8C2MI8K (https://github.com/wbudic/EContactHash.md)
+
+Open Source Code License -> https://github.com/wbudic/PerlCNF/blob/master/ISC_License.md
+=cut copyright
\ No newline at end of file
--- /dev/null
+package RSSFeedsPlugin;
+
+use strict;
+use warnings;
+
+use feature qw(signatures);
+use Scalar::Util qw(looks_like_number);
+use Syntax::Keyword::Try;
+use Clone qw(clone);
+use Capture::Tiny 'capture_stdout';
+use FileHandle;
+use XML::RSS::Parser;
+use Date::Manip::Date;
+use LWP::Protocol::https; #<-- 20230829 This module some times, will not be auto installed for some reason.
+use LWP::Simple;
+
+use Benchmark;
+
+use constant VERSION => '1.0';
+
+# require CNFNode;
+# require CNFDateTime;
+
+CNFParser::import();
+
+sub new ($class, $plugin){
+ my $settings;
+ if($plugin){
+ $settings = clone $plugin; #clone otherwise will get hijacked with blessings.
+ }
+ return bless $settings, $class
+}
+
+###
+# Process config data to contain expected fields.
+###
+sub process ($self, $parser, $property) {
+ my @data = @{$parser->data()->{$property}};
+ $self->{date} = now();
+ for my $idx (0 .. $#data){
+ my @col = @{$data[$idx]};
+ if($idx>0){
+ $col[0] = $idx+1;
+ $col[4] = $self-> {date} -> toTimestamp();
+ }else{
+ $col[4] = 'last_updated';
+ }
+ $data[$idx]=\@col;
+ }
+ $parser->addPostParseProcessor($self,'collectFeeds');
+ $parser->data()->{$property} =\@data;
+}
+
+sub collectFeeds($self,$parser) {
+ my $property = $self->{property};
+ my %hdr;
+ my @data = @{$parser->data()->{$property}};
+ my $page;
+ for my $idx (0 .. $#data){
+ my @col = @{$data[$idx]};
+ if($idx==0){
+ for my $i(0..$#col){ # Get the matching table column index names as scripted.
+ $hdr{$col[$i]}=$i
+ }
+ }else{
+ my $name = $col[$hdr{Name}]; # Now use the column names as coded, if names in script are changed, you must change.
+ my $tree = fetchFeed($self, $name, $col[$hdr{URL}], $col[$hdr{Description}]);
+ if($tree && ref($$tree) eq 'CNFNode'){
+ if(not isCNFTrue($self->{CNF_TREE_LOADED}) && isCNFTrue($self->{CNF_TREE_STORE})){
+ my $output_local = getOutputDir($self);
+ my $fname = $name; $fname =~ s/[\s|\W]/_/g; $fname = ">$output_local"."tree_feed_$fname.cnf";
+ my $FH = FileHandle->new($fname);
+ my $root = $$tree;
+ print $FH $root->toScript();
+ close $FH;
+ $parser->addTree($name, $tree);
+ }
+ if(isCNFTrue($self->{CONVERT_CNF_HTML})){
+ $page .= _treeToHTML($tree);
+ }
+ }else{
+ $parser-> warn("Feed '$name' bailed to return a CNFNode tree.")
+ }
+ }
+ }
+ $parser->data()->{PAGE} = \$page if $page;
+}
+### PerlCNF TREE to HTML Conversion Routine, XML based RSS of various Internet feeds convert to PerlCNF previously.
+sub _treeToHTML($tree){
+ my $root = $$tree;
+ my $feed = $root->node('Feed');
+ my $brew = $root->node('Brew');
+ my ($Title, $Published,$URL,$Description) = $feed -> array('Title','Published','URL','#');
+ my $bf = qq(
+ <div class="feed">
+ <div class="feeds_hdr">
+ <div class="feed_title"><h2>$Title</hd></div>
+ <div class-"feed_lbl"><div class="feed_hdr_lbl">Published:</div>$Published</span></div>
+ <div class-"feed_hdr"><div class="feed_hdr_lbl"><span style="text-align:right;width:inherit;">URL: </span></div>)._htmlURL($URL).qq(</div>
+ <div class-"feed_hdr"><p>$Description</p></div>
+ </div>
+ </div>
+ );
+ my $alt = 0;
+ foreach
+ my $item(@{$brew->items()}){
+ next if $item->name() ne 'Item';
+ my ($Title,$Link,$Date) = $item -> array('Title','Link','Date');
+ my $Description = $item -> node('Description') -> val();
+ $bf.= qq(
+ <div class="feed">
+ <div class="feeds_item_$alt">
+ <div class="feed_title"><div class="feed_lbl">Title:</div>$Title</div>
+ <div class="feed_link"><div class="feed_lbl">Link:</div>)._htmlURL($Link).qq(</div>
+ <div class="feed_Date"><div class="feed_lbl">Date:</div>$Date<div><hr></div></div>
+ <div class="feed_desc"><span>$Description<span></div>
+ </div>
+ </div>
+ );
+ $alt = $alt?0:1;
+ }
+ return $bf . '<hr class="feeds">'
+}
+
+sub _htmlURL {
+ my $link = shift;
+ return qq(<a class="feed_link" href="$link" target="feed">$link</a>)
+}
+
+sub getOutputDir($self){
+ my $output_local = $self->{OUTPUT_DIR};
+ if ($output_local){
+ $output_local.= '/';
+ mkdir $output_local unless -d $output_local;
+ }
+ return $output_local
+}
+
+sub fetchFeed($self,$name,$url,$description){
+
+ my ($MD, $tree, $brew,$bench);
+ my $console = isCNFTrue($self->{OUTPUT_TO_CONSOLE});
+ my $convert = isCNFTrue($self->{CONVERT_TO_CNF_NODES}); #<--_ If true,
+ my $stored = isCNFTrue($self->{CNF_TREE_STORE}); #<-\_ Will use a fast stashed local CNF tree instead of the XML::RSS::Parser.
+ my $markup = isCNFTrue($self->{OUTPUT_TO_MD});
+ my $benchmark = isCNFTrue($self->{BENCHMARK});
+ my $output_local= getOutputDir($self);
+ my $fname = $name; $fname =~ s/[\s|\W]/_/g;
+
+ $fname = $output_local."rss_$fname.rdf";
+
+ if(isCNFTrue($self->{RUN_FEEDS})){
+ if(-e $fname) {
+ my $now = new Date::Manip::Date -> new_date(); $now->parse("today");
+ my $fdate = new Date::Manip::Date;
+ my $fsepoch = (stat($fname))[9]; $fdate->parse("epoch $fsepoch"); $fdate->parse("3 business days");
+ my $delta = $fdate->calc($now);
+ $self->{CNF_TREE_LOADED} = 0;
+ if($now->cmp($fdate)>0){
+ unlink $fname;
+ }else{
+ my $cnf_fname = $name; $cnf_fname =~ s/[\s|\W]/_/g;
+ $cnf_fname = $output_local."tree_feed_$cnf_fname.cnf";
+ if($convert && $stored && -e $cnf_fname){
+ $self->{CNF_TREE_LOADED} = 1 if $_ = CNFParser -> new($cnf_fname,{DO_ENABLED => 1}) -> getTree('CNF_FEED');
+ return $_;
+ }
+ }
+ }
+ unless ( -e $fname ) {
+ try{
+ print "Fetching: $fname -> $url ...";
+ my $res = getstore($url, $fname);
+ if ($res == 200){
+ print "\e[2Adone!\n"
+ }else{
+ print "\e[2AError<$res>!\n"
+ }
+ }catch{
+ print "Error: $@.\n";
+ return;
+ }
+ }
+ }
+
+ my $parser = XML::RSS::Parser->new;
+ my $fh = FileHandle->new($fname);
+ my $t0 = Benchmark->new;
+ my $feed = $parser->parse_file($fh);
+ my $t1 = Benchmark->new;
+ my $td = timediff($t1, $t0);
+ $bench = "The XML parser for $fname took:\t".timestr($td)."\n" if $benchmark;
+
+ print "Parsing: $fname\n";
+
+ if(!$feed){
+ print "Failed to parse RSS feed:$name file:$fname\n";
+ return
+ }
+
+my $buffer = capture_stdout {
+ my $Title = $feed->query('/channel/title')->text_content;
+ if($console){
+ print 'x'x60,"\n";
+ print $Title, " [ Items: ",$feed->item_count, " ]\n";
+ print 'x'x60,"\n\n";
+ }else{
+ if($markup){
+ $fname = ">$output_local"."rss_$name.md";
+ $MD = FileHandle->new($fname);
+ #binmode($MD, ":encoding(UTF-8)");
+ print $MD "# ", $Title, "\n";
+ print $MD "\n $description\n\n";
+ print $MD "* Feed: [$name]($url)\n";
+ print $MD "* Items: ",$feed->item_count, "\n";
+ print $MD "* Date: ", $self->{date} -> toSchlong(), "\n\n";
+ }
+ }
+ if($convert){
+ my $published = CNFDateTime->new()->toTimestamp();
+ my $expires = new Date::Manip::Date -> new_date(); $expires->parse("7 business days");
+ $expires = $expires->printf(CNFDateTime::FORMAT());
+ my $fnm = $name; $fnm =~ s/[\s|\W]/_/g;
+ my $Title = $feed->query('/channel/title')->text_content;
+ my $feed = CNFNode -> new({'_'=>'Feed',Title => $Title, Published=>$published, Expires=>$expires,
+ File => $output_local."tree_feed_$fnm.cnf", '#'=>$description,
+ URL=>$url});
+ $tree = CNFNode -> new({'_'=>'CNF_FEED',Version=>'1.0', Release=>'1'});
+ $brew = CNFNode -> new({'_'=>'Brew'});
+ $tree -> add($feed)->add($brew);
+ }
+ $t0 = Benchmark->new;
+ my $items_cnt =0;
+ foreach my $item
+ ( $feed->query('//item') ) {
+ my $title = $item->query('title')->text_content;
+ my $date = $item->query('pubDate');
+ my $desc = $item->query('description')->text_content;
+ my $link = $item->query('link')->text_content;
+ my $CNFItm; $items_cnt++;
+ if(!$date) {
+ $date = $item->query('dc:date');
+ }
+ $date = $date->text_content;
+ $date = CNFDateTime::_toCNFDate($date, $self->{TZ})->toTimestampShort();
+ if($console){
+ print "Title : $title\n";
+ print "Link : $link\n";
+ print "Date : $date\n";
+ }else{
+ if($markup){
+ print $MD "\n## $title\n\n";
+ print $MD "* Link : <$link>\n";
+ print $MD "* Date : $date\n\n";
+ }
+ }
+ if($convert){
+ $CNFItm = CNFNode -> new({
+ '_' => 'Item',
+ Title => $title,
+ Link => $link,
+ Date => $date
+ });
+ $brew->add($CNFItm);
+ }
+ if (length($desc)>0){
+ if($console){
+ print '-'x20,"\n";
+ print $desc;
+ print "\n" if $desc !~ /\s$/
+ }else{
+ print $MD " $desc\n" if $markup;
+ }
+ if($convert){
+ $CNFItm->add(CNFNode -> new({'_'=>"Description",'#'=>\$desc}));
+ }
+ }
+ if($console){ print '-'x40,"\n";
+ }else{
+ print $MD "\n---\n" if $markup
+ }
+ }
+ $t1 = Benchmark->new;
+ $td = timediff($t1, $t0);
+ #TODO: XML query method is very slow, we will have to resort and test the CNFParser->find in comparance.
+ # Use XML RSS only to fetch, from foreing servers the feeds, and translate to CNFNodes.
+ $bench .= "The XML QUERY(//Item) for $fname items($items_cnt) took:\t".timestr($td)."\n" if $benchmark;
+
+ if($console){
+ print 'X'x20, " ", $feed->query('/channel/title')->text_content." Feed End ",'X'x20,"\n\n";
+ }else{
+ $MD->close() if $markup
+ }
+ };
+ print $buffer if $console;
+ print $bench if $benchmark;
+ return \$tree if $convert;
+ return \$buffer;
+}
+
+1; # <-- The score I get for using multipe functionality returns, I know. But if can swat 7 flies in one go, why not do it?
+
+=begin scrap
+
+# Remote PerlCNF Feed Format, opposed to RSS XML, would look like this:
+<<CNF_FEED<TREE>
+ Version = 1.0
+ Release = 1
+ <Feed<
+ Published: 2023-12-15
+ Expires: 2023-12-30
+ URL: https://lalaland.com/feeds.cgi
+ >Feed>
+ [brew[
+ [item[
+ Title:
+ Date:
+ Link:
+ [Description[
+ [#[
+
+ ]#]
+ ]Description]
+ ]item]
+ [item[
+ Title:
+ Date:
+ Link:
+ [Description[
+ [#[
+
+ ]#]
+ ]Description]
+ ]item]
+ ]brew]
+>>
+
+=cut scrap
+
+=begin copyright
+Programed by : Will Budic
+EContactHash : 990MWWLWM8C2MI8K (https://github.com/wbudic/EContactHash.md)
+Source : https://github.com/wbudic/PerlCNF.git
+Documentation : Specifications_For_CNF_ReadMe.md
+ This source file is copied and usually placed in a local directory, outside of its repository 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.
+Open Source Code License -> https://github.com/wbudic/PerlCNF/blob/master/ISC_License.md
+=cut copyright
\ No newline at end of file
--- /dev/null
+.feeds_hdr {
+ text-align: left;
+ vertical-align: auto;
+}
+
+.feed {
+ text-align:left;
+ width: 100%;
+ border: 1px solid black;
+ margin-bottom: 5px;
+ padding: 8px;
+}
+.feed div {
+ text-align:left;
+ border:0;
+
+}
+
+.feed_lbl {
+ font-weight: bolder;
+ font-style: normal;
+ width: 48px;
+ display: inline-flex;
+
+}
+.feed_hdr_lbl {
+ font-weight: bolder;
+ font-style: oblique;
+ width: 88px;
+ display: inline-flex;
+
+}
+.feeds hr{
+ color: black;
+ height: 1px;
+}
+
+
+
+.feed_hdr_r1 {
+ background-color: #e6ffff;
+ border: 1px solid black;
+ border-right: 1px solid black;
+ vertical-align: top;
+}
+
+.feed_hdr_r2 {
+ background-color: #ccffff;
+ border: 1px solid black;
+ border-right: 1px solid black;
+ vertical-align: top;
+}
+
+
+.feed_hdr_r3 {
+ background-color: #ccfff0;
+ border: 1px solid black;
+ border-right: 1px solid black;
+ vertical-align: top;
+}
+
+
var TXT_LOG_ROWS = 3;
var TIME_STAMP;
var LOCALE;
-var TIMEZONE;
+var TIMEZONE;
var DBI_LVAR_SZ;
var EDIT_LOG_TXT = "";
function onBodyLoad(toggle, locale, tz, today, expires, rs_cur, log_limit) {
LOCALE = locale;
- TIMEZONE = tz;
+ TIMEZONE = tz;
TIME_STAMP = new Date(today);
- DBI_LVAR_SZ = parseInt(log_limit);
-
+ DBI_LVAR_SZ = parseInt(log_limit);
+
onBodyLoadGeneric();
-
+
if (toggle) {
this.toggle("#div_srh", false);
let str = $('#el').val();
let m; var tot = 0;
- while ((m = regex.exec(str)) !== null) {
+ while ((m = regex.exec(str)) !== null) {
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
});
}
if(tot==0){tot=""}
- $('#am').val(tot.toFixed(2));
+ $('#am').val(tot.toFixed(2));
}
alignY: 'bottom',
offsetX: 5,
showTimeout: 100
- });
+ });
$("#menu_close").poshytip({
content: "<b>Do not click on this</b> little heart of mine,<br> <b>the menu will be closed</b>!",
className: 'tip-yellowsimple',
- showOn: 'mouseover',
+ showOn: 'mouseover',
alignTo: 'target',
alignX: 'center',
- alignY: 'bottom',
- showTimeout: 100
+ alignY: 'bottom',
+ showTimeout: 100
});
$("#menu_close").click(function() {
$("#dutch_left").poshytip({
content: "<span class='ui-icon ui-icon-arrowthick-1-w' style='float:none;'></span>Pass the dutchie to the <b>left</b> on side.",
className: 'tip-yellowsimple',
- showOn: 'mouseover',
+ showOn: 'mouseover',
alignTo: 'target',
alignX: 'center',
- alignY: 'bottom',
- showTimeout: 100
+ alignY: 'bottom',
+ showTimeout: 100
});
$("#dutch_right").poshytip({
content: "Pass the dutchie to the <b>right</b> on side.<span class='ui-icon ui-icon-arrowthick-1-e' style='float:none;'></span>",
className: 'tip-yellowsimple',
- showOn: 'mouseover',
+ showOn: 'mouseover',
alignTo: 'target',
alignX: 'center',
- alignY: 'bottom',
- showTimeout: 100
+ alignY: 'bottom',
+ showTimeout: 100
});
$('#ec').show();
$("#RTF").prop("checked", false);
-
- if ($('#editor-container').length) {
+
+ if ($('#editor-container').length) {
QUILL = new Quill('#editor-container', {
placeholder: 'Enter your Document here...',
theme: 'snow',
modules: {
formula: true,
- syntax: true,
- toolbar: '#toolbar-container'
+ syntax: true,
+ toolbar: '#toolbar-container'
}
});
Delta = Quill.import('delta');
CHANGE = new Delta();
-
+
// toggleDocument();
}
// let bg=RGBToHex('rgb(180, 169, 169)'); //<-is set in css file
// $('#toolbar-container').css('background-color',bg);
$('#toolbar-container').css('color',DEF_BACKGROUND);
-
+
}
var amf = $( "#amf" );//Amount Field Type dropdown
var ec = $( "#ec" ); //Category dropdown
}
}
}});
-
+
jQuery.fn.dispPos = function () {
this.css("position","absolute");
lbl = lbl.replace(/\s*$/g, "");
lbl = lbl + " ".repeat(16-lbl.length);
$("#lcat_v").html(lbl);
- $("#vc").val(ci);
- $("#cat_desc").show();
+ $("#vc").val(ci);
+ $("#cat_desc").show();
}).mouseenter(function(e){
var pr = $(event.target).parent(); pr = pr.attr('id');
if(pr){
}
}).mouseleave(function(e){$("#cat_desc").hide();});
-
+
$( "#dlgValidation" ).dialog({
dialogClass: "alert",
buttons: [
setPageSessionTimer(expires);
- $(function() {
+ $(function() {
$( "#rs_keys, #rs_keys2" ).autocomplete({
source: AUTOWORDS
});
});
var CHK_PREV;
-
+
$("#frm_log td").mouseover(function(e){
if(e.target != 'thr'){
var chk = $(e.target).find('input[name="chk"]');
var tr = e.target.parentNode.closest("tr");
if(tr.id != "summary_row" && tr.id !="brw_row"){
- if(CHK_PREV && !CHK_PREV.prop('checked')){
+ if(CHK_PREV && !CHK_PREV.prop('checked')){
CHK_PREV.closest("tr").removeClass("hover");
}
$(e.target.parentNode).closest("tr").addClass("hover");
$(e.target.parentNode).closest("tr").removeClass("hover");
}
});
-
+
if($("#isInViewMode").val()>0){
- this.toggle('#div_srh', true);
+ this.toggle('#div_srh', true);
this.toggle('#div_log', true);
}
- $(function() {
+ $(function() {
$( "#rs_keys, #rs_keys2" ).autocomplete({
source: AUTOWORDS
});
});
- display("Log page is ready!", 5);
-
+ display("Log page is ready!", 5);
+
}
function encodeText(){
}
function backToMain() {// func. required as chrome submits whole form on if buttons are not falsed.
- $("[name='confirmed']").val(0);
+ $("[name='confirmed']").val(0);
//window.location.href='main.cgi';
history.back();
return false;
if(msg){
return dialogModal( "Sorry Form Validation Failed", msg);
}
- $('#frm_entry').hide();
+ $('#frm_entry').hide();
encodeText();
return true;
}
date.value = year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + seconds;
$("#submit_is_edit").val("0");
- toggleDoc(true);
+ toggleDoc(true);
EDIT_LOG_TXT = "";
return false;
}
txt = txt.replace("/>/g", ">");
txt = txt.replace("/	/g", "\t");
txt = txt.replace(/br\s*[\/]?>/gi, "\n");
- txt = txt.replace(/\\n/g, "\n");
- txt = txt.replace(/ /g, "\n");
+ txt = txt.replace(/\\n/g, "\n");
+ txt = txt.replace(/ /g, "\n");
txt = txt.replace(/"/g, "\"");
txt = txt.replace(/'/g, "'");
-
+
return txt;
}
txt = txt.replace(/<hr>.*RTF<\/button>/gm, "");
txt = txt.replace(/<br\s*[\/]?>/gi, "\n");
//If first line bolded
-
+
let res = txt.matchAll(REGX_BTM);
if(res){
- txt = txt.replace(REGX_BTM, REGX_BTM_SUBST);
+ txt = txt.replace(REGX_BTM, REGX_BTM_SUBST);
}
return txt;
}
frm.rs_prev.value = 0;
frm.submit_is_view.value = 1;
frm.submit();
-
+
return false;
}
function resizeLogText() {
- $("#div_log .collpsd").show();
+ $("#div_log .collpsd").show();
$('#div_log').show();
-
+
if(TXT_LOG_ROWS == 3){
- TXT_LOG_ROWS = 10;
+ TXT_LOG_ROWS = 10;
}
else{
TXT_LOG_ROWS = 3;
}
$("#el").prop("rows",TXT_LOG_ROWS)
-
+
}
function resizeDoc() {
var distance = $(id).offset().top;
if($(this).scrollTop() <= distance){
$(id).toggle();
- }
+ }
}
}
else{
function showAll() {
show("#menu_page");
-
+
if(_show_all){
- $("#lnk_show_all").text("Hide All");
+ $("#lnk_show_all").text("Hide All");
show("#div_log");
show("#div_srh");
show("#tbl_hlp");
$("html, body").animate({ scrollTop: 0 }, "fast");
-
+
return false;
}
function submitNewCategory() {
- var frm = $("#frm_config");
+ var frm = $("#frm_config");
$("#frm_config [name='cchg']").val(2);
return true;
}
-function deleteSelected() {
+function deleteSelected() {
display("Please Wait!",150);
- $("#opr").val(0);
+ $("#opr").val(0);
$("#del_sel").click();
display("Please Wait!",150);
return false;
display("Please Wait!");
$("#opr").val(2);
return true;
-
+
}
function viewSelected() {
display("Please Wait!");
let id = chks[i].value;
let am = $("#a"+id).text();
let ct = $("#c"+id).text();
- let at = $("#f"+id).val();
+ let at = $("#f"+id).val();
am = am.replace(/\,/g,"");//rem formatting
if(ct=='Expense' || at=='2'){
var is_submit = (id==-1);
if (id < 1) {
- id = $("#submit_is_edit").val();
+ id = $("#submit_is_edit").val();
}
-
+
if(is_submit && (EDIT_LOG_TXT && $('#el').val() !== EDIT_LOG_TXT)){
if(formValidation()){ //If it is false, failed. That needs to altered by the user first.
},
buttons: [
- { text: "Yes",
+ { text: "Yes",
icons: { primary: "ui-icon-circle-check" },
- click: function() {
+ click: function() {
$( this ).dialog( "close" );
$("#frm_entry").submit();
}
},
-
+
{ text: "No",
click: function() {
decodeText();
- $( this ).dialog( "close" );
+ $( this ).dialog( "close" );
return false;
}
}
return false;
}
else
- if(is_submit && !$("#RTF").prop('checked')){
+ if(is_submit && !$("#RTF").prop('checked')){
return true;//we submit normal log entry
}
RTF_SUBMIT = true;
dialogModal("Service Error: "+response.status,response.responseText);
}
);
- if(is_submit){
+ if(is_submit){
$("#idx_cat").value = "SAVING DOCUMENT...";
$("#idx_cat").show();
//we must wait before submitting actual form!
return false;
}
-function saveRTFResult(result) {
+function saveRTFResult(result) {
//console.log("Result->" + result);
- var json = JSON.parse(result);
+ var json = JSON.parse(result);
$("html, body").animate({ scrollTop: 0 }, "fast");
-
+
let msg = json.response;
if(json.log_id==0){
- console.log(msg = "Saved to Buffer");
+ console.log(msg = "Saved to Buffer");
}else{
- console.log(msg = "Saved document by lid -> "+json.log_id);
+ console.log(msg = "Saved document by lid -> "+json.log_id);
}
display(msg, 5);
id = RTF_DOC_CUR_ID; // btn_load_rtf clicked
}
- QUILL.setText('Loading Document...\n');
+ QUILL.setText('Loading Document...\n');
$.post('json.cgi', {action:'load', id:id}, loadRTFResult).fail(
function(response) {dialogModal("Service Error: "+response.status,response.responseText);}
);
$("#q-scroll"+id).attr('class',cls);
if(css){
css.backgroundColor = DEF_BACKGROUND; //Removing colours makes it inherit from parent these properties.
- css.foregroundColor = "";//json.content.fg;
+ css.foregroundColor = "";//json.content.fg;
}
}
}
if(json.log_id==0){
console.log(msg = "Loaded in Buffer");
- $('#btn_zero_doc').show();
+ $('#btn_zero_doc').show();
}else{
console.log(msg = "Loaded in document by lid -> "+json.log_id);
$('#btn_load_doc').show();
}
- display(msg, 3);
+ display(msg, 3);
}
return "#" + r + g + b;
}
-function fetchBackup() {
- window.location = "config.cgi?bck=1";
+function fetchBackup() {
+ window.location = "config.cgi?bck=1";
setTimeout("location.reload(true);", 5000);
}
function deleteBackup() {
var timeout;
var now = new moment();
var val = expires.replace(/\+|[A-Z]|[a-z]/g, '');
-
+
if(expires.indexOf("h")>0){
timeout = moment(now).add(val, "h");
}
}
else
if(expires.indexOf("s")>0){
- if(val<60){val=2};
+ if(val<60){val=2};
timeout = moment(now).add(val, "s");
}
else{
}
display("<span id='sss_expired'>Session is about to expire!</span>",10);}
}
- var dsp = "<font size='1px;'>[" + tim + "]</font><span "+sty+"> Session expires in " + out + "</span>";
+ var dsp = "<font size='1px;'>[" + tim + "]</font><span "+sty+"> Session expires in " + out + "</span>";
$("#sss_status").html(dsp);
if(now.isAfter(timeout)){
$("#sss_status").html("<span id='sss_expired'><a href='login_ctr.cgi'>Page Session has Expired!</a></span>");
$("#ed").prop( "disabled", true );
$("#el").prop( "disabled", true );
$("#am").prop( "disabled", true );
- if($('#auto_logoff').val()=='1'){
- dialogModal("Page Session has Expired","Please login again!", true);
+ if($('#auto_logoff').val()=='1'){
+ dialogModal("Page Session has Expired","Please login again!", true);
}
}
}
function dialogModal(title, message, logout) {
-
+
if(logout) {
$('<div></div>').dialog({
modal: true,
$( this ).dialog( "close" );
location.reload();
}
- }
+ }
});
- }else {
-
+ }else {
+
$('<div></div>').dialog({
modal: true,
title: title,
--- /dev/null
+#!/usr/bin/env perl
+##
+# Module installer for projects.
+# Run this script from any Project directory containing perl modules or scripts.
+##
+use warnings; use strict;
+###
+# Prerequisites for this script itself. Run first:
+# cpan Term::ReadKey;
+# cpan Term::ANSIColor;
+## no critic (ProhibitStringyEval)
+use Term::ReadKey;
+use Term::ANSIColor qw(:constants);
+
+use constant PERL_FILES_GLOB => "*local/*.pl local/*.pm system/modules/*.pm htdocs/cgi-bin/*.cgi htdocs/cgi-bin/system/modules/*.pm tests/*.pm tests/*.pl .pl *.pm *.cgi";
+
+my $project = `pwd`."/".$0; $project =~ s/\/.*.pl$//g; $project =~ s/\s$//g;
+my @user_glob;
+our $PERL_VERSION = $^V->{'original'}; my $ERR = 0; my $key;
+
+print WHITE "\n *** Project Perl Module Installer coded by ",BRIGHT_RED, "https://github.com/wbudic", WHITE,"***", qq(
+ \nRunning scan on project path:$project
+ \nYou have Perl on $^O [$^X] version: $PERL_VERSION\n
+);
+print BLUE "<<@<\@INC<\n# Your default module package paths:\n", YELLOW;
+local $. = 0; foreach(@INC){
+ print $.++.".: $_\n";
+}
+print BLUE ">>\n", RESET;
+if($> > 0){
+ print "You are NOT installing system wide, which is required for webservers CGI.\nAre you sure about this?\n";
+ print "Tip -> If you are getting web page errors of some modules missing, try runing this utility as sudo.\n";
+}else{
+ print "You are INSTALLING modules SYSTEM WIDE, are you sure about this?\n"
+}
+if(@ARGV==0){
+ print qq(\nThis program will try to figure out now all the modules
+ required for this project, and install them if missing.
+ This can take some time.
+ );
+ print RED "Do you want to proceed (press either the 'Y'es or 'N'o key)?", RESET;
+
+do{
+ ReadMode('cbreak');
+ $key = ReadKey(0); print "\n";
+ ReadMode('normal');
+ exit 1 if(uc $key eq 'N');
+ $key = "[ENTER]" if $key =~ /\n/;
+ print "You have pressed the '$key' key, that is nice, but why?\nOnly the CTRL+C/Y/N keys do something normal." if uc $key ne 'Y';
+ }while(uc $key ne 'Y');
+}
+else{
+ foreach(@ARGV){
+ if(-d $_){
+ $_ =~ s/\s$//g;
+ print "\nGlobing for perl files in $project/$_";
+ my @located = glob("$_/*.pl $_/*.pm");
+ print " ... found ".@located." files.";
+ push @user_glob, @located;
+
+ }else{
+ warn "Argument: $_ is not a local directory."
+ }
+ }
+}
+
+my @locals=();
+print "\nGlobing for perl modules in project $project";
+my @perl_files = glob(PERL_FILES_GLOB);
+print " ... found ".@perl_files." files.\n";
+push @perl_files, @user_glob;
+my %modules; my %localPackages;
+foreach my $file(@perl_files){
+ next if $0 =~ /$file$/;
+ if($file =~ /(\w*)\.pm$/){
+ $localPackages{$1}=$file;
+ }
+ print "\nExamining:$file\n";
+ my $res = `perl -ne '/\\s*(^use\\s([a-zA-Z:]*))\\W/ and print "\$2;"' $file`;
+ my @list = split(/;+/,$res);
+ foreach(@list){
+ if($_=~ /^\w\d\.\d+.*/){
+ print "\tA specified 'use $_' found in ->$file\n";
+ if($PERL_VERSION ne $_){
+ $_ =~s/^v//g;
+ my @fv = split(/\./, $_);
+ $PERL_VERSION =~s/^v//g;
+ my @pv = split(/\./, $PERL_VERSION);
+ push @fv, 0 if @fv < 3;
+ for my$i(0..$#fv){
+ if( $pv[$i] < $fv[$i] ){
+ $ERR++; print "\n\t\033[31mERROR -> Perl required version has been found not matching.\033[0m\n";
+ last
+ }
+ }
+ }
+ }
+ }
+ foreach(@list){
+ $_ =~ s/^\s*|\s*use\s*//g;
+ $_ =~ s/[\'\"].*[\'\"]$//g;
+ next if !$_ or $_ =~ /^[a-z]|\d*\.\d*$|^\W/;
+ $_ =~ s/\(\)|\(.*\)|qw\(.*\)//g;
+ $modules{$_}=$file if $_;
+ print "$_\n";
+ }
+ if($file=~/\.pm$/){# it is presumed local package module.
+ $locals[@locals] = `perl -ne '/\\s*(^package\\s(\\w+))/ and print "\$2" and exit' $file`;
+ }
+}
+
+print WHITE "\nList of Modules required for thie project:\n";
+my @missing=();
+foreach my $mod (sort keys %modules){
+ my $missing;
+ eval "use $mod";
+ if ($@){
+ $missing[@missing] = $mod;
+ print MAGENTA "\t$mod \t in ", $modules{$mod}," is suspicious?\n";
+ }else{
+ print BLUE "\t$mod\n"
+ }
+}foreach(@missing){
+ if(exists $localPackages{$_}){
+ delete $modules{$_}
+ }else{
+ print BRIGHT_RED $_, MAGENTA, " is missing!\n"
+ }
+}
+my %skip_candidates;
+my $missing_count = @missing;
+if($missing_count>0){
+ foreach my $candidate(@missing){
+ foreach(@locals){
+ if($_ eq $candidate && not exists $skip_candidates{$_}){
+ $missing_count--;
+ $skip_candidates{$_} = 1;
+ print GREEN, "Found the missing $candidate module in locals.\n"
+ }
+ }
+ }
+}
+my $perls = `whereis perl`;
+print GREEN, "Following is all of ",$perls;
+print YELLOW, "Reminder -> Make sure you switched to the right brew release.\n" if $perls =~ /perlbrew/;
+print RESET, "Number of local modules:",scalar(@locals),"\n";
+print RESET, "Number of external modules:",scalar(keys %modules),"\n";
+print RESET, "Number of cpan modules about to be tried to install:",$missing_count,"\n";
+
+print GREEN, qq(
+Do you still want to continue to compile/test/install or check further modules?
+Only the first run is the depest and can take a long time, i.e. if you have to install over 5 modules.
+At other times this will only check further your current status.
+
+Now (press either the 'Y'es or 'N'o key) please?), RESET;
+do{
+ReadMode('cbreak');
+$key = ReadKey(0); print "\n";
+ReadMode('normal');
+ exit 1 if(uc $key eq 'N');
+ $key = "[ENTER]" if $key =~ /\n/;
+ print "You have pressed the '$key' key, that is nice, but why?\nOnly the CTRL+C/Y/N keys do something normal.\n" if uc $key ne 'Y';
+}while(uc $key ne 'Y');
+
+my ($mcnt,$mins) = (0,0);
+my @kangaroos = sort keys %skip_candidates;
+
+##
+# Some modules if found to be forcefeed. can be hardcoded here my friends, why not?
+# You got plenty of space on your disc, these days, don't you?
+##
+foreach ((
+ 'Syntax::Keyword::Try',
+ 'DBD::SQLite',
+ 'DBD::Pg',
+ 'LWP::Simple',
+ 'LWP::Protocol::https',
+ 'XML::LibXML::SAX'
+)){
+ $modules{$_}=1; print "Forcefeed: $_\n"
+}
+
+MODULES_LOOP:
+foreach my $mod (sort keys %modules){
+
+ foreach(@kangaroos){
+ if($_ eq $mod){
+ next MODULES_LOOP
+ }
+ }
+ $mcnt++;
+ ## no critic (ProhibitStringyEval)
+ eval "use $mod";
+ if ($@) {
+ system(qq(perl -MCPAN -e 'install $mod'));
+ if ($? == -1) {
+ print "failed to install: $mod\n";
+ }else{
+ my $v = eval "\$$mod\::VERSION";
+ $v = $v ? "(v$v)" : "";
+ print "Installed module $mod $v!\n";
+ $mins++
+ }
+ }else{
+ $mod =~ s/\s*$//;
+ my $v = eval "\$$mod\::VERSION";
+ $v = $v ? "(v$v)" : "";
+ print "Skipping module $mod $v, already installed!\n";
+ }
+}
+print "\nProject $project\nRequires $mcnt modules.\nInstalled New: $mins\n";
+print "WARNING! - This project requires in ($ERR) parts code that might not be compatible yet with your installed/running version of perl (v$PERL_VERSION).\n"
+if $ERR;
+
+
+=begin copyright
+Programed by : Will Budic
+EContactHash : 990MWWLWM8C2MI8K (https://github.com/wbudic/EContactHash.md)
+Source : https://github.com/wbudic/PerlCNF.git
+Documentation : Specifications_For_CNF_ReadMe.md
+ This source file is copied and usually placed in a local directory, outside of its repository 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.
+Open Source Code License -> https://github.com/wbudic/PerlCNF/blob/master/ISC_License.md
+=cut copyright
\ No newline at end of file
--- /dev/null
+<<CNF_FEED<TREE>
+ Release: 1
+ Version: 1.0
+ <Feed<
+ Expires: 2023-09-26 08:46:42
+ File: ./rss_output/tree_feed_CPAN.cnf
+ Published: 2023-09-14 22:46:42.042 UTC
+ Title: 'Recent CPAN uploads - MetaCPAN'
+ URL: http://search.cpan.org/uploads.rdf
+ [#[
+ CPAN modules news and agenda.
+ ]#]
+ >Feed>
+ <Brew<
+ <Item<
+ Date: 2023-09-14 08:33:57
+ Link: https://metacpan.org/release/SHLOMIF/XML-GrammarBase-0.2.10
+ Title: XML-GrammarBase-0.2.10
+ <Description<
+ [#[
+ <p>Provide roles and base classes for processors of specialized XML grammars.</p><p>Changes for 0.2.10 - 2023-09-14</p><ul><li>Better compatibility with bleadperl</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-14 08:01:08
+ Link: https://metacpan.org/release/SYP/Net-Curl-0.54_2
+ Title: Net-Curl-0.54_2
+ <Description<
+ [#[
+ Perl interface for libcurl
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-14 03:02:53
+ Link: https://metacpan.org/release/ANATOFUZ/Teng-0.34
+ Title: Teng-0.34
+ <Description<
+ [#[
+ <p>very simple DBI wrapper/ORMapper</p><p>Changes for 0.34 - 2023-09-14T03:02:36Z</p><ul><li>[IMPORTANT] change the minimum supported perl version to 5.16 (#165)</li>
+ <li>FIX: Don't update when set column from null to null (#164 thanks hitode909)</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-14 02:18:56
+ Link: https://metacpan.org/release/KIMOTO/SPVM-0.989042
+ Title: SPVM-0.989042
+ <Description<
+ [#[
+ <p>SPVM Language</p><p>Changes for 0.989042 - 2023-09-12</p><ul><li>Incompatible Changes</li>
+ <li>New Features</li>
+ <li>Document Improvement</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-14 00:05:27
+ Link: https://metacpan.org/release/PERLANCAR/Perinci-To-Doc-0.881
+ Title: Perinci-To-Doc-0.881
+ <Description<
+ [#[
+ <p>Convert Rinci metadata to documentation</p><p>Changes for 0.881 - 2023-07-09</p><ul><li>No functional changes.</li>
+ <li>Remove usage of smartmatch.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 23:57:14
+ Link: https://metacpan.org/release/MARIOROY/MCE-Shared-1.886
+ Title: MCE-Shared-1.886
+ <Description<
+ [#[
+ <p>MCE extension for sharing data supporting threads and processes</p><p>Changes for 1.886</p><ul><li>Add Android support. This required moving MCE::Shared::Base::Common out of MCE::Shared::Base to separate file MCE::Shared::Common.</li>
+ <li>Bump MCE dependency to 1.889.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 23:37:02
+ Link: https://metacpan.org/release/MARIOROY/MCE-1.889
+ Title: MCE-1.889
+ <Description<
+ [#[
+ <p>Many-Core Engine for Perl providing parallel processing capabilities</p><p>Changes for 1.889</p><ul><li>Add Android support. Thank you, Dimitrios Kechagias.</li>
+ <li>Revert defer signal-handling in MCE::Channel (send2 method).</li>
+ <li>Improve mutex synchronize (aka enter) with guard capability. Thank you, Jos� Joaqu�n Atria.</li>
+ <li>Fix mutex re-entrant lock on the Windows platform.</li>
+ <li>Add mutex guard_lock method.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 23:35:35
+ Link: https://metacpan.org/release/MARIOROY/Mutex-1.011
+ Title: Mutex-1.011
+ <Description<
+ [#[
+ <p>Various locking implementations supporting processes and threads</p><p>Changes for 1.011</p><ul><li>Bump version.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 22:40:32
+ Link: https://metacpan.org/release/EXODIST/Test2-Suite-0.000156
+ Title: Test2-Suite-0.000156
+ <Description<
+ [#[
+ <p>Distribution with a rich set of tools built upon the Test2 framework.</p><p>Changes for 0.000156 - 2023-09-13T15:11:52-07:00</p><ul><li>Fix typo in POD for Test2::Util::Importer</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 21:57:38
+ Link: https://metacpan.org/release/PEVANS/Device-AVR-UPDI-0.14
+ Title: Device-AVR-UPDI-0.14
+ <Description<
+ [#[
+ <p>interact with an AVR microcontroller over UPDI</p><p>Changes for 0.14 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 21:30:55
+ Link: https://metacpan.org/release/AJNN/Mac-Finder-Tags-0.02
+ Title: Mac-Finder-Tags-0.02
+ <Description<
+ [#[
+ <p>Access macOS file tags (aka Finder labels)</p><p>Changes for 0.02 - 2023-09-13</p><ul><li>Avoid syntax that causes warnings in Object::Pad 0.801.</li>
+ <li>Tests no longer fail for unexpected warnings, except during author testing.</li>
+ <li>Drop Devel::CheckOS prerequisite (by bundling it).</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 21:00:16
+ Link: https://metacpan.org/release/MICHIELB/GD-Barcode-2.00
+ Title: GD-Barcode-2.00
+ <Description<
+ [#[
+ <p>Create barcode image with GD</p><p>Changes for 2.00 - 2023-09-13</p><ul><li>'Production' release, no changes to 1.99_03</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 20:58:49
+ Link: https://metacpan.org/release/BENNIE/VMware-vCloud-2.403
+ Title: VMware-vCloud-2.403
+ <Description<
+ [#[
+ <p>VMware vCloud API</p><p>Changes for 2.403 - 2023-09-13</p><ul><li>Added: POD test</li>
+ <li>Improved: 'use warnings' on all modules</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 20:44:39
+ Link: https://metacpan.org/release/RKAPL/EAI-Wrap-0.3
+ Title: EAI-Wrap-0.3
+ <Description<
+ [#[
+ framework for easy creation of Enterprise Application Integration tasks
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 20:27:57
+ Link: https://metacpan.org/release/MIYAGAWA/Starman-0.4017
+ Title: Starman-0.4017
+ <Description<
+ [#[
+ <p>High-performance preforking PSGI/Plack web server</p><p>Changes for 0.4017 - 2023-09-13T13:27:02Z</p><ul><li>Handle EINTR when doing sysread calls (Rob Mueller) #148</li>
+ <li>Requires perl 5.14</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 17:41:55
+ Link: https://metacpan.org/release/EXODIST/Term-Table-0.017
+ Title: Term-Table-0.017
+ <Description<
+ [#[
+ <p>Format a header and rows into a table</p><p>Changes for 0.017 - 2023-09-13T10:41:08-07:00</p><ul><li>Remove 'Importer' dependency</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 16:02:42
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-TSL256x-0.09
+ Title: Device-Chip-TSL256x-0.09
+ <Description<
+ [#[
+ <p>chip driver for TSL256x</p><p>Changes for 0.09 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 16:01:19
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-TCS3472x-0.05
+ Title: Device-Chip-TCS3472x-0.05
+ <Description<
+ [#[
+ <p>chip driver for TCS3472x-family</p><p>Changes for 0.05 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 16:01:04
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-SSD1306-0.14
+ Title: Device-Chip-SSD1306-0.14
+ <Description<
+ [#[
+ <p>chip driver for monochrome OLED modules</p><p>Changes for 0.14 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:59:38
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-Si5351-0.02
+ Title: Device-Chip-Si5351-0.02
+ <Description<
+ [#[
+ <p>chip driver for Si5351</p><p>Changes for 0.02 - 2023-09-13</p><ul><li>CHANGES</li>
+ <li>BUGFIXES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:58:10
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-SDCard-0.04
+ Title: Device-Chip-SDCard-0.04
+ <Description<
+ [#[
+ <p>chip driver for SD and MMC cards</p><p>Changes for 0.04 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:56:44
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-PCF8574-0.06
+ Title: Device-Chip-PCF8574-0.06
+ <Description<
+ [#[
+ <p>chip driver for a PCF8574 or PCA8574</p><p>Changes for 0.06 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:56:33
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-PCF8563-0.04
+ Title: Device-Chip-PCF8563-0.04
+ <Description<
+ [#[
+ <p>chip driver for a PCF8563</p><p>Changes for 0.04 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:54:59
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-OPT3001-0.03
+ Title: Device-Chip-OPT3001-0.03
+ <Description<
+ [#[
+ <p>chip driver for OPT3001</p><p>Changes for 0.03 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:53:40
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-nRF24L01P-0.08
+ Title: Device-Chip-nRF24L01P-0.08
+ <Description<
+ [#[
+ <p>chip driver for a nRF24L01+</p><p>Changes for 0.08 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:52:21
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-NoritakeGU_D-0.06
+ Title: Device-Chip-NoritakeGU_D-0.06
+ <Description<
+ [#[
+ <p>chip driver for Noritake GU-D display modules</p><p>Changes for 0.06 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:50:58
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-MPL3115A2-0.13
+ Title: Device-Chip-MPL3115A2-0.13
+ <Description<
+ [#[
+ <p>chip driver for a MPL3115A2</p><p>Changes for 0.13 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:49:37
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-MCP23x17-0.07
+ Title: Device-Chip-MCP23x17-0.07
+ <Description<
+ [#[
+ <p>chip driver for the MCP23x17 family</p><p>Changes for 0.07 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:48:18
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-MAX7219-0.09
+ Title: Device-Chip-MAX7219-0.09
+ <Description<
+ [#[
+ <p>chip driver for a MAX7219</p><p>Changes for 0.09 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:47:00
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-MAX44009-0.05
+ Title: Device-Chip-MAX44009-0.05
+ <Description<
+ [#[
+ <p>chip driver for MAX44009</p><p>Changes for 0.05 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:45:41
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-INA219-0.10
+ Title: Device-Chip-INA219-0.10
+ <Description<
+ [#[
+ <p>chip driver for an INA219</p><p>Changes for 0.10 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:44:22
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-HTU21D-0.10
+ Title: Device-Chip-HTU21D-0.10
+ <Description<
+ [#[
+ <p>chip driver for HTU21D</p><p>Changes for 0.10 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:43:03
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-DS1307-0.08
+ Title: Device-Chip-DS1307-0.08
+ <Description<
+ [#[
+ <p>chip driver for a DS1307</p><p>Changes for 0.08 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:41:44
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-CCS811-0.03
+ Title: Device-Chip-CCS811-0.03
+ <Description<
+ [#[
+ <p>chip driver for CCS811</p><p>Changes for 0.03 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:40:25
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-CC1101-0.09
+ Title: Device-Chip-CC1101-0.09
+ <Description<
+ [#[
+ <p>chip driver for a CC1101</p><p>Changes for 0.09 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:38:58
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-BV4243-0.04
+ Title: Device-Chip-BV4243-0.04
+ <Description<
+ [#[
+ <p>chip driver for a BV4243</p><p>Changes for 0.04 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:37:36
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-BNO055-0.04
+ Title: Device-Chip-BNO055-0.04
+ <Description<
+ [#[
+ <p>chip driver for BNO055</p><p>Changes for 0.04 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:36:09
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-BME280-0.06
+ Title: Device-Chip-BME280-0.06
+ <Description<
+ [#[
+ <p>chip driver for BME280</p><p>Changes for 0.06 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:33:22
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-AVR_HVSP-0.07
+ Title: Device-Chip-AVR_HVSP-0.07
+ <Description<
+ [#[
+ <p>high-voltage serial programming for AVR chips</p><p>Changes for 0.07 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:26:50
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-AS3935-0.04
+ Title: Device-Chip-AS3935-0.04
+ <Description<
+ [#[
+ <p>chip driver for AS3935</p><p>Changes for 0.04 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:25:06
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-AnalogConverters-0.15
+ Title: Device-Chip-AnalogConverters-0.15
+ <Description<
+ [#[
+ <p>a collection of chip drivers</p><p>Changes for 0.15 - 2023-08-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 15:23:40
+ Link: https://metacpan.org/release/PEVANS/Device-Chip-AD9833-0.05
+ Title: Device-Chip-AD9833-0.05
+ <Description<
+ [#[
+ <p>chip driver for AD9833</p><p>Changes for 0.05 - 2023-09-13</p><ul><li>CHANGES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 14:58:27
+ Link: https://metacpan.org/release/YANICK/Dist-Zilla-Plugin-CoalescePod-1.0.0
+ Title: Dist-Zilla-Plugin-CoalescePod-1.0.0
+ <Description<
+ [#[
+ <p>merge .pod files into their .pm counterparts</p><p>Changes for 1.0.0 - 2023-09-13</p><ul><li>API CHANGES</li>
+ <li>STATISTICS</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 14:57:01
+ Link: https://metacpan.org/release/YANICK/Dist-Zilla-Plugin-CoalescePod-0.3.1
+ Title: Dist-Zilla-Plugin-CoalescePod-0.3.1
+ <Description<
+ [#[
+ <p>merge .pod files into their .pm counterparts</p><p>Changes for 0.3.1 - 2023-09-13</p><ul><li>STATISTICS</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 14:10:21
+ Link: https://metacpan.org/release/PEVANS/App-sdview-Output-Tickit-0.03
+ Title: App-sdview-Output-Tickit-0.03
+ <Description<
+ [#[
+ <p>interactive terminal-based viewer for App::sdview</p><p>Changes for 0.03 - 2023-09-13</p><ul><li>CHANGES</li>
+ <li>BUGFIXES</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 11:25:40
+ Link: https://metacpan.org/release/AWNCORP/Venus-4.11
+ Title: Venus-4.11
+ <Description<
+ [#[
+ <p>OO Library for Perl 5</p><p>Changes for 4.11 - 2023-09-13</p><ul><li>[feature] Implement Venus::Assert#includes</li>
+ <li>[feature] Implement Venus::Future</li>
+ <li>[feature] Refactor Venus::Assert, Implement Venus::{Coercion,Constraint}</li>
+ <li>[feature] Implement Venus::Space#{patch,patched,unpatch}</li>
+ <li>[feature] Implement Venus::Sealed</li>
+ <li>[feature] Implement Venus::Atom</li>
+ <li>[feature] Implement Venus::Enum</li>
+ <li>[feature] Implement Venus::Role::Superable</li>
+ <li>[feature] Implement Venus::Role::Patchable</li>
+ <li>[feature] Implement Venus#clone</li>
+ <li>[feature] Implement Venus::Process#future</li>
+ <li>[feature] Implement Venus::Future#wait</li>
+ <li>[update] Refactor Venus::Test</li>
+ <li>[update] Add test and documentation for Venus::Process#is_dyadic</li>
+ <li>[update] Update Venus::Process#await, auto-reap processes</li>
+ <li>[update] Research CPANTS issue with Venus::Process</li>
+ <li>[update] Update Venus::Process, prevent PPID in dyads</li>
+ <li>[update] Use Venus::Check types in all signatures</li>
+ <li>[update] Update Venus#async to return Venus::Future</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 11:00:19
+ Link: https://metacpan.org/release/JBAIER/Pass-OTP-1.6
+ Title: Pass-OTP-1.6
+ <Description<
+ [#[
+ <p>Perl implementation of HOTP / TOTP algorithms</p><p>Changes for 1.6 - 2023-09-13</p><ul><li>fix SHA384 and SHA512 blocksize (#1)</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 10:35:02
+ Link: https://metacpan.org/release/BOD/Image-Square-0.01_4
+ Title: Image-Square-0.01_4
+ <Description<
+ [#[
+ <p>Crop and resize an image to create a square image</p><p>Changes for 0.01_4</p><ul><li>Tests still fail on different builds of GD. Now using PNG as input image and native GD format for output.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 09:13:52
+ Link: https://metacpan.org/release/MRUEDA/Convert-Pheno-0.13
+ Title: Convert-Pheno-0.13
+ <Description<
+ [#[
+ <p>A module to interconvert common data models for phenotypic data</p><p>Changes for 0.13 - 2023-09-12T00:00:00Z</p><ul><li>Pushing new version after passing all tests</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 09:12:25
+ Link: https://metacpan.org/release/TONYC/Imager-zxing-1.001
+ Title: Imager-zxing-1.001
+ <Description<
+ [#[
+ <p>Barcode scanning with libzxing-cpp</p><p>Changes for 1.001</p><ul><li>re-work std::string handling to use the typemap</li>
+ <li>fix "decoder" -> "decode" in the SYNOPSIS</li>
+ <li>support all Imager image layouts</li>
+ <li>require a recent enough ExtUtils::CppGuess and set the required C++ standard</li>
+ <li>allow the zxing-cpp package name for pkg-config, which seems to be what packagers used before upstream decided on "zxing.pc". https://github.com/tonycoz/imager-zxing/issues/1</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 05:55:56
+ Link: https://metacpan.org/release/KIMOTO/SPVM-Sys-0.491
+ Title: SPVM-Sys-0.491
+ <Description<
+ [#[
+ <p>System Calls for File IO, User, Process, Signal, Socket</p><p>Changes for 0.491 - 2023-09-13</p><ul><li>New Features</li>
+ <li>Incompatible Changes</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 04:12:50
+ Link: https://metacpan.org/release/GRYPHON/Log-Dispatch-Email-Mailer-1.13
+ Title: Log-Dispatch-Email-Mailer-1.13
+ <Description<
+ [#[
+ <p>Log::Dispatch::Email subclass that sends mail using Email::Mailer</p><p>Changes for 1.13 - 2023-09-12T21:12:32-07:00</p><ul><li>Require exact v1.23 (resolves issue #5)</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 04:11:27
+ Link: https://metacpan.org/release/GRYPHON/exact-me-1.05
+ Title: exact-me-1.05
+ <Description<
+ [#[
+ <p>Original program path locations extension for exact</p><p>Changes for 1.05 - 2023-09-12T21:10:17-07:00</p><ul><li>Remove redundant strict (since it's provided by exact)</li>
+ <li>New import signature change required by exact v1.23</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 04:10:01
+ Link: https://metacpan.org/release/GRYPHON/exact-lib-1.04
+ Title: exact-lib-1.04
+ <Description<
+ [#[
+ <p>Compile-time @INC manipulation extension for exact</p><p>Changes for 1.04 - 2023-09-12T21:09:28-07:00</p><ul><li>Remove redundant strict (since it's provided by exact)</li>
+ <li>New import signature change required by exact v1.23</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 04:09:57
+ Link: https://metacpan.org/release/GRYPHON/exact-fun-1.01
+ Title: exact-fun-1.01
+ <Description<
+ [#[
+ <p>Functions and methods with parameter lists for exact</p><p>Changes for 1.01 - 2023-09-12T21:08:36-07:00</p><ul><li>Use Import::Into instead of eval to inject/import</li>
+ <li>New import signature change required by exact v1.23</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 04:08:39
+ Link: https://metacpan.org/release/GRYPHON/exact-conf-1.08
+ Title: exact-conf-1.08
+ <Description<
+ [#[
+ <p>Cascading merged application configuration extension for exact</p><p>Changes for 1.08 - 2023-09-12T21:07:37-07:00</p><ul><li>Remove redundant strict (since it's provided by exact)</li>
+ <li>New import signature change required by exact v1.23</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 04:07:18
+ Link: https://metacpan.org/release/GRYPHON/exact-cli-1.07
+ Title: exact-cli-1.07
+ <Description<
+ [#[
+ <p>Command-line interface helper utilities extension for exact</p><p>Changes for 1.07 - 2023-09-12T21:06:47-07:00</p><ul><li>Remove redundant strict (since it's provided by exact)</li>
+ <li>New import signature change required by exact v1.23</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 04:05:52
+ Link: https://metacpan.org/release/GRYPHON/exact-class-1.19
+ Title: exact-class-1.19
+ <Description<
+ [#[
+ <p>Simple class interface extension for exact</p><p>Changes for 1.19 - 2023-09-12T21:05:22-07:00</p><ul><li>New import signature change required by exact v1.23</li>
+ <li>Use Import::Into instead of eval to inject code</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 01:04:01
+ Link: https://metacpan.org/release/MBRADSHAW/Mail-BIMI-3.20230913
+ Title: Mail-BIMI-3.20230913
+ <Description<
+ [#[
+ <p>BIMI object</p><p>Changes for 3.20230913 - 2023-09-13</p><ul><li>Add policy.mark-type to Authentication-Results</li>
+ <li>Add policy.experimental to Authentication-Results</li>
+ <li>Add options to limit which mark types a MBP accepts</li>
+ <li>Add options to limit acceptance of experimental certificates</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-13 00:06:02
+ Link: https://metacpan.org/release/PERLANCAR/App-rimetadb-0.226
+ Title: App-rimetadb-0.226
+ <Description<
+ [#[
+ <p>Manage a Rinci metadata database</p><p>Changes for 0.226 - 2023-07-09</p><ul><li>No functional changes.</li>
+ <li>Remove the usage of smartmatch.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 23:33:11
+ Link: https://metacpan.org/release/DRCLAW/constant-more-v0.3.0
+ Title: constant-more-v0.3.0
+ <Description<
+ [#[
+ <p>Constants and Enumerations. Assign constant values from the command line</p><p>Changes for v0.3.0 - 2023-09-13</p><ul><li>Features</li>
+ <li>Tests</li>
+ <li>POD</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 23:07:51
+ Link: https://metacpan.org/release/GRYPHON/exact-1.23
+ Title: exact-1.23
+ <Description<
+ [#[
+ <p>Perl pseudo pragma to enable strict, warnings, features, mro, filehandle methods</p><p>Changes for 1.23 - 2023-09-12T16:06:03-07:00</p><ul><li>Improve/fix import of packages into other packages (resolves issue #4)</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 22:14:53
+ Link: https://metacpan.org/release/JIMAVERA/ODF-MailMerge-1.000
+ Title: ODF-MailMerge-1.000
+ <Description<
+ [#[
+ <p>"Mail Merge" or just substitute tokens in ODF documents</p><p>Changes for 1.000</p><ul><li>ODF::MailMerge::Engine->new positional args eliminated; now use proto_elt => $table # specify the object directly context => $context, proto_tag => "tagstring" # search for it Modifier :die ("Delete If Empty") replaces :delempty</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 21:49:07
+ Link: https://metacpan.org/release/SHANCOCK/Perl-Tidy-20230912
+ Title: Perl-Tidy-20230912
+ <Description<
+ [#[
+ indent and reformat perl scripts
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 21:45:10
+ Link: https://metacpan.org/release/BOD/Image-Square-0.01_3
+ Title: Image-Square-0.01_3
+ <Description<
+ [#[
+ Crop and resize an image to create a square image
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 19:38:33
+ Link: https://metacpan.org/release/TURNERJW/StreamFinder-2.19
+ Title: StreamFinder-2.19
+ <Description<
+ [#[
+ <p>Fetch actual raw streamable URLs from various radio-station, video & podcast websites.</p><p>Changes for 2.19 - 2023-09-12</p><ul><li>StreamFinder::Youtube - 1) Fix failure to fetch artist, icon, etc. sometimes on embedded IFRAME urls (slight site changes) and first episode from some channels. 2) Add -youtube-site argument to specify a different default youtube site (default https://www.youtube.com). 3) Add ability to parse youtube channel URLs containing an at-sign, ie.: https://www.youtube.com/@channelID.</li>
+ <li>StreamFinder::Subsplash - Restore as EXPERIMENTAL, as this site seems to now work again, at least for audio streams on some sites.</li>
+ <li>StreamFinder::Anystream - doc. touchups.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 19:00:33
+ Link: https://metacpan.org/release/AWNCORP/Venus-4.10
+ Title: Venus-4.10
+ <Description<
+ [#[
+ <p>OO Library for Perl 5</p><p>Changes for 4.10 - 2023-09-12</p><ul><li>[feature] Implement Venus::Assert#includes</li>
+ <li>[feature] Implement Venus::Future</li>
+ <li>[feature] Refactor Venus::Assert, Implement Venus::{Coercion,Constraint}</li>
+ <li>[feature] Implement Venus::Space#{patch,patched,unpatch}</li>
+ <li>[feature] Implement Venus::Sealed</li>
+ <li>[feature] Implement Venus::Atom</li>
+ <li>[feature] Implement Venus::Enum</li>
+ <li>[feature] Implement Venus::Role::Superable</li>
+ <li>[feature] Implement Venus::Role::Patchable</li>
+ <li>[feature] Implement Venus#clone</li>
+ <li>[feature] Implement Venus::Process#future</li>
+ <li>[feature] Implement Venus::Future#wait</li>
+ <li>[update] Refactor Venus::Test</li>
+ <li>[update] Add test and documentation for Venus::Process#is_dyadic</li>
+ <li>[update] Update Venus::Process#await, auto-reap processes</li>
+ <li>[update] Research CPANTS issue with Venus::Process</li>
+ <li>[update] Update Venus::Process, prevent PPID in dyads</li>
+ <li>[update] Use Venus::Check types in all signatures</li>
+ <li>[update] Update Venus#async to return Venus::Future</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 17:09:39
+ Link: https://metacpan.org/release/DERIV/Net-Async-Blockchain-0.003
+ Title: Net-Async-Blockchain-0.003
+ <Description<
+ [#[
+ <p>base for blockchain subscription clients.</p><p>Changes for 0.003 - 2023-09-12T17:08:09+00:00</p><ul><li>Improvements</li>
+ <li>Breaking changes</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 14:47:38
+ Link: https://metacpan.org/release/OALDERS/Open-This-0.000033
+ Title: Open-This-0.000033
+ <Description<
+ [#[
+ <p>Try to Do the Right Thing when opening files</p><p>Changes for 0.000033 - 2023-09-12T14:46:08Z</p><ul><li>Add support for IntellJ IDEA, VSCode, VSCodium and more. Also fix typo (GH#51) (mcneb10)</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 13:50:33
+ Link: https://metacpan.org/release/NLNETLABS/Net-DNS-SEC-1.22
+ Title: Net-DNS-SEC-1.22
+ <Description<
+ [#[
+ DNSSEC extensions to Net::DNS
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 09:35:41
+ Link: https://metacpan.org/release/MIKIHOSHI/WebService-Mailgun-0.16
+ Title: WebService-Mailgun-0.16
+ <Description<
+ [#[
+ <p>API client for Mailgun (https://mailgun.com/)</p><p>Changes for 0.16 - 2023-09-12T09:33:42Z</p><ul><li>fix document</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 09:29:10
+ Link: https://metacpan.org/release/MIKIHOSHI/WebService-Mailgun-0.15.1
+ Title: WebService-Mailgun-0.15.1
+ <Description<
+ [#[
+ <p>API client for Mailgun (https://mailgun.com/)</p><p>Changes for 0.15.1 - 2023-09-12T09:27:19Z</p><ul><li>fix document</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 09:16:10
+ Link: https://metacpan.org/release/MRUEDA/Convert-Pheno-0.12_4
+ Title: Convert-Pheno-0.12_4
+ <Description<
+ [#[
+ A module to interconvert common data models for phenotypic data
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 08:44:03
+ Link: https://metacpan.org/release/LICHTKIND/Graphics-Toolkit-Color-1.61
+ Title: Graphics-Toolkit-Color-1.61
+ <Description<
+ [#[
+ <p>color palette creation helper</p><p>Changes for 1.61 - 2023-09-12</p><ul><li>= fix tests</li>
+ <li>+ renamed complementary method => complement</li>
+ <li>- deprecated complementary, will be removed at 2.0</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 06:33:21
+ Link: https://metacpan.org/release/MERKYS/Graph-SSSR-0.1.0
+ Title: Graph-SSSR-0.1.0
+ <Description<
+ [#[
+ <p>Find Smallest Set of Smallest Rings in graphs</p><p>Changes for 0.1.0 - 2022-12-15</p><ul><li>Initial release.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 03:59:54
+ Link: https://metacpan.org/release/DJZORT/Net-Proxmox-VE-0.38
+ Title: Net-Proxmox-VE-0.38
+ <Description<
+ [#[
+ <p>Pure perl API for Proxmox virtualisation</p><p>Changes for 0.38 - 2023-09-11</p><ul><li>fix/use correct parameter name for user in tests thanks to MartijnLivaart</li>
+ <li>Feat/check new arguments thanks to MartijnLivaart</li>
+ <li>Fix/test access directory thanks to MartijnLivaart via GH#27</li>
+ <li>feat: check if debug parameter propagates from new() thanks to MartijnLivaart via GH#29</li>
+ <li>Pod corrections thanks to poptix via GH#31</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 01:48:59
+ Link: https://metacpan.org/release/KIMOTO/SPVM-IO-0.208
+ Title: SPVM-IO-0.208
+ <Description<
+ [#[
+ <p>File IO, Socket, Select/Polling.</p><p>Changes for 0.208 - 2023-09-11</p><ul><li>Prerequirement Changes</li>
+ <li>Incompatibe Changes</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-12 00:05:49
+ Link: https://metacpan.org/release/PERLANCAR/Perinci-Access-Perl-0.899
+ Title: Perinci-Access-Perl-0.899
+ <Description<
+ [#[
+ <p>Access Perl module, functions, variables through Riap</p><p>Changes for 0.899 - 2023-07-09</p><ul><li>No functional changes.</li>
+ <li>Remove usage of smartmatch.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 23:07:19
+ Link: https://metacpan.org/release/LICHTKIND/Graphics-Toolkit-Color-1.60
+ Title: Graphics-Toolkit-Color-1.60
+ <Description<
+ [#[
+ <p>color palette creation helper</p><p>Changes for 1.60 - 2023-09-11</p><ul><li>= API development</li>
+ <li>* added color spaces HSB HSW YIQ</li>
+ <li>+ output format array: ['rgb',1,2,3]</li>
+ <li>+ input and output format string: 'rgb: 1,2,3'</li>
+ <li>+ input and output format css_string: 'rgb(1,2,3)'</li>
+ <li>- deprecated getter method string</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 21:32:59
+ Link: https://metacpan.org/release/SKIM/PYX-GraphViz-0.05
+ Title: PYX-GraphViz-0.05
+ <Description<
+ [#[
+ <p>GraphViz output for PYX handling.</p><p>Changes for 0.05 - 2023-09-11T23:32:16+02:00</p><ul><li>Fix Makefile.PL which fails with no '.' in @INC.</li>
+ <li>Fix link to image in doc.</li>
+ <li>Improve LICENSE AND COPYRIGHT section in doc.</li>
+ <li>Improve SYNOPSIS section in doc.</li>
+ <li>Rename example file to better name.</li>
+ <li>Rewrite bugtracker to github.</li>
+ <li>Rewrite to new author github username.</li>
+ <li>Update Module::Install to 1.21 version.</li>
+ <li>Update copyright years.</li>
+ <li>Update my name to actual version.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 21:13:51
+ Link: https://metacpan.org/release/SKIM/PYX-0.09
+ Title: PYX-0.09
+ <Description<
+ [#[
+ <p>A perl module for PYX handling.</p><p>Changes for 0.09 - 2023-09-11T23:12:41+02:00</p><ul><li>Common</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 19:34:24
+ Link: https://metacpan.org/release/RJBS/App-Cronjob-1.200014
+ Title: App-Cronjob-1.200014
+ <Description<
+ [#[
+ <p>wrap up programs to be run as cron jobs</p><p>Changes for 1.200014 - 2023-09-11T15:34:04-04:00</p><ul><li>fix documentation to add missing switches</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 18:38:50
+ Link: https://metacpan.org/release/PREACTION/Minion-Backend-mysql-1.002
+ Title: Minion-Backend-mysql-1.002
+ <Description<
+ [#[
+ <p>MySQL backend</p><p>Changes for 1.002 - 2023-09-11T13:37:53-05:00</p><ul><li>Fixed</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 18:34:53
+ Link: https://metacpan.org/release/SRI/Mojolicious-9.34
+ Title: Mojolicious-9.34
+ <Description<
+ [#[
+ <p>Real-time web framework</p><p>Changes for 9.34 - 2023-09-11</p><ul><li>Added support for serving static files with a prefix.</li>
+ <li>Deprecated Mojo::File::spurt in favor of Mojo::File::spew.</li>
+ <li>Added prefix attribute to Mojolicious::Static.</li>
+ <li>Added url_for_file method to Mojolicious::Controller.</li>
+ <li>Added file_path method to Mojolicious::Static.</li>
+ <li>Added spew method to Mojo::File. (genio)</li>
+ <li>Added encoding option to slurp method in Mojo::File. (genio)</li>
+ <li>Added url_for_asset and url_for_file helpers to Mojolicious::Plugins::DefaultHelpers.</li>
+ <li>Added favicon helper to Mojolicious::Plugin::TagHelpers.</li>
+ <li>Fixed support for module_true Perl feature in Mojolicious apps. (haarg)</li>
+ <li>Fixed a bug in Mojo::Promise where map could hang on false values after concurrency limit. (ilmari)</li>
+ <li>Fixed built-in templates to not require an internet connection. (hernan604)</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 17:14:12
+ Link: https://metacpan.org/release/LEONT/version-0.9930
+ Title: version-0.9930
+ <Description<
+ [#[
+ <p>Structured version objects</p><p>Changes for 0.9930</p><ul><li>Permit a colon after a vstring, thus allowing an attrlist to follow a version declaration on a 'class' statement (Perl5 #20891)</li>
+ <li>Simplify and fix w.r.t locale handling</li>
+ <li>Make tests not fail when path to dist includes "panic"</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 16:14:59
+ Link: https://metacpan.org/release/SKIM/PYX-Sort-0.04
+ Title: PYX-Sort-0.04
+ <Description<
+ [#[
+ <p>Processing PYX data or file and sort element attributes.</p><p>Changes for 0.04 - 2023-09-11T18:14:08+02:00</p><ul><li>Fix bugtracker.</li>
+ <li>Fix sense of example in doc.</li>
+ <li>Fix use lib '.' in Makefile.PL.</li>
+ <li>Improve LICENSE AND COPYRIGHT section in doc.</li>
+ <li>Improve SYNOPSIS section in doc.</li>
+ <li>Rename example to better name.</li>
+ <li>Update Module::Install to 1.21 version.</li>
+ <li>Update author github username.</li>
+ <li>Update author username.</li>
+ <li>Update copyright years.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 15:29:26
+ Link: https://metacpan.org/release/RKAPL/EAI-Wrap-0.2
+ Title: EAI-Wrap-0.2
+ <Description<
+ [#[
+ framework for easy creation of Enterprise Application Integration tasks
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 15:25:17
+ Link: https://metacpan.org/release/PROCH/NBI-Slurm-0.6.1
+ Title: NBI-Slurm-0.6.1
+ <Description<
+ [#[
+ <p>NBI Slurm module</p><p>Changes for 0.6.1 - 2023-09-02</p><ul><li>Minor improvements in `make_image_from_bioconda` and `make_package`</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 15:16:08
+ Link: https://metacpan.org/release/PROCH/NBI-Slurm-0.6.0
+ Title: NBI-Slurm-0.6.0
+ <Description<
+ [#[
+ <p>NBI Slurm module</p><p>Changes for 0.6.0 - 2023-09-01</p><ul><li>Adding packaging tools: `make_image_from_bioconda` and `make_package`</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 15:00:49
+ Link: https://metacpan.org/release/CORION/Net-Async-OSC-0.01
+ Title: Net-Async-OSC-0.01
+ <Description<
+ [#[
+ <p>send/receive OSC asynchronously</p><p>Changes for 0.01 - 2023-09-11</p><ul><li>Released on an unsuspecting world</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 13:36:23
+ Link: https://metacpan.org/release/IDOPEREL/Svsh-1.003000
+ Title: Svsh-1.003000
+ <Description<
+ [#[
+ <p>Process supervision shell for daemontools/perp/s6/runit</p><p>Changes for 1.003000 - 2023-09-11T16:35:55+03:00</p><ul><li>Replace Getopt::Compact with core module Getopt::Long</li>
+ <li>Switch license to Apache 2.0</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 13:20:12
+ Link: https://metacpan.org/release/WYANT/Astro-App-Satpass2-0.051
+ Title: Astro-App-Satpass2-0.051
+ <Description<
+ [#[
+ <p>Predict satellite visibility using Astro::Coord::ECI</p><p>Changes for 0.051 - 2023-09-11</p><ul><li>Without DateTime, ParseTime::ISO8601 now accepts any zone. These are handled by setting $ENV{TZ} before the conversion and hoping for the best. The documentation warns that this is a shaky way to handle zones.</li>
+ <li>Make Warner->wail() stack dump if $Carp::Verbose true.</li>
+ <li>Add --almanac to pass(). This adds almanac data to appropriate passes. --ephemeris is more verbose, adding almanac data to all passes. This change involved refactoring event formatting to use sub-templates, rather than if-elsif-else chains.</li>
+ <li>Add 'none' as valid argument to FormatTime->round_time(). It is equivalent to specifying undef, i.e. no rounding.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 11:14:37
+ Link: https://metacpan.org/release/MRSCOTTY/Connector-1.51
+ Title: Connector-1.51
+ <Description<
+ [#[
+ <p>a generic connection to a hierarchical-structured data set</p><p>Changes for 1.51 - 2023-09-11T11:13:04Z</p><ul></ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 09:30:18
+ Link: https://metacpan.org/release/NLNETLABS/Net-DNS-SEC-1.21_01
+ Title: Net-DNS-SEC-1.21_01
+ <Description<
+ [#[
+ DNSSEC extensions to Net::DNS
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 08:05:24
+ Link: https://metacpan.org/release/KIMOTO/SPVM-Sys-0.490
+ Title: SPVM-Sys-0.490
+ <Description<
+ [#[
+ <p>System Calls for File IO, User, Process, Signal, Socket</p><p>Changes for 0.490 - 2023-09-11</p><ul><li>Bug Fix</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 07:21:21
+ Link: https://metacpan.org/release/MRSCOTTY/Connector-1.50
+ Title: Connector-1.50
+ <Description<
+ [#[
+ <p>a generic connection to a hierarchical-structured data set</p><p>Changes for 1.50 - 2023-09-11T07:06:09Z</p><ul></ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 06:52:02
+ Link: https://metacpan.org/release/MBRADSHAW/Mail-Milter-Authentication-3.20230911
+ Title: Mail-Milter-Authentication-3.20230911
+ <Description<
+ [#[
+ <p>A Perl Mail Authentication Milter</p><p>Changes for 3.20230911 - 2023-09-11T06:18:44+00:00</p><ul><li>Core: Switch from deprecated method in Net::DNS In Net::DNS::Resolver, call the rdstring method rather than the deprecated rdstring method This change bumps the minimum version of Net::DNS required to 1.01</li>
+ <li>SPF: Add option to detect and optionally mitigate SPF upgrade problems.</li>
+ <li>Core: Add authentication_milter_log command with arex subcommand which can be used to process ARex JSON log format back into standard Authentication-Results: header lines</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 04:26:54
+ Link: https://metacpan.org/release/KIMOTO/SPVM-Sys-0.489
+ Title: SPVM-Sys-0.489
+ <Description<
+ [#[
+ <p>System Calls for File IO, User, Process, Signal, Socket</p><p>Changes for 0.489 - 2023-09-11</p><ul><li>New Features</li>
+ <li>Bug Fix</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 01:44:08
+ Link: https://metacpan.org/release/KIMOTO/SPVM-Sys-0.488
+ Title: SPVM-Sys-0.488
+ <Description<
+ [#[
+ <p>System Calls for File IO, User, Process, Signal, Socket</p><p>Changes for 0.488 - 2023-09-11</p><ul><li>Prerequirement Changes</li>
+ <li>Incompatible Changes</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ <Item<
+ Date: 2023-09-11 01:37:35
+ Link: https://metacpan.org/release/JIMAVERA/ODF-MailMerge-0.003
+ Title: ODF-MailMerge-0.003
+ <Description<
+ [#[
+ <p>"Mail Merge" or just substitute tokens in ODF documents</p><p>Changes for 0.003</p><ul><li>(i.e. only if the row is being replicated). Preened docs.</li>
+ </ul>
+ ]#]
+ >Description>
+ >Item>
+ >Brew>
+>>