proscenium 0.14.0-x86_64-darwin → 0.15.0.beta.1-x86_64-darwin
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +63 -54
- data/lib/proscenium/builder.rb +62 -19
- data/lib/proscenium/ensure_loaded.rb +6 -6
- data/lib/proscenium/ext/proscenium +0 -0
- data/lib/proscenium/ext/proscenium.h +16 -1
- data/lib/proscenium/helper.rb +23 -70
- data/lib/proscenium/importer.rb +2 -6
- data/lib/proscenium/libs/react-manager/index.jsx +56 -36
- data/lib/proscenium/log_subscriber.rb +14 -2
- data/lib/proscenium/middleware/esbuild.rb +2 -2
- data/lib/proscenium/monkey.rb +67 -32
- data/lib/proscenium/phlex/asset_inclusions.rb +4 -83
- data/lib/proscenium/phlex.rb +9 -1
- data/lib/proscenium/railtie.rb +21 -16
- data/lib/proscenium/react_componentable.rb +3 -3
- data/lib/proscenium/side_load.rb +120 -6
- data/lib/proscenium/version.rb +1 -1
- data/lib/proscenium/view_component.rb +7 -1
- data/lib/proscenium.rb +10 -0
- metadata +3 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 7929040e00f84812706b3c5b644cef6b850e2be1a6305a02c4b85e1926e00a67
         | 
| 4 | 
            +
              data.tar.gz: '067892643a5fdb9fccddf8312146f8c1c900ef308153fb74bd25277457f2b29c'
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: fc3f3b4b1ee7e052f0bd15a5fb4cf3321ad7cb3ab19d694778a67c38ba851543dc03b0599e47f1690382eac3fedf6c4cce76c7e8244f320f38dcd9015a5b2eb4
         | 
| 7 | 
            +
              data.tar.gz: 1f8892a2bc18ed763437e0981eb0ef43ffdb0fe03d415acbdd2598881bc635c4db603792a9aecfc31fbcd6bf05dd2a4a5e998b5f8eec2338cd7f8e816820d4cb
         | 
    
        data/README.md
    CHANGED
    
    | @@ -58,8 +58,8 @@ Getting started obviously depends on whether you are adding Proscenium to an exi | |
