├── .editorconfig ├── .github ├── PULL_REQUEST_TEMPLATE │ └── pull_request_template.md └── workflows │ ├── deploy-docs.yml │ └── php-standards.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING ├── LICENSE ├── README.md ├── asset-loader.php ├── composer.json ├── composer.lock ├── docs ├── 01-index.md ├── 02-usage.md ├── 03-local-development.md ├── 404.html ├── Gemfile ├── Gemfile.lock └── _config.yml ├── inc ├── admin.php ├── manifest.php ├── namespace.php └── paths.php ├── phpcs.xml ├── phpunit.xml └── tests ├── bootstrap.php ├── class-asset-loader-test-case.php ├── class-mock-asset-registry.php ├── fixtures ├── devserver-asset-manifest.json └── prod-asset-manifest.json └── inc ├── class-test-admin-scripts.php ├── class-test-asset-loader.php ├── class-test-manifest.php └── class-test-paths.php /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | [*.{js,ts,jsx,tsx,scss,php,xml}] 12 | # Avoid trailing whitespace 13 | trim_trailing_whitespace = true 14 | # Set default charset for JS files 15 | charset = utf-8 16 | # Tab indentation 17 | indent_style = tab 18 | 19 | # Use 4-space indentation on composer.json 20 | [{composer.json}] 21 | indent_style = space 22 | indent_size = 4 23 | 24 | # Matches the exact files either package.json or .travis.yml 25 | # and overrides them to use 2-space indentation 26 | [{package.json,.travis.yml}] 27 | indent_style = space 28 | indent_size = 2 29 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/pull_request_template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Default PR Template 3 | title: '' 4 | labels: '' 5 | assignees: '' 6 | --- 7 | 8 | ## Describe the PR 9 | 18 | 19 | 20 | 21 | --- 22 | 23 | ## For Altis Team Use 24 | 25 | ### Completion Checklist 26 | Does this PR meet our definition of done? See [the Play Book Definition of Done](https://playbook.hmn.md/play/product/definition-of-done-2/) 27 | 28 | - [ ] Has the acceptance criteria been met? 29 | - [ ] Is the documentation updated (including README)? 30 | - [ ] Do any code/documentation changes meet project standards? 31 | - [ ] Are automatic tests in place to verify the fix or new functionality? 32 | - [ ] OR, are manual tests documented (at least on the ticket/PR)? 33 | - [ ] Are any Playbook/Handbook pages updated? 34 | - [ ] Has a new module release (patch/minor) been created/scheduled? 35 | - [ ] Have the appropriate `backport` labels been added to the PR? 36 | - [ ] Is there a roll-out (and roll-back) plan, if required? 37 | -------------------------------------------------------------------------------- /.github/workflows/deploy-docs.yml: -------------------------------------------------------------------------------- 1 | name: Deploy documentation to GitHub Pages 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | workflow_dispatch: 7 | 8 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 9 | permissions: 10 | contents: read 11 | pages: write 12 | id-token: write 13 | 14 | # Allow one concurrent deployment 15 | concurrency: 16 | group: "pages" 17 | cancel-in-progress: true 18 | 19 | jobs: 20 | # Build job 21 | build: 22 | runs-on: ubuntu-latest 23 | steps: 24 | - name: Checkout 25 | uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 26 | - name: Setup Ruby 27 | uses: ruby/setup-ruby@8575951200e472d5f2d95c625da0c7bec8217c42 # v1.161.0 28 | with: 29 | working-directory: ./docs 30 | ruby-version: '3.1' 31 | bundler-cache: true 32 | - name: Setup Pages 33 | id: pages 34 | uses: actions/configure-pages@1f0c5cde4bc74cd7e1254d0cb4de8d49e9068c7d # v4.0.0 35 | - name: Bundle install 36 | run: | 37 | cd docs 38 | bundle install --jobs 4 --retry 3 39 | - name: Build with Jekyll 40 | run: | 41 | cd docs 42 | bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}" 43 | env: 44 | JEKYLL_ENV: production 45 | - name: Upload artifact 46 | uses: actions/upload-pages-artifact@a753861a5debcf57bf8b404356158c8e1e33150c # v2.0.0 47 | with: 48 | path: ./docs/_site 49 | 50 | 51 | # Deployment job 52 | deploy: 53 | environment: 54 | name: github-pages 55 | url: ${{ steps.deployment.outputs.page_url }} 56 | runs-on: ubuntu-latest 57 | needs: build 58 | steps: 59 | - name: Deploy to GitHub Pages 60 | id: deployment 61 | uses: actions/deploy-pages@13b55b33dd8996121833dbc1db458c793a334630 # v3.0.1 62 | -------------------------------------------------------------------------------- /.github/workflows/php-standards.yml: -------------------------------------------------------------------------------- 1 | name: PHP Standards 2 | on: 3 | push: 4 | branches: 5 | - 'main' 6 | paths: 7 | - '**.php' 8 | - '**.json' 9 | pull_request: 10 | branches: 11 | - '**' 12 | paths: 13 | - '**.php' 14 | - '**.json' 15 | 16 | jobs: 17 | build: 18 | name: PHP Coding Standards 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Checkout repository 22 | uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 23 | 24 | - name: Install PHP 25 | uses: shivammathur/setup-php@e6f75134d35752277f093989e72e140eaa222f35 # v2.28.0 26 | with: 27 | php-version: '8.1' 28 | coverage: none 29 | 30 | - name: Echo PHP & Composer versions 31 | run: | 32 | php --version 33 | php -m 34 | composer --version 35 | 36 | - name: Get Composer Cache Directory 37 | id: composer-cache-dir 38 | run: | 39 | echo "::set-output name=dir::$(composer config cache-files-dir)" 40 | 41 | - name: Cache PHP Dependencies 42 | id: composer-cache 43 | uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 44 | with: 45 | path: ${{ steps.composer-cache-dir.outputs.dir }} 46 | key: ${{ runner.os }}-composer-7.2-${{ hashFiles('composer.lock') }} 47 | 48 | - name: Install PHP Dependencies 49 | run: | 50 | composer install --prefer-dist --no-progress --no-suggest --no-interaction 51 | 52 | - name: PHPCS cache 53 | uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 54 | with: 55 | path: tests/cache 56 | key: ${{ runner.os }}-phpcs-7.2-${{ hashFiles('plugin.php') }} 57 | 58 | - name: Check the code for style issues 59 | run: | 60 | composer lint 61 | 62 | - name: Run the tests 63 | run: | 64 | composer test 65 | env: 66 | MYSQL_DATABASE: wordpress 67 | WP_TESTS_DB_PASS: root 68 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | docs/_site/ 3 | .bundle 4 | .phpunit.result.cache 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Travis CI Configuration File 2 | dist: jammy 3 | 4 | branches: 5 | only: 6 | - main 7 | 8 | # Tell Travis CI we're using PHP 9 | language: php 10 | 11 | php: 12 | - 8.1 13 | - 8.2 14 | 15 | install: composer install 16 | 17 | script: 18 | - composer lint 19 | - composer test 20 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## v0.7.1 4 | 5 | - Fix invalid `sprintf` string token in manifest loading error message so that a missing manifest does not cause a fatal. 6 | 7 | ## v0.7.0 8 | 9 | - Fix bug where passing an empty manifest to `enqueue_asset` or `register_asset` would fail with a TypeError. 10 | - **Breaking**: Minimum supported PHP version is now PHP 8.1. 11 | - Plugin should continue to work on 7.4 but there is no support guarantee, and the plugin's development tooling now requires at least 8.0. 12 | 13 | ## v0.6.4 14 | 15 | - Point to specific commit for 3rd-party Github action 16 | - Secure href attribute in 404 page to prevent XSS vulnerabilities 17 | 18 | ## v0.6.3 19 | 20 | - Adds support for the composer installers v2 package 21 | 22 | ## v0.6.2 23 | 24 | - Ensure that a version string is always set on an asset, even when the built file has a hash string in the file name. This ensures proper cache invalidation in sites using asset concatenation. 25 | 26 | ## v0.6.1 27 | 28 | - Fix get_file_uri() when using symlinks 29 | 30 | ## v0.6.0 31 | 32 | - **Breaking**: Remove deprecated `autoregister`, `autoenqueue`, and `register_assets` methods. 33 | - Add filter `asset_loader_manifest_contents` to allow filtering of loaded asset manifest contents. 34 | 35 | ## v0.5.0 36 | 37 | - Support enqueuing scripts in the page `
` by passing `'in-footer' => false` in options array. 38 | - Introduce `get_active_manifest()` function to return the first available manifest in a list. 39 | 40 | ## v0.4.1 41 | 42 | - Fix bug where admin namespace was not loaded. 43 | 44 | ## v0.4.0 45 | 46 | - **Breaking**: Remove undocumented `Asset_Loader\is_development` method. 47 | - **Breaking**: Remove undocumented `Asset_Loader\enqueue_assets` method. 48 | - **New**: Introduce new `Asset_Loader\register_asset()` and `Asset_Loader\enqueue_asset()` public API. 49 | - Assets should now be registered individually. 50 | - If a bundle exports both a CSS and JS file, both files should be registered or enqueued individually. 51 | - **Deprecate** `Asset_Loader\autoenqueue()` method. Use the new, singular `enqueue_asset()` instead. 52 | - **Deprecate** `Asset_Loader\autoregister()` method. Use the new, singular `register_asset()` instead. 53 | - **Deprecate** `Asset_Loader\register_assets()` method. Use the new, singular `register_asset()` instead. 54 | - Refactor how SSL warning notice behavior gets triggered during asset registration. 55 | - Change how version strings are determined when registering assets 56 | - If asset is detected to be using a uniquely hashed filename, no version string is used. 57 | - If an asset manifest is in use, assets are versioned based on a content hash of that manifest. 58 | - If no other version information can be determined and the loader is running within[Altis](https://altis-dxp.com), the Altis revision constant is used to version registered assets. 59 | 60 | ## v0.3.4 61 | 62 | - Added `composer/installers` as a dependency to permit custom installation paths when installing this package. 63 | 64 | ## v0.3.3 65 | 66 | - Display admin notification about accepting Webpack's SSL certificate if `https://localhost` scripts encounter errors when loading. 67 | - Derive script & style version string from file hash, not `filemtime`. 68 | 69 | ## v0.3.2 70 | 71 | - Do not require plugin files if plugin is already active elsewhere in the project. 72 | 73 | ## v0.3.1 74 | 75 | - Transfer plugin to `humanmade` GitHub organization 76 | 77 | ## v0.3.0 78 | 79 | - Fix bug when loading plugin assets outside of `wp-content/plugins` 80 | - Permit installation with `composer`. 81 | 82 | ## v0.2.0 83 | 84 | - Initial release: introduce `autoregister()` and `autoenqueue()` public API. 85 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | For complete documentation of this plugin, including the [contributing process](https://humanmade.github.io/asset-loader/contributing), visit the [docs site](https://humanmade.github.io/asset-loader/). 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This program is free software; you can redistribute it and/or modify 2 | it under the terms of the GNU General Public License as published by 3 | the Free Software Foundation; either version 2 of the License, or 4 | (at your option) any later version. 5 | 6 | This program is distributed in the hope that it will be useful, 7 | but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 | GNU General Public License for more details. 10 | 11 | You should have received a copy of the GNU General Public License 12 | along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 14 | 15 | 16 | =================================== 17 | 18 | 19 | GNU GENERAL PUBLIC LICENSE 20 | Version 2, June 1991 21 | 22 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 23 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 24 | Everyone is permitted to copy and distribute verbatim copies 25 | of this license document, but changing it is not allowed. 26 | 27 | Preamble 28 | 29 | The licenses for most software are designed to take away your 30 | freedom to share and change it. By contrast, the GNU General Public 31 | License is intended to guarantee your freedom to share and change free 32 | software--to make sure the software is free for all its users. This 33 | General Public License applies to most of the Free Software 34 | Foundation's software and to any other program whose authors commit to 35 | using it. (Some other Free Software Foundation software is covered by 36 | the GNU Lesser General Public License instead.) You can apply it to 37 | your programs, too. 38 | 39 | When we speak of free software, we are referring to freedom, not 40 | price. Our General Public Licenses are designed to make sure that you 41 | have the freedom to distribute copies of free software (and charge for 42 | this service if you wish), that you receive source code or can get it 43 | if you want it, that you can change the software or use pieces of it 44 | in new free programs; and that you know you can do these things. 45 | 46 | To protect your rights, we need to make restrictions that forbid 47 | anyone to deny you these rights or to ask you to surrender the rights. 48 | These restrictions translate to certain responsibilities for you if you 49 | distribute copies of the software, or if you modify it. 50 | 51 | For example, if you distribute copies of such a program, whether 52 | gratis or for a fee, you must give the recipients all the rights that 53 | you have. You must make sure that they, too, receive or can get the 54 | source code. And you must show them these terms so they know their 55 | rights. 56 | 57 | We protect your rights with two steps: (1) copyright the software, and 58 | (2) offer you this license which gives you legal permission to copy, 59 | distribute and/or modify the software. 60 | 61 | Also, for each author's protection and ours, we want to make certain 62 | that everyone understands that there is no warranty for this free 63 | software. If the software is modified by someone else and passed on, we 64 | want its recipients to know that what they have is not the original, so 65 | that any problems introduced by others will not reflect on the original 66 | authors' reputations. 67 | 68 | Finally, any free program is threatened constantly by software 69 | patents. We wish to avoid the danger that redistributors of a free 70 | program will individually obtain patent licenses, in effect making the 71 | program proprietary. To prevent this, we have made it clear that any 72 | patent must be licensed for everyone's free use or not licensed at all. 73 | 74 | The precise terms and conditions for copying, distribution and 75 | modification follow. 76 | 77 | GNU GENERAL PUBLIC LICENSE 78 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 79 | 80 | 0. This License applies to any program or other work which contains 81 | a notice placed by the copyright holder saying it may be distributed 82 | under the terms of this General Public License. The "Program", below, 83 | refers to any such program or work, and a "work based on the Program" 84 | means either the Program or any derivative work under copyright law: 85 | that is to say, a work containing the Program or a portion of it, 86 | either verbatim or with modifications and/or translated into another 87 | language. (Hereinafter, translation is included without limitation in 88 | the term "modification".) Each licensee is addressed as "you". 89 | 90 | Activities other than copying, distribution and modification are not 91 | covered by this License; they are outside its scope. The act of 92 | running the Program is not restricted, and the output from the Program 93 | is covered only if its contents constitute a work based on the 94 | Program (independent of having been made by running the Program). 95 | Whether that is true depends on what the Program does. 96 | 97 | 1. You may copy and distribute verbatim copies of the Program's 98 | source code as you receive it, in any medium, provided that you 99 | conspicuously and appropriately publish on each copy an appropriate 100 | copyright notice and disclaimer of warranty; keep intact all the 101 | notices that refer to this License and to the absence of any warranty; 102 | and give any other recipients of the Program a copy of this License 103 | along with the Program. 104 | 105 | You may charge a fee for the physical act of transferring a copy, and 106 | you may at your option offer warranty protection in exchange for a fee. 107 | 108 | 2. You may modify your copy or copies of the Program or any portion 109 | of it, thus forming a work based on the Program, and copy and 110 | distribute such modifications or work under the terms of Section 1 111 | above, provided that you also meet all of these conditions: 112 | 113 | a) You must cause the modified files to carry prominent notices 114 | stating that you changed the files and the date of any change. 115 | 116 | b) You must cause any work that you distribute or publish, that in 117 | whole or in part contains or is derived from the Program or any 118 | part thereof, to be licensed as a whole at no charge to all third 119 | parties under the terms of this License. 120 | 121 | c) If the modified program normally reads commands interactively 122 | when run, you must cause it, when started running for such 123 | interactive use in the most ordinary way, to print or display an 124 | announcement including an appropriate copyright notice and a 125 | notice that there is no warranty (or else, saying that you provide 126 | a warranty) and that users may redistribute the program under 127 | these conditions, and telling the user how to view a copy of this 128 | License. (Exception: if the Program itself is interactive but 129 | does not normally print such an announcement, your work based on 130 | the Program is not required to print an announcement.) 131 | 132 | These requirements apply to the modified work as a whole. If 133 | identifiable sections of that work are not derived from the Program, 134 | and can be reasonably considered independent and separate works in 135 | themselves, then this License, and its terms, do not apply to those 136 | sections when you distribute them as separate works. But when you 137 | distribute the same sections as part of a whole which is a work based 138 | on the Program, the distribution of the whole must be on the terms of 139 | this License, whose permissions for other licensees extend to the 140 | entire whole, and thus to each and every part regardless of who wrote it. 141 | 142 | Thus, it is not the intent of this section to claim rights or contest 143 | your rights to work written entirely by you; rather, the intent is to 144 | exercise the right to control the distribution of derivative or 145 | collective works based on the Program. 146 | 147 | In addition, mere aggregation of another work not based on the Program 148 | with the Program (or with a work based on the Program) on a volume of 149 | a storage or distribution medium does not bring the other work under 150 | the scope of this License. 151 | 152 | 3. You may copy and distribute the Program (or a work based on it, 153 | under Section 2) in object code or executable form under the terms of 154 | Sections 1 and 2 above provided that you also do one of the following: 155 | 156 | a) Accompany it with the complete corresponding machine-readable 157 | source code, which must be distributed under the terms of Sections 158 | 1 and 2 above on a medium customarily used for software interchange; or, 159 | 160 | b) Accompany it with a written offer, valid for at least three 161 | years, to give any third party, for a charge no more than your 162 | cost of physically performing source distribution, a complete 163 | machine-readable copy of the corresponding source code, to be 164 | distributed under the terms of Sections 1 and 2 above on a medium 165 | customarily used for software interchange; or, 166 | 167 | c) Accompany it with the information you received as to the offer 168 | to distribute corresponding source code. (This alternative is 169 | allowed only for noncommercial distribution and only if you 170 | received the program in object code or executable form with such 171 | an offer, in accord with Subsection b above.) 172 | 173 | The source code for a work means the preferred form of the work for 174 | making modifications to it. For an executable work, complete source 175 | code means all the source code for all modules it contains, plus any 176 | associated interface definition files, plus the scripts used to 177 | control compilation and installation of the executable. However, as a 178 | special exception, the source code distributed need not include 179 | anything that is normally distributed (in either source or binary 180 | form) with the major components (compiler, kernel, and so on) of the 181 | operating system on which the executable runs, unless that component 182 | itself accompanies the executable. 183 | 184 | If distribution of executable or object code is made by offering 185 | access to copy from a designated place, then offering equivalent 186 | access to copy the source code from the same place counts as 187 | distribution of the source code, even though third parties are not 188 | compelled to copy the source along with the object code. 189 | 190 | 4. You may not copy, modify, sublicense, or distribute the Program 191 | except as expressly provided under this License. Any attempt 192 | otherwise to copy, modify, sublicense or distribute the Program is 193 | void, and will automatically terminate your rights under this License. 194 | However, parties who have received copies, or rights, from you under 195 | this License will not have their licenses terminated so long as such 196 | parties remain in full compliance. 197 | 198 | 5. You are not required to accept this License, since you have not 199 | signed it. However, nothing else grants you permission to modify or 200 | distribute the Program or its derivative works. These actions are 201 | prohibited by law if you do not accept this License. Therefore, by 202 | modifying or distributing the Program (or any work based on the 203 | Program), you indicate your acceptance of this License to do so, and 204 | all its terms and conditions for copying, distributing or modifying 205 | the Program or works based on it. 206 | 207 | 6. Each time you redistribute the Program (or any work based on the 208 | Program), the recipient automatically receives a license from the 209 | original licensor to copy, distribute or modify the Program subject to 210 | these terms and conditions. You may not impose any further 211 | restrictions on the recipients' exercise of the rights granted herein. 212 | You are not responsible for enforcing compliance by third parties to 213 | this License. 214 | 215 | 7. If, as a consequence of a court judgment or allegation of patent 216 | infringement or for any other reason (not limited to patent issues), 217 | conditions are imposed on you (whether by court order, agreement or 218 | otherwise) that contradict the conditions of this License, they do not 219 | excuse you from the conditions of this License. If you cannot 220 | distribute so as to satisfy simultaneously your obligations under this 221 | License and any other pertinent obligations, then as a consequence you 222 | may not distribute the Program at all. For example, if a patent 223 | license would not permit royalty-free redistribution of the Program by 224 | all those who receive copies directly or indirectly through you, then 225 | the only way you could satisfy both it and this License would be to 226 | refrain entirely from distribution of the Program. 227 | 228 | If any portion of this section is held invalid or unenforceable under 229 | any particular circumstance, the balance of the section is intended to 230 | apply and the section as a whole is intended to apply in other 231 | circumstances. 232 | 233 | It is not the purpose of this section to induce you to infringe any 234 | patents or other property right claims or to contest validity of any 235 | such claims; this section has the sole purpose of protecting the 236 | integrity of the free software distribution system, which is 237 | implemented by public license practices. Many people have made 238 | generous contributions to the wide range of software distributed 239 | through that system in reliance on consistent application of that 240 | system; it is up to the author/donor to decide if he or she is willing 241 | to distribute software through any other system and a licensee cannot 242 | impose that choice. 243 | 244 | This section is intended to make thoroughly clear what is believed to 245 | be a consequence of the rest of this License. 246 | 247 | 8. If the distribution and/or use of the Program is restricted in 248 | certain countries either by patents or by copyrighted interfaces, the 249 | original copyright holder who places the Program under this License 250 | may add an explicit geographical distribution limitation excluding 251 | those countries, so that distribution is permitted only in or among 252 | countries not thus excluded. In such case, this License incorporates 253 | the limitation as if written in the body of this License. 254 | 255 | 9. The Free Software Foundation may publish revised and/or new versions 256 | of the General Public License from time to time. Such new versions will 257 | be similar in spirit to the present version, but may differ in detail to 258 | address new problems or concerns. 259 | 260 | Each version is given a distinguishing version number. If the Program 261 | specifies a version number of this License which applies to it and "any 262 | later version", you have the option of following the terms and conditions 263 | either of that version or of any later version published by the Free 264 | Software Foundation. If the Program does not specify a version number of 265 | this License, you may choose any version ever published by the Free Software 266 | Foundation. 267 | 268 | 10. If you wish to incorporate parts of the Program into other free 269 | programs whose distribution conditions are different, write to the author 270 | to ask for permission. For software which is copyrighted by the Free 271 | Software Foundation, write to the Free Software Foundation; we sometimes 272 | make exceptions for this. Our decision will be guided by the two goals 273 | of preserving the free status of all derivatives of our free software and 274 | of promoting the sharing and reuse of software generally. 275 | 276 | NO WARRANTY 277 | 278 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 279 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 280 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 281 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 282 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 283 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 284 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 285 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 286 | REPAIR OR CORRECTION. 287 | 288 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 289 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 290 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 291 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 292 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 293 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 294 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 295 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 296 | POSSIBILITY OF SUCH DAMAGES. 297 | 298 | END OF TERMS AND CONDITIONS 299 | 300 | How to Apply These Terms to Your New Programs 301 | 302 | If you develop a new program, and you want it to be of the greatest 303 | possible use to the public, the best way to achieve this is to make it 304 | free software which everyone can redistribute and change under these terms. 305 | 306 | To do so, attach the following notices to the program. It is safest 307 | to attach them to the start of each source file to most effectively 308 | convey the exclusion of warranty; and each file should have at least 309 | the "copyright" line and a pointer to where the full notice is found. 310 | 311 |The page you requested could not be found. Try using the navigation {% if site.search_enabled != false %}or search {% endif %}to find what you're looking for or go to this site's home page.
12 | -------------------------------------------------------------------------------- /docs/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "jekyll", "~> 4.3.2" 4 | gem "webrick", "~> 1.8" 5 | gem "just-the-hm-docs", github: "humanmade/just-the-hm-docs" 6 | -------------------------------------------------------------------------------- /docs/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GIT 2 | remote: https://github.com/humanmade/just-the-hm-docs.git 3 | revision: 07115607c8d441811d1fc49de89c2591d4029785 4 | specs: 5 | just-the-hm-docs (1.0.2.rc1) 6 | jekyll (>= 4.3.2) 7 | jekyll-seo-tag (>= 2.0) 8 | rake (>= 12.3.1) 9 | 10 | GEM 11 | remote: https://rubygems.org/ 12 | specs: 13 | addressable (2.8.1) 14 | public_suffix (>= 2.0.2, < 6.0) 15 | colorator (1.1.0) 16 | concurrent-ruby (1.2.0) 17 | em-websocket (0.5.3) 18 | eventmachine (>= 0.12.9) 19 | http_parser.rb (~> 0) 20 | eventmachine (1.2.7) 21 | ffi (1.15.5) 22 | forwardable-extended (2.6.0) 23 | google-protobuf (3.25.5-x86_64-darwin) 24 | google-protobuf (3.25.5-x86_64-linux) 25 | http_parser.rb (0.8.0) 26 | i18n (1.12.0) 27 | concurrent-ruby (~> 1.0) 28 | jekyll (4.3.2) 29 | addressable (~> 2.4) 30 | colorator (~> 1.0) 31 | em-websocket (~> 0.5) 32 | i18n (~> 1.0) 33 | jekyll-sass-converter (>= 2.0, < 4.0) 34 | jekyll-watch (~> 2.0) 35 | kramdown (~> 2.3, >= 2.3.1) 36 | kramdown-parser-gfm (~> 1.0) 37 | liquid (~> 4.0) 38 | mercenary (>= 0.3.6, < 0.5) 39 | pathutil (~> 0.9) 40 | rouge (>= 3.0, < 5.0) 41 | safe_yaml (~> 1.0) 42 | terminal-table (>= 1.8, < 4.0) 43 | webrick (~> 1.7) 44 | jekyll-sass-converter (3.0.0) 45 | sass-embedded (~> 1.54) 46 | jekyll-seo-tag (2.8.0) 47 | jekyll (>= 3.8, < 5.0) 48 | jekyll-watch (2.2.1) 49 | listen (~> 3.0) 50 | kramdown (2.4.0) 51 | rexml 52 | kramdown-parser-gfm (1.1.0) 53 | kramdown (~> 2.0) 54 | liquid (4.0.4) 55 | listen (3.8.0) 56 | rb-fsevent (~> 0.10, >= 0.10.3) 57 | rb-inotify (~> 0.9, >= 0.9.10) 58 | mercenary (0.4.0) 59 | pathutil (0.16.2) 60 | forwardable-extended (~> 2.6) 61 | public_suffix (5.0.1) 62 | rake (13.0.6) 63 | rb-fsevent (0.11.2) 64 | rb-inotify (0.10.1) 65 | ffi (~> 1.0) 66 | rexml (3.3.9) 67 | rouge (4.0.1) 68 | safe_yaml (1.0.5) 69 | sass-embedded (1.58.0-x86_64-darwin) 70 | google-protobuf (~> 3.21) 71 | sass-embedded (1.58.0-x86_64-linux-gnu) 72 | google-protobuf (~> 3.21) 73 | terminal-table (3.0.2) 74 | unicode-display_width (>= 1.1.1, < 3) 75 | unicode-display_width (2.4.2) 76 | webrick (1.8.2) 77 | 78 | PLATFORMS 79 | x86_64-darwin-21 80 | x86_64-linux 81 | 82 | DEPENDENCIES 83 | jekyll (~> 4.3.2) 84 | just-the-hm-docs! 85 | webrick (~> 1.8) 86 | 87 | BUNDLED WITH 88 | 2.3.5 89 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | # Welcome to Jekyll! 2 | # 3 | # This config file is meant for settings that affect your whole site, values 4 | # which you are expected to set up once and rarely edit after that. If you find 5 | # yourself editing these this file very often, consider using Jekyll's data files 6 | # feature for the data you need to update frequently. 7 | # 8 | # For technical reasons, this file is *NOT* reloaded automatically when you use 9 | # 'jekyll serve'. If you change this file, please restart the server process. 10 | 11 | # Site settings 12 | # These are used to personalize your new site. If you look in the HTML files, 13 | # you will see them accessed via {{ site.title }}, {{ site.github_repo }}, and so on. 14 | # You can create any custom variable you would like, and they will be accessible 15 | # in the templates via {{ site.myvariable }}. 16 | title: Asset Loader 17 | tagline: Helper framework for WordPress development using hot module replacement and hot reloading. 18 | description: Asset Loader provides convenience methods for conditionally loading assets from a hot-replacing dev server in local development 19 | author: Human Made 20 | baseurl: '/asset-loader' # the subpath of your site, e.g. /blog 21 | url: 'https://humanmade.github.io' # the base hostname & protocol for your site, e.g. http://example.com 22 | 23 | # Theme settings 24 | theme: just-the-hm-docs 25 | 26 | aux_links: 27 | "Asset Loader on GitHub": 28 | - https://github.com/humanmade/asset-loader 29 | 30 | nav_external_links: 31 | - title: GitHub source 32 | url: https://github.com/humanmade/asset-loader 33 | - title: Issues 34 | url: https://github.com/humanmade/asset-loader/issues 35 | -------------------------------------------------------------------------------- /inc/admin.php: -------------------------------------------------------------------------------- 1 | 82 | 150 | registered[ $handle ]->deps ) ) { 42 | if ( ! empty( $existing_scripts->registered[ $handle ]->deps ) ) { 43 | // We have dependencies, but so does the already-registered script. 44 | // This is a weird state, and may be an error in future releases. 45 | return null; 46 | } 47 | 48 | $existing_scripts->registered[ $handle ]->deps = $dependencies; 49 | 50 | // Updating those dependencies is assumed to be all that needs to be done. 51 | return $handle; 52 | } 53 | } 54 | wp_register_script( $handle, $asset_uri, $dependencies, $version, $in_footer ); 55 | 56 | return $handle; 57 | } 58 | 59 | /** 60 | * Attempt to register a particular script bundle from a manifest. 61 | * 62 | * @param ?string $manifest_path File system path for an asset manifest JSON file. 63 | * @param string $target_asset Asset to retrieve within the specified manifest. 64 | * @param array $options { 65 | * @type string $handle Handle to use when enqueuing the asset. Optional. 66 | * @type array $dependencies Script or Style dependencies. Optional. 67 | * } 68 | * @return array Array detailing which script and/or style handles got registered. 69 | */ 70 | function register_asset( ?string $manifest_path, string $target_asset, array $options = [] ): array { 71 | if ( empty( $manifest_path ) ) { 72 | trigger_error( sprintf( 'No manifest specified when loading %s', esc_attr( $target_asset ) ), E_USER_NOTICE ); 73 | return []; 74 | } 75 | 76 | $defaults = [ 77 | 'dependencies' => [], 78 | 'in-footer' => true, 79 | ]; 80 | $options = wp_parse_args( $options, $defaults ); 81 | 82 | // Track whether we are falling back to a JS file because a CSS asset could not be found. 83 | $is_js_style_fallback = false; 84 | 85 | $manifest_folder = trailingslashit( dirname( $manifest_path ) ); 86 | 87 | $asset_uri = Manifest\get_manifest_resource( $manifest_path, $target_asset ); 88 | 89 | // If we fail to match a .css asset, try again with .js in case there is a 90 | // JS wrapper for that asset available (e.g. when using DevServer). 91 | if ( empty( $asset_uri ) && is_css( $target_asset ) ) { 92 | $asset_uri = Manifest\get_manifest_resource( $manifest_path, preg_replace( '/\.css$/', '.js', $target_asset ) ); 93 | if ( ! empty( $asset_uri ) ) { 94 | $is_js_style_fallback = true; 95 | } 96 | } 97 | 98 | // If asset is not present in manifest, attempt to resolve the $target_asset 99 | // relative to the folder containing the manifest file. 100 | if ( empty( $asset_uri ) ) { 101 | // TODO: Consider checking is_readable( $manifest_folder . $target_asset ) 102 | // and warning (in console or error log) if it is not present on disk. 103 | $asset_uri = $target_asset; 104 | } 105 | 106 | // Reconcile static asset build paths relative to the manifest's directory. 107 | if ( strpos( $asset_uri, '//' ) === false ) { 108 | $asset_uri = Paths\get_file_uri( $manifest_folder . $asset_uri ); 109 | } 110 | 111 | // Use the requested asset as the asset handle if no handle was provided. 112 | $asset_handle = $options['handle'] ?? $target_asset; 113 | $asset_version = Manifest\get_version( $asset_uri, $manifest_path ); 114 | 115 | // Track registered handles so we can enqueue the correct assets later. 116 | $handles = []; 117 | 118 | if ( is_css( $asset_uri ) ) { 119 | // Register a normal CSS bundle. 120 | wp_register_style( 121 | $asset_handle, 122 | $asset_uri, 123 | $options['dependencies'], 124 | $asset_version 125 | ); 126 | $handles['style'] = $asset_handle; 127 | } elseif ( $is_js_style_fallback ) { 128 | // We're registering a JS bundle when we originally asked for a CSS bundle. 129 | // Register the JS, but if any dependencies were passed in, also register a 130 | // dummy style bundle so that those style dependencies still get loaded. 131 | Admin\maybe_setup_ssl_cert_error_handling( $asset_uri ); 132 | _register_or_update_script( 133 | $asset_handle, 134 | $asset_uri, 135 | [], 136 | $asset_version, 137 | true 138 | ); 139 | $handles['script'] = $asset_handle; 140 | if ( ! empty( $options['dependencies'] ) ) { 141 | wp_register_style( 142 | $asset_handle, 143 | false, 144 | $options['dependencies'], 145 | $asset_version 146 | ); 147 | $handles['style'] = $asset_handle; 148 | } 149 | } else { 150 | // Register a normal JS bundle. 151 | Admin\maybe_setup_ssl_cert_error_handling( $asset_uri ); 152 | _register_or_update_script( 153 | $asset_handle, 154 | $asset_uri, 155 | $options['dependencies'], 156 | $asset_version, 157 | $options['in-footer'] 158 | ); 159 | $handles['script'] = $asset_handle; 160 | } 161 | 162 | return $handles; 163 | } 164 | 165 | /** 166 | * Register and immediately enqueue a particular asset within a manifest. 167 | * 168 | * @param ?string $manifest_path File system path for an asset manifest JSON file. 169 | * @param string $target_asset Asset to retrieve within the specified manifest. 170 | * @param array $options { 171 | * @type string $handle Handle to use when enqueuing the asset. Optional. 172 | * @type array $dependencies Script or Style dependencies. Optional. 173 | * } 174 | */ 175 | function enqueue_asset( ?string $manifest_path, string $target_asset, array $options = [] ): void { 176 | $registered_handles = register_asset( $manifest_path, $target_asset, $options ); 177 | 178 | if ( isset( $registered_handles['script'] ) ) { 179 | wp_enqueue_script( $registered_handles['script'] ); 180 | } 181 | if ( isset( $registered_handles['style'] ) ) { 182 | wp_enqueue_style( $registered_handles['style'] ); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /inc/paths.php: -------------------------------------------------------------------------------- 1 | 2 |