The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Progressive::Web::Application - Utility for making an application 'progressive'

VERSION

Version 0.08

SYNOPSIS

# vim MyApp/pwa.pl

        use Progressive::Web::Application;

        my $pwa = Progressive::Web::Application->new({
                root => 'root',
                pathpart => 'payments',
                manifest => {
                        name => 'Progressive Web Application Demo',
                        short_name => 'PWA Demo',
                        icons => '/root/static/images/icons',
                        start_url => '/',
                        display => 'standalone',
                        background_color => '#2b3e50',
                        theme_color => '#2c3e50'
                },
                params => {
                        offline_path => '/offline.html',
                        cache_name => 'my-cache-name',
                        files_to_cache  => [
                                '/manifest.json',
                                '/favicon.ico',
                                '/static/css/bootstrap.min.css',
                                '/static/css/lnation.css',
                                ...
                        ],
                }
        });

        $pwa->compile();

        ...

DESCRIPTION

This module is a Utility for aiding you in creating Progressive Web Applications (PWA's). Progressive web apps use modern browser APIs along with traditional progressive enhancement strategy to create cross-platform applications. These apps work everywhere that a browser runs and provide several features that give them the same user experience advantages as native apps.

PWAs should be discoverable, installable, linkable, network independent, progressive, re-engageable, responsive, and safe.

Discoverable

The eventual aim is that web apps should have better representation in search engines, be easier to expose, catalog and rank, and have metadata usable by browsers to give them special capabilities.

Installable

A core part of the apps experience is for users to have app icons on their home screen, that launch in a native container that feels integrated with the underlying platform.

Linkable

One of the most powerful features of the Web is to be able to link to an app at a specific URL - no app store needed, no complex installation process. This is how it has always been.

Network Independent

Can work when the network is unreliable, or even non-existent.

Progressive

Can be developed to provide a modern experience to fully capable browsers, and an acceptable (although not quite as shiny) experience in less capable browsers.

Re-engageable

One major advantage of native platforms is the ease with which users can be re-engaged by updates and new content, even when they aren't looking at the app or using their devices. Modern Web APIs allow us to do this too, using new technologies such as Service Workers for controlling pages, the Web Push API for sending updates straight from server to app via a service worker, and the Notifications API for generating system notifications to help engage users when they're not in the browser.

Responsive

Responsive web apps use technologies like media queries and viewport to make sure that their UIs will fit any form factor: desktop, mobile, tablet, or whatever comes next.

Safe

You can verify the true nature of a PWA by confirming that it is at the correct URL, whereas apps in apps stores can often look like one thing, but be another. Example - https://twitter.com/andreasbovens/status/926965095296651264

Methods

new

Instantiate a new Progressive::Web::Application Object.

        Progressive::Web::Application->new();

options

root

The root(/) directory of your application, this is used to validate links and where any output from this module will be compiled/written.

        lnation:High lnation$ ls
        MyApp

        .......

        Progressive::Web::Application->new( 
                root => 'MyApp/root'
        );

pathpart

Is your application proxied to a path.

        https://localhost/admin/*

        .......

        Progressive::Web::Application->new(
                pathpart => 'admin'
        );

manifest

A Hash reference of params to build the web app manifest. See manifest_schema for more information.

        Progressive::Web::Application->new(
                manifest => {
                        name => 'Progressive Web Application Demo',
                        short_name => 'PWA Demo',
                        icons => '/root/static/images/icons',
                        start_url => '/',
                        display => 'standalone',
                        background_color => '#2b3e50',
                        theme_color => '#2c3e50'
                },
        );

template

A string that represents a template class. See Progressive::Web::Application::Template namespace for options.

        Progressive::Web::Application->new(
                template => 'General' # the default
        );

params

A Hash reference of params that are passed into the template. These are dynamic based upon the selected template so check the documentation for more information on what is required. However the following have some addtional logic to aide you.

cache_name

All templates will have a cache name, it is used to keep track of the version of the cache. Each release that has resource changes will require an update to the cache_name. This ensures your end users service workers clears the existing cache and re-fetch's the resources from your server.

        Progressive::Web::Application->new(
                params => {
                        cache_name => 'my_cache_name_v2'
                }
        );
files_to_cache

You can pass in as an Array reference, Hash reference or Code block.

ARRAY - expects a list of files to be cached

        Progressive::Web::Application->new(
                params => {
                        files_to_cache => [
                                'resources/css/app.css',
                                'resources/js/app.js',
                                ...
                        ]
                }
        );

HASH - params to be passed to $pwa->tools->{identify_files_to_cache}, see documentation for more information.

        Progressive::Web::Application->new(
                params => {
                        files_to_cache => {
                                directory => 'root/static',
                                recurse => 1
                        }
                }
        );

CODE - a custom code block that returns an Array references of files to cache.

        Progressive::Web::Application->new(
                params => {
                        files_to_cache => sub {
                                my $tool = @_;
                                my @files = (
                                        $tool->{read_directory}->('root/static/js'),
                                        $tool->{read_directory}->('root/static/css'),
                                );
                                ...
                                return \@files;
                        }
                }
        );

set_template

Set the template class.

        $pwa->set_template(template => 'General');

set_pathpart

Set the pathpart of your application.

        $pwa->set_pathpart('somepath');

set_root

Set the root directory of your application.

        $pwa->set_root('MyApp/root');

has_manifest

Does the Progressive::Web::Applcation object have a manifest configured, returns true or false value (1|0).

        $pwa->has_manifest();

manifest

Return the configured manifest, if a true param is passed then this is returned as json.

        $pwa->manifest(1);

set_manifest

Set the manifest params see manifest_schema for full options.

        $pwa->set_manifest(
                name => 'Progressive Web Application Demo',
                short_name => 'PWA Demo',
                icons => '/root/static/images/icons',
                start_url => '/',
                display => 'standalone',
                background_color => '#2b3e50',
                theme_color => '#2c3e50'
        );

clear_manifest

Clear/Delete manifest from the object, this is usefull for when you call 'compile' to different outpaths multiple times within a script.

        $pwa->clear_manifest();

has_params

Does the Progressive::Web::Application have params configured, returns true or false value (1|0).

        $pwa->has_params();

params

Return the configured manifest, if a true param is passed then this is returned as json.

        $pwa->params(1);

set_params

Set the template params see the configured template for what is required.

        $pwa->set_params(
                offline_path => '/offline.html',
                cache_name => 'my-cache-name',
                files_to_cache  => [
                        '/manifest.json',
                        '/favicon.ico',
                        '/static/css/bootstrap.min.css',
                        '/static/css/lnation.css',
                        ...
                ],
        );

clear_params

Clear/Delete params from the object, this is usefull for when you call 'compile' to different outpaths multiple times within a script.

        $pwa->clear_params();

template

Returns the template object.

        $pwa->template();

templates

Returns the rendered templates as a hash reference.

        $pwa->templates();

compile

This will write the manifest.json and any templates configured in the Template class into the root directory. You can optionally pass in a different path for the resources to be written.

        $pwa->compile();

        ...

        $pwa->compile('MyApp/root/resources');

manifest_schema

name

Scalar - The applications 'full' name.

        $pwa->set_manifest(name => 'My Application Name');

The name member is a string that represents the name of the web application as it is usually displayed to the user (e.g., amongst a list of other applications, or as a label for an icon). name is directionality-capable, which means it can be displayed left-to-right or right-to-left based on the values of the dir and lang manifest members.

https://developer.mozilla.org/en-US/docs/Web/Manifest/name

short_name

Scalar - The applications 'abbreviation' name

        $pwa->set_manifest(short_name => 'MyApp');

The short_name member is a string that represents the name of the web application displayed to the user if there is not enough space to display name (e.g., as a label for an icon on the phone home screen). short_name is directionality-capable, which means it can be displayed left-to-right or right-to-left based on the value of the dir and lang manifest members.

https://developer.mozilla.org/en-US/docs/Web/Manifest/short_name

description

Scalar - Description of the application.

        $pwa->set_manifest(description => 'A description about my application');

The description member is a string in which developers can explain what the application does. description is directionality-capable, which means it can be displayed left to right or right to left based on the values of the dir and lang manifest members.

https://developer.mozilla.org/en-US/docs/Web/Manifest/description

lang

Scalar - Language of the application

        $pwa->set_manifest(lang => 'en-GB');

The lang member is a string containing a single language tag (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang). It specifies the primary language for the values of the manifest's directionality-capable members, and together with dir determines their directionality.

https://developer.mozilla.org/en-US/docs/Web/Manifest/lang

dir

Scalar - Direction of Lang (auto|ltr|rtl)

        $pwa->set_manifest(dir => 'ltr');

The base direction in which to display direction-capable members of the manifest. Together with the lang member, it helps to correctly display right-to-left languages.

https://developer.mozilla.org/en-US/docs/Web/Manifest/dir

orientation

Scalar - orientation of the screen (any|natural|landscape|landscape-primary|landscape-secondary|portrait|portrait-primary|portrait-secondary)

        $pwa->set_manifest(orientation => 'natural');

The orientation member defines the default orientation for all the website's top-level browsing contexts. The orientation can be changed at runtime via the Screen Orientation API (https://developer.mozilla.org/en-US/docs/Web/API/Screen/orientation)

https://developer.mozilla.org/en-US/docs/Web/Manifest/orientation

Boolean - Prefer a related web application to recommend to 'install'.

        $pwa->set_manifest(prefer_related_applications => \1)

The prefer_related_applications member is a boolean value that specifies that applications listed in related_applications should be preferred over the web application. If the prefer_related_applications member is set to true, the user agent might suggest installing one of the related applications instead of this web app.

https://developer.mozilla.org/en-US/docs/Web/Manifest/prefer_related_applications

ArrayRef - A list of related application to recommend

        $pwa->set_manifest(related_applications => [
                {
                        platform => "play",
                        url => "https://play.google.com/store/apps/details?id=com.example.app1",
                        id => "com.example.app1"
                }
        ]);

The related_applications field is an array of objects specifying native applications that are installable by, or accessible to, the underlying platform - for example, a native Android application obtainable through the Google Play Store. Such applications are intended to be alternatives to the manifest's website that provides similar/equivalent functionality - like the native app equivalent.

https://developer.mozilla.org/en-US/docs/Web/Manifest/related_applications

iarc_rating_id

Scalar - International Age Rating Coalition (IARC) certification code

        $pwa->set_manifest(iarc_rating_id => 'e84b072d-71b3-4d3e-86ae-31a8ce4e53b7');

The iarc_rating_id member is a string that represents the International Age Rating Coalition (https://www.globalratings.com) certification code of the web application. It is intended to be used to determine which ages the web application is appropriate for.

https://developer.mozilla.org/en-US/docs/Web/Manifest/iarc_rating_id

scope

Scalar - Applications scope

        $pwa->set_manifest(scope => '/app/');

The scope member is a string that defines the navigation scope of this web application's application context. It restricts what web pages can be viewed while the manifest is applied. If the user navigates outside the scope, it reverts to a normal web page inside a browser tab or window.

https://developer.mozilla.org/en-US/docs/Web/Manifest/scope

screenshots

ArrayRef - Application screenshot previews

        $pwa->set_manifest(screenshots => [
                {
                        src => "screenshot1.webp",
                        sizes => "1280x720",
                        type => "image/webp"
                }
        ]);

The screenshots member defines an array of screenshots intended to showcase the application. These images are intended to be used by progressive web app stores.

https://developer.mozilla.org/en-US/docs/Web/Manifest/screenshots

categories

ArrayRef - Application categories

        $pwa->set_manifest(categories => [
                "finance"
        ]);

The categories member is an array of strings defining the names of categories that the application supposedly belongs to. There is no standard list of possible values, but the W3C maintains a list of known categories. (https://github.com/w3c/manifest/wiki/Categories)

https://developer.mozilla.org/en-US/docs/Web/Manifest/categories

start_url

Scalar - Start path the application will launch

        $pwa->set_manifest(start_url => '/home');

The start_url member is a string that represents the start URL of the web application - the prefered URL that should be loaded when the user launches the web application (e.g., when the user taps on the web application's icon from a device's application menu or homescreen).

https://developer.mozilla.org/en-US/docs/Web/Manifest/start_url

icons

Scalar - a directory path passed into $TOOL{identify_icon_information}

        $pwa->set_manifest(icons => 'root/static/images/icons');

HashRef - generate_icons or validate hash as an icon.

        $pwa->set_manifest(icons => {
                file => 'root/static/images/320x320-icon.png',
                outpath => 't/resources/icons',
        });

        ...

        $pwa->set_manidest(icons => {
                sizes => '310x310',
                src => '/t/resources/320x320-icon.png',
                type => 'image/png'
        });

Code - Custom coderef that returns an array of icons

        $pwa->set_manidest(icons => sub {
                my $tool = shift;
        });

ArrayRef - itterate Scalar/Hash/Code

The icons member specifies an array of objects representing image files that can serve as application icons for different contexts. For example, they can be used to represent the web application amongst a list of other applications, or to integrate the web application with an OS's task switcher and/or system preferences.

https://developer.mozilla.org/en-US/docs/Web/Manifest/icons

display

Scalar - Browser display mode (standalone|minimal-ui|fullscreen|browser)

The display member is a string that determines the developers preferred display mode for the website. The display mode changes how much of browser UI is shown to the user and can range from "browser" (when the full browser window is shown) to "fullscreen" (when the app is full-screened).

https://developer.mozilla.org/en-US/docs/Web/Manifest/display

background_color

Scalar - Background colour

The background_color member defines a placeholeder background color for the application page to display before its stylesheet is loaded. This value is used by the user agent to draw the background color of a shortcut when the manifest is available before the stylesheet has loaded.

https://developer.mozilla.org/en-US/docs/Web/Manifest/background_color

theme_color

Scalar - Theme colour

The theme_color member is a string that defines the default theme color for the application. This sometimes affects how the OS displays the site (e.g., on Android's task switcher, the theme color surrounds the site).

https://developer.mozilla.org/en-US/docs/Web/Manifest/theme_color

tools

tainted

Returns a regex used to make paths/files taint safe.

        my $filename =~ $tools->{tainted};
        $1 # taint safe *\o/*

array_check

Validate the param is an Array, returns the param if valid and it will die/croak if invalid.

        my $arrayref = [qw/a b c/];
        $tool->{array_check}->($arrayref);

scalar_check

Validate the param is a Scalar (not a scalar reference), return the param if vaid and it will die/croak if invalid.

        my $string = 'abc';
        $tool->{scalar_check}->($string);

colour_check

Validate the param is a valid colour, returns the param if valid and it will die/croak if invalid.

        my $colour = '#000';
        $tool->{colour_check}->($colour);

JSON

Returns a JSON object with 'pretty' mode turned on.

        $tool->{JSON}->encode($ref);

to_json

Encodes the passed param as JSON.

        my $ref = { a => 'b' };
        $tool->{to_json}->($ref);

from_json

Decodes the passed json into a perl struct.

        my $json = q|{"a":"b"}|;
        $tool->{from_json}->($ref);

make_path

Creates the path in the file system.

        $tool->{make_path}->('root/static/new/path');

remove_abs

Removes the absolute path from a file path.

        my $path = '/var/www/MyApp/root/static/images/icon/one.png';
        my $relative = $tool->{remove_abs}->($path);
        # 'root/static/images/icon/one.png'
        

abs

Converts a relative path into an absolute path.

        my $rel = 'root/static/images/icon/one.png';
        my $abs = $tool->{abs}->($rel);
        # '/var/www/MyApp/root/static/images/icon/one.png'

write_file

Creates/Writes a file.

        $tool->{write_file}->('root/static/images/icons/two.png', $png_data);   

read_file

Reads a file into memory.

        $tool->{read_file}->('root/static/images/icons/two.png');

remove_file

Removes/Deletes a file.

        $tool->{remove_file}->('root/static/images/icons/two.png');

read_directory

Reads a directory into an array of filenames. First argument should be the directory path, you can optionally pass the following options.

recurse

Boolean to determine whether directories within the passed directory should be recursed.

blacklist_regex

A blacklist regex which will skip file paths that match it.

whitelist_regex

A whitelist regex which will skip file paths that do not match it.

        $tool->{read_directory}->('root/static', 
                recurse => 1,
                blacklist_regex => qr/documentation/
        );

remove_directory

Removes/Deletes a directory.

        $tool->{remove_directory}->('root/static/images/icons');

valid_icon_sizes

Returns an Hash reference of known valid icon sizes, this is to cater for the various devices your application may be installed on.

        $tool->{valid_icon_sizes}->{'36x36'}; # valid
        $tool->{valid_icon_sizes}->{'1000x1000'}; # invalid

vaid_icon_types

Returns an Hash reference of currently supported icon types.

        $tool->{valid_icon_types}->{'image/png'};

generate_icons

Accepts an path to an icon and generates an icon for each of the valid_icon_sizes. You can optionally pass the following options.

outpath

The directory the icons will be generated/written too (default is the directory of the original icon).

icon_name

The suffix that will applied to the icon name (default is 'icon')

        $tool->{generate_icons}->('root/static/images/one.png', 
                outpath => 'root/static/images/icons'
        );

identify_icon_size

Identify an icons size and validate tagains valid_icon_sizes.

        $tool->{identify_icon_size}->('root/static/images/icon/my-icon.png');

identify_icon_information

Identify icon information from a passed file.

        $tool->{identify_icon_size}->('root', 'root/static/images/icon/my-icon.png');
        
        # {
        #       src => '/static/images/icon/my-icon.png',
        #       type => 'image/png',
        #       sizes => '36x36'
        # }

validate_icon_information

Validate a passed hashref is a valid 'icon' definition.

        my $icon = {
                src => '/static/images/icon/my-icon.png',
                type => 'image/png',
                sizes => '36x36'
        };
        $tool->{validate_icon_information}->($icon);

parse_params

Parse params, from a hash reference into a hash 'list'.

        my ($self, %hash) = $tool->{parse_params}->($self, { a => "b" });
        my ($self, %hash) = $tool->{parse_params}->($self, a => "b");

identify_files_to_cache

Returns a list of files/resources to cache. Accepts a directory or an Arrayref of directorys and optionally params that are passed to $tool{reaD_directory} see documentation for more information.

        my @files_to_cache = $tool->{identify_files_to_cache}->([
                'root/static/js',
                'root/static/css',
                'root/static/images'
        ]);

valid_orientation

Returns an Hash reference of known orientations.

        $tool->{valid_icon_sizes}->{'landscape'}; # valid
        $tool->{valid_icon_sizes}->{'introverted'}; # invalid

AUTHOR

LNATION, <email at lnation.org>

BUGS

Please report any bugs or feature requests to bug-progressive-web-application at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Progressive-Web-Application. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

        perldoc Progressive::Web::Application

You can also look for information at:

ACKNOWLEDGEMENTS

LICENSE AND COPYRIGHT

Copyright 2019 LNATION.

This program is free software; you can redistribute it and/or modify it under the terms of the the Artistic License (2.0). You may obtain a copy of the full license at:

http://www.perlfoundation.org/artistic_license_2_0

Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license.

If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license.

This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder.

This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed.

Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.