vaersaagod/toolmate

Is that a tool in your pocket, or are you just happy to see me, mate?

Installs: 1 355

Dependents: 0

Suggesters: 0

Security: 0

Stars: 3

Watchers: 5

Forks: 1

Open Issues: 1

Type:craft-plugin

1.5.0 2024-02-21 13:01 UTC

This package is auto-updated.

Last update: 2024-12-21 14:43:08 UTC


README

Is that a tool in your pocket, or are you just happy to see me, mate!

Screenshot

Requirements

This plugin requires Craft CMS 3.1.0 or later.

Installation

To install the plugin, either install it from the plugin store, or follow these instructions:

  1. Install with composer via composer require vaersaagod/toolmate from your project directory.
  2. Install the plugin in the Craft Control Panel under Settings → Plugins, or from the command line via ./craft install/plugin toolmate.

Configuring

ToolMate can be configured by creating a file named toolmate.php in your Craft config folder, and overriding settings as needed.

publicRoot [string]

Default: @webroot

Sets the public webroot that is used by inline and stamp on servers where $_SERVER['DOCUMENT_ROOT'] and @webroot is incorrect.

enableMinify [bool]

Default: true

Enables/disables all minifying.

embedCacheDuration [int|string|bool|null]

Default: null

The number of seconds to cache responses from craft.toolmate.getVideoEmbed().

If set to null, the core cacheDuration setting is used.

If set to false responses are not cached.

If set to 0, cached responses will be stored indefinitely.

See craft\helpers\ConfigHelper::durationInSeconds() for a list of supported value types.

embedCacheDurationOnError [int|string|bool|null]

Default: 300 (5 minutes)

The number of seconds to cache responses from craft.toolmate.getVideoEmbed() when there is an error (i.e. a valid embed code could not be returned).

If set to null, the default value (300, 5 minutes) is used.

If set to false, error responses are not cached.

If set to 0, error response caches will be stored indefinitely.

See craft\helpers\ConfigHelper::durationInSeconds() for a list of supported value types.

csp [array|null]

Default null

Configure the Content-Security-Policy header set by Toolmate. Some useful tips:

  • Avoid using unsafe-inline and unsafe-eval policies, especially for the script-src directive. CSP nonces should ideally be used for inline script or style tags, see the cspNonce() Twig function.
  • Nonces and unsafe-inline cannot be combined. Toolmate works around this to avoid CSP errors, but TLDR; is that you don't need to set nonces if you're also using unsafe-inline.
  • CSP nonces generated by cspNonce() are safe to put inside {% cache %} tags
  • To enable data-URLs, add a data: policy to the relevant directives
  • For CP requests, Toolmate will always add the necessary unsafe-inline and unsafe-eval policies, because the CP isn't possible to use without.

csp[enabled] [bool]

Default false

If set to false, the CSP header will not be sent for any requests.

csp[enabledForCp] [bool]

Default false

If set to false, the CSP header will only be sent for site requests.

csp[reportOnly] [bool]

Default false

If set to true, the CSP header will be sent, but not enforced (i.e. dry-run mode). Useful for testing policies.

csp[directives] [array]

See https://content-security-policy.com/, and the example config below.

Example CSP configuration:

'csp' => [
    'enabled' => true,
    'enabledForCp' => false,
    'reportOnly' => false,
    'directives' => [
        'defaultSrc' => [
            "'self'",
        ],
        'scriptSrc' => [
            "'self'",
            "'unsafe-inline'",
        ],
        // Sources for stylesheets
        'styleSrc' => [
            "'self'",
            "'unsafe-inline'",
        ],
        // Sources for images
        'imgSrc' => [
            "'self'",
            'https://some-project.imgix.net',
            'data:'
        ],
        // Sources for iframes
        'frameSrc' => [
            "'self'",
            'https://www.youtube.com https://player.vimeo.com https://www.facebook.com https://www.googletagmanager.com https://bid.g.doubleclick.net',
        ],
        // Domains that are allowed to iframe this site
        'frameAncestors' => [
            "'self'",
        ],
        'baseUri' => [
            "'none'",
        ],
        'connectSrc' => [],
        'fontSrc' => [
            //"'self'",
        ],
        'objectSrc' => [],
        'mediaSrc' => [],
        'sandbox' => [],
        'reportUri' => [],
        'childSrc' => [],
        'formAction' => [],
        'reportTo' => [],
        'workerSrc' => [],
        'manifestSrc' => [],
        'navigateTo' => [],
    ],
],

