From d4bdd1fde03b03a9ce1194cce071cedec76e0f4e Mon Sep 17 00:00:00 2001 From: inpsyde-maticluznar Date: Wed, 24 Jul 2024 06:41:20 +0200 Subject: [PATCH] Restore docs --- docs/.gitignore | 10 + docs/README.md | 33 +++ docs/_config.yml | 39 ++++ docs/asset-factory.md | 36 ++++ docs/assets.md | 437 ++++++++++++++++++++++++++++++++++++++++ docs/getting-started.md | 28 +++ docs/helpers.md | 43 ++++ docs/loaders.md | 180 +++++++++++++++++ docs/migration.md | 137 +++++++++++++ docs/output-filter.md | 85 ++++++++ 10 files changed, 1028 insertions(+) create mode 100644 docs/.gitignore create mode 100644 docs/README.md create mode 100644 docs/_config.yml create mode 100644 docs/asset-factory.md create mode 100644 docs/assets.md create mode 100644 docs/getting-started.md create mode 100644 docs/helpers.md create mode 100644 docs/loaders.md create mode 100644 docs/migration.md create mode 100644 docs/output-filter.md diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..e771d9e --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,10 @@ +_site +.sass-cache +.jekyll-cache +.jekyll-metadata +vendor + +Gemfile +Gemfile.lock +gems.rb +gems.locked diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..6247ac4 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,33 @@ +--- +title: Home +nav_order: 0 +permalink: / +--- + +# Inpsyde Assets + +## Introduction +Inpsyde Assets is a Composer package (not a plugin) that allows to deal with scripts and styles in a WordPress site. + +## Installation + +```bash +$ composer require inpsyde/assets +``` + +## Minimum Requirements and Dependencies + +* PHP 7.2+ +* WordPress latest-2 + +When installed for development, via Composer, Inpsyde Assets also requires: + +* phpunit/phpunit (BSD-3-Clause) +* brain/monkey (MIT) +* inpsyde/php-coding-standards + +## License and Copyright + +Copyright (c) Inpsyde GmbH. + +The team at [Inpsyde](https://inpsyde.com) is engineering the Web since 2006. diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 0000000..031bf85 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1,39 @@ +title: Inpsyde Assets +description: >- + Inpsyde Assets is a Composer package (not a plugin) that allows to deal with scripts and styles in a WordPress site. +baseurl: /assets # Your repo name with a leading slash. + +# Aux links for the upper right navigation +aux_links: + "Inpsyde Assets on GitHub": + - https://github.com/inpsyde/assets + +# Footer "Edit this page on GitHub" link text +gh_edit_repository: https://github.com/inpsyde/assets # Your repo GitHub URL + +# Everything above is repo specific. + +############################################################### + +# This section is repo specific. These can be omitted if defaults make sense. + +gh_edit_branch: master # The default branch of the repo. Default: main +gh_edit_source: docs # The directory containing the docs. Default: docs + +############################################################### + +# Everything below should be copy and pasted into package repos +remote_theme: inpsyde/jekyll-syde-theme + +############################################################### + +# Everything below should be copy and pasted into package repos +# To be replaced by jekyll-inpsyde-theme's `_config.yml` when GitHub Pages supports Jekyll v4. + +plugins: + - jekyll-remote-theme + - jekyll-seo-tag + - jekyll-sitemap + - jemoji + +permalink: pretty diff --git a/docs/asset-factory.md b/docs/asset-factory.md new file mode 100644 index 0000000..1099936 --- /dev/null +++ b/docs/asset-factory.md @@ -0,0 +1,36 @@ +--- +nav_order: 2 +--- +# Asset Factory +{: .no_toc } +## Table of contents +{: .no_toc .text-delta } +1. TOC +{:toc} +--- + +## `AssetFactory` +Instead of creating instances by hand, it's sometimes easier to use configuration via array or file to manage your specific assets. + +**:warning: Note:** The `AssetFactory` is replaced step by step via Loaders. Methods are set to `@deprecated` which have been moved to a Loader. + +## `AssetFactory::create()` + +To create a single Asset from an array, you can do following: + +```php + 'foo', + 'url' => 'www.example.com/assets/style.css', + 'location' => Asset::FRONTEND, + 'type' => Style::class + ], +); +``` diff --git a/docs/assets.md b/docs/assets.md new file mode 100644 index 0000000..09316ac --- /dev/null +++ b/docs/assets.md @@ -0,0 +1,437 @@ +--- +nav_order: 4 +--- +# Assets +{: .no_toc } +## Table of contents +{: .no_toc .text-delta } +1. TOC +{:toc} +--- + +There are two main classes delivered: + +* `Inpsyde\Assets\Script` - dealing with JavaScript-files. +* `Inpsyde\Assets\Style` - dealing with CSS-files. + +Each instance requires a `string $handle`, `string $url` and `int $location`. + +## Overview API + +Following configurations are available: + +|property|type|default|`Script`|`Style`|description| +|----|----|----|----|----|----| +|filePath|string|`''`|x|x|optional path which can be set to autodiscover the Asset version| +|dependencies|array|`[]`|x|x|all defined depending handles| +|location|int|falls back to `Asset::FRONTEND`|x|x|depending on location of the `Asset`, it will be enqueued with different hooks| +|version|string|`null`|x|x|version of the given asset| +|enqueue|bool/callable|`true`|x|x|is the asset only registered or also enqueued| +|data|array/callable|`[]`|x|x|additional data assigned to the asset via `WP_Script::add_data` or `WP_Style::add_data`| +|filters|callable[]|`[]`|x|x|an array of `Inpsyde\Assets\OutputFilter` or callable values to manipulate the output| +|handler|string|`ScriptHandler::class` or `StyleHandler::class`|x|x|The handler which will be used to register/enqueue the Asset| +|attributes|array|`[]`|x|x|Allows to set additional attributes to the `script`- or `link`-tag| +|media|string|`'all'`| |x|type of media for the `Style`| +|localize|array|`[]`|x| |localized array of data attached to `Script`| +|inFooter|bool|`true`|x| |defines if the current `Script` is printed in footer| +|inline|array|`[]`|x| |allows you to add inline scripts to `Script`-class via `['before' => [], 'after' => []]`| +|translation|array|`[]`|x| |Load translation for `Script`-class via `['path' => string, 'domain' => string]`| + +## Using the public API (methods) + +### Versions + +The version can be set in different ways and even autogenerated based on the file time. Following is possible: + +| version | autodiscover | returns | note | +|----|----|----|----| +| `null` (default) | `true` (default) | filemtime | the default behavior | +| `null` (default) |`false` | `null` | no version in WP is used | +| `'1.2.3'` | `true` / `false` | `'1.2.3'` | | +| `''` | `true` / `false` | current WP version | | + +```php +withFilePath('/path/to/script.js') + ->disableAutodiscoverVersion() + ->enableAutodiscoverVersion() + ->withVersion('1.0'); + +$style = new Style('foo', 'www.example.com/style.css'); +$style + ->withFilePath('/path/to/style.css') + ->disableAutodiscoverVersion() + ->enableAutodiscoverVersion() + ->withVersion('1.0'); +``` + +### Enqueue conditionally + +You can enqueue your Assets conditionally by using following API: + +```php +canEnqueue(true); + +$style = new Style('foo', 'www.example.com/style.css'); +$style->canEnqueue(function(): bool { + return is_admin(); +}); +``` + +By default Assets are always enqueued. + +### Location + +By default, the package comes with predefined locations of assets: + +|const|hook|location| +|---|---|---| +|`Asset::FRONTEND`|`wp_enqueue_scripts`|Frontend| +|`Asset::BACKEND`|`admin_enqueue_scripts`|Backend| +|`Asset::LOGIN`|`login_enqueue_scripts`|wp-login.php| +|`Asset::CUSTOMIZER`|`customize_controls_enqueue_scripts`|Customizer| +|`Asset::CUSTOMIZER_PREVIEW`|`customize_preview_init`|Customizer Preview| +|`Asset::BLOCK_EDITOR_ASSETS`|`enqueue_block_editor_assets`|Gutenberg Editor| +|`Asset::BLOCK_ASSETS`|`enqueue_block_editor_assets`|Frontend and Gutenberg Editor| +|`Asset::ACTIVATE`|`activate_wp_head`|wp-activate.php| + +#### API + +Location can be set either in constructor directly or via methods: + +```php +forLocation(Asset::BACKEND); + +$style = new Style('foo', 'www.example.com/style.css'); +$style->forLocation(Asset::FRONTEND); +``` + +The default location is `Asset::FRONTEND`. + +#### Using multiple locations + +To avoid duplicated registration of Assets in different locations such as backend and frontend, it is possible to add +multiple ones via bitwise operator `|` (OR). + +Here's a short example for a `Style` which will be enqueued in frontend *and* backend: + +```php +forLocation(Asset::BACKEND | Asset::FRONTEND); + + $assetManager->register($style); + } +); +``` + +### Dependencies resolving + +Adding an `Asset` with dependencies can be done like following: + +```php +use Inpsyde\Assets\Script; +use Inpsyde\Assets\Style; +use Inpsyde\Assets\Asset; + +$script = new Script('foo', 'www.example.com/script.js', Asset::FRONTEND); +$script->withDependencies('wp-elements', 'wp-core', 'wp-i18n'); + +$style = new Style('foo', 'www.example.com/style.css'); +$style->withDependencies('wp-elements'); +``` + +#### Automatic resolving of Script dependencies with Webpack + +The `Inpsyde\Assets\Script`-class has support for resolving dependencies and version which are generated +by [dependency-extraction-webpack-plugin](https://github.com/WordPress/gutenberg/tree/master/packages/dependency-extraction-webpack-plugin) +. + +This Webpack-Plugin will create an additional `{fileName}.assets.json` or `{fileName}.assets.php`-file which contains an +array of dependencies parsed out of your JavaScript-file and a version string. To use that feature you can use +following: + +**script.assets.json** + +```json +{ + "dependencies": [ + "foo", + "bar", + "baz" + ], + "version": "1234567" +} +``` + +```php +forLocation(Asset::FRONTEND) + ->withFilePath('/path/to/script.js'); + +$script->dependencies(); // ["foo", "bar", "baz"] +$script->version(); // "1234567" +``` + +Based on your `Asset::filePath` the `Script` automatically searches in the same folder for `{fileName}.assets.json|php` +and will load the data. + +:warning: This will not overwrite your existing settings: + +**script.assets.php** + +```php + ["foo", "bar", "baz"], + "version" => "1234567" +]; +``` + +```php +forLocation(Asset::FRONTEND) + ->withVersion('1.0') + ->withDependencies("some", "other", "dependencies") + ->withFilePath('/path/to/script.js'); + +$script->dependencies(); // ["foo", "bar", "baz", "some", "other", "dependencies"] +$script->version(); // "1.0" +``` + +### Change the Handler + +It is possible to change for an `Asset` the Handler like following: + +```php +useHandler(ScriptHandler::class); +``` + +### Add Filters + +#### `Script` + +Scripts are having the following filters available: + +```php +withFilters(AsyncScriptOutputFilter::class) + ->useDeferFilter() // shortcut + ->useAsyncFilter() // shortcut + ->useInlineFilter() // shortcut + ->withFilters(function(string $html, Asset $asset): string { + // your custom filter + return $html; + }); +``` + +#### `Style` + +Styles are having following filters available: + +```php +withFilters(AsyncStyleOutputFilter::class) + ->useAsyncFilter() // shortcut to above method + ->useInlineFilter() // shortcut + ->withFilters(function(string $html, Asset $asset): string { + return $html; + }); +``` + +### Localize data + +Scripts can have localized data via `wp_localize_script()`, which can be added like following: + +```php +withLocalize('foo', ['multiple values']) + ->withLocalize('bar', static function(): string { + return 'other value'; + }); +``` + +### Translation data + +Scripts can also have translation data via `wp_set_script_translations()`. This can be added like following: + +```php +withTranslation('domain', '/path/to/json/file.json'); +``` + +### Script enqueue Footer/Header + +To enqueue a script in header or footer - default is "footer" - we have following API available: + +```php +isInFooter() + ->isInHeader(); +``` + +### Adding inline scripts + +To add inline scripts via `wp_add_inline_script()` to your `Script`, you can use following: + +```php +appendInlineScript('var foo = "bar";') + ->prependInlineScript('var baz = "bam"'); +``` + +### Adding inline styles + +To add inline styles via `wp_add_inline_style()` to your `Style`, you can use following: + +```php +withInlineStyles('body { background-color: #000; }'); +``` + +### Adding custom CSS properties + +To add custom [CSS properties](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties) (CSS vars) you can use following API on your `Style`: + +```php +use Inpsyde\Assets\Style; + +$style = new Style('foo', 'www.example.com/style.css'); +$style->withCssVars('.some-element', ['white' => '#fff', 'black' => '000']); +$style->withCssVars(':root', ['grey' => '#ddd']); +``` + +The `StyleHandler` will automatically check if there are CSS vars available via `Style::cssVars()` and add them via `wp_add_inline_style()` to your handle. + +**Note:** Registered CSS vars will be automatically prefixed with `--` if not present. The example from above will generate following output: + +```css +.some-element{--white:#fff;--black:#000} +:root{--grey:#ddd} +``` + +### Conditional comments for Script/Style + +Styles and Script can be wrapped into Conditional comments. To do so, you can use following: + +```php +withCondition('gt IE 9'); // + +$style = new Style('foo', 'www.example.com/style.css'); +$style->withCondition('lt IE 9'); // +``` + +### Attributes + +Allows you to set additional attributes to your `script`- or `link`-tag like following: + +```php +withAttributes( + [ + 'async' => true, + 'data-value' => 'key', + 'nonce' => wp_create_nonce() + ] +); +// + + +$style = new Style('my-handle', 'style.css'); +$style->withAttributes( + [ + 'data-value' => 'key', + 'nonce' => wp_create_nonce() + ] +); +// +``` + +Existing attributes like "src" or "id" are not overwriteable. The `Inpsyde\Assets\OutputFilter\AttributesOutputFilter` only sets attributes which are not already existent on the html-tag. This will *not* work: + +```php +withAttributes(['src' => 'another-script.js']); // Will not overwrite "script.js" +``` diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 0000000..788483f --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,28 @@ +--- +nav_order: 1 +--- + +# Getting started + +## Getting started - the `AssetManager` + +When using Assets in your theme or plugin, you can simply access the `Inpsyde\Assets\AssetManager` by hooking into the setup-hook. + +This way you can start registering your assets: + +```php +register( + new Script('foo', 'www.example.com/script.js'), + new Style('foo', 'www.example.com/style.css') + ); + } +); +``` diff --git a/docs/helpers.md b/docs/helpers.md new file mode 100644 index 0000000..45ccee1 --- /dev/null +++ b/docs/helpers.md @@ -0,0 +1,43 @@ +--- +nav_order: 6 +--- +# Helpers +{: .no_toc } +## Table of contents +{: .no_toc .text-delta } +1. TOC +{:toc} +--- + + +The `inpsyde/assets`-Package comes with some useful helper functions. + +## Asset Suffix + +The function `Inpsyde\Assets\assetSuffix` allows to automatically suffix the given Asset with `.min` if `SCRIPT_DEBUG === false`: + +```php + my-script.min.js +// if SCRIPT_DEBUG === true -> my-script.js +``` + + +## Symlink an Asset-folder + +Sometimes your Assets will not be inside the web-root, like Composer packages which are normally published outside of web-root. +Therefor you can use a simple helper `Inpsyde\Assets\symlinkedAssetFolder` which allows you to move your asset-folder inside the web-root: + +```php +load('manifest.json'); +``` + +If the Asset URL needs to be changed, you can use following: + +```php +withDirectoryUrl('www.example.com/path/to/assets/'); +/** @var \Inpsyde\Assets\Asset[] $assets */ +$assets = $loader->load('manifest.json'); +``` + +### `EncoreEntrypointsLoader` + +[Symfony Webpack Encore](https://symfony.com/doc/current/frontend.html) provides a custom implementation of the [assets-webpack-plugin](https://www.npmjs.com/package/assets-webpack-plugin) which groups asset chunks into a single array for a given handle. + +The `EncoreEntrypointsLoader` can load those configurations and automatically configure your dependencies for splitted chunks. + +**entrypoints.json** + +```json +{ + "entrypoints": { + "theme": { + "css": [ + "./theme.css", + "./theme1.css", + "./theme2.css", + ] + } + } +} +``` + +And loading this file: + +```php +load('entrypoints.json'); + +$second = $assets[1]; // theme1.css +$second->dependencies(); // handle from $asset[0] + +$third = $assets[2]; // theme2.css +$third->dependencies(); // handles from $asset[1] and $asset[2] +``` + + +## `ArrayLoader` + +To create multiple Assets you can use following: + +```php + 'foo', + 'url' => 'www.example.com/assets/style.css', + 'location' => Asset::FRONTEND, + 'type' => Style::class + ], + [ + 'handle' => 'bar', + 'url' => 'www.example.com/assets/bar.js', + 'location' => Asset::FRONTEND, + 'type' => Script::class + ], +]; + +$loader = new ArrayLoader(); +/** @var Asset[] $assets */ +$assets = $loader->load($config); +``` + +## `PhpFileLoader` + +If you want to avoid having large array configuration in your code, you can move everything to an external PHP-file which returns the array: + +**config/assets.php** +```php + 'foo', + 'url' => 'www.example.com/assets/style.css', + 'location' => Asset::FRONTEND, + 'type' => Style::class + ], + [ + 'handle' => 'bar', + 'url' => 'www.example.com/assets/bar.js', + 'location' => Asset::FRONTEND, + 'type' => Script::class + ], +]; +``` + +And in your application: + +```php +load('config/assets.php'); +``` + + +## Configure autodiscovering version + +In webpack it is possible to configure file name versioning which will produce something like: `script.{hash}.js`. To support versioning via file name you can simply disable the auto discovering of file versioning like this: + +```php +disableAutodiscoverVersion(); +/** @var \Inpsyde\Assets\Asset[] $assets */ +$assets = $loader->load('manifest.json'); +``` + +:warning: All 4 loaders supporting to disable the auto discovering of version. diff --git a/docs/migration.md b/docs/migration.md new file mode 100644 index 0000000..03fcd90 --- /dev/null +++ b/docs/migration.md @@ -0,0 +1,137 @@ +--- +nav_order: 7 +--- +# Migration +{: .no_toc } +## Table of contents +{: .no_toc .text-delta } +1. TOC +{:toc} +--- + +## From 1.0 to 1.1 +In version 1.1 we didn't implemented breaking changes, but we're renamend some internals for `Inpsyde\Assets\Asset` to be more clear when using the config-driven approach. In future you'll have to change your Asset-configuration, since we don't want to ship to much legacy code. + +The config key `type` has been renamend to `location`, while `class` is now `type`. The `Inpsyde\Assets\Asset:type()` will be now `Inpsyde\Assets\Asset:location()`. + +**Before:** +```php + 'my-handle', + 'src' => 'script.css', + 'type' => Asset::FRONTEND, + 'class' => Style::class, + ] +); +``` + +**After:** +```php + 'my-handle', + 'src' => 'script.css', + 'location' => Asset::FRONTEND, + 'type' => Style::class, + ] +); +``` + + +## From 0.2 to 1.0 +### Asset registration +{: .no_toc } +In version 1.0 the function `Inpsyde\Assets\assetManager()` was replaced to improve the compatilibty with WordPress and to avoid calling `wp_styles()` and `wp_scripts()` too early. This is why the registration of an `Asset` now happens via hook callback instead of using the factory-function. + +**Before:** +```php +register(...); +``` + +**After:** +```php +register(...); + } +); +``` + +### Renaming of `Asset`-flags and `AssetFactory::create` requirements +{: .no_toc } +The type-flags from `Inpsyde\Assets\Asset` are renamed after the location where the given asset will be enqueued. Also the `type` is now no longer used to create instances of the class. Instead the class itself should be defined in `'class'`-field of the `$config` when using the `AssetFactory`. + +This enables also the possiblity to use different implementations of `Inpsyde\Assets\Asset` with own `INpsyde\Assets\Handler\AssetHandler`. + +**Before:** +```php + 'my-handle', + 'src' => 'script.css', + 'type' => Asset::TYPE_STYLE, + ] +); +``` + +**After:** +```php + 'my-handle', + 'src' => 'script.css', + 'type' => Asset::FRONTEND, + 'class' => Style::class + ] +); +``` + +---- + +## From 0.1 to 0.2 +In version 0.2 the function `Inpsyde\Assets\assetFactory()` was removed and replaced by the static factory. + + +**Before:** +```php +create(...); +``` + +**After:** +```php +withFilters(AsyncScriptOutputFilter::class); +``` + +## Available filters + +Following default OutputFilters are shipped with this package: + +### `AsyncStyleOutputFilter` +{: .no_toc } +This filter will allow you to load your CSS async via `preload`. It also delivers a polyfill for older browsers which is +appended once to ensure that script-loading works properly. + +```html + + + +``` + +### `InlineAssetOutputFilter` +{: .no_toc } +This filter allows you to print your `Style` or `Script` inline into the DOM if the file is readable. + +### `AttributesOutputFilter` +{: .no_toc } +This filter will be added automatically if you're using `Asset::withAttributes([])` and allows you to set additonal +key-value pairs as attributes to your `script`- or `link`-tag. + +See more in [Assets](./assets.md). + +### `AsyncScriptOutputFilter` (deprecated) +{: .no_toc } +:warning: **Deprecated:** Please use instead `Script::withAttributes(['async' => true]);` + +### `DeferScriptOutputFilter` (deprecated) +{: .no_toc } +:warning: **Deprecated:** Please use instead `Script::withAttributes(['defer' => true]);` + +## Create your own filter + +You can either implement the `Inpsyde\Assets\OutputFilter\AssetOutputFilter`-interface or just use a normal callable +function which will applied on the `Asset`: + +```php +withFilters($customFilter); +```