pulumi-package-docs 0.8.0 → 0.9.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.
Files changed (62) hide show
  1. package/README.md +98 -4
  2. package/bin/args.js +62 -3
  3. package/bin/args.test.js +60 -0
  4. package/bin/cli-bun.js +55 -23
  5. package/bin/cli.js +74 -28
  6. package/bin/cli.test.js +18 -0
  7. package/bin/static.js +196 -0
  8. package/bin/static.test.js +176 -0
  9. package/dist/client/assets/MemberDetail-Du4HYTda.js +1 -0
  10. package/dist/client/assets/{token-oQmZfAP3.js → examples-zkHFEaMt.js} +1 -1
  11. package/dist/client/assets/index-g58gbZKl.js +12 -0
  12. package/dist/client/assets/matchContext-BfDTxnb0.js +2 -0
  13. package/dist/client/assets/providers._name-DztqmroK.js +1 -0
  14. package/dist/client/assets/providers._name.functions._token-Dds2hD5R.js +1 -0
  15. package/dist/client/assets/providers._name.functions._token-DkZe4R_v.js +1 -0
  16. package/dist/client/assets/providers._name.index-B6cK3ZCZ.js +1 -0
  17. package/dist/client/assets/providers._name.index-CvFTUtAs.js +1 -0
  18. package/dist/client/assets/providers._name.resources._token-Bf7TPYcB.js +1 -0
  19. package/dist/client/assets/providers._name.resources._token-CIjv9yb8.js +1 -0
  20. package/dist/client/assets/routes-Dz3Kksbm.js +1 -0
  21. package/dist/mcp/stdio.js +449 -0
  22. package/dist/server/assets/{MemberDetail-C5sAHNZW.js → MemberDetail-CdHUSmQD.js} +2 -1
  23. package/dist/server/assets/{_tanstack-start-manifest_v-B0J-S-em.js → _tanstack-start-manifest_v-Drm3Ru6D.js} +15 -15
  24. package/dist/server/assets/api-D49ZDhMh.js +27 -0
  25. package/dist/server/assets/{providers._name.functions._token-Gkw4zt3M.js → providers._name.functions._token-BvkwmQ-L.js} +3 -2
  26. package/dist/server/assets/{providers._name.index-CEXkl-76.js → providers._name.index-DBkfEjsy.js} +3 -2
  27. package/dist/server/assets/{providers._name.resources._token-R_i2MmRl.js → providers._name.resources._token-Sl31Qlvd.js} +3 -2
  28. package/dist/server/assets/{schema.server-B-VvU1qb.js → providers.server-B1ZHZ5jE.js} +48 -1
  29. package/dist/server/assets/{router-1INob9fh.js → router-_zs8P-B2.js} +24 -87
  30. package/dist/server/assets/{routes-4jiXnS1p.js → routes-BUxagg9r.js} +1 -1
  31. package/dist/server/assets/token-DBEFeZIN.js +92 -0
  32. package/dist/server/server.js +987 -375
  33. package/examples/github-pages.yml +56 -0
  34. package/examples/gitlab-ci.yml +22 -0
  35. package/package.json +7 -3
  36. package/src/components/ThemeToggle.tsx +37 -0
  37. package/src/lib/pulumi/api.ts +18 -69
  38. package/src/lib/pulumi/mcp.server.test.ts +112 -0
  39. package/src/lib/pulumi/mcp.server.ts +11 -6
  40. package/src/lib/pulumi/providers.server.ts +80 -0
  41. package/src/lib/pulumi/stdio.server.ts +16 -0
  42. package/src/lib/pulumi/token.test.ts +44 -1
  43. package/src/lib/pulumi/token.ts +28 -0
  44. package/src/lib/static-docs.ts +15 -0
  45. package/src/router.tsx +3 -0
  46. package/src/routes/__root.tsx +6 -3
  47. package/src/routes/providers.$name.functions.$token.tsx +7 -4
  48. package/src/routes/providers.$name.index.tsx +2 -2
  49. package/src/routes/providers.$name.resources.$token.tsx +7 -4
  50. package/vite.config.ts +41 -1
  51. package/dist/client/assets/MemberDetail-BS9DbqEt.js +0 -1
  52. package/dist/client/assets/index-2FzxAhzN.js +0 -13
  53. package/dist/client/assets/providers._name-FmJEVkdV.js +0 -1
  54. package/dist/client/assets/providers._name.functions._token-BzjmNHea.js +0 -1
  55. package/dist/client/assets/providers._name.functions._token-D768U6I-.js +0 -1
  56. package/dist/client/assets/providers._name.index-C42yQ95z.js +0 -1
  57. package/dist/client/assets/providers._name.index-Dm0YiZWP.js +0 -1
  58. package/dist/client/assets/providers._name.resources._token-CIYPoqyA.js +0 -1
  59. package/dist/client/assets/providers._name.resources._token-D0OLvgo_.js +0 -1
  60. package/dist/client/assets/routes-DKNWlgPZ.js +0 -1
  61. package/dist/client/assets/useSelector-BIt42tGI.js +0 -1
  62. package/dist/server/assets/api-C55bS4R6.js +0 -64
