@rspack/plugin-react-refresh 0.7.6-canary-1a0d77d-20240627143904 → 1.0.0-alpha.1
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.
- package/README.md +2 -2
- package/client/errorOverlayEntry.js +108 -0
- package/client/overlay/components/CompileErrorTrace.js +58 -0
- package/client/overlay/components/PageHeader.js +58 -0
- package/client/overlay/components/RuntimeErrorFooter.js +93 -0
- package/client/overlay/components/RuntimeErrorHeader.js +37 -0
- package/client/overlay/components/RuntimeErrorStack.js +79 -0
- package/client/overlay/components/Spacer.js +19 -0
- package/client/overlay/containers/CompileErrorContainer.js +25 -0
- package/client/overlay/containers/RuntimeErrorContainer.js +29 -0
- package/client/overlay/index.js +348 -0
- package/client/overlay/theme.js +39 -0
- package/client/overlay/utils.js +74 -0
- package/client/utils/ansi-html.js +305 -0
- package/client/utils/errorEventHandlers.js +102 -0
- package/client/utils/formatWebpackErrors.js +96 -0
- package/client/utils/retry.js +23 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +33 -3
- package/dist/options.d.ts +16 -1
- package/dist/options.js +19 -0
- package/dist/sockets/WDSSocket.d.ts +10 -0
- package/dist/sockets/WDSSocket.js +41 -0
- package/dist/sockets/utils/getCurrentScriptSource.d.ts +1 -0
- package/dist/sockets/utils/getCurrentScriptSource.js +26 -0
- package/dist/sockets/utils/getSocketUrlParts.d.ts +9 -0
- package/dist/sockets/utils/getSocketUrlParts.js +112 -0
- package/dist/sockets/utils/getUrlFromParts.d.ts +9 -0
- package/dist/sockets/utils/getUrlFromParts.js +32 -0
- package/dist/sockets/utils/getWDSMetadata.d.ts +5 -0
- package/dist/sockets/utils/getWDSMetadata.js +30 -0
- package/dist/utils/getAdditionalEntries.d.ts +9 -0
- package/dist/utils/getAdditionalEntries.js +93 -0
- package/dist/utils/getSocketIntegration.d.ts +2 -0
- package/dist/utils/getSocketIntegration.js +17 -0
- package/package.json +10 -5
    
        package/README.md
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            <picture>
         | 
| 2 | 
            -
              <source media="(prefers-color-scheme: dark)" srcset="https:// | 
| 3 | 
            -
              <img alt="Rspack Banner" src="https:// | 
| 2 | 
            +
              <source media="(prefers-color-scheme: dark)" srcset="https://assets.rspack.dev/rspack/rspack-banner-plain-dark.png">
         | 
| 3 | 
            +
              <img alt="Rspack Banner" src="https://assets.rspack.dev/rspack/rspack-banner-plain-light.png">
         | 
| 4 4 | 
             
            </picture>
         | 
| 5 5 |  | 
| 6 6 | 
             
            # @rspack/plugin-react-refresh
         | 
| @@ -0,0 +1,108 @@ | |
| 1 | 
            +
            /* global __react_refresh_error_overlay__, __react_refresh_socket__, __resourceQuery */
         | 
| 2 | 
            +
            /**
         | 
| 3 | 
            +
             * The following code is modified based on
         | 
| 4 | 
            +
             * https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/f1c8b9a44198449093ca95f85af5df97925e1cfc/client/ErrorOverlayEntry.js
         | 
| 5 | 
            +
             *
         | 
| 6 | 
            +
             * MIT Licensed
         | 
| 7 | 
            +
             * Author Michael Mok
         | 
| 8 | 
            +
             * Copyright (c) 2019 Michael Mok
         | 
| 9 | 
            +
             * https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/0b960573797bf38926937994c481e4fec9ed8aa6/LICENSE
         | 
| 10 | 
            +
             */
         | 
| 11 | 
            +
            const events = require('./utils/errorEventHandlers.js');
         | 
| 12 | 
            +
            const formatWebpackErrors = require('./utils/formatWebpackErrors.js');
         | 
| 13 | 
            +
            const runWithRetry = require('./utils/retry.js');
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            // Setup error states
         | 
| 16 | 
            +
            let isHotReload = false;
         | 
