mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-06-08 02:15:02 -04:00
fix: Move content into to frontend directory
Doing this BEFORE the merge prevents a lot of merge conflicts. Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
4e18ce38f3
commit
762a0a850e
1051 changed files with 0 additions and 35 deletions
|
@ -0,0 +1,19 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`YoutubeFrame renders a click shield 1`] = `
|
||||
<div>
|
||||
<span>
|
||||
This is a click shield for
|
||||
<span
|
||||
class="embed-responsive embed-responsive-16by9"
|
||||
>
|
||||
<iframe
|
||||
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
|
||||
class="embed-responsive-item"
|
||||
src="https://www.youtube-nocookie.com/embed/validYoutubeId?autoplay=1"
|
||||
title="youtube video of validYoutubeId"
|
||||
/>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
|
@ -0,0 +1,37 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`youtube markdown extension doesn't render invalid youtube ids in short code syntax 1`] = `
|
||||
<div>
|
||||
<p>
|
||||
{%youtube a %}
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`youtube markdown extension renders legacy youtube syntax 1`] = `
|
||||
<div>
|
||||
<p>
|
||||
<span>
|
||||
this is a mock for the youtube frame with id
|
||||
XDnhKh5V5XQ
|
||||
</span>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`youtube markdown extension renders plain youtube URLs 1`] = `
|
||||
<div>
|
||||
<p>
|
||||
<span>
|
||||
this is a mock for the youtube frame with id
|
||||
XDnhKh5V5XQ
|
||||
</span>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
`;
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import MarkdownIt from 'markdown-it'
|
||||
import { replaceLegacyYoutubeShortCodeMarkdownItPlugin } from './replace-legacy-youtube-short-code'
|
||||
|
||||
describe('Replace legacy youtube short codes', () => {
|
||||
let markdownIt: MarkdownIt
|
||||
|
||||
beforeEach(() => {
|
||||
markdownIt = new MarkdownIt('default', {
|
||||
html: false,
|
||||
breaks: true,
|
||||
langPrefix: '',
|
||||
typographer: true
|
||||
})
|
||||
markdownIt.use(replaceLegacyYoutubeShortCodeMarkdownItPlugin)
|
||||
})
|
||||
|
||||
it('detects a valid legacy youtube short code', () => {
|
||||
expect(markdownIt.renderInline('{%youtube 12312312312 %}')).toBe('<app-youtube id="12312312312"></app-youtube>')
|
||||
})
|
||||
|
||||
it("won't detect an empty string", () => {
|
||||
const code = '{%youtube %}'
|
||||
expect(markdownIt.renderInline(code)).toBe(code)
|
||||
})
|
||||
|
||||
it("won't detect an invalid(too short) youtube id", () => {
|
||||
const code = '{%youtube 1 %}'
|
||||
expect(markdownIt.renderInline(code)).toBe(code)
|
||||
})
|
||||
|
||||
it("won't detect an invalid(invalid characters) youtube id", () => {
|
||||
const code = '{%youtube /!#/ %}'
|
||||
expect(markdownIt.renderInline(code)).toBe(code)
|
||||
})
|
||||
|
||||
it("won't detect an invalid(too long) youtube id", () => {
|
||||
const code = '{%youtube 111111111111111111111111111111111 %}'
|
||||
expect(markdownIt.renderInline(code)).toBe(code)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { YoutubeMarkdownExtension } from './youtube-markdown-extension'
|
||||
import markdownItRegex from 'markdown-it-regex'
|
||||
import type MarkdownIt from 'markdown-it'
|
||||
import type { RegexOptions } from '../../../external-types/markdown-it-regex/interface'
|
||||
|
||||
export const legacyYouTubeRegex = /^{%youtube\s+([\w-]{11})\s*%}$/
|
||||
|
||||
/**
|
||||
* Configure the given {@link MarkdownIt} to render legacy hedgedoc 1 youtube short codes as embeddings.
|
||||
*
|
||||
* @param markdownIt The {@link MarkdownIt} to configure
|
||||
*/
|
||||
export const replaceLegacyYoutubeShortCodeMarkdownItPlugin: MarkdownIt.PluginSimple = (markdownIt: MarkdownIt): void =>
|
||||
markdownItRegex(markdownIt, {
|
||||
name: 'legacy-youtube-short-code',
|
||||
regex: legacyYouTubeRegex,
|
||||
replace: (match) => {
|
||||
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
||||
// noinspection CheckTagEmptyBody
|
||||
return `<${YoutubeMarkdownExtension.tagName} id="${match}"></${YoutubeMarkdownExtension.tagName}>`
|
||||
}
|
||||
} as RegexOptions)
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { replaceYouTubeLinkMarkdownItPlugin } from './replace-youtube-link'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
|
||||
describe('Replace youtube link', () => {
|
||||
let markdownIt: MarkdownIt
|
||||
|
||||
beforeEach(() => {
|
||||
markdownIt = new MarkdownIt('default', {
|
||||
html: false,
|
||||
breaks: true,
|
||||
langPrefix: '',
|
||||
typographer: true
|
||||
})
|
||||
markdownIt.use(replaceYouTubeLinkMarkdownItPlugin)
|
||||
})
|
||||
;['http://', 'https://', ''].forEach((protocol) => {
|
||||
;['www.', ''].forEach((subdomain) => {
|
||||
;['youtube.com', 'youtube-nocookie.com'].forEach((domain) => {
|
||||
const origin = `${protocol}${subdomain}${domain}/`
|
||||
describe(origin, () => {
|
||||
const validUrl = `${origin}?v=12312312312`
|
||||
it(`can detect a correct youtube video url`, () => {
|
||||
expect(markdownIt.renderInline(validUrl)).toBe('<app-youtube id="12312312312"></app-youtube>')
|
||||
})
|
||||
|
||||
it("won't detect an URL without video id", () => {
|
||||
expect(markdownIt.renderInline(origin)).toBe(origin)
|
||||
})
|
||||
|
||||
it("won't detect an invalid(too short) youtube id", () => {
|
||||
const invalidUrl = `${origin}?v=1`
|
||||
expect(markdownIt.renderInline(invalidUrl)).toBe(invalidUrl)
|
||||
})
|
||||
|
||||
it("won't detect an invalid(invalid characters) youtube id", () => {
|
||||
const invalidUrl = `${origin}?v= /!#/`
|
||||
expect(markdownIt.renderInline(invalidUrl)).toBe(invalidUrl)
|
||||
})
|
||||
|
||||
it("won't detect an invalid(too long) youtube id", () => {
|
||||
const invalidUrl = `${origin}?v=111111111111111111111111111111111`
|
||||
expect(markdownIt.renderInline(invalidUrl)).toBe(invalidUrl)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { YoutubeMarkdownExtension } from './youtube-markdown-extension'
|
||||
import markdownItRegex from 'markdown-it-regex'
|
||||
import type MarkdownIt from 'markdown-it'
|
||||
import type { RegexOptions } from '../../../external-types/markdown-it-regex/interface'
|
||||
|
||||
const linkRegex =
|
||||
/^(?:https?:\/\/)?(?:www.)?(?:youtube(?:-nocookie)?\.com\/(?:[^\\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([\w-]{11})(?:[?&#].*)?$/i
|
||||
|
||||
/**
|
||||
* Replacer for youtube links.
|
||||
*/
|
||||
export const replaceYouTubeLinkMarkdownItPlugin: MarkdownIt.PluginSimple = (markdownIt: MarkdownIt) =>
|
||||
markdownItRegex(markdownIt, {
|
||||
name: 'youtube-link',
|
||||
regex: linkRegex,
|
||||
replace: (match) => {
|
||||
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
||||
// noinspection CheckTagEmptyBody
|
||||
return `<${YoutubeMarkdownExtension.tagName} id="${match}"></${YoutubeMarkdownExtension.tagName}>`
|
||||
}
|
||||
} as RegexOptions)
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { AppExtension } from '../../base/app-extension'
|
||||
import type { MarkdownRendererExtension } from '../../../components/markdown-renderer/extensions/base/markdown-renderer-extension'
|
||||
import { YoutubeMarkdownExtension } from './youtube-markdown-extension'
|
||||
import type { Linter } from '../../../components/editor-page/editor-pane/linter/linter'
|
||||
import { SingleLineRegexLinter } from '../../../components/editor-page/editor-pane/linter/single-line-regex-linter'
|
||||
import { legacyYouTubeRegex } from './replace-legacy-youtube-short-code'
|
||||
import { t } from 'i18next'
|
||||
|
||||
/**
|
||||
* Adds YouTube video embeddings to the markdown renderer.
|
||||
*/
|
||||
export class YoutubeAppExtension extends AppExtension {
|
||||
buildMarkdownRendererExtensions(): MarkdownRendererExtension[] {
|
||||
return [new YoutubeMarkdownExtension()]
|
||||
}
|
||||
|
||||
public buildCodeMirrorLinter(): Linter[] {
|
||||
return [
|
||||
new SingleLineRegexLinter(
|
||||
legacyYouTubeRegex,
|
||||
t('editor.linter.shortcode', { shortcode: 'YouTube' }),
|
||||
(match: string) => `https://www.youtube.com/watch?v=${match}`
|
||||
)
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { render } from '@testing-library/react'
|
||||
import { YouTubeFrame } from './youtube-frame'
|
||||
import React from 'react'
|
||||
import * as ClickShieldModule from '../../../components/markdown-renderer/replace-components/click-shield/click-shield'
|
||||
import type { ClickShieldProps } from '../../../components/markdown-renderer/replace-components/click-shield/click-shield'
|
||||
|
||||
jest.mock('../../../components/markdown-renderer/replace-components/click-shield/click-shield')
|
||||
|
||||
describe('YoutubeFrame', () => {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(ClickShieldModule, 'ClickShield').mockImplementation((({ children }) => {
|
||||
return <span>This is a click shield for {children}</span>
|
||||
}) as React.FC<ClickShieldProps>)
|
||||
})
|
||||
|
||||
it('renders a click shield', () => {
|
||||
const view = render(<YouTubeFrame id={'validYoutubeId'} />)
|
||||
expect(view.container).toMatchSnapshot()
|
||||
})
|
||||
})
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { ClickShield } from '../../../components/markdown-renderer/replace-components/click-shield/click-shield'
|
||||
import type { IdProps } from '../../../components/markdown-renderer/replace-components/custom-tag-with-id-component-replacer'
|
||||
|
||||
/**
|
||||
* Renders a video player embedding for https://youtube.com
|
||||
*
|
||||
* @param id The id from the youtube video url
|
||||
*/
|
||||
export const YouTubeFrame: React.FC<IdProps> = ({ id }) => {
|
||||
return (
|
||||
<ClickShield
|
||||
hoverIcon={'youtube-play'}
|
||||
targetDescription={'YouTube'}
|
||||
fallbackPreviewImageUrl={`https://i.ytimg.com/vi/${id}/maxresdefault.jpg`}
|
||||
fallbackBackgroundColor={'#ff0000'}
|
||||
data-cypress-id={'click-shield-youtube'}>
|
||||
<span className={'embed-responsive embed-responsive-16by9'}>
|
||||
<iframe
|
||||
className='embed-responsive-item'
|
||||
title={`youtube video of ${id}`}
|
||||
src={`https://www.youtube-nocookie.com/embed/${id}?autoplay=1`}
|
||||
allow='accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture'
|
||||
/>
|
||||
</span>
|
||||
</ClickShield>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { YoutubeMarkdownExtension } from './youtube-markdown-extension'
|
||||
import { render } from '@testing-library/react'
|
||||
import * as YouTubeFrameModule from './youtube-frame'
|
||||
import React from 'react'
|
||||
import { mockI18n } from '../../../components/markdown-renderer/test-utils/mock-i18n'
|
||||
import { TestMarkdownRenderer } from '../../../components/markdown-renderer/test-utils/test-markdown-renderer'
|
||||
import type { IdProps } from '../../../components/markdown-renderer/replace-components/custom-tag-with-id-component-replacer'
|
||||
|
||||
jest.mock('./youtube-frame')
|
||||
|
||||
describe('youtube markdown extension', () => {
|
||||
beforeAll(async () => {
|
||||
jest
|
||||
.spyOn(YouTubeFrameModule, 'YouTubeFrame')
|
||||
.mockImplementation((({ id }) => (
|
||||
<span>this is a mock for the youtube frame with id {id}</span>
|
||||
)) as React.FC<IdProps>)
|
||||
await mockI18n()
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.resetAllMocks()
|
||||
jest.resetModules()
|
||||
})
|
||||
|
||||
it('renders plain youtube URLs', () => {
|
||||
const view = render(
|
||||
<TestMarkdownRenderer
|
||||
extensions={[new YoutubeMarkdownExtension()]}
|
||||
content={'https://www.youtube.com/watch?v=XDnhKh5V5XQ'}
|
||||
/>
|
||||
)
|
||||
expect(view.container).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('renders legacy youtube syntax', () => {
|
||||
const view = render(
|
||||
<TestMarkdownRenderer extensions={[new YoutubeMarkdownExtension()]} content={'{%youtube XDnhKh5V5XQ %}'} />
|
||||
)
|
||||
expect(view.container).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it("doesn't render invalid youtube ids in short code syntax", () => {
|
||||
const view = render(
|
||||
<TestMarkdownRenderer extensions={[new YoutubeMarkdownExtension()]} content={'{%youtube a %}'} />
|
||||
)
|
||||
expect(view.container).toMatchSnapshot()
|
||||
})
|
||||
})
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { replaceYouTubeLinkMarkdownItPlugin } from './replace-youtube-link'
|
||||
import { replaceLegacyYoutubeShortCodeMarkdownItPlugin } from './replace-legacy-youtube-short-code'
|
||||
import type MarkdownIt from 'markdown-it'
|
||||
import { YouTubeFrame } from './youtube-frame'
|
||||
import { MarkdownRendererExtension } from '../../../components/markdown-renderer/extensions/base/markdown-renderer-extension'
|
||||
import { CustomTagWithIdComponentReplacer } from '../../../components/markdown-renderer/replace-components/custom-tag-with-id-component-replacer'
|
||||
import type { ComponentReplacer } from '../../../components/markdown-renderer/replace-components/component-replacer'
|
||||
|
||||
/**
|
||||
* Adds YouTube video embeddings using link detection and the legacy YouTube short code syntax.
|
||||
*/
|
||||
export class YoutubeMarkdownExtension extends MarkdownRendererExtension {
|
||||
public static readonly tagName = 'app-youtube'
|
||||
|
||||
public configureMarkdownIt(markdownIt: MarkdownIt): void {
|
||||
replaceYouTubeLinkMarkdownItPlugin(markdownIt)
|
||||
replaceLegacyYoutubeShortCodeMarkdownItPlugin(markdownIt)
|
||||
}
|
||||
|
||||
public buildReplacers(): ComponentReplacer[] {
|
||||
return [new CustomTagWithIdComponentReplacer(YouTubeFrame, YoutubeMarkdownExtension.tagName)]
|
||||
}
|
||||
|
||||
public buildTagNameAllowList(): string[] {
|
||||
return [YoutubeMarkdownExtension.tagName]
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue