diff --git a/docs/Komponentengalerie/media-shortcuts.md b/docs/Komponentengalerie/media-shortcuts.md
deleted file mode 100644
index a65e8334..00000000
--- a/docs/Komponentengalerie/media-shortcuts.md
+++ /dev/null
@@ -1,63 +0,0 @@
----
-page_id: d38be43d-eb1a-43f0-8b8b-42d9336fa726
----
-import BrowserWindow from '@tdev-components/BrowserWindow';
-
-# Medien Einfügen
-
-Folgende Quellen werden aktuell unterstützt:
-- video
-- audio
-- youtube
-- circuitverse
-- learningapps
-
-```md
-::video[./assets/yogi-bear.mp4]{width=100% height=200px}
-
-::audio[./assets/sound.mp3]
-@by [KAM HESARI - Chill](https://freemusicarchive.org/music/kam-hesari/single/chill-3/)
-
-::youtube[https://www.youtube.com/embed/QPZ0pIK_wsc?si=fP8L8fYQ-TYgYwUe]
-
-::circuitverse[https://circuitverse.org/simulator/embed/rothe-inverter]
-
-::learningapps[https://learningapps.org/7863213]
-```
-
-
-::video[./assets/yogi-bear.mp4]{width=100% height=200px}
-
-
-::audio[./assets/sound.mp3]
-
-@by [KAM HESARI - Chill](https://freemusicarchive.org/music/kam-hesari/single/chill-3/)
-
-
-::youtube[https://www.youtube.com/embed/QPZ0pIK_wsc?si=fP8L8fYQ-TYgYwUe]
-
-
-::circuitverse[https://circuitverse.org/simulator/embed/rothe-inverter]
-
-
-::learningapps[https://learningapps.org/7863213]
-
-
-
-## Installation
-
-:::info[Code]
-- `src/plugins/remark-media`
-:::
-
-:::info[`docusaurus.config.ts`]
-
-```ts
-import mediaPlugin from './src/plugins/remark-media/plugin';
-
-const REMARK_PLUGINS = [
- /* ... */
- mediaPlugin
-];
-```
-:::
diff --git a/docs/Komponentengalerie/remark-media/assets/sound.mp3 b/docs/Komponentengalerie/remark-media/assets/sound.mp3
new file mode 100644
index 00000000..d373631e
Binary files /dev/null and b/docs/Komponentengalerie/remark-media/assets/sound.mp3 differ
diff --git a/docs/Komponentengalerie/remark-media/assets/yogi-bear.mp4 b/docs/Komponentengalerie/remark-media/assets/yogi-bear.mp4
new file mode 100644
index 00000000..f1545e95
Binary files /dev/null and b/docs/Komponentengalerie/remark-media/assets/yogi-bear.mp4 differ
diff --git a/docs/Komponentengalerie/remark-media/audio.mdx b/docs/Komponentengalerie/remark-media/audio.mdx
new file mode 100644
index 00000000..a0a809a3
--- /dev/null
+++ b/docs/Komponentengalerie/remark-media/audio.mdx
@@ -0,0 +1,32 @@
+---
+page_id: 41c6a9c0-61fd-4c97-9375-936f552de079
+---
+
+import BrowserWindow from '@tdev-components/BrowserWindow';
+
+# ::audio
+
+Bindet eine lokale Audio-Datei ein.
+
+```mdx
+::audio[./assets/sound.mp3]
+@by [KAM HESARI - Chill](https://freemusicarchive.org/music/kam-hesari/single/chill-3/)
+```
+
+
+::audio[./assets/sound.mp3]
+@by [KAM HESARI - Chill](https://freemusicarchive.org/music/kam-hesari/single/chill-3/)
+
+
+## Optionen
+
+css Eigenschaften
+: Es können beliebige css-Eigenschaften in Form `eigenschaft=wert` angegeben werden, die auf das Video angewendet werden.
+
+```mdx
+::audio[./assets/sound.mp3]{marginLeft=auto marginRight=auto display=block}
+```
+
+
+::audio[./assets/sound.mp3]{marginLeft=auto marginRight=auto display=block}
+
diff --git a/docs/Komponentengalerie/remark-media/circuitverse.mdx b/docs/Komponentengalerie/remark-media/circuitverse.mdx
new file mode 100644
index 00000000..336a9d15
--- /dev/null
+++ b/docs/Komponentengalerie/remark-media/circuitverse.mdx
@@ -0,0 +1,38 @@
+---
+page_id: 41c6a9c0-61fd-4c97-9375-936f552de079
+---
+
+import BrowserWindow from '@tdev-components/BrowserWindow';
+
+# ::circuitverse
+
+Bindet einen [Circuitverse](https://circuitverse.org/) Schaltkreis ein.
+
+```mdx
+::circuitverse[https://circuitverse.org/simulator/embed/rothe-inverter]
+```
+
+
+::circuitverse[https://circuitverse.org/simulator/embed/rothe-inverter]
+
+
+## Optionen
+
+`height`
+: Höhe des iframes.
+: Standardmässig auf __315px__ gesetzt.
+: z.B. `height=200px`
+`width`
+: Breite des iframes.
+: Standardmässig auf __100%__ gesetzt.
+css Eigenschaften
+: Es können beliebige css-Eigenschaften in Form `eigenschaft=wert` angegeben werden, die auf das iframe angewendet werden.
+
+
+```mdx
+::circuitverse[https://circui...]{width=300px height=200px border="2px solid red"}
+```
+
+
+::circuitverse[https://circuitverse.org/simulator/embed/rothe-inverter]{width=300px height=200px border="2px solid red"}
+
\ No newline at end of file
diff --git a/docs/Komponentengalerie/remark-media/codepen.mdx b/docs/Komponentengalerie/remark-media/codepen.mdx
new file mode 100644
index 00000000..9a437c20
--- /dev/null
+++ b/docs/Komponentengalerie/remark-media/codepen.mdx
@@ -0,0 +1,55 @@
+---
+page_id: 41c6a9c0-61fd-4c97-9375-936f552de079
+---
+
+import BrowserWindow from '@tdev-components/BrowserWindow';
+
+# ::codepen
+
+Bindet ein [Codepen](https://codepen.io/) ein.
+
+```mdx
+::codepen[https://codepen.io/lebalz/pen/PwYoOBK]
+```
+
+
+::codepen[https://codepen.io/lebalz/pen/PwYoOBK]
+
+
+:::note[URL]
+Es dürfen jeweils nur `codepen.io/user/embed/*` URLs verwendet werden, auf codepen.io wird allerdings die URL `codepen.io//pen/*` verwendet. Aus den __pen__ URLs wird automatisch die korrekte __embed__ URL generiert.
+:::
+
+## Optionen
+
+`editable`
+: Erlaubt das Bearbeiten des Codepens.
+: Standardmässig `true`.
+: z.B. `editable=false`
+`theme`
+: Wählt das Theme des Codepens.
+: Standardmässig nicht gesetzt.
+: z.B. `theme=dark` oder `theme=light`
+`defaultTab`
+: Wählt die Standard-Tabs des Codepens.
+: Standardmässig `result`.
+: z.B. `defaultTab=html,result` oder `defaultTab=css,js`
+`height`
+: Höhe des iframes.
+: Standardmässig auf __500px__ gesetzt.
+: z.B. `height=200px`
+`width`
+: Breite des iframes.
+: Standardmässig auf __100%__ gesetzt.
+: z.B. `width=200px`
+css Eigenschaften
+: Es können beliebige css-Eigenschaften in Form `eigenschaft=wert` angegeben werden, die auf das iframe angewendet werden.
+
+
+```mdx
+::codepen[https://codepen.io/lebalz/pen/PwYoOBK]{editable=false theme=light defaultTab=html,result height=300px}
+```
+
+
+::codepen[https://codepen.io/lebalz/pen/PwYoOBK]{editable=false theme=light defaultTab=html,result height=300px}
+
diff --git a/docs/Komponentengalerie/remark-media/index.mdx b/docs/Komponentengalerie/remark-media/index.mdx
new file mode 100644
index 00000000..9048c3e5
--- /dev/null
+++ b/docs/Komponentengalerie/remark-media/index.mdx
@@ -0,0 +1,32 @@
+---
+page_id: 117c8fba-9e80-4400-944d-050129aa9fe5
+---
+import DocCardList from '@theme/DocCardList';
+
+# Remark Media
+
+Das Remark-Media Plugin hilft, iframes einfach einzubinden:
+
+```mdx
+::[url]{optionen}
+```
+
+
+
+## Installation
+
+:::info[Code]
+- `src/plugins/remark-media`
+:::
+
+:::info[`docusaurus.config.ts`]
+
+```ts
+import mediaPlugin from './src/plugins/remark-media/plugin';
+
+const REMARK_PLUGINS = [
+ /* ... */
+ mediaPlugin,
+];
+```
+:::
\ No newline at end of file
diff --git a/docs/Komponentengalerie/remark-media/learningapps.mdx b/docs/Komponentengalerie/remark-media/learningapps.mdx
new file mode 100644
index 00000000..95cf660b
--- /dev/null
+++ b/docs/Komponentengalerie/remark-media/learningapps.mdx
@@ -0,0 +1,37 @@
+---
+page_id: 41c6a9c0-61fd-4c97-9375-936f552de079
+---
+
+import BrowserWindow from '@tdev-components/BrowserWindow';
+
+# ::learningapps
+
+Bindet eine [Learning-App](https://learningapps.org/) ein.
+
+```mdx
+::learningapps[https://learningapps.org/7863213]
+```
+
+
+::learningapps[https://learningapps.org/7863213]
+
+
+## Optionen
+`height`
+: Höhe des iframes.
+: Standardmässig auf __500px__ gesetzt.
+: z.B. `height=200px`
+`width`
+: Breite des iframes.
+: Standardmässig auf __100%__ gesetzt.
+: z.B. `width=200px`
+css Eigenschaften
+: Es können beliebige css-Eigenschaften in Form `eigenschaft=wert` angegeben werden, die auf das iframe angewendet werden.
+
+```mdx
+::learningapps[https://learningapps.org/7863213]{width=300px height=200px border="2px solid red"}
+```
+
+
+::learningapps[https://learningapps.org/7863213]{width=300px height=200px border="2px solid red"}
+
diff --git a/docs/Komponentengalerie/remark-media/video.mdx b/docs/Komponentengalerie/remark-media/video.mdx
new file mode 100644
index 00000000..84c90133
--- /dev/null
+++ b/docs/Komponentengalerie/remark-media/video.mdx
@@ -0,0 +1,49 @@
+---
+page_id: 41c6a9c0-61fd-4c97-9375-936f552de079
+---
+
+import BrowserWindow from '@tdev-components/BrowserWindow';
+
+# ::video
+
+Fügt ein lokales Video ein.
+
+```mdx
+::video[./assets/yogi-bear.mp4]
+```
+
+
+::video[./assets/yogi-bear.mp4]
+
+
+## Optionen
+`autoplay`
+: Startet das Video automatisch.
+: Standardmässig `false`.
+: z.B. `autoplay`
+`muted`
+: Schaltet den Ton des Videos stumm.
+: Standardmässig `false`.
+: z.B. `muted`
+`loop`
+: Startet das Video automatisch neu, wenn es beendet ist.
+: Standardmässig `false`.
+: z.B. `loop`
+`height`
+: Höhe des Videos.
+: z.B. `height=200px`
+`width`
+: Breite des Videos.
+: Standardmässig auf die natürliche Breite des Videos gesetzt (wobei `max-width=100%` gesetzt wird).
+: z.B. `width=200px`
+css Eigenschaften
+: Es können beliebige css-Eigenschaften in Form `eigenschaft=wert` angegeben werden, die auf das Video angewendet werden.
+
+
+```mdx
+::video[./assets/yogi-bear.mp4]{width=300px height=200px muted autoplay loop border="2px solid red"}
+```
+
+
+::video[./assets/yogi-bear.mp4]{width=300px height=200px muted autoplay loop border="2px solid red"}
+
diff --git a/docs/Komponentengalerie/remark-media/youtube.mdx b/docs/Komponentengalerie/remark-media/youtube.mdx
new file mode 100644
index 00000000..b964a5b5
--- /dev/null
+++ b/docs/Komponentengalerie/remark-media/youtube.mdx
@@ -0,0 +1,35 @@
+---
+page_id: 9492f5bd-6e5d-403d-ad01-a9e1ba83d2e7
+---
+import BrowserWindow from '@tdev-components/BrowserWindow';
+
+# ::youtube
+
+Fügt ein YouTube-Video ein.
+
+```mdx
+::youtube[https://www.youtube.com/embed/QPZ0pIK_wsc?si=fP8L8fYQ-TYgYwUe]
+```
+
+
+::youtube[https://www.youtube.com/embed/QPZ0pIK_wsc?si=fP8L8fYQ-TYgYwUe]
+
+
+## Optionen
+
+`height`
+: Höhe des Videos.
+: Standardmässig nicht gesetzt, dann wird das __16 / 9__ Breitbildformat verwendet.
+: z.B. `height=200px`
+`width`
+: Breite des Videos, wobei die `max-width` standardmässig auf `100%` gesetzt ist.
+: z.B. `width=200px`
+
+
+```mdx
+::youtube[https://www.youtube...]{width=300px height=200px}
+```
+
+
+::youtube[https://www.youtube.com/embed/QPZ0pIK_wsc?si=fP8L8fYQ-TYgYwUe]{height=200px width=300px}
+
\ No newline at end of file
diff --git a/src/plugins/remark-media/plugin.ts b/src/plugins/remark-media/plugin.ts
index 210e0272..d7487aec 100644
--- a/src/plugins/remark-media/plugin.ts
+++ b/src/plugins/remark-media/plugin.ts
@@ -9,7 +9,8 @@ enum LeafDirectiveName {
AUDIO = 'audio',
YOUTUBE = 'youtube',
CIRCUITVERSE = 'circuitverse',
- LEARNINGAPPS = 'learningapps'
+ LEARNINGAPPS = 'learningapps',
+ CODEPEN = 'codepen'
}
const DirectiveNames = Object.values(LeafDirectiveName) as string[];
@@ -73,13 +74,16 @@ const plugin: Plugin = function plugin(): Transformer {
children: [],
data: {}
});
+ if (Object.keys(style).length > 0) {
+ newNode.attributes.push(toJsxAttribute('style', style));
+ }
break;
case LeafDirectiveName.YOUTUBE:
const youtubeIframe: MdxJsxFlowElement = {
type: 'mdxJsxFlowElement',
name: 'iframe',
attributes: [
- toJsxAttribute('width', '100%'),
+ toJsxAttribute('width', style.minWidth || '100%'),
toJsxAttribute('height', style.height || '100%'),
toJsxAttribute('src', src),
toJsxAttribute('title', 'YouTube video player'),
@@ -95,39 +99,88 @@ const plugin: Plugin = function plugin(): Transformer {
};
newNode.name = 'div';
+ const ytStyle: { marginLeft?: string; marginRight?: string; maxWidth?: string } = {};
+ if (style.minWidth) {
+ ytStyle.marginLeft = 'auto';
+ ytStyle.marginRight = 'auto';
+ ytStyle.maxWidth = '100%';
+ }
newNode.attributes.push(
toJsxAttribute('style', {
- width: style.maxWidth || '100%',
- aspectRatio: style.height ? undefined : '16 / 9'
+ ...ytStyle,
+ width: style.minWidth ? style.minWidth : '100%',
+ aspectRatio: style.height ? undefined : '16 / 9',
+ ...style
})
);
newNode.children.push(youtubeIframe);
break;
case LeafDirectiveName.CIRCUITVERSE:
newNode.name = 'iframe';
- newNode.attributes.push(toJsxAttribute('width', style.width || '100%'));
newNode.attributes.push(toJsxAttribute('height', style.height || '315px'));
newNode.attributes.push(toJsxAttribute('src', src));
newNode.attributes.push(toJsxAttribute('title', 'Circuit Verse'));
newNode.attributes.push(toJsxAttribute('frameBorder', '0'));
newNode.attributes.push(toJsxAttribute('scrolling', 'no'));
- newNode.attributes.push(toJsxAttribute('webkitAllowFullScreen', ''));
- newNode.attributes.push(toJsxAttribute('mozAllowFullScreen', ''));
- newNode.attributes.push(toJsxAttribute('allowFullScreen', ''));
+ newNode.attributes.push(toJsxAttribute('allowFullScreen', true));
+ newNode.attributes.push(
+ toJsxAttribute('style', {
+ width: style.minWidth ? style.minWidth : '100%',
+ maxWidth: '100%',
+ ...style
+ })
+ );
break;
case LeafDirectiveName.LEARNINGAPPS:
const appId = new URL(src).pathname.split('/')[1];
const transformedSrc = `https://learningapps.org/watch?app=${appId}`;
newNode.name = 'iframe';
- newNode.attributes.push(toJsxAttribute('width', style.width || '100%'));
newNode.attributes.push(toJsxAttribute('height', style.height || '500px'));
newNode.attributes.push(toJsxAttribute('src', transformedSrc));
newNode.attributes.push(toJsxAttribute('title', 'Learningapps'));
newNode.attributes.push(toJsxAttribute('frameBorder', '0'));
newNode.attributes.push(toJsxAttribute('scrolling', 'no'));
- newNode.attributes.push(toJsxAttribute('webkitallowfullscreen', ''));
- newNode.attributes.push(toJsxAttribute('mozAllowFullScreen', ''));
- newNode.attributes.push(toJsxAttribute('allowFullScreen', ''));
+ newNode.attributes.push(toJsxAttribute('allowFullScreen', true));
+ newNode.attributes.push(
+ toJsxAttribute('style', {
+ width: style.minWidth ? style.minWidth : '100%',
+ maxWidth: '100%',
+ ...style
+ })
+ );
+ break;
+ case LeafDirectiveName.CODEPEN:
+ let pen = src;
+ if (/codepen\.io\/.*\/pen\/.*/.test(src)) {
+ pen = src.replace(/\/pen\//, '/embed/');
+ }
+ const penSource = new URL(pen);
+ penSource.searchParams.set('editable', 'true');
+ if (attributes.theme) {
+ penSource.searchParams.set('theme-id', `${attributes.theme}`);
+ }
+ if (attributes.defaultTab) {
+ penSource.searchParams.set('default-tab', `${attributes.defaultTab}`);
+ }
+ if (attributes.editable !== undefined && !attributes.editable) {
+ penSource.searchParams.delete('editable');
+ }
+ newNode.name = 'iframe';
+ newNode.attributes.push(toJsxAttribute('height', style.height || '500px'));
+ newNode.attributes.push(toJsxAttribute('src', penSource.toString()));
+ newNode.attributes.push(toJsxAttribute('title', 'Codepen'));
+ newNode.attributes.push(toJsxAttribute('scrolling', 'no'));
+ newNode.attributes.push(toJsxAttribute('frameBorder', 'no'));
+ newNode.attributes.push(toJsxAttribute('loading', 'lazy'));
+ newNode.attributes.push(toJsxAttribute('allowTransparency', true));
+ newNode.attributes.push(toJsxAttribute('allowFullScreen', true));
+ newNode.attributes.push(
+ toJsxAttribute('style', {
+ width: style.minWidth ? style.minWidth : '100%',
+ maxWidth: '100%',
+ ...style
+ })
+ );
break;
}
diff --git a/src/plugins/remark-media/tests/plugin.test.ts b/src/plugins/remark-media/tests/plugin.test.ts
index ac8edb45..7405c497 100644
--- a/src/plugins/remark-media/tests/plugin.test.ts
+++ b/src/plugins/remark-media/tests/plugin.test.ts
@@ -73,13 +73,45 @@ describe('#medialinks', () => {
"
`);
});
+ it('can convert youtube directive with opitions', async () => {
+ const input = `
+ ::youtube[https://www.youtube.com/embed/QPZ0pIK_wsc?si=fP8L8fYQ-TYgYwUe]{width=200px height=100px}
+ `;
+ const result = await process(input);
+ expect(result).toMatchInlineSnapshot(`
+ "
+
+
+ "
+ `);
+ });
it('can convert circuitverse directive', async () => {
const input = `
::circuitverse[https://circuitverse.org/simulator/embed/rothe-inverter]
`;
const result = await process(input);
expect(result).toMatchInlineSnapshot(`
- "
+ "
+ "
+ `);
+ });
+ it('can convert codepen directive', async () => {
+ const input = `
+ ::codepen[https://codepen.io/lebalz/pen/PwYoOBK]
+ `;
+ const result = await process(input);
+ expect(result).toMatchInlineSnapshot(`
+ "
+ "
+ `);
+ });
+ it('can convert codepen directive with attributes', async () => {
+ const input = `
+ ::codepen[https://codepen.io/lebalz/pen/PwYoOBK]{theme=dark editable=false defaultTab=css,result width=920px height=500}
+ `;
+ const result = await process(input);
+ expect(result).toMatchInlineSnapshot(`
+ "
"
`);
});