| 17 | 
            +
            let hasRuntimeErrors = false;
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            /**
         | 
| 20 | 
            +
             * Try dismissing the compile error overlay.
         | 
| 21 | 
            +
             * This will also reset runtime error records (if any),
         | 
| 22 | 
            +
             * because we have new source to evaluate.
         | 
| 23 | 
            +
             * @returns {void}
         | 
| 24 | 
            +
             */
         | 
| 25 | 
            +
            function tryDismissErrorOverlay() {
         | 
| 26 | 
            +
              __react_refresh_error_overlay__.clearCompileError();
         | 
| 27 | 
            +
              __react_refresh_error_overlay__.clearRuntimeErrors(!hasRuntimeErrors);
         | 
| 28 | 
            +
              hasRuntimeErrors = false;
         | 
| 29 | 
            +
            }
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            /**
         | 
| 32 | 
            +
             * A function called after a compile success signal is received from Webpack.
         | 
| 33 | 
            +
             * @returns {void}
         | 
| 34 | 
            +
             */
         | 
| 35 | 
            +
            function handleCompileSuccess() {
         | 
| 36 | 
            +
              isHotReload = true;
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              if (isHotReload) {
         | 
| 39 | 
            +
                tryDismissErrorOverlay();
         | 
| 40 | 
            +
              }
         | 
| 41 | 
            +
            }
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            /**
         | 
| 44 | 
            +
             * A function called after a compile errored signal is received from Webpack.
         | 
| 45 | 
            +
             * @param {string[]} errors
         | 
| 46 | 
            +
             * @returns {void}
         | 
| 47 | 
            +
             */
         | 
| 48 | 
            +
            function handleCompileErrors(errors) {
         | 
| 49 | 
            +
              isHotReload = true;
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              const formattedErrors = formatWebpackErrors(errors);
         | 
| 52 | 
            +
             | 
| 53 | 
            +
              // Only show the first error
         | 
| 54 | 
            +
              __react_refresh_error_overlay__.showCompileError(formattedErrors[0]);
         | 
| 55 | 
            +
            }
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            /**
         | 
| 58 | 
            +
             * Handles compilation messages from Webpack.
         | 
| 59 | 
            +
             * Integrates with a compile error overlay.
         | 
| 60 | 
            +
             * @param {*} message A Webpack HMR message sent via WebSockets.
         | 
| 61 | 
            +
             * @returns {void}
         | 
| 62 | 
            +
             */
         | 
| 63 | 
            +
            function compileMessageHandler(message) {
         | 
| 64 | 
            +
              switch (message.type) {
         | 
| 65 | 
            +
                case 'ok':
         | 
| 66 | 
            +
                case 'still-ok':
         | 
| 67 | 
            +
                case 'warnings': {
         | 
| 68 | 
            +
                  // TODO: Implement handling for warnings
         | 
| 69 | 
            +
                  handleCompileSuccess();
         | 
| 70 | 
            +
                  break;
         | 
| 71 | 
            +
                }
         | 
| 72 | 
            +
                case 'errors': {
         | 
| 73 | 
            +
                  handleCompileErrors(message.data);
         | 
| 74 | 
            +
                  break;
         | 
| 75 | 
            +
                }
         | 
| 76 | 
            +
                default: {
         | 
| 77 | 
            +
                  // Do nothing.
         | 
| 78 | 
            +
                }
         | 
| 79 | 
            +
              }
         | 
| 80 | 
            +
            }
         | 
| 81 | 
            +
             | 
