Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/twelve-trainers-laugh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'spectacle': patch
---

Allow react-syntax-highlighter prism theme imports to have more tolerant `.default` behavior with CJS vs. ESM.
2 changes: 1 addition & 1 deletion examples/js/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import ReactDOM from 'react-dom';
import {
FlexBox,
Heading,
Expand All @@ -21,7 +22,6 @@ import {
DefaultTemplate,
SlideLayout
} from 'spectacle';
import ReactDOM from 'react-dom';

const formidableLogo =
'https://avatars2.githubusercontent.com/u/5078602?s=280&v=4';
Expand Down
50 changes: 40 additions & 10 deletions examples/one-page/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,45 @@
<body>
<div id="root"></div>

<script src="https://unpkg.com/react@18.2.0/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18.2.0/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/react-is@18.2.0/umd/react-is.production.min.js"></script>
<script src="https://unpkg.com/prop-types@15.7.2/prop-types.min.js"></script>
<script src="https://unpkg.com/spectacle@^10/lib/index.global.js"></script>
<!-- <script src="../../packages/spectacle/lib/index.global.js"></script>-->

<script type="importmap">
{
"imports": {
"htm": "https://esm.sh/v121/htm@^3?deps=react@18.2.0",
"spectacle": "https://esm.sh/v121/spectacle@^10?deps=react@18.2.0",
"broadcast-channel": "https://esm.sh/v121/broadcast-channel@^4.17.0?deps=react@18.2.0",
"history": "https://esm.sh/v121/history@^5.3.0?deps=react@18.2.0",
"kbar": "https://esm.sh/v121/kbar@0.1.0-beta.40?deps=react@18.2.0",
"mdast-builder": "https://esm.sh/v121/mdast-builder@^1.1.1?deps=react@18.2.0",
"mdast-zone": "https://esm.sh/v121/mdast-zone@^4.0.0?deps=react@18.2.0",
"merge-anything": "https://esm.sh/v121/merge-anything@^3.0.3?deps=react@18.2.0",
"mousetrap": "https://esm.sh/v121/mousetrap@^1.6.5?deps=react@18.2.0",
"query-string": "https://esm.sh/v121/query-string@^7.1.1?deps=react@18.2.0",
"react": "https://esm.sh/v121/react@18.2.0?deps=react@18.2.0",
"react/jsx-runtime": "https://esm.sh/v121/react@18.2.0/jsx-runtime?deps=react@18.2.0",
"react-dom": "https://esm.sh/v121/react-dom@>=18.0.0?deps=react@18.2.0",
"react-fast-compare": "https://esm.sh/v121/react-fast-compare@^3.2.0?deps=react@18.2.0",
"react-is": "https://esm.sh/v121/react-is@^18.1.0?deps=react@18.2.0",
"react-spring": "https://esm.sh/v121/react-spring@^9.5.5?deps=react@18.2.0",
"react-swipeable": "https://esm.sh/v121/react-swipeable@^7.0.0?deps=react@18.2.0",
"react-syntax-highlighter": "https://esm.sh/v121/react-syntax-highlighter@^15.5.0?deps=react@18.2.0",
"react-syntax-highlighter/dist/cjs/styles/prism/vs-dark.js": "https://esm.sh/v121/react-syntax-highlighter@^15.5.0/dist/esm/styles/prism/vs-dark.js?deps=react@18.2.0",
"react-syntax-highlighter/dist/cjs/styles/prism/index.js": "https://esm.sh/v121/react-syntax-highlighter@^15.5.0/dist/esm/styles/prism/index.js?deps=react@18.2.0",
"rehype-raw": "https://esm.sh/v121/rehype-raw@^5.1.0?deps=react@18.2.0",
"rehype-react": "https://esm.sh/v121/rehype-react@^6.0.0?deps=react@18.2.0",
"remark-parse": "https://esm.sh/v121/remark-parse@^8.0.3?deps=react@18.2.0",
"remark-rehype": "https://esm.sh/v121/remark-rehype@^7.0.0?deps=react@18.2.0",
"styled-components": "https://esm.sh/v121/styled-components@^5.3.6?deps=react@18.2.0",
"styled-system": "https://esm.sh/v121/styled-system@5.1.5?deps=react@18.2.0",
"unified": "https://esm.sh/v121/unified@^9.0.0?deps=react@18.2.0",
"unist-util-visit": "https://esm.sh/v121/unist-util-visit@^2.0.3?deps=react@18.2.0",
"use-resize-observer": "https://esm.sh/v121/use-resize-observer@^9.0.2?deps=react@18.2.0"
}
}
</script>
<script type="module">
const {
import React from 'react';
import ReactDOM from 'react-dom';
import {
FlexBox,
Heading,
SpectacleLogo,
Expand All @@ -38,9 +68,9 @@
Notes,
DefaultTemplate,
SlideLayout
} = Spectacle;
} from 'spectacle';

import htm from 'https://unpkg.com/htm@^3?module';
import htm from 'htm';
const html = htm.bind(React.createElement);
const formidableLogo = 'https://avatars2.githubusercontent.com/u/5078602?s=280&v=4';

Expand Down
1 change: 1 addition & 0 deletions examples/one-page/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"pretty": "^2.0.0"
},
"scripts": {
"start": "pnpm exec serve --listen 5000 ../..",
"build": "wireit",
"lint": "wireit",
"lint:fix": "wireit",
Expand Down
93 changes: 88 additions & 5 deletions examples/one-page/scripts/one-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,86 @@ const path = require('path');
const { transformFileAsync } = require('@babel/core');
const pretty = require('pretty');

// Paths
const EXAMPLES = path.resolve(__dirname, '../..');
const SPECTACLE_PATH = path.resolve(__dirname, '../../../packages/spectacle');
const SRC_FILE = path.join(EXAMPLES, 'js/index.js');
const DEST_FILE = path.join(EXAMPLES, 'one-page/index.html');

// Dependencies.
const ESM_SH_VERSION = 'v121'; // v121, stable, etc.
const {
dependencies,
peerDependencies
} = require(`${SPECTACLE_PATH}/package.json`);
const reactPkgPath = require.resolve('react/package.json', {
paths: [SPECTACLE_PATH]
});
const { version: reactVersion } = require(reactPkgPath);
const DEPS = `deps=react@${reactVersion}`;

// Toggle dev resources. (Use if debugging load / dependency errors).
const IS_DEV = false;
const DEV = IS_DEV ? '&dev' : '';

// Use local built spectacle? Toggle to `true` for dev-only.
// Note: Due to CORS, you'll need to run `pnpm run --filter ./examples/one-page start` and
// open http://localhost:5000/examples/one-page to work.
const USE_LOCAL = false;

// ================================================================================================
// Import Map
// ================================================================================================
const importUrl = (k, v, extra = '') => {
// Pin react.
if (k === 'react') {
v = reactVersion;
}

return `https://esm.sh/${ESM_SH_VERSION}/${k}@${v}${extra}?${DEPS}${DEV}`;
};

const getImportMap = () => {
// Start with extra imports for one-page alone.
const importMap = {
htm: importUrl('htm', '^3'),
spectacle: USE_LOCAL
? '../../packages/spectacle/lib/index.mjs'
: importUrl('spectacle', '^10')
};

Object.entries(Object.assign({}, dependencies, peerDependencies))
.sort((a, b) => a[0].localeCompare(b[0]))
.forEach(([k, v]) => {
// General
importMap[k] = importUrl(k, v);

// Special case internal deps
if (k === 'react') {
importMap[`${k}/jsx-runtime`] = importUrl(k, v, '/jsx-runtime');
}
if (k === 'react-syntax-highlighter') {
importMap[`${k}/dist/cjs/styles/prism/vs-dark.js`] = importUrl(
k,
v,
'/dist/esm/styles/prism/vs-dark.js'
);
importMap[`${k}/dist/cjs/styles/prism/index.js`] = importUrl(
k,
v,
'/dist/esm/styles/prism/index.js'
);
}
});

return importMap;
};

// ================================================================================================
// Rewriting
// ================================================================================================
const htmImport = `
import htm from 'https://unpkg.com/htm@^3?module';
import htm from 'htm';
const html = htm.bind(React.createElement);
`
.replace(/ /gm, '')
Expand All @@ -27,7 +101,7 @@ const spectacleImportReplacer = (match, imports) => {
.map((i) => ` ${i.trim()}`)
.join(`,\n`);

return `const {\n${imports}\n} = Spectacle;\n\n${htmImport}`;
return `import {\n${imports}\n} from 'spectacle';\n\n${htmImport}`;
};

const getSrcContent = async (src) => {
Expand All @@ -40,7 +114,6 @@ const getSrcContent = async (src) => {
// Mutate exports and comments.
code = code
// Mutate exports to our global imports.
.replace(/import React(|DOM) from 'react(|-dom)';[\n]*/gm, '')
.replace(/import {[ ]*(.*)} from 'spectacle';/, spectacleImportReplacer)
// Hackily fix / undo babel's poor control comment placment.
.replace(/\/\/ SPECTACLE_CLI/gm, '\n// SPECTACLE_CLI')
Expand Down Expand Up @@ -84,17 +157,27 @@ const getSrcContent = async (src) => {
return code;
};

// ================================================================================================
// Output
// ================================================================================================
const writeDestContent = async (destFile, code) => {
// Format for indentation in index.html.
const indent = ' ';
code = `${indent}${code}`;
code = code.split('\n').join(`\n${indent}`);
code = `${indent}${code.split('\n').join(`\n${indent}`)}`;

// Import map
let importMap = JSON.stringify({ imports: getImportMap() }, null, 2);
importMap = `${indent}${importMap.split('\n').join(`\n${indent}`)}`;

// Get destination content.
let destContent = (await fs.readFile(destFile)).toString();

// Mutate in our updated code.
destContent = destContent
.replace(
/(<script type="importmap">\n)[\s\S]*?(\n[ ]*<\/script>)/m,
(match, open, close) => `${open}${importMap}${close}`
)
.replace(
/(<script type="module">\n)[\s\S]*?(\n[ ]*<\/script>\n[ ]*<\/body>\n[ ]*<\/html>)/m,
(match, open, close) => `${open}${code}${close}`
Expand Down
2 changes: 1 addition & 1 deletion examples/typescript/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import { createRoot } from 'react-dom/client';
import {
FlexBox,
Heading,
Expand All @@ -22,7 +23,6 @@ import {
SlideLayout,
codePaneThemes
} from 'spectacle';
import { createRoot } from 'react-dom/client';

const formidableLogo =
'https://avatars2.githubusercontent.com/u/5078602?s=280&v=4';
Expand Down
9 changes: 8 additions & 1 deletion packages/spectacle/src/components/code-pane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,19 @@ import { compose, layout, position } from 'styled-system';
* We export all the themes from the index file and the VSCode Dark Theme.
* The default VSCode dark theme is not part of the index file, so we need
* to import it separately and re-export with the rest of the themes.
*
* **Note**: For ESM + one-page we swap out for `dist/esm/**` files instead.
*/
// @ts-ignore
import vsDark from 'react-syntax-highlighter/dist/cjs/styles/prism/vs-dark.js';
// @ts-ignore
import * as allThemes from 'react-syntax-highlighter/dist/cjs/styles/prism/index.js';
export const codePaneThemes = { vsDark: vsDark.default, ...allThemes };

// Allow for rewriting of RSH `/cjs/` to `/esm/` by flexibly falling back to object
// if `.default` isn't available.
const vsDarkTheme = vsDark.default || vsDark;

export const codePaneThemes = { vsDark: vsDarkTheme, ...allThemes };

type Ranges = Array<number | number[]>;

Expand Down