@readme/markdown 14.10.2 → 14.11.0
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/components/Embed/index.tsx +4 -1
- package/components/Embed/normalizeYouTubeUrl.ts +41 -0
- package/dist/components/Embed/normalizeYouTubeUrl.d.ts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/micromark/mdx-component/syntax.d.ts +7 -6
- package/dist/lib/micromark/mdx-expression-lenient/index.d.ts +1 -0
- package/dist/lib/micromark/mdx-expression-lenient/syntax.d.ts +2 -0
- package/dist/main.js +276 -247
- package/dist/main.node.js +276 -247
- package/dist/main.node.js.map +1 -1
- package/dist/processor/transform/mdxish/components/inline-html.d.ts +6 -5
- package/dist/processor/transform/mdxish/remove-jsx-comments.d.ts +11 -0
- package/dist/processor/transform/mdxish/resolve-esm-imports.d.ts +13 -0
- package/dist/render-fixture.node.js +276 -247
- package/dist/render-fixture.node.js.map +1 -1
- package/package.json +2 -2
- package/dist/processor/transform/mdxish/preprocess-jsx-expressions.d.ts +0 -23
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
/* eslint-disable react/jsx-props-no-spreading */
|
|
3
3
|
import React from 'react';
|
|
4
4
|
|
|
5
|
+
import { normalizeYouTubeUrlToEmbedUrl } from './normalizeYouTubeUrl';
|
|
6
|
+
|
|
5
7
|
interface FaviconProps {
|
|
6
8
|
alt?: string;
|
|
7
9
|
src: string;
|
|
@@ -72,7 +74,8 @@ const Embed = ({
|
|
|
72
74
|
!html && !explicitOptOut && url && typeOfEmbed && IFRAME_DERIVABLE_TYPES.has(typeOfEmbed);
|
|
73
75
|
|
|
74
76
|
if (iframe || renderTypeAsIframe) {
|
|
75
|
-
|
|
77
|
+
const src = normalizeYouTubeUrlToEmbedUrl(url);
|
|
78
|
+
return <iframe {...spreadAttrs} src={src} style={iframeStyle} title={title} />;
|
|
76
79
|
}
|
|
77
80
|
|
|
78
81
|
if (!providerUrl && url)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// YouTube watch/share URLs (youtube.com/watch?v=ID, youtu.be/ID) set X-Frame-Options
|
|
2
|
+
// and refuse to be framed. The player only allows embedding via youtube.com/embed/ID.
|
|
3
|
+
const YOUTUBE_HOSTS = new Set(['youtube.com', 'www.youtube.com', 'm.youtube.com', 'youtu.be', 'www.youtu.be', 'm.youtu.be']);
|
|
4
|
+
|
|
5
|
+
// /embed/ accepts `start` (integer seconds), not the watch-page `t` value which may carry units (e.g. 596s, 1h2m3s).
|
|
6
|
+
const toStartSeconds = (timestamp: string): string | null => {
|
|
7
|
+
const [, hours, minutes, seconds] = timestamp.match(/^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s?)?$/) ?? [];
|
|
8
|
+
const total = (Number(hours) || 0) * 3600 + (Number(minutes) || 0) * 60 + (Number(seconds) || 0);
|
|
9
|
+
return total > 0 ? String(total) : null;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const extractVideoId = (parsed: URL): string | null => {
|
|
13
|
+
if (parsed.hostname.endsWith('youtu.be')) return parsed.pathname.slice(1).split('/')[0] || null;
|
|
14
|
+
if (parsed.pathname.startsWith('/watch')) return parsed.searchParams.get('v');
|
|
15
|
+
if (parsed.pathname.startsWith('/shorts/')) return parsed.pathname.slice('/shorts/'.length).split('/')[0] || null;
|
|
16
|
+
return null;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// Most youtube links we get from the browser are watch URLs, like https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
20
|
+
// These /watch URLs won't work in an iframe, so we need to convert them to the embed URL if iframe is used
|
|
21
|
+
export const normalizeYouTubeUrlToEmbedUrl = (url: string): string => {
|
|
22
|
+
let parsed: URL;
|
|
23
|
+
try {
|
|
24
|
+
parsed = new URL(url);
|
|
25
|
+
} catch {
|
|
26
|
+
return url;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!YOUTUBE_HOSTS.has(parsed.hostname)) return url;
|
|
30
|
+
if (parsed.pathname.startsWith('/embed/')) return url;
|
|
31
|
+
|
|
32
|
+
const videoId = extractVideoId(parsed);
|
|
33
|
+
if (!videoId) return url;
|
|
34
|
+
|
|
35
|
+
const embed = new URL(`https://www.youtube.com/embed/${videoId}`);
|
|
36
|
+
const timestamp = parsed.searchParams.get('start') || parsed.searchParams.get('t');
|
|
37
|
+
const start = timestamp ? toStartSeconds(timestamp) : null;
|
|
38
|
+
if (start) embed.searchParams.set('start', start);
|
|
39
|
+
|
|
40
|
+
return embed.toString();
|
|
41
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const normalizeYouTubeUrlToEmbedUrl: (url: string) => string;
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ declare const utils: {
|
|
|
7
7
|
calloutIcons: {};
|
|
8
8
|
};
|
|
9
9
|
export { compile, exports, FLOW_TYPES, hast, INLINE_ONLY_PARENT_TYPES, run, mdast, mdastV6, mdx, mdxish, mdxishAstProcessor, mdxishMdastToMd, mdxishTags, extractToc, migrate, mix, plain, renderMdxish, remarkPlugins, stripComments, tags, } from './lib';
|
|
10
|
+
export type { MdxishOpts, RenderMdxishOpts, RunOpts } from './lib';
|
|
10
11
|
export { default as Owlmoji } from './lib/owlmoji';
|
|
11
12
|
export { Components, utils };
|
|
12
13
|
export { tailwindCompiler } from './utils/tailwind-compiler';
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export { default as plain } from './plain';
|
|
|
16
16
|
export { default as renderMdxish } from './renderMdxish';
|
|
17
17
|
export type { RenderMdxishOpts } from './renderMdxish';
|
|
18
18
|
export { default as run } from './run';
|
|
19
|
+
export type { RunOpts } from './run';
|
|
19
20
|
export { default as tags } from './tags';
|
|
20
21
|
export { default as mdxishTags } from './mdxishTags';
|
|
21
22
|
export { default as stripComments } from './stripComments';
|
|
@@ -13,12 +13,13 @@ declare module 'micromark-util-types' {
|
|
|
13
13
|
* self-closing `<Component />`). Prevents CommonMark from fragmenting them
|
|
14
14
|
* across multiple HTML / paragraph nodes.
|
|
15
15
|
*
|
|
16
|
-
* **Text (inline)** — registers
|
|
17
|
-
* (
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
16
|
+
* **Text (inline)** — registers for lowercase tags and inline PascalCase
|
|
17
|
+
* components (Anchor, Glossary) that carry brace attrs (e.g.
|
|
18
|
+
* `Start <a href={url}>here</a> end`, `<Anchor href={url}>x</Anchor>`). Picks
|
|
19
|
+
* them up during inline parsing so they render inline inside their paragraph,
|
|
20
|
+
* then are rewritten to `mdxJsxTextElement` by the `components/inline-html`
|
|
21
|
+
* transformer. All other PascalCase is flow-only; ReadMe's custom components
|
|
22
|
+
* are authored as block-level elements.
|
|
22
23
|
*
|
|
23
24
|
* Excludes tags handled by dedicated tokenizers: Table, HTMLBlock, Glossary,
|
|
24
25
|
* Anchor.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { mdxExpressionLenient } from './syntax';
|