| 82 | 
            +
            if (process.env.NODE_ENV !== 'production') {
         | 
| 83 | 
            +
              if (typeof window !== 'undefined') {
         | 
| 84 | 
            +
                function setupOverlay() {
         | 
| 85 | 
            +
                  // Only register if no other overlay have been registered
         | 
| 86 | 
            +
                  if (!window.__reactRefreshOverlayInjected && __react_refresh_socket__) {
         | 
| 87 | 
            +
                    // Registers handlers for compile errors with retry -
         | 
| 88 | 
            +
                    // This is to prevent mismatching injection order causing errors to be thrown
         | 
| 89 | 
            +
                    runWithRetry(function initSocket() {
         | 
| 90 | 
            +
                      __react_refresh_socket__.init(compileMessageHandler, __resourceQuery);
         | 
| 91 | 
            +
                    }, 3);
         | 
| 92 | 
            +
                    // Registers handlers for runtime errors
         | 
| 93 | 
            +
                    events.handleError(function handleError(error) {
         | 
| 94 | 
            +
                      hasRuntimeErrors = true;
         | 
| 95 | 
            +
                      __react_refresh_error_overlay__.handleRuntimeError(error);
         | 
| 96 | 
            +
                    });
         | 
| 97 | 
            +
                    events.handleUnhandledRejection(function handleUnhandledPromiseRejection(error) {
         | 
| 98 | 
            +
                      hasRuntimeErrors = true;
         | 
| 99 | 
            +
                      __react_refresh_error_overlay__.handleRuntimeError(error);
         | 
| 100 | 
            +
                    });
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                    // Mark overlay as injected to prevent double-injection
         | 
| 103 | 
            +
                    window.__reactRefreshOverlayInjected = true;
         | 
| 104 | 
            +
                  }
         | 
| 105 | 
            +
                };
         | 
| 106 | 
            +
                setupOverlay()
         | 
| 107 | 
            +
              }
         | 
| 108 | 
            +
            }
         | 
| @@ -0,0 +1,58 @@ | |
| 1 | 
            +
            const ansiHTML = require('../../utils/ansi-html.js');
         | 
| 2 | 
            +
            const entities = require('html-entities');
         | 
| 3 | 
            +
            const theme = require('../theme.js');
         | 
| 4 | 
            +
            const utils = require('../utils.js');
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            ansiHTML.setColors(theme);
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            /**
         | 
| 9 | 
            +
             * @typedef {Object} CompileErrorTraceProps
         | 
| 10 | 
            +
             * @property {string} errorMessage
         | 
| 11 | 
            +
             */
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            /**
         | 
| 14 | 
            +
             * A formatter that turns Webpack compile error messages into highlighted HTML source traces.
         | 
| 15 | 
            +
             * @param {Document} document
         | 
| 16 | 
            +
             * @param {HTMLElement} root
         | 
| 17 | 
            +
             * @param {CompileErrorTraceProps} props
         | 
| 18 | 
            +
             * @returns {void}
         | 
| 19 | 
            +
             */
         | 
| 20 | 
            +
            function CompileErrorTrace(document, root, props) {
         | 
| 21 | 
            +
              const errorParts = props.errorMessage.split('\n');
         | 
| 22 | 
            +
              if (errorParts.length) {
         | 
| 23 | 
            +
                if (errorParts[0]) {
         | 
| 24 | 
            +
                  errorParts[0] = utils.formatFilename(errorParts[0]);
         | 
| 25 | 
            +
                }
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                const errorMessage = errorParts.splice(1, 1)[0];
         | 
| 28 | 
            +
                if (errorMessage) {
         | 
| 29 | 
            +
                  // Strip filename from the error message
         | 
| 30 | 
            +
                  errorParts.unshift(errorMessage.replace(/^(.*:)\s.*:(\s.*)$/, '$1$2'));
         | 
| 31 | 
            +
                }
         | 
| 32 | 
            +
              }
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              const stackContainer = document.createElement('pre');
         | 
| 35 | 
            +
              stackContainer.innerHTML = entities.decode(
         | 
| 36 | 
            +
                ansiHTML(entities.encode(errorParts.join('\n'), { level: 'html5', mode: 'nonAscii' })),
         | 
| 37 | 
            +
                { level: 'html5' }
         | 
| 38 | 
            +
              );
         | 
| 39 | 
            +
              stackContainer.style.fontFamily = [
         | 
| 40 | 
            +
                '"Operator Mono SSm"',
         | 
| 41 | 
            +
                '"Operator Mono"',
         | 
| 42 | 
            +
                '"Fira Code Retina"',
         | 
| 43 | 
            +
                '"Fira Code"',
         | 
| 44 | 
            +
                '"FiraCode-Retina"',
         | 
| 45 | 
            +
                '"Andale Mono"',
         | 
| 46 | 
            +
                '"Lucida Console"',
         | 
| 47 | 
            +
                'Menlo',
         | 
| 48 | 
            +
                'Consolas',
         | 
| 49 | 
            +
                'Monaco',
         | 
| 50 | 
            +
                'monospace',
         | 
| 51 | 
            +
              ].join(', ');
         | 
| 52 | 
            +
              stackContainer.style.margin = '0';
         | 
| 53 | 
            +
              stackContainer.style.whiteSpace = 'pre-wrap';
         | 
| 54 | 
            +
             | 
| 55 | 
            +
              root.appendChild(stackContainer);
         | 
| 56 | 
            +
            }
         | 