Template variables

craft.toolmate.inline(filename [, remote=false])

{{ craft.toolmate.inline('/assets/critical.css') }}

craft.toolmate.stamp(filename [, mode = 'file', type = 'ts'])

{# /assets/bundle.1522425799.js #}
{{ craft.tool.stamp('/assets/bundle.js') }}

{# /assets/1522425799/bundle.js #}
{{ craft.tool.stamp('/assets/bundle.js', 'folder') }}

{# /assets/5140247221/bundle.js #}
{{ craft.tool.stamp('/assets/bundle.js', 'folder', 'hash') }}

{# /assets/bundle.js?ts=1522425799 #}
{{ craft.tool.stamp('/assets/bundle.js', 'query') }}

{# 1522425799 #}
{{ craft.tool.stamp('/assets/bundle.js', 'tsonly') }}

craft.toolmate.setCookie(params [, secure = false])

{% do craft.toolmate.setCookie({ name: 'testing', value: 'Just testing!' }) %}
{% do craft.toolmate.setCookie({ name: 'testingsecure', value: { lorem: 'ipsum', dolor: 'sit amet' } }, true) %}

{% set params = {
    name: 'cookiename',
    value: 'thevalue',
    expire: 0,
    path: '/',
    domain: '',
    secure: false,
    httpOnly: false,
    sameSite: null,
} %}

{% do craft.toolmate.setCookie(params) %}

craft.toolmate.getCookie(name [, secure = false])

{{ craft.toolmate.getCookie('testing') }}
{{ dump(craft.toolmate.getCookie('testingsecure', true)) }}

craft.toolmate.getVideoEmbed(url [, params = []])

{% set videoEmbed = craft.toolmate.getVideoEmbed(videoUrl, {
    youtube_enablejsapi: 1,
    youtube_rel: 0,
    youtube_showinfo: 0,
    youtube_controls: 1,
    youtube_autoplay: 0,
    youtube_modestbranding: 1,
    youtube_playsinline: 0,
    vimeo_byline: 0,
    vimeo_title: 0,
    vimeo_autoplay: 0,
    vimeo_portrait: 0
}) %}

Twig tags

minify

<style>    
    {% minify css %}
        .lorem {
            width: 200px;
        }
        .ipsum {
            padding: 0px;
        }
    {% endminify %}
</style>

<script>
    {% minify js %}
        var myFunction = function () {
            console.log('Some inline JS');
        }
    {% endminify %}
</script>

{% minify html %}
    <div>
        <p>Some html</p>
    </div>
{% endminify %}

Twig functions

inline(filename [, remote=false])

See craft.toolmate.inline.

stamp(filename [, mode = 'file', type = 'ts'])

See craft.toolmate.stamp.

setCookie(params [, secure = false])

See craft.toolmate.setCookie.

getCookie(name [, secure = false])

See craft.toolmate.getCookie.

getVideoEmbed(url [, params = []])

See craft.toolmate.getCookie.

cspNonce(directive, [, asAttribute = false, hash = true])

Output a CSP nonce. Example:

<script nonce="{{ cspNonce('script-src') }}">
   console.log('Hello world');
</script>
<style nonce="{{ cspNonce('style-src') }}">
    body { ... }
</style>
{% js 'foo.js' with { nonce: cspNonce('script-src') } %}

Price, license and support

The plugin is released under the MIT license. It's made for Værsågod and friends, and no support is given. Submitted issues are resolved if it scratches an itch.

Changelog

See CHANGELOG.MD.

Credits

Brought to you by Værsågod

Icon designed by Freepik from Flaticon.