From: Will Budic Date: Thu, 15 May 2025 08:26:03 +0000 (+1000) Subject: init X-Git-Url: https://lifelog.hopto.org/gitweb/?a=commitdiff_plain;h=6569764355e3dc6ca3ce8c923395d507779be61b;p=PerlCNFWEBServer.git init --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3e4abb5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vscode +system +wsrc \ No newline at end of file diff --git a/server.pl b/server.pl new file mode 100755 index 0000000..161dfaf --- /dev/null +++ b/server.pl @@ -0,0 +1,418 @@ +#!/usr/bin/perl +package PerlCNFWebServer; +use lib::relative 'system/modules'; +use lib::relative 'apps'; +use PerlCNFWebServerBase; + +use IO::Socket::SSL; +use HTTP::Server::Simple::CGI; +use base qw(HTTP::Server::Simple::CGI); + +use Gzip::Faster; no warnings qw(experimental::signatures); + +our ($START_UP_ERRORS, $START_UP_PROPS, $SERVER_DIR); +our $GLOB_HTML_SERVE = "'{}/*.cgi' '{}/*.htm' '{}/*.html' '{}/*.md' '{}/*.txt'"; +BEGIN {use Cwd; $SERVER_DIR = cwd} +use lib $SERVER_DIR.'/apps'; use lib $SERVER_DIR.'/apps'; + +our $cnf_index; +our %locals; +our %includes; +our $INDEX_FILE = CNFGlobalFile -> new('index.cnf'); +our $LOCAL_PATH = $0; +our %TYPE_HANDLER = ( + css => \&asTxtFile, + txt => \&asTxtFile, + js => \&asTxtFile, + png => \&asBinFile, jpg => \&asBinFile, jpeg => \&asBinFile, + gif => \&asBinFile, + ttf => \&asBinFile, woff2=> \&asBinFile +); +our %dispatch = ( + '/' => \&index, + '/wsrc' => \&wsrc, +); +our %SSL; +my $cnf_server = CNFParser::_configure({DEBUG=>1,DO_ENABLED => 1,SERVER_DIR=>$SERVER_DIR},$0); +my @globs = $cnf_server -> property('@GLOB_HTML_SERVE'); +if(@globs){ + my $gs; + foreach(@globs) { + $gs .= "{}/*.$_ " if $_ + } + if ($gs){ + $GLOB_HTML_SERVE = $gs; + $START_UP_PROPS = "\@GLOB_HTML_SERVE => $GLOB_HTML_SERVE"; + } +}else{ + my $err ="\@GLOB_HTML_SERVE property not found in config, using default."; + warn($err); $START_UP_ERRORS .= "$err\n \@GLOB_HTML_SERVE => $GLOB_HTML_SERVE"; +} +no warnings qw(experimental::signatures);#Placed here as earlier versions of Perl shoot warnings. +sub asTxtFile ($cgi, $request_header, $type, $full_path) { + my $file = CNFGlobalFile->new($full_path); + my $last_modified = CNFDateTime->now({epoch=>$file->{last_modified}, TZ => $cnf_server->{TZ}}); + my $now = CNFDateTime->now({TZ => $cnf_server->{TZ}}); + my $content = ${$file->content()}; + my $gzip = CNFParser::_isTrue($cnf_server -> const('compress_particulars')); + if($gzip){ #Check if browser supports gzip? + my $accept_encoding = %$request_header{HTTP_ACCEPT_ENCODING}; + $gzip = 0 if $accept_encoding !~ m/gzip/; + } + print "HTTP/1.0 200 OK\n", + "content-type: text/$type; charset=utf-8\n"; + print "content-encoding: gzip\n" if $gzip; + print "content-length: ",$file -> {content_length},"\n", + "last-modified: ",$last_modified->toSchlong(),"\n", + "date: ",$now->toSchlong(),"\n", + "cache-control: public\n", + "server: ".__PACKAGE__."/".CNFParser::VERSION(),"\n\n"; + print $gzip?gzip($content):$content; +} + +sub asBinFile ($cgi, $request_headers, $type, $full_path){ + my $file = CNFGlobalFile->new($full_path); + my $last_modified = CNFDateTime->now({epoch=>$file->{last_modified}, TZ => $cnf_server->{TZ}}); + my $now = CNFDateTime->now({TZ => $cnf_server->{TZ}}); + print "HTTP/1.0 200 OK\n", + "content-type: image/$type;\n", + "content-length: ", $file -> {content_length},"\n", + "last-modified: ",$last_modified->toSchlong(),"\n", + "date: ",$now->toSchlong(),"\n", + "cache-control: public","\n", + "server: ".__PACKAGE__."/".CNFParser::VERSION(),"\n\n"; + $file -> binary(); +} + +sub error_to_browser ($cgi, $err){ + my $now = CNFDateTime->now({TZ => $cnf_server->{TZ}}); + my $page_link = $cgi->protocol().'//'.$cgi->remote_host().':'.$cgi->server_port().$cgi->request_uri(); + print "HTTP/1.0 500 Internal Server Error\n", + "content-type: text/html; charset=utf-8\n", + "date: ",$now->toSchlong(),"\n", + "server: ".__PACKAGE__."/".CNFParser::VERSION(),"\n\n", + $cgi->start_html(">>Server Error!<"), + $cgi ->h2("ServerError@ ⇒ $page_link"), + $cgi->pre($err), + $cgi->end_html; +} + +sub deliverByParticulars ($cgi, $request_header, $dir, $full_path) { + $full_path =~ m/\.(\w+)$/; my $type = $1; + my $handler = $TYPE_HANDLER{$type}; + if($handler && -e $full_path){ + $handler -> ($cgi, $request_header, $type, $full_path); + }else{ + print "HTTP/1.0 404 Not found\r\n"; + print $cgi->header, + $cgi->start_html('Not found :'.$cgi->path_info()), + $cgi->h1('Not found -> '.$cgi->path_info()), + $cgi->end_html; + } +} + +sub obtainDirListingHTML ($dir) { + my $ret; + my $html = listFiles($dir); + if($html){ + $ret .=""; + } + return $ret; +} + +sub listFiles ($dir){ + my $ret; + my $path = $dir; + my $spec = $GLOB_HTML_SERVE; $spec =~ s/{}/$path/gp; + my @files = glob ($spec); + @files = sort { + ( $a=~m/\w+[_-]*/ eq $b=~m/\w+[_-]*/ && length $a > length $b) || + $a <=> $b + } @files; + foreach my $file(@files){ + ($file =~ m/(\w+\.\w*)$/g); + my $name = $1; + if($file =~ /\.md$/){ + my @title = getDocTitle($file); + $ret .= qq(\t\t\t
  • $title[1] ‐ $name
  • \n); + }else{ + $ret .= qq(\t\t\t
  • $name
  • \n); + } + } + + return $ret; +} + +sub wsrc($cgi,$hdrs) { +my $ret = obtainDirListingHTML($SERVER_DIR.'/wsrc'); +print $cgi->header, + $cgi->start_html, + $cgi->div($ret), + $cgi->end_html; + +} +sub index($cgi,$hdrs) { + if (check_if_has_changed($INDEX_FILE)){ + try{ + + $cnf_index = CNFParser -> new ( + $INDEX_FILE,{ + DO_ENABLED => 1, HAS_EXTENSIONS=>1, + ANONS_ARE_PUBLIC => 1, + DEBUG => 1, + TZ => $cnf_server->{TZ}, + PAGE_HEAD => "

    Index Page of Docs Directory

    ", + PAGE_CONTENT => "

    Hello World

    ", + PAGE_FOOT => "" + } + ); + $locals{$INDEX_FILE} = \$cnf_index; + + }catch($e){ + $cnf_server -> error($e); + error_to_browser($cgi, $e); + return + } + } + my $ptr = $cnf_index->data(); + $ptr = $ptr->{'PAGE'}; + print $$ptr if $ptr; +} + +sub check_if_has_changed ($config_file){ + my $entry = $locals{$config_file->{path}}; + if($entry){$entry = $$entry; + if($config_file -> changed()){ + $cnf_server -> log("Config has changed for: ". $entry->{CNF_CONTENT}); + return 1 + }else{ + my $ptr = $includes{$config_file->{path}}; + if($ptr){ + foreach my $cnf_glob_file(@$ptr){ + if($cnf_glob_file->changed()){ + $cnf_server -> log("Config include changed: ". $cnf_glob_file->{path}); + return 1 + } + } + } + } + return 0 + }else{ + $cnf_server -> log("Config load initiated for: ". $config_file->{path}); + return 1 + } +} + + +sub page($cgi, $request_header, $prp_name, $cnf_app) { + my $property = $cnf_app -> property($prp_name); + my ($html_head,$html_body,$html_foot); + my $ref = ref($property); + if(not $property){ + $property = $cnf_app->writeOut(); + $property =~ s//>/gs; + $html_body = \$property + }elsif($ref eq 'Pagelet'){ + $property -> {plugin} -> setParameters($cnf_app, $prp_name, $cgi->{param}) if (keys %{$cgi->{param}} > 0); + $html_head = $property -> {html_head}; + $html_body = $property -> {html_body}; + $html_foot = $property -> {html_foot}; + }else{ + $html_body = $cnf_app -> data() -> {$property->{property}} + } + my $now = CNFDateTime->now({TZ => $cnf_server->{TZ}}); + my $last_modified = CNFDateTime->now({TZ => $cnf_server->{TZ}, epoch=> @{$cnf_app->{CNF_STAT}}[9]}); + my $gzip = CNFParser::_isTrue($cnf_server -> const('compress_particulars')); + if($gzip){ #Check if browser supports gzip? + my $accept_encoding = %$request_header{HTTP_ACCEPT_ENCODING}; + $gzip = 0 if $accept_encoding !~ m/gzip/; + } + + # Modern browser html specs have changed, support but do not like/need + # header doc type xml/html declarations, that perl's cgi lib builds and delivers for old browser compatibility. + # This suits us well, as can configure head parameters start up directly or via CNF from here. + print "content-type: text/html; charset=utf-8\n"; + print "content-encoding: gzip\n" if $gzip; + print "last-modified: ",$last_modified->toSchlong(),"\n", + "date: ",$now->toSchlong(),"\n", + "cache-control: public","\n", + "server: ".__PACKAGE__."/".CNFParser::VERSION(),"\n\n"; + my $content; + if(not $html_head){ + $content = qq(\n\n
    \n)
    +    }else{
    +       $content = $$html_head
    +    }
    +    $content .= $$html_body;
    +    if(not $html_foot ){
    +       $content .=  qq(\n
    ); + }else{ + $content .= $$html_foot; + } + print $gzip ? gzip($content):$content; +} + + +sub handle_request ($self, $cgi){ + + my $path = $cgi->path_info(); + my $handler = $dispatch{$path}; + + if($path && not $handler){ + # We might got file particulars access, + # or direct links for files that have content-type. + my @pa = ($path =~ m/(.*)\/(.*\..*)/); + my $path_particular = $pa[0]; + my $path_file = $pa[1]; + $path = $SERVER_DIR.$path_particular; + if(-d $path){ + my %request_header = map { $_ => $cgi->http($_) } $cgi->http(); + deliverByParticulars($cgi, \%request_header,$path, $path.'/'.$path_file); + return; + } + } + + if (ref($handler) eq "CODE") { + my %request_header = map { $_ => $cgi->http($_) } $cgi->http(); + print "HTTP/1.0 200 OK\r\n"; + $handler->($cgi, \%request_header); + } else { + print "HTTP/1.0 404 Not found\r\n"; + print $cgi->header, + $cgi->start_html('Not found'), + $cgi->h1("Not found: $path"), + $cgi->end_html; + } +} + +sub accept_hook { + if(isTrue($SSL{enabled})){ + my $self = shift; $self->SUPER::accept_hook(@_); + my $fh = $self->stdio_handle; + my $newfh = + IO::Socket::SSL->start_SSL( $fh, + SSL_server => $SSL{server}, + SSL_use_cert => $SSL{use_cert}, + SSL_cert_file => $SSL{cert_file}, + SSL_key_file => $SSL{key_file}, + ) + or warn "problem setting up SSL socket: " . IO::Socket::SSL::errstr(); + $self->stdio_handle($newfh) if $newfh; + } +} + +sub include_hook { + my ($config_file, $include_file) = @_; + if ($config_file && $include_file) { + my @arr; my $ptr = $includes{$config_file}; + @arr = @$ptr if $ptr; + foreach(@arr){ + return 0 if $_->{path} eq $include_file; + } + $arr[@arr] = CNFGlobalFile->new($include_file); + $includes{$config_file} = \@arr; + } + return 0; +} + + sub MAIN +{ + our %SSL = $cnf_server -> property('%SSL'); + my %log = $cnf_server -> property('%LOG'); + my %registry = $cnf_server -> property('%REGISTRY'); + if (%registry){ + foreach my $path (keys(%registry)){ + my ($prp_name, $config, $cnf_app) = $registry{$path}; + my @pair= ($prp_name =~ m/([\w\.\_\-\/]+)\s*,\s*(\w*)/g); + $config = $pair[0]; + $prp_name = $pair[1]; + my $cnf_file = CNFGlobalFile->new($config); + # Anonymous handler passing our $cgi. + $dispatch {"/$path"} = sub ($cgi, $request_header) { + + if(!$cnf_app or check_if_has_changed($cnf_file)){ + try{ + $cnf_app = CNFParser -> new($cnf_file, { + DO_ENABLED => 1, + '%LOG' => \%log, + TZ => $cnf_server->{TZ}, + INCLUDES_LISTENER => *include_hook + } + ); + $locals{$config} = \$cnf_app; + }catch($e){ + $cnf_server -> error($e); + error_to_browser($cgi, $e); + return + } + } + page($cgi, $request_header, $prp_name, $cnf_app); + $cnf_server -> log("Delivered -> ".$registry{$path}); + } + } + }else{ + $cnf_server -> warn("A \%REGISTRY property was not located in server config."); + } + + my $settings = "Starting -> [". __PACKAGE__ ."]\n"; + foreach my $k (keys(%$cnf_server)){ + $settings .= "$k=\'$cnf_server->{$k}\'\n" if $k !~ /^__/; + } + + if(%log){ + $settings .= 'my %LOG = {'; + foreach my $k (keys(%log)){ + $settings .= "$k=>\'".$log{$k}."\', " + } + $settings =~ s/, $//; $settings .= "}\n"; + } + + $cnf_server -> log($settings); print $settings; print $START_UP_PROPS, "\n", '-'x80, "\n"; + $cnf_server -> warn($START_UP_ERRORS) if $START_UP_ERRORS; + + my $pid = isTrue($cnf_server->const('run_as_background_process')) ? + PerlCNFWebServer->new($cnf_server->{port})->background() : + PerlCNFWebServer->new($cnf_server->{port})->run(); + print `lsof -i tcp:$cnf_server->{port}`; + my $run = `lsof -i tcp:$cnf_server->{port} | sed -n '2p' | awk '{print \$2}'`; $run =~s/\s*$//; + if($run eq $pid){ + print "Use kill $pid to stop this server.\n"; + }else{ + print "Use kill $run to stop that server.\n"; + } +} + +sub print_banner { + my $self = shift; + my $proto = isTrue($SSL{enabled})?"https":"http"; + my $host = `hostname`; $host =~s/\s*$//; + print( ref($self) . ": You can connect to your server at " . "$proto://$host:".$self->{port}."/\n" ); +} + +&MAIN; +1; + +=begin copyright +Programed by : Will Budić +EContactHash : 990MWWLWM8C2MI8K (https://github.com/wbudic/EContactHash.md) +Source : git clone git://lifelog.hopto.org/PerlCNFWebServer + : git clone git://lifelog.hopto.org/PerlCNF + : 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 modified 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 diff --git a/specs.md b/specs.md new file mode 100644 index 0000000..e3340d2 --- /dev/null +++ b/specs.md @@ -0,0 +1,15 @@ +# PerlCNFWebServer + + PerlCNF Standalone HTML Web Server implementation. + +## Features + +* Can run in a full background process. +* On server startup provides in memory resident staying of the perl compilations of modules. +* Auto reloads CNF files and contents if have changed. No server restart required. +* Web server CNF global app settings for features like: logging, time zones and data resource connections. +* To remind CNF also provides own data properties and format, besides that can be used for SQL data schemas and operations. +* Connection pools for datasource management. No waiting for a data connection, as it is in a pool. +* Forked client request or access management. +* Server side page caching and resolve on dynamic content for immediate dispatch. Useful if builders and other processors generate outputs, but only if it has changed between requests. Giving a faster response therefore. +* Static HTML direct output, but also decorated MD files translation to HTML output (cashed as well). diff --git a/web_sources/app.css b/web_sources/app.css new file mode 100644 index 0000000..dd80d15 --- /dev/null +++ b/web_sources/app.css @@ -0,0 +1,119 @@ + +/** Layers are in root.css **/ +@layer reset, base; + +html{ + height: 100%; + display: flex; +} + +body { + + padding: 0.5em; + display: grid; + overflow: scroll; + + .content { + display: inline-flex; + /* border: 5px dotted rgb(168, 120, 96); */ + max-width: 100%; + height: 98%; + align-items: stretch; + flex-direction: row; + } + p{ + padding-left: 1ch; + padding-bottom: 1ch; + } + .indent{ + padding-left: 3ch; + p{ + padding-left: 2ch; + } + } +} + +.page_title { + font-style: italic; + font-weight: bold; + box-shadow: 2px 2px 2px black; + margin-bottom: 1em; +} + +.col { + /* border: 1px solid rgb(133, 133, 233); */ + text-wrap: wrap; + text-align: center; + position: sticky; +} + + +.col_main { + border: 1px solid rgb(133, 133, 233); + min-width: 70%; + padding: 1em; + margin-top: 1ch; + + h1 { + margin-top:1ch; + color:blueviolet; + } + div{ + padding-left: 3ch; + p{ + padding-left: 2ch; + } + } +} + +.toc { + position: fixed; + background-color: #00a087; + padding: 1ch; + border: 2px solid rgb(133, 133, 233); + border-radius: 10px 100px / 120px; + box-shadow: 10px 5px 5px lightslategrey; + cursor: se-resize; +} +.toc:hover .scrolling{ + display: block; + cursor: pointer; +} + +ul .scrolling{ + margin-block-start: 0; + margin-block-end: 1em; + padding-inline-start: 20px; +} + +.scrolling{ + position: fixed; + + text-wrap: wrap; text-align: left; + + + padding: 1ch; + background-color: #00a087; + border: 2px solid #42a9b8; + + display: none; + box-shadow: 5px 5px 5px lightslategrey; + opacity: 80%; + + ul { + margin-block-start: 0; + margin-block-end: 1em; + padding-left: 20px; + } + a:active{ + font-size: larger; + color: cadetblue; + } + a:visited{ + font-size: larger; + color: black; + } + +} + + diff --git a/web_sources/fonts/DMSams/DMSans-Italic-VariableFont_opsz,wght.ttf b/web_sources/fonts/DMSams/DMSans-Italic-VariableFont_opsz,wght.ttf new file mode 100644 index 0000000..a7ee5c9 Binary files /dev/null and b/web_sources/fonts/DMSams/DMSans-Italic-VariableFont_opsz,wght.ttf differ diff --git a/web_sources/fonts/DMSams/DMSans-VariableFont_opsz,wght.ttf b/web_sources/fonts/DMSams/DMSans-VariableFont_opsz,wght.ttf new file mode 100644 index 0000000..3d81b31 Binary files /dev/null and b/web_sources/fonts/DMSams/DMSans-VariableFont_opsz,wght.ttf differ diff --git a/web_sources/fonts/DMSams/OFL.txt b/web_sources/fonts/DMSams/OFL.txt new file mode 100644 index 0000000..bd7058f --- /dev/null +++ b/web_sources/fonts/DMSams/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2014 The DM Sans Project Authors (https://github.com/googlefonts/dm-fonts) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/web_sources/fonts/DMSams/README.txt b/web_sources/fonts/DMSams/README.txt new file mode 100644 index 0000000..4725723 --- /dev/null +++ b/web_sources/fonts/DMSams/README.txt @@ -0,0 +1,67 @@ +DM Sans Variable Font +===================== + +This download contains DM Sans as both variable fonts and static fonts. + +DM Sans is a variable font with these axes: + opsz + wght + +This means all the styles are contained in these files: + DMSans-VariableFont_opsz,wght.ttf + DMSans-Italic-VariableFont_opsz,wght.ttf + +If your app fully supports variable fonts, you can now pick intermediate styles +that aren’t available as static fonts. Not all apps support variable fonts, and +in those cases you can use the static font files for DM Sans: + static/DMSans-Regular.ttf + static/DMSans-Medium.ttf + static/DMSans-MediumItalic.ttf + +Get started +----------- + +1. Install the font files you want to use + +2. Use your app's font picker to view the font family and all the +available styles + +Learn more about variable fonts +------------------------------- + + https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts + https://variablefonts.typenetwork.com + https://medium.com/variable-fonts + +In desktop apps + + https://theblog.adobe.com/can-variable-fonts-illustrator-cc + https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts + +Online + + https://developers.google.com/fonts/docs/getting_started + https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide + https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts + +Installing fonts + + MacOS: https://support.apple.com/en-us/HT201749 + Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux + Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows + +Android Apps + + https://developers.google.com/fonts/docs/android + https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts + +License +------- +Please read the full license text (OFL.txt) to understand the permissions, +restrictions and requirements for usage, redistribution, and modification. + +You can use them in your products & projects – print or digital, +commercial or otherwise. + +This isn't legal advice, please consider consulting a lawyer and see the full +license for all details. diff --git a/web_sources/fonts/DMSams/static/DMSans-Medium.ttf b/web_sources/fonts/DMSams/static/DMSans-Medium.ttf new file mode 100644 index 0000000..841d31d Binary files /dev/null and b/web_sources/fonts/DMSams/static/DMSans-Medium.ttf differ diff --git a/web_sources/fonts/DMSams/static/DMSans-MediumItalic.ttf b/web_sources/fonts/DMSams/static/DMSans-MediumItalic.ttf new file mode 100644 index 0000000..343122f Binary files /dev/null and b/web_sources/fonts/DMSams/static/DMSans-MediumItalic.ttf differ diff --git a/web_sources/fonts/DMSams/static/DMSans-Regular.ttf b/web_sources/fonts/DMSams/static/DMSans-Regular.ttf new file mode 100644 index 0000000..07266ae Binary files /dev/null and b/web_sources/fonts/DMSams/static/DMSans-Regular.ttf differ diff --git a/web_sources/fonts/Lato/Lato-Black.ttf b/web_sources/fonts/Lato/Lato-Black.ttf new file mode 100644 index 0000000..6848db0 Binary files /dev/null and b/web_sources/fonts/Lato/Lato-Black.ttf differ diff --git a/web_sources/fonts/Lato/Lato-BlackItalic.ttf b/web_sources/fonts/Lato/Lato-BlackItalic.ttf new file mode 100644 index 0000000..5decf12 Binary files /dev/null and b/web_sources/fonts/Lato/Lato-BlackItalic.ttf differ diff --git a/web_sources/fonts/Lato/Lato-Bold.ttf b/web_sources/fonts/Lato/Lato-Bold.ttf new file mode 100644 index 0000000..7434369 Binary files /dev/null and b/web_sources/fonts/Lato/Lato-Bold.ttf differ diff --git a/web_sources/fonts/Lato/Lato-BoldItalic.ttf b/web_sources/fonts/Lato/Lato-BoldItalic.ttf new file mode 100644 index 0000000..684aacf Binary files /dev/null and b/web_sources/fonts/Lato/Lato-BoldItalic.ttf differ diff --git a/web_sources/fonts/Lato/Lato-Hairline.ttf b/web_sources/fonts/Lato/Lato-Hairline.ttf new file mode 100644 index 0000000..288be29 Binary files /dev/null and b/web_sources/fonts/Lato/Lato-Hairline.ttf differ diff --git a/web_sources/fonts/Lato/Lato-HairlineItalic.ttf b/web_sources/fonts/Lato/Lato-HairlineItalic.ttf new file mode 100644 index 0000000..c2bfd33 Binary files /dev/null and b/web_sources/fonts/Lato/Lato-HairlineItalic.ttf differ diff --git a/web_sources/fonts/Lato/Lato-Italic.ttf b/web_sources/fonts/Lato/Lato-Italic.ttf new file mode 100644 index 0000000..3d3b7a2 Binary files /dev/null and b/web_sources/fonts/Lato/Lato-Italic.ttf differ diff --git a/web_sources/fonts/Lato/Lato-Light.ttf b/web_sources/fonts/Lato/Lato-Light.ttf new file mode 100644 index 0000000..a958067 Binary files /dev/null and b/web_sources/fonts/Lato/Lato-Light.ttf differ diff --git a/web_sources/fonts/Lato/Lato-LightItalic.ttf b/web_sources/fonts/Lato/Lato-LightItalic.ttf new file mode 100644 index 0000000..5e45ad9 Binary files /dev/null and b/web_sources/fonts/Lato/Lato-LightItalic.ttf differ diff --git a/web_sources/fonts/Lato/Lato-Regular.ttf b/web_sources/fonts/Lato/Lato-Regular.ttf new file mode 100644 index 0000000..04ea8ef Binary files /dev/null and b/web_sources/fonts/Lato/Lato-Regular.ttf differ diff --git a/web_sources/fonts/Lato/Lato-Thin.ttf b/web_sources/fonts/Lato/Lato-Thin.ttf new file mode 100644 index 0000000..ba58da1 Binary files /dev/null and b/web_sources/fonts/Lato/Lato-Thin.ttf differ diff --git a/web_sources/fonts/Lato/Lato-ThinItalic.ttf b/web_sources/fonts/Lato/Lato-ThinItalic.ttf new file mode 100644 index 0000000..4d82766 Binary files /dev/null and b/web_sources/fonts/Lato/Lato-ThinItalic.ttf differ diff --git a/web_sources/fonts/Lato/OFL.txt b/web_sources/fonts/Lato/OFL.txt new file mode 100644 index 0000000..1d7bf3b --- /dev/null +++ b/web_sources/fonts/Lato/OFL.txt @@ -0,0 +1,93 @@ +Copyright (c) 2010-2014 by tyPoland Lukasz Dziedzic (team@latofonts.com) with Reserved Font Name "Lato" + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/web_sources/fonts/Lato/STYLES.css b/web_sources/fonts/Lato/STYLES.css new file mode 100644 index 0000000..21d8c8d --- /dev/null +++ b/web_sources/fonts/Lato/STYLES.css @@ -0,0 +1,60 @@ + .lato-thin { + font-family: "Lato", sans-serif; + font-weight: 100; + font-style: normal; + } + + .lato-light { + font-family: "Lato", sans-serif; + font-weight: 300; + font-style: normal; + } + + .lato-regular { + font-family: "Lato", sans-serif; + font-weight: 400; + font-style: normal; + } + + .lato-bold { + font-family: "Lato", sans-serif; + font-weight: 700; + font-style: normal; + } + + .lato-black { + font-family: "Lato", sans-serif; + font-weight: 900; + font-style: normal; + } + + .lato-thin-italic { + font-family: "Lato", sans-serif; + font-weight: 100; + font-style: italic; + } + + .lato-light-italic { + font-family: "Lato", sans-serif; + font-weight: 300; + font-style: italic; + } + + .lato-regular-italic { + font-family: "Lato", sans-serif; + font-weight: 400; + font-style: italic; + } + + .lato-bold-italic { + font-family: "Lato", sans-serif; + font-weight: 700; + font-style: italic; + } + + .lato-black-italic { + font-family: "Lato", sans-serif; + font-weight: 900; + font-style: italic; + } + \ No newline at end of file diff --git a/web_sources/fonts/LeagueMono-VF.woff2 b/web_sources/fonts/LeagueMono-VF.woff2 new file mode 100644 index 0000000..c6504ce Binary files /dev/null and b/web_sources/fonts/LeagueMono-VF.woff2 differ diff --git a/web_sources/fonts/fontawesome-webfont.woff2 b/web_sources/fonts/fontawesome-webfont.woff2 new file mode 100644 index 0000000..4d13fc6 Binary files /dev/null and b/web_sources/fonts/fontawesome-webfont.woff2 differ diff --git a/web_sources/root.css b/web_sources/root.css new file mode 100644 index 0000000..f237c9a --- /dev/null +++ b/web_sources/root.css @@ -0,0 +1,68 @@ +@font-face { + font-family: "Lato"; + src: url(fonts/Lato/Lato-Regular.ttf); +} + +:root { + --primary-subdued: hsl(254, 88%, 90%); + --primary-base: hsl(256, 67%, 59%); + --accent-subdued: hsl(31, 66%, 93%); + --accent-base: hsl(39, 100%, 71%); + --white: hsl(0, 0%, 100%); + --off-white: hsl(0, 0%, 96%); + --black: hsl(0, 0%, 7%); + --bck-col: #8dd8e7; + + --f-def: "Lato"; + --fs-reg: 1.25rem; + --fs-md: 2.25rem; + --fs-lg: 3rem; + --fs-xl: 4rem; + } + + @layer reset { + + *, + *::before, + *::after { + box-sizing: border-box; + } + + h1, + h2, + h3, + h4, + h5, + h6, + p, + ul, + ol, + figure { + margin: 0; + } + + h1, + h2, + h3, + h4, + h5, + h6 { + font-weight: 500; + } + + img { + max-width: 100%; + display: block; + } + } + + @layer base { + body, html { + font-family: "Lato", sans-serif; + line-height: 1.3; + padding: 0.5em; + color: var(--black,black); + background-color: var(--bck-col, #8dd8e7); + margin: 0; + } + } \ No newline at end of file diff --git a/web_sources/style-kevin-powell.css b/web_sources/style-kevin-powell.css new file mode 100644 index 0000000..a2da04a --- /dev/null +++ b/web_sources/style-kevin-powell.css @@ -0,0 +1,285 @@ +@font-face { + font-family: "DM Sans"; + font-weight: 400 500; + src: url("fonts/DMSans/DMSans-VariableFont_opsz,wght.ttf"); +} + +@font-face { + font-family: "DM Sans"; + font-style: italic; + font-weight: 400 500; + src: url("fonts/DMSans/DMSans-Italic-VariableFont_opsz,wght.ttf"); +} + +:root { + --primary-subdued: hsl(254, 88%, 90%); + --primary-base: hsl(256, 67%, 59%); + --accent-subdued: hsl(31, 66%, 93%); + --accent-base: hsl(39, 100%, 71%); + --white: hsl(0, 0%, 100%); + --off-white: hsl(0, 0%, 96%); + --black: hsl(0, 0%, 7%); + + --fs-reg: 1.25rem; + + --fs-md: 2.25rem; + --fs-lg: 3rem; + --fs-xl: 4rem; +} + +@layer reset { + + *, + *::before, + *::after { + box-sizing: border-box; + } + + h1, + h2, + h3, + h4, + h5, + h6, + p, + ul, + ol, + figure { + margin: 0; + } + + h1, + h2, + h3, + h4, + h5, + h6 { + font-weight: 500; + } + + img { + max-width: 100%; + display: block; + } +} + +@layer base { + html { + font-family: "DM Sans", sans-serif; + line-height: 1.3; + } + + body { + margin: 32px; + color: var(--black); + font-size: var(--fs-reg); + background: var(--off-white); + } + + h1, + h2 { + color: var(--heading-foreground, inherit); + font-size: var(--heading-font-size, var(--fs-md)); + line-height: 1.1; + text-wrap: balance; + + span { + display: var(--heading-span-display, inline); + color: var(--heading-span-foreground, var(--black)); + font-size: var(--heading-span-font-size, inherit); + font-style: var(--heading-span-style, normal); + } + } +} + +@layer layout { + .bento-grid { + display: grid; + gap: 24px; + max-inline-size: 1200px; + margin-inline: auto; + grid-template-areas: + 'one' + 'two' + 'three' + 'four' + 'five' + 'six' + 'seven' + 'eight'; + + @media (width > 660px) { + grid-template-areas: + "one one" + "two three" + "four six" + "four seven" + "five eight" + ; + } + + @media (width > 960px) { + grid-template-areas: + "seven one one four" + "seven two three four" + "eight two three four" + "eight six five five" + ; + } + } + + .bento-grid>* { + color: var(--bento-card-foreground, var(--black)); + background-color: var(--bento-card-surface, var(--white)); + padding: var(--bento-card-padding, 32px); + border-radius: var(--bento-card-border-radius, 21px); + + overflow: clip; + + display: grid; + gap: var(--bento-card-gap, 32px); + align-content: var(--bento-card-vertical-alignment, start); + align-items: var(--bento-card-vertical-alignment, start); + justify-items: var(--bento-card-horizontal-alignment, start); + text-align: var(--bento-card-horizontal-alignment, start); + } + + .bento-grid img { + max-width: var(--bento-card-image-width, 100%); + width: var(--bento-card-image-width, 100%); + order: var(--bento-card-image-order); + } + + .bento-grid> :nth-child(1) { + --heading-font-size: var(--fs-xl); + --heading-span-foreground: var(--accent-base); + --bento-card-foreground: var(--white); + --bento-card-surface: var(--primary-base); + --bento-card-padding: 48px; + --bento-card-horizontal-alignment: center; + --bento-card-image-width: 70%; + --bento-card-gap: 16px; + + @media (width > 960px) { + --bento-card-image-width: 45%; + } + + grid-area: one; + } + + .bento-grid> :nth-child(2) { + --bento-card-image-order: -1; + + grid-area: two; + + @media (width > 960px) { + --bento-card-image-width: 150%; + } + + /* fixing shadow issue in asset */ + >img { + filter: drop-shadow(0 0 1rem hsl(0 0% 0% / .25)); + border-radius: 100vw; + /* box-shadow: 0 0 1rem hsl(0 0% 0%); */ + } + } + + .bento-grid> :nth-child(3) { + --bento-card-surface: var(--accent-base); + + grid-area: three; + + + >img { + --bento-card-image-width: 75%; + + margin-bottom: -55px; + + @media (width > 960px) { + --bento-card-image-width: 100%; + margin-bottom: -125px; + } + } + } + + .bento-grid> :nth-child(4) { + --bento-card-horizontal-alignment: center; + --bento-card-surface: var(--primary-subdued); + + grid-area: four; + + @media (width > 960px) { + --bento-card-image-width: 180%; + --bento-card-horizontal-alignment: start; + --bento-card-vertical-alignment: center; + } + + } + + .bento-grid> :nth-child(5) { + --bento-card-horizontal-alignment: center; + --bento-card-foreground: var(--white); + --bento-card-surface: var(--primary-base); + --bento-card-image-width: 75%; + --bento-card-image-order: -1; + + grid-area: five; + + @media (width > 960px) { + --bento-card-gap: 16px; + --bento-card-image-width: 100%; + --bento-card-vertical-alignment: center; + --bento-card-horizontal-alignment: start; + grid-template-columns: 1fr 1fr; + } + } + + .bento-grid> :nth-child(6) { + --heading-font-size: var(--fs-xl); + --heading-span-display: block; + --heading-span-font-size: var(--fs-reg); + + --bento-card-image-width: 60%; + + grid-area: six; + + @media (width > 960px) { + --bento-card-image-width: 80%; + } + + } + + .bento-grid> :nth-child(7) { + --heading-span-foreground: var(--primary-base); + --heading-span-style: italic; + + --bento-card-surface: var(--accent-subdued); + --bento-card-image-width: 60%; + + + grid-area: seven; + + @media (width > 960px) { + --bento-card-image-width: 100%; + --bento-card-vertical-alignment: center; + } + } + + .bento-grid> :nth-child(8) { + --bento-card-surface: var(--accent-base); + --bento-card-image-width: 60%; + + grid-area: eight; + + @media (width > 960px) { + --bento-card-image-width: 105%; + --bento-card-vertical-alignment: center; + } + } +} + +@layer utilities { + .visually-first { + order: -1; + } +} \ No newline at end of file