| 57 | 
            +
             | 
| 58 | 
            +
            module.exports = CompileErrorTrace;
         | 
| @@ -0,0 +1,58 @@ | |
| 1 | 
            +
            const Spacer = require('./Spacer.js');
         | 
| 2 | 
            +
            const theme = require('../theme.js');
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            /**
         | 
| 5 | 
            +
             * @typedef {Object} PageHeaderProps
         | 
| 6 | 
            +
             * @property {string} [message]
         | 
| 7 | 
            +
             * @property {string} title
         | 
| 8 | 
            +
             * @property {string} [topOffset]
         | 
| 9 | 
            +
             */
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            /**
         | 
| 12 | 
            +
             * The header of the overlay.
         | 
| 13 | 
            +
             * @param {Document} document
         | 
| 14 | 
            +
             * @param {HTMLElement} root
         | 
| 15 | 
            +
             * @param {PageHeaderProps} props
         | 
| 16 | 
            +
             * @returns {void}
         | 
| 17 | 
            +
             */
         | 
| 18 | 
            +
            function PageHeader(document, root, props) {
         | 
| 19 | 
            +
              const pageHeaderContainer = document.createElement('div');
         | 
| 20 | 
            +
              pageHeaderContainer.style.background = '#' + theme.dimgrey;
         | 
| 21 | 
            +
              pageHeaderContainer.style.boxShadow = '0 1px 4px rgba(0, 0, 0, 0.3)';
         | 
| 22 | 
            +
              pageHeaderContainer.style.color = '#' + theme.white;
         | 
| 23 | 
            +
              pageHeaderContainer.style.left = '0';
         | 
| 24 | 
            +
              pageHeaderContainer.style.right = '0';
         | 
| 25 | 
            +
              pageHeaderContainer.style.padding = '1rem 1.5rem';
         | 
| 26 | 
            +
              pageHeaderContainer.style.paddingLeft = 'max(1.5rem, env(safe-area-inset-left))';
         | 
| 27 | 
            +
              pageHeaderContainer.style.paddingRight = 'max(1.5rem, env(safe-area-inset-right))';
         | 
| 28 | 
            +
              pageHeaderContainer.style.position = 'fixed';
         | 
| 29 | 
            +
              pageHeaderContainer.style.top = props.topOffset || '0';
         | 
| 30 | 
            +
             | 
| 31 | 
            +
              const title = document.createElement('h3');
         | 
| 32 | 
            +
              title.innerText = props.title;
         | 
| 33 | 
            +
              title.style.color = '#' + theme.red;
         | 
| 34 | 
            +
              title.style.fontSize = '1.125rem';
         | 
| 35 | 
            +
              title.style.lineHeight = '1.3';
         | 
| 36 | 
            +
              title.style.margin = '0';
         | 
| 37 | 
            +
              pageHeaderContainer.appendChild(title);
         | 
| 38 | 
            +
             | 
| 39 | 
            +
              if (props.message) {
         | 
| 40 | 
            +
                title.style.margin = '0 0 0.5rem';
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                const message = document.createElement('span');
         | 
| 43 | 
            +
                message.innerText = props.message;
         | 
| 44 | 
            +
                message.style.color = '#' + theme.white;
         | 
| 45 | 
            +
                message.style.wordBreak = 'break-word';
         | 
| 46 | 
            +
                pageHeaderContainer.appendChild(message);
         | 
| 47 | 
            +
              }
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              root.appendChild(pageHeaderContainer);
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              // This has to run after appending elements to root
         | 
| 52 | 
            +
              // because we need to actual mounted height.
         | 
| 53 | 
            +
              Spacer(document, root, {
         | 
| 54 | 
            +
                space: pageHeaderContainer.offsetHeight.toString(10),
         | 
| 55 | 
            +
              });
         | 
| 56 | 
            +
            }
         | 
| 57 | 
            +
             | 
| 58 | 
            +
            module.exports = PageHeader;
         | 
