Allow embedding of GitLab snippets (#6217)
This commit is contained in:
BIN
public/images/gitlab.png
Normal file
BIN
public/images/gitlab.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.3 KiB |
@@ -24,9 +24,19 @@ import auth from "../routes/auth";
|
|||||||
|
|
||||||
// Construct scripts CSP based on services in use by this installation
|
// Construct scripts CSP based on services in use by this installation
|
||||||
const defaultSrc = ["'self'"];
|
const defaultSrc = ["'self'"];
|
||||||
const scriptSrc = ["'self'", "gist.github.com", "www.googletagmanager.com"];
|
const scriptSrc = [
|
||||||
|
"'self'",
|
||||||
|
"gist.github.com",
|
||||||
|
"www.googletagmanager.com",
|
||||||
|
"gitlab.com",
|
||||||
|
];
|
||||||
|
|
||||||
const styleSrc = ["'self'", "'unsafe-inline'", "github.githubassets.com"];
|
const styleSrc = [
|
||||||
|
"'self'",
|
||||||
|
"'unsafe-inline'",
|
||||||
|
"github.githubassets.com",
|
||||||
|
"gitlab.com",
|
||||||
|
];
|
||||||
|
|
||||||
if (env.isCloudHosted) {
|
if (env.isCloudHosted) {
|
||||||
scriptSrc.push("cdn.zapier.com");
|
scriptSrc.push("cdn.zapier.com");
|
||||||
|
|||||||
31
shared/editor/embeds/GitLabSnippet.test.ts
Normal file
31
shared/editor/embeds/GitLabSnippet.test.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import GitLabSnippet from "./GitLabSnippet";
|
||||||
|
|
||||||
|
describe("GitLabSnippet", () => {
|
||||||
|
const match = GitLabSnippet.ENABLED[0];
|
||||||
|
|
||||||
|
test("to be enabled on snippet link", () => {
|
||||||
|
expect("https://gitlab.com/-/snippets/1234".match(match)).toBeTruthy();
|
||||||
|
expect(
|
||||||
|
"https://gitlab.com/gitlab-org/gitlab/-/snippets/2256824".match(match)
|
||||||
|
).toBeTruthy();
|
||||||
|
expect(
|
||||||
|
"https://gitlab.com/group/project/sub-project/sub-sub-project/test/-/snippets/9876".match(
|
||||||
|
match
|
||||||
|
)
|
||||||
|
).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("to not be enabled elsewhere", () => {
|
||||||
|
expect("https://gitlab.com".match(match)).toBe(null);
|
||||||
|
expect("https://gitlab.com/gitlab-org".match(match)).toBe(null);
|
||||||
|
expect("https://gitlab.com/gitlab-org/gitlab".match(match)).toBe(null);
|
||||||
|
expect("https://gitlab.com/gitlab-org/gitlab/-/issues".match(match)).toBe(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
"https://gitlab.com/gitlab-org/gitlab/-/merge_requests/137948".match(
|
||||||
|
match
|
||||||
|
)
|
||||||
|
).toBe(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
38
shared/editor/embeds/GitLabSnippet.tsx
Normal file
38
shared/editor/embeds/GitLabSnippet.tsx
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
import { EmbedProps as Props } from ".";
|
||||||
|
|
||||||
|
const GITLAB_NAMESPACE_REGEX = "(([a-zA-Z\\d-]+)/)";
|
||||||
|
|
||||||
|
const Iframe = styled.iframe`
|
||||||
|
margin-top: 8px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
function GitLabSnippet(props: Props) {
|
||||||
|
const snippetUrl = new URL(props.attrs.href);
|
||||||
|
const id = snippetUrl.pathname.split("/").pop();
|
||||||
|
const snippetLink = `${snippetUrl}.js`;
|
||||||
|
const snippetScript = `<script type="text/javascript" src="${snippetLink}"></script>`;
|
||||||
|
const styles = "<style>body { margin: 0; }</style>";
|
||||||
|
const iframeHtml = `<html><head><base target="_parent">${styles}</head><body>${snippetScript}</body></html>`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Iframe
|
||||||
|
src={`data:text/html;base64,${btoa(iframeHtml)}`}
|
||||||
|
className={props.isSelected ? "ProseMirror-selectednode" : ""}
|
||||||
|
frameBorder="0"
|
||||||
|
width="100%"
|
||||||
|
height="400px"
|
||||||
|
id={`gitlab-snippet-${id}`}
|
||||||
|
title="GitLab Snippet"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
GitLabSnippet.ENABLED = [
|
||||||
|
new RegExp(
|
||||||
|
`^https://gitlab\\.com/${GITLAB_NAMESPACE_REGEX}*-/snippets/\\d+$`
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
export default GitLabSnippet;
|
||||||
@@ -20,6 +20,7 @@ import Diagrams from "./Diagrams";
|
|||||||
import Figma from "./Figma";
|
import Figma from "./Figma";
|
||||||
import Framer from "./Framer";
|
import Framer from "./Framer";
|
||||||
import Gist from "./Gist";
|
import Gist from "./Gist";
|
||||||
|
import GitLabSnippet from "./GitLabSnippet";
|
||||||
import Gliffy from "./Gliffy";
|
import Gliffy from "./Gliffy";
|
||||||
import GoogleCalendar from "./GoogleCalendar";
|
import GoogleCalendar from "./GoogleCalendar";
|
||||||
import GoogleDocs from "./GoogleDocs";
|
import GoogleDocs from "./GoogleDocs";
|
||||||
@@ -211,6 +212,12 @@ const embeds: EmbedDescriptor[] = [
|
|||||||
icon: <Img src="/images/github-gist.png" alt="GitHub" />,
|
icon: <Img src="/images/github-gist.png" alt="GitHub" />,
|
||||||
component: Gist,
|
component: Gist,
|
||||||
}),
|
}),
|
||||||
|
new EmbedDescriptor({
|
||||||
|
title: "GitLab Snippet",
|
||||||
|
keywords: "code",
|
||||||
|
icon: <Img src="/images/gitlab.png" alt="GitLab" />,
|
||||||
|
component: GitLabSnippet,
|
||||||
|
}),
|
||||||
new EmbedDescriptor({
|
new EmbedDescriptor({
|
||||||
title: "Gliffy",
|
title: "Gliffy",
|
||||||
keywords: "diagram",
|
keywords: "diagram",
|
||||||
|
|||||||
Reference in New Issue
Block a user