| 58 58 | 
             
            - [Getting Started with a new Rails app](https://github.com/joelmoss/proscenium/blob/master/docs/guides/new_rails_app.md)
         | 
| 59 59 | 
             
            - Getting Started with an existing Rails app
         | 
| 60 60 | 
             
              - [Migrate from Sprockets](docs/guides/migrate_from_sprockets.md)
         | 
| 61 | 
            -
              - Migrate from Propshaft  | 
| 62 | 
            -
              - Migrate from Webpacker  | 
| 61 | 
            +
              - Migrate from Propshaft _[Coming soon]_
         | 
| 62 | 
            +
              - Migrate from Webpacker _[Coming soon]_
         | 
| 63 63 | 
             
            - [Render a React component with Proscenium](docs/guides/basic_react.md)
         | 
| 64 64 |  | 
| 65 65 | 
             
            ## Installation
         | 
| @@ -162,29 +162,34 @@ Your application layout is at `/app/views/layouts/application.hml.erb`, and the | |
| 162 162 | 
             
            - `/app/views/users/index.js`
         | 
| 163 163 | 
             
            - `/app/views/users/_user.js` (partial)
         | 
| 164 164 |  | 
| 165 | 
            -
            Now, in your layout and view, replace the `javascript_include_tag` and `stylesheet_link_tag` helpers with the ` | 
| 165 | 
            +
            Now, in your layout and view, replace the `javascript_include_tag` and `stylesheet_link_tag` helpers with the `include_asset` helper from Proscenium. Something like this:
         | 
| 166 166 |  | 
| 167 167 | 
             
            ```erb
         | 
| 168 168 | 
             
            <!DOCTYPE html>
         | 
| 169 169 | 
             
            <html>
         | 
| 170 170 | 
             
              <head>
         | 
| 171 171 | 
             
                <title>Hello World</title>
         | 
| 172 | 
            -
                <%=  | 
| 172 | 
            +
                <%= include_assets # <-- %>
         | 
| 173 173 | 
             
              </head>
         | 
| 174 174 | 
             
              <body>
         | 
| 175 175 | 
             
                <%= yield %>
         | 
| 176 | 
            -
                <%= include_javascripts type: 'module', defer: true %>
         | 
| 177 176 | 
             
              </body>
         | 
| 178 177 | 
             
            </html>
         | 
| 179 178 | 
             
            ```
         | 
| 180 179 |  | 
| 181 | 
            -
             | 
| 180 | 
            +
            On each page request, Proscenium will check if any of your views, layouts and partials have a
         | 
| 181 | 
            +
            JS/TS/CSS file of the same name, and then include them wherever your placed the `include_assets`
         | 
| 182 | 
            +
            helper.
         | 
| 182 183 |  | 
| 183 | 
            -
             | 
| 184 | 
            +
            Now you never have to remember to include your assets again. Just create them alongside your views,
         | 
| 185 | 
            +
            partials and layouts, and Proscenium will take care of the rest.
         | 
| 184 186 |  | 
| 185 | 
            -
             | 
| 187 | 
            +
            Side loading is enabled by default, but you can disable it by setting `config.proscenium.side_load`
         | 
| 188 | 
            +
            to `false` in your `/config/application.rb`.
         | 
| 186 189 |  | 
| 187 | 
            -
             | 
| 190 | 
            +
            There are also `include_stylesheets` and `include_javascripts` helpers to allow you to control where
         | 
| 191 | 
            +
            the CSS and JS assets are included in the HTML. These helpers should be used instead of
         | 
| 192 | 
            +
            `include_assets` if you want to control exactly where the assets are included.
         | 
| 188 193 |  | 
| 189 194 | 
             
            ## Importing Assets
         | 
| 190 195 |  | 
| @@ -199,11 +204,11 @@ Imports are assumed to be JS files, so there is no need to specify the file exte | |
| 199 204 | 
             
            Any import beginning with `http://` or `https://` will be fetched from the URL provided. For example:
         | 
| 200 205 |  | 
| 201 206 | 
             
            ```js
         | 
| 202 | 
            -
            import React from  | 
| 207 | 
            +
            import React from "https://esm.sh/react";
         | 
| 203 208 | 
             
            ```
         | 
| 204 209 |  | 
| 205 210 | 
             
            ```css
         | 
| 206 | 
            -
            @import  | 
| 211 | 
            +
            @import "https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css";
         | 
| 207 212 | 
             
            ```
         | 
| 208 213 |  | 
| 209 214 | 
             
            URL imports are cached, so that each import is only fetched once per server restart.
         | 
| @@ -213,7 +218,7 @@ URL imports are cached, so that each import is only fetched once per server rest | |
| 213 218 | 
             
            Bare imports (imports not beginning with `./`, `/`, `https://`, `http://`) are fully supported, and will use your package manager of choice (eg, NPM, Yarn, pnpm) via the `package.json` file:
         | 
| 214 219 |  | 
| 215 220 | 
             
            ```js
         | 
| 216 | 
            -
            import React from  | 
| 221 | 
            +
            import React from "react";
         | 
| 217 222 | 
             
            ```
         | 
| 218 223 |  | 
| 219 224 | 
             
            ### Local Imports
         | 
| @@ -221,15 +226,15 @@ import React from 'react' | |
| 221 226 | 
             
            And of course you can import your own code, using relative or absolute paths (file extension is optional):
         | 
| 222 227 |  | 
| 223 228 | 
             
            ```js /app/views/layouts/application.js
         | 
| 224 | 
            -
            import utils from  | 
| 229 | 
            +
            import utils from "/lib/utils";
         | 
| 225 230 | 
             
            ```
         | 
| 226 231 |  | 
| 227 232 | 
             
            ```js /lib/utils.js
         | 
| 228 | 
            -
            import constants from  | 
| 233 | 
            +
            import constants from "./constants";
         | 
| 229 234 | 
             
            ```
         | 
| 230 235 |  | 
| 231 236 | 
             
            ```css /app/views/layouts/application.css
         | 
| 232 | 
            -
            @import  | 
| 237 | 
            +
            @import "/lib/reset";
         | 
| 233 238 | 
             
            ```
         | 
| 234 239 |  | 
| 235 240 | 
             
            ```css /lib/reset.css
         | 
| @@ -243,7 +248,7 @@ body { | |
| 243 248 | 
             
            Sometimes you don't want to bundle an import. For example, you want to ensure that only one instance of React is loaded. In this cases, you can use the `unbundle` prefix
         | 
| 244 249 |  | 
| 245 250 | 
             
            ```js
         | 
| 246 | 
            -
            import React from  | 
| 251 | 
            +
            import React from "unbundle:react";
         | 
| 247 252 | 
             
            ```
         | 
| 248 253 |  | 
| 249 254 | 
             
            This only works any bare and local imports.
         | 
| @@ -261,7 +266,7 @@ You can also use the `unbundle` prefix in your import map, which ensures that al | |
| 261 266 | 
             
            Then just import as normal:
         | 
| 262 267 |  | 
| 263 268 | 
             
            ```js
         | 
| 264 | 
            -
            import React from  | 
| 269 | 
            +
            import React from "react";
         | 
| 265 270 | 
             
            ```
         | 
| 266 271 |  | 
| 267 272 | 
             
            ## Import Maps
         | 
| @@ -280,7 +285,7 @@ Just create `config/import_map.json` and specify the imports you want to use. Fo | |
| 280 285 | 
             
                "react": "https://esm.sh/react@18.2.0",
         | 
| 281 286 | 
             
                "start": "/lib/start.js",
         | 
| 282 287 | 
             
                "common": "/lib/common.css",
         | 
| 283 | 
            -
                "@radix-ui/colors/": "https://esm.sh/@radix-ui/colors@0.1.8/" | 
| 288 | 
            +
                "@radix-ui/colors/": "https://esm.sh/@radix-ui/colors@0.1.8/"
         | 
| 284 289 | 
             
              }
         | 
| 285 290 | 
             
            }
         | 
| 286 291 | 
             
            ```
         | 
| @@ -288,26 +293,29 @@ Just create `config/import_map.json` and specify the imports you want to use. Fo | |
| 288 293 | 
             
            Using the above import map, we can do...
         | 
| 289 294 |  | 
| 290 295 | 
             
            ```js
         | 
| 291 | 
            -
            import { useCallback } from  | 
| 292 | 
            -
            import startHere from  | 
| 293 | 
            -
            import styles from  | 
| 296 | 
            +
            import { useCallback } from "react";
         | 
| 297 | 
            +
            import startHere from "start";
         | 
| 298 | 
            +
            import styles from "common";
         | 
| 294 299 | 
             
            ```
         | 
| 295 300 |  | 
| 296 301 | 
             
            and for CSS...
         | 
| 297 302 |  | 
| 298 303 | 
             
            ```css
         | 
| 299 | 
            -
            @import  | 
| 300 | 
            -
            @import  | 
| 304 | 
            +
            @import "common";
         | 
| 305 | 
            +
            @import "@radix-ui/colors/blue.css";
         | 
| 301 306 | 
             
            ```
         | 
| 302 307 |  | 
| 303 308 | 
             
            You can also write your import map in JavaScript instead of JSON. So instead of `config/import_map.json`, create `config/import_map.js`, and define an anonymous function. This function accepts a single `environment` argument.
         | 
| 304 309 |  | 
| 305 310 | 
             
            ```js
         | 
| 306 | 
            -
            env => ({
         | 
| 311 | 
            +
            (env) => ({
         | 
| 307 312 | 
             
              imports: {
         | 
| 308 | 
            -
                react: | 
| 309 | 
            -
             | 
| 310 | 
            -
             | 
| 313 | 
            +
                react:
         | 
| 314 | 
            +
                  env === "development"
         | 
| 315 | 
            +
                    ? "https://esm.sh/react@18.2.0?dev"
         | 
| 316 | 
            +
                    : "https://esm.sh/react@18.2.0",
         | 
| 317 | 
            +
              },
         | 
| 318 | 
            +
            });
         | 
| 311 319 | 
             
            ```
         | 
| 312 320 |  | 
| 313 321 | 
             
            ## Source Maps
         | 
| @@ -344,8 +352,8 @@ This assumes that the environment variable of the same name has already been def | |
| 344 352 | 
             
            These declared environment variables will be replaced with constant expressions, allowing you to use this like this:
         | 
| 345 353 |  | 
| 346 354 | 
             
            ```js
         | 
| 347 | 
            -
            console.log(proscenium.env.RAILS_ENV) // console.log("development")
         | 
| 348 | 
            -
            console.log(proscenium.env.RAILS_ENV ===  | 
| 355 | 
            +
            console.log(proscenium.env.RAILS_ENV); // console.log("development")
         | 
| 356 | 
            +
            console.log(proscenium.env.RAILS_ENV === "development"); // console.log(true)
         | 
| 349 357 | 
             
            ```
         | 
| 350 358 |  | 
| 351 359 | 
             
            The `RAILS_ENV` and `NODE_ENV` environment variables will always automatically be declared for you.
         | 
| @@ -356,24 +364,24 @@ Environment variables are particularly powerful in aiding [tree shaking](#tree-s | |
| 356 364 |  | 
| 357 365 | 
             
            ```js
         | 
| 358 366 | 
             
            function start() {
         | 
| 359 | 
            -
              console.log("start")
         | 
| 367 | 
            +
              console.log("start");
         | 
| 360 368 | 
             
            }
         | 
| 361 369 | 
             
            function doSomethingDangerous() {
         | 
| 362 | 
            -
              console.log("resetDatabase")
         | 
| 370 | 
            +
              console.log("resetDatabase");
         | 
| 363 371 | 
             
            }
         | 
| 364 372 |  | 
| 365 | 
            -
            proscenium.env.RAILS_ENV === "development" && doSomethingDangerous()
         | 
| 373 | 
            +
            proscenium.env.RAILS_ENV === "development" && doSomethingDangerous();
         | 
| 366 374 |  | 
| 367 | 
            -
            start()
         | 
| 375 | 
            +
            start();
         | 
| 368 376 | 
             
            ```
         | 
| 369 377 |  | 
| 370 378 | 
             
            In development the above code will be transformed into the following code, discarding the definition, and call to`doSomethingDangerous()`.
         | 
| 371 379 |  | 
| 372 380 | 
             
            ```js
         | 
| 373 381 | 
             
            function start() {
         | 
| 374 | 
            -
              console.log("start")
         | 
| 382 | 
            +
              console.log("start");
         | 
| 375 383 | 
             
            }
         | 
| 376 | 
            -
            start()
         | 
| 384 | 
            +
            start();
         | 
| 377 385 | 
             
            ```
         | 
| 378 386 |  | 
| 379 387 | 
             
            Please note that for security reasons environment variables are not replaced in URL imports.
         | 
| @@ -381,7 +389,7 @@ Please note that for security reasons environment variables are not replaced in | |
| 381 389 | 
             
            An undefined environment variable will be replaced with `undefined`.
         | 
| 382 390 |  | 
| 383 391 | 
             
            ```js
         | 
| 384 | 
            -
            console.log(proscenium.env.UNKNOWN) // console.log((void 0).UNKNOWN)
         | 
| 392 | 
            +
            console.log(proscenium.env.UNKNOWN); // console.log((void 0).UNKNOWN)
         | 
| 385 393 | 
             
            ```
         | 
| 386 394 |  | 
| 387 395 | 
             
            This means that code that relies on this will not be tree shaken. You can work around this by using the [optional chaining operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining):
         | 
| @@ -397,7 +405,7 @@ if (typeof proscenium.env?.UNKNOWN !== "undefined") { | |
| 397 405 | 
             
            Basic support is provided for importing your Rails locale files from `config/locales/*.yml`, exporting them as JSON.
         | 
| 398 406 |  | 
| 399 407 | 
             
            ```js
         | 
| 400 | 
            -
            import translations from  | 
| 408 | 
            +
            import translations from "@proscenium/i18n";
         | 
| 401 409 | 
             
            // translations.en.*
         | 
| 402 410 | 
             
            ```
         | 
| 403 411 |  | 
| @@ -411,12 +419,12 @@ Tree shaking is the term the JavaScript community uses for dead code elimination | |
| 411 419 |  | 
| 412 420 | 
             
            ```javascript
         | 
| 413 421 | 
             
            function one() {
         | 
| 414 | 
            -
              console.log( | 
| 422 | 
            +
              console.log("one");
         | 
| 415 423 | 
             
            }
         | 
| 416 424 | 
             
            function two() {
         | 
| 417 | 
            -
              console.log( | 
| 425 | 
            +
              console.log("two");
         | 
| 418 426 | 
             
            }
         | 
| 419 | 
            -
            one()
         | 
| 427 | 
            +
            one();
         | 
| 420 428 | 
             
            ```
         | 
| 421 429 |  | 
| 422 430 | 
             
            The above code will be transformed to the following code, discarding `two()`, as it is never called.
         | 
| @@ -466,6 +474,7 @@ If these files are side loaded, then `father.js` will be split off into a separa | |
| 466 474 | 
             
            - Without code splitting, an import() expression becomes `Promise.resolve().then(() => require())` instead. This still preserves the asynchronous semantics of the expression but it means the imported code is included in the same bundle instead of being split off into a separate file.
         | 
| 467 475 |  | 
| 468 476 | 
             
            Code splitting is enabled by default. You can disable it by setting the `code_splitting` configuration option to `false` in your application's `/config/application.rb`:
         | 
| 477 | 
            +
             | 
| 469 478 | 
             
            ```ruby
         | 
| 470 479 | 
             
            config.proscenium.code_splitting = false
         | 
| 471 480 | 
             
            ```
         | 
| @@ -487,11 +496,11 @@ The new CSS nesting syntax is supported, and transformed into non-nested CSS for | |
| 487 496 | 
             
            You can also import CSS from JavaScript. When you do this, Proscenium will automatically append each stylesheet to the document's head as a `<link>` element.
         | 
| 488 497 |  | 
| 489 498 | 
             
            ```jsx
         | 
| 490 | 
            -
            import  | 
| 499 | 
            +
            import "./button.css";
         | 
| 491 500 |  | 
| 492 501 | 
             
            export let Button = ({ text }) => {
         | 
| 493 | 
            -
              return <div className="button">{text}</div | 
| 494 | 
            -
            }
         | 
| 502 | 
            +
              return <div className="button">{text}</div>;
         | 
| 503 | 
            +
            };
         | 
| 495 504 | 
             
            ```
         | 
| 496 505 |  | 
| 497 506 | 
             
            ### CSS Modules
         | 
| @@ -564,7 +573,7 @@ css_module :my_module_name, path: Rails.root.join('app/components/button.css') | |
| 564 573 | 
             
            Importing a CSS module from JS will automatically append the stylesheet to the document's head. And the result of the import will be an object of CSS class to module names.
         | 
| 565 574 |  | 
| 566 575 | 
             
            ```js
         | 
| 567 | 
            -
            import styles from  | 
| 576 | 
            +
            import styles from "./styles.module.css";
         | 
| 568 577 | 
             
            // styles == { header: 'header-5564cdbb' }
         | 
| 569 578 | 
             
            ```
         | 
| 570 579 |  | 
| @@ -592,7 +601,7 @@ Use a mixin using the `@mixin` at-rule. Pass it the name of the mixin you want t | |
| 592 601 | 
             
            ```css
         | 
| 593 602 | 
             
            // /app/views/layouts/application.css
         | 
| 594 603 | 
             
            p {
         | 
| 595 | 
            -
              @mixin bigText from url( | 
| 604 | 
            +
              @mixin bigText from url("/lib/mixins.css");
         | 
| 596 605 | 
             
              color: red;
         | 
| 597 606 | 
             
            }
         | 
| 598 607 | 
             
            ```
         | 
| @@ -640,8 +649,8 @@ There are a few important caveats as far as Typescript is concerned. These are [ | |
| 640 649 | 
             
            Using JSX syntax usually requires you to manually import the JSX library you are using. For example, if you are using React, by default you will need to import React into each JSX file like this:
         | 
| 641 650 |  | 
| 642 651 | 
             
            ```javascript
         | 
| 643 | 
            -
            import * as React from  | 
| 644 | 
            -
            render(<div/>)
         | 
| 652 | 
            +
            import * as React from "react";
         | 
| 653 | 
            +
            render(<div />);
         | 
| 645 654 | 
             
            ```
         | 
| 646 655 |  | 
| 647 656 | 
             
            This is because the JSX transform turns JSX syntax into a call to `React.createElement` but it does not itself import anything, so the React variable is not automatically present.
         | 
| @@ -655,15 +664,15 @@ In the [not too distant] future, you will be able to configure Proscenium to use | |
| 655 664 | 
             
            Importing .json files parses the JSON file into a JavaScript object, and exports the object as the default export. Using it looks something like this:
         | 
| 656 665 |  | 
| 657 666 | 
             
            ```javascript
         | 
| 658 | 
            -
            import object from  | 
| 659 | 
            -
            console.log(object)
         | 
| 667 | 
            +
            import object from "./example.json";
         | 
| 668 | 
            +
            console.log(object);
         | 
| 660 669 | 
             
            ```
         | 
| 661 670 |  | 
| 662 671 | 
             
            In addition to the default export, there are also named exports for each top-level property in the JSON object. Importing a named export directly means Proscenium can automatically remove unused parts of the JSON file from the bundle, leaving only the named exports that you actually used. For example, this code will only include the version field when bundled:
         | 
| 663 672 |  | 
| 664 673 | 
             
            ```javascript
         | 
| 665 | 
            -
            import { version } from  | 
| 666 | 
            -
            console.log(version)
         | 
| 674 | 
            +
            import { version } from "./package.json";
         | 
| 675 | 
            +
            console.log(version);
         | 
| 667 676 | 
             
            ```
         | 
| 668 677 |  | 
| 669 678 | 
             
            ## Phlex Support
         | 
| @@ -682,14 +691,14 @@ In your layouts, include `Proscenium::Phlex::AssetInclusions`, and call the `inc | |
| 682 691 |  | 
| 683 692 | 
             
            ```ruby
         | 
| 684 693 | 
             
            class ApplicationLayout < Proscenium::Phlex
         | 
| 685 | 
            -
              include Proscenium::Phlex::AssetInclusions
         | 
| 694 | 
            +
              include Proscenium::Phlex::AssetInclusions # <--
         | 
| 686 695 |  | 
| 687 696 | 
             
              def template(&)
         | 
| 688 697 | 
             
                doctype
         | 
| 689 698 | 
             
                html do
         | 
| 690 699 | 
             
                  head do
         | 
| 691 700 | 
             
                    title { 'My Awesome App' }
         | 
| 692 | 
            -
                    include_assets
         | 
| 701 | 
            +
                    include_assets # <--
         | 
| 693 702 | 
             
                  end
         | 
| 694 703 | 
             
                  body(&)
         | 
| 695 704 | 
             
                end
         | 
| @@ -798,7 +807,7 @@ The view above will be rendered something like this: | |
| 798 807 |  | 
| 799 808 | 
             
            ## Cache Busting
         | 
| 800 809 |  | 
| 801 | 
            -
            >  | 
| 810 | 
            +
            > _COMING SOON_
         | 
| 802 811 |  | 
| 803 812 | 
             
            By default, all assets are not cached by the browser. But if in production, you populate the `REVISION` env variable, all CSS and JS URL's will be appended with its value as a query string, and the `Cache-Control` response header will be set to `public` and a max-age of 30 days.
         | 
| 804 813 |  | 
    
        data/lib/proscenium/builder.rb
    CHANGED
    
    | @@ -18,19 +18,34 @@ module Proscenium | |
| 18 18 |  | 
| 19 19 | 
             
                  enum :environment, [:development, 1, :test, :production]
         | 
| 20 20 |  | 
| 21 | 
            -
                  attach_function : | 
| 22 | 
            -
                    :string,      #  | 
| 23 | 
            -
                    :string,      #  | 
| 24 | 
            -
                    :string,      #  | 
| 21 | 
            +
                  attach_function :build_to_string, [
         | 
| 22 | 
            +
                    :string,      # Path or entry point.
         | 
| 23 | 
            +
                    :string,      # Base URL of the Rails app. eg. https://example.com
         | 
| 24 | 
            +
                    :string,      # Path to import map, relative to root
         | 
| 25 25 | 
             
                    :string,      # ENV variables as a JSON string
         | 
| 26 26 |  | 
| 27 27 | 
             
                    # Config
         | 
| 28 28 | 
             
                    :string,      # Rails application root
         | 
| 29 29 | 
             
                    :string,      # Proscenium gem root
         | 
| 30 30 | 
             
                    :environment, # Rails environment as a Symbol
         | 
| 31 | 
            -
                    :bool,        #  | 
| 32 | 
            -
                    :string,      #  | 
| 33 | 
            -
                    :bool         #  | 
| 31 | 
            +
                    :bool,        # Code splitting enabled?
         | 
| 32 | 
            +
                    :string,      # Engine names and paths as a JSON string
         | 
| 33 | 
            +
                    :bool         # Debugging enabled?
         | 
| 34 | 
            +
                  ], Result.by_value
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  attach_function :build_to_path, [
         | 
| 37 | 
            +
                    :string,      # Path or entry point. Multiple can be given by separating with a semi-colon
         | 
| 38 | 
            +
                    :string,      # Base URL of the Rails app. eg. https://example.com
         | 
| 39 | 
            +
                    :string,      # Path to import map, relative to root
         | 
| 40 | 
            +
                    :string,      # ENV variables as a JSON string
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    # Config
         | 
| 43 | 
            +
                    :string,      # Rails application root
         | 
| 44 | 
            +
                    :string,      # Proscenium gem root
         | 
| 45 | 
            +
                    :environment, # Rails environment as a Symbol
         | 
| 46 | 
            +
                    :bool,        # Code splitting enabled?
         | 
| 47 | 
            +
                    :string,      # Engine names and paths as a JSON string
         | 
| 48 | 
            +
                    :bool         # Debugging enabled?
         | 
| 34 49 | 
             
                  ], Result.by_value
         | 
| 35 50 |  | 
| 36 51 | 
             
                  attach_function :resolve, [
         | 
| @@ -68,8 +83,12 @@ module Proscenium | |
| 68 83 | 
             
                  end
         | 
| 69 84 | 
             
                end
         | 
| 70 85 |  | 
| 71 | 
            -
                def self. | 
| 72 | 
            -
                  new(root: root, base_url: base_url). | 
| 86 | 
            +
                def self.build_to_path(path, root: nil, base_url: nil)
         | 
| 87 | 
            +
                  new(root: root, base_url: base_url).build_to_path(path)
         | 
| 88 | 
            +
                end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                def self.build_to_string(path, root: nil, base_url: nil)
         | 
| 91 | 
            +
                  new(root: root, base_url: base_url).build_to_string(path)
         | 
| 73 92 | 
             
                end
         | 
| 74 93 |  | 
| 75 94 | 
             
                def self.resolve(path, root: nil)
         | 
| @@ -81,15 +100,35 @@ module Proscenium | |
| 81 100 | 
             
                  @base_url = base_url
         | 
| 82 101 | 
             
                end
         | 
| 83 102 |  | 
| 84 | 
            -
                def  | 
| 85 | 
            -
                  ActiveSupport::Notifications.instrument(' | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 103 | 
            +
                def build_to_path(path) # rubocop:disable Metrics/AbcSize
         | 
| 104 | 
            +
                  ActiveSupport::Notifications.instrument('build_to_path.proscenium',
         | 
| 105 | 
            +
                                                          identifier: path,
         | 
| 106 | 
            +
                                                          cached: Proscenium.cache.exist?(path)) do
         | 
| 107 | 
            +
                    Proscenium.cache.fetch path do
         | 
| 108 | 
            +
                      result = Request.build_to_path(path, @base_url, import_map, env_vars.to_json,
         | 
| 109 | 
            +
                                                     @root.to_s,
         | 
| 110 | 
            +
                                                     gem_root,
         | 
| 111 | 
            +
                                                     Rails.env.to_sym,
         | 
| 112 | 
            +
                                                     Proscenium.config.code_splitting,
         | 
| 113 | 
            +
                                                     engines.to_json,
         | 
| 114 | 
            +
                                                     Proscenium.config.debug)
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                      raise BuildError, result[:response] unless result[:success]
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                      result[:response]
         | 
| 119 | 
            +
                    end
         | 
| 120 | 
            +
                  end
         | 
| 121 | 
            +
                end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                def build_to_string(path)
         | 
| 124 | 
            +
                  ActiveSupport::Notifications.instrument('build_to_string.proscenium', identifier: path) do
         | 
| 125 | 
            +
                    result = Request.build_to_string(path, @base_url, import_map, env_vars.to_json,
         | 
| 126 | 
            +
                                                     @root.to_s,
         | 
| 127 | 
            +
                                                     gem_root,
         | 
| 128 | 
            +
                                                     Rails.env.to_sym,
         | 
| 129 | 
            +
                                                     Proscenium.config.code_splitting,
         | 
| 130 | 
            +
                                                     engines.to_json,
         | 
| 131 | 
            +
                                                     Proscenium.config.debug)
         | 
| 93 132 |  | 
| 94 133 | 
             
                    raise BuildError, result[:response] unless result[:success]
         | 
| 95 134 |  | 
| @@ -100,7 +139,7 @@ module Proscenium | |
| 100 139 | 
             
                def resolve(path)
         | 
| 101 140 | 
             
                  ActiveSupport::Notifications.instrument('resolve.proscenium', identifier: path) do
         | 
| 102 141 | 
             
                    result = Request.resolve(path, import_map, @root.to_s,
         | 
| 103 | 
            -
                                              | 
| 142 | 
            +
                                             gem_root,
         | 
| 104 143 | 
             
                                             Rails.env.to_sym,
         | 
| 105 144 | 
             
                                             Proscenium.config.debug)
         | 
| 106 145 | 
             
                    raise ResolveError.new(path, result[:response]) unless result[:success]
         | 
| @@ -140,5 +179,9 @@ module Proscenium | |
| 140 179 |  | 
| 141 180 | 
             
                  nil
         | 
| 142 181 | 
             
                end
         | 
| 182 | 
            +
             | 
| 183 | 
            +
                def gem_root
         | 
| 184 | 
            +
                  Pathname.new(__dir__).join('..', '..').to_s
         | 
| 185 | 
            +
                end
         | 
| 143 186 | 
             
              end
         | 
| 144 187 | 
             
            end
         | 
| @@ -9,15 +9,15 @@ module Proscenium | |
| 9 9 | 
             
                    append_after_action do
         | 
| 10 10 | 
             
                      if request.format.html? && Importer.imported?
         | 
| 11 11 | 
             
                        if Importer.js_imported?
         | 
| 12 | 
            -
                          raise NotIncludedError, 'There are javascripts to be included, but  | 
| 13 | 
            -
                                                  'not been included in the page. Did you forget  | 
| 14 | 
            -
                                                  '`# | 
| 12 | 
            +
                          raise NotIncludedError, 'There are side loaded javascripts to be included, but ' \
         | 
| 13 | 
            +
                                                  'they have not been included in the page. Did you forget ' \
         | 
| 14 | 
            +
                                                  'to add the `#include_assets` helper in your views?'
         | 
| 15 15 | 
             
                        end
         | 
| 16 16 |  | 
| 17 17 | 
             
                        if Importer.css_imported?
         | 
| 18 | 
            -
                          raise NotIncludedError, 'There are stylesheets to be included, but  | 
| 19 | 
            -
                                                  'not been included in the page. Did you forget  | 
| 20 | 
            -
                                                  '`# | 
| 18 | 
            +
                          raise NotIncludedError, 'There are side loaded stylesheets to be included, but ' \
         | 
| 19 | 
            +
                                                  'they have not been included in the page. Did you forget ' \
         | 
| 20 | 
            +
                                                  'to add the `#include_assets` helper in your views?'
         | 
| 21 21 | 
             
                        end
         | 
| 22 22 | 
             
                      end
         | 
| 23 23 | 
             
                    end
         | 
| Binary file | 
| @@ -83,6 +83,21 @@ extern "C" { | |
| 83 83 | 
             
            #endif
         | 
| 84 84 |  | 
| 85 85 |  | 
| 86 | 
            +
            // Build the given `path` in the `root`.
         | 
| 87 | 
            +
            //
         | 
| 88 | 
            +
            //	BuildOptions
         | 
| 89 | 
            +
            //	- path - The path to build relative to `root`.
         | 
| 90 | 
            +
            //	- baseUrl - base URL of the Rails app. eg. https://example.com
         | 
| 91 | 
            +
            //	- importMap - Path to the import map relative to `root`.
         | 
| 92 | 
            +
            //	- envVars - JSON string of environment variables.
         | 
| 93 | 
            +
            //	Config:
         | 
| 94 | 
            +
            //	- root - The working directory.
         | 
| 95 | 
            +
            //	- env - The environment (1 = development, 2 = test, 3 = production)
         | 
| 96 | 
            +
            //	- codeSpitting?
         | 
| 97 | 
            +
            //	- debug?
         | 
| 98 | 
            +
            //
         | 
| 99 | 
            +
            extern struct Result build_to_string(char* filepath, char* baseUrl, char* importMap, char* envVars, char* appRoot, char* gemPath, unsigned int env, GoUint8 codeSplitting, char* engines, GoUint8 debug);
         | 
| 100 | 
            +
             | 
| 86 101 | 
             
            // Build the given `path` in the `root`.
         | 
| 87 102 | 
             
            //
         | 
| 88 103 | 
             
            //	BuildOptions
         | 
| @@ -97,7 +112,7 @@ extern "C" { | |
| 97 112 | 
             
            //	- codeSpitting?
         | 
| 98 113 | 
             
            //	- debug?
         | 
| 99 114 | 
             
            //
         | 
| 100 | 
            -
            extern struct Result  | 
| 115 | 
            +
            extern struct Result build_to_path(char* filepath, char* baseUrl, char* importMap, char* envVars, char* appRoot, char* gemPath, unsigned int env, GoUint8 codeSplitting, char* engines, GoUint8 debug);
         | 
| 101 116 |  | 
| 102 117 | 
             
            // Resolve the given `path` relative to the `root`.
         | 
| 103 118 | 
             
            //
         | 
    
        data/lib/proscenium/helper.rb
    CHANGED
    
    | @@ -2,15 +2,23 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            module Proscenium
         | 
| 4 4 | 
             
              module Helper
         | 
| 5 | 
            +
                def sideload_assets(value)
         | 
| 6 | 
            +
                  if value.nil?
         | 
| 7 | 
            +
                    @current_template.instance_variable_defined?(:@sideload_assets_options) &&
         | 
| 8 | 
            +
                      @current_template.remove_instance_variable(:@sideload_assets_options)
         | 
| 9 | 
            +
                  else
         | 
| 10 | 
            +
                    @current_template.instance_variable_set :@sideload_assets_options, value
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                # Overriden to allow regular use of javascript_include_tag and stylesheet_link_tag, while still
         | 
| 15 | 
            +
                # building with Proscenium. It's important to note that `include_assets` will not call this, as
         | 
| 16 | 
            +
                # those asset paths all begin with a slash, which the Rails asset helpers do not pass through to
         | 
| 17 | 
            +
                # here.
         | 
| 5 18 | 
             
                def compute_asset_path(path, options = {})
         | 
| 6 19 | 
             
                  if %i[javascript stylesheet].include?(options[:type])
         | 
| 7 | 
            -
                    result =  | 
| 8 | 
            -
             | 
| 9 | 
            -
                    if (qs = Proscenium.config.cache_query_string)
         | 
| 10 | 
            -
                      result << "?#{qs}"
         | 
| 11 | 
            -
                    end
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                    return result
         | 
| 20 | 
            +
                    result = Proscenium::Builder.build_to_path(path, base_url: request.base_url)
         | 
| 21 | 
            +
                    return result.split('::').last.delete_prefix 'public'
         | 
| 14 22 | 
             
                  end
         | 
| 15 23 |  | 
| 16 24 | 
             
                  super
         | 
| @@ -40,78 +48,23 @@ module Proscenium | |
| 40 48 | 
             
                  CssModule::Transformer.new(path).class_names(*names).map { |name, _| name }.join(' ')
         | 
| 41 49 | 
             
                end
         | 
| 42 50 |  | 
| 43 | 
            -
                def  | 
| 44 | 
            -
                   | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
                   | 
| 51 | 
            +
                def include_assets
         | 
| 52 | 
            +
                  include_stylesheets + include_javascripts
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                def include_stylesheets
         | 
| 56 | 
            +
                  '<!-- [PROSCENIUM_STYLESHEETS] -->'.html_safe
         | 
| 49 57 | 
             
                end
         | 
| 50 58 | 
             
                alias side_load_stylesheets include_stylesheets
         | 
| 51 59 | 
             
                deprecate side_load_stylesheets: 'Use `include_stylesheets` instead', deprecator: Deprecator.new
         | 
| 52 60 |  | 
| 53 61 | 
             
                # Includes all javascripts that have been imported and side loaded.
         | 
| 54 62 | 
             
                #
         | 
| 55 | 
            -
                # @param extract_lazy_scripts [Boolean] if true, any lazy scripts will be extracted using
         | 
| 56 | 
            -
                #   `content_for` to `:proscenium_lazy_scripts` for later use. Be sure to include this in your
         | 
| 57 | 
            -
                #   page with the `declare_lazy_scripts` helper, or simply
         | 
| 58 | 
            -
                #   `content_for :proscenium_lazy_scripts`.
         | 
| 59 63 | 
             
                # @return [String] the HTML tags for the javascripts.
         | 
| 60 | 
            -
                def include_javascripts | 
| 61 | 
            -
                   | 
| 62 | 
            -
             | 
| 63 | 
            -
                  if Rails.application.config.proscenium.code_splitting && Importer.multiple_js_imported?
         | 
| 64 | 
            -
                    imports = Importer.imported.dup
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                    paths_to_build = []
         | 
| 67 | 
            -
                    Importer.each_javascript(delete: true) do |x, _|
         | 
| 68 | 
            -
                      paths_to_build << x.delete_prefix('/')
         | 
| 69 | 
            -
                    end
         | 
| 70 | 
            -
             | 
| 71 | 
            -
                    result = Builder.build(paths_to_build.join(';'), base_url: request.base_url)
         | 
| 72 | 
            -
             | 
| 73 | 
            -
                    # Remove the react components from the results, so they are not side loaded. Instead they
         | 
| 74 | 
            -
                    # are lazy loaded by the component manager.
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                    scripts = {}
         | 
| 77 | 
            -
                    result.split(';').each do |x|
         | 
| 78 | 
            -
                      inpath, outpath = x.split('::')
         | 
| 79 | 
            -
                      inpath.prepend '/'
         | 
| 80 | 
            -
                      outpath.delete_prefix! 'public'
         | 
| 81 | 
            -
             | 
| 82 | 
            -
                      next unless imports.key?(inpath)
         | 
| 83 | 
            -
             | 
| 84 | 
            -
                      if (import = imports[inpath]).delete(:lazy)
         | 
| 85 | 
            -
                        scripts[inpath] = import.merge(outpath: outpath)
         | 
| 86 | 
            -
                      else
         | 
| 87 | 
            -
                        out << javascript_include_tag(outpath, extname: false, **options)
         | 
| 88 | 
            -
                      end
         | 
| 89 | 
            -
                    end
         | 
| 90 | 
            -
             | 
| 91 | 
            -
                    if extract_lazy_scripts
         | 
| 92 | 
            -
                      content_for :proscenium_lazy_scripts do
         | 
| 93 | 
            -
                        tag.script type: 'application/json', id: 'prosceniumLazyScripts' do
         | 
| 94 | 
            -
                          raw scripts.to_json
         | 
| 95 | 
            -
                        end
         | 
| 96 | 
            -
                      end
         | 
| 97 | 
            -
                    else
         | 
| 98 | 
            -
                      out << tag.script(type: 'application/json', id: 'prosceniumLazyScripts') do
         | 
| 99 | 
            -
                        raw scripts.to_json
         | 
| 100 | 
            -
                      end
         | 
| 101 | 
            -
                    end
         | 
| 102 | 
            -
                  else
         | 
| 103 | 
            -
                    Importer.each_javascript(delete: true) do |path, _|
         | 
| 104 | 
            -
                      out << javascript_include_tag(path, extname: false, **options)
         | 
| 105 | 
            -
                    end
         | 
| 106 | 
            -
                  end
         | 
| 107 | 
            -
             | 
| 108 | 
            -
                  out.join("\n").html_safe
         | 
| 64 | 
            +
                def include_javascripts
         | 
| 65 | 
            +
                  '<!-- [PROSCENIUM_LAZY_SCRIPTS] --><!-- [PROSCENIUM_JAVASCRIPTS] -->'.html_safe
         | 
| 109 66 | 
             
                end
         | 
| 110 67 | 
             
                alias side_load_javascripts include_javascripts
         | 
| 111 68 | 
             
                deprecate side_load_javascripts: 'Use `include_javascripts` instead', deprecator: Deprecator.new
         | 
| 112 | 
            -
             | 
| 113 | 
            -
                def declare_lazy_scripts
         | 
| 114 | 
            -
                  content_for :proscenium_lazy_scripts
         | 
| 115 | 
            -
                end
         | 
| 116 69 | 
             
              end
         | 
| 117 70 | 
             
            end
         | 
    
        data/lib/proscenium/importer.rb
    CHANGED
    
    | @@ -72,8 +72,8 @@ module Proscenium | |
| 72 72 | 
             
                      end
         | 
| 73 73 | 
             
                    end
         | 
| 74 74 |  | 
| 75 | 
            -
                    JS_EXTENSIONS.find(&import_if_exists)
         | 
| 76 | 
            -
                    CSS_EXTENSIONS.find(&import_if_exists)
         | 
| 75 | 
            +
                    JS_EXTENSIONS.find(&import_if_exists) unless options[:js] == false
         | 
| 76 | 
            +
                    CSS_EXTENSIONS.find(&import_if_exists) unless options[:css] == false
         | 
| 77 77 | 
             
                  end
         | 
| 78 78 |  | 
| 79 79 | 
             
                  def each_stylesheet(delete: false)
         | 
| @@ -109,10 +109,6 @@ module Proscenium | |
| 109 109 | 
             
                    imported&.keys&.any? { |x| x.end_with?(*JS_EXTENSIONS) }
         | 
| 110 110 | 
             
                  end
         | 
| 111 111 |  | 
| 112 | 
            -
                  def multiple_js_imported?
         | 
| 113 | 
            -
                    imported&.keys&.many? { |x| x.end_with?(*JS_EXTENSIONS) }
         | 
| 114 | 
            -
                  end
         | 
| 115 | 
            -
             | 
| 116 112 | 
             
                  def imported?(filepath = nil)
         | 
| 117 113 | 
             
                    filepath ? imported&.key?(filepath) : !imported.blank?
         | 
| 118 114 | 
             
                  end
         |