| @@ -0,0 +1,93 @@ | |
| 1 | 
            +
            const Spacer = require('./Spacer.js');
         | 
| 2 | 
            +
            const theme = require('../theme.js');
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            /**
         | 
| 5 | 
            +
             * @typedef {Object} RuntimeErrorFooterProps
         | 
| 6 | 
            +
             * @property {string} [initialFocus]
         | 
| 7 | 
            +
             * @property {boolean} multiple
         | 
| 8 | 
            +
             * @property {function(MouseEvent): void} onClickCloseButton
         | 
| 9 | 
            +
             * @property {function(MouseEvent): void} onClickNextButton
         | 
| 10 | 
            +
             * @property {function(MouseEvent): void} onClickPrevButton
         | 
| 11 | 
            +
             */
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            /**
         | 
| 14 | 
            +
             * A fixed footer that handles pagination of runtime errors.
         | 
| 15 | 
            +
             * @param {Document} document
         | 
| 16 | 
            +
             * @param {HTMLElement} root
         | 
| 17 | 
            +
             * @param {RuntimeErrorFooterProps} props
         | 
| 18 | 
            +
             * @returns {void}
         | 
| 19 | 
            +
             */
         | 
| 20 | 
            +
            function RuntimeErrorFooter(document, root, props) {
         | 
| 21 | 
            +
              const footer = document.createElement('div');
         | 
| 22 | 
            +
              footer.style.backgroundColor = '#' + theme.dimgrey;
         | 
| 23 | 
            +
              footer.style.bottom = '0';
         | 
| 24 | 
            +
              footer.style.boxShadow = '0 -1px 4px rgba(0, 0, 0, 0.3)';
         | 
| 25 | 
            +
              footer.style.height = '2.5rem';
         | 
| 26 | 
            +
              footer.style.left = '0';
         | 
| 27 | 
            +
              footer.style.right = '0';
         | 
| 28 | 
            +
              footer.style.lineHeight = '2.5rem';
         | 
| 29 | 
            +
              footer.style.paddingBottom = '0';
         | 
| 30 | 
            +
              footer.style.paddingBottom = 'env(safe-area-inset-bottom)';
         | 
| 31 | 
            +
              footer.style.position = 'fixed';
         | 
| 32 | 
            +
              footer.style.textAlign = 'center';
         | 
| 33 | 
            +
              footer.style.zIndex = '2';
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              const BUTTON_CONFIGS = {
         | 
| 36 | 
            +
                prev: {
         | 
| 37 | 
            +
                  id: 'prev',
         | 
| 38 | 
            +
                  label: '◀ Prev',
         | 
| 39 | 
            +
                  onClick: props.onClickPrevButton,
         | 
| 40 | 
            +
                },
         | 
| 41 | 
            +
                close: {
         | 
| 42 | 
            +
                  id: 'close',
         | 
| 43 | 
            +
                  label: '× Close',
         | 
| 44 | 
            +
                  onClick: props.onClickCloseButton,
         | 
| 45 | 
            +
                },
         | 
| 46 | 
            +
                next: {
         | 
| 47 | 
            +
                  id: 'next',
         | 
| 48 | 
            +
                  label: 'Next ▶',
         | 
| 49 | 
            +
                  onClick: props.onClickNextButton,
         | 
| 50 | 
            +
                },
         | 
| 51 | 
            +
              };
         | 
| 52 | 
            +
             | 
| 53 | 
            +
              let buttons = [BUTTON_CONFIGS.close];
         | 
| 54 | 
            +
              if (props.multiple) {
         | 
| 55 | 
            +
                buttons = [BUTTON_CONFIGS.prev, BUTTON_CONFIGS.close, BUTTON_CONFIGS.next];
         | 
| 56 | 
            +
              }
         | 
| 57 | 
            +
             | 
| 58 | 
            +
              /** @type {HTMLButtonElement | undefined} */
         | 
| 59 | 
            +
              let initialFocusButton;
         | 
| 60 | 
            +
              for (let i = 0; i < buttons.length; i += 1) {
         | 
| 61 | 
            +
                const buttonConfig = buttons[i];
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                const button = document.createElement('button');
         | 
| 64 | 
            +
                button.id = buttonConfig.id;
         | 
| 65 | 
            +
                button.innerHTML = buttonConfig.label;
         | 
| 66 | 
            +
                button.tabIndex = 1;
         | 
| 67 | 
            +
                button.style.backgroundColor = '#' + theme.dimgrey;
         | 
| 68 | 
            +
                button.style.border = 'none';
         | 
| 69 | 
            +
                button.style.color = '#' + theme.white;
         | 
| 70 | 
            +
                button.style.cursor = 'pointer';
         | 
| 71 | 
            +
                button.style.fontSize = 'inherit';
         | 
| 72 | 
            +
                button.style.height = '100%';
         | 
| 73 | 
            +
                button.style.padding = '0.5rem 0.75rem';
         | 
| 74 | 
            +
                button.style.width = (100 / buttons.length).toString(10) + '%';
         | 
| 75 | 
            +
                button.addEventListener('click', buttonConfig.onClick);
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                if (buttonConfig.id === props.initialFocus) {
         | 
| 78 | 
            +
                  initialFocusButton = button;
         | 
| 79 | 
            +
                }
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                footer.appendChild(button);
         | 
| 82 | 
            +
              }
         | 
| 83 | 
            +
             | 
| 84 | 
            +
              root.appendChild(footer);
         | 
| 85 | 
            +
             | 
| 86 | 
            +
              Spacer(document, root, { space: '2.5rem' });
         | 
| 87 | 
            +
             | 
| 88 | 
            +
              if (initialFocusButton) {
         | 
| 89 | 
            +
                initialFocusButton.focus();
         | 
| 90 | 
            +
              }
         | 
| 91 | 
            +
            }
         | 
