From a9bdd9cc4e41512fbe723620c995e6a110032ebf Mon Sep 17 00:00:00 2001
From: Matthew Phillips <matthew@skypack.dev>
Date: Thu, 9 Feb 2023 14:22:57 -0500
Subject: [PATCH] Fixes usage of Code component in Vercel (#6198)

* Fixes usage of Code component in Vercel

* Adding a changeset
---
 .changeset/great-mails-agree.md               |  5 +++
 packages/astro/components/Shiki.js            | 20 +++++++---
 packages/astro/test/units/shiki/shiki.test.js | 40 +++++++++++++++++++
 3 files changed, 60 insertions(+), 5 deletions(-)
 create mode 100644 .changeset/great-mails-agree.md
 create mode 100644 packages/astro/test/units/shiki/shiki.test.js

diff --git a/.changeset/great-mails-agree.md b/.changeset/great-mails-agree.md
new file mode 100644
index 0000000000..df5e9d82c1
--- /dev/null
+++ b/.changeset/great-mails-agree.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Fixes usage of Code component in Vercel
diff --git a/packages/astro/components/Shiki.js b/packages/astro/components/Shiki.js
index bc94e2dce4..1a2a4b1568 100644
--- a/packages/astro/components/Shiki.js
+++ b/packages/astro/components/Shiki.js
@@ -15,14 +15,14 @@ function stringify(opts) {
 
 /**
  * @param {import('shiki').HighlighterOptions} opts
- * @returns {Promise<import('shiki').Highlighter>}
+ * @returns {Promise<import('shiki').HighlighterOptions>}
  */
-async function resolveHighlighter(opts) {
+export async function resolveHighlighterOptions(opts) {
 	const resolvedThemes = [];
-	if (Object.keys(opts.theme).length) {
-		resolvedThemes.push(opts.theme);
-	} else if (opts.theme && opts.theme in themes) {
+	if (opts.theme && opts.theme in themes) {
 		resolvedThemes.push(await themes[opts.theme]());
+	} else if (Object.keys(opts.theme).length) {
+		resolvedThemes.push(opts.theme);
 	}
 
 	let resolvedLanguages;
@@ -47,6 +47,16 @@ async function resolveHighlighter(opts) {
 	// Do not pass through the theme as that will attempt to load it, even if it's included in themes
 	delete highlighterOptions['theme'];
 
+	return highlighterOptions;
+}
+
+/**
+ * @param {import('shiki').HighlighterOptions} opts
+ * @returns {Promise<import('shiki').Highlighter>}
+ */
+async function resolveHighlighter(opts) {
+	const highlighterOptions = await resolveHighlighterOptions(opts);
+
 	// Start the async getHighlighter call and cache the Promise
 	const highlighter = getShikiHighlighter(highlighterOptions).then((hl) => {
 		hl.setColorReplacements({
diff --git a/packages/astro/test/units/shiki/shiki.test.js b/packages/astro/test/units/shiki/shiki.test.js
new file mode 100644
index 0000000000..436e366126
--- /dev/null
+++ b/packages/astro/test/units/shiki/shiki.test.js
@@ -0,0 +1,40 @@
+import { expect } from 'chai';
+import { createContainer } from '../../../dist/core/dev/index.js';
+import { createViteLoader } from '../../../dist/core/module-loader/index.js';
+
+const root = new URL('../../fixtures/alias/', import.meta.url);
+
+describe('<Code />', () => {
+	describe('Shiki - getHighlighterOptions', () => {
+		let container;
+		let mod;
+		before(async () => {
+			container = await createContainer({ root, disableTelemetry: true });
+			const loader = createViteLoader(container.viteServer);
+			mod = await loader.import('astro/components/Shiki.js');
+		});
+
+		after(async () => {
+			await container.close();
+		})
+
+		it('uses the bundles themes for built-in themes', async () => {
+			const { resolveHighlighterOptions } = mod;
+			const opts = await resolveHighlighterOptions({ theme: 'css-variables' });
+			const themes = opts.themes;
+			
+			expect(themes).to.have.a.lengthOf(1);
+			expect(themes[0]).to.be.an('object');
+		});
+
+		it('uses the string theme name for custom themes', async () => {
+			const { resolveHighlighterOptions } = mod;
+			const opts = await resolveHighlighterOptions({ theme: 'some-custom-theme' });
+			const themes = opts.themes;
+			
+			expect(themes).to.have.a.lengthOf(1);
+			expect(themes[0]).to.be.an('string');
+			expect(themes[0]).to.equal('some-custom-theme');
+		})
+	});
+});