├── .eslintignore ├── .eslintrc ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ └── new_custom_action.md ├── dependabot.yml └── workflows │ ├── codeql.yml │ └── tests.yml ├── .gitignore ├── .node-version ├── .npmignore ├── .prettierrc.json ├── LICENSE ├── README.md ├── assets ├── hero-dark.png ├── hero.png ├── icon.png └── logo.png ├── package.json ├── playground ├── index.html ├── index.js ├── mock │ └── routes.js ├── mock_example.html ├── package.json ├── turbo_frame_static_file.html ├── vite.config.js └── yarn.lock ├── rollup.config.mjs ├── src ├── actions.ts ├── actions │ ├── attributes.ts │ ├── browser.ts │ ├── debug.ts │ ├── deprecated.ts │ ├── document.ts │ ├── document │ │ └── cookie_string_builder.ts │ ├── dom.ts │ ├── events.ts │ ├── form.ts │ ├── history.ts │ ├── notification.ts │ ├── storage.ts │ ├── turbo.ts │ ├── turbo_frame.ts │ └── turbo_progress_bar.ts ├── index.ts ├── proxy.ts └── utils.ts ├── test ├── attributes │ ├── add_css_class.test.js │ ├── remove_attribute.test.js │ ├── remove_css_class.test.js │ ├── replace_css_class.test.js │ ├── set_attribute.test.js │ ├── set_dataset_attribute.test.js │ ├── set_property.test.js │ ├── set_value.test.js │ ├── toggle_attribute.test.js │ └── toggle_css_class.test.js ├── browser │ ├── scroll_into_view.test.js │ └── set_title.test.js ├── debug │ └── console_log.test.js ├── deprecated │ └── invoke.test.js ├── document │ ├── set_cookie.test.js │ └── set_cookie_item.test.js ├── events │ └── dispatch_event.test.js ├── fixtures │ ├── frame1.html │ ├── frame2.html │ ├── page1.html │ ├── page2.html │ └── page3.html ├── form │ └── reset_form.test.js ├── history │ ├── history_back.test.js │ ├── history_forward.test.js │ └── push_state.test.js ├── notifications │ └── notification.test.js ├── storage │ ├── clear_storage.test.js │ ├── remove_storage_item.test.js │ └── set_storage_item.test.js ├── test_helpers.js ├── turbo │ ├── redirect_to.test.js │ └── turbo_clear_cache.test.js ├── turbo_frame │ ├── reload.test.js │ └── set_src.test.js ├── turbo_progress_bar │ ├── turbo_progress_bar_hide.test.js │ ├── turbo_progress_bar_set_value.test.js │ └── turbo_progress_bar_show.test.js └── utils │ ├── tokenize.test.js │ └── typecast.test.js ├── tsconfig.json ├── types └── .keep ├── web-test-runner.config.mjs └── yarn.lock /.eslintignore: -------------------------------------------------------------------------------- 1 | dist/**/*.* 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "plugins": [ 5 | "@typescript-eslint", 6 | "prettier" 7 | ], 8 | "extends": [ 9 | "eslint:recommended", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended", 12 | "prettier" 13 | ], 14 | "rules": { 15 | "prettier/prettier": ["error"], 16 | "@typescript-eslint/no-explicit-any": "off", 17 | "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }] 18 | }, 19 | "overrides": [ 20 | { 21 | "files": [ "test/**/*.test.js" ], 22 | "globals": { 23 | "describe": true, 24 | "context": true, 25 | "it": true, 26 | "beforeEach": true, 27 | "afterEach": true, 28 | "Turbo": true, 29 | "TurboPowerLocation": true 30 | } 31 | } 32 | ], 33 | "env": { 34 | "browser": true, 35 | "node": true 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | playground/**/* linguist-vendored 2 | test/**/*.js linguist-vendored 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/new_custom_action.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: New Custom Action 3 | about: Suggest a custom action which we should consider to implement 4 | title: 'Implement [action name] action' 5 | labels: new custom action 6 | --- 7 | 8 | **Action signature:** 9 | ```ruby 10 | turbo_stream.[action_name](targets, [arguments], **attributes) 11 | ``` 12 | 13 | **Example Turbo Stream Element:** 14 | ```html 15 | 16 | ``` 17 | 18 | **Action content:** 19 | ```js 20 | target.[action_name]([arguments]) 21 | ``` 22 | 23 | **Reference:** 24 | * [add links to implementation details/docs/additional details] 25 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "npm" 9 | directory: "/" 10 | schedule: 11 | interval: "weekly" 12 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | schedule: 9 | - cron: "49 0 * * 6" 10 | 11 | jobs: 12 | analyze: 13 | name: Analyze 14 | runs-on: ubuntu-latest 15 | permissions: 16 | actions: read 17 | contents: read 18 | security-events: write 19 | 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | language: [ javascript ] 24 | 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v3 28 | 29 | - name: Initialize CodeQL 30 | uses: github/codeql-action/init@v2 31 | with: 32 | languages: ${{ matrix.language }} 33 | queries: +security-and-quality 34 | 35 | - name: Autobuild 36 | uses: github/codeql-action/autobuild@v2 37 | 38 | - name: Perform CodeQL Analysis 39 | uses: github/codeql-action/analyze@v2 40 | with: 41 | category: "/language:${{ matrix.language }}" 42 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - '*' 7 | 8 | push: 9 | branches: 10 | - main 11 | 12 | jobs: 13 | test: 14 | name: JavaScript Test Action 15 | runs-on: ubuntu-latest 16 | strategy: 17 | matrix: 18 | node: [20, 22, 23, 24] 19 | 20 | steps: 21 | - uses: actions/checkout@master 22 | 23 | - name: Setup Node v${{ matrix.node }} 24 | uses: actions/setup-node@v3 25 | with: 26 | node-version: ${{ matrix.node }} 27 | cache: 'yarn' 28 | 29 | - name: Yarn install 30 | run: yarn install --frozen-lockfile 31 | 32 | - name: Run JavaScript Tests 33 | run: yarn build 34 | 35 | - name: Run JavaScript Tests 36 | run: yarn test 37 | 38 | - name: Lint 39 | run: yarn lint 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.tgz 2 | *.tsbuildinfo 3 | *.log 4 | *~ 5 | 6 | /dist 7 | node_modules/ 8 | coverage/ 9 | 10 | yarn-error.log 11 | 12 | .DS_Store 13 | .rollup.cache 14 | .tool-versions 15 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 20.9.0 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .babelrc 2 | .babelrc.js 3 | .DS_Store 4 | .gitignore 5 | .yarn.lock 6 | 7 | *.log 8 | *.tsbuildinfo 9 | *.tgz 10 | 11 | README.md 12 | rollup.config.js 13 | web-test-runner.config.mjs 14 | tsconfig.json 15 | webpack.config.js 16 | yarn-error.log 17 | *~ 18 | 19 | /.git 20 | /.github 21 | /.gitattributes 22 | 23 | /node_modules 24 | /playground 25 | /src 26 | /test 27 | /coverage 28 | /assets 29 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": false, 3 | "printWidth": 120, 4 | "semi": false 5 | } 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Marco Roth 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 |

7 | 8 |

TurboPower

9 | 10 |

11 | 12 | 13 | 14 | 15 | NPM Version 16 | 17 | 18 | 19 | NPM Downloads 20 | 21 | 22 | NPM Bundle Size 23 | 24 |

25 | 26 | ## Getting Started 27 | 28 | `turbo_power` is a power-pack for Turbo Streams. It provides Turbo Streams with a bunch of new actions and additionally adds the `morph` action from [`turbo-morph`](https://github.com/marcoroth/turbo-morph). 29 | 30 | **Note:** Requires Turbo **7.2+** 31 | 32 | ## Getting Started 33 | 34 | ```bash 35 | yarn add turbo_power 36 | ``` 37 | 38 | ```diff 39 | // application.js 40 | import * as Turbo from '@hotwired/turbo' 41 | 42 | +import TurboPower from 'turbo_power' 43 | +TurboPower.initialize(Turbo.StreamActions) 44 | ``` 45 | 46 | ## Getting Started with Rails 47 | 48 | Checkout the instructions in the [`turbo_power-rails`](https://github.com/marcoroth/turbo_power-rails) repo. 49 | 50 | ## Getting Started with Django 51 | 52 | Checkout the doc of the [`django-turbo-helper`](https://github.com/rails-inspire-django/django-turbo-helper) repo. 53 | 54 | ## Custom Actions 55 | 56 | ### DOM Actions 57 | 58 | * `turbo_stream.graft(target, parent, **attributes)` 59 | * [`turbo_stream.morph(target, html = nil, **attributes, &block)`](https://github.com/marcoroth/turbo-morph) 60 | * `turbo_stream.inner_html(target, html = nil, **attributes, &block)` 61 | * `turbo_stream.insert_adjacent_html(target, html = nil, position: 'beforeend', **attributes, &block)` 62 | * `turbo_stream.insert_adjacent_text(target, text, position: 'beforebegin', **attributes)` 63 | * `turbo_stream.outer_html(target, html = nil, **attributes, &block)` 64 | * `turbo_stream.text_content(target, text, **attributes)` 65 | * `turbo_stream.set_meta(name, content)` 66 | 67 | 68 | ### Attribute Actions 69 | 70 | * `turbo_stream.add_css_class(target, classes, **attributes)` 71 | * `turbo_stream.remove_attribute(target, attribute, **attributes)` 72 | * `turbo_stream.remove_css_class(target, classes, **attributes)` 73 | * `turbo_stream.set_attribute(target, attribute, value, **attributes)` 74 | * `turbo_stream.set_dataset_attribute(target, attribute, value, **attributes)` 75 | * `turbo_stream.set_property(target, property, value, **attributes)` 76 | * `turbo_stream.set_style(target, name, value, **attributes)` 77 | * `turbo_stream.set_styles(target, styles, **attributes)` 78 | * `turbo_stream.set_value(target, value, **attributes)` 79 | * `turbo_stream.toggle_attribute(target, attribute, force, **attributes)` 80 | * `turbo_stream.toggle_css_class(target, classes, **attributes)` 81 | * `turbo_stream.replace_css_class(target, from, to, **attributes)` 82 | 83 | 84 | ### Event Actions 85 | 86 | * `turbo_stream.dispatch_event(target, name, detail: {}, **attributes)` 87 | 88 | 89 | ### Form Actions 90 | 91 | * `turbo_stream.reset_form(target, **attributes)` 92 | 93 | 94 | ### Storage Actions 95 | 96 | * `turbo_stream.clear_storage(type, **attributes)` 97 | * `turbo_stream.clear_local_storage(**attributes)` 98 | * `turbo_stream.clear_session_storage(**attributes)` 99 | * `turbo_stream.remove_storage_item(key, type, **attributes)` 100 | * `turbo_stream.remove_local_storage_item(key, **attributes)` 101 | * `turbo_stream.remove_session_storage_item(key, **attributes)` 102 | * `turbo_stream.set_storage_item(key, value, type, **attributes)` 103 | * `turbo_stream.set_local_storage_item(key, value, **attributes)` 104 | * `turbo_stream.set_session_storage_item(key, value, **attributes)` 105 | 106 | 107 | ### Browser Actions 108 | 109 | * `turbo_stream.reload(**attributes)` 110 | * `turbo_stream.scroll_into_view(**attributes)` 111 | * `turbo_stream.scroll_into_view(targets)` 112 | * `turbo_stream.scroll_into_view(targets, align_to_top)` 113 | * `turbo_stream.scroll_into_view(targets, behavior:, block:, inline:)` 114 | * `turbo_stream.set_focus(target, **attributes)` 115 | * `turbo_stream.set_title(title, **attributes)` 116 | 117 | 118 | ### Document Actions 119 | 120 | * `turbo_stream.set_cookie(cookie, **attributes)` 121 | * `turbo_stream.set_cookie_item(key, value, **attributes)` 122 | 123 | 124 | ### Browser History Actions 125 | 126 | * `turbo_stream.history_back(**attributes)` 127 | * `turbo_stream.history_forward(**attributes)` 128 | * `turbo_stream.history_go(delta, **attributes)` 129 | * `turbo_stream.push_state(url, title = nil, state = nil, **attributes)` 130 | * `turbo_stream.replace_state(url, title = nil, state = nil, **attributes)` 131 | 132 | 133 | ### Debug Actions 134 | 135 | * `turbo_stream.console_log(message, level = :log)` 136 | * `turbo_stream.console_table(data, columns)` 137 | 138 | 139 | ### Notification Actions 140 | 141 | * `turbo_stream.notification(title, **options)` 142 | 143 | 144 | ### Turbo Actions 145 | 146 | * `turbo_stream.redirect_to(url, turbo_action = nil, turbo_frame = nil, **attributes)` 147 | * `turbo_stream.turbo_clear_cache()` 148 | 149 | 150 | ### Turbo Progress Bar Actions 151 | 152 | * `turbo_stream.turbo_progress_bar_show()` 153 | * `turbo_stream.turbo_progress_bar_hide()` 154 | * `turbo_stream.turbo_progress_bar_set_value(value)` 155 | 156 | 157 | ### Turbo Frame Actions 158 | 159 | * `turbo_stream.turbo_frame_reload(frame_id)` 160 | * `turbo_stream.turbo_frame_set_src(frame_id, src)` 161 | 162 | 163 | 164 | ## Previous Art 165 | 166 | TurboPower is heavily inspired by [CableReady](https://github.com/stimulusreflex/cable_ready) and its operations. This library aims to bring the same level of operation-diversity to Turbo Streams. 167 | 168 | ## Development 169 | 170 | To run the test runner: 171 | 172 | ```plain 173 | yarn build 174 | yarn test 175 | ``` 176 | 177 | ## Acknowledgments 178 | 179 | `turbo_power` is [MIT-licensed](LICENSE) open-source software from [Marco Roth](https://github.com/marcoroth). 180 | 181 | `turbo-morph` is [MIT-licensed](https://github.com/marcoroth/turbo-morph/blob/master/LICENSE) open-source software from [Marco Roth](https://github.com/marcoroth). 182 | 183 | Turbo is [MIT-licensed](https://github.com/hotwired/turbo/blob/main/MIT-LICENSE) open-source software from [Basecamp](https://basecamp.com/). 184 | -------------------------------------------------------------------------------- /assets/hero-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcoroth/turbo_power/4219232851e19de3a4aa0d63f76c496fdfc141af/assets/hero-dark.png -------------------------------------------------------------------------------- /assets/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcoroth/turbo_power/4219232851e19de3a4aa0d63f76c496fdfc141af/assets/hero.png -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcoroth/turbo_power/4219232851e19de3a4aa0d63f76c496fdfc141af/assets/icon.png -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcoroth/turbo_power/4219232851e19de3a4aa0d63f76c496fdfc141af/assets/logo.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "turbo_power", 3 | "version": "0.7.1", 4 | "description": "Power-pack for Turbo", 5 | "main": "dist/turbo_power.js", 6 | "module": "dist/turbo_power.js", 7 | "unpkg": "dist/turbo_power.umd.js", 8 | "types": "dist/types/index.d.ts", 9 | "author": "Marco Roth", 10 | "license": "MIT", 11 | "repository": "https://github.com/marcoroth/turbo_power", 12 | "sideEffects": false, 13 | "scripts": { 14 | "start": "cd playground && yarn start", 15 | "prebuild": "yarn clean", 16 | "build": "tsc --noEmit false --declaration true --emitDeclarationOnly true --outDir dist/types && rollup -c", 17 | "watch": "rollup -wc", 18 | "dev": "concurrently 'yarn run watch' 'yarn run start'", 19 | "clean": "rimraf dist", 20 | "prerelease": "yarn build", 21 | "test": "web-test-runner test/**/*.test.js", 22 | "lint": "eslint .", 23 | "format": "yarn lint --fix" 24 | }, 25 | "devDependencies": { 26 | "@hotwired/turbo": "^7.2.5", 27 | "@open-wc/testing": "^4.0.0", 28 | "@rollup/plugin-node-resolve": "^16.0.1", 29 | "@rollup/plugin-terser": "^0.4.0", 30 | "@rollup/plugin-typescript": "^12.1.0", 31 | "@typescript-eslint/eslint-plugin": "^7.0.0", 32 | "@typescript-eslint/parser": "^6.18.0", 33 | "@web/test-runner": "^0.20.0", 34 | "concurrently": "^9.0.0", 35 | "eslint": "^8.56.0", 36 | "eslint-config-prettier": "^10.0.1", 37 | "eslint-plugin-prettier": "^5.1.2", 38 | "prettier": "^3.1.1", 39 | "rimraf": "^5.0.1", 40 | "rollup": "^4.1.5", 41 | "rollup-plugin-filesize": "^10.0.0", 42 | "sinon": "^20.0.0", 43 | "sourcemap": "^0.1.0", 44 | "tslib": "^2.6.2", 45 | "turbo-morph": "^0.2.0", 46 | "typescript": "^5.3.3" 47 | }, 48 | "peerDependencies": { 49 | "@hotwired/turbo": ">= 7.2" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /playground/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | TurboPower Playground 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /playground/index.js: -------------------------------------------------------------------------------- 1 | import * as Turbo from "@hotwired/turbo" 2 | import * as TurboPower from "turbo_power" 3 | 4 | TurboPower.initialize(Turbo.StreamActions) 5 | -------------------------------------------------------------------------------- /playground/mock/routes.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | url: /\/turbo-frame-[\d]/, 4 | method: "get", 5 | rawResponse: async (req, res) => { 6 | // let _reqbody = "" 7 | await new Promise((resolve) => { 8 | req.on("data", (_chunk) => { 9 | // _reqbody += _chunk 10 | }) 11 | req.on("end", () => resolve(undefined)) 12 | }) 13 | res.setHeader("Content-Type", "text/html") 14 | res.statusCode = 200 15 | res.end(`Dynamic Turbo Frame ${res.req.url}`) 16 | }, 17 | }, 18 | { 19 | url: /\/turbo-stream-[\w+]/, 20 | method: "get", 21 | rawResponse: async (req, res) => { 22 | // let _reqbody = "" 23 | await new Promise((resolve) => { 24 | req.on("data", (_chunk) => { 25 | // _reqbody += _chunk 26 | }) 27 | req.on("end", () => resolve(undefined)) 28 | }) 29 | const kindValue = res.req.url.split("turbo-stream-")[1] 30 | res.setHeader("Content-Type", "text/vnd.turbo-stream.html; charset=utf-8") 31 | res.statusCode = 200 32 | const htmlResponse = (kind) => 33 | ({ 34 | frame_src: 35 | '', 36 | frame_reload: '', 37 | inner_html: 38 | '', 39 | })[kind] 40 | res.end(htmlResponse(kindValue)) 41 | }, 42 | }, 43 | ] 44 | -------------------------------------------------------------------------------- /playground/mock_example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | TurboPower Playground 5 | 6 | 7 | 8 | 9 | 23 | 24 | 25 |

Main page

26 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /playground/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "turbo_power-playground", 3 | "private": true, 4 | "version": "0.1.0", 5 | "description": "A playground for TurboPower", 6 | "license": "MIT", 7 | "repository": "https://github.com/marcoroth/turbo_power", 8 | "dependencies": { 9 | "@hotwired/turbo": "^7.2.4", 10 | "turbo_power": "link:../" 11 | }, 12 | "scripts": { 13 | "start": "yarn run dev", 14 | "dev": "vite", 15 | "build": "vite build", 16 | "preview": "vite preview" 17 | }, 18 | "devDependencies": { 19 | "mockjs": "^1.1.0", 20 | "vite": "^4.5.14", 21 | "vite-plugin-mock": "^2.9.6" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /playground/turbo_frame_static_file.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Static Frame 4 | 7 | 8 | -------------------------------------------------------------------------------- /playground/vite.config.js: -------------------------------------------------------------------------------- 1 | import { viteMockServe } from "vite-plugin-mock" 2 | import path from "path" 3 | 4 | export default { 5 | resolve: { 6 | alias: { 7 | turbo_power: path.resolve(__dirname, "../dist/index"), 8 | }, 9 | }, 10 | plugins: [ 11 | viteMockServe({ 12 | mockPath: "mock", 13 | localEnabled: true, 14 | }), 15 | ], 16 | } 17 | -------------------------------------------------------------------------------- /playground/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@esbuild/android-arm64@0.18.20": 6 | version "0.18.20" 7 | resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz#984b4f9c8d0377443cc2dfcef266d02244593622" 8 | integrity sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ== 9 | 10 | "@esbuild/android-arm@0.18.20": 11 | version "0.18.20" 12 | resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.18.20.tgz#fedb265bc3a589c84cc11f810804f234947c3682" 13 | integrity sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw== 14 | 15 | "@esbuild/android-x64@0.18.20": 16 | version "0.18.20" 17 | resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.18.20.tgz#35cf419c4cfc8babe8893d296cd990e9e9f756f2" 18 | integrity sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg== 19 | 20 | "@esbuild/darwin-arm64@0.18.20": 21 | version "0.18.20" 22 | resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz#08172cbeccf95fbc383399a7f39cfbddaeb0d7c1" 23 | integrity sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA== 24 | 25 | "@esbuild/darwin-x64@0.18.20": 26 | version "0.18.20" 27 | resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz#d70d5790d8bf475556b67d0f8b7c5bdff053d85d" 28 | integrity sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ== 29 | 30 | "@esbuild/freebsd-arm64@0.18.20": 31 | version "0.18.20" 32 | resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz#98755cd12707f93f210e2494d6a4b51b96977f54" 33 | integrity sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw== 34 | 35 | "@esbuild/freebsd-x64@0.18.20": 36 | version "0.18.20" 37 | resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz#c1eb2bff03915f87c29cece4c1a7fa1f423b066e" 38 | integrity sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ== 39 | 40 | "@esbuild/linux-arm64@0.18.20": 41 | version "0.18.20" 42 | resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz#bad4238bd8f4fc25b5a021280c770ab5fc3a02a0" 43 | integrity sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA== 44 | 45 | "@esbuild/linux-arm@0.18.20": 46 | version "0.18.20" 47 | resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz#3e617c61f33508a27150ee417543c8ab5acc73b0" 48 | integrity sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg== 49 | 50 | "@esbuild/linux-ia32@0.18.20": 51 | version "0.18.20" 52 | resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz#699391cccba9aee6019b7f9892eb99219f1570a7" 53 | integrity sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA== 54 | 55 | "@esbuild/linux-loong64@0.18.20": 56 | version "0.18.20" 57 | resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz#e6fccb7aac178dd2ffb9860465ac89d7f23b977d" 58 | integrity sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg== 59 | 60 | "@esbuild/linux-mips64el@0.18.20": 61 | version "0.18.20" 62 | resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz#eeff3a937de9c2310de30622a957ad1bd9183231" 63 | integrity sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ== 64 | 65 | "@esbuild/linux-ppc64@0.18.20": 66 | version "0.18.20" 67 | resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz#2f7156bde20b01527993e6881435ad79ba9599fb" 68 | integrity sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA== 69 | 70 | "@esbuild/linux-riscv64@0.18.20": 71 | version "0.18.20" 72 | resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz#6628389f210123d8b4743045af8caa7d4ddfc7a6" 73 | integrity sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A== 74 | 75 | "@esbuild/linux-s390x@0.18.20": 76 | version "0.18.20" 77 | resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz#255e81fb289b101026131858ab99fba63dcf0071" 78 | integrity sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ== 79 | 80 | "@esbuild/linux-x64@0.18.20": 81 | version "0.18.20" 82 | resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz#c7690b3417af318a9b6f96df3031a8865176d338" 83 | integrity sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w== 84 | 85 | "@esbuild/netbsd-x64@0.18.20": 86 | version "0.18.20" 87 | resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz#30e8cd8a3dded63975e2df2438ca109601ebe0d1" 88 | integrity sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A== 89 | 90 | "@esbuild/openbsd-x64@0.18.20": 91 | version "0.18.20" 92 | resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz#7812af31b205055874c8082ea9cf9ab0da6217ae" 93 | integrity sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg== 94 | 95 | "@esbuild/sunos-x64@0.18.20": 96 | version "0.18.20" 97 | resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz#d5c275c3b4e73c9b0ecd38d1ca62c020f887ab9d" 98 | integrity sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ== 99 | 100 | "@esbuild/win32-arm64@0.18.20": 101 | version "0.18.20" 102 | resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz#73bc7f5a9f8a77805f357fab97f290d0e4820ac9" 103 | integrity sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg== 104 | 105 | "@esbuild/win32-ia32@0.18.20": 106 | version "0.18.20" 107 | resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz#ec93cbf0ef1085cc12e71e0d661d20569ff42102" 108 | integrity sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g== 109 | 110 | "@esbuild/win32-x64@0.18.20": 111 | version "0.18.20" 112 | resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz#786c5f41f043b07afb1af37683d7c33668858f6d" 113 | integrity sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ== 114 | 115 | "@hotwired/turbo@^7.2.4": 116 | version "7.2.4" 117 | resolved "https://registry.yarnpkg.com/@hotwired/turbo/-/turbo-7.2.4.tgz#0d35541be32cfae3b4f78c6ab9138f5b21f28a21" 118 | integrity sha512-c3xlOroHp/cCZHDOuLp6uzQYEbvXBUVaal0puXoGJ9M8L/KHwZ3hQozD4dVeSN9msHWLxxtmPT1TlCN7gFhj4w== 119 | 120 | "@nodelib/fs.scandir@2.1.5": 121 | version "2.1.5" 122 | resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" 123 | integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== 124 | dependencies: 125 | "@nodelib/fs.stat" "2.0.5" 126 | run-parallel "^1.1.9" 127 | 128 | "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": 129 | version "2.0.5" 130 | resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" 131 | integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== 132 | 133 | "@nodelib/fs.walk@^1.2.3": 134 | version "1.2.8" 135 | resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" 136 | integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== 137 | dependencies: 138 | "@nodelib/fs.scandir" "2.1.5" 139 | fastq "^1.6.0" 140 | 141 | "@rollup/plugin-node-resolve@^13.0.4": 142 | version "13.3.0" 143 | resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.3.0.tgz#da1c5c5ce8316cef96a2f823d111c1e4e498801c" 144 | integrity sha512-Lus8rbUo1eEcnS4yTFKLZrVumLPY+YayBdWXgFSHYhTT2iJbMhoaaBL3xl5NCdeRytErGr8tZ0L71BMRmnlwSw== 145 | dependencies: 146 | "@rollup/pluginutils" "^3.1.0" 147 | "@types/resolve" "1.17.1" 148 | deepmerge "^4.2.2" 149 | is-builtin-module "^3.1.0" 150 | is-module "^1.0.0" 151 | resolve "^1.19.0" 152 | 153 | "@rollup/pluginutils@^3.1.0": 154 | version "3.1.0" 155 | resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" 156 | integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== 157 | dependencies: 158 | "@types/estree" "0.0.39" 159 | estree-walker "^1.0.1" 160 | picomatch "^2.2.2" 161 | 162 | "@types/estree@0.0.39": 163 | version "0.0.39" 164 | resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" 165 | integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== 166 | 167 | "@types/mockjs@^1.0.4": 168 | version "1.0.7" 169 | resolved "https://registry.yarnpkg.com/@types/mockjs/-/mockjs-1.0.7.tgz#3a0f1bc3f286ae2891d9592422529268665c88d3" 170 | integrity sha512-OCxXz6hEaJOVpRwuJMiVY5a6LtJcih+br9gwB/Q8ooOBikvk5FpBQ31OlNimXo3EqKha1Z7PFBni+q9m+8NCWg== 171 | 172 | "@types/node@*": 173 | version "18.11.3" 174 | resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.3.tgz#78a6d7ec962b596fc2d2ec102c4dd3ef073fea6a" 175 | integrity sha512-fNjDQzzOsZeKZu5NATgXUPsaFaTxeRgFXoosrHivTl8RGeV733OLawXsGfEk9a8/tySyZUyiZ6E8LcjPFZ2y1A== 176 | 177 | "@types/resolve@1.17.1": 178 | version "1.17.1" 179 | resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" 180 | integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw== 181 | dependencies: 182 | "@types/node" "*" 183 | 184 | ansi-styles@^4.1.0: 185 | version "4.3.0" 186 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 187 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 188 | dependencies: 189 | color-convert "^2.0.1" 190 | 191 | anymatch@~3.1.2: 192 | version "3.1.2" 193 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" 194 | integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== 195 | dependencies: 196 | normalize-path "^3.0.0" 197 | picomatch "^2.0.4" 198 | 199 | binary-extensions@^2.0.0: 200 | version "2.2.0" 201 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" 202 | integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== 203 | 204 | braces@^3.0.3, braces@~3.0.2: 205 | version "3.0.3" 206 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" 207 | integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== 208 | dependencies: 209 | fill-range "^7.1.1" 210 | 211 | builtin-modules@^3.3.0: 212 | version "3.3.0" 213 | resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" 214 | integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== 215 | 216 | chalk@^4.1.2: 217 | version "4.1.2" 218 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 219 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 220 | dependencies: 221 | ansi-styles "^4.1.0" 222 | supports-color "^7.1.0" 223 | 224 | chokidar@^3.5.2: 225 | version "3.5.3" 226 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" 227 | integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== 228 | dependencies: 229 | anymatch "~3.1.2" 230 | braces "~3.0.2" 231 | glob-parent "~5.1.2" 232 | is-binary-path "~2.1.0" 233 | is-glob "~4.0.1" 234 | normalize-path "~3.0.0" 235 | readdirp "~3.6.0" 236 | optionalDependencies: 237 | fsevents "~2.3.2" 238 | 239 | color-convert@^2.0.1: 240 | version "2.0.1" 241 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 242 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 243 | dependencies: 244 | color-name "~1.1.4" 245 | 246 | color-name@~1.1.4: 247 | version "1.1.4" 248 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 249 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 250 | 251 | commander@*: 252 | version "9.4.1" 253 | resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.1.tgz#d1dd8f2ce6faf93147295c0df13c7c21141cfbdd" 254 | integrity sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw== 255 | 256 | connect@^3.7.0: 257 | version "3.7.0" 258 | resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" 259 | integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== 260 | dependencies: 261 | debug "2.6.9" 262 | finalhandler "1.1.2" 263 | parseurl "~1.3.3" 264 | utils-merge "1.0.1" 265 | 266 | debug@2.6.9: 267 | version "2.6.9" 268 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 269 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 270 | dependencies: 271 | ms "2.0.0" 272 | 273 | debug@^4.3.2: 274 | version "4.3.4" 275 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" 276 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 277 | dependencies: 278 | ms "2.1.2" 279 | 280 | deepmerge@^4.2.2: 281 | version "4.2.2" 282 | resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" 283 | integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== 284 | 285 | ee-first@1.1.1: 286 | version "1.1.1" 287 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 288 | integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== 289 | 290 | encodeurl@~1.0.2: 291 | version "1.0.2" 292 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 293 | integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== 294 | 295 | esbuild@0.11.3: 296 | version "0.11.3" 297 | resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.11.3.tgz#b57165b907be4ffba651f6450538ce8d8c1d5eb0" 298 | integrity sha512-BzVRHcCtFepjS9WcqRjqoIxLqgpK21a8J4Zi4msSGxDxiXVO1IbcqT1KjhdDDnJxKfe7bvzZrvMEX+bVO0Elcw== 299 | 300 | esbuild@^0.18.10: 301 | version "0.18.20" 302 | resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.18.20.tgz#4709f5a34801b43b799ab7d6d82f7284a9b7a7a6" 303 | integrity sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA== 304 | optionalDependencies: 305 | "@esbuild/android-arm" "0.18.20" 306 | "@esbuild/android-arm64" "0.18.20" 307 | "@esbuild/android-x64" "0.18.20" 308 | "@esbuild/darwin-arm64" "0.18.20" 309 | "@esbuild/darwin-x64" "0.18.20" 310 | "@esbuild/freebsd-arm64" "0.18.20" 311 | "@esbuild/freebsd-x64" "0.18.20" 312 | "@esbuild/linux-arm" "0.18.20" 313 | "@esbuild/linux-arm64" "0.18.20" 314 | "@esbuild/linux-ia32" "0.18.20" 315 | "@esbuild/linux-loong64" "0.18.20" 316 | "@esbuild/linux-mips64el" "0.18.20" 317 | "@esbuild/linux-ppc64" "0.18.20" 318 | "@esbuild/linux-riscv64" "0.18.20" 319 | "@esbuild/linux-s390x" "0.18.20" 320 | "@esbuild/linux-x64" "0.18.20" 321 | "@esbuild/netbsd-x64" "0.18.20" 322 | "@esbuild/openbsd-x64" "0.18.20" 323 | "@esbuild/sunos-x64" "0.18.20" 324 | "@esbuild/win32-arm64" "0.18.20" 325 | "@esbuild/win32-ia32" "0.18.20" 326 | "@esbuild/win32-x64" "0.18.20" 327 | 328 | escape-html@~1.0.3: 329 | version "1.0.3" 330 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 331 | integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== 332 | 333 | estree-walker@^1.0.1: 334 | version "1.0.1" 335 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" 336 | integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== 337 | 338 | fast-glob@^3.2.7: 339 | version "3.2.12" 340 | resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" 341 | integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== 342 | dependencies: 343 | "@nodelib/fs.stat" "^2.0.2" 344 | "@nodelib/fs.walk" "^1.2.3" 345 | glob-parent "^5.1.2" 346 | merge2 "^1.3.0" 347 | micromatch "^4.0.4" 348 | 349 | fastq@^1.6.0: 350 | version "1.13.0" 351 | resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" 352 | integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== 353 | dependencies: 354 | reusify "^1.0.4" 355 | 356 | fill-range@^7.1.1: 357 | version "7.1.1" 358 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" 359 | integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== 360 | dependencies: 361 | to-regex-range "^5.0.1" 362 | 363 | finalhandler@1.1.2: 364 | version "1.1.2" 365 | resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" 366 | integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== 367 | dependencies: 368 | debug "2.6.9" 369 | encodeurl "~1.0.2" 370 | escape-html "~1.0.3" 371 | on-finished "~2.3.0" 372 | parseurl "~1.3.3" 373 | statuses "~1.5.0" 374 | unpipe "~1.0.0" 375 | 376 | fsevents@~2.3.2: 377 | version "2.3.2" 378 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" 379 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== 380 | 381 | function-bind@^1.1.1: 382 | version "1.1.1" 383 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 384 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 385 | 386 | glob-parent@^5.1.2, glob-parent@~5.1.2: 387 | version "5.1.2" 388 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 389 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 390 | dependencies: 391 | is-glob "^4.0.1" 392 | 393 | has-flag@^4.0.0: 394 | version "4.0.0" 395 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 396 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 397 | 398 | has@^1.0.3: 399 | version "1.0.3" 400 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 401 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 402 | dependencies: 403 | function-bind "^1.1.1" 404 | 405 | is-binary-path@~2.1.0: 406 | version "2.1.0" 407 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 408 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 409 | dependencies: 410 | binary-extensions "^2.0.0" 411 | 412 | is-builtin-module@^3.1.0: 413 | version "3.2.0" 414 | resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.0.tgz#bb0310dfe881f144ca83f30100ceb10cf58835e0" 415 | integrity sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw== 416 | dependencies: 417 | builtin-modules "^3.3.0" 418 | 419 | is-core-module@^2.9.0: 420 | version "2.9.0" 421 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" 422 | integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== 423 | dependencies: 424 | has "^1.0.3" 425 | 426 | is-extglob@^2.1.1: 427 | version "2.1.1" 428 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 429 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 430 | 431 | is-glob@^4.0.1, is-glob@~4.0.1: 432 | version "4.0.3" 433 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 434 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 435 | dependencies: 436 | is-extglob "^2.1.1" 437 | 438 | is-module@^1.0.0: 439 | version "1.0.0" 440 | resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" 441 | integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== 442 | 443 | is-number@^7.0.0: 444 | version "7.0.0" 445 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 446 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 447 | 448 | merge2@^1.3.0: 449 | version "1.4.1" 450 | resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" 451 | integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== 452 | 453 | micromatch@^4.0.4: 454 | version "4.0.8" 455 | resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" 456 | integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== 457 | dependencies: 458 | braces "^3.0.3" 459 | picomatch "^2.3.1" 460 | 461 | mockjs@^1.1.0: 462 | version "1.1.0" 463 | resolved "https://registry.yarnpkg.com/mockjs/-/mockjs-1.1.0.tgz#e6a0c378e91906dbaff20911cc0273b3c7d75b06" 464 | integrity sha512-eQsKcWzIaZzEZ07NuEyO4Nw65g0hdWAyurVol1IPl1gahRwY+svqzfgfey8U8dahLwG44d6/RwEzuK52rSa/JQ== 465 | dependencies: 466 | commander "*" 467 | 468 | ms@2.0.0: 469 | version "2.0.0" 470 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 471 | integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== 472 | 473 | ms@2.1.2: 474 | version "2.1.2" 475 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 476 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 477 | 478 | nanoid@^3.3.8: 479 | version "3.3.8" 480 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" 481 | integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== 482 | 483 | normalize-path@^3.0.0, normalize-path@~3.0.0: 484 | version "3.0.0" 485 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 486 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 487 | 488 | on-finished@~2.3.0: 489 | version "2.3.0" 490 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" 491 | integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== 492 | dependencies: 493 | ee-first "1.1.1" 494 | 495 | parseurl@~1.3.3: 496 | version "1.3.3" 497 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" 498 | integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== 499 | 500 | path-parse@^1.0.7: 501 | version "1.0.7" 502 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" 503 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 504 | 505 | path-to-regexp@^6.2.0: 506 | version "6.3.0" 507 | resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz#2b6a26a337737a8e1416f9272ed0766b1c0389f4" 508 | integrity sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ== 509 | 510 | picocolors@^1.1.1: 511 | version "1.1.1" 512 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" 513 | integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== 514 | 515 | picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.3.1: 516 | version "2.3.1" 517 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 518 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 519 | 520 | postcss@^8.4.27: 521 | version "8.5.1" 522 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.1.tgz#e2272a1f8a807fafa413218245630b5db10a3214" 523 | integrity sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ== 524 | dependencies: 525 | nanoid "^3.3.8" 526 | picocolors "^1.1.1" 527 | source-map-js "^1.2.1" 528 | 529 | queue-microtask@^1.2.2: 530 | version "1.2.3" 531 | resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" 532 | integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== 533 | 534 | readdirp@~3.6.0: 535 | version "3.6.0" 536 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" 537 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 538 | dependencies: 539 | picomatch "^2.2.1" 540 | 541 | resolve@^1.19.0: 542 | version "1.22.1" 543 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" 544 | integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== 545 | dependencies: 546 | is-core-module "^2.9.0" 547 | path-parse "^1.0.7" 548 | supports-preserve-symlinks-flag "^1.0.0" 549 | 550 | reusify@^1.0.4: 551 | version "1.0.4" 552 | resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" 553 | integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== 554 | 555 | rollup@^3.27.1: 556 | version "3.29.5" 557 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.5.tgz#8a2e477a758b520fb78daf04bca4c522c1da8a54" 558 | integrity sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w== 559 | optionalDependencies: 560 | fsevents "~2.3.2" 561 | 562 | run-parallel@^1.1.9: 563 | version "1.2.0" 564 | resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" 565 | integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== 566 | dependencies: 567 | queue-microtask "^1.2.2" 568 | 569 | source-map-js@^1.2.1: 570 | version "1.2.1" 571 | resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" 572 | integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== 573 | 574 | statuses@~1.5.0: 575 | version "1.5.0" 576 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" 577 | integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== 578 | 579 | supports-color@^7.1.0: 580 | version "7.2.0" 581 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 582 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 583 | dependencies: 584 | has-flag "^4.0.0" 585 | 586 | supports-preserve-symlinks-flag@^1.0.0: 587 | version "1.0.0" 588 | resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" 589 | integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== 590 | 591 | to-regex-range@^5.0.1: 592 | version "5.0.1" 593 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 594 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 595 | dependencies: 596 | is-number "^7.0.0" 597 | 598 | "turbo_power@link:..": 599 | version "0.7.1" 600 | 601 | unpipe@~1.0.0: 602 | version "1.0.0" 603 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 604 | integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== 605 | 606 | utils-merge@1.0.1: 607 | version "1.0.1" 608 | resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" 609 | integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== 610 | 611 | vite-plugin-mock@^2.9.6: 612 | version "2.9.6" 613 | resolved "https://registry.yarnpkg.com/vite-plugin-mock/-/vite-plugin-mock-2.9.6.tgz#04dd23de6baa052faa5b9ad317514c90d6205e25" 614 | integrity sha512-/Rm59oPppe/ncbkSrUuAxIQihlI2YcBmnbR4ST1RA2VzM1C0tEQc1KlbQvnUGhXECAGTaQN2JyasiwXP6EtKgg== 615 | dependencies: 616 | "@rollup/plugin-node-resolve" "^13.0.4" 617 | "@types/mockjs" "^1.0.4" 618 | chalk "^4.1.2" 619 | chokidar "^3.5.2" 620 | connect "^3.7.0" 621 | debug "^4.3.2" 622 | esbuild "0.11.3" 623 | fast-glob "^3.2.7" 624 | path-to-regexp "^6.2.0" 625 | 626 | vite@^4.5.14: 627 | version "4.5.14" 628 | resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.14.tgz#2e652bc1d898265d987d6543ce866ecd65fa4086" 629 | integrity sha512-+v57oAaoYNnO3hIu5Z/tJRZjq5aHM2zDve9YZ8HngVHbhk66RStobhb1sqPMIPEleV6cNKYK4eGrAbE9Ulbl2g== 630 | dependencies: 631 | esbuild "^0.18.10" 632 | postcss "^8.4.27" 633 | rollup "^3.27.1" 634 | optionalDependencies: 635 | fsevents "~2.3.2" 636 | -------------------------------------------------------------------------------- /rollup.config.mjs: -------------------------------------------------------------------------------- 1 | import resolve from "@rollup/plugin-node-resolve" 2 | import typescript from "@rollup/plugin-typescript" 3 | import terser from "@rollup/plugin-terser" 4 | import filesize from "rollup-plugin-filesize" 5 | import { readFileSync } from "fs" 6 | 7 | const json = JSON.parse(readFileSync("./package.json")) 8 | const banner = `/*\n * TurboPower ${json.version}\n */` 9 | 10 | const pretty = () => { 11 | return terser({ 12 | mangle: false, 13 | compress: false, 14 | format: { 15 | comments: "all", 16 | beautify: true, 17 | indent_level: 2 18 | } 19 | }) 20 | } 21 | 22 | export default [ 23 | { 24 | input: "src/index.ts", 25 | external: ["@hotwired/turbo"], 26 | output: [ 27 | { 28 | name: "TurboPower", 29 | file: "dist/turbo_power.umd.js", 30 | format: "umd", 31 | banner, 32 | globals: { 33 | "@hotwired/turbo": "Turbo", 34 | }, 35 | }, 36 | { 37 | file: "dist/turbo_power.js", 38 | format: "es", 39 | banner, 40 | }, 41 | ], 42 | plugins: [ 43 | resolve(), 44 | typescript(), 45 | pretty(), 46 | filesize(), 47 | ], 48 | watch: { 49 | include: "src/**", 50 | }, 51 | }, 52 | ] 53 | -------------------------------------------------------------------------------- /src/actions.ts: -------------------------------------------------------------------------------- 1 | import { TurboStreamActions } from "@hotwired/turbo" 2 | 3 | import * as Attributes from "./actions/attributes" 4 | import * as Browser from "./actions/browser" 5 | import * as Debug from "./actions/debug" 6 | import * as Deprecated from "./actions/deprecated" 7 | import * as Document from "./actions/document" 8 | import * as DOM from "./actions/dom" 9 | import * as Events from "./actions/events" 10 | import * as Form from "./actions/form" 11 | import * as History from "./actions/history" 12 | import * as Notification from "./actions/notification" 13 | import * as Storage from "./actions/storage" 14 | import * as Turbo from "./actions/turbo" 15 | import * as TurboProgressBar from "./actions/turbo_progress_bar" 16 | import * as TurboFrame from "./actions/turbo_frame" 17 | 18 | export * from "./actions/attributes" 19 | export * from "./actions/browser" 20 | export * from "./actions/debug" 21 | export * from "./actions/deprecated" 22 | export * from "./actions/document" 23 | export * from "./actions/dom" 24 | export * from "./actions/events" 25 | export * from "./actions/form" 26 | export * from "./actions/history" 27 | export * from "./actions/notification" 28 | export * from "./actions/storage" 29 | export * from "./actions/turbo" 30 | export * from "./actions/turbo_progress_bar" 31 | export * from "./actions/turbo_frame" 32 | 33 | export function register(streamActions: TurboStreamActions) { 34 | Attributes.registerAttributesActions(streamActions) 35 | Browser.registerBrowserActions(streamActions) 36 | Debug.registerDebugActions(streamActions) 37 | Deprecated.registerDeprecatedActions(streamActions) 38 | Document.registerDocumentActions(streamActions) 39 | DOM.registerDOMActions(streamActions) 40 | Events.registerEventsActions(streamActions) 41 | Form.registerFormActions(streamActions) 42 | History.registerHistoryActions(streamActions) 43 | Notification.registerNotificationActions(streamActions) 44 | Storage.registerStorageActions(streamActions) 45 | Turbo.registerTurboActions(streamActions) 46 | TurboProgressBar.registerTurboProgressBarActions(streamActions) 47 | TurboFrame.registerTurboFrameActions(streamActions) 48 | } 49 | -------------------------------------------------------------------------------- /src/actions/attributes.ts: -------------------------------------------------------------------------------- 1 | import { StreamElement, TurboStreamActions } from "@hotwired/turbo" 2 | 3 | import { camelize, typecast, tokenize } from "../utils" 4 | 5 | type TargetElement = { [key: string]: any } 6 | 7 | export function add_css_class(this: StreamElement) { 8 | const classes = tokenize(this.getAttribute("classes")) 9 | 10 | if (classes.length > 0) { 11 | this.targetElements.forEach((element: Element) => element.classList.add(...classes)) 12 | } else { 13 | console.warn(`[TurboPower] no "classes" provided for Turbo Streams operation "add_css_class"`) 14 | } 15 | } 16 | 17 | export function remove_attribute(this: StreamElement) { 18 | const attribute = this.getAttribute("attribute") 19 | 20 | if (attribute) { 21 | this.targetElements.forEach((element: Element) => element.removeAttribute(attribute)) 22 | } else { 23 | console.warn(`[TurboPower] no "attribute" provided for Turbo Streams operation "remove_attribute"`) 24 | } 25 | } 26 | 27 | export function remove_css_class(this: StreamElement) { 28 | const classes = tokenize(this.getAttribute("classes")) 29 | 30 | if (classes.length > 0) { 31 | this.targetElements.forEach((element: Element) => element.classList.remove(...classes)) 32 | } else { 33 | console.warn(`[TurboPower] no "classes" provided for Turbo Streams operation "remove_css_class"`) 34 | } 35 | } 36 | 37 | export function set_attribute(this: StreamElement) { 38 | const attribute = this.getAttribute("attribute") 39 | const value = this.getAttribute("value") || "" 40 | 41 | if (attribute) { 42 | this.targetElements.forEach((element: Element) => element.setAttribute(attribute, value)) 43 | } else { 44 | console.warn(`[TurboPower] no "attribute" provided for Turbo Streams operation "set_attribute"`) 45 | } 46 | } 47 | 48 | export function toggle_attribute(this: StreamElement): void { 49 | const attribute: string | null = this.getAttribute("attribute") 50 | const force: string | null = this.getAttribute("force") 51 | 52 | if (!attribute) { 53 | console.warn(`[TurboPower] no "attribute" provided for Turbo Streams operation "toggle_attribute"`) 54 | return 55 | } 56 | 57 | const toggleForce: boolean | undefined = force === null ? undefined : force.toLowerCase() === "true" 58 | 59 | this.targetElements.forEach((element: HTMLElement): void => { 60 | element.toggleAttribute(attribute, toggleForce) 61 | }) 62 | } 63 | 64 | export function set_dataset_attribute(this: StreamElement) { 65 | const attribute = this.getAttribute("attribute") 66 | const value = this.getAttribute("value") || "" 67 | 68 | if (attribute) { 69 | this.targetElements.forEach((element: HTMLElement) => (element.dataset[camelize(attribute)] = value)) 70 | } else { 71 | console.warn(`[TurboPower] no "attribute" provided for Turbo Streams operation "set_dataset_attribute"`) 72 | } 73 | } 74 | 75 | export function set_property(this: StreamElement) { 76 | const name = this.getAttribute("name") 77 | const value = typecast(this.getAttribute("value") || "") 78 | 79 | if (name) { 80 | this.targetElements.forEach((element: TargetElement) => (element[name] = value)) 81 | } else { 82 | console.error(`[TurboPower] no "name" provided for Turbo Streams operation "set_property"`) 83 | } 84 | } 85 | 86 | export function set_style(this: StreamElement) { 87 | const name = this.getAttribute("name") 88 | const value = this.getAttribute("value") || "" 89 | 90 | if (name) { 91 | this.targetElements.forEach((element: TargetElement) => (element.style[name] = value)) 92 | } else { 93 | console.error(`[TurboPower] no "name" provided for Turbo Streams operation "set_style"`) 94 | } 95 | } 96 | 97 | export function set_styles(this: StreamElement) { 98 | const styles = this.getAttribute("styles") || "" 99 | 100 | this.targetElements.forEach((element: HTMLElement) => element.setAttribute("style", styles)) 101 | } 102 | 103 | export function set_value(this: StreamElement) { 104 | const value = this.getAttribute("value") || "" 105 | 106 | this.targetElements.forEach((element: HTMLInputElement) => (element.value = value)) 107 | } 108 | 109 | export function toggle_css_class(this: StreamElement) { 110 | const classes = tokenize(this.getAttribute("classes")) 111 | 112 | if (classes.length > 0) { 113 | this.targetElements.forEach((element: Element) => { 114 | classes.forEach((className: string) => element.classList.toggle(className)) 115 | }) 116 | } else { 117 | console.warn(`[TurboPower] no "classes" provided for Turbo Streams operation "toggle_css_class"`) 118 | } 119 | } 120 | 121 | export function replace_css_class(this: StreamElement) { 122 | const from = this.getAttribute("from") || "" 123 | const to = this.getAttribute("to") || "" 124 | 125 | if (from && to) { 126 | this.targetElements.forEach((element: HTMLElement) => { 127 | const wasReplaced = element.classList.replace(from, to) 128 | 129 | if (!wasReplaced) { 130 | console.warn( 131 | `[TurboPower] The "${from}" CSS class provided in the "from" attribute for the "replace_css_class" action was not found on the target element. No replacements made.`, 132 | element, 133 | ) 134 | } 135 | }) 136 | } else { 137 | console.warn(`[TurboPower] no "from" or "to" class provided for Turbo Streams operation "replace_css_class"`) 138 | } 139 | } 140 | 141 | export function registerAttributesActions(streamActions: TurboStreamActions) { 142 | streamActions.add_css_class = add_css_class 143 | streamActions.remove_css_class = remove_css_class 144 | streamActions.remove_attribute = remove_attribute 145 | streamActions.set_attribute = set_attribute 146 | streamActions.toggle_attribute = toggle_attribute 147 | streamActions.set_dataset_attribute = set_dataset_attribute 148 | streamActions.set_property = set_property 149 | streamActions.set_style = set_style 150 | streamActions.set_styles = set_styles 151 | streamActions.set_value = set_value 152 | streamActions.toggle_css_class = toggle_css_class 153 | streamActions.replace_css_class = replace_css_class 154 | } 155 | -------------------------------------------------------------------------------- /src/actions/browser.ts: -------------------------------------------------------------------------------- 1 | import { StreamElement, TurboStreamActions } from "@hotwired/turbo" 2 | 3 | export function reload(this: StreamElement) { 4 | window.location.reload() 5 | } 6 | 7 | export function scroll_into_view(this: StreamElement) { 8 | const alignToTop = this.getAttribute("align-to-top") 9 | const block = this.getAttribute("block") as ScrollLogicalPosition 10 | const inline = this.getAttribute("inline") as ScrollLogicalPosition 11 | const behavior = this.getAttribute("behavior") as ScrollBehavior 12 | 13 | if (alignToTop) { 14 | this.targetElements.forEach((element: Element) => element.scrollIntoView(alignToTop === "true")) 15 | } else if (block || inline || behavior) { 16 | const options: ScrollIntoViewOptions = {} 17 | 18 | if (block) options.block = block 19 | if (inline) options.inline = inline 20 | if (behavior) options.behavior = behavior 21 | 22 | this.targetElements.forEach((element: Element) => element.scrollIntoView(options)) 23 | } else { 24 | this.targetElements.forEach((element: Element) => element.scrollIntoView()) 25 | } 26 | } 27 | 28 | export function set_focus(this: StreamElement) { 29 | this.targetElements.forEach((element: HTMLElement) => element.focus()) 30 | } 31 | 32 | export function set_title(this: StreamElement) { 33 | const title = this.getAttribute("title") || "" 34 | let titleElement = document.head.querySelector("title") 35 | 36 | if (!titleElement) { 37 | titleElement = document.createElement("title") 38 | document.head.appendChild(titleElement) 39 | } 40 | 41 | titleElement.textContent = title 42 | } 43 | 44 | export function registerBrowserActions(streamActions: TurboStreamActions) { 45 | streamActions.reload = reload 46 | streamActions.scroll_into_view = scroll_into_view 47 | streamActions.set_focus = set_focus 48 | streamActions.set_title = set_title 49 | } 50 | -------------------------------------------------------------------------------- /src/actions/debug.ts: -------------------------------------------------------------------------------- 1 | import { StreamElement, TurboStreamActions } from "@hotwired/turbo" 2 | 3 | // turbo_stream.console_log(message, level = :log) 4 | export function console_log(this: StreamElement) { 5 | type ConsoleLevel = "log" | "info" | "warn" | "debug" | "error" 6 | 7 | const message = this.getAttribute("message") 8 | const level = (this.getAttribute("level") || "log") as ConsoleLevel 9 | 10 | console[level](message) 11 | } 12 | 13 | // turbo_stream.console_table(data, columns) 14 | export function console_table(this: StreamElement) { 15 | const data = JSON.parse(this.getAttribute("data") || "[]") 16 | const columns = JSON.parse(this.getAttribute("columns") || "[]") 17 | 18 | console.table(data, columns) 19 | } 20 | 21 | export function registerDebugActions(streamActions: TurboStreamActions) { 22 | streamActions.console_log = console_log 23 | streamActions.console_table = console_table 24 | } 25 | -------------------------------------------------------------------------------- /src/actions/deprecated.ts: -------------------------------------------------------------------------------- 1 | import { StreamElement, TurboStreamActions } from "@hotwired/turbo" 2 | 3 | export function invoke(this: StreamElement) { 4 | console.warn( 5 | "[TurboPower] The `invoke` Turbo Stream Action was removed from TurboPower. If you'd like to continue using this action please use the successor library instead. Read more here: https://github.com/hopsoft/turbo_boost-streams", 6 | ) 7 | } 8 | 9 | export function registerDeprecatedActions(streamActions: TurboStreamActions) { 10 | if (!streamActions.invoke) { 11 | streamActions.invoke = invoke 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/actions/document.ts: -------------------------------------------------------------------------------- 1 | import { StreamElement, TurboStreamActions } from "@hotwired/turbo" 2 | import { CookieStringBuilder } from "./document/cookie_string_builder" 3 | 4 | export function set_cookie(this: StreamElement) { 5 | const cookie = this.getAttribute("cookie") || "" 6 | 7 | document.cookie = cookie 8 | } 9 | 10 | export function set_cookie_item(this: StreamElement) { 11 | const cookieStringBuilder = new CookieStringBuilder(this) 12 | document.cookie = cookieStringBuilder.build() 13 | } 14 | 15 | export function registerDocumentActions(streamActions: TurboStreamActions) { 16 | streamActions.set_cookie = set_cookie 17 | streamActions.set_cookie_item = set_cookie_item 18 | } 19 | -------------------------------------------------------------------------------- /src/actions/document/cookie_string_builder.ts: -------------------------------------------------------------------------------- 1 | import { StreamElement } from "@hotwired/turbo" 2 | 3 | type MappingRow = [string, string, boolean] 4 | 5 | export class CookieStringBuilder { 6 | ATTRIBUTE_TO_COOKIE_KEY_MAPPING: MappingRow[] = [ 7 | ["domain", "Domain", false], 8 | ["path", "Path", false], 9 | ["expires", "Expires", false], 10 | ["max-age", "Max-Age", false], 11 | ["http-only", "HttpOnly", true], 12 | ["secure", "Secure", true], 13 | ["same-site", "SameSite", false], 14 | ] 15 | 16 | streamElement: StreamElement 17 | 18 | constructor(streamElement: StreamElement) { 19 | this.streamElement = streamElement 20 | } 21 | 22 | build(): string { 23 | let cookieString = `${this.streamElement.getAttribute("name")}=${this.streamElement.getAttribute("value")}` 24 | 25 | this.ATTRIBUTE_TO_COOKIE_KEY_MAPPING.forEach(([streamElementAttribute, cookieKey, isBooleanAttribute]) => { 26 | const cookieValue = this.streamElement.getAttribute(streamElementAttribute) 27 | 28 | if (cookieValue !== null) { 29 | const cookieKeyPair = isBooleanAttribute ? cookieKey : `${cookieKey}=${cookieValue}` 30 | cookieString = `${cookieString}; ${cookieKeyPair}` 31 | } 32 | }) 33 | 34 | return cookieString 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/actions/dom.ts: -------------------------------------------------------------------------------- 1 | import { StreamElement, TurboStreamActions } from "@hotwired/turbo" 2 | 3 | export function graft(this: StreamElement) { 4 | const selector = this.getAttribute("parent") 5 | 6 | if (selector) { 7 | const parent = document.querySelector(selector) 8 | 9 | if (parent) { 10 | this.targetElements.forEach((element: Element) => parent.appendChild(element)) 11 | } else { 12 | console.error( 13 | `[TurboPower] couldn't find parent element using selector "${selector}" for Turbo Streams operation "graft"`, 14 | ) 15 | } 16 | } else { 17 | console.error(`[TurboPower] no "parent" selector provided for Turbo Streams operation "graft"`) 18 | } 19 | } 20 | 21 | export function inner_html(this: StreamElement) { 22 | const html = this.templateContent.textContent || "" 23 | 24 | this.targetElements.forEach((element: Element) => (element.innerHTML = html)) 25 | } 26 | 27 | export function insert_adjacent_html(this: StreamElement) { 28 | const position = (this.getAttribute("position") || "beforebegin") as InsertPosition 29 | const html = this.templateContent.textContent || "" 30 | 31 | this.targetElements.forEach((element: Element) => element.insertAdjacentHTML(position, html)) 32 | } 33 | 34 | export function insert_adjacent_text(this: StreamElement) { 35 | const position = (this.getAttribute("position") || "beforebegin") as InsertPosition 36 | const message = this.getAttribute("text") || "" 37 | 38 | this.targetElements.forEach((element: Element) => element.insertAdjacentText(position, message)) 39 | } 40 | 41 | export function outer_html(this: StreamElement) { 42 | const html = this.templateContent.textContent || "" 43 | 44 | this.targetElements.forEach((element: Element) => (element.outerHTML = html)) 45 | } 46 | 47 | export function set_meta(this: StreamElement) { 48 | const name = this.getAttribute("name") 49 | const content = this.getAttribute("content") || "" 50 | 51 | if (name) { 52 | let meta: HTMLMetaElement | null = document.head.querySelector(`meta[name='${name}']`) 53 | 54 | if (!meta) { 55 | meta = document.createElement("meta") 56 | meta.name = name 57 | document.head.appendChild(meta) 58 | } 59 | 60 | meta.content = content 61 | } else { 62 | console.error(`[TurboPower] no "name" provided for Turbo Streams operation "set_meta"`) 63 | } 64 | } 65 | 66 | export function text_content(this: StreamElement) { 67 | const text = this.getAttribute("text") || "" 68 | 69 | this.targetElements.forEach((element: Element) => (element.textContent = text)) 70 | } 71 | 72 | export function registerDOMActions(streamActions: TurboStreamActions) { 73 | streamActions.graft = graft 74 | streamActions.inner_html = inner_html 75 | streamActions.insert_adjacent_html = insert_adjacent_html 76 | streamActions.insert_adjacent_text = insert_adjacent_text 77 | streamActions.outer_html = outer_html 78 | streamActions.text_content = text_content 79 | streamActions.set_meta = set_meta 80 | } 81 | -------------------------------------------------------------------------------- /src/actions/events.ts: -------------------------------------------------------------------------------- 1 | import { StreamElement, TurboStreamActions } from "@hotwired/turbo" 2 | 3 | export function dispatch_event(this: StreamElement) { 4 | const name = this.getAttribute("name") 5 | let template = null 6 | 7 | try { 8 | template = this.templateContent.textContent 9 | } catch (e) { 10 | // default to empty object 11 | } 12 | 13 | try { 14 | const detail = template ? JSON.parse(template) : {} 15 | 16 | if (name) { 17 | const options = { bubbles: true, cancelable: true, detail } 18 | const event = new CustomEvent(name, options) 19 | 20 | this.targetElements.forEach((element: Element) => element.dispatchEvent(event)) 21 | } else { 22 | console.warn(`[TurboPower] no "name" provided for Turbo Streams operation "dispatch_event"`) 23 | } 24 | } catch (error: any) { 25 | console.error( 26 | `[TurboPower] error proccessing provided "detail" in "