| 92 | 
            +
             | 
| 93 | 
            +
            module.exports = RuntimeErrorFooter;
         | 
| @@ -0,0 +1,37 @@ | |
| 1 | 
            +
            const Spacer = require('./Spacer.js');
         | 
| 2 | 
            +
            const theme = require('../theme.js');
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            /**
         | 
| 5 | 
            +
             * @typedef {Object} RuntimeErrorHeaderProps
         | 
| 6 | 
            +
             * @property {number} currentErrorIndex
         | 
| 7 | 
            +
             * @property {number} totalErrors
         | 
| 8 | 
            +
             */
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            /**
         | 
| 11 | 
            +
             * A fixed header that shows the total runtime error count.
         | 
| 12 | 
            +
             * @param {Document} document
         | 
| 13 | 
            +
             * @param {HTMLElement} root
         | 
| 14 | 
            +
             * @param {RuntimeErrorHeaderProps} props
         | 
| 15 | 
            +
             * @returns {void}
         | 
| 16 | 
            +
             */
         | 
| 17 | 
            +
            function RuntimeErrorHeader(document, root, props) {
         | 
| 18 | 
            +
              const header = document.createElement('div');
         | 
| 19 | 
            +
              header.innerText = 'Error ' + (props.currentErrorIndex + 1) + ' of ' + props.totalErrors;
         | 
| 20 | 
            +
              header.style.backgroundColor = '#' + theme.red;
         | 
| 21 | 
            +
              header.style.color = '#' + theme.white;
         | 
| 22 | 
            +
              header.style.fontWeight = '500';
         | 
| 23 | 
            +
              header.style.height = '2.5rem';
         | 
| 24 | 
            +
              header.style.left = '0';
         | 
| 25 | 
            +
              header.style.lineHeight = '2.5rem';
         | 
| 26 | 
            +
              header.style.position = 'fixed';
         | 
| 27 | 
            +
              header.style.textAlign = 'center';
         | 
| 28 | 
            +
              header.style.top = '0';
         | 
| 29 | 
            +
              header.style.width = '100vw';
         | 
| 30 | 
            +
              header.style.zIndex = '2';
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              root.appendChild(header);
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              Spacer(document, root, { space: '2.5rem' });
         | 
| 35 | 
            +
            }
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            module.exports = RuntimeErrorHeader;
         | 
| @@ -0,0 +1,79 @@ | |
| 1 | 
            +
            const ErrorStackParser = require('error-stack-parser');
         | 
| 2 | 
            +
            const theme = require('../theme.js');
         | 
