diff --git a/config/default.json b/config/default.json
index 6b7aeb4..a8a7e27 100644
--- a/config/default.json
+++ b/config/default.json
@@ -32,9 +32,9 @@
"google_analytics_id": "UA-106330268-3",
"helmet": {
"directives": {
- "childSrc": "'self' player.twitch.tv www.youtube.com staticxx.facebook.com w.soundcloud.com open.spotify.com player.vimeo.com www.theweedtube.com emb.d.tube player.twitch.tv www.twitch.tv gleam.io js.gleam.io",
+ "childSrc": "'self' emb.d.tube player.twitch.tv www.youtube.com staticxx.facebook.com w.soundcloud.com open.spotify.com player.vimeo.com www.theweedtube.com emb.d.tube player.twitch.tv www.twitch.tv gleam.io js.gleam.io",
"connectSrc": "'self' smoke.io rpc.smoke.io https://rpc.smoke.io wss://rpc.smoke.io pubrpc.smoke.io api.smoke.io",
- "defaultSrc": "'self' www.youtube.com staticxx.facebook.com player.vimeo.com open.spotify.com",
+ "defaultSrc": "'self' emb.d.tube www.youtube.com staticxx.facebook.com player.vimeo.com open.spotify.com",
"fontSrc": "data: fonts.gstatic.com",
"frameAncestors": "'none'",
"imgSrc": "* data:",
diff --git a/src/app/components/cards/MarkdownViewer.jsx b/src/app/components/cards/MarkdownViewer.jsx
index d6a338e..3e18bfd 100644
--- a/src/app/components/cards/MarkdownViewer.jsx
+++ b/src/app/components/cards/MarkdownViewer.jsx
@@ -110,7 +110,7 @@ class MarkdownViewer extends Component {
// HtmlReady inserts ~~~ embed:${id} type ~~~
for (let section of cleanText.split('~~~ embed:')) {
- const match = section.match(/^([A-Za-z0-9\?\=\_\-]+) (youtube|vimeo|twitch|spotify|spotifyLarge) ~~~/)
+ const match = section.match(/^([A-Za-z0-9\?\=\_\-\/]+) (youtube|vimeo|twitch|spotify|spotifyLarge|dtube) ~~~/)
if (match && match.length >= 2) {
const id = match[1]
const type = match[2]
@@ -180,6 +180,20 @@ class MarkdownViewer extends Component {
/>
);
+ } else if (type === 'dtube') {
+ const url = `https://emb.d.tube/#!/${id}`;
+ sections.push(
+
+
+
+ );
} else {
console.error('MarkdownViewer unknown embed type', type);
}
diff --git a/src/app/utils/Links.js b/src/app/utils/Links.js
index 5d7a07e..1e17f51 100644
--- a/src/app/utils/Links.js
+++ b/src/app/utils/Links.js
@@ -36,6 +36,8 @@ export default {
// simpleLink: new RegExp(`(.*)<\/a>`, 'ig'),
ipfsPrefix: /(https?:\/\/.*)?\/ipfs/i,
twitch: /https?:\/\/(?:www.)?twitch.tv\/(?:(videos)\/)?([a-zA-Z0-9][\w]{3,24})/i,
+ dtube: /https:\/\/(?:emb\.)?(?:d.tube\/\#\!\/(?:v\/)?)([a-zA-Z0-9\/]*)/,
+ dtubeId: /(?:d\.tube\/#!\/(?:v\/)?([a-zA-Z0-9\/]*))+/,
}
// Original regex
diff --git a/src/app/utils/SanitizeConfig.js b/src/app/utils/SanitizeConfig.js
index 5994a8e..d577a73 100644
--- a/src/app/utils/SanitizeConfig.js
+++ b/src/app/utils/SanitizeConfig.js
@@ -69,6 +69,13 @@ const iframeWhitelist = [
return src;
},
},
+ {
+ re: /^https:\/\/emb.d.tube\/\#\!\/([a-zA-Z0-9\/]+)$/,
+ fn: src => {
+ //
+ return src;
+ },
+ },
];
export const noImageText = '(Image not shown due to low ratings)'
export const allowedTags = `
diff --git a/src/app/utils/SlateEditor/Iframe.js b/src/app/utils/SlateEditor/Iframe.js
index 678a6a2..d16bab4 100644
--- a/src/app/utils/SlateEditor/Iframe.js
+++ b/src/app/utils/SlateEditor/Iframe.js
@@ -33,6 +33,12 @@ export default class Iframe extends React.Component {
}
}
+ // Detect dtube
+ match = url.match(linksRe.dtubeId);
+ if (match && match.length >= 2) {
+ return 'https://emb.d.tube/#!/' + match[1];
+ }
+
console.log("unable to auto-detect embed url", url)
return null
}
diff --git a/src/shared/HtmlReady.js b/src/shared/HtmlReady.js
index 14c60d6..493f870 100644
--- a/src/shared/HtmlReady.js
+++ b/src/shared/HtmlReady.js
@@ -220,6 +220,7 @@ function linkifyNode(child, state) {
child = embedYouTubeNode(child, state.links, state.images);
child = embedVimeoNode(child, state.links, state.images);
child = embedTwitchNode(child, state.links, state.images);
+ child = embedDTubeNode(child, state.links, state.images);
if (embedSpotifyNode(child, state.links, state.images)) return
if (embedSpotifyLargeNode(child, state.links, state.images)) return
@@ -421,6 +422,33 @@ function twitchId(data) {
};
}
+function embedDTubeNode(child, links /*images*/) {
+ try {
+ const data = child.data;
+ const dtube = dtubeId(data);
+ if (!dtube) return child;
+
+ child.data = data.replace(dtube.url, `~~~ embed:${dtube.id} dtube ~~~`);
+
+ if (links) links.add(dtube.canonical);
+ } catch (error) {
+ console.log(error);
+ }
+ return child;
+}
+
+function dtubeId(data) {
+ if (!data) return null;
+ const m = data.match(linksRe.dtube);
+ if (!m || m.length < 2) return null;
+
+ return {
+ id: m[1],
+ url: m[0],
+ canonical: `https://emb.d.tube/#!/${m[1]}`,
+ };
+}
+
function ipfsPrefix(url) {
if ($STM_Config.ipfs_prefix) {
// Convert //ipfs/xxx or /ipfs/xxx into https://smoke.io/ipfs/xxxxx
diff --git a/src/shared/HtmlReady.test.js b/src/shared/HtmlReady.test.js
index c50a996..2a5e2e6 100644
--- a/src/shared/HtmlReady.test.js
+++ b/src/shared/HtmlReady.test.js
@@ -38,6 +38,24 @@ describe('htmlready', () => {
expect(res).toEqual(htmlified);
});
+ it('should not omit text on same line as dtube link', () => {
+ const testString =
+ 'before text https://d.tube/#!/v/tibfox/mvh7g26e after text
';
+ const htmlified =
+ 'before text ~~~ embed:tibfox/mvh7g26e dtube ~~~ after text
';
+ const res = HtmlReady(testString).html;
+ expect(res).toEqual(htmlified);
+ });
+
+ it('should handle dtube embed', () => {
+ const testString =
+ '';
+ const htmlified =
+ '';
+ const res = HtmlReady(testString).html;
+ expect(res).toEqual(htmlified);
+ });
+
it('should not allow links where the text portion contains smoke.io but the link does not', () => {
// There isn't an easy way to mock counterpart, even with proxyquire, so we just test for the missing translation message -- ugly but ok