├── .gitattributes ├── .gitignore ├── .nvmrc ├── .vscode └── launch.json ├── .vscodeignore ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── images ├── drupal_logo.png ├── element_prefix.gif ├── element_tabstop_options.gif ├── element_type.gif ├── form_element_snippet.gif ├── preprocess.gif ├── render_element_snippet.gif ├── services_deprecated.gif ├── services_with_snippets.gif ├── services_without_snippets.gif └── views_data.gif ├── index.js ├── package-lock.json ├── package.json ├── snippets ├── elements.json ├── hooks.json └── services.json └── src ├── formatElements.js ├── formatHooks.js ├── formatServices.js ├── getApiFiles.js ├── getCoreVersion.js ├── getElementFiles.js ├── getRawElements.js ├── getRawHooks.js ├── getServices.js └── sortSnippets.js /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set default behavior to automatically normalize line endings. 2 | * text=auto 3 | 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | tmp 3 | *.vsix 4 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v18 2 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that launches the extension inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "args": [ 13 | "--extensionDevelopmentPath=${workspaceFolder}" 14 | ] 15 | }, 16 | { 17 | "type": "node", 18 | "name": "Debug JavaScript file", 19 | "request": "launch", 20 | "program": "${workspaceFolder}/index.js", 21 | "runtimeExecutable": "node", 22 | "console": "integratedTerminal", 23 | "internalConsoleOptions": "neverOpen", 24 | "sourceMaps": true, 25 | "skipFiles": [ 26 | "/**" 27 | ] 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | node_modules/ 4 | tmp/ 5 | package-lock.json 6 | .gitignore 7 | .nvmrc 8 | scrape.js 9 | vsc-extension-quickstart.md -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to the "drupal-smart-snippets" extension will be documented in this file. 4 | 5 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. 6 | 7 | ## [Unreleased] 8 | 9 | ## [0.0.1] 10 | - Initial release 11 | - Added hooks 12 | - Does not work due to faulty manifest 13 | 14 | ## [0.0.2] 15 | - No changes 16 | 17 | ## [0.0.3] 18 | - Fix snippets file & manifest to create base functionality 19 | 20 | ## [0.1.0] 21 | - Update ReadMe & Manifest for marketplace changes 22 | - Update hooks snippets to adhere to Drupal code standards 23 | 24 | ## [0.1.1] 25 | - Change readme image paths to absolute urls 26 | 27 | ## [0.2.0] 28 | ### Added 29 | - Miniumum core versions in hook description 30 | - Deprecation warnings in hook description 31 | - Inline deprecation comments in hook body 32 | - Documentation & images for above additions 33 | 34 | ### Changed 35 | - Altered all hooks to account for additions 36 | - Reordered hook snippets based on scraper script 37 | 38 | ## [0.3.0] 39 | ### Changed 40 | - scraper pulls from 9.0.7 (prev 9.0.6) 41 | - scraper now checks hookName variable for secondary hooks ("HOOK", "ENTITY_TYPE", 42 | etc) instead of the function usage to prevent matching on arguments with multiple 43 | capitalized letters (e.g. "OEmbed", "ViewsUI") 44 | - scraper has better regex matching for secondary hooks, leading to... 45 | - hook_update_N now has second tab-stop for "N" 46 | - hook_plugin_filter_TYPE__CONSUMER_alter differentiates between second tab-stop 47 | "TYPE" and third tab-stop "CONSUMER" 48 | 49 | ## [0.3.1] 50 | ### Changed 51 | - hook docblocks now include parenthesis after hook name 52 | (`implements hook_preprocess().` vs `implements hook_preprocess.`) 53 | - hook descriptions now include hookname and deprecation warning at the very 54 | beginning, hopefully making it easier to know which hook snippet you're about to 55 | use and if it's been deprecated 56 | 57 | ## [0.4.0] 58 | ### Changed 59 | - Updated scraper to load snippets from 9.1.0, 8.9.11. No changes to hooks 60 | at this time. 61 | 62 | ## [0.5.0] 63 | ### Added 64 | - Added new snippets 65 | - hook_entity_form_mode_alter 66 | - hook_block_alter 67 | - hook_field_widget_single_element_form_alter 68 | - hook_field_widget_single_element_WIDGET_TYPE_form_alter 69 | - hook_field_widget_complete_form_alter 70 | - hook_field_widget_complete_WIDGET_TYPE_form_alter 71 | ### Changed 72 | - Snippets load from 9.2.0 & 8.9.16 73 | 74 | ## [1.0.0] 75 | ### Added 76 | - Added 9.3.0 hooks 77 | - hook_ckeditor5_plugin_info_alter 78 | - hook_ckeditor4to5upgrade_plugin_info_alter 79 | ### Changed 80 | - Updated D9 source (9.2.0 t0 9.3.0) 81 | ### Removed 82 | - Removed support for Drupal 8 (EOL) 83 | - Removed D8-deprecated hooks 84 | - hook_path_insert 85 | - hook_path_update 86 | - hook_path_delete 87 | - hook_rest_type_uri_alter 88 | - hook_rest_relation_uri_alter 89 | - hook_simpletest_alter 90 | - hook_test_group_started 91 | - hook_test_group_finished 92 | - hook_test_finished 93 | 94 | ## [1.0.1] 95 | ### Changed 96 | - Updated README to reflect changes in 1.0.0 97 | 98 | ## [1.0.2] 99 | ### Added 100 | - Add MIT license 101 | 102 | ## [1.1.0] 103 | ### Changed 104 | - Update scraper from 9.3.0 to 9.4.0 105 | 106 | ## [1.2.0] 107 | ### Added 108 | - Added Form/Render Element snippets 109 | - Added tags for marketplace visibility 110 | 111 | ### Changed 112 | - Update node version 113 | - Refactor script into smaller files 114 | - Hooks snippets now sorted alphabetically 115 | 116 | ## [1.2.1] 117 | ### Changed 118 | - Fixed broken '#required' boolean values 119 | 120 | ## [1.2.2] 121 | - No changes, error in deployment process 122 | 123 | ## [1.3.0] 124 | ### Added 125 | - Added Services snippets 126 | 127 | ### Changed 128 | - Changelog up to date 129 | 130 | ## [1.4.0] 131 | ### Changed 132 | - Updated core source versions to 10.1.0 and 9.5.9 133 | 134 | ## [2.0.0] 135 | ### Changed 136 | - Deprecated ajax element ([change record](https://www.drupal.org/node/3068104)) 137 | ### Removed 138 | - Removed support for Drupal 9 ([psa-2023-11-01](https://www.drupal.org/psa-2023-11-01)) 139 | - Removed deprecated hooks 140 | - hook_aggregator_fetcher_info_alter ([change record](https://www.drupal.org/node/3304999)) 141 | - hook_aggregator_parser_info_alter ([change record](https://www.drupal.org/node/3304999)) 142 | - hook_aggregator_processor_info_alter ([change record](https://www.drupal.org/node/3304999)) 143 | - hook_ckeditor_css_alter ([change record](https://www.drupal.org/node/3304481)) 144 | - hook_ckeditor_plugin_info_alter ([change record](https://www.drupal.org/node/3304481)) 145 | - hook_field_widget_form_alter ([change record](https://www.drupal.org/node/3180429)) 146 | - hook_field_widget_multivalue_form_alter ([change record](https://www.drupal.org/node/3180429)) 147 | - hook_field_widget_multivalue_WIDGET_TYPE_form_alter ([change record](https://www.drupal.org/node/3180429)) 148 | - hook_field_widget_WIDGET_TYPE_form_alter ([change record](https://www.drupal.org/node/3180429)) 149 | - hook_hal_relation_uri_alter ([change record](https://www.drupal.org/node/3266403)) 150 | - hook_hal_type_uri_alter ([change record](https://www.drupal.org/node/3266403)) 151 | - hook_quickedit_editor_alter ([change record](https://www.drupal.org/node/3252839)) 152 | - hook_quickedit_render_field ([change record](https://www.drupal.org/node/3252839)) 153 | - hook_rdf_namespaces ([change record](https://www.drupal.org/node/3304899)) 154 | - Removed deprecated services 155 | - access_check.entity_bundles ([change record](https://www.drupal.org/node/3155569)) 156 | - app.root ([change record](https://www.drupal.org/node/3080612)) 157 | - config.storage.staging ([change record](https://www.drupal.org/node/2574957)) 158 | - feed.bridge.reader ([change record](https://www.drupal.org/node/3258656)) 159 | - feed.reader.atomentry ([change record](https://www.drupal.org/node/2979042)) 160 | - feed.reader.atomfeed ([change record](https://www.drupal.org/node/2979042)) 161 | - feed.reader.contententry ([change record](https://www.drupal.org/node/2979042)) 162 | - feed.reader.dublincoreentry ([change record](https://www.drupal.org/node/2979042)) 163 | - feed.reader.dublincorefeed ([change record](https://www.drupal.org/node/2979042)) 164 | - feed.reader.podcastentry ([change record](https://www.drupal.org/node/2979042)) 165 | - feed.reader.podcastfeed ([change record](https://www.drupal.org/node/2979042)) 166 | - feed.reader.slashentry ([change record](https://www.drupal.org/node/2979042)) 167 | - feed.reader.threadentry ([change record](https://www.drupal.org/node/2979042)) 168 | - feed.reader.wellformedwebentry ([change record](https://www.drupal.org/node/2979042)) 169 | - feed.writer.atomrendererfeed ([change record](https://www.drupal.org/node/2979042)) 170 | - feed.writer.contentrendererentry ([change record](https://www.drupal.org/node/2979042)) 171 | - feed.writer.dublincorerendererentry ([change record](https://www.drupal.org/node/2979042)) 172 | - feed.writer.dublincorerendererfeed ([change record](https://www.drupal.org/node/2979042)) 173 | - feed.writer.itunesentry ([change record](https://www.drupal.org/node/2979042)) 174 | - feed.writer.itunesfeed ([change record](https://www.drupal.org/node/2979042)) 175 | - feed.writer.itunesrendererentry ([change record](https://www.drupal.org/node/2979042)) 176 | - feed.writer.itunesrendererfeed ([change record](https://www.drupal.org/node/2979042)) 177 | - feed.writer.slashrendererentry ([change record](https://www.drupal.org/node/2979042)) 178 | - feed.writer.threadingrendererentry ([change record](https://www.drupal.org/node/2979042)) 179 | - feed.writer.wellformedwebrendererentry ([change record](https://www.drupal.org/node/2979042)) 180 | - site.path ([change record](https://www.drupal.org/node/3080612)) 181 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2022 Andrew Blum 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Visual Studio Code Smart Drupal Snippets 2 | 3 | This extension adds rich language support for the 4 | [Drupal Hooks API](https://api.drupal.org/api/drupal/core%21core.api.php/group/hooks) and [Drupal Form and render elements](https://api.drupal.org/api/drupal/elements) 5 | to VS Code. This extension is intended as a successor to 6 | [Drupal 8 Snippets](https://marketplace.visualstudio.com/items?itemName=dssiqueira.drupal-8-snippets). 7 | 8 | # Usage & Features 9 | Type part of a snippet, press enter and/Or tab, and the snippet unfolds. 10 | 11 | ## Built from Drupal Core 12 | Hooks gathered by scraping the codebase of the latest minor versions of Drupal 9. This includes those that are marked as deprecated. 13 | 14 | ## Smart hook replacement 15 | Snippets will automatically replace the leading `hook` with the current file's name. 16 | 17 | ![Gif showing usage of hook_views_data snippet](https://raw.githubusercontent.com/andy-blum/smart-drupal-snippets/main/images/views_data.gif) 18 | 19 | ## Smart element replacement 20 | Snippets will automatically render the element array base on RenderElement or FormElement. Start by typing `@RenderElement`, `@FormElement`, `@Element` or the `[type_name]` itself. 21 | 22 | FormElement will have `#title`, `#title_display`, `#description` and `#required` properties by default. Additional properties listed on docblock is generated automatically. 23 | 24 | ### @FormElement 25 | ![Gif showing usage of form element snippet](images/form_element_snippet.gif) 26 | 27 | ### @RenderElement 28 | ![Gif showing usage of render element snippet](images/render_element_snippet.gif) 29 | 30 | ### @Element 31 | ![Gif showing usage of form/render element snippet](images/element_prefix.gif) 32 | 33 | ### Typing [type_name] 34 | ![Gif showing usage of element type snippet](images/element_type.gif) 35 | 36 | ## Smart service snippet 37 | While services with global methods allow IDEs to suggest methods and properties, those retrieved using the \Drupal::service() method do not. Service snippets provide a easy access to all core services in a datatyped variable allowing intellisense suggestions. 38 | 39 | ### Services without datatyping 40 | ![Gif showing intellisense results to un-typed variables](images/services_without_snippets.gif) 41 | 42 | ### Services with datatyping 43 | ![Gif showing intellisense results to typed variables](images/services_with_snippets.gif) 44 | 45 | ### Deprecated services 46 | ![Gif showing deprecation of a service](images/services_deprecated.gif) 47 | 48 | ## Tab Stops 49 | Snippets are formatted to have tab stops on values that need replaced like `HOOK`, 50 | `ENTITY_TYPE`, `BASE_FORM_ID`, etc. 51 | 52 | ### Hook Replacement 53 | ![Gif showing usage of hook_preprocess_HOOK snippet](https://raw.githubusercontent.com/andy-blum/smart-drupal-snippets/main/images/preprocess.gif ) 54 | 55 | ### Element Replacement 56 | FormElement have `#title`, `#title_display` ([providing default options](https://www.drupal.org/docs/drupal-apis/form-api/form-render-elements)), `#description`, `#required` (*TRUE* or *FALSE*) and final ending option of comma `','` or semi-colon `';'` as deafult tab stops. 57 | ![Gif showing usage of element snippet tab stops](images/element_tabstop_options.gif) 58 | 59 | ### Services 60 | Services snippets provide a snake-cased, tab-stopped variable matching the service's name. On snippet insertion, the variable can be overwritten easily. 61 | 62 | # Installation 63 | 64 | 1. Open VS Code 65 | 2. From the command palette `Ctrl-Shift-P` (Windows, Linux) or `Cmd-Shift-P` (OSX) 66 | 3. Select Install Extension 67 | 4. Search by `Drupal Smart Snippets` 68 | 5. Click install 69 | 6. Reload Visual Studio Code 70 | 71 | # Contributions 72 | This project is maintained on 73 | [Github](https://github.com/andy-blum/smart-drupal-snippets). 74 | 75 | Your bugs, feature requests, and pull requests are welcome. 76 | -------------------------------------------------------------------------------- /images/drupal_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-blum/drupal-smart-snippets/32c825d22344b59f4c3d3693d5e3cc77462db0e5/images/drupal_logo.png -------------------------------------------------------------------------------- /images/element_prefix.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-blum/drupal-smart-snippets/32c825d22344b59f4c3d3693d5e3cc77462db0e5/images/element_prefix.gif -------------------------------------------------------------------------------- /images/element_tabstop_options.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-blum/drupal-smart-snippets/32c825d22344b59f4c3d3693d5e3cc77462db0e5/images/element_tabstop_options.gif -------------------------------------------------------------------------------- /images/element_type.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-blum/drupal-smart-snippets/32c825d22344b59f4c3d3693d5e3cc77462db0e5/images/element_type.gif -------------------------------------------------------------------------------- /images/form_element_snippet.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-blum/drupal-smart-snippets/32c825d22344b59f4c3d3693d5e3cc77462db0e5/images/form_element_snippet.gif -------------------------------------------------------------------------------- /images/preprocess.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-blum/drupal-smart-snippets/32c825d22344b59f4c3d3693d5e3cc77462db0e5/images/preprocess.gif -------------------------------------------------------------------------------- /images/render_element_snippet.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-blum/drupal-smart-snippets/32c825d22344b59f4c3d3693d5e3cc77462db0e5/images/render_element_snippet.gif -------------------------------------------------------------------------------- /images/services_deprecated.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-blum/drupal-smart-snippets/32c825d22344b59f4c3d3693d5e3cc77462db0e5/images/services_deprecated.gif -------------------------------------------------------------------------------- /images/services_with_snippets.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-blum/drupal-smart-snippets/32c825d22344b59f4c3d3693d5e3cc77462db0e5/images/services_with_snippets.gif -------------------------------------------------------------------------------- /images/services_without_snippets.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-blum/drupal-smart-snippets/32c825d22344b59f4c3d3693d5e3cc77462db0e5/images/services_without_snippets.gif -------------------------------------------------------------------------------- /images/views_data.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-blum/drupal-smart-snippets/32c825d22344b59f4c3d3693d5e3cc77462db0e5/images/views_data.gif -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import { rm, readdir, writeFile } from "node:fs/promises"; 2 | import he from "he"; 3 | import { getApiFiles } from "./src/getApiFiles.js"; 4 | import { getCoreVersion } from "./src/getCoreVersion.js"; 5 | import { getRawHooks } from "./src/getRawHooks.js"; 6 | import { formatHooks } from "./src/formatHooks.js"; 7 | import { getElementFiles } from "./src/getElementFiles.js"; 8 | import { getRawElements } from "./src/getRawElements.js"; 9 | import { formatElements } from "./src/formatElements.js"; 10 | import { getServices } from "./src/getServices.js"; 11 | import { sortSnippets } from "./src/sortSnippets.js"; 12 | import { formatServices } from "./src/formatServices.js"; 13 | 14 | const SUPPORTED_VERSIONS = [ 15 | '11.0.0', 16 | '10.3.0', 17 | ]; 18 | 19 | // 1. Set up final snippets files. 20 | let allHooks = {}; 21 | let allElements = {}; 22 | let allServices = {}; 23 | 24 | // 2. Clean tmp directory. 25 | try { 26 | const contents = await readdir('./tmp'); 27 | for (const item of contents) { 28 | await rm(`./tmp/${item}`, { 29 | force: true, 30 | recursive: true 31 | }); 32 | } 33 | } catch (error) {} 34 | 35 | for (const version of SUPPORTED_VERSIONS) { 36 | console.log(`Drupal ${version}`); 37 | 38 | // 3. Download & un-archive tarball. 39 | await getCoreVersion(version); 40 | console.log(` - Downloaded`); 41 | 42 | /******************************* 43 | * Hooks 44 | *******************************/ 45 | 46 | // 4. Find all *.api.php files. 47 | const apiFiles = await getApiFiles(version); 48 | console.log(` - Found ${apiFiles.length} files matching *.api.php`); 49 | 50 | // 5. Find all hook docblocks. 51 | const rawHooks = await getRawHooks(apiFiles); 52 | console.log(` - Found ${rawHooks.length} defined hooks`); 53 | 54 | // 6. Format hook object for VS Code usage. 55 | const formattedHooks = formatHooks(rawHooks); 56 | 57 | // 7. Add hook snippet to full set. 58 | formattedHooks.forEach(hook => { 59 | allHooks[hook.prefix] = hook; 60 | }); 61 | 62 | /******************************* 63 | * Elements 64 | *******************************/ 65 | 66 | // 8. Find all .php files for element. 67 | const elementFiles = await getElementFiles(version); 68 | console.log(` - Found ${elementFiles.length} files under core/lib/Drupal/Core/Render/Element`); 69 | 70 | // 9. Find all Element docblocks. 71 | const rawElements = await getRawElements(elementFiles); 72 | console.log(` - Found ${rawElements.length} defined Elements`); 73 | 74 | // 10. Format element objects for VS Code usage. 75 | const formattedElements = formatElements(rawElements); 76 | 77 | // 11. Add element snippet to full set. 78 | formattedElements.forEach(element => { 79 | allElements[element.prefix[1]] = element; 80 | }); 81 | 82 | /******************************* 83 | * Services 84 | *******************************/ 85 | 86 | // 12. Get all services. 87 | const rawServices = await getServices(version); 88 | console.log(` - Found ${rawServices.length} defined Services`); 89 | 90 | // 13. Format services snippets. 91 | const formattedServices = await formatServices(rawServices, version); 92 | 93 | // 14. Add snippets to set. 94 | formattedServices.forEach(([name, snippet]) => { 95 | allServices[`${name}`] = snippet; 96 | }); 97 | } 98 | 99 | // 15. Sort snippets alphabetically. 100 | allHooks = sortSnippets(allHooks); 101 | allElements = sortSnippets(allElements); 102 | allServices = sortSnippets(allServices); 103 | 104 | // 16. Write final files. 105 | await writeFile( 106 | './snippets/hooks.json', 107 | he.unescape(JSON.stringify(allHooks, null, 2)), 108 | ); 109 | 110 | await writeFile( 111 | './snippets/elements.json', 112 | he.unescape(JSON.stringify(allElements, null, 2)), 113 | ); 114 | 115 | await writeFile( 116 | './snippets/services.json', 117 | he.unescape(JSON.stringify(allServices, null, 2)), 118 | ) 119 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "drupal-smart-snippets", 3 | "version": "2.2.1", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "drupal-smart-snippets", 9 | "version": "2.2.1", 10 | "dependencies": { 11 | "del": "^6.1.1", 12 | "download": "^8.0.0", 13 | "find": "^0.3.0", 14 | "he": "^1.2.0", 15 | "php-parser": "^3.1.4", 16 | "tar": "^6.1.11", 17 | "write-json-file": "^4.3.0", 18 | "yaml": "^2.2.1" 19 | }, 20 | "engines": { 21 | "vscode": "^1.49.0" 22 | } 23 | }, 24 | "node_modules/@nodelib/fs.scandir": { 25 | "version": "2.1.5", 26 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 27 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 28 | "dependencies": { 29 | "@nodelib/fs.stat": "2.0.5", 30 | "run-parallel": "^1.1.9" 31 | }, 32 | "engines": { 33 | "node": ">= 8" 34 | } 35 | }, 36 | "node_modules/@nodelib/fs.stat": { 37 | "version": "2.0.5", 38 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 39 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 40 | "engines": { 41 | "node": ">= 8" 42 | } 43 | }, 44 | "node_modules/@nodelib/fs.walk": { 45 | "version": "1.2.8", 46 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 47 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 48 | "dependencies": { 49 | "@nodelib/fs.scandir": "2.1.5", 50 | "fastq": "^1.6.0" 51 | }, 52 | "engines": { 53 | "node": ">= 8" 54 | } 55 | }, 56 | "node_modules/@sindresorhus/is": { 57 | "version": "0.7.0", 58 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", 59 | "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", 60 | "engines": { 61 | "node": ">=4" 62 | } 63 | }, 64 | "node_modules/aggregate-error": { 65 | "version": "3.1.0", 66 | "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", 67 | "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", 68 | "dependencies": { 69 | "clean-stack": "^2.0.0", 70 | "indent-string": "^4.0.0" 71 | }, 72 | "engines": { 73 | "node": ">=8" 74 | } 75 | }, 76 | "node_modules/archive-type": { 77 | "version": "4.0.0", 78 | "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", 79 | "integrity": "sha512-zV4Ky0v1F8dBrdYElwTvQhweQ0P7Kwc1aluqJsYtOBP01jXcWCyW2IEfI1YiqsG+Iy7ZR+o5LF1N+PGECBxHWA==", 80 | "dependencies": { 81 | "file-type": "^4.2.0" 82 | }, 83 | "engines": { 84 | "node": ">=4" 85 | } 86 | }, 87 | "node_modules/archive-type/node_modules/file-type": { 88 | "version": "4.4.0", 89 | "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", 90 | "integrity": "sha512-f2UbFQEk7LXgWpi5ntcO86OeA/cC80fuDDDaX/fZ2ZGel+AF7leRQqBBW1eJNiiQkrZlAoM6P+VYP5P6bOlDEQ==", 91 | "engines": { 92 | "node": ">=4" 93 | } 94 | }, 95 | "node_modules/array-union": { 96 | "version": "2.1.0", 97 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", 98 | "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", 99 | "engines": { 100 | "node": ">=8" 101 | } 102 | }, 103 | "node_modules/balanced-match": { 104 | "version": "1.0.2", 105 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 106 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 107 | }, 108 | "node_modules/base64-js": { 109 | "version": "1.5.1", 110 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 111 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 112 | "funding": [ 113 | { 114 | "type": "github", 115 | "url": "https://github.com/sponsors/feross" 116 | }, 117 | { 118 | "type": "patreon", 119 | "url": "https://www.patreon.com/feross" 120 | }, 121 | { 122 | "type": "consulting", 123 | "url": "https://feross.org/support" 124 | } 125 | ] 126 | }, 127 | "node_modules/bl": { 128 | "version": "1.2.3", 129 | "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", 130 | "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", 131 | "dependencies": { 132 | "readable-stream": "^2.3.5", 133 | "safe-buffer": "^5.1.1" 134 | } 135 | }, 136 | "node_modules/brace-expansion": { 137 | "version": "1.1.11", 138 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 139 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 140 | "dependencies": { 141 | "balanced-match": "^1.0.0", 142 | "concat-map": "0.0.1" 143 | } 144 | }, 145 | "node_modules/braces": { 146 | "version": "3.0.3", 147 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 148 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 149 | "dependencies": { 150 | "fill-range": "^7.1.1" 151 | }, 152 | "engines": { 153 | "node": ">=8" 154 | } 155 | }, 156 | "node_modules/buffer": { 157 | "version": "5.7.1", 158 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", 159 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", 160 | "funding": [ 161 | { 162 | "type": "github", 163 | "url": "https://github.com/sponsors/feross" 164 | }, 165 | { 166 | "type": "patreon", 167 | "url": "https://www.patreon.com/feross" 168 | }, 169 | { 170 | "type": "consulting", 171 | "url": "https://feross.org/support" 172 | } 173 | ], 174 | "dependencies": { 175 | "base64-js": "^1.3.1", 176 | "ieee754": "^1.1.13" 177 | } 178 | }, 179 | "node_modules/buffer-alloc": { 180 | "version": "1.2.0", 181 | "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", 182 | "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", 183 | "dependencies": { 184 | "buffer-alloc-unsafe": "^1.1.0", 185 | "buffer-fill": "^1.0.0" 186 | } 187 | }, 188 | "node_modules/buffer-alloc-unsafe": { 189 | "version": "1.1.0", 190 | "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", 191 | "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" 192 | }, 193 | "node_modules/buffer-crc32": { 194 | "version": "0.2.13", 195 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 196 | "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", 197 | "engines": { 198 | "node": "*" 199 | } 200 | }, 201 | "node_modules/buffer-fill": { 202 | "version": "1.0.0", 203 | "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", 204 | "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==" 205 | }, 206 | "node_modules/cacheable-request": { 207 | "version": "2.1.4", 208 | "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", 209 | "integrity": "sha512-vag0O2LKZ/najSoUwDbVlnlCFvhBE/7mGTY2B5FgCBDcRD+oVV1HYTOwM6JZfMg/hIcM6IwnTZ1uQQL5/X3xIQ==", 210 | "dependencies": { 211 | "clone-response": "1.0.2", 212 | "get-stream": "3.0.0", 213 | "http-cache-semantics": "3.8.1", 214 | "keyv": "3.0.0", 215 | "lowercase-keys": "1.0.0", 216 | "normalize-url": "2.0.1", 217 | "responselike": "1.0.2" 218 | } 219 | }, 220 | "node_modules/cacheable-request/node_modules/get-stream": { 221 | "version": "3.0.0", 222 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", 223 | "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", 224 | "engines": { 225 | "node": ">=4" 226 | } 227 | }, 228 | "node_modules/cacheable-request/node_modules/lowercase-keys": { 229 | "version": "1.0.0", 230 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", 231 | "integrity": "sha512-RPlX0+PHuvxVDZ7xX+EBVAp4RsVxP/TdDSN2mJYdiq1Lc4Hz7EUSjUI7RZrKKlmrIzVhf6Jo2stj7++gVarS0A==", 232 | "engines": { 233 | "node": ">=0.10.0" 234 | } 235 | }, 236 | "node_modules/chownr": { 237 | "version": "2.0.0", 238 | "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", 239 | "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", 240 | "engines": { 241 | "node": ">=10" 242 | } 243 | }, 244 | "node_modules/clean-stack": { 245 | "version": "2.2.0", 246 | "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", 247 | "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", 248 | "engines": { 249 | "node": ">=6" 250 | } 251 | }, 252 | "node_modules/clone-response": { 253 | "version": "1.0.2", 254 | "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", 255 | "integrity": "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==", 256 | "dependencies": { 257 | "mimic-response": "^1.0.0" 258 | } 259 | }, 260 | "node_modules/commander": { 261 | "version": "2.20.3", 262 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 263 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" 264 | }, 265 | "node_modules/concat-map": { 266 | "version": "0.0.1", 267 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 268 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" 269 | }, 270 | "node_modules/content-disposition": { 271 | "version": "0.5.4", 272 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 273 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 274 | "dependencies": { 275 | "safe-buffer": "5.2.1" 276 | }, 277 | "engines": { 278 | "node": ">= 0.6" 279 | } 280 | }, 281 | "node_modules/core-util-is": { 282 | "version": "1.0.3", 283 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", 284 | "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" 285 | }, 286 | "node_modules/decode-uri-component": { 287 | "version": "0.2.2", 288 | "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", 289 | "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", 290 | "engines": { 291 | "node": ">=0.10" 292 | } 293 | }, 294 | "node_modules/decompress": { 295 | "version": "4.2.1", 296 | "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", 297 | "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", 298 | "dependencies": { 299 | "decompress-tar": "^4.0.0", 300 | "decompress-tarbz2": "^4.0.0", 301 | "decompress-targz": "^4.0.0", 302 | "decompress-unzip": "^4.0.1", 303 | "graceful-fs": "^4.1.10", 304 | "make-dir": "^1.0.0", 305 | "pify": "^2.3.0", 306 | "strip-dirs": "^2.0.0" 307 | }, 308 | "engines": { 309 | "node": ">=4" 310 | } 311 | }, 312 | "node_modules/decompress-response": { 313 | "version": "3.3.0", 314 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", 315 | "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", 316 | "dependencies": { 317 | "mimic-response": "^1.0.0" 318 | }, 319 | "engines": { 320 | "node": ">=4" 321 | } 322 | }, 323 | "node_modules/decompress-tar": { 324 | "version": "4.1.1", 325 | "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", 326 | "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", 327 | "dependencies": { 328 | "file-type": "^5.2.0", 329 | "is-stream": "^1.1.0", 330 | "tar-stream": "^1.5.2" 331 | }, 332 | "engines": { 333 | "node": ">=4" 334 | } 335 | }, 336 | "node_modules/decompress-tar/node_modules/file-type": { 337 | "version": "5.2.0", 338 | "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", 339 | "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", 340 | "engines": { 341 | "node": ">=4" 342 | } 343 | }, 344 | "node_modules/decompress-tarbz2": { 345 | "version": "4.1.1", 346 | "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", 347 | "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", 348 | "dependencies": { 349 | "decompress-tar": "^4.1.0", 350 | "file-type": "^6.1.0", 351 | "is-stream": "^1.1.0", 352 | "seek-bzip": "^1.0.5", 353 | "unbzip2-stream": "^1.0.9" 354 | }, 355 | "engines": { 356 | "node": ">=4" 357 | } 358 | }, 359 | "node_modules/decompress-tarbz2/node_modules/file-type": { 360 | "version": "6.2.0", 361 | "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", 362 | "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", 363 | "engines": { 364 | "node": ">=4" 365 | } 366 | }, 367 | "node_modules/decompress-targz": { 368 | "version": "4.1.1", 369 | "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", 370 | "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", 371 | "dependencies": { 372 | "decompress-tar": "^4.1.1", 373 | "file-type": "^5.2.0", 374 | "is-stream": "^1.1.0" 375 | }, 376 | "engines": { 377 | "node": ">=4" 378 | } 379 | }, 380 | "node_modules/decompress-targz/node_modules/file-type": { 381 | "version": "5.2.0", 382 | "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", 383 | "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", 384 | "engines": { 385 | "node": ">=4" 386 | } 387 | }, 388 | "node_modules/decompress-unzip": { 389 | "version": "4.0.1", 390 | "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", 391 | "integrity": "sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==", 392 | "dependencies": { 393 | "file-type": "^3.8.0", 394 | "get-stream": "^2.2.0", 395 | "pify": "^2.3.0", 396 | "yauzl": "^2.4.2" 397 | }, 398 | "engines": { 399 | "node": ">=4" 400 | } 401 | }, 402 | "node_modules/decompress-unzip/node_modules/file-type": { 403 | "version": "3.9.0", 404 | "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", 405 | "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", 406 | "engines": { 407 | "node": ">=0.10.0" 408 | } 409 | }, 410 | "node_modules/decompress-unzip/node_modules/get-stream": { 411 | "version": "2.3.1", 412 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", 413 | "integrity": "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==", 414 | "dependencies": { 415 | "object-assign": "^4.0.1", 416 | "pinkie-promise": "^2.0.0" 417 | }, 418 | "engines": { 419 | "node": ">=0.10.0" 420 | } 421 | }, 422 | "node_modules/decompress-unzip/node_modules/pify": { 423 | "version": "2.3.0", 424 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 425 | "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", 426 | "engines": { 427 | "node": ">=0.10.0" 428 | } 429 | }, 430 | "node_modules/decompress/node_modules/make-dir": { 431 | "version": "1.3.0", 432 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", 433 | "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", 434 | "dependencies": { 435 | "pify": "^3.0.0" 436 | }, 437 | "engines": { 438 | "node": ">=4" 439 | } 440 | }, 441 | "node_modules/decompress/node_modules/make-dir/node_modules/pify": { 442 | "version": "3.0.0", 443 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 444 | "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", 445 | "engines": { 446 | "node": ">=4" 447 | } 448 | }, 449 | "node_modules/decompress/node_modules/pify": { 450 | "version": "2.3.0", 451 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 452 | "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", 453 | "engines": { 454 | "node": ">=0.10.0" 455 | } 456 | }, 457 | "node_modules/del": { 458 | "version": "6.1.1", 459 | "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", 460 | "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", 461 | "dependencies": { 462 | "globby": "^11.0.1", 463 | "graceful-fs": "^4.2.4", 464 | "is-glob": "^4.0.1", 465 | "is-path-cwd": "^2.2.0", 466 | "is-path-inside": "^3.0.2", 467 | "p-map": "^4.0.0", 468 | "rimraf": "^3.0.2", 469 | "slash": "^3.0.0" 470 | }, 471 | "engines": { 472 | "node": ">=10" 473 | }, 474 | "funding": { 475 | "url": "https://github.com/sponsors/sindresorhus" 476 | } 477 | }, 478 | "node_modules/detect-indent": { 479 | "version": "6.1.0", 480 | "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", 481 | "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", 482 | "engines": { 483 | "node": ">=8" 484 | } 485 | }, 486 | "node_modules/dir-glob": { 487 | "version": "3.0.1", 488 | "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", 489 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", 490 | "dependencies": { 491 | "path-type": "^4.0.0" 492 | }, 493 | "engines": { 494 | "node": ">=8" 495 | } 496 | }, 497 | "node_modules/download": { 498 | "version": "8.0.0", 499 | "resolved": "https://registry.npmjs.org/download/-/download-8.0.0.tgz", 500 | "integrity": "sha512-ASRY5QhDk7FK+XrQtQyvhpDKanLluEEQtWl/J7Lxuf/b+i8RYh997QeXvL85xitrmRKVlx9c7eTrcRdq2GS4eA==", 501 | "dependencies": { 502 | "archive-type": "^4.0.0", 503 | "content-disposition": "^0.5.2", 504 | "decompress": "^4.2.1", 505 | "ext-name": "^5.0.0", 506 | "file-type": "^11.1.0", 507 | "filenamify": "^3.0.0", 508 | "get-stream": "^4.1.0", 509 | "got": "^8.3.1", 510 | "make-dir": "^2.1.0", 511 | "p-event": "^2.1.0", 512 | "pify": "^4.0.1" 513 | }, 514 | "engines": { 515 | "node": ">=10" 516 | } 517 | }, 518 | "node_modules/duplexer3": { 519 | "version": "0.1.5", 520 | "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", 521 | "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==" 522 | }, 523 | "node_modules/end-of-stream": { 524 | "version": "1.4.4", 525 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 526 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 527 | "dependencies": { 528 | "once": "^1.4.0" 529 | } 530 | }, 531 | "node_modules/escape-string-regexp": { 532 | "version": "1.0.5", 533 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 534 | "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", 535 | "engines": { 536 | "node": ">=0.8.0" 537 | } 538 | }, 539 | "node_modules/ext-list": { 540 | "version": "2.2.2", 541 | "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", 542 | "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", 543 | "dependencies": { 544 | "mime-db": "^1.28.0" 545 | }, 546 | "engines": { 547 | "node": ">=0.10.0" 548 | } 549 | }, 550 | "node_modules/ext-name": { 551 | "version": "5.0.0", 552 | "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", 553 | "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", 554 | "dependencies": { 555 | "ext-list": "^2.0.0", 556 | "sort-keys-length": "^1.0.0" 557 | }, 558 | "engines": { 559 | "node": ">=4" 560 | } 561 | }, 562 | "node_modules/fast-glob": { 563 | "version": "3.3.2", 564 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", 565 | "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", 566 | "dependencies": { 567 | "@nodelib/fs.stat": "^2.0.2", 568 | "@nodelib/fs.walk": "^1.2.3", 569 | "glob-parent": "^5.1.2", 570 | "merge2": "^1.3.0", 571 | "micromatch": "^4.0.4" 572 | }, 573 | "engines": { 574 | "node": ">=8.6.0" 575 | } 576 | }, 577 | "node_modules/fastq": { 578 | "version": "1.17.1", 579 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", 580 | "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", 581 | "dependencies": { 582 | "reusify": "^1.0.4" 583 | } 584 | }, 585 | "node_modules/fd-slicer": { 586 | "version": "1.1.0", 587 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", 588 | "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", 589 | "dependencies": { 590 | "pend": "~1.2.0" 591 | } 592 | }, 593 | "node_modules/file-type": { 594 | "version": "11.1.0", 595 | "resolved": "https://registry.npmjs.org/file-type/-/file-type-11.1.0.tgz", 596 | "integrity": "sha512-rM0UO7Qm9K7TWTtA6AShI/t7H5BPjDeGVDaNyg9BjHAj3PysKy7+8C8D137R88jnR3rFJZQB/tFgydl5sN5m7g==", 597 | "engines": { 598 | "node": ">=6" 599 | } 600 | }, 601 | "node_modules/filename-reserved-regex": { 602 | "version": "2.0.0", 603 | "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", 604 | "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", 605 | "engines": { 606 | "node": ">=4" 607 | } 608 | }, 609 | "node_modules/filenamify": { 610 | "version": "3.0.0", 611 | "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-3.0.0.tgz", 612 | "integrity": "sha512-5EFZ//MsvJgXjBAFJ+Bh2YaCTRF/VP1YOmGrgt+KJ4SFRLjI87EIdwLLuT6wQX0I4F9W41xutobzczjsOKlI/g==", 613 | "dependencies": { 614 | "filename-reserved-regex": "^2.0.0", 615 | "strip-outer": "^1.0.0", 616 | "trim-repeated": "^1.0.0" 617 | }, 618 | "engines": { 619 | "node": ">=6" 620 | } 621 | }, 622 | "node_modules/fill-range": { 623 | "version": "7.1.1", 624 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 625 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 626 | "dependencies": { 627 | "to-regex-range": "^5.0.1" 628 | }, 629 | "engines": { 630 | "node": ">=8" 631 | } 632 | }, 633 | "node_modules/find": { 634 | "version": "0.3.0", 635 | "resolved": "https://registry.npmjs.org/find/-/find-0.3.0.tgz", 636 | "integrity": "sha512-iSd+O4OEYV/I36Zl8MdYJO0xD82wH528SaCieTVHhclgiYNe9y+yPKSwK+A7/WsmHL1EZ+pYUJBXWTL5qofksw==", 637 | "dependencies": { 638 | "traverse-chain": "~0.1.0" 639 | } 640 | }, 641 | "node_modules/from2": { 642 | "version": "2.3.0", 643 | "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", 644 | "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", 645 | "dependencies": { 646 | "inherits": "^2.0.1", 647 | "readable-stream": "^2.0.0" 648 | } 649 | }, 650 | "node_modules/fs-constants": { 651 | "version": "1.0.0", 652 | "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", 653 | "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" 654 | }, 655 | "node_modules/fs-minipass": { 656 | "version": "2.1.0", 657 | "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", 658 | "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", 659 | "dependencies": { 660 | "minipass": "^3.0.0" 661 | }, 662 | "engines": { 663 | "node": ">= 8" 664 | } 665 | }, 666 | "node_modules/fs-minipass/node_modules/minipass": { 667 | "version": "3.3.6", 668 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", 669 | "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", 670 | "dependencies": { 671 | "yallist": "^4.0.0" 672 | }, 673 | "engines": { 674 | "node": ">=8" 675 | } 676 | }, 677 | "node_modules/fs.realpath": { 678 | "version": "1.0.0", 679 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 680 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" 681 | }, 682 | "node_modules/get-stream": { 683 | "version": "4.1.0", 684 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", 685 | "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", 686 | "dependencies": { 687 | "pump": "^3.0.0" 688 | }, 689 | "engines": { 690 | "node": ">=6" 691 | } 692 | }, 693 | "node_modules/glob": { 694 | "version": "7.2.3", 695 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", 696 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 697 | "deprecated": "Glob versions prior to v9 are no longer supported", 698 | "dependencies": { 699 | "fs.realpath": "^1.0.0", 700 | "inflight": "^1.0.4", 701 | "inherits": "2", 702 | "minimatch": "^3.1.1", 703 | "once": "^1.3.0", 704 | "path-is-absolute": "^1.0.0" 705 | }, 706 | "engines": { 707 | "node": "*" 708 | }, 709 | "funding": { 710 | "url": "https://github.com/sponsors/isaacs" 711 | } 712 | }, 713 | "node_modules/glob-parent": { 714 | "version": "5.1.2", 715 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 716 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 717 | "dependencies": { 718 | "is-glob": "^4.0.1" 719 | }, 720 | "engines": { 721 | "node": ">= 6" 722 | } 723 | }, 724 | "node_modules/globby": { 725 | "version": "11.1.0", 726 | "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", 727 | "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", 728 | "dependencies": { 729 | "array-union": "^2.1.0", 730 | "dir-glob": "^3.0.1", 731 | "fast-glob": "^3.2.9", 732 | "ignore": "^5.2.0", 733 | "merge2": "^1.4.1", 734 | "slash": "^3.0.0" 735 | }, 736 | "engines": { 737 | "node": ">=10" 738 | }, 739 | "funding": { 740 | "url": "https://github.com/sponsors/sindresorhus" 741 | } 742 | }, 743 | "node_modules/got": { 744 | "version": "8.3.2", 745 | "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", 746 | "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", 747 | "dependencies": { 748 | "@sindresorhus/is": "^0.7.0", 749 | "cacheable-request": "^2.1.1", 750 | "decompress-response": "^3.3.0", 751 | "duplexer3": "^0.1.4", 752 | "get-stream": "^3.0.0", 753 | "into-stream": "^3.1.0", 754 | "is-retry-allowed": "^1.1.0", 755 | "isurl": "^1.0.0-alpha5", 756 | "lowercase-keys": "^1.0.0", 757 | "mimic-response": "^1.0.0", 758 | "p-cancelable": "^0.4.0", 759 | "p-timeout": "^2.0.1", 760 | "pify": "^3.0.0", 761 | "safe-buffer": "^5.1.1", 762 | "timed-out": "^4.0.1", 763 | "url-parse-lax": "^3.0.0", 764 | "url-to-options": "^1.0.1" 765 | }, 766 | "engines": { 767 | "node": ">=4" 768 | } 769 | }, 770 | "node_modules/got/node_modules/get-stream": { 771 | "version": "3.0.0", 772 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", 773 | "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", 774 | "engines": { 775 | "node": ">=4" 776 | } 777 | }, 778 | "node_modules/got/node_modules/pify": { 779 | "version": "3.0.0", 780 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 781 | "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", 782 | "engines": { 783 | "node": ">=4" 784 | } 785 | }, 786 | "node_modules/graceful-fs": { 787 | "version": "4.2.11", 788 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", 789 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" 790 | }, 791 | "node_modules/has-symbol-support-x": { 792 | "version": "1.4.2", 793 | "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", 794 | "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", 795 | "engines": { 796 | "node": "*" 797 | } 798 | }, 799 | "node_modules/has-to-string-tag-x": { 800 | "version": "1.4.1", 801 | "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", 802 | "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", 803 | "dependencies": { 804 | "has-symbol-support-x": "^1.4.1" 805 | }, 806 | "engines": { 807 | "node": "*" 808 | } 809 | }, 810 | "node_modules/he": { 811 | "version": "1.2.0", 812 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 813 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 814 | "bin": { 815 | "he": "bin/he" 816 | } 817 | }, 818 | "node_modules/http-cache-semantics": { 819 | "version": "3.8.1", 820 | "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", 821 | "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" 822 | }, 823 | "node_modules/ieee754": { 824 | "version": "1.2.1", 825 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 826 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", 827 | "funding": [ 828 | { 829 | "type": "github", 830 | "url": "https://github.com/sponsors/feross" 831 | }, 832 | { 833 | "type": "patreon", 834 | "url": "https://www.patreon.com/feross" 835 | }, 836 | { 837 | "type": "consulting", 838 | "url": "https://feross.org/support" 839 | } 840 | ] 841 | }, 842 | "node_modules/ignore": { 843 | "version": "5.3.2", 844 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", 845 | "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", 846 | "engines": { 847 | "node": ">= 4" 848 | } 849 | }, 850 | "node_modules/imurmurhash": { 851 | "version": "0.1.4", 852 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 853 | "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", 854 | "engines": { 855 | "node": ">=0.8.19" 856 | } 857 | }, 858 | "node_modules/indent-string": { 859 | "version": "4.0.0", 860 | "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", 861 | "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", 862 | "engines": { 863 | "node": ">=8" 864 | } 865 | }, 866 | "node_modules/inflight": { 867 | "version": "1.0.6", 868 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 869 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 870 | "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", 871 | "dependencies": { 872 | "once": "^1.3.0", 873 | "wrappy": "1" 874 | } 875 | }, 876 | "node_modules/inherits": { 877 | "version": "2.0.4", 878 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 879 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 880 | }, 881 | "node_modules/into-stream": { 882 | "version": "3.1.0", 883 | "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", 884 | "integrity": "sha512-TcdjPibTksa1NQximqep2r17ISRiNE9fwlfbg3F8ANdvP5/yrFTew86VcO//jk4QTaMlbjypPBq76HN2zaKfZQ==", 885 | "dependencies": { 886 | "from2": "^2.1.1", 887 | "p-is-promise": "^1.1.0" 888 | }, 889 | "engines": { 890 | "node": ">=4" 891 | } 892 | }, 893 | "node_modules/is-extglob": { 894 | "version": "2.1.1", 895 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 896 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 897 | "engines": { 898 | "node": ">=0.10.0" 899 | } 900 | }, 901 | "node_modules/is-glob": { 902 | "version": "4.0.3", 903 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 904 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 905 | "dependencies": { 906 | "is-extglob": "^2.1.1" 907 | }, 908 | "engines": { 909 | "node": ">=0.10.0" 910 | } 911 | }, 912 | "node_modules/is-natural-number": { 913 | "version": "4.0.1", 914 | "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", 915 | "integrity": "sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==" 916 | }, 917 | "node_modules/is-number": { 918 | "version": "7.0.0", 919 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 920 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 921 | "engines": { 922 | "node": ">=0.12.0" 923 | } 924 | }, 925 | "node_modules/is-object": { 926 | "version": "1.0.2", 927 | "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", 928 | "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", 929 | "funding": { 930 | "url": "https://github.com/sponsors/ljharb" 931 | } 932 | }, 933 | "node_modules/is-path-cwd": { 934 | "version": "2.2.0", 935 | "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", 936 | "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", 937 | "engines": { 938 | "node": ">=6" 939 | } 940 | }, 941 | "node_modules/is-path-inside": { 942 | "version": "3.0.3", 943 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", 944 | "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", 945 | "engines": { 946 | "node": ">=8" 947 | } 948 | }, 949 | "node_modules/is-plain-obj": { 950 | "version": "1.1.0", 951 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", 952 | "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", 953 | "engines": { 954 | "node": ">=0.10.0" 955 | } 956 | }, 957 | "node_modules/is-retry-allowed": { 958 | "version": "1.2.0", 959 | "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", 960 | "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", 961 | "engines": { 962 | "node": ">=0.10.0" 963 | } 964 | }, 965 | "node_modules/is-stream": { 966 | "version": "1.1.0", 967 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 968 | "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", 969 | "engines": { 970 | "node": ">=0.10.0" 971 | } 972 | }, 973 | "node_modules/is-typedarray": { 974 | "version": "1.0.0", 975 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 976 | "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" 977 | }, 978 | "node_modules/isarray": { 979 | "version": "1.0.0", 980 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 981 | "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" 982 | }, 983 | "node_modules/isurl": { 984 | "version": "1.0.0", 985 | "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", 986 | "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", 987 | "dependencies": { 988 | "has-to-string-tag-x": "^1.2.0", 989 | "is-object": "^1.0.1" 990 | }, 991 | "engines": { 992 | "node": ">= 4" 993 | } 994 | }, 995 | "node_modules/json-buffer": { 996 | "version": "3.0.0", 997 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", 998 | "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==" 999 | }, 1000 | "node_modules/keyv": { 1001 | "version": "3.0.0", 1002 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", 1003 | "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", 1004 | "dependencies": { 1005 | "json-buffer": "3.0.0" 1006 | } 1007 | }, 1008 | "node_modules/lowercase-keys": { 1009 | "version": "1.0.1", 1010 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", 1011 | "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", 1012 | "engines": { 1013 | "node": ">=0.10.0" 1014 | } 1015 | }, 1016 | "node_modules/make-dir": { 1017 | "version": "2.1.0", 1018 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", 1019 | "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", 1020 | "dependencies": { 1021 | "pify": "^4.0.1", 1022 | "semver": "^5.6.0" 1023 | }, 1024 | "engines": { 1025 | "node": ">=6" 1026 | } 1027 | }, 1028 | "node_modules/merge2": { 1029 | "version": "1.4.1", 1030 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 1031 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 1032 | "engines": { 1033 | "node": ">= 8" 1034 | } 1035 | }, 1036 | "node_modules/micromatch": { 1037 | "version": "4.0.8", 1038 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", 1039 | "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", 1040 | "dependencies": { 1041 | "braces": "^3.0.3", 1042 | "picomatch": "^2.3.1" 1043 | }, 1044 | "engines": { 1045 | "node": ">=8.6" 1046 | } 1047 | }, 1048 | "node_modules/mime-db": { 1049 | "version": "1.53.0", 1050 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", 1051 | "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", 1052 | "engines": { 1053 | "node": ">= 0.6" 1054 | } 1055 | }, 1056 | "node_modules/mimic-response": { 1057 | "version": "1.0.1", 1058 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", 1059 | "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", 1060 | "engines": { 1061 | "node": ">=4" 1062 | } 1063 | }, 1064 | "node_modules/minimatch": { 1065 | "version": "3.1.2", 1066 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1067 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1068 | "dependencies": { 1069 | "brace-expansion": "^1.1.7" 1070 | }, 1071 | "engines": { 1072 | "node": "*" 1073 | } 1074 | }, 1075 | "node_modules/minipass": { 1076 | "version": "5.0.0", 1077 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", 1078 | "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", 1079 | "engines": { 1080 | "node": ">=8" 1081 | } 1082 | }, 1083 | "node_modules/minizlib": { 1084 | "version": "2.1.2", 1085 | "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", 1086 | "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", 1087 | "dependencies": { 1088 | "minipass": "^3.0.0", 1089 | "yallist": "^4.0.0" 1090 | }, 1091 | "engines": { 1092 | "node": ">= 8" 1093 | } 1094 | }, 1095 | "node_modules/minizlib/node_modules/minipass": { 1096 | "version": "3.3.6", 1097 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", 1098 | "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", 1099 | "dependencies": { 1100 | "yallist": "^4.0.0" 1101 | }, 1102 | "engines": { 1103 | "node": ">=8" 1104 | } 1105 | }, 1106 | "node_modules/mkdirp": { 1107 | "version": "1.0.4", 1108 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", 1109 | "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", 1110 | "bin": { 1111 | "mkdirp": "bin/cmd.js" 1112 | }, 1113 | "engines": { 1114 | "node": ">=10" 1115 | } 1116 | }, 1117 | "node_modules/normalize-url": { 1118 | "version": "2.0.1", 1119 | "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", 1120 | "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", 1121 | "dependencies": { 1122 | "prepend-http": "^2.0.0", 1123 | "query-string": "^5.0.1", 1124 | "sort-keys": "^2.0.0" 1125 | }, 1126 | "engines": { 1127 | "node": ">=4" 1128 | } 1129 | }, 1130 | "node_modules/object-assign": { 1131 | "version": "4.1.1", 1132 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1133 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 1134 | "engines": { 1135 | "node": ">=0.10.0" 1136 | } 1137 | }, 1138 | "node_modules/once": { 1139 | "version": "1.4.0", 1140 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1141 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1142 | "dependencies": { 1143 | "wrappy": "1" 1144 | } 1145 | }, 1146 | "node_modules/p-cancelable": { 1147 | "version": "0.4.1", 1148 | "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", 1149 | "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", 1150 | "engines": { 1151 | "node": ">=4" 1152 | } 1153 | }, 1154 | "node_modules/p-event": { 1155 | "version": "2.3.1", 1156 | "resolved": "https://registry.npmjs.org/p-event/-/p-event-2.3.1.tgz", 1157 | "integrity": "sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==", 1158 | "dependencies": { 1159 | "p-timeout": "^2.0.1" 1160 | }, 1161 | "engines": { 1162 | "node": ">=6" 1163 | } 1164 | }, 1165 | "node_modules/p-finally": { 1166 | "version": "1.0.0", 1167 | "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", 1168 | "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", 1169 | "engines": { 1170 | "node": ">=4" 1171 | } 1172 | }, 1173 | "node_modules/p-is-promise": { 1174 | "version": "1.1.0", 1175 | "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", 1176 | "integrity": "sha512-zL7VE4JVS2IFSkR2GQKDSPEVxkoH43/p7oEnwpdCndKYJO0HVeRB7fA8TJwuLOTBREtK0ea8eHaxdwcpob5dmg==", 1177 | "engines": { 1178 | "node": ">=4" 1179 | } 1180 | }, 1181 | "node_modules/p-map": { 1182 | "version": "4.0.0", 1183 | "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", 1184 | "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", 1185 | "dependencies": { 1186 | "aggregate-error": "^3.0.0" 1187 | }, 1188 | "engines": { 1189 | "node": ">=10" 1190 | }, 1191 | "funding": { 1192 | "url": "https://github.com/sponsors/sindresorhus" 1193 | } 1194 | }, 1195 | "node_modules/p-timeout": { 1196 | "version": "2.0.1", 1197 | "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", 1198 | "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", 1199 | "dependencies": { 1200 | "p-finally": "^1.0.0" 1201 | }, 1202 | "engines": { 1203 | "node": ">=4" 1204 | } 1205 | }, 1206 | "node_modules/path-is-absolute": { 1207 | "version": "1.0.1", 1208 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1209 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 1210 | "engines": { 1211 | "node": ">=0.10.0" 1212 | } 1213 | }, 1214 | "node_modules/path-type": { 1215 | "version": "4.0.0", 1216 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", 1217 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", 1218 | "engines": { 1219 | "node": ">=8" 1220 | } 1221 | }, 1222 | "node_modules/pend": { 1223 | "version": "1.2.0", 1224 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 1225 | "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" 1226 | }, 1227 | "node_modules/php-parser": { 1228 | "version": "3.1.5", 1229 | "resolved": "https://registry.npmjs.org/php-parser/-/php-parser-3.1.5.tgz", 1230 | "integrity": "sha512-jEY2DcbgCm5aclzBdfW86GM6VEIWcSlhTBSHN1qhJguVePlYe28GhwS0yoeLYXpM2K8y6wzLwrbq814n2PHSoQ==" 1231 | }, 1232 | "node_modules/picomatch": { 1233 | "version": "2.3.1", 1234 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1235 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1236 | "engines": { 1237 | "node": ">=8.6" 1238 | }, 1239 | "funding": { 1240 | "url": "https://github.com/sponsors/jonschlinkert" 1241 | } 1242 | }, 1243 | "node_modules/pify": { 1244 | "version": "4.0.1", 1245 | "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", 1246 | "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", 1247 | "engines": { 1248 | "node": ">=6" 1249 | } 1250 | }, 1251 | "node_modules/pinkie": { 1252 | "version": "2.0.4", 1253 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", 1254 | "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", 1255 | "engines": { 1256 | "node": ">=0.10.0" 1257 | } 1258 | }, 1259 | "node_modules/pinkie-promise": { 1260 | "version": "2.0.1", 1261 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", 1262 | "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", 1263 | "dependencies": { 1264 | "pinkie": "^2.0.0" 1265 | }, 1266 | "engines": { 1267 | "node": ">=0.10.0" 1268 | } 1269 | }, 1270 | "node_modules/prepend-http": { 1271 | "version": "2.0.0", 1272 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", 1273 | "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", 1274 | "engines": { 1275 | "node": ">=4" 1276 | } 1277 | }, 1278 | "node_modules/process-nextick-args": { 1279 | "version": "2.0.1", 1280 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 1281 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 1282 | }, 1283 | "node_modules/pump": { 1284 | "version": "3.0.2", 1285 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", 1286 | "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", 1287 | "dependencies": { 1288 | "end-of-stream": "^1.1.0", 1289 | "once": "^1.3.1" 1290 | } 1291 | }, 1292 | "node_modules/query-string": { 1293 | "version": "5.1.1", 1294 | "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", 1295 | "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", 1296 | "dependencies": { 1297 | "decode-uri-component": "^0.2.0", 1298 | "object-assign": "^4.1.0", 1299 | "strict-uri-encode": "^1.0.0" 1300 | }, 1301 | "engines": { 1302 | "node": ">=0.10.0" 1303 | } 1304 | }, 1305 | "node_modules/queue-microtask": { 1306 | "version": "1.2.3", 1307 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 1308 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 1309 | "funding": [ 1310 | { 1311 | "type": "github", 1312 | "url": "https://github.com/sponsors/feross" 1313 | }, 1314 | { 1315 | "type": "patreon", 1316 | "url": "https://www.patreon.com/feross" 1317 | }, 1318 | { 1319 | "type": "consulting", 1320 | "url": "https://feross.org/support" 1321 | } 1322 | ] 1323 | }, 1324 | "node_modules/readable-stream": { 1325 | "version": "2.3.8", 1326 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", 1327 | "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", 1328 | "dependencies": { 1329 | "core-util-is": "~1.0.0", 1330 | "inherits": "~2.0.3", 1331 | "isarray": "~1.0.0", 1332 | "process-nextick-args": "~2.0.0", 1333 | "safe-buffer": "~5.1.1", 1334 | "string_decoder": "~1.1.1", 1335 | "util-deprecate": "~1.0.1" 1336 | } 1337 | }, 1338 | "node_modules/readable-stream/node_modules/safe-buffer": { 1339 | "version": "5.1.2", 1340 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1341 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1342 | }, 1343 | "node_modules/responselike": { 1344 | "version": "1.0.2", 1345 | "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", 1346 | "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", 1347 | "dependencies": { 1348 | "lowercase-keys": "^1.0.0" 1349 | } 1350 | }, 1351 | "node_modules/reusify": { 1352 | "version": "1.0.4", 1353 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 1354 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 1355 | "engines": { 1356 | "iojs": ">=1.0.0", 1357 | "node": ">=0.10.0" 1358 | } 1359 | }, 1360 | "node_modules/rimraf": { 1361 | "version": "3.0.2", 1362 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1363 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1364 | "deprecated": "Rimraf versions prior to v4 are no longer supported", 1365 | "dependencies": { 1366 | "glob": "^7.1.3" 1367 | }, 1368 | "bin": { 1369 | "rimraf": "bin.js" 1370 | }, 1371 | "funding": { 1372 | "url": "https://github.com/sponsors/isaacs" 1373 | } 1374 | }, 1375 | "node_modules/run-parallel": { 1376 | "version": "1.2.0", 1377 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 1378 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 1379 | "funding": [ 1380 | { 1381 | "type": "github", 1382 | "url": "https://github.com/sponsors/feross" 1383 | }, 1384 | { 1385 | "type": "patreon", 1386 | "url": "https://www.patreon.com/feross" 1387 | }, 1388 | { 1389 | "type": "consulting", 1390 | "url": "https://feross.org/support" 1391 | } 1392 | ], 1393 | "dependencies": { 1394 | "queue-microtask": "^1.2.2" 1395 | } 1396 | }, 1397 | "node_modules/safe-buffer": { 1398 | "version": "5.2.1", 1399 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1400 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1401 | "funding": [ 1402 | { 1403 | "type": "github", 1404 | "url": "https://github.com/sponsors/feross" 1405 | }, 1406 | { 1407 | "type": "patreon", 1408 | "url": "https://www.patreon.com/feross" 1409 | }, 1410 | { 1411 | "type": "consulting", 1412 | "url": "https://feross.org/support" 1413 | } 1414 | ] 1415 | }, 1416 | "node_modules/seek-bzip": { 1417 | "version": "1.0.6", 1418 | "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", 1419 | "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", 1420 | "dependencies": { 1421 | "commander": "^2.8.1" 1422 | }, 1423 | "bin": { 1424 | "seek-bunzip": "bin/seek-bunzip", 1425 | "seek-table": "bin/seek-bzip-table" 1426 | } 1427 | }, 1428 | "node_modules/semver": { 1429 | "version": "5.7.2", 1430 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", 1431 | "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", 1432 | "bin": { 1433 | "semver": "bin/semver" 1434 | } 1435 | }, 1436 | "node_modules/signal-exit": { 1437 | "version": "3.0.7", 1438 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", 1439 | "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" 1440 | }, 1441 | "node_modules/slash": { 1442 | "version": "3.0.0", 1443 | "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", 1444 | "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", 1445 | "engines": { 1446 | "node": ">=8" 1447 | } 1448 | }, 1449 | "node_modules/sort-keys": { 1450 | "version": "2.0.0", 1451 | "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", 1452 | "integrity": "sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==", 1453 | "dependencies": { 1454 | "is-plain-obj": "^1.0.0" 1455 | }, 1456 | "engines": { 1457 | "node": ">=4" 1458 | } 1459 | }, 1460 | "node_modules/sort-keys-length": { 1461 | "version": "1.0.1", 1462 | "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", 1463 | "integrity": "sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==", 1464 | "dependencies": { 1465 | "sort-keys": "^1.0.0" 1466 | }, 1467 | "engines": { 1468 | "node": ">=0.10.0" 1469 | } 1470 | }, 1471 | "node_modules/sort-keys-length/node_modules/sort-keys": { 1472 | "version": "1.1.2", 1473 | "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", 1474 | "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==", 1475 | "dependencies": { 1476 | "is-plain-obj": "^1.0.0" 1477 | }, 1478 | "engines": { 1479 | "node": ">=0.10.0" 1480 | } 1481 | }, 1482 | "node_modules/strict-uri-encode": { 1483 | "version": "1.1.0", 1484 | "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", 1485 | "integrity": "sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==", 1486 | "engines": { 1487 | "node": ">=0.10.0" 1488 | } 1489 | }, 1490 | "node_modules/string_decoder": { 1491 | "version": "1.1.1", 1492 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1493 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1494 | "dependencies": { 1495 | "safe-buffer": "~5.1.0" 1496 | } 1497 | }, 1498 | "node_modules/string_decoder/node_modules/safe-buffer": { 1499 | "version": "5.1.2", 1500 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1501 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1502 | }, 1503 | "node_modules/strip-dirs": { 1504 | "version": "2.1.0", 1505 | "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", 1506 | "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", 1507 | "dependencies": { 1508 | "is-natural-number": "^4.0.1" 1509 | } 1510 | }, 1511 | "node_modules/strip-outer": { 1512 | "version": "1.0.1", 1513 | "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", 1514 | "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", 1515 | "dependencies": { 1516 | "escape-string-regexp": "^1.0.2" 1517 | }, 1518 | "engines": { 1519 | "node": ">=0.10.0" 1520 | } 1521 | }, 1522 | "node_modules/tar": { 1523 | "version": "6.2.1", 1524 | "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", 1525 | "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", 1526 | "dependencies": { 1527 | "chownr": "^2.0.0", 1528 | "fs-minipass": "^2.0.0", 1529 | "minipass": "^5.0.0", 1530 | "minizlib": "^2.1.1", 1531 | "mkdirp": "^1.0.3", 1532 | "yallist": "^4.0.0" 1533 | }, 1534 | "engines": { 1535 | "node": ">=10" 1536 | } 1537 | }, 1538 | "node_modules/tar-stream": { 1539 | "version": "1.6.2", 1540 | "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", 1541 | "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", 1542 | "dependencies": { 1543 | "bl": "^1.0.0", 1544 | "buffer-alloc": "^1.2.0", 1545 | "end-of-stream": "^1.0.0", 1546 | "fs-constants": "^1.0.0", 1547 | "readable-stream": "^2.3.0", 1548 | "to-buffer": "^1.1.1", 1549 | "xtend": "^4.0.0" 1550 | }, 1551 | "engines": { 1552 | "node": ">= 0.8.0" 1553 | } 1554 | }, 1555 | "node_modules/through": { 1556 | "version": "2.3.8", 1557 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1558 | "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" 1559 | }, 1560 | "node_modules/timed-out": { 1561 | "version": "4.0.1", 1562 | "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", 1563 | "integrity": "sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA==", 1564 | "engines": { 1565 | "node": ">=0.10.0" 1566 | } 1567 | }, 1568 | "node_modules/to-buffer": { 1569 | "version": "1.1.1", 1570 | "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", 1571 | "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" 1572 | }, 1573 | "node_modules/to-regex-range": { 1574 | "version": "5.0.1", 1575 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1576 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1577 | "dependencies": { 1578 | "is-number": "^7.0.0" 1579 | }, 1580 | "engines": { 1581 | "node": ">=8.0" 1582 | } 1583 | }, 1584 | "node_modules/traverse-chain": { 1585 | "version": "0.1.0", 1586 | "resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz", 1587 | "integrity": "sha512-up6Yvai4PYKhpNp5PkYtx50m3KbwQrqDwbuZP/ItyL64YEWHAvH6Md83LFLV/GRSk/BoUVwwgUzX6SOQSbsfAg==" 1588 | }, 1589 | "node_modules/trim-repeated": { 1590 | "version": "1.0.0", 1591 | "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", 1592 | "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", 1593 | "dependencies": { 1594 | "escape-string-regexp": "^1.0.2" 1595 | }, 1596 | "engines": { 1597 | "node": ">=0.10.0" 1598 | } 1599 | }, 1600 | "node_modules/typedarray-to-buffer": { 1601 | "version": "3.1.5", 1602 | "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", 1603 | "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", 1604 | "dependencies": { 1605 | "is-typedarray": "^1.0.0" 1606 | } 1607 | }, 1608 | "node_modules/unbzip2-stream": { 1609 | "version": "1.4.3", 1610 | "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", 1611 | "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", 1612 | "dependencies": { 1613 | "buffer": "^5.2.1", 1614 | "through": "^2.3.8" 1615 | } 1616 | }, 1617 | "node_modules/url-parse-lax": { 1618 | "version": "3.0.0", 1619 | "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", 1620 | "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", 1621 | "dependencies": { 1622 | "prepend-http": "^2.0.0" 1623 | }, 1624 | "engines": { 1625 | "node": ">=4" 1626 | } 1627 | }, 1628 | "node_modules/url-to-options": { 1629 | "version": "1.0.1", 1630 | "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", 1631 | "integrity": "sha512-0kQLIzG4fdk/G5NONku64rSH/x32NOA39LVQqlK8Le6lvTF6GGRJpqaQFGgU+CLwySIqBSMdwYM0sYcW9f6P4A==", 1632 | "engines": { 1633 | "node": ">= 4" 1634 | } 1635 | }, 1636 | "node_modules/util-deprecate": { 1637 | "version": "1.0.2", 1638 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1639 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" 1640 | }, 1641 | "node_modules/wrappy": { 1642 | "version": "1.0.2", 1643 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1644 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" 1645 | }, 1646 | "node_modules/write-file-atomic": { 1647 | "version": "3.0.3", 1648 | "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", 1649 | "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", 1650 | "dependencies": { 1651 | "imurmurhash": "^0.1.4", 1652 | "is-typedarray": "^1.0.0", 1653 | "signal-exit": "^3.0.2", 1654 | "typedarray-to-buffer": "^3.1.5" 1655 | } 1656 | }, 1657 | "node_modules/write-json-file": { 1658 | "version": "4.3.0", 1659 | "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-4.3.0.tgz", 1660 | "integrity": "sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ==", 1661 | "dependencies": { 1662 | "detect-indent": "^6.0.0", 1663 | "graceful-fs": "^4.1.15", 1664 | "is-plain-obj": "^2.0.0", 1665 | "make-dir": "^3.0.0", 1666 | "sort-keys": "^4.0.0", 1667 | "write-file-atomic": "^3.0.0" 1668 | }, 1669 | "engines": { 1670 | "node": ">=8.3" 1671 | }, 1672 | "funding": { 1673 | "url": "https://github.com/sponsors/sindresorhus" 1674 | } 1675 | }, 1676 | "node_modules/write-json-file/node_modules/is-plain-obj": { 1677 | "version": "2.1.0", 1678 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", 1679 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", 1680 | "engines": { 1681 | "node": ">=8" 1682 | } 1683 | }, 1684 | "node_modules/write-json-file/node_modules/make-dir": { 1685 | "version": "3.1.0", 1686 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", 1687 | "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", 1688 | "dependencies": { 1689 | "semver": "^6.0.0" 1690 | }, 1691 | "engines": { 1692 | "node": ">=8" 1693 | }, 1694 | "funding": { 1695 | "url": "https://github.com/sponsors/sindresorhus" 1696 | } 1697 | }, 1698 | "node_modules/write-json-file/node_modules/semver": { 1699 | "version": "6.3.1", 1700 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", 1701 | "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", 1702 | "bin": { 1703 | "semver": "bin/semver.js" 1704 | } 1705 | }, 1706 | "node_modules/write-json-file/node_modules/sort-keys": { 1707 | "version": "4.2.0", 1708 | "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-4.2.0.tgz", 1709 | "integrity": "sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==", 1710 | "dependencies": { 1711 | "is-plain-obj": "^2.0.0" 1712 | }, 1713 | "engines": { 1714 | "node": ">=8" 1715 | }, 1716 | "funding": { 1717 | "url": "https://github.com/sponsors/sindresorhus" 1718 | } 1719 | }, 1720 | "node_modules/xtend": { 1721 | "version": "4.0.2", 1722 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 1723 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", 1724 | "engines": { 1725 | "node": ">=0.4" 1726 | } 1727 | }, 1728 | "node_modules/yallist": { 1729 | "version": "4.0.0", 1730 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 1731 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 1732 | }, 1733 | "node_modules/yaml": { 1734 | "version": "2.6.0", 1735 | "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", 1736 | "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", 1737 | "bin": { 1738 | "yaml": "bin.mjs" 1739 | }, 1740 | "engines": { 1741 | "node": ">= 14" 1742 | } 1743 | }, 1744 | "node_modules/yauzl": { 1745 | "version": "2.10.0", 1746 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", 1747 | "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", 1748 | "dependencies": { 1749 | "buffer-crc32": "~0.2.3", 1750 | "fd-slicer": "~1.1.0" 1751 | } 1752 | } 1753 | } 1754 | } 1755 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "drupal-smart-snippets", 3 | "displayName": "Drupal Smart Snippets", 4 | "description": "Context-aware snippets for Drupal development", 5 | "version": "2.2.1", 6 | "publisher": "andrewdavidblum", 7 | "type": "module", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/andy-blum/smart-drupal-snippets" 11 | }, 12 | "engines": { 13 | "vscode": "^1.49.0" 14 | }, 15 | "galleryBanner": { 16 | "color": "#0678BE", 17 | "theme": "dark" 18 | }, 19 | "icon": "images/drupal_logo.png", 20 | "categories": [ 21 | "Snippets" 22 | ], 23 | "keywords": [ 24 | "Drupal", 25 | "Drupal-9", 26 | "Drupal-10", 27 | "PHP", 28 | "Snippets" 29 | ], 30 | "contributes": { 31 | "snippets": [ 32 | { 33 | "language": "php", 34 | "path": "./snippets/hooks.json" 35 | }, 36 | { 37 | "language": "php", 38 | "path": "./snippets/elements.json" 39 | }, 40 | { 41 | "language": "php", 42 | "path": "./snippets/services.json" 43 | } 44 | ], 45 | "languages": [ 46 | { 47 | "id": "php", 48 | "aliases": [ 49 | "PHP", 50 | "php" 51 | ], 52 | "extensions": [ 53 | ".engine", 54 | ".install", 55 | ".inc", 56 | ".make", 57 | ".module", 58 | ".profile", 59 | ".test", 60 | ".theme" 61 | ] 62 | } 63 | ] 64 | }, 65 | "dependencies": { 66 | "del": "^6.1.1", 67 | "download": "^8.0.0", 68 | "find": "^0.3.0", 69 | "he": "^1.2.0", 70 | "php-parser": "^3.1.4", 71 | "tar": "^6.1.11", 72 | "write-json-file": "^4.3.0", 73 | "yaml": "^2.2.1" 74 | }, 75 | "scripts": { 76 | "start": "node index.js", 77 | "vscode:prepublish": "node index.js" 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /snippets/elements.json: -------------------------------------------------------------------------------- 1 | { 2 | "@Element (\"actions\")": { 3 | "prefix": [ 4 | "@RenderElement (\"actions\")", 5 | "@Element (\"actions\")", 6 | "actions" 7 | ], 8 | "body": [ 9 | "[", 10 | " '#type' => 'actions',", 11 | "]${5|\\,,;|}" 12 | ], 13 | "description": [ 14 | "Provides a wrapper element to group one or more buttons in a form.", 15 | "", 16 | "Use of a single Actions element with an array key of 'actions' to group the", 17 | "primary submit buttons on a form helps to ensure proper styling in themes,", 18 | "and enables other modules to properly alter a form's actions.", 19 | "", 20 | "Usage example:", 21 | "@code", 22 | "$form['actions'] = ['#type' => 'actions'];", 23 | "$form['actions']['submit'] = [", 24 | " '#type' => 'submit',", 25 | " '#value' => $this->t('Save'),", 26 | "];", 27 | "@endcode" 28 | ], 29 | "scope": "php" 30 | }, 31 | "@Element (\"ajax\")": { 32 | "prefix": [ 33 | "@RenderElement (\"ajax\")", 34 | "@Element (\"ajax\")", 35 | "ajax" 36 | ], 37 | "body": [ 38 | "[", 39 | " '#type' => 'ajax',", 40 | "]${5|\\,,;|}" 41 | ], 42 | "description": [ 43 | "Provides a render element for adding Ajax to a render element.", 44 | "", 45 | "Holds an array whose values control the Ajax behavior of the element.", 46 | "", 47 | "@ingroup ajax", 48 | "", 49 | "@deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. Return an", 50 | " \\Drupal\\Core\\Ajax\\AjaxResponse instead.", 51 | "", 52 | "@see https://www.drupal.org/node/3068104" 53 | ], 54 | "scope": "php" 55 | }, 56 | "@Element (\"break_lock_link\")": { 57 | "prefix": [ 58 | "@RenderElement (\"break_lock_link\")", 59 | "@Element (\"break_lock_link\")", 60 | "break_lock_link" 61 | ], 62 | "body": [ 63 | "[", 64 | " '#type' => 'break_lock_link',", 65 | " '#label' => '',", 66 | " '#lock' => '',", 67 | " '#url' => '',", 68 | "]${5|\\,,;|}" 69 | ], 70 | "description": [ 71 | "Provides a link to break a tempstore lock.", 72 | "", 73 | "Properties:", 74 | "- #label: The label of the object that is locked.", 75 | "- #lock: \\Drupal\\Core\\TempStore\\Lock object.", 76 | "- #url: \\Drupal\\Core\\Url object pointing to the break lock form.", 77 | "", 78 | "Usage example:", 79 | "@code", 80 | "$build['examples_lock'] = [", 81 | " '#type' => 'break_lock_link',", 82 | " '#label' => $this->t('example item'),", 83 | " '#lock' => $tempstore->getMetadata('example_key'),", 84 | " '#url' => \\Drupal\\Core\\Url::fromRoute('examples.break_lock_form'),", 85 | "];", 86 | "@endcode" 87 | ], 88 | "scope": "php" 89 | }, 90 | "@Element (\"button\")": { 91 | "prefix": [ 92 | "@FormElement (\"button\")", 93 | "@Element (\"button\")", 94 | "button" 95 | ], 96 | "body": [ 97 | "[", 98 | " '#type' => 'button',", 99 | " '#title' => ${1|t(''),$this->t('')|},", 100 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 101 | " '#description' => ${3|t(''),$this->t('')|},", 102 | " '#required' => ${4|TRUE,FALSE|},", 103 | " '#limit_validation_errors' => '',", 104 | " '#value' => '',", 105 | "]${5|\\,,;|}" 106 | ], 107 | "description": [ 108 | "Provides an action button form element.", 109 | "", 110 | "When the button is pressed, the form will be submitted to Drupal, where it is", 111 | "validated and rebuilt. The submit handler is not invoked.", 112 | "", 113 | "Properties:", 114 | "- #limit_validation_errors: An array of form element keys that will block", 115 | " form submission when validation for these elements or any child elements", 116 | " fails. Specify an empty array to suppress all form validation errors.", 117 | "- #value: The text to be shown on the button.", 118 | "", 119 | "", 120 | "Usage Example:", 121 | "@code", 122 | "$form['actions']['preview'] = [", 123 | " '#type' => 'button',", 124 | " '#value' => $this->t('Preview'),", 125 | "];", 126 | "@endcode", 127 | "", 128 | "@see \\Drupal\\Core\\Render\\Element\\Submit" 129 | ], 130 | "scope": "php" 131 | }, 132 | "@Element (\"checkbox\")": { 133 | "prefix": [ 134 | "@FormElement (\"checkbox\")", 135 | "@Element (\"checkbox\")", 136 | "checkbox" 137 | ], 138 | "body": [ 139 | "[", 140 | " '#type' => 'checkbox',", 141 | " '#title' => ${1|t(''),$this->t('')|},", 142 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 143 | " '#description' => ${3|t(''),$this->t('')|},", 144 | " '#required' => ${4|TRUE,FALSE|},", 145 | " '#return_value' => '',", 146 | "]${5|\\,,;|}" 147 | ], 148 | "description": [ 149 | "Provides a form element for a single checkbox.", 150 | "", 151 | "Properties:", 152 | "- #return_value: The value to return when the checkbox is checked.", 153 | "", 154 | "Usage example:", 155 | "@code", 156 | "$form['copy'] = [", 157 | " '#type' => 'checkbox',", 158 | " '#title' => $this->t('Send me a copy'),", 159 | "];", 160 | "@endcode", 161 | "", 162 | "@see \\Drupal\\Core\\Render\\Element\\Checkboxes" 163 | ], 164 | "scope": "php" 165 | }, 166 | "@Element (\"checkboxes\")": { 167 | "prefix": [ 168 | "@FormElement (\"checkboxes\")", 169 | "@Element (\"checkboxes\")", 170 | "checkboxes" 171 | ], 172 | "body": [ 173 | "[", 174 | " '#type' => 'checkboxes',", 175 | " '#title' => ${1|t(''),$this->t('')|},", 176 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 177 | " '#description' => ${3|t(''),$this->t('')|},", 178 | " '#required' => ${4|TRUE,FALSE|},", 179 | " '#options' => '',", 180 | "]${5|\\,,;|}" 181 | ], 182 | "description": [ 183 | "Provides a form element for a set of checkboxes.", 184 | "", 185 | "Properties:", 186 | "- #options: An associative array whose keys are the values returned for each", 187 | " checkbox, and whose values are the labels next to each checkbox. The", 188 | " #options array cannot have a 0 key, as it would not be possible to discern", 189 | " checked and unchecked states.", 190 | "", 191 | "Usage example:", 192 | "@code", 193 | "$form['favorites']['colors'] = [", 194 | " '#type' => 'checkboxes',", 195 | " '#options' => ['blue' => $this->t('Blue'), 'red' => $this->t('Red')],", 196 | " '#title' => $this->t('Which colors do you like?'),", 197 | " ...", 198 | "];", 199 | "@endcode", 200 | "", 201 | "Element properties may be set on single option items as follows.", 202 | "", 203 | "@code", 204 | "$form['favorites']['colors']['blue']['#description'] = $this->t('The color of the sky.');", 205 | "@endcode", 206 | "", 207 | "@see \\Drupal\\Core\\Render\\Element\\Radios", 208 | "@see \\Drupal\\Core\\Render\\Element\\Checkbox" 209 | ], 210 | "scope": "php" 211 | }, 212 | "@Element (\"color\")": { 213 | "prefix": [ 214 | "@FormElement (\"color\")", 215 | "@Element (\"color\")", 216 | "color" 217 | ], 218 | "body": [ 219 | "[", 220 | " '#type' => 'color',", 221 | " '#title' => ${1|t(''),$this->t('')|},", 222 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 223 | " '#description' => ${3|t(''),$this->t('')|},", 224 | " '#required' => ${4|TRUE,FALSE|},", 225 | " '#default_value' => '',", 226 | "]${5|\\,,;|}" 227 | ], 228 | "description": [ 229 | "Provides a form element for choosing a color.", 230 | "", 231 | "Properties:", 232 | "- #default_value: Default value, in a format like #ffffff.", 233 | "", 234 | "Example usage:", 235 | "@code", 236 | "$form['color'] = [", 237 | " '#type' => 'color',", 238 | " '#title' => $this->t('Color'),", 239 | " '#default_value' => '#ffffff',", 240 | "];", 241 | "@endcode" 242 | ], 243 | "scope": "php" 244 | }, 245 | "@Element (\"component\")": { 246 | "prefix": [ 247 | "@RenderElement (\"component\")", 248 | "@Element (\"component\")", 249 | "component" 250 | ], 251 | "body": [ 252 | "[", 253 | " '#type' => 'component',", 254 | " '#component' => '',", 255 | " '#props' => '',", 256 | " '#slots' => '',", 257 | " '#propsAlter' => '',", 258 | " '#slotsAlter' => '',", 259 | "]${5|\\,,;|}" 260 | ], 261 | "description": [ 262 | "Provides a Single Directory Component render element.", 263 | "", 264 | "Properties:", 265 | "- #component: The machine name of the component.", 266 | "- #props: an associative array where the keys are the names of the", 267 | " component props, and the values are the prop values.", 268 | "- #slots: an associative array where the keys are the slot names, and the", 269 | " values are the slot values. Expected slot values are renderable arrays.", 270 | "- #propsAlter: an array of trusted callbacks. These are used to prepare the", 271 | " context. Typical uses include replacing tokens in props.", 272 | "- #slotsAlter: an array of trusted callbacks to alter the render array in", 273 | " #slots.", 274 | "", 275 | "Usage Example:", 276 | "", 277 | "@code", 278 | "$build['component'] = [", 279 | " '#type' => 'component',", 280 | " '#component' => 'olivero:button',", 281 | "];", 282 | "@endcode", 283 | "", 284 | "@see \\Drupal\\Core\\Render\\Element\\Textarea" 285 | ], 286 | "scope": "php" 287 | }, 288 | "@Element (\"container\")": { 289 | "prefix": [ 290 | "@RenderElement (\"container\")", 291 | "@Element (\"container\")", 292 | "container" 293 | ], 294 | "body": [ 295 | "[", 296 | " '#type' => 'container',", 297 | " '#optional' => '',", 298 | "]${5|\\,,;|}" 299 | ], 300 | "description": [ 301 | "Provides a render element that wraps child elements in a container.", 302 | "", 303 | "Surrounds child elements with a and adds attributes such as classes or", 304 | "an HTML ID.", 305 | "", 306 | "Properties:", 307 | "- #optional: Indicates whether the container should render when it has no", 308 | " visible children. Defaults to FALSE.", 309 | "", 310 | "Usage example:", 311 | "@code", 312 | "$form['needs_accommodation'] = [", 313 | " '#type' => 'checkbox',", 314 | " '#title' => $this->t('Need Special Accommodations?'),", 315 | "];", 316 | "", 317 | "$form['accommodation'] = [", 318 | " '#type' => 'container',", 319 | " '#attributes' => [", 320 | " 'class' => ['accommodation'],", 321 | " ],", 322 | " '#states' => [", 323 | " 'invisible' => [", 324 | " 'input[name=\"needs_accommodation\"]' => ['checked' => FALSE],", 325 | " ],", 326 | " ],", 327 | "];", 328 | "", 329 | "$form['accommodation']['diet'] = [", 330 | " '#type' => 'textfield',", 331 | " '#title' => $this->t('Dietary Restrictions'),", 332 | "];", 333 | "@endcode" 334 | ], 335 | "scope": "php" 336 | }, 337 | "@Element (\"contextual_links\")": { 338 | "prefix": [ 339 | "@RenderElement (\"contextual_links\")", 340 | "@Element (\"contextual_links\")", 341 | "contextual_links" 342 | ], 343 | "body": [ 344 | "[", 345 | " '#type' => 'contextual_links',", 346 | "]${5|\\,,;|}" 347 | ], 348 | "description": [ 349 | "Provides a contextual_links element." 350 | ], 351 | "scope": "php" 352 | }, 353 | "@Element (\"contextual_links_placeholder\")": { 354 | "prefix": [ 355 | "@RenderElement (\"contextual_links_placeholder\")", 356 | "@Element (\"contextual_links_placeholder\")", 357 | "contextual_links_placeholder" 358 | ], 359 | "body": [ 360 | "[", 361 | " '#type' => 'contextual_links_placeholder',", 362 | "]${5|\\,,;|}" 363 | ], 364 | "description": [ 365 | "Provides a contextual_links_placeholder element." 366 | ], 367 | "scope": "php" 368 | }, 369 | "@Element (\"date\")": { 370 | "prefix": [ 371 | "@FormElement (\"date\")", 372 | "@Element (\"date\")", 373 | "date" 374 | ], 375 | "body": [ 376 | "[", 377 | " '#type' => 'date',", 378 | " '#title' => ${1|t(''),$this->t('')|},", 379 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 380 | " '#description' => ${3|t(''),$this->t('')|},", 381 | " '#required' => ${4|TRUE,FALSE|},", 382 | " '#default_value' => '',", 383 | " '#size' => '',", 384 | "]${5|\\,,;|}" 385 | ], 386 | "description": [ 387 | "Provides a form element for date selection.", 388 | "", 389 | "Properties:", 390 | "- #default_value: A string for the default date in 'Y-m-d' format.", 391 | "- #size: The size of the input element in characters.", 392 | "", 393 | "@code", 394 | "$form['expiration'] = [", 395 | " '#type' => 'date',", 396 | " '#title' => $this->t('Content expiration'),", 397 | " '#default_value' => '2020-02-05',", 398 | "];", 399 | "@endcode" 400 | ], 401 | "scope": "php" 402 | }, 403 | "@Element (\"datelist\")": { 404 | "prefix": [ 405 | "@FormElement (\"datelist\")", 406 | "@Element (\"datelist\")", 407 | "datelist" 408 | ], 409 | "body": [ 410 | "[", 411 | " '#type' => 'datelist',", 412 | " '#title' => ${1|t(''),$this->t('')|},", 413 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 414 | " '#description' => ${3|t(''),$this->t('')|},", 415 | " '#required' => ${4|TRUE,FALSE|},", 416 | "]${5|\\,,;|}" 417 | ], 418 | "description": [ 419 | "Provides a datelist element." 420 | ], 421 | "scope": "php" 422 | }, 423 | "@Element (\"datetime\")": { 424 | "prefix": [ 425 | "@FormElement (\"datetime\")", 426 | "@Element (\"datetime\")", 427 | "datetime" 428 | ], 429 | "body": [ 430 | "[", 431 | " '#type' => 'datetime',", 432 | " '#title' => ${1|t(''),$this->t('')|},", 433 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 434 | " '#description' => ${3|t(''),$this->t('')|},", 435 | " '#required' => ${4|TRUE,FALSE|},", 436 | "]${5|\\,,;|}" 437 | ], 438 | "description": [ 439 | "Provides a datetime element." 440 | ], 441 | "scope": "php" 442 | }, 443 | "@Element (\"deprecated\")": { 444 | "prefix": [ 445 | "@RenderElement (\"deprecated\")", 446 | "@Element (\"deprecated\")", 447 | "deprecated" 448 | ], 449 | "body": [ 450 | "[", 451 | " '#type' => 'deprecated',", 452 | "]${5|\\,,;|}" 453 | ], 454 | "description": [ 455 | "Provides deprecated render element for testing." 456 | ], 457 | "scope": "php" 458 | }, 459 | "@Element (\"deprecated_extends_form\")": { 460 | "prefix": [ 461 | "@FormElement (\"deprecated_extends_form\")", 462 | "@Element (\"deprecated_extends_form\")", 463 | "deprecated_extends_form" 464 | ], 465 | "body": [ 466 | "[", 467 | " '#type' => 'deprecated_extends_form',", 468 | " '#title' => ${1|t(''),$this->t('')|},", 469 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 470 | " '#description' => ${3|t(''),$this->t('')|},", 471 | " '#required' => ${4|TRUE,FALSE|},", 472 | "]${5|\\,,;|}" 473 | ], 474 | "description": [ 475 | "Provides render element that extends deprecated FormElement for testing.", 476 | "", 477 | "@phpstan-ignore-next-line" 478 | ], 479 | "scope": "php" 480 | }, 481 | "@Element (\"deprecated_extends_render\")": { 482 | "prefix": [ 483 | "@RenderElement (\"deprecated_extends_render\")", 484 | "@Element (\"deprecated_extends_render\")", 485 | "deprecated_extends_render" 486 | ], 487 | "body": [ 488 | "[", 489 | " '#type' => 'deprecated_extends_render',", 490 | "]${5|\\,,;|}" 491 | ], 492 | "description": [ 493 | "Provides render element that extends deprecated RenderElement for testing.", 494 | "", 495 | "@phpstan-ignore-next-line" 496 | ], 497 | "scope": "php" 498 | }, 499 | "@Element (\"details\")": { 500 | "prefix": [ 501 | "@RenderElement (\"details\")", 502 | "@Element (\"details\")", 503 | "details" 504 | ], 505 | "body": [ 506 | "[", 507 | " '#type' => 'details',", 508 | " '#open' => '',", 509 | " '#summary_attributes' => '',", 510 | "]${5|\\,,;|}" 511 | ], 512 | "description": [ 513 | "Provides a render element for a details element, similar to a fieldset.", 514 | "", 515 | "Fieldsets can only be used in forms, while details elements can be used", 516 | "outside of forms. Users click on the title to open or close the details", 517 | "element, showing or hiding the contained elements.", 518 | "", 519 | "Properties:", 520 | "- #title: The title of the details container. Defaults to \"Details\".", 521 | "- #open: Indicates whether the container should be open by default.", 522 | " Defaults to FALSE.", 523 | "- #summary_attributes: An array of attributes to apply to the ", 524 | " element.", 525 | "", 526 | "Usage example:", 527 | "@code", 528 | "$form['author'] = [", 529 | " '#type' => 'details',", 530 | " '#title' => $this->t('Author'),", 531 | "];", 532 | "", 533 | "$form['author']['name'] = [", 534 | " '#type' => 'textfield',", 535 | " '#title' => $this->t('Name'),", 536 | "];", 537 | "@endcode", 538 | "", 539 | "@see \\Drupal\\Core\\Render\\Element\\Fieldset", 540 | "@see \\Drupal]Core\\Render\\Element\\VerticalTabs" 541 | ], 542 | "scope": "php" 543 | }, 544 | "@Element (\"dropbutton\")": { 545 | "prefix": [ 546 | "@RenderElement (\"dropbutton\")", 547 | "@Element (\"dropbutton\")", 548 | "dropbutton" 549 | ], 550 | "body": [ 551 | "[", 552 | " '#type' => 'dropbutton',", 553 | " '#links' => '',", 554 | " '#dropbutton_type' => '',", 555 | "]${5|\\,,;|}" 556 | ], 557 | "description": [ 558 | "Provides a render element for a set of links rendered as a drop-down button.", 559 | "", 560 | "By default, this element sets #theme so that the 'links' theme hook is used", 561 | "for rendering, with suffixes so that themes can override this specifically", 562 | "without overriding all links theming. If the #subtype property is provided in", 563 | "your render array with value 'foo', #theme is set to links__dropbutton__foo;", 564 | "if not, it's links__dropbutton; both of these can be overridden by setting", 565 | "the #theme property in your render array. See template_preprocess_links()", 566 | "for documentation on the other properties used in theming; for instance, use", 567 | "element property #links to provide $variables['links'] for theming.", 568 | "", 569 | "Properties:", 570 | "- #links: An array of links to actions. See template_preprocess_links() for", 571 | " documentation the properties of links in this array.", 572 | "- #dropbutton_type: A string defining a type of dropbutton variant for", 573 | " styling proposes. Renders as class `dropbutton--#dropbutton_type`.", 574 | "", 575 | "Usage Example:", 576 | "@code", 577 | "$form['actions']['extra_actions'] = [", 578 | " '#type' => 'dropbutton',", 579 | " '#dropbutton_type' => 'small',", 580 | " '#links' => [", 581 | " 'simple_form' => [", 582 | " 'title' => $this->t('Simple Form'),", 583 | " 'url' => Url::fromRoute('fapi_example.simple_form'),", 584 | " ],", 585 | " 'demo' => [", 586 | " 'title' => $this->t('Build Demo'),", 587 | " 'url' => Url::fromRoute('fapi_example.build_demo'),", 588 | " ],", 589 | " ],", 590 | "];", 591 | "@endcode", 592 | "", 593 | "@see \\Drupal\\Core\\Render\\Element\\Operations" 594 | ], 595 | "scope": "php" 596 | }, 597 | "@Element (\"email\")": { 598 | "prefix": [ 599 | "@FormElement (\"email\")", 600 | "@Element (\"email\")", 601 | "email" 602 | ], 603 | "body": [ 604 | "[", 605 | " '#type' => 'email',", 606 | " '#title' => ${1|t(''),$this->t('')|},", 607 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 608 | " '#description' => ${3|t(''),$this->t('')|},", 609 | " '#required' => ${4|TRUE,FALSE|},", 610 | " '#default_value' => '',", 611 | " '#size' => '',", 612 | " '#pattern' => '',", 613 | "]${5|\\,,;|}" 614 | ], 615 | "description": [ 616 | "Provides a form input element for entering an email address.", 617 | "", 618 | "Properties:", 619 | "- #default_value: An RFC-compliant email address.", 620 | "- #size: The size of the input element in characters.", 621 | "- #pattern: A string for the native HTML5 pattern attribute.", 622 | "", 623 | "Example usage:", 624 | "@code", 625 | "$form['email'] = [", 626 | " '#type' => 'email',", 627 | " '#title' => $this->t('Email'),", 628 | " '#pattern' => '*@example.com',", 629 | "];", 630 | "@endcode", 631 | "", 632 | "@see \\Drupal\\Core\\Render\\Element\\Textfield" 633 | ], 634 | "scope": "php" 635 | }, 636 | "@Element (\"entity_autocomplete\")": { 637 | "prefix": [ 638 | "@FormElement (\"entity_autocomplete\")", 639 | "@Element (\"entity_autocomplete\")", 640 | "entity_autocomplete" 641 | ], 642 | "body": [ 643 | "[", 644 | " '#type' => 'entity_autocomplete',", 645 | " '#title' => ${1|t(''),$this->t('')|},", 646 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 647 | " '#description' => ${3|t(''),$this->t('')|},", 648 | " '#required' => ${4|TRUE,FALSE|},", 649 | " '#target_type' => '',", 650 | " '#tags' => '',", 651 | " '#default_value' => '',", 652 | " '#selection_handler' => '',", 653 | " '#selection_settings' => '',", 654 | " '#autocreate' => '',", 655 | " '#process_default_value' => '',", 656 | " '#validate_reference' => '',", 657 | "]${5|\\,,;|}" 658 | ], 659 | "description": [ 660 | "Provides an entity autocomplete form element.", 661 | "", 662 | "The autocomplete form element allows users to select one or multiple", 663 | "entities, which can come from all or specific bundles of an entity type.", 664 | "", 665 | "Properties:", 666 | "- #target_type: (required) The ID of the target entity type.", 667 | "- #tags: (optional) TRUE if the element allows multiple selection. Defaults", 668 | " to FALSE.", 669 | "- #default_value: (optional) The default entity or an array of default", 670 | " entities, depending on the value of #tags.", 671 | "- #selection_handler: (optional) The plugin ID of the entity reference", 672 | " selection handler (a plugin of type EntityReferenceSelection). The default", 673 | " value is the lowest-weighted plugin that is compatible with #target_type.", 674 | "- #selection_settings: (optional) An array of settings for the selection", 675 | " handler. Settings for the default selection handler", 676 | " \\Drupal\\Core\\Entity\\Plugin\\EntityReferenceSelection\\DefaultSelection are:", 677 | " - target_bundles: Array of bundles to allow (omit to allow all bundles).", 678 | " - sort: Array with 'field' and 'direction' keys, determining how results", 679 | " will be sorted. Defaults to unsorted.", 680 | "- #autocreate: (optional) Array of settings used to auto-create entities", 681 | " that do not exist (omit to not auto-create entities). Elements:", 682 | " - bundle: (required) Bundle to use for auto-created entities.", 683 | " - uid: User ID to use as the author of auto-created entities. Defaults to", 684 | " the current user.", 685 | "- #process_default_value: (optional) Set to FALSE if the #default_value", 686 | " property is processed and access checked elsewhere (such as by a Field API", 687 | " widget). Defaults to TRUE.", 688 | "- #validate_reference: (optional) Set to FALSE if validation of the selected", 689 | " entities is performed elsewhere. Defaults to TRUE.", 690 | "", 691 | "Usage example:", 692 | "@code", 693 | "$form['my_element'] = [", 694 | " '#type' => 'entity_autocomplete',", 695 | " '#target_type' => 'node',", 696 | " '#tags' => TRUE,", 697 | " '#default_value' => $node,", 698 | " '#selection_handler' => 'default',", 699 | " '#selection_settings' => [", 700 | " 'target_bundles' => ['article', 'page'],", 701 | " ],", 702 | " '#autocreate' => [", 703 | " 'bundle' => 'article',", 704 | " 'uid' => ,", 705 | " ],", 706 | "];", 707 | "@endcode", 708 | "", 709 | "@see \\Drupal\\Core\\Entity\\Plugin\\EntityReferenceSelection\\DefaultSelection" 710 | ], 711 | "scope": "php" 712 | }, 713 | "@Element (\"field_ui_table\")": { 714 | "prefix": [ 715 | "@RenderElement (\"field_ui_table\")", 716 | "@Element (\"field_ui_table\")", 717 | "field_ui_table" 718 | ], 719 | "body": [ 720 | "[", 721 | " '#type' => 'field_ui_table',", 722 | "]${5|\\,,;|}" 723 | ], 724 | "description": [ 725 | "Provides a field_ui table element." 726 | ], 727 | "scope": "php" 728 | }, 729 | "@Element (\"fieldgroup\")": { 730 | "prefix": [ 731 | "@RenderElement (\"fieldgroup\")", 732 | "@Element (\"fieldgroup\")", 733 | "fieldgroup" 734 | ], 735 | "body": [ 736 | "[", 737 | " '#type' => 'fieldgroup',", 738 | "]${5|\\,,;|}" 739 | ], 740 | "description": [ 741 | "Provides a render element for a group of form elements.", 742 | "", 743 | "In default rendering, the only difference between a 'fieldgroup' and a", 744 | "'fieldset' is the CSS class applied to the containing HTML element. Normally", 745 | "use a fieldset.", 746 | "", 747 | "@see \\Drupal\\Core\\Render\\Element\\Fieldset for documentation and usage.", 748 | "", 749 | "@see \\Drupal\\Core\\Render\\Element\\Fieldset", 750 | "@see \\Drupal\\Core\\Render\\Element\\Details" 751 | ], 752 | "scope": "php" 753 | }, 754 | "@Element (\"fieldset\")": { 755 | "prefix": [ 756 | "@RenderElement (\"fieldset\")", 757 | "@Element (\"fieldset\")", 758 | "fieldset" 759 | ], 760 | "body": [ 761 | "[", 762 | " '#type' => 'fieldset',", 763 | "]${5|\\,,;|}" 764 | ], 765 | "description": [ 766 | "Provides a render element for a group of form elements.", 767 | "", 768 | "Usage example:", 769 | "@code", 770 | "$form['author'] = [", 771 | " '#type' => 'fieldset',", 772 | " '#title' => $this->t('Author'),", 773 | "];", 774 | "", 775 | "$form['author']['name'] = [", 776 | " '#type' => 'textfield',", 777 | " '#title' => $this->t('Name'),", 778 | "];", 779 | "@endcode", 780 | "", 781 | "@see \\Drupal\\Core\\Render\\Element\\Fieldgroup", 782 | "@see \\Drupal\\Core\\Render\\Element\\Details" 783 | ], 784 | "scope": "php" 785 | }, 786 | "@Element (\"file\")": { 787 | "prefix": [ 788 | "@FormElement (\"file\")", 789 | "@Element (\"file\")", 790 | "file" 791 | ], 792 | "body": [ 793 | "[", 794 | " '#type' => 'file',", 795 | " '#title' => ${1|t(''),$this->t('')|},", 796 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 797 | " '#description' => ${3|t(''),$this->t('')|},", 798 | " '#required' => ${4|TRUE,FALSE|},", 799 | "]${5|\\,,;|}" 800 | ], 801 | "description": [ 802 | "Provides a form element for uploading a file.", 803 | "", 804 | "If you add this element to a form the enctype=\"multipart/form-data\" attribute", 805 | "will automatically be added to the form element.", 806 | "", 807 | "Properties:", 808 | "- #multiple: A Boolean indicating whether multiple files may be uploaded.", 809 | "- #size: The size of the file input element in characters.", 810 | "", 811 | "The value of this form element will always be an array of", 812 | "\\Symfony\\Component\\HttpFoundation\\File\\UploadedFile objects, regardless of", 813 | "whether #multiple is TRUE or FALSE" 814 | ], 815 | "scope": "php" 816 | }, 817 | "@Element (\"form\")": { 818 | "prefix": [ 819 | "@RenderElement (\"form\")", 820 | "@Element (\"form\")", 821 | "form" 822 | ], 823 | "body": [ 824 | "[", 825 | " '#type' => 'form',", 826 | "]${5|\\,,;|}" 827 | ], 828 | "description": [ 829 | "Provides a render element for a form." 830 | ], 831 | "scope": "php" 832 | }, 833 | "@Element (\"hidden\")": { 834 | "prefix": [ 835 | "@FormElement (\"hidden\")", 836 | "@Element (\"hidden\")", 837 | "hidden" 838 | ], 839 | "body": [ 840 | "[", 841 | " '#type' => 'hidden',", 842 | " '#title' => ${1|t(''),$this->t('')|},", 843 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 844 | " '#description' => ${3|t(''),$this->t('')|},", 845 | " '#required' => ${4|TRUE,FALSE|},", 846 | " '#default_value' => '',", 847 | " '#value' => '',", 848 | "]${5|\\,,;|}" 849 | ], 850 | "description": [ 851 | "Provides a form element for an HTML 'hidden' input element.", 852 | "", 853 | "Specify either #default_value or #value but not both.", 854 | "", 855 | "Properties:", 856 | "- #default_value: The initial value of the form element. JavaScript may", 857 | " alter the value prior to submission.", 858 | "- #value: The value of the form element. The Form API ensures that this", 859 | " value remains unchanged by the browser.", 860 | "", 861 | "Usage example:", 862 | "@code", 863 | "$form['entity_id'] = ['#type' => 'hidden', '#value' => $entity_id];", 864 | "@endcode", 865 | "", 866 | "@see \\Drupal\\Core\\Render\\Element\\Value" 867 | ], 868 | "scope": "php" 869 | }, 870 | "@Element (\"html\")": { 871 | "prefix": [ 872 | "@RenderElement (\"html\")", 873 | "@Element (\"html\")", 874 | "html" 875 | ], 876 | "body": [ 877 | "[", 878 | " '#type' => 'html',", 879 | "]${5|\\,,;|}" 880 | ], 881 | "description": [ 882 | "Provides a render element for an entire HTML page: plus its children." 883 | ], 884 | "scope": "php" 885 | }, 886 | "@Element (\"html_tag\")": { 887 | "prefix": [ 888 | "@RenderElement (\"html_tag\")", 889 | "@Element (\"html_tag\")", 890 | "html_tag" 891 | ], 892 | "body": [ 893 | "[", 894 | " '#type' => 'html_tag',", 895 | " '#tag' => '',", 896 | " '#attributes' => '',", 897 | " '#value' => '',", 898 | " '#noscript' => '',", 899 | "]${5|\\,,;|}" 900 | ], 901 | "description": [ 902 | "Provides a render element for any HTML tag, with properties and value.", 903 | "", 904 | "Properties:", 905 | "- #tag: The tag name to output.", 906 | "- #attributes: (array, optional) HTML attributes to apply to the tag. The", 907 | " attributes are escaped, see \\Drupal\\Core\\Template\\Attribute.", 908 | "- #value: (string, optional) A string containing the textual contents of", 909 | " the tag.", 910 | "- #noscript: (bool, optional) When set to TRUE, the markup", 911 | " (including any prefix or suffix) will be wrapped in a element.", 912 | "", 913 | "Usage example:", 914 | "@code", 915 | "$build['hello'] = [", 916 | " '#type' => 'html_tag',", 917 | " '#tag' => 'p',", 918 | " '#value' => $this->t('Hello World'),", 919 | "];", 920 | "@endcode" 921 | ], 922 | "scope": "php" 923 | }, 924 | "@Element (\"image_button\")": { 925 | "prefix": [ 926 | "@FormElement (\"image_button\")", 927 | "@Element (\"image_button\")", 928 | "image_button" 929 | ], 930 | "body": [ 931 | "[", 932 | " '#type' => 'image_button',", 933 | " '#title' => ${1|t(''),$this->t('')|},", 934 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 935 | " '#description' => ${3|t(''),$this->t('')|},", 936 | " '#required' => ${4|TRUE,FALSE|},", 937 | "]${5|\\,,;|}" 938 | ], 939 | "description": [ 940 | "Provides a form element for a submit button with an image." 941 | ], 942 | "scope": "php" 943 | }, 944 | "@Element (\"inline_template\")": { 945 | "prefix": [ 946 | "@RenderElement (\"inline_template\")", 947 | "@Element (\"inline_template\")", 948 | "inline_template" 949 | ], 950 | "body": [ 951 | "[", 952 | " '#type' => 'inline_template',", 953 | " '#template' => '',", 954 | " '#context' => '',", 955 | "]${5|\\,,;|}" 956 | ], 957 | "description": [ 958 | "Provides a render element where the user supplies an in-line Twig template.", 959 | "", 960 | "Properties:", 961 | "- #template: The inline Twig template used to render the element.", 962 | "- #context: (array) The variables to substitute into the Twig template.", 963 | " Each variable may be a string or a render array.", 964 | "", 965 | "Usage example:", 966 | "@code", 967 | "$build['hello'] = [", 968 | " '#type' => 'inline_template',", 969 | " '#template' => \"{% trans %} Hello {% endtrans %} {{name}}\",", 970 | " '#context' => [", 971 | " 'name' => $name,", 972 | " ]", 973 | "];", 974 | "@endcode" 975 | ], 976 | "scope": "php" 977 | }, 978 | "@Element (\"item\")": { 979 | "prefix": [ 980 | "@FormElement (\"item\")", 981 | "@Element (\"item\")", 982 | "item" 983 | ], 984 | "body": [ 985 | "[", 986 | " '#type' => 'item',", 987 | " '#title' => ${1|t(''),$this->t('')|},", 988 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 989 | " '#description' => ${3|t(''),$this->t('')|},", 990 | " '#required' => ${4|TRUE,FALSE|},", 991 | "]${5|\\,,;|}" 992 | ], 993 | "description": [ 994 | "Provides a display-only form element with an optional title and description.", 995 | "", 996 | "Note: since this is a read-only field, setting the #required property will do", 997 | "nothing except theme the form element to look as if it were actually required", 998 | "(i.e. by placing a red star next to the #title)." 999 | ], 1000 | "scope": "php" 1001 | }, 1002 | "@Element (\"label\")": { 1003 | "prefix": [ 1004 | "@RenderElement (\"label\")", 1005 | "@Element (\"label\")", 1006 | "label" 1007 | ], 1008 | "body": [ 1009 | "[", 1010 | " '#type' => 'label',", 1011 | "]${5|\\,,;|}" 1012 | ], 1013 | "description": [ 1014 | "Provides a render element for displaying the label for a form element.", 1015 | "", 1016 | "Labels are generated automatically from element properties during processing", 1017 | "of most form elements. This element is used internally by the form system", 1018 | "to render labels for form elements." 1019 | ], 1020 | "scope": "php" 1021 | }, 1022 | "@Element (\"language_configuration\")": { 1023 | "prefix": [ 1024 | "@FormElement (\"language_configuration\")", 1025 | "@Element (\"language_configuration\")", 1026 | "language_configuration" 1027 | ], 1028 | "body": [ 1029 | "[", 1030 | " '#type' => 'language_configuration',", 1031 | " '#title' => ${1|t(''),$this->t('')|},", 1032 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 1033 | " '#description' => ${3|t(''),$this->t('')|},", 1034 | " '#required' => ${4|TRUE,FALSE|},", 1035 | "]${5|\\,,;|}" 1036 | ], 1037 | "description": [ 1038 | "Defines an element for language configuration for a single field." 1039 | ], 1040 | "scope": "php" 1041 | }, 1042 | "@Element (\"language_select\")": { 1043 | "prefix": [ 1044 | "@FormElement (\"language_select\")", 1045 | "@Element (\"language_select\")", 1046 | "language_select" 1047 | ], 1048 | "body": [ 1049 | "[", 1050 | " '#type' => 'language_select',", 1051 | " '#title' => ${1|t(''),$this->t('')|},", 1052 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 1053 | " '#description' => ${3|t(''),$this->t('')|},", 1054 | " '#required' => ${4|TRUE,FALSE|},", 1055 | "]${5|\\,,;|}" 1056 | ], 1057 | "description": [ 1058 | "Provides a form element for selecting a language.", 1059 | "", 1060 | "This does not render an actual form element, but always returns the value of", 1061 | "the default language. It is then extended by Language module via", 1062 | "language_element_info_alter() to provide a proper language selector.", 1063 | "", 1064 | "@see language_element_info_alter()" 1065 | ], 1066 | "scope": "php" 1067 | }, 1068 | "@Element (\"layout_builder\")": { 1069 | "prefix": [ 1070 | "@RenderElement (\"layout_builder\")", 1071 | "@Element (\"layout_builder\")", 1072 | "layout_builder" 1073 | ], 1074 | "body": [ 1075 | "[", 1076 | " '#type' => 'layout_builder',", 1077 | "]${5|\\,,;|}" 1078 | ], 1079 | "description": [ 1080 | "Defines a render element for building the Layout Builder UI.", 1081 | "", 1082 | "@internal", 1083 | " Plugin classes are internal." 1084 | ], 1085 | "scope": "php" 1086 | }, 1087 | "@Element (\"link\")": { 1088 | "prefix": [ 1089 | "@RenderElement (\"link\")", 1090 | "@Element (\"link\")", 1091 | "link" 1092 | ], 1093 | "body": [ 1094 | "[", 1095 | " '#type' => 'link',", 1096 | " '#url' => '',", 1097 | "]${5|\\,,;|}" 1098 | ], 1099 | "description": [ 1100 | "Provides a link render element.", 1101 | "", 1102 | "Properties:", 1103 | "- #title: The link text.", 1104 | "- #url: \\Drupal\\Core\\Url object containing URL information pointing to an", 1105 | " internal or external link. See \\Drupal\\Core\\Utility\\LinkGeneratorInterface.", 1106 | "", 1107 | "Usage example:", 1108 | "@code", 1109 | "$build['examples_link'] = [", 1110 | " '#title' => $this->t('Examples'),", 1111 | " '#type' => 'link',", 1112 | " '#url' => \\Drupal\\Core\\Url::fromRoute('examples.description')", 1113 | "];", 1114 | "@endcode" 1115 | ], 1116 | "scope": "php" 1117 | }, 1118 | "@Element (\"machine_name\")": { 1119 | "prefix": [ 1120 | "@FormElement (\"machine_name\")", 1121 | "@Element (\"machine_name\")", 1122 | "machine_name" 1123 | ], 1124 | "body": [ 1125 | "[", 1126 | " '#type' => 'machine_name',", 1127 | " '#title' => ${1|t(''),$this->t('')|},", 1128 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 1129 | " '#description' => ${3|t(''),$this->t('')|},", 1130 | " '#required' => ${4|TRUE,FALSE|},", 1131 | " '#machine_name' => '',", 1132 | " '#maxlength' => '',", 1133 | " '#disabled' => '',", 1134 | "]${5|\\,,;|}" 1135 | ], 1136 | "description": [ 1137 | "Provides a machine name render element.", 1138 | "", 1139 | "Provides a form element to enter a machine name, which is validated to ensure", 1140 | "that the name is unique and does not contain disallowed characters.", 1141 | "", 1142 | "The element may be automatically populated via JavaScript when used in", 1143 | "conjunction with a separate \"source\" form element (typically specifying the", 1144 | "human-readable name). As the user types text into the source element, the", 1145 | "JavaScript converts all values to lower case, replaces any remaining", 1146 | "disallowed characters with a replacement, and populates the associated", 1147 | "machine name form element.", 1148 | "", 1149 | "Properties:", 1150 | "- #machine_name: An associative array containing:", 1151 | " - exists: A callable to invoke for checking whether a submitted machine", 1152 | " name value already exists. The arguments passed to the callback will be:", 1153 | " - The submitted value.", 1154 | " - The element array.", 1155 | " - The form state object.", 1156 | " In most cases, an existing API or menu argument loader function can be", 1157 | " re-used. The callback is only invoked if the submitted value differs from", 1158 | " the element's initial #default_value. The initial #default_value is", 1159 | " stored in form state so AJAX forms can be reliably validated.", 1160 | " - source: (optional) The #array_parents of the form element containing the", 1161 | " human-readable name (i.e., as contained in the $form structure) to use as", 1162 | " source for the machine name. Defaults to ['label'].", 1163 | " - label: (optional) Text to display as label for the machine name value", 1164 | " after the human-readable name form element. Defaults to t('Machine name').", 1165 | " - replace_pattern: (optional) A regular expression (without delimiters)", 1166 | " matching disallowed characters in the machine name. Defaults to", 1167 | " '[^a-z0-9_]+'.", 1168 | " - replace: (optional) A character to replace disallowed characters in the", 1169 | " machine name via JavaScript. Defaults to '_' (underscore). When using a", 1170 | " different character, 'replace_pattern' needs to be set accordingly.", 1171 | " - error: (optional) A custom form error message string to show, if the", 1172 | " machine name contains disallowed characters.", 1173 | " - standalone: (optional) Whether the live preview should stay in its own", 1174 | " form element rather than in the suffix of the source element. The source", 1175 | " element must appear in the form structure before this element. Defaults", 1176 | " to FALSE.", 1177 | "- #maxlength: (optional) Maximum allowed length of the machine name. Defaults", 1178 | " to 64.", 1179 | "- #disabled: (optional) Should be set to TRUE if an existing machine name", 1180 | " must not be changed after initial creation.", 1181 | "", 1182 | "Usage example:", 1183 | "@code", 1184 | "$form['id'] = [", 1185 | " '#type' => 'machine_name',", 1186 | " '#default_value' => $this->entity->id(),", 1187 | " '#disabled' => !$this->entity->isNew(),", 1188 | " '#maxlength' => 64,", 1189 | " '#description' => $this->t('A unique name for this item. It must only contain lowercase letters, numbers, and underscores.'),", 1190 | " '#machine_name' => [", 1191 | " 'exists' => [$this, 'exists'],", 1192 | " ],", 1193 | "];", 1194 | "@endcode", 1195 | "", 1196 | "@see \\Drupal\\Core\\Render\\Element\\Textfield" 1197 | ], 1198 | "scope": "php" 1199 | }, 1200 | "@Element (\"managed_file\")": { 1201 | "prefix": [ 1202 | "@FormElement (\"managed_file\")", 1203 | "@Element (\"managed_file\")", 1204 | "managed_file" 1205 | ], 1206 | "body": [ 1207 | "[", 1208 | " '#type' => 'managed_file',", 1209 | " '#title' => ${1|t(''),$this->t('')|},", 1210 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 1211 | " '#description' => ${3|t(''),$this->t('')|},", 1212 | " '#required' => ${4|TRUE,FALSE|},", 1213 | "]${5|\\,,;|}" 1214 | ], 1215 | "description": [ 1216 | "Provides an AJAX/progress aware widget for uploading and saving a file." 1217 | ], 1218 | "scope": "php" 1219 | }, 1220 | "@Element (\"more_link\")": { 1221 | "prefix": [ 1222 | "@RenderElement (\"more_link\")", 1223 | "@Element (\"more_link\")", 1224 | "more_link" 1225 | ], 1226 | "body": [ 1227 | "[", 1228 | " '#type' => 'more_link',", 1229 | "]${5|\\,,;|}" 1230 | ], 1231 | "description": [ 1232 | "Provides a link render element for a \"more\" link, like those used in blocks.", 1233 | "", 1234 | "Properties:", 1235 | "- #title: The text of the link to generate (defaults to 'More').", 1236 | "", 1237 | "See \\Drupal\\Core\\Render\\Element\\Link for additional properties.", 1238 | "", 1239 | "Usage Example:", 1240 | "@code", 1241 | "$build['more'] = [", 1242 | " '#type' => 'more_link',", 1243 | " '#url' => Url::fromRoute('examples.more_examples')", 1244 | "]", 1245 | "@endcode" 1246 | ], 1247 | "scope": "php" 1248 | }, 1249 | "@Element (\"number\")": { 1250 | "prefix": [ 1251 | "@FormElement (\"number\")", 1252 | "@Element (\"number\")", 1253 | "number" 1254 | ], 1255 | "body": [ 1256 | "[", 1257 | " '#type' => 'number',", 1258 | " '#title' => ${1|t(''),$this->t('')|},", 1259 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 1260 | " '#description' => ${3|t(''),$this->t('')|},", 1261 | " '#required' => ${4|TRUE,FALSE|},", 1262 | " '#default_value' => '',", 1263 | " '#min' => '',", 1264 | " '#max' => '',", 1265 | " '#step' => '',", 1266 | "]${5|\\,,;|}" 1267 | ], 1268 | "description": [ 1269 | "Provides a form element for numeric input, with special numeric validation.", 1270 | "", 1271 | "Properties:", 1272 | "- #default_value: A valid floating point number.", 1273 | "- #min: Minimum value.", 1274 | "- #max: Maximum value.", 1275 | "- #step: Ensures that the number is an even multiple of step, offset by #min", 1276 | " if specified. A #min of 1 and a #step of 2 would allow values of 1, 3, 5,", 1277 | " etc.", 1278 | "", 1279 | "Usage example:", 1280 | "@code", 1281 | "$form['quantity'] = [", 1282 | " '#type' => 'number',", 1283 | " '#title' => $this->t('Quantity'),", 1284 | "];", 1285 | "@endcode", 1286 | "", 1287 | "@see \\Drupal\\Core\\Render\\Element\\Range", 1288 | "@see \\Drupal\\Core\\Render\\Element\\Textfield" 1289 | ], 1290 | "scope": "php" 1291 | }, 1292 | "@Element (\"operations\")": { 1293 | "prefix": [ 1294 | "@RenderElement (\"operations\")", 1295 | "@Element (\"operations\")", 1296 | "operations" 1297 | ], 1298 | "body": [ 1299 | "[", 1300 | " '#type' => 'operations',", 1301 | "]${5|\\,,;|}" 1302 | ], 1303 | "description": [ 1304 | "Provides a render element for a set of operations links.", 1305 | "", 1306 | "This is a special case of \\Drupal\\Core\\Render\\Element\\Dropbutton; the only", 1307 | "difference is that it offers themes the possibility to render it differently", 1308 | "through a theme suggestion.", 1309 | "", 1310 | "@see \\Drupal|Core\\Render\\Element\\DropButton" 1311 | ], 1312 | "scope": "php" 1313 | }, 1314 | "@Element (\"page\")": { 1315 | "prefix": [ 1316 | "@RenderElement (\"page\")", 1317 | "@Element (\"page\")", 1318 | "page" 1319 | ], 1320 | "body": [ 1321 | "[", 1322 | " '#type' => 'page',", 1323 | "]${5|\\,,;|}" 1324 | ], 1325 | "description": [ 1326 | "Provides a render element for the content of an HTML page.", 1327 | "", 1328 | "This represents the \"main part\" of the HTML page's body; see html.html.twig.", 1329 | " */" 1330 | ], 1331 | "scope": "php" 1332 | }, 1333 | "@Element (\"page_title\")": { 1334 | "prefix": [ 1335 | "@RenderElement (\"page_title\")", 1336 | "@Element (\"page_title\")", 1337 | "page_title" 1338 | ], 1339 | "body": [ 1340 | "[", 1341 | " '#type' => 'page_title',", 1342 | "]${5|\\,,;|}" 1343 | ], 1344 | "description": [ 1345 | "Provides a render element for the title of an HTML page.", 1346 | "", 1347 | "This represents the title of the HTML page's body." 1348 | ], 1349 | "scope": "php" 1350 | }, 1351 | "@Element (\"pager\")": { 1352 | "prefix": [ 1353 | "@RenderElement (\"pager\")", 1354 | "@Element (\"pager\")", 1355 | "pager" 1356 | ], 1357 | "body": [ 1358 | "[", 1359 | " '#type' => 'pager',", 1360 | " '#element' => '',", 1361 | " '#pagination_heading_level' => '',", 1362 | " '#parameters' => '',", 1363 | " '#quantity' => '',", 1364 | " '#tags' => '',", 1365 | " '#route_name' => '',", 1366 | "]${5|\\,,;|}" 1367 | ], 1368 | "description": [ 1369 | "Provides a render element for a pager.", 1370 | "", 1371 | "The pager must be initialized with a call to", 1372 | "\\Drupal\\Core\\Pager\\PagerManagerInterface::createPager() in order to render", 1373 | "properly. When used with database queries, this is performed for you when you", 1374 | "extend a select query with \\Drupal\\Core\\Database\\Query\\PagerSelectExtender.", 1375 | "", 1376 | "Properties:", 1377 | "- #element: (optional, int) The pager ID, to distinguish between multiple", 1378 | " pagers on the same page (defaults to 0).", 1379 | "- #pagination_heading_level: (optional) A heading level for the pager.", 1380 | "- #parameters: (optional) An associative array of query string parameters to", 1381 | " append to the pager.", 1382 | "- #quantity: The maximum number of numbered page links to create (defaults", 1383 | " to 9).", 1384 | "- #tags: (optional) An array of labels for the controls in the pages.", 1385 | "- #route_name: (optional) The name of the route to be used to build pager", 1386 | " links. Defaults to '', which will make links relative to the current", 1387 | " URL. This makes the page more effectively cacheable.", 1388 | "", 1389 | "@code", 1390 | "$build['pager'] = [", 1391 | " '#type' => 'pager',", 1392 | "];", 1393 | "@endcode" 1394 | ], 1395 | "scope": "php" 1396 | }, 1397 | "@Element (\"password\")": { 1398 | "prefix": [ 1399 | "@FormElement (\"password\")", 1400 | "@Element (\"password\")", 1401 | "password" 1402 | ], 1403 | "body": [ 1404 | "[", 1405 | " '#type' => 'password',", 1406 | " '#title' => ${1|t(''),$this->t('')|},", 1407 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 1408 | " '#description' => ${3|t(''),$this->t('')|},", 1409 | " '#required' => ${4|TRUE,FALSE|},", 1410 | " '#size' => '',", 1411 | " '#pattern' => '',", 1412 | "]${5|\\,,;|}" 1413 | ], 1414 | "description": [ 1415 | "Provides a form element for entering a password, with hidden text.", 1416 | "", 1417 | "Properties:", 1418 | "- #size: The size of the input element in characters.", 1419 | "- #pattern: A string for the native HTML5 pattern attribute.", 1420 | "", 1421 | "Usage example:", 1422 | "@code", 1423 | "$form['pass'] = [", 1424 | " '#type' => 'password',", 1425 | " '#title' => $this->t('Password'),", 1426 | " '#size' => 25,", 1427 | " '#pattern' => '[01]+',", 1428 | "];", 1429 | "@endcode", 1430 | "", 1431 | "@see \\Drupal\\Core\\Render\\Element\\PasswordConfirm", 1432 | "@see \\Drupal\\Core\\Render\\Element\\Textfield" 1433 | ], 1434 | "scope": "php" 1435 | }, 1436 | "@Element (\"password_confirm\")": { 1437 | "prefix": [ 1438 | "@FormElement (\"password_confirm\")", 1439 | "@Element (\"password_confirm\")", 1440 | "password_confirm" 1441 | ], 1442 | "body": [ 1443 | "[", 1444 | " '#type' => 'password_confirm',", 1445 | " '#title' => ${1|t(''),$this->t('')|},", 1446 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 1447 | " '#description' => ${3|t(''),$this->t('')|},", 1448 | " '#required' => ${4|TRUE,FALSE|},", 1449 | " '#size' => '',", 1450 | "]${5|\\,,;|}" 1451 | ], 1452 | "description": [ 1453 | "Provides a form element for double-input of passwords.", 1454 | "", 1455 | "Formats as a pair of password fields, which do not validate unless the two", 1456 | "entered passwords match.", 1457 | "", 1458 | "Properties:", 1459 | "- #size: The size of the input element in characters.", 1460 | "", 1461 | "Usage example:", 1462 | "@code", 1463 | "$form['pass'] = [", 1464 | " '#type' => 'password_confirm',", 1465 | " '#title' => $this->t('Password'),", 1466 | " '#size' => 25,", 1467 | "];", 1468 | "@endcode", 1469 | "", 1470 | "@see \\Drupal\\Core\\Render\\Element\\Password" 1471 | ], 1472 | "scope": "php" 1473 | }, 1474 | "@Element (\"path\")": { 1475 | "prefix": [ 1476 | "@FormElement (\"path\")", 1477 | "@Element (\"path\")", 1478 | "path" 1479 | ], 1480 | "body": [ 1481 | "[", 1482 | " '#type' => 'path',", 1483 | " '#title' => ${1|t(''),$this->t('')|},", 1484 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 1485 | " '#description' => ${3|t(''),$this->t('')|},", 1486 | " '#required' => ${4|TRUE,FALSE|},", 1487 | "]${5|\\,,;|}" 1488 | ], 1489 | "description": [ 1490 | "Provides a matched path render element.", 1491 | "", 1492 | "Provides a form element to enter a path which can be optionally validated and", 1493 | "stored as either a \\Drupal\\Core\\Url value object or an array containing a", 1494 | "route name and route parameters pair." 1495 | ], 1496 | "scope": "php" 1497 | }, 1498 | "@Element (\"processed_text\")": { 1499 | "prefix": [ 1500 | "@RenderElement (\"processed_text\")", 1501 | "@Element (\"processed_text\")", 1502 | "processed_text" 1503 | ], 1504 | "body": [ 1505 | "[", 1506 | " '#type' => 'processed_text',", 1507 | "]${5|\\,,;|}" 1508 | ], 1509 | "description": [ 1510 | "Provides a processed text render element." 1511 | ], 1512 | "scope": "php" 1513 | }, 1514 | "@Element (\"radio\")": { 1515 | "prefix": [ 1516 | "@FormElement (\"radio\")", 1517 | "@Element (\"radio\")", 1518 | "radio" 1519 | ], 1520 | "body": [ 1521 | "[", 1522 | " '#type' => 'radio',", 1523 | " '#title' => ${1|t(''),$this->t('')|},", 1524 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 1525 | " '#description' => ${3|t(''),$this->t('')|},", 1526 | " '#required' => ${4|TRUE,FALSE|},", 1527 | "]${5|\\,,;|}" 1528 | ], 1529 | "description": [ 1530 | "Provides a form element for a single radio button.", 1531 | "", 1532 | "This is an internal element that is primarily used to render the radios form", 1533 | "element. Refer to \\Drupal\\Core\\Render\\Element\\Radios for more documentation.", 1534 | "", 1535 | "@see \\Drupal\\Core\\Render\\Element\\Radios", 1536 | "@see \\Drupal\\Core\\Render\\Element\\Checkbox" 1537 | ], 1538 | "scope": "php" 1539 | }, 1540 | "@Element (\"radios\")": { 1541 | "prefix": [ 1542 | "@FormElement (\"radios\")", 1543 | "@Element (\"radios\")", 1544 | "radios" 1545 | ], 1546 | "body": [ 1547 | "[", 1548 | " '#type' => 'radios',", 1549 | " '#title' => ${1|t(''),$this->t('')|},", 1550 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 1551 | " '#description' => ${3|t(''),$this->t('')|},", 1552 | " '#required' => ${4|TRUE,FALSE|},", 1553 | " '#options' => '',", 1554 | "]${5|\\,,;|}" 1555 | ], 1556 | "description": [ 1557 | "Provides a form element for a set of radio buttons.", 1558 | "", 1559 | "Properties:", 1560 | "- #options: An associative array, where the keys are the returned values for", 1561 | " each radio button, and the values are the labels next to each radio button.", 1562 | "", 1563 | "Usage example:", 1564 | "@code", 1565 | "$form['settings']['active'] = [", 1566 | " '#type' => 'radios',", 1567 | " '#title' => $this->t('Poll status'),", 1568 | " '#default_value' => 1,", 1569 | " '#options' => [0 => $this->t('Closed'), 1 => $this->t('Active')],", 1570 | "];", 1571 | "@endcode", 1572 | "", 1573 | "Element properties may be set on single option items as follows.", 1574 | "", 1575 | "@code", 1576 | "$form['settings']['active'][0]['#description'] = $this->t('Description for the Closed option.');", 1577 | "@endcode", 1578 | "", 1579 | "@see \\Drupal\\Core\\Render\\Element\\Checkboxes", 1580 | "@see \\Drupal\\Core\\Render\\Element\\Radio", 1581 | "@see \\Drupal\\Core\\Render\\Element\\Select" 1582 | ], 1583 | "scope": "php" 1584 | }, 1585 | "@Element (\"range\")": { 1586 | "prefix": [ 1587 | "@FormElement (\"range\")", 1588 | "@Element (\"range\")", 1589 | "range" 1590 | ], 1591 | "body": [ 1592 | "[", 1593 | " '#type' => 'range',", 1594 | " '#title' => ${1|t(''),$this->t('')|},", 1595 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 1596 | " '#description' => ${3|t(''),$this->t('')|},", 1597 | " '#required' => ${4|TRUE,FALSE|},", 1598 | " '#min' => '',", 1599 | " '#max' => '',", 1600 | "]${5|\\,,;|}" 1601 | ], 1602 | "description": [ 1603 | "Provides a slider for input of a number within a specific range.", 1604 | "", 1605 | "Provides an HTML5 input element with type of \"range\".", 1606 | "", 1607 | "Properties:", 1608 | "- #min: Minimum value (defaults to 0).", 1609 | "- #max: Maximum value (defaults to 100).", 1610 | "Refer to \\Drupal\\Core\\Render\\Element\\Number for additional properties.", 1611 | "", 1612 | "Usage example:", 1613 | "@code", 1614 | "$form['quantity'] = [", 1615 | " '#type' => 'range',", 1616 | " '#title' => $this->t('Quantity'),", 1617 | "];", 1618 | "@endcode", 1619 | "", 1620 | "@see \\Drupal\\Core\\Render\\Element\\Number" 1621 | ], 1622 | "scope": "php" 1623 | }, 1624 | "@Element (\"responsive_image\")": { 1625 | "prefix": [ 1626 | "@RenderElement (\"responsive_image\")", 1627 | "@Element (\"responsive_image\")", 1628 | "responsive_image" 1629 | ], 1630 | "body": [ 1631 | "[", 1632 | " '#type' => 'responsive_image',", 1633 | "]${5|\\,,;|}" 1634 | ], 1635 | "description": [ 1636 | "Provides a responsive image element." 1637 | ], 1638 | "scope": "php" 1639 | }, 1640 | "@Element (\"search\")": { 1641 | "prefix": [ 1642 | "@FormElement (\"search\")", 1643 | "@Element (\"search\")", 1644 | "search" 1645 | ], 1646 | "body": [ 1647 | "[", 1648 | " '#type' => 'search',", 1649 | " '#title' => ${1|t(''),$this->t('')|},", 1650 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 1651 | " '#description' => ${3|t(''),$this->t('')|},", 1652 | " '#required' => ${4|TRUE,FALSE|},", 1653 | "]${5|\\,,;|}" 1654 | ], 1655 | "description": [ 1656 | "Provides an HTML5 input element with type of \"search\".", 1657 | "", 1658 | "Usage example:", 1659 | "@code", 1660 | "$form['search'] = [", 1661 | " '#type' => 'search',", 1662 | " '#title' => $this->t('Search'),", 1663 | "];", 1664 | "@endcode", 1665 | "", 1666 | "@see \\Drupal\\Core\\Render\\Element\\Textfield" 1667 | ], 1668 | "scope": "php" 1669 | }, 1670 | "@Element (\"select\")": { 1671 | "prefix": [ 1672 | "@FormElement (\"select\")", 1673 | "@Element (\"select\")", 1674 | "select" 1675 | ], 1676 | "body": [ 1677 | "[", 1678 | " '#type' => 'select',", 1679 | " '#title' => ${1|t(''),$this->t('')|},", 1680 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 1681 | " '#description' => ${3|t(''),$this->t('')|},", 1682 | " '#required' => ${4|TRUE,FALSE|},", 1683 | " '#options' => '',", 1684 | " '#sort_options' => '',", 1685 | " '#sort_start' => '',", 1686 | " '#empty_option' => '',", 1687 | " '#empty_value' => '',", 1688 | " '#multiple' => '',", 1689 | " '#default_value' => '',", 1690 | " '#size' => '',", 1691 | "]${5|\\,,;|}" 1692 | ], 1693 | "description": [ 1694 | "Provides a form element for a drop-down menu or scrolling selection box.", 1695 | "", 1696 | "Properties:", 1697 | "- #options: An associative array of options for the select. Do not use", 1698 | " placeholders that sanitize data in any labels, as doing so will lead to", 1699 | " double-escaping. Each array value can be:", 1700 | " - A single translated string representing an HTML option element, where", 1701 | " the outer array key is the option value and the translated string array", 1702 | " value is the option label. The option value will be visible in the HTML", 1703 | " and can be modified by malicious users, so it should not contain", 1704 | " sensitive information and should be treated as possibly malicious data in", 1705 | " processing.", 1706 | " - An array representing an HTML optgroup element. The outer array key", 1707 | " should be a translated string, and is used as the label for the group.", 1708 | " The inner array contains the options for the group (with the keys as", 1709 | " option values, and translated string values as option labels). Nesting", 1710 | " option groups is not supported.", 1711 | " - An object with an 'option' property. In this case, the outer array key", 1712 | " is ignored, and the contents of the 'option' property are interpreted as", 1713 | " an array of options to be merged with any other regular options and", 1714 | " option groups found in the outer array.", 1715 | "- #sort_options: (optional) If set to TRUE (default is FALSE), sort the", 1716 | " options by their labels, after rendering and translation is complete.", 1717 | " Can be set within an option group to sort that group.", 1718 | "- #sort_start: (optional) Option index to start sorting at, where 0 is the", 1719 | " first option. Can be used within an option group. If an empty option is", 1720 | " being added automatically (see #empty_option and #empty_value properties),", 1721 | " this defaults to 1 to keep the empty option at the top of the list.", 1722 | " Otherwise, it defaults to 0.", 1723 | "- #empty_option: (optional) The label to show for the first default option.", 1724 | " By default, the label is automatically set to \"- Select -\" for a required", 1725 | " field and \"- None -\" for an optional field.", 1726 | "- #empty_value: (optional) The value for the first default option, which is", 1727 | " used to determine whether the user submitted a value or not.", 1728 | " - If #required is TRUE, this defaults to '' (an empty string).", 1729 | " - If #required is not TRUE and this value isn't set, then no extra option", 1730 | " is added to the select control, leaving the control in a slightly", 1731 | " illogical state, because there's no way for the user to select nothing,", 1732 | " since all user agents automatically preselect the first available", 1733 | " option. But people are used to this being the behavior of select", 1734 | " controls.", 1735 | " @todo Address the above issue in Drupal 8.", 1736 | " - If #required is not TRUE and this value is set (most commonly to an", 1737 | " empty string), then an extra option (see #empty_option above)", 1738 | " representing a \"non-selection\" is added with this as its value.", 1739 | "- #multiple: (optional) Indicates whether one or more options can be", 1740 | " selected. Defaults to FALSE.", 1741 | "- #default_value: Must be NULL or not set in case there is no value for the", 1742 | " element yet, in which case a first default option is inserted by default.", 1743 | " Whether this first option is a valid option depends on whether the field", 1744 | " is #required or not.", 1745 | "- #required: (optional) Whether the user needs to select an option (TRUE)", 1746 | " or not (FALSE). Defaults to FALSE.", 1747 | "- #size: The number of rows in the list that should be visible at one time.", 1748 | "", 1749 | "Usage example:", 1750 | "@code", 1751 | "$form['example_select'] = [", 1752 | " '#type' => 'select',", 1753 | " '#title' => $this->t('Select element'),", 1754 | " '#options' => [", 1755 | " '1' => $this->t('One'),", 1756 | " '2' => [", 1757 | " '2.1' => $this->t('Two point one'),", 1758 | " '2.2' => $this->t('Two point two'),", 1759 | " ],", 1760 | " '3' => $this->t('Three'),", 1761 | " ],", 1762 | "];", 1763 | "@endcode" 1764 | ], 1765 | "scope": "php" 1766 | }, 1767 | "@Element (\"status_messages\")": { 1768 | "prefix": [ 1769 | "@RenderElement (\"status_messages\")", 1770 | "@Element (\"status_messages\")", 1771 | "status_messages" 1772 | ], 1773 | "body": [ 1774 | "[", 1775 | " '#type' => 'status_messages',", 1776 | "]${5|\\,,;|}" 1777 | ], 1778 | "description": [ 1779 | "Provides a messages element.", 1780 | "", 1781 | "Used to display results of \\Drupal::messenger()->addMessage() calls.", 1782 | "", 1783 | "Usage example:", 1784 | "@code", 1785 | "$build['status_messages'] = [", 1786 | " '#type' => 'status_messages',", 1787 | "];", 1788 | "@endcode" 1789 | ], 1790 | "scope": "php" 1791 | }, 1792 | "@Element (\"status_report\")": { 1793 | "prefix": [ 1794 | "@RenderElement (\"status_report\")", 1795 | "@Element (\"status_report\")", 1796 | "status_report" 1797 | ], 1798 | "body": [ 1799 | "[", 1800 | " '#type' => 'status_report',", 1801 | "]${5|\\,,;|}" 1802 | ], 1803 | "description": [ 1804 | "Creates status report page element." 1805 | ], 1806 | "scope": "php" 1807 | }, 1808 | "@Element (\"status_report_page\")": { 1809 | "prefix": [ 1810 | "@RenderElement (\"status_report_page\")", 1811 | "@Element (\"status_report_page\")", 1812 | "status_report_page" 1813 | ], 1814 | "body": [ 1815 | "[", 1816 | " '#type' => 'status_report_page',", 1817 | "]${5|\\,,;|}" 1818 | ], 1819 | "description": [ 1820 | "Creates status report page element." 1821 | ], 1822 | "scope": "php" 1823 | }, 1824 | "@Element (\"submit\")": { 1825 | "prefix": [ 1826 | "@FormElement (\"submit\")", 1827 | "@Element (\"submit\")", 1828 | "submit" 1829 | ], 1830 | "body": [ 1831 | "[", 1832 | " '#type' => 'submit',", 1833 | " '#title' => ${1|t(''),$this->t('')|},", 1834 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 1835 | " '#description' => ${3|t(''),$this->t('')|},", 1836 | " '#required' => ${4|TRUE,FALSE|},", 1837 | " '#submit' => '',", 1838 | " '#value' => '',", 1839 | "]${5|\\,,;|}" 1840 | ], 1841 | "description": [ 1842 | "Provides a form submit button.", 1843 | "", 1844 | "Submit buttons are processed the same as regular buttons, except they trigger", 1845 | "the form's submit handler.", 1846 | "", 1847 | "Properties:", 1848 | "- #submit: Specifies an alternate callback for form submission when the", 1849 | " submit button is pressed. Use '::methodName' format or an array containing", 1850 | " the object and method name (for example, [ $this, 'methodName'] ).", 1851 | "- #value: The text to be shown on the button.", 1852 | "", 1853 | "Usage Example:", 1854 | "@code", 1855 | "$form['actions']['submit'] = [", 1856 | " '#type' => 'submit',", 1857 | " '#value' => $this->t('Save'),", 1858 | "];", 1859 | "@endcode", 1860 | "", 1861 | "@see \\Drupal\\Core\\Render\\Element\\Button" 1862 | ], 1863 | "scope": "php" 1864 | }, 1865 | "@Element (\"system_compact_link\")": { 1866 | "prefix": [ 1867 | "@RenderElement (\"system_compact_link\")", 1868 | "@Element (\"system_compact_link\")", 1869 | "system_compact_link" 1870 | ], 1871 | "body": [ 1872 | "[", 1873 | " '#type' => 'system_compact_link',", 1874 | "]${5|\\,,;|}" 1875 | ], 1876 | "description": [ 1877 | "Provides a link to show or hide help text on administration pages.", 1878 | "", 1879 | "Usage example:", 1880 | "@code", 1881 | "$form['system_compact_link'] = [", 1882 | " '#type' => 'system_compact_link',", 1883 | "];", 1884 | "@endcode" 1885 | ], 1886 | "scope": "php" 1887 | }, 1888 | "@Element (\"table\")": { 1889 | "prefix": [ 1890 | "@FormElement (\"table\")", 1891 | "@Element (\"table\")", 1892 | "table" 1893 | ], 1894 | "body": [ 1895 | "[", 1896 | " '#type' => 'table',", 1897 | " '#title' => ${1|t(''),$this->t('')|},", 1898 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 1899 | " '#description' => ${3|t(''),$this->t('')|},", 1900 | " '#required' => ${4|TRUE,FALSE|},", 1901 | " '#header' => '',", 1902 | " '#rows' => '',", 1903 | " '#empty' => '',", 1904 | " '#responsive' => '',", 1905 | " '#sticky' => '',", 1906 | " '#footer' => '',", 1907 | " '#caption' => '',", 1908 | "]${5|\\,,;|}" 1909 | ], 1910 | "description": [ 1911 | "Provides a render element for a table.", 1912 | "", 1913 | "Note: Although this extends FormElementBase, it can be used outside the", 1914 | "context of a form.", 1915 | "", 1916 | "Properties:", 1917 | "- #header: An array of table header labels.", 1918 | "- #rows: An array of the rows to be displayed. Each row is either an array", 1919 | " of cell contents or an array of properties as described in table.html.twig", 1920 | " Alternatively specify the data for the table as child elements of the table", 1921 | " element. Table elements would contain rows elements that would in turn", 1922 | " contain column elements.", 1923 | "- #empty: Text to display when no rows are present.", 1924 | "- #responsive: Indicates whether to add the drupal.tableresponsive library", 1925 | " providing responsive tables. Defaults to TRUE.", 1926 | "- #sticky: Indicates whether to make the table headers sticky at", 1927 | " the top of the page. Defaults to FALSE.", 1928 | "- #footer: Table footer rows, in the same format as the #rows property.", 1929 | "- #caption: A localized string for the tag.", 1930 | "", 1931 | "Usage example 1: A simple form with an additional information table which", 1932 | "doesn't include any other form field.", 1933 | "@code", 1934 | "// Table header.", 1935 | "$header = [", 1936 | " 'name' => $this->t('Name'),", 1937 | " 'age' => $this->t('Age'),", 1938 | " 'email' => $this->t('Email'),", 1939 | "];", 1940 | "", 1941 | "// Default data rows (these can be fetched from the database or any other", 1942 | "// source).", 1943 | "$default_rows = [", 1944 | " ['name' => 'John', 'age' => 28, 'email' => 'john@example.com'],", 1945 | " ['name' => 'Jane', 'age' => 25, 'email' => 'jane@example.com'],", 1946 | "];", 1947 | "", 1948 | "// Prepare rows for the table element. We just display the information with", 1949 | "// #markup.", 1950 | "$rows = [];", 1951 | "foreach ($default_rows as $default_row) {", 1952 | " $rows[] = [", 1953 | " 'name' => ['data' => ['#markup' => $default_row['name']]],", 1954 | " 'age' => ['data' => ['#markup' => $default_row['age']]],", 1955 | " 'email' => ['data' => ['#markup' => $default_row['email']]],", 1956 | " ];", 1957 | "}", 1958 | "", 1959 | "// Now set the table element.", 1960 | "$form['information'] = [", 1961 | " '#type' => 'table',", 1962 | " '#header' => $header,", 1963 | " '#rows' => $rows, // Add the prepared rows here.", 1964 | " '#empty' => $this->t('No entries available.'),", 1965 | "];", 1966 | "@endcode", 1967 | "", 1968 | "Usage example 2: A table of form fields without the #rows property defined.", 1969 | "@code", 1970 | "// Set the contact element as a table render element with no #rows property.", 1971 | "// Next add five rows as sub-elements (or children) that will populate", 1972 | "// automatically the #rows property in preRenderTable().", 1973 | "$form['contacts'] = [", 1974 | " '#type' => 'table',", 1975 | " '#caption' => $this->t('Sample Table'),", 1976 | " '#header' => [$this->t('Name'), $this->t('Phone')],", 1977 | " '#rows' => [],", 1978 | " '#empty' => $this->t('No entries available.'),", 1979 | "];", 1980 | "", 1981 | "// Add arbitrarily four rows to the table. Each row contains two fields", 1982 | "// (name and phone). The preRenderTable() method will add each sub-element", 1983 | "// (or children) of the table element to the #rows property.", 1984 | "for ($i = 1; $i <= 4; $i++) {", 1985 | " // Add foo and baz classes for each row.", 1986 | " $form['contacts'][$i]['#attributes'] = ['class' => ['foo', 'baz']];", 1987 | "", 1988 | " // Set the first column.", 1989 | " $form['contacts'][$i]['name'] = [", 1990 | " '#type' => 'textfield',", 1991 | " '#title' => $this->t('Name'),", 1992 | " '#title_display' => 'invisible',", 1993 | " ];", 1994 | "", 1995 | " // Set the second column.", 1996 | " $form['contacts'][$i]['phone'] = [", 1997 | " '#type' => 'tel',", 1998 | " '#title' => $this->t('Phone'),", 1999 | " '#title_display' => 'invisible',", 2000 | " ];", 2001 | "}", 2002 | "", 2003 | "// Add the fifth row as a colspan of two columns.", 2004 | "$form['contacts'][]['colspan_example'] = [", 2005 | " '#plain_text' => 'Colspan Example',", 2006 | " '#wrapper_attributes' => ['colspan' => 2, 'class' => ['foo', 'bar']],", 2007 | "];", 2008 | "@endcode", 2009 | "@see \\Drupal\\Core\\Render\\Element\\Tableselect" 2010 | ], 2011 | "scope": "php" 2012 | }, 2013 | "@Element (\"tableselect\")": { 2014 | "prefix": [ 2015 | "@FormElement (\"tableselect\")", 2016 | "@Element (\"tableselect\")", 2017 | "tableselect" 2018 | ], 2019 | "body": [ 2020 | "[", 2021 | " '#type' => 'tableselect',", 2022 | " '#title' => ${1|t(''),$this->t('')|},", 2023 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 2024 | " '#description' => ${3|t(''),$this->t('')|},", 2025 | " '#required' => ${4|TRUE,FALSE|},", 2026 | " '#header' => '',", 2027 | " '#options' => '',", 2028 | " '#empty' => '',", 2029 | " '#multiple' => '',", 2030 | " '#js_select' => '',", 2031 | "]${5|\\,,;|}" 2032 | ], 2033 | "description": [ 2034 | "Provides a form element for a table with radios or checkboxes in left column.", 2035 | "", 2036 | "Properties:", 2037 | "- #header: An array of table header labels.", 2038 | "- #options: An associative array where each key is the value returned when", 2039 | " a user selects the radio button or checkbox, and each value is the row of", 2040 | " table data.", 2041 | "- #empty: The message to display if table does not have any options.", 2042 | "- #multiple: Set to FALSE to render the table with radios instead checkboxes.", 2043 | "- #js_select: Set to FALSE if you don't want the select all checkbox added to", 2044 | " the header.", 2045 | "", 2046 | "Other properties of the \\Drupal\\Core\\Render\\Element\\Table element are also", 2047 | "available.", 2048 | "", 2049 | "Usage example:", 2050 | "@code", 2051 | "$header = [", 2052 | " 'color' => $this->t('Color'),", 2053 | " 'shape' => $this->t('Shape'),", 2054 | "];", 2055 | "", 2056 | "$options = [", 2057 | " 1 => ['color' => 'Red', 'shape' => 'Triangle'],", 2058 | " 2 => ['color' => 'Green', 'shape' => 'Square'],", 2059 | " // Prevent users from selecting a row by adding a '#disabled' property set", 2060 | " // to TRUE.", 2061 | " 3 => ['color' => 'Blue', 'shape' => 'Hexagon', '#disabled' => TRUE],", 2062 | "];", 2063 | "", 2064 | "$form['table'] = [", 2065 | " '#type' => 'tableselect',", 2066 | " '#header' => $header,", 2067 | " '#options' => $options,", 2068 | " '#empty' => $this->t('No shapes found'),", 2069 | "];", 2070 | "@endcode", 2071 | "", 2072 | "See https://www.drupal.org/node/945102 for a full explanation.", 2073 | "", 2074 | "@see \\Drupal\\Core\\Render\\Element\\Table" 2075 | ], 2076 | "scope": "php" 2077 | }, 2078 | "@Element (\"tel\")": { 2079 | "prefix": [ 2080 | "@FormElement (\"tel\")", 2081 | "@Element (\"tel\")", 2082 | "tel" 2083 | ], 2084 | "body": [ 2085 | "[", 2086 | " '#type' => 'tel',", 2087 | " '#title' => ${1|t(''),$this->t('')|},", 2088 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 2089 | " '#description' => ${3|t(''),$this->t('')|},", 2090 | " '#required' => ${4|TRUE,FALSE|},", 2091 | " '#size' => '',", 2092 | " '#pattern' => '',", 2093 | "]${5|\\,,;|}" 2094 | ], 2095 | "description": [ 2096 | "Provides a form element for entering a telephone number.", 2097 | "", 2098 | "Provides an HTML5 input element with type of \"tel\". It provides no special", 2099 | "validation.", 2100 | "", 2101 | "Properties:", 2102 | "- #size: The size of the input element in characters.", 2103 | "- #pattern: A string for the native HTML5 pattern attribute.", 2104 | "", 2105 | "Usage example:", 2106 | "@code", 2107 | "$form['phone'] = [", 2108 | " '#type' => 'tel',", 2109 | " '#title' => $this->t('Phone'),", 2110 | " '#pattern' => '[^\\d]*',", 2111 | "];", 2112 | "@endcode", 2113 | "", 2114 | "@see \\Drupal\\Core\\Render\\Element" 2115 | ], 2116 | "scope": "php" 2117 | }, 2118 | "@Element (\"text_format\")": { 2119 | "prefix": [ 2120 | "@RenderElement (\"text_format\")", 2121 | "@Element (\"text_format\")", 2122 | "text_format" 2123 | ], 2124 | "body": [ 2125 | "[", 2126 | " '#type' => 'text_format',", 2127 | " '#base_type' => '',", 2128 | " '#format' => '',", 2129 | " '#allowed_formats' => '',", 2130 | "]${5|\\,,;|}" 2131 | ], 2132 | "description": [ 2133 | "Provides a text format render element.", 2134 | "", 2135 | "Properties:", 2136 | "- #base_type: The form element #type to use for the 'value' element.", 2137 | " 'textarea' by default.", 2138 | "- #format: (optional) The text format ID to preselect. If omitted, the", 2139 | " default format for the current user will be used.", 2140 | "- #allowed_formats: (optional) An array of text format IDs that are available", 2141 | " for this element. If omitted, all text formats that the current user has", 2142 | " access to will be allowed.", 2143 | "", 2144 | "Usage Example:", 2145 | "@code", 2146 | "$form['body'] = [", 2147 | " '#type' => 'text_format',", 2148 | " '#title' => 'Body',", 2149 | " '#format' => 'full_html',", 2150 | " '#default_value' => 'The quick brown fox jumped over the lazy dog.',", 2151 | "];", 2152 | "@endcode", 2153 | "", 2154 | "@see \\Drupal\\Core\\Render\\Element\\Textarea" 2155 | ], 2156 | "scope": "php" 2157 | }, 2158 | "@Element (\"textarea\")": { 2159 | "prefix": [ 2160 | "@FormElement (\"textarea\")", 2161 | "@Element (\"textarea\")", 2162 | "textarea" 2163 | ], 2164 | "body": [ 2165 | "[", 2166 | " '#type' => 'textarea',", 2167 | " '#title' => ${1|t(''),$this->t('')|},", 2168 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 2169 | " '#description' => ${3|t(''),$this->t('')|},", 2170 | " '#required' => ${4|TRUE,FALSE|},", 2171 | " '#rows' => '',", 2172 | " '#cols' => '',", 2173 | " '#resizable' => '',", 2174 | " '#maxlength' => '',", 2175 | "]${5|\\,,;|}" 2176 | ], 2177 | "description": [ 2178 | "Provides a form element for input of multiple-line text.", 2179 | "", 2180 | "Properties:", 2181 | "- #rows: Number of rows in the text box.", 2182 | "- #cols: Number of columns in the text box.", 2183 | "- #resizable: Controls whether the text area is resizable. Allowed values", 2184 | " are \"none\", \"vertical\", \"horizontal\", or \"both\" (defaults to \"vertical\").", 2185 | "- #maxlength: The maximum amount of characters to accept as input.", 2186 | "", 2187 | "Usage example:", 2188 | "@code", 2189 | "$form['text'] = [", 2190 | " '#type' => 'textarea',", 2191 | " '#title' => $this->t('Text'),", 2192 | "];", 2193 | "@endcode", 2194 | "", 2195 | "@see \\Drupal\\Core\\Render\\Element\\Textfield", 2196 | "@see \\Drupal\\filter\\Element\\TextFormat" 2197 | ], 2198 | "scope": "php" 2199 | }, 2200 | "@Element (\"textfield\")": { 2201 | "prefix": [ 2202 | "@FormElement (\"textfield\")", 2203 | "@Element (\"textfield\")", 2204 | "textfield" 2205 | ], 2206 | "body": [ 2207 | "[", 2208 | " '#type' => 'textfield',", 2209 | " '#title' => ${1|t(''),$this->t('')|},", 2210 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 2211 | " '#description' => ${3|t(''),$this->t('')|},", 2212 | " '#required' => ${4|TRUE,FALSE|},", 2213 | " '#maxlength' => '',", 2214 | " '#size' => '',", 2215 | " '#autocomplete_route_name' => '',", 2216 | " '#autocomplete_route_parameters' => '',", 2217 | " '#pattern' => '',", 2218 | "]${5|\\,,;|}" 2219 | ], 2220 | "description": [ 2221 | "Provides a one-line text field form element.", 2222 | "", 2223 | "Properties:", 2224 | "- #maxlength: Maximum number of characters of input allowed.", 2225 | "- #size: The size of the input element in characters.", 2226 | "- #autocomplete_route_name: A route to be used as callback URL by the", 2227 | " autocomplete JavaScript library.", 2228 | "- #autocomplete_route_parameters: An array of parameters to be used in", 2229 | " conjunction with the route name.", 2230 | "- #pattern: A string for the native HTML5 pattern attribute.", 2231 | "", 2232 | "Usage example:", 2233 | "@code", 2234 | "$form['title'] = [", 2235 | " '#type' => 'textfield',", 2236 | " '#title' => $this->t('Subject'),", 2237 | " '#default_value' => $node->title,", 2238 | " '#size' => 60,", 2239 | " '#maxlength' => 128,", 2240 | " '#pattern' => 'some-prefix-[a-z]+',", 2241 | " '#required' => TRUE,", 2242 | "];", 2243 | "@endcode", 2244 | "", 2245 | "@see \\Drupal\\Core\\Render\\Element\\Color", 2246 | "@see \\Drupal\\Core\\Render\\Element\\Email", 2247 | "@see \\Drupal\\Core\\Render\\Element\\MachineName", 2248 | "@see \\Drupal\\Core\\Render\\Element\\Number", 2249 | "@see \\Drupal\\Core\\Render\\Element\\Password", 2250 | "@see \\Drupal\\Core\\Render\\Element\\PasswordConfirm", 2251 | "@see \\Drupal\\Core\\Render\\Element\\Range", 2252 | "@see \\Drupal\\Core\\Render\\Element\\Tel", 2253 | "@see \\Drupal\\Core\\Render\\Element\\Url" 2254 | ], 2255 | "scope": "php" 2256 | }, 2257 | "@Element (\"token\")": { 2258 | "prefix": [ 2259 | "@FormElement (\"token\")", 2260 | "@Element (\"token\")", 2261 | "token" 2262 | ], 2263 | "body": [ 2264 | "[", 2265 | " '#type' => 'token',", 2266 | " '#title' => ${1|t(''),$this->t('')|},", 2267 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 2268 | " '#description' => ${3|t(''),$this->t('')|},", 2269 | " '#required' => ${4|TRUE,FALSE|},", 2270 | "]${5|\\,,;|}" 2271 | ], 2272 | "description": [ 2273 | "Stores token data in a hidden form field.", 2274 | "", 2275 | "This is generally used to protect against cross-site forgeries. A token", 2276 | "element is automatically added to each Drupal form by an implementation of", 2277 | "\\Drupal\\Core\\Form\\FormBuilderInterface::prepareForm() so you don't generally", 2278 | "have to add one yourself." 2279 | ], 2280 | "scope": "php" 2281 | }, 2282 | "@Element (\"toolbar\")": { 2283 | "prefix": [ 2284 | "@RenderElement (\"toolbar\")", 2285 | "@Element (\"toolbar\")", 2286 | "toolbar" 2287 | ], 2288 | "body": [ 2289 | "[", 2290 | " '#type' => 'toolbar',", 2291 | "]${5|\\,,;|}" 2292 | ], 2293 | "description": [ 2294 | "Provides a render element for the default Drupal toolbar." 2295 | ], 2296 | "scope": "php" 2297 | }, 2298 | "@Element (\"toolbar_item\")": { 2299 | "prefix": [ 2300 | "@RenderElement (\"toolbar_item\")", 2301 | "@Element (\"toolbar_item\")", 2302 | "toolbar_item" 2303 | ], 2304 | "body": [ 2305 | "[", 2306 | " '#type' => 'toolbar_item',", 2307 | "]${5|\\,,;|}" 2308 | ], 2309 | "description": [ 2310 | "Provides a toolbar item that is wrapped in markup for common styling.", 2311 | "", 2312 | "The 'tray' property contains a renderable array." 2313 | ], 2314 | "scope": "php" 2315 | }, 2316 | "@Element (\"url\")": { 2317 | "prefix": [ 2318 | "@FormElement (\"url\")", 2319 | "@Element (\"url\")", 2320 | "url" 2321 | ], 2322 | "body": [ 2323 | "[", 2324 | " '#type' => 'url',", 2325 | " '#title' => ${1|t(''),$this->t('')|},", 2326 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 2327 | " '#description' => ${3|t(''),$this->t('')|},", 2328 | " '#required' => ${4|TRUE,FALSE|},", 2329 | " '#default_value' => '',", 2330 | " '#size' => '',", 2331 | " '#pattern' => '',", 2332 | "]${5|\\,,;|}" 2333 | ], 2334 | "description": [ 2335 | "Provides a form element for input of a URL.", 2336 | "", 2337 | "Properties:", 2338 | "- #default_value: A valid URL string.", 2339 | "- #size: The size of the input element in characters.", 2340 | "- #pattern: A string for the native HTML5 pattern attribute.", 2341 | "", 2342 | "Usage example:", 2343 | "@code", 2344 | "$form['homepage'] = [", 2345 | " '#type' => 'url',", 2346 | " '#title' => $this->t('Home Page'),", 2347 | " '#size' => 30,", 2348 | " '#pattern' => '*.example.com',", 2349 | " ...", 2350 | "];", 2351 | "@endcode", 2352 | "", 2353 | "@see \\Drupal\\Core\\Render\\Element\\Textfield" 2354 | ], 2355 | "scope": "php" 2356 | }, 2357 | "@Element (\"value\")": { 2358 | "prefix": [ 2359 | "@FormElement (\"value\")", 2360 | "@Element (\"value\")", 2361 | "value" 2362 | ], 2363 | "body": [ 2364 | "[", 2365 | " '#type' => 'value',", 2366 | " '#title' => ${1|t(''),$this->t('')|},", 2367 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 2368 | " '#description' => ${3|t(''),$this->t('')|},", 2369 | " '#required' => ${4|TRUE,FALSE|},", 2370 | " '#value' => '',", 2371 | "]${5|\\,,;|}" 2372 | ], 2373 | "description": [ 2374 | "Provides a form element for storage of internal information.", 2375 | "", 2376 | "Unlike \\Drupal\\Core\\Render\\Element\\Hidden, this information is not sent to", 2377 | "the browser in a hidden form field, but only stored in the form array for use", 2378 | "in validation and submit processing.", 2379 | "", 2380 | "Properties:", 2381 | "- #value: The value of the form element that cannot be edited by the user.", 2382 | "", 2383 | "Usage Example:", 2384 | "@code", 2385 | "$form['entity_id'] = ['#type' => 'value', '#value' => $entity_id];", 2386 | "@endcode" 2387 | ], 2388 | "scope": "php" 2389 | }, 2390 | "@Element (\"vertical_tabs\")": { 2391 | "prefix": [ 2392 | "@FormElement (\"vertical_tabs\")", 2393 | "@Element (\"vertical_tabs\")", 2394 | "vertical_tabs" 2395 | ], 2396 | "body": [ 2397 | "[", 2398 | " '#type' => 'vertical_tabs',", 2399 | " '#title' => ${1|t(''),$this->t('')|},", 2400 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 2401 | " '#description' => ${3|t(''),$this->t('')|},", 2402 | " '#required' => ${4|TRUE,FALSE|},", 2403 | " '#default_tab' => '',", 2404 | "]${5|\\,,;|}" 2405 | ], 2406 | "description": [ 2407 | "Provides a render element for vertical tabs in a form.", 2408 | "", 2409 | "Formats all child and non-child details elements whose #group is assigned", 2410 | "this element's name as vertical tabs.", 2411 | "", 2412 | "Properties:", 2413 | "- #default_tab: The HTML ID of the rendered details element to be used as", 2414 | " the default tab. View the source of the rendered page to determine the ID.", 2415 | "", 2416 | "Usage example:", 2417 | "@code", 2418 | "$form['information'] = [", 2419 | " '#type' => 'vertical_tabs',", 2420 | " '#default_tab' => 'edit-publication',", 2421 | "];", 2422 | "", 2423 | "$form['author'] = [", 2424 | " '#type' => 'details',", 2425 | " '#title' => $this->t('Author'),", 2426 | " '#group' => 'information',", 2427 | "];", 2428 | "", 2429 | "$form['author']['name'] = [", 2430 | " '#type' => 'textfield',", 2431 | " '#title' => $this->t('Name'),", 2432 | "];", 2433 | "", 2434 | "$form['publication'] = [", 2435 | " '#type' => 'details',", 2436 | " '#title' => $this->t('Publication'),", 2437 | " '#group' => 'information',", 2438 | "];", 2439 | "", 2440 | "$form['publication']['publisher'] = [", 2441 | " '#type' => 'textfield',", 2442 | " '#title' => $this->t('Publisher'),", 2443 | "];", 2444 | "@endcode" 2445 | ], 2446 | "scope": "php" 2447 | }, 2448 | "@Element (\"view\")": { 2449 | "prefix": [ 2450 | "@RenderElement (\"view\")", 2451 | "@Element (\"view\")", 2452 | "view" 2453 | ], 2454 | "body": [ 2455 | "[", 2456 | " '#type' => 'view',", 2457 | "]${5|\\,,;|}" 2458 | ], 2459 | "description": [ 2460 | "Provides a render element to display a view." 2461 | ], 2462 | "scope": "php" 2463 | }, 2464 | "@Element (\"weight\")": { 2465 | "prefix": [ 2466 | "@FormElement (\"weight\")", 2467 | "@Element (\"weight\")", 2468 | "weight" 2469 | ], 2470 | "body": [ 2471 | "[", 2472 | " '#type' => 'weight',", 2473 | " '#title' => ${1|t(''),$this->t('')|},", 2474 | " '#title_display' => '${2|before,after,invisible,attribute|}',", 2475 | " '#description' => ${3|t(''),$this->t('')|},", 2476 | " '#required' => ${4|TRUE,FALSE|},", 2477 | " '#delta' => '',", 2478 | "]${5|\\,,;|}" 2479 | ], 2480 | "description": [ 2481 | "Provides a form element for input of a weight.", 2482 | "", 2483 | "Weights are integers used to indicate ordering, with larger numbers later in", 2484 | "the order.", 2485 | "", 2486 | "Properties:", 2487 | "- #delta: The range of possible weight values used. A delta of 10 would", 2488 | " indicate possible weight values between -10 and 10.", 2489 | "", 2490 | "Usage example:", 2491 | "@code", 2492 | "$form['weight'] = [", 2493 | " '#type' => 'weight',", 2494 | " '#title' => $this->t('Weight'),", 2495 | " '#default_value' => $edit['weight'],", 2496 | " '#delta' => 10,", 2497 | "];", 2498 | "@endcode" 2499 | ], 2500 | "scope": "php" 2501 | } 2502 | } -------------------------------------------------------------------------------- /src/formatElements.js: -------------------------------------------------------------------------------- 1 | export function formatElements(rawElements) { 2 | 3 | const formattedElements = rawElements 4 | .map(({name, type, docs}) => { 5 | 6 | // Format description text 7 | const desc = docs.value 8 | .split('\n') 9 | .map(line => { 10 | if (line !== '/**' && line !== ' */') { 11 | return line 12 | // Remove PHP comment markup 13 | .replace(/^\s\*\s{0,1}/g, '') 14 | 15 | // Special/escaped character replacement 16 | .replaceAll(""", "\"") 17 | .replaceAll(/<([^>]*)>/g, ""); 18 | } 19 | }) 20 | .filter(line => line !== undefined) 21 | 22 | const elementObj = { 23 | prefix: [`@${type} ("${name}")` ,`@Element ("${name}")` , name], 24 | body: [ 25 | `[`, 26 | ` '#type' => '${name}',`, 27 | ], 28 | description: desc, 29 | scope: 'php', 30 | } 31 | 32 | if (type == 'FormElement') { 33 | // tab stops for FormElement 34 | const titleInput = "${1|t(''),$this->t('')|}"; 35 | const titleDisplayOption = '${2|before,after,invisible,attribute|}'; 36 | const descriptionInput = "${3|t(''),$this->t('')|}"; 37 | const boolOption = '${4|TRUE,FALSE|}'; 38 | 39 | const defaultSettings = [ 40 | ` '#title' => ${titleInput},`, 41 | ` '#title_display' => '${titleDisplayOption}',`, 42 | ` '#description' => ${descriptionInput},`, 43 | ` '#required' => ${boolOption},` 44 | ]; 45 | defaultSettings.forEach(setting => { 46 | elementObj.body.push(setting); 47 | }) 48 | } 49 | 50 | // Get properties from docblock description 51 | const propertiesRegex = /Properties:(.*)(?=(@code\n))/s; 52 | const propertiesMatch = docs.value.match(propertiesRegex); 53 | const propertiesString = propertiesMatch ? propertiesMatch[1] : ''; 54 | const properties = propertiesString.match(/(#\w+):{1}/g) || []; 55 | 56 | // Push property found in description 57 | if (properties.length > 0) { 58 | properties.forEach(element => { 59 | const excludeProperties = [ 60 | '#type', 61 | '#title', 62 | '#title_display', 63 | '#description', 64 | '#required', 65 | ]; 66 | 67 | // Remove colon 68 | let property = element.slice(0, -1); 69 | if (excludeProperties.includes(property)) { 70 | // Skip adding this property 71 | return; 72 | } 73 | let newPropertyArray = ` '${property}' => '',`; 74 | elementObj.body.push(newPropertyArray) 75 | }); 76 | } 77 | 78 | // Close body 79 | elementObj.body.push(']${5|\\,,;|}'); 80 | 81 | 82 | return elementObj; 83 | }); 84 | 85 | return formattedElements; 86 | } 87 | -------------------------------------------------------------------------------- /src/formatHooks.js: -------------------------------------------------------------------------------- 1 | export function formatHooks(rawHooks) { 2 | 3 | const formattedHooks = rawHooks 4 | .map(({name, definition, docs}) => { 5 | 6 | // Parts of the function name that need replaced. 7 | const placeholders = [ 8 | 'hook', 9 | ...Array.from( 10 | name.match(/[A-Z]+(_(?=[A-Z])[A-Z]+)*/g) || [] 11 | ) 12 | ]; 13 | 14 | // Escape variable names. 15 | // @see https://code.visualstudio.com/docs/editor/userdefinedsnippets#_how-do-i-have-a-snippet-place-a-variable-in-the-pasted-script 16 | let titleWithPlaceholders = definition.replaceAll('$', '\\$'); 17 | 18 | // Create tab-stops at placeholders. 19 | placeholders.forEach((placeholder, i) => { 20 | titleWithPlaceholders = titleWithPlaceholders 21 | .replace(placeholder, `\${${i + 1}:${placeholder}}`); 22 | }) 23 | 24 | // Auto-replace `hook` with filename. 25 | titleWithPlaceholders = titleWithPlaceholders 26 | .replace("${1:hook}", "${1:${TM_FILENAME_BASE:hook}}"); 27 | 28 | // Format description text 29 | const desc = docs.value 30 | .split('\n') 31 | .map(line => { 32 | if (line !== '/**' && line !== ' */') { 33 | return line 34 | // Remove PHP comment markup 35 | .replace(/^\s\*\s{0,1}/g, '') 36 | 37 | // Special/escaped character replacement 38 | .replaceAll(""", "\"") 39 | .replaceAll(/<([^>]*)>/g, ""); 40 | } 41 | }) 42 | .filter(line => line !== undefined) 43 | 44 | const hookObj = { 45 | prefix: name, 46 | body: [ 47 | `/**`, 48 | ` * Implements ${name}().`, 49 | ` */`, 50 | `${titleWithPlaceholders} {`, 51 | ` $0`, 52 | `}` 53 | ], 54 | description: desc, 55 | scope: 'php', 56 | } 57 | 58 | // Add notices of deprecated hooks. 59 | if (docs.value.includes('@deprecated')) { 60 | hookObj.description.splice(0, 0, 'DEPRECATED', ''); 61 | hookObj.body.splice(2, 0, ' * @deprecated'); 62 | } 63 | 64 | return hookObj; 65 | }); 66 | 67 | return formattedHooks; 68 | } 69 | -------------------------------------------------------------------------------- /src/formatServices.js: -------------------------------------------------------------------------------- 1 | import engine from "php-parser"; 2 | import { readFile } from "fs/promises"; 3 | 4 | export async function formatServices(rawServices, version) { 5 | // Prepare to receive formatted hooks. 6 | const services = []; 7 | 8 | const parser = new engine({ 9 | parser: { 10 | locations: true, 11 | extractDoc: true, 12 | }, 13 | ast: { 14 | withPositions: true, 15 | withSource: true 16 | } 17 | }); 18 | 19 | // Iterate over each service. 20 | for (const service of rawServices) { 21 | const [name, value] = service; 22 | 23 | let { class: classNamespace } = value ?? {}; 24 | 25 | if (!classNamespace && value?.parent) { 26 | const parentService = rawServices.find(service => service[0] === value.parent); 27 | classNamespace = parentService[1].class; 28 | } 29 | 30 | if (!classNamespace && value?.alias) { 31 | const aliasedService = rawServices.find(service => service[0] === value.alias); 32 | classNamespace = aliasedService[1].class; 33 | } 34 | 35 | if (classNamespace && value?.public !== false) { 36 | const classFile = classNamespace.split('\\').join('/'); 37 | 38 | const deprecationWarning = value.deprecated 39 | ?.replaceAll('%alias_id%', name) 40 | ?.replaceAll('%service_id%', name); 41 | 42 | let description = []; 43 | 44 | if (classFile.startsWith('Drupal')) { 45 | const classFileContents = await readFile(`tmp/drupal-${version}/core/lib/${classFile}.php`, { 46 | encoding: 'utf-8', 47 | }); 48 | 49 | const { comments } = parser.parseCode(classFileContents); 50 | 51 | description = comments[0].value 52 | .split('\n') 53 | .map(line => { 54 | if (line !== '/**' && line !== ' */') { 55 | return line 56 | // Remove PHP comment markup 57 | .replace(/^\s\*\s{0,1}/g, '') 58 | 59 | // Special/escaped character replacement 60 | .replaceAll(""", "\"") 61 | .replaceAll(/<([^>]*)>/g, ""); 62 | } 63 | }) 64 | .filter(line => line !== undefined) 65 | } 66 | 67 | const snippet = { 68 | prefix: [ 69 | `@Service ("${name}")` 70 | ], 71 | body: [ 72 | `/**`, 73 | ` * @var ${classNamespace}`, 74 | ` */`, 75 | `\${1:\\$${name.replaceAll('.', '_')}_service} = \\Drupal::service('${name}');`, 76 | `` 77 | ], 78 | description, 79 | scope: "php", 80 | }; 81 | 82 | if (deprecationWarning) { 83 | snippet.description.splice(0, 0, 'DEPRECATED'); 84 | snippet.body.splice(2, 0, ` * @deprecated ${deprecationWarning}`); 85 | } 86 | 87 | services.push([name, snippet]); 88 | } 89 | } 90 | 91 | return services; 92 | } 93 | -------------------------------------------------------------------------------- /src/getApiFiles.js: -------------------------------------------------------------------------------- 1 | import find from "find"; 2 | 3 | export async function getApiFiles(version) { 4 | return new Promise((res) => { 5 | find.file(`tmp/drupal-${version}/`, (file) => { 6 | const filtered = file.filter((filename) => filename.endsWith('.api.php')); 7 | res(filtered); 8 | }); 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /src/getCoreVersion.js: -------------------------------------------------------------------------------- 1 | import { createWriteStream } from "fs"; 2 | import download from "download"; 3 | import tar from "tar"; 4 | 5 | const DRUPAL_URL = 'https://ftp.drupal.org/files/projects'; 6 | 7 | export async function getCoreVersion(version) { 8 | const versionFile = `drupal-${version}.tar.gz`; 9 | 10 | await download(`${DRUPAL_URL}/${versionFile}`, 'tmp'); 11 | 12 | await tar.x({ 13 | gzip: true, 14 | file: `tmp/${versionFile}`, 15 | cwd: `tmp` 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /src/getElementFiles.js: -------------------------------------------------------------------------------- 1 | import find from "find"; 2 | 3 | function filterElementFiles(files) { 4 | return files.filter((filename) => ( 5 | filename.match(/\/Element\/[^\.]*\.php/g) 6 | )); 7 | } 8 | 9 | export async function getElementFiles(version) { 10 | return new Promise(async (res) => { 11 | const lib = await find.fileSync(`tmp/drupal-${version}/core/lib`); 12 | const mod = await find.fileSync(`tmp/drupal-${version}/core/modules`); 13 | const files = filterElementFiles([...lib, ...mod]); 14 | res(files); 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /src/getRawElements.js: -------------------------------------------------------------------------------- 1 | import { stdout } from "node:process"; 2 | import { readFile } from "fs/promises"; 3 | import engine from "php-parser"; 4 | 5 | export async function getRawElements(elementFiles) { 6 | 7 | const rawElements = []; 8 | 9 | let i = 0; 10 | let pct = Math.floor(i / elementFiles.length); 11 | stdout.write(` - ${pct}% scanning\r`) 12 | 13 | const parser = new engine({ 14 | parser: { 15 | locations: true, 16 | extractDoc: true, 17 | }, 18 | ast: { 19 | withPositions: true, 20 | withSource: true 21 | } 22 | }); 23 | 24 | for (const file of elementFiles) { 25 | 26 | const contents = await readFile(file, { 27 | encoding: 'utf-8', 28 | }); 29 | 30 | // #[*Element(*)] 31 | if (contents.match(/#\[[\w]+Element\([^\s]*\)\]/g)) { 32 | const parsedElements = parser.parseCode(contents).children; 33 | 34 | for (const element of parsedElements) { 35 | const phpClass = element.children.find(child => child.kind === 'class'); 36 | 37 | const attributeType = phpClass.attrGroups?.at(0)?.attrs?.at(0)?.name; 38 | const attributeValue = phpClass.attrGroups?.at(0)?.attrs?.at(0)?.args[0]?.value; 39 | const docs = phpClass?.leadingComments?.at(-1) || 40 | phpClass.attrGroups?.at(0)?.leadingComments?.at(-1) || 41 | ""; 42 | 43 | rawElements.push({ 44 | name: attributeValue, 45 | type: attributeType, 46 | docs 47 | }) 48 | } 49 | } 50 | } 51 | 52 | return rawElements; 53 | } 54 | -------------------------------------------------------------------------------- /src/getRawHooks.js: -------------------------------------------------------------------------------- 1 | import { stdout } from "node:process"; 2 | import { readFile } from "fs/promises"; 3 | import engine from "php-parser"; 4 | 5 | export async function getRawHooks(apiFiles) { 6 | 7 | const rawHooks = []; 8 | 9 | let i = 0; 10 | let pct = Math.floor(i / apiFiles.length); 11 | stdout.write(` - ${pct}% scanning\r`) 12 | 13 | for (const file of apiFiles) { 14 | 15 | const contents = await readFile(file, { 16 | encoding: 'utf-8', 17 | }); 18 | 19 | const parser = new engine({ 20 | parser: { 21 | locations: true, 22 | extractDoc: true, 23 | }, 24 | ast: { 25 | withPositions: true, 26 | withSource: true 27 | } 28 | }); 29 | 30 | const parsedHooks = parser.parseCode(contents).children; 31 | 32 | parsedHooks 33 | .filter(hook => ( 34 | hook.kind === 'function' && 35 | hook.name.name.startsWith('hook_') 36 | )) 37 | .forEach(hook => { 38 | const docs = hook.leadingComments.at(-1); 39 | const { name } = hook.name; 40 | const definition = hook.loc.source; 41 | 42 | rawHooks.push({name, definition, docs}); 43 | }); 44 | } 45 | 46 | return rawHooks; 47 | } 48 | -------------------------------------------------------------------------------- /src/getServices.js: -------------------------------------------------------------------------------- 1 | import { readFile } from "fs/promises"; 2 | import { parse } from 'yaml'; 3 | 4 | export async function getServices(version) { 5 | return new Promise(async (res) => { 6 | 7 | const serviceYmlContents = await readFile(`tmp/drupal-${version}/core/core.services.yml`, { 8 | encoding: 'utf-8', 9 | }); 10 | 11 | const { services } = parse(serviceYmlContents); 12 | 13 | res(Object.entries(services)); 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /src/sortSnippets.js: -------------------------------------------------------------------------------- 1 | export function sortSnippets(snippets) { 2 | return Object.fromEntries( 3 | Object 4 | .entries(snippets) 5 | .sort((a, b) => { 6 | const aName = a[0].toLowerCase() 7 | const bName = b[0].toLowerCase() 8 | if (aName > bName) { 9 | return 1; 10 | } 11 | 12 | if (aName < bName) { 13 | return -1; 14 | } 15 | 16 | return 0; 17 | }) 18 | ) 19 | } 20 | --------------------------------------------------------------------------------