| 3 | 
            +
            const utils = require('../utils.js');
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            /**
         | 
| 6 | 
            +
             * @typedef {Object} RuntimeErrorStackProps
         | 
| 7 | 
            +
             * @property {Error} error
         | 
| 8 | 
            +
             */
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            /**
         | 
| 11 | 
            +
             * A formatter that turns runtime error stacks into highlighted HTML stacks.
         | 
| 12 | 
            +
             * @param {Document} document
         | 
| 13 | 
            +
             * @param {HTMLElement} root
         | 
| 14 | 
            +
             * @param {RuntimeErrorStackProps} props
         | 
| 15 | 
            +
             * @returns {void}
         | 
| 16 | 
            +
             */
         | 
| 17 | 
            +
            function RuntimeErrorStack(document, root, props) {
         | 
| 18 | 
            +
              const stackTitle = document.createElement('h4');
         | 
| 19 | 
            +
              stackTitle.innerText = 'Call Stack';
         | 
| 20 | 
            +
              stackTitle.style.color = '#' + theme.white;
         | 
| 21 | 
            +
              stackTitle.style.fontSize = '1.0625rem';
         | 
| 22 | 
            +
              stackTitle.style.fontWeight = '500';
         | 
| 23 | 
            +
              stackTitle.style.lineHeight = '1.3';
         | 
| 24 | 
            +
              stackTitle.style.margin = '0 0 0.5rem';
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              const stackContainer = document.createElement('div');
         | 
| 27 | 
            +
              stackContainer.style.fontSize = '0.8125rem';
         | 
| 28 | 
            +
              stackContainer.style.lineHeight = '1.3';
         | 
| 29 | 
            +
              stackContainer.style.whiteSpace = 'pre-wrap';
         | 
| 30 | 
            +
             | 
| 31 | 
            +
              let errorStacks;
         | 
| 32 | 
            +
              try {
         | 
| 33 | 
            +
                errorStacks = ErrorStackParser.parse(props.error);
         | 
| 34 | 
            +
              } catch (e) {
         | 
| 35 | 
            +
                errorStacks = [];
         | 
| 36 | 
            +
                stackContainer.innerHTML = 'No stack trace is available for this error!';
         | 
| 37 | 
            +
              }
         | 
| 38 | 
            +
             | 
| 39 | 
            +
              for (let i = 0; i < Math.min(errorStacks.length, 10); i += 1) {
         | 
| 40 | 
            +
                const currentStack = errorStacks[i];
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                const functionName = document.createElement('code');
         | 
| 43 | 
            +
                functionName.innerHTML = ' ' + currentStack.functionName || '(anonymous function)';
         | 
| 44 | 
            +
                functionName.style.color = '#' + theme.yellow;
         | 
| 45 | 
            +
                functionName.style.fontFamily = [
         | 
| 46 | 
            +
                  '"Operator Mono SSm"',
         | 
| 47 | 
            +
                  '"Operator Mono"',
         | 
| 48 | 
            +
                  '"Fira Code Retina"',
         | 
| 49 | 
            +
                  '"Fira Code"',
         | 
| 50 | 
            +
                  '"FiraCode-Retina"',
         | 
| 51 | 
            +
                  '"Andale Mono"',
         | 
| 52 | 
            +
                  '"Lucida Console"',
         | 
| 53 | 
            +
                  'Menlo',
         | 
| 54 | 
            +
                  'Consolas',
         | 
| 55 | 
            +
                  'Monaco',
         | 
| 56 | 
            +
                  'monospace',
         | 
| 57 | 
            +
                ].join(', ');
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                const fileName = document.createElement('div');
         | 
| 60 | 
            +
                fileName.innerHTML =
         | 
| 61 | 
            +
                  '  ' +
         | 
| 62 | 
            +
                  utils.formatFilename(currentStack.fileName) +
         | 
| 63 | 
            +
                  ':' +
         | 
| 64 | 
            +
                  currentStack.lineNumber +
         | 
| 65 | 
            +
                  ':' +
         | 
| 66 | 
            +
                  currentStack.columnNumber;
         | 
| 67 | 
            +
                fileName.style.color = '#' + theme.white;
         | 
| 68 | 
            +
                fileName.style.fontSize = '0.6875rem';
         | 
| 69 | 
            +
                fileName.style.marginBottom = '0.25rem';
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                stackContainer.appendChild(functionName);
         | 
| 72 | 
            +
                stackContainer.appendChild(fileName);
         | 
| 73 | 
            +
              }
         | 
| 74 | 
            +
             | 
| 75 | 
            +
              root.appendChild(stackTitle);
         | 
| 76 | 
            +
              root.appendChild(stackContainer);
         | 
| 77 | 
            +
            }
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            module.exports = RuntimeErrorStack;
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            /**
         | 
| 2 | 
            +
             * @typedef {Object} SpacerProps
         | 
| 3 | 
            +
             * @property {string} space
         | 
| 4 | 
            +
             */
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            /**
         | 
| 7 | 
            +
             * An empty element to add spacing manually.
         | 
| 8 | 
            +
             * @param {Document} document
         | 
| 9 | 
            +
             * @param {HTMLElement} root
         | 
| 10 | 
            +
             * @param {SpacerProps} props
         | 
| 11 | 
            +
             * @returns {void}
         | 
| 12 | 
            +
             */
         | 