package/bin/static.js ADDED
@@ -0,0 +1,196 @@
1
+ import {
2
+ existsSync,
3
+ mkdirSync,
4
+ readFileSync,
5
+ readdirSync,
6
+ rmSync,
7
+ statSync,
8
+ writeFileSync,
9
+ } from 'node:fs'
10
+ import { spawn } from 'node:child_process'
11
+ import { dirname, isAbsolute, join, relative } from 'node:path'
12
+
13
+ /**
14
+ * Written into every generated site. `--out` is wiped and rebuilt on each run,
15
+ * so this marks a directory as ours to overwrite: without it (and without
16
+ * `--force`), a non-empty output directory is left alone.
17
+ */
18
+ export const SITE_MARKER = '.pulumi-package-docs-site'
19
+
20
+ /** The intermediate Vite output directory (see `build.outDir` in vite.config.ts). */
21
+ const STATIC_BUILD_DIR = 'dist-static'
22
+
23
+ /**
24
+ * Normalizes a `--base` value to the form Vite and the router want: a path
25
+ * with both a leading and a trailing slash ("/repo" -> "/repo/"), or "/" for a
26
+ * site served from a domain root.
27
+ */
28
+ export function normalizeBase(base) {
29
+ const trimmed = (base ?? '').trim()
30
+ if (trimmed === '' || trimmed === '/') return '/'
31
+ return `/${trimmed.replace(/^\/+/, '').replace(/\/+$/, '')}/`
32
+ }
33
+
34
+ /**
35
+ * Drops the leftovers of a client bundle the static pages never load.
36
+ *
37
+ * Static pages are rendered without the hydration script (see
38
+ * `src/lib/static-docs.ts`), but the framework still emits `modulepreload`
39
+ * hints for the client chunks and, after `</html>`, the serialized loader data
40
+ * hydration would have used. Nothing reads either one here, so removing them
41
+ * saves every page a round of pointless downloads and roughly halves its size.
42
+ * Both patterns are best-effort: if a future version emits something else, the
43
+ * pages are merely bigger, never broken.
44
+ */
45
+ export function stripClientPayload(html) {
46
+ return html
47
+ .replace(/<link\s+rel="modulepreload"[^>]*>/g, '')
48
+ .replace(/<\/html>[\s\S]*$/, '</html>')
49
+ }
50
+
51
+ function walk(dir) {
52
+ const files = []
53
+ for (const entry of readdirSync(dir)) {
54
+ const full = join(dir, entry)
55
+ if (statSync(full).isDirectory()) files.push(...walk(full))
56
+ else files.push(full)
57
+ }
58
+ return files
59
+ }
60
+
61
+ /** True when `child` is `parent` itself or sits inside it. */
62
+ function contains(parent, child) {
63
+ const rel = relative(parent, child)
64
+ return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel))
65
+ }
66
+
67
+ function isReusableOutputDir(out) {
68
+ if (!existsSync(out)) return true
69
+ if (!statSync(out).isDirectory()) return false
70
+ const entries = readdirSync(out)
71
+ return entries.length === 0 || entries.includes(SITE_MARKER)
72
+ }
73
+
74
+ /**
75
+ * Copies a prerendered client build into the output directory, rewriting HTML
76
+ * on the way, and adds the files a Pages host expects.
77
+ */
78
+ export function collectSite(clientDir, out) {
79
+ rmSync(out, { recursive: true, force: true })
80
+ mkdirSync(out, { recursive: true })
81
+
82
+ const files = walk(clientDir)
83
+ const htmlFiles = files.filter((file) => file.endsWith('.html'))
84
+ const assetFiles = files.filter((file) => !file.endsWith('.html'))
85
+
86
+ let rendered = ''
87
+ for (const file of htmlFiles) {
88
+ const html = stripClientPayload(readFileSync(file, 'utf-8'))
89
+ const target = join(out, relative(clientDir, file))
90
+ mkdirSync(dirname(target), { recursive: true })
91
+ writeFileSync(target, html)
92
+ rendered += html
93
+ }
94
+
95
+ for (const file of assetFiles) {
96
+ const path = relative(clientDir, file).split('\\').join('/')
97
+ // The client bundle is built but never loaded by a static page, so its
98
+ // chunks are dead weight in the published site. Scripts are the only
99
+ // asset a page can pull in without the HTML naming them (stylesheets are
100
+ // linked, and this app's CSS references no other files), so checking the
101
+ // rendered HTML is enough to know a chunk is unused.
102
+ if (/\.(js|mjs|map)$/.test(path) && !rendered.includes(path)) continue
103
+ const target = join(out, path)
104
+ mkdirSync(dirname(target), { recursive: true })
105
+ writeFileSync(target, readFileSync(file))
106
+ }
107
+
108
+ const pages = htmlFiles.length
109
+
110
+ // GitHub Pages runs the output through Jekyll unless this file is present,
111
+ // which would drop anything starting with "_" or ".".
112
+ writeFileSync(join(out, '.nojekyll'), '')
113
+ writeFileSync(
114
+ join(out, SITE_MARKER),
115
+ 'Generated by `pulumi-package-docs static`. This directory is rebuilt from scratch on every run.\n',
116
+ )
117
+
118
+ return pages
119
+ }
120
+
121
+ function runViteBuild({ packageRoot, viteBin, dir, base }) {
122
+ return new Promise((resolve, reject) => {
123
+ const child = spawn(process.execPath, [viteBin, 'build'], {
124
+ cwd: packageRoot,
125
+ stdio: 'inherit',
126
+ env: {
127
+ ...process.env,
128
+ PULUMI_LOCAL_DOCS_DIR: dir,
129
+ VITE_STATIC_DOCS: 'true',
130
+ PULUMI_DOCS_BASE: base,
131
+ },
132
+ })
133
+ child.on('error', reject)
134
+ child.on('exit', (code) =>
135
+ code === 0
136
+ ? resolve()
137
+ : reject(new Error(`vite build exited with code ${code}`)),
138
+ )
139
+ })
140
+ }
141
+
142
+ /**
143
+ * Builds a self-contained static site for the Pulumi project in `dir`: every
144
+ * provider, resource and function page prerendered to HTML, ready to publish
145
+ * to GitHub Pages, GitLab Pages, or any other static host.
146
+ */
147
+ export async function buildStaticSite({
148
+ packageRoot,
149
+ viteBin,
150
+ dir,
151
+ out,
152
+ base,
153
+ force,
154
+ }) {
155
+ const normalizedBase = normalizeBase(base)
156
+
157
+ // The output directory is wiped and rebuilt on every run, so it must never
158
+ // be the Pulumi project itself (`--out .`) or anything above it — not even
159
+ // with --force.
160
+ if (contains(out, dir)) {
161
+ throw new Error(
162
+ `Refusing to generate into ${out}: it holds the Pulumi project being documented, and --out is erased on each run.`,
163
+ )
164
+ }
165
+
166
+ if (!force && !isReusableOutputDir(out)) {
167
+ throw new Error(
168
+ `Refusing to overwrite ${out}: it isn't empty and wasn't generated by pulumi-package-docs.\n` +
169
+ 'Pass --out <path> to write somewhere else, or --force to overwrite it anyway.',
170
+ )
171
+ }
172
+
173
+ console.log(`Generating static docs for: ${dir}`)
174
+ if (normalizedBase !== '/') console.log(`Base path: ${normalizedBase}`)
175
+
176
+ await runViteBuild({ packageRoot, viteBin, dir, base: normalizedBase })
177
+
178
+ const clientDir = join(packageRoot, STATIC_BUILD_DIR, 'client')
179
+ if (!existsSync(clientDir)) {
180
+ throw new Error(
181
+ `The build produced no client output at ${clientDir}; cannot generate a static site.`,
182
+ )
183
+ }
184
+
185
+ const pages = collectSite(clientDir, out)
186
+ console.log(`\nWrote ${pages} pages to ${out}`)
187
+ if (normalizedBase === '/') {
188
+ console.log(
189
+ 'Preview it locally with: npx serve <out> (or any static file server)',
190
+ )
191
+ } else {
192
+ console.log(
193
+ `The site expects to be served from ${normalizedBase} — links and assets are prefixed with it.`,
194
+ )
195
+ }
196
+ }
@@ -0,0 +1,176 @@
1
+ import {
2
+ mkdirSync,
3
+ mkdtempSync,
4
+ readFileSync,
5
+ readdirSync,
6
+ rmSync,
7
+ writeFileSync,
8
+ } from 'node:fs'
9
+ import { tmpdir } from 'node:os'
10
+ import { join } from 'node:path'
11
+ import { afterEach, describe, expect, it } from 'vitest'
12
+
13
+ import {
14
+ SITE_MARKER,
15
+ buildStaticSite,
16
+ collectSite,
17
+ normalizeBase,
18
+ stripClientPayload,
19
+ } from './static.js'
20
+
21
+ const tmpDirs = []
22
+
23
+ function makeTmpDir() {
24
+ const dir = mkdtempSync(join(tmpdir(), 'pulumi-package-docs-test-'))
25
+ tmpDirs.push(dir)
26
+ return dir
27
+ }
28
+
29
+ afterEach(() => {
30
+ while (tmpDirs.length) rmSync(tmpDirs.pop(), { recursive: true, force: true })
31
+ })
32
+
33
+ describe('normalizeBase', () => {
34
+ it('keeps a root base as a single slash', () => {
35
+ expect(normalizeBase('/')).toBe('/')
36
+ expect(normalizeBase('')).toBe('/')
37
+ expect(normalizeBase(undefined)).toBe('/')
38
+ })
39
+
40
+ it('adds the leading and trailing slashes a project path needs', () => {
41
+ expect(normalizeBase('my-repo')).toBe('/my-repo/')
42
+ expect(normalizeBase('/my-repo')).toBe('/my-repo/')
43
+ expect(normalizeBase('my-repo/')).toBe('/my-repo/')
44
+ expect(normalizeBase(' /my-repo/ ')).toBe('/my-repo/')
45
+ })
46
+
47
+ it('keeps nested path segments', () => {
48
+ expect(normalizeBase('group/project')).toBe('/group/project/')
49
+ })
50
+ })
51
+
52
+ describe('stripClientPayload', () => {
53
+ it('removes modulepreload hints for the unused client bundle', () => {
54
+ const html =
55
+ '<html><head><link rel="modulepreload" href="/assets/index-abc.js"/><link rel="stylesheet" href="/assets/app.css"/></head><body>hi</body></html>'
56
+ const stripped = stripClientPayload(html)
57
+ expect(stripped).not.toContain('modulepreload')
58
+ expect(stripped).toContain(
59
+ '<link rel="stylesheet" href="/assets/app.css"/>',
60
+ )
61
+ })
62
+
63
+ it('removes the hydration payload emitted after the document', () => {
64
+ const html = '<html><body>hi</body></html><script>$_TSR.router={}</script>'
65
+ expect(stripClientPayload(html)).toBe('<html><body>hi</body></html>')
66
+ })
67
+
68
+ it('leaves a page with neither untouched', () => {
69
+ const html = '<html><body>hi</body></html>'
70
+ expect(stripClientPayload(html)).toBe(html)
71
+ })
72
+ })
73
+
74
+ describe('collectSite', () => {
75
+ function seedClientDir() {
76
+ const clientDir = makeTmpDir()
77
+ mkdirSync(join(clientDir, 'assets'))
78
+ mkdirSync(join(clientDir, 'providers', 'random'), { recursive: true })
79
+ writeFileSync(
80
+ join(clientDir, 'index.html'),
81
+ '<html><head><link rel="modulepreload" href="/assets/entry.js"/><link rel="stylesheet" href="/assets/app.css"/></head><body>index</body></html><script>$_TSR.router={}</script>',
82
+ )
83
+ writeFileSync(
84
+ join(clientDir, 'providers', 'random', 'index.html'),
85
+ '<html><body>random</body></html>',
86
+ )
87
+ writeFileSync(join(clientDir, 'assets', 'app.css'), 'body{}')
88
+ writeFileSync(join(clientDir, 'assets', 'entry.js'), 'console.log(1)')
89
+ return clientDir
90
+ }
91
+
92
+ it('writes every page, stripped, alongside the assets they use', () => {
93
+ const clientDir = seedClientDir()
94
+ const out = join(makeTmpDir(), 'site')
95
+
96
+ expect(collectSite(clientDir, out)).toBe(2)
97
+
98
+ const index = readFileSync(join(out, 'index.html'), 'utf-8')
99
+ expect(index).not.toContain('modulepreload')
100
+ expect(index).not.toContain('$_TSR')
101
+ expect(
102
+ readFileSync(join(out, 'providers', 'random', 'index.html'), 'utf-8'),
103
+ ).toContain('random')
104
+ expect(readFileSync(join(out, 'assets', 'app.css'), 'utf-8')).toBe('body{}')
105
+ })
106
+
107
+ it('leaves out client chunks no page loads', () => {
108
+ const clientDir = seedClientDir()
109
+ const out = join(makeTmpDir(), 'site')
110
+
111
+ collectSite(clientDir, out)
112
+
113
+ expect(readdirSync(join(out, 'assets'))).toEqual(['app.css'])
114
+ })
115
+
116
+ it('keeps a chunk a page does reference', () => {
117
+ const clientDir = seedClientDir()
118
+ writeFileSync(
119
+ join(clientDir, 'index.html'),
120
+ '<html><body><script type="module" src="/assets/entry.js"></script></body></html>',
121
+ )
122
+ const out = join(makeTmpDir(), 'site')
123
+
124
+ collectSite(clientDir, out)
125
+
126
+ expect(readdirSync(join(out, 'assets')).sort()).toEqual([
127
+ 'app.css',
128
+ 'entry.js',
129
+ ])
130
+ })
131
+
132
+ it('adds the files a Pages host needs, and replaces a previous run', () => {
133
+ const clientDir = seedClientDir()
134
+ const out = join(makeTmpDir(), 'site')
135
+
136
+ collectSite(clientDir, out)
137
+ writeFileSync(join(out, 'stale.html'), 'from a previous run')
138
+ collectSite(clientDir, out)
139
+
140
+ const entries = readdirSync(out)
141
+ expect(entries).toContain('.nojekyll')
142
+ expect(entries).toContain(SITE_MARKER)
143
+ expect(entries).not.toContain('stale.html')
144
+ })
145
+ })
146
+
147
+ describe('buildStaticSite', () => {
148
+ it('refuses an output directory that holds the project being documented', async () => {
149
+ const dir = makeTmpDir()
150
+ await expect(
151
+ buildStaticSite({
152
+ packageRoot: dir,
153
+ viteBin: 'unused',
154
+ dir: join(dir, 'project'),
155
+ out: dir,
156
+ base: '/',
157
+ force: true,
158
+ }),
159
+ ).rejects.toThrow(/holds the Pulumi project/)
160
+ })
161
+
162
+ it("refuses an output directory it didn't generate", async () => {
163
+ const out = makeTmpDir()
164
+ writeFileSync(join(out, 'index.html'), 'someone else lives here')
165
+ await expect(
166
+ buildStaticSite({
167
+ packageRoot: makeTmpDir(),
168
+ viteBin: 'unused',
169
+ dir: makeTmpDir(),
170
+ out,
171
+ base: '/',
172
+ force: false,
173
+ }),
174
+ ).rejects.toThrow(/Refusing to overwrite/)
175
+ })
176
+ })
@@ -0,0 +1 @@
1
+ import{o as e}from"./matchContext-BfDTxnb0.js";import{c as t}from"./index-g58gbZKl.js";import{a as n,n as r,r as i,t as a}from"./examples-zkHFEaMt.js";var o=e();function s({example:e}){return e?(0,o.jsxs)(`div`,{className:`code-example`,children:[(0,o.jsx)(`span`,{className:`code-example-lang`,children:e.language}),(0,o.jsx)(`pre`,{children:(0,o.jsx)(`code`,{children:e.code})})]}):(0,o.jsx)(`p`,{className:`empty-state`,children:`No examples in the schema.`})}function c(e){if(!e)return`any`;if(e.$ref){let t=e.$ref.split(`/`).pop()??e.$ref;return decodeURIComponent(t)}return e.type===`array`&&e.items?`${c(e.items)}[]`:e.type??`any`}function l(e){return e.replace(/([a-z0-9])([A-Z])/g,`$1_$2`).replace(/([A-Z]+)([A-Z][a-z])/g,`$1_$2`).toLowerCase()}function u(e){return e.length===0?e:e.charAt(0).toUpperCase()+e.slice(1)}function d(e,t){switch(t){case`python`:return l(e);case`go`:case`dotnet`:return u(e);default:return e}}function f({properties:e,required:t,runtime:r}){let i=Object.keys(e??{});if(i.length===0)return(0,o.jsx)(`p`,{className:`empty-state`,children:`None`});let a=new Set(t??[]);return(0,o.jsxs)(`table`,{className:`props-table`,children:[(0,o.jsx)(`thead`,{children:(0,o.jsxs)(`tr`,{children:[(0,o.jsx)(`th`,{children:`Name`}),(0,o.jsx)(`th`,{children:`Type`}),(0,o.jsx)(`th`,{children:`Required`}),(0,o.jsx)(`th`,{children:`Description`})]})}),(0,o.jsx)(`tbody`,{children:i.map(t=>{let i=e[t];return(0,o.jsxs)(`tr`,{children:[(0,o.jsx)(`td`,{children:(0,o.jsx)(`code`,{children:d(t,r)})}),(0,o.jsx)(`td`,{children:(0,o.jsx)(`code`,{children:c(i)})}),(0,o.jsx)(`td`,{children:a.has(t)?`yes`:`no`}),(0,o.jsx)(`td`,{children:n(i.description,r)??``})]},t)})})]})}function p({providerName:e,kind:c,displayName:l,token:u,description:d,deprecationMessage:p,runtime:m,inputProperties:h,requiredInputs:g,outputProperties:_,requiredOutputs:v}){let y=n(d,m),b=i(y),x=r(a(y),m);return(0,o.jsxs)(`main`,{className:`provider-detail`,children:[(0,o.jsxs)(t,{to:`/providers/$name`,params:{name:e},className:`back-link`,children:[`← Back to `,e]}),(0,o.jsx)(`h1`,{children:l}),(0,o.jsxs)(`p`,{className:`subtitle`,children:[(0,o.jsx)(`span`,{className:`badge ${c===`Resource`?`badge-resource`:`badge-function`}`,children:c}),` `,`· `,(0,o.jsx)(`code`,{children:u})]}),p&&(0,o.jsxs)(`p`,{className:`banner banner-warning`,children:[`Deprecated: `,p]}),b?.split(/\n{2,}/).map((e,t)=>(0,o.jsx)(`p`,{children:e},t)),(0,o.jsx)(`h2`,{children:`Example`}),(0,o.jsx)(s,{example:x}),(0,o.jsx)(`h2`,{children:`Inputs`}),(0,o.jsx)(f,{properties:h,required:g,runtime:m}),(0,o.jsx)(`h2`,{children:`Outputs`}),(0,o.jsx)(f,{properties:_,required:v,runtime:m})]})}export{p as t};
@@ -1 +1 @@
1
- var e=/<span\s+((?:pulumi-lang-[a-z]+="[^"]*"\s*)+)>([\s\S]*?)<\/span>/g,t=/pulumi-lang-([a-z]+)="([^"]*)"/g;function n(n,r){return n.replace(e,(e,n,i)=>{if(!r)return i;t.lastIndex=0;let a;for(;a=t.exec(n);)if(a[1]===r)return a[2];return i})}function r(e,t){return e&&n(e,t)}var i=/```([a-zA-Z0-9+#-]+)\n([\s\S]*?)```/g;function a(e){return e?[...e.matchAll(i)].map(e=>({language:e[1].toLowerCase(),code:e[2].trimEnd()})):[]}function o(e){return e&&(e.replace(i,``).trim()||void 0)}function s(e){let t=o(e);if(t)return t.split(/\n{2,}/)[0]?.trim()||void 0}var c={nodejs:[`typescript`,`javascript`],python:[`python`],go:[`go`,`golang`],dotnet:[`csharp`],java:[`java`],yaml:[`yaml`]};function l(e,t){let n=t?c[t]:void 0;return(n?e.find(e=>n.includes(e.language)):void 0)??e[0]}function u(e){let t=e.split(`:`).pop();return t&&t.length>0?t:e}export{s as a,o as i,a as n,r as o,l as r,u as t};
1
+ var e=/<span\s+((?:pulumi-lang-[a-z]+="[^"]*"\s*)+)>([\s\S]*?)<\/span>/g,t=/pulumi-lang-([a-z]+)="([^"]*)"/g;function n(n,r){return n.replace(e,(e,n,i)=>{if(!r)return i;t.lastIndex=0;let a;for(;a=t.exec(n);)if(a[1]===r)return a[2];return i})}function r(e,t){return e&&n(e,t)}var i=/```([a-zA-Z0-9+#-]+)\n([\s\S]*?)```/g;function a(e){return e?[...e.matchAll(i)].map(e=>({language:e[1].toLowerCase(),code:e[2].trimEnd()})):[]}function o(e){return e&&(e.replace(i,``).trim()||void 0)}function s(e){let t=o(e);if(t)return t.split(/\n{2,}/)[0]?.trim()||void 0}var c={nodejs:[`typescript`,`javascript`],python:[`python`],go:[`go`,`golang`],dotnet:[`csharp`],java:[`java`],yaml:[`yaml`]};function l(e,t){let n=t?c[t]:void 0;return(n?e.find(e=>n.includes(e.language)):void 0)??e[0]}export{r as a,s as i,l as n,o as r,a as t};