| 13 | 
            +
            function Spacer(document, root, props) {
         | 
| 14 | 
            +
              const spacer = document.createElement('div');
         | 
| 15 | 
            +
              spacer.style.paddingBottom = props.space;
         | 
| 16 | 
            +
              root.appendChild(spacer);
         | 
| 17 | 
            +
            }
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            module.exports = Spacer;
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            const CompileErrorTrace = require('../components/CompileErrorTrace.js');
         | 
| 2 | 
            +
            const PageHeader = require('../components/PageHeader.js');
         | 
| 3 | 
            +
            const Spacer = require('../components/Spacer.js');
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            /**
         | 
| 6 | 
            +
             * @typedef {Object} CompileErrorContainerProps
         | 
| 7 | 
            +
             * @property {string} errorMessage
         | 
| 8 | 
            +
             */
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            /**
         | 
| 11 | 
            +
             * A container to render Webpack compilation error messages with source trace.
         | 
| 12 | 
            +
             * @param {Document} document
         | 
| 13 | 
            +
             * @param {HTMLElement} root
         | 
| 14 | 
            +
             * @param {CompileErrorContainerProps} props
         | 
| 15 | 
            +
             * @returns {void}
         | 
| 16 | 
            +
             */
         | 
| 17 | 
            +
            function CompileErrorContainer(document, root, props) {
         | 
| 18 | 
            +
              PageHeader(document, root, {
         | 
| 19 | 
            +
                title: 'Failed to compile.',
         | 
| 20 | 
            +
              });
         | 
| 21 | 
            +
              CompileErrorTrace(document, root, { errorMessage: props.errorMessage });
         | 
| 22 | 
            +
              Spacer(document, root, { space: '1rem' });
         | 
| 23 | 
            +
            }
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            module.exports = CompileErrorContainer;
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            const PageHeader = require('../components/PageHeader.js');
         | 
| 2 | 
            +
            const RuntimeErrorStack = require('../components/RuntimeErrorStack.js');
         | 
| 3 | 
            +
            const Spacer = require('../components/Spacer.js');
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            /**
         | 
| 6 | 
            +
             * @typedef {Object} RuntimeErrorContainerProps
         | 
| 7 | 
            +
             * @property {Error} currentError
         | 
| 8 | 
            +
             */
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            /**
         | 
| 11 | 
            +
             * A container to render runtime error messages with stack trace.
         | 
| 12 | 
            +
             * @param {Document} document
         | 
| 13 | 
            +
             * @param {HTMLElement} root
         | 
| 14 | 
            +
             * @param {RuntimeErrorContainerProps} props
         | 
| 15 | 
            +
             * @returns {void}
         | 
| 16 | 
            +
             */
         | 
| 17 | 
            +
            function RuntimeErrorContainer(document, root, props) {
         | 
| 18 | 
            +
              PageHeader(document, root, {
         | 
| 19 | 
            +
                message: props.currentError.message,
         | 
| 20 | 
            +
                title: props.currentError.name,
         | 
| 21 | 
            +
                topOffset: '2.5rem',
         | 
| 22 | 
            +
              });
         | 
| 23 | 
            +
              RuntimeErrorStack(document, root, {
         | 
| 24 | 
            +
                error: props.currentError,
         | 
| 25 | 
            +
              });
         | 
| 26 | 
            +
              Spacer(document, root, { space: '1rem' });
         | 
| 27 | 
            +
            }
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            module.exports = RuntimeErrorContainer;
         |