mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-14 07:04:45 -04:00
parent
3a0e35a9f3
commit
0e912d64dd
39 changed files with 87 additions and 84 deletions
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -30,7 +30,7 @@ assignees: ''
|
||||||
- OS: [e.g. iOS 13, Ubuntu 20.04, Windows 10]
|
- OS: [e.g. iOS 13, Ubuntu 20.04, Windows 10]
|
||||||
- Browser with version [e.g. Chrome 81, Safari 13.1]
|
- Browser with version [e.g. Chrome 81, Safari 13.1]
|
||||||
- [Check your Browser Version](https://www.whatismybrowser.com/)
|
- [Check your Browser Version](https://www.whatismybrowser.com/)
|
||||||
- CodiMD version (Click "Version info" in the footer)
|
- HedgeDoc version (Click "Version info" in the footer)
|
||||||
- server [e.g. 2.0]
|
- server [e.g. 2.0]
|
||||||
- client [e.g. 2.0]
|
- client [e.g. 2.0]
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
<component name="ProjectDictionaryState">
|
<component name="ProjectDictionaryState">
|
||||||
<dictionary name="codimd">
|
<dictionary name="hedgedoc">
|
||||||
<words>
|
<words>
|
||||||
<w>CodiMD</w>
|
<w>CodiMD</w>
|
||||||
|
<w>HedgeDoc</w>
|
||||||
<w>codimd</w>
|
<w>codimd</w>
|
||||||
|
<w>hedgedoc</w>
|
||||||
</words>
|
</words>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
</component>
|
</component>
|
|
@ -3,7 +3,7 @@
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
### Deprecations
|
### Deprecations
|
||||||
- This version of CodiMD is the last version that supports the following short-code syntaxes for embedding content. Embedding works now instead by putting the plain webpage link to the content into a single line.
|
- This version of HedgeDoc is the last version that supports the following short-code syntaxes for embedding content. Embedding works now instead by putting the plain webpage link to the content into a single line.
|
||||||
- `{%youtube someid %}` -> https://youtube.com/watch?v=someid
|
- `{%youtube someid %}` -> https://youtube.com/watch?v=someid
|
||||||
- `{%vimeo 123456789 %}` -> https://vimeo.com/123456789
|
- `{%vimeo 123456789 %}` -> https://vimeo.com/123456789
|
||||||
- `{%gist user/12345 %}` -> https://gist.github.com/user/12345
|
- `{%gist user/12345 %}` -> https://gist.github.com/user/12345
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
- Highlighted code blocks can now use line wrapping and line numbers at once
|
- Highlighted code blocks can now use line wrapping and line numbers at once
|
||||||
- Images, videos, and other non-text content is now wider in View Mode
|
- Images, videos, and other non-text content is now wider in View Mode
|
||||||
- Notes may now be deleted directly from the history page
|
- Notes may now be deleted directly from the history page
|
||||||
- CodiMD instances can now be branded either with a '@ <custom string>' or '@ <custom logo>' after the CodiMD logo and text
|
- HedgeDoc instances can now be branded either with a '@ <custom string>' or '@ <custom logo>' after the HedgeDoc logo and text
|
||||||
- Images will be loaded via proxy if an image proxy is configured in the backend
|
- Images will be loaded via proxy if an image proxy is configured in the backend
|
||||||
- Asciinema videos may now be embedded by pasting the URL of one video into a single line
|
- Asciinema videos may now be embedded by pasting the URL of one video into a single line
|
||||||
- The Toolbar includes an EmojiPicker
|
- The Toolbar includes an EmojiPicker
|
||||||
|
|
12
README.md
12
README.md
|
@ -1,9 +1,9 @@
|
||||||
# CodiMD - React Client
|
# HedgeDoc - React Client
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
This is the new, improved and better looking frontend for CodiMD 2.0.
|
This is the new, improved and better looking frontend for HedgeDoc 2.0.
|
||||||
Our goal is to recreate the current frontend in react and to improve it.
|
Our goal is to recreate the current frontend in react and to improve it.
|
||||||
|
|
||||||
## Preparation
|
## Preparation
|
||||||
|
@ -11,8 +11,8 @@ You'll need at least Node 12. We use [yarn](https://yarnpkg.com/) for our depend
|
||||||
|
|
||||||
## Development mode
|
## Development mode
|
||||||
|
|
||||||
1. Clone this repo (e.g. `git clone https://github.com/codimd/react-client.git codimd-react-client`)
|
1. Clone this repo (e.g. `git clone https://github.com/codimd/react-client.git hedgedoc-react-client`)
|
||||||
2. Go inside the repo (e.g. `cd codimd-react-client`)
|
2. Go inside the repo (e.g. `cd hedgedoc-react-client`)
|
||||||
3. Run `yarn install`
|
3. Run `yarn install`
|
||||||
4. Either run
|
4. Either run
|
||||||
- `yarn start:dev` (expects [a server](https://github.com/codimd/server/tree/develop) running under [http://localhost:3000](http://localhost:3000))
|
- `yarn start:dev` (expects [a server](https://github.com/codimd/server/tree/develop) running under [http://localhost:3000](http://localhost:3000))
|
||||||
|
@ -42,8 +42,8 @@ We use [cypress](https://cypress.io) for e2e tests.
|
||||||
|
|
||||||
## Production mode
|
## Production mode
|
||||||
|
|
||||||
1. Clone this repo (e.g. `git clone https://github.com/codimd/react-client.git codimd-react-client`)
|
1. Clone this repo (e.g. `git clone https://github.com/codimd/react-client.git hedgedoc-react-client`)
|
||||||
2. Go inside the repo (e.g. `cd codimd-react-client`)
|
2. Go inside the repo (e.g. `cd hedgedoc-react-client`)
|
||||||
3. Run `yarn install`
|
3. Run `yarn install`
|
||||||
4. Run `yarn build`
|
4. Run `yarn build`
|
||||||
|
|
||||||
|
|
|
@ -15,19 +15,19 @@ describe('Document Title', () => {
|
||||||
it('just yaml metadata title', () => {
|
it('just yaml metadata title', () => {
|
||||||
cy.get('.CodeMirror textarea')
|
cy.get('.CodeMirror textarea')
|
||||||
.type(`---\ntitle: ${title}\n---`)
|
.type(`---\ntitle: ${title}\n---`)
|
||||||
cy.title().should('eq', `${title} - CodiMD @ ${branding.name}`)
|
cy.title().should('eq', `${title} - HedgeDoc @ ${branding.name}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('yaml metadata title and opengraph title', () => {
|
it('yaml metadata title and opengraph title', () => {
|
||||||
cy.get('.CodeMirror textarea')
|
cy.get('.CodeMirror textarea')
|
||||||
.type(`---\ntitle: ${title}\nopengraph:\n title: False title\n{backspace}{backspace}---`)
|
.type(`---\ntitle: ${title}\nopengraph:\n title: False title\n{backspace}{backspace}---`)
|
||||||
cy.title().should('eq', `${title} - CodiMD @ ${branding.name}`)
|
cy.title().should('eq', `${title} - HedgeDoc @ ${branding.name}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('yaml metadata title, opengraph title and first heading', () => {
|
it('yaml metadata title, opengraph title and first heading', () => {
|
||||||
cy.get('.CodeMirror textarea')
|
cy.get('.CodeMirror textarea')
|
||||||
.type(`---\ntitle: ${title}\nopengraph:\n title: False title\n{backspace}{backspace}---\n# a first title`)
|
.type(`---\ntitle: ${title}\nopengraph:\n title: False title\n{backspace}{backspace}---\n# a first title`)
|
||||||
cy.title().should('eq', `${title} - CodiMD @ ${branding.name}`)
|
cy.title().should('eq', `${title} - HedgeDoc @ ${branding.name}`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -35,13 +35,13 @@ describe('Document Title', () => {
|
||||||
it('just opengraph title', () => {
|
it('just opengraph title', () => {
|
||||||
cy.get('.CodeMirror textarea')
|
cy.get('.CodeMirror textarea')
|
||||||
.type(`---\nopengraph:\n title: ${title}\n{backspace}{backspace}---`)
|
.type(`---\nopengraph:\n title: ${title}\n{backspace}{backspace}---`)
|
||||||
cy.title().should('eq', `${title} - CodiMD @ ${branding.name}`)
|
cy.title().should('eq', `${title} - HedgeDoc @ ${branding.name}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('opengraph title and first heading', () => {
|
it('opengraph title and first heading', () => {
|
||||||
cy.get('.CodeMirror textarea')
|
cy.get('.CodeMirror textarea')
|
||||||
.type(`---\nopengraph:\n title: ${title}\n{backspace}{backspace}---\n# a first title`)
|
.type(`---\nopengraph:\n title: ${title}\n{backspace}{backspace}---\n# a first title`)
|
||||||
cy.title().should('eq', `${title} - CodiMD @ ${branding.name}`)
|
cy.title().should('eq', `${title} - HedgeDoc @ ${branding.name}`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -49,19 +49,19 @@ describe('Document Title', () => {
|
||||||
it('just first heading', () => {
|
it('just first heading', () => {
|
||||||
cy.get('.CodeMirror textarea')
|
cy.get('.CodeMirror textarea')
|
||||||
.type(`# ${title}`)
|
.type(`# ${title}`)
|
||||||
cy.title().should('eq', `${title} - CodiMD @ ${branding.name}`)
|
cy.title().should('eq', `${title} - HedgeDoc @ ${branding.name}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('just first heading with alt-text instead of image', () => {
|
it('just first heading with alt-text instead of image', () => {
|
||||||
cy.get('.CodeMirror textarea')
|
cy.get('.CodeMirror textarea')
|
||||||
.type(`# ${title} `)
|
.type(`# ${title} `)
|
||||||
cy.title().should('eq', `${title} abc - CodiMD @ ${branding.name}`)
|
cy.title().should('eq', `${title} abc - HedgeDoc @ ${branding.name}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('just first heading without link syntax', () => {
|
it('just first heading without link syntax', () => {
|
||||||
cy.get('.CodeMirror textarea')
|
cy.get('.CodeMirror textarea')
|
||||||
.type(`# ${title} [link](https://hedgedoc.org)`)
|
.type(`# ${title} [link](https://codimd.org)`)
|
||||||
cy.title().should('eq', `${title} link - CodiMD @ ${branding.name}`)
|
cy.title().should('eq', `${title} link - HedgeDoc @ ${branding.name}`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -108,7 +108,7 @@ describe('Links Intro', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Powered By Links', () => {
|
describe('Powered By Links', () => {
|
||||||
it('CodiMD', () => {
|
it('HedgeDoc', () => {
|
||||||
cy.get('a[href="https://codimd.org"]')
|
cy.get('a[href="https://codimd.org"]')
|
||||||
.checkExternalLink('https://codimd.org')
|
.checkExternalLink('https://codimd.org')
|
||||||
})
|
})
|
||||||
|
@ -148,8 +148,8 @@ describe('Links Intro', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Matrix', () => {
|
it('Matrix', () => {
|
||||||
cy.get('a[href="https://riot.im/app/#/room/#codimd:matrix.org"]')
|
cy.get('a[href="https://riot.im/app/#/room/#hedgedoc:matrix.org"]')
|
||||||
.checkExternalLink('https://riot.im/app/#/room/#codimd:matrix.org')
|
.checkExternalLink('https://riot.im/app/#/room/#hedgedoc:matrix.org')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Mastodon', () => {
|
it('Mastodon', () => {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const testText = 'textText'
|
const testText = 'textText'
|
||||||
const testLink = 'http://hedgedoc.org'
|
const testLink = 'http://codimd.org'
|
||||||
|
|
||||||
describe('Toolbar', () => {
|
describe('Toolbar', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": "29QLD0AmT-adevdOPECtqg",
|
"id": "29QLD0AmT-adevdOPECtqg",
|
||||||
"title": "CodiMD community call 2020-04-26",
|
"title": "HedgeDoc community call 2020-04-26",
|
||||||
"lastVisited": "2020-05-16T22:26:56.547Z",
|
"lastVisited": "2020-05-16T22:26:56.547Z",
|
||||||
"tags": [
|
"tags": [
|
||||||
"CodiMD",
|
"HedgeDoc",
|
||||||
"Community Call"
|
"Community Call"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ODakLc2MQkyyFc_Xmb53sg",
|
"id": "ODakLc2MQkyyFc_Xmb53sg",
|
||||||
"title": "CodiMD V2 API",
|
"title": "HedgeDoc V2 API",
|
||||||
"lastVisited": "2020-05-25T19:48:14.025Z",
|
"lastVisited": "2020-05-25T19:48:14.025Z",
|
||||||
"tags": []
|
"tags": []
|
||||||
},
|
},
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
"lastVisited": "2020-05-24T16:04:36.433Z",
|
"lastVisited": "2020-05-24T16:04:36.433Z",
|
||||||
"tags": [
|
"tags": [
|
||||||
"agenda",
|
"agenda",
|
||||||
"CodiMD community",
|
"HedgeDoc community",
|
||||||
"community call"
|
"community call"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "CodiMD",
|
"name": "HedgeDoc",
|
||||||
"short_name": "CodiMD",
|
"short_name": "HedgeDoc",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/icons/android-chrome-192x192.png",
|
"src": "/icons/android-chrome-192x192.png",
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<title>CodiMD</title>
|
<title>HedgeDoc</title>
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/icons/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="/icons/apple-touch-icon.png">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32x32.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32x32.png">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/icons/favicon-16x16.png">
|
<link rel="icon" type="image/png" sizes="16x16" href="/icons/favicon-16x16.png">
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
<meta name="msapplication-config" content="/icons/browserconfig.xml">
|
<meta name="msapplication-config" content="/icons/browserconfig.xml">
|
||||||
<meta name="theme-color" content="#ffffff">
|
<meta name="theme-color" content="#ffffff">
|
||||||
<meta content="width=device-width, initial-scale=1" name="viewport"/>
|
<meta content="width=device-width, initial-scale=1" name="viewport"/>
|
||||||
<meta content="CodiMD - Collaborative markdown notes" name="description"/>
|
<meta content="HedgeDoc - Collaborative markdown notes" name="description"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
"katex": "Works with charts and KaTeX",
|
"katex": "Works with charts and KaTeX",
|
||||||
"slides": "Supports slide mode"
|
"slides": "Supports slide mode"
|
||||||
},
|
},
|
||||||
"screenShotAltText": "CodiMD Screenshot"
|
"screenShotAltText": "HedgeDoc Screenshot"
|
||||||
},
|
},
|
||||||
"history": {
|
"history": {
|
||||||
"error": {
|
"error": {
|
||||||
|
@ -200,7 +200,7 @@
|
||||||
},
|
},
|
||||||
"newVersion": {
|
"newVersion": {
|
||||||
"title": "New version available!",
|
"title": "New version available!",
|
||||||
"description": "A new version of CodiMD is available",
|
"description": "A new version of HedgeDoc is available",
|
||||||
"linkText": "See releases notes here",
|
"linkText": "See releases notes here",
|
||||||
"advice": "Refresh to enjoy new features."
|
"advice": "Refresh to enjoy new features."
|
||||||
},
|
},
|
||||||
|
|
|
@ -8,7 +8,8 @@ export const defaultFetchConfig: Partial<RequestInit> = {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
redirect: 'follow',
|
redirect: 'follow',
|
||||||
referrerPolicy: 'no-referrer'
|
referrerPolicy: 'no-referrer',
|
||||||
|
method: 'GET'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getApiUrl = (): string => {
|
export const getApiUrl = (): string => {
|
||||||
|
|
|
@ -10,7 +10,7 @@ export const DocumentTitle: React.FC<DocumentTitleProps> = ({ title }) => {
|
||||||
const brandingName = useSelector((state: ApplicationState) => state.config.branding.name)
|
const brandingName = useSelector((state: ApplicationState) => state.config.branding.name)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.title = `${title ? title + ' - ' : ''}CodiMD ${brandingName ? ` @ ${brandingName}` : ''}`
|
document.title = `${title ? title + ' - ' : ''}HedgeDoc ${brandingName ? ` @ ${brandingName}` : ''}`
|
||||||
}, [brandingName, title])
|
}, [brandingName, title])
|
||||||
|
|
||||||
return null
|
return null
|
||||||
|
|
|
@ -24,7 +24,7 @@ export const Links: React.FC = () => {
|
||||||
<TranslatedExternalLink
|
<TranslatedExternalLink
|
||||||
i18nKey='editor.help.contacts.meetUsOn'
|
i18nKey='editor.help.contacts.meetUsOn'
|
||||||
i18nOption={{ service: 'Matrix' }}
|
i18nOption={{ service: 'Matrix' }}
|
||||||
href='https://riot.im/app/#/room/#codimd:matrix.org'
|
href='https://riot.im/app/#/room/#hedgedoc:matrix.org'
|
||||||
icon='hashtag'
|
icon='hashtag'
|
||||||
className='text-primary'
|
className='text-primary'
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -9,7 +9,7 @@ export const NavbarBranding: React.FC = () => {
|
||||||
<Navbar.Brand>
|
<Navbar.Brand>
|
||||||
<Link to="/intro" className="text-secondary text-decoration-none d-flex align-items-center">
|
<Link to="/intro" className="text-secondary text-decoration-none d-flex align-items-center">
|
||||||
<ForkAwesomeIcon icon="file-text" className={'mr-2'}/>
|
<ForkAwesomeIcon icon="file-text" className={'mr-2'}/>
|
||||||
<span>CodiMD</span>
|
<span>HedgeDoc</span>
|
||||||
<Branding inline={true}/>
|
<Branding inline={true}/>
|
||||||
</Link>
|
</Link>
|
||||||
</Navbar.Brand>
|
</Navbar.Brand>
|
||||||
|
|
|
@ -2,7 +2,7 @@ export const editorTestContent = `---
|
||||||
title: Features
|
title: Features
|
||||||
description: Many features, such wow!
|
description: Many features, such wow!
|
||||||
robots: noindex
|
robots: noindex
|
||||||
tags: codimd, demo, react
|
tags: hedgedoc, demo, react
|
||||||
opengraph:
|
opengraph:
|
||||||
title: Features
|
title: Features
|
||||||
---
|
---
|
||||||
|
|
|
@ -13,7 +13,7 @@ const IntroPage: React.FC = () => {
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<h1 dir='auto' className={'align-items-center d-flex justify-content-center'}>
|
<h1 dir='auto' className={'align-items-center d-flex justify-content-center'}>
|
||||||
<ForkAwesomeIcon icon="file-text" className={'mr-2'}/>
|
<ForkAwesomeIcon icon="file-text" className={'mr-2'}/>
|
||||||
<span>CodiMD</span>
|
<span>HedgeDoc</span>
|
||||||
<Branding/>
|
<Branding/>
|
||||||
</h1>
|
</h1>
|
||||||
<p className="lead mb-5">
|
<p className="lead mb-5">
|
||||||
|
|
|
@ -15,7 +15,7 @@ export const PoweredByLinks: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<p>
|
<p>
|
||||||
<Trans i18nKey="landing.footer.poweredBy">
|
<Trans i18nKey="landing.footer.poweredBy">
|
||||||
<ExternalLink href="https://codimd.org" text="CodiMD"/>
|
<ExternalLink href="https://codimd.org" text="HedgeDoc"/>
|
||||||
</Trans>
|
</Trans>
|
||||||
|
|
|
|
||||||
<TranslatedInternalLink href='/n/release-notes' i18nKey='landing.footer.releases'/>
|
<TranslatedInternalLink href='/n/release-notes' i18nKey='landing.footer.releases'/>
|
||||||
|
|
|
@ -9,7 +9,7 @@ const SocialLink: React.FC = () => {
|
||||||
<Trans i18nKey="landing.footer.followUs" components={[
|
<Trans i18nKey="landing.footer.followUs" components={[
|
||||||
<ExternalLink href="https://github.com/codimd/server" icon='github' text="GitHub"/>,
|
<ExternalLink href="https://github.com/codimd/server" icon='github' text="GitHub"/>,
|
||||||
<ExternalLink href="https://community.codimd.org" icon='users' text="Discourse"/>,
|
<ExternalLink href="https://community.codimd.org" icon='users' text="Discourse"/>,
|
||||||
<ExternalLink href="https://riot.im/app/#/room/#codimd:matrix.org" icon="comment" text="Riot"/>,
|
<ExternalLink href="https://riot.im/app/#/room/#hedgedoc:matrix.org" icon="comment" text="Riot"/>,
|
||||||
<ExternalLink href="https://social.codimd.org/mastodon" icon='mastodon' text="Mastodon"/>,
|
<ExternalLink href="https://social.codimd.org/mastodon" icon='mastodon' text="Mastodon"/>,
|
||||||
<ExternalLink href="https://translate.codimd.org" icon="globe" text="POEditor"/>
|
<ExternalLink href="https://translate.codimd.org" icon="globe" text="POEditor"/>
|
||||||
]}/>
|
]}/>
|
||||||
|
|
|
@ -16,7 +16,7 @@ export interface LineNumberMarkerOptions {
|
||||||
*/
|
*/
|
||||||
export const lineNumberMarker: () => MarkdownIt.PluginWithOptions<LineNumberMarkerOptions> = () => {
|
export const lineNumberMarker: () => MarkdownIt.PluginWithOptions<LineNumberMarkerOptions> = () => {
|
||||||
return (md: MarkdownIt, options) => {
|
return (md: MarkdownIt, options) => {
|
||||||
// add codimd_linemarker token before each opening or self-closing level-0 tag
|
// add app_linemarker token before each opening or self-closing level-0 tag
|
||||||
md.core.ruler.push('line_number_marker', (state) => {
|
md.core.ruler.push('line_number_marker', (state) => {
|
||||||
const lineMarkers: LineMarkers[] = []
|
const lineMarkers: LineMarkers[] = []
|
||||||
tagTokens(state.tokens, lineMarkers)
|
tagTokens(state.tokens, lineMarkers)
|
||||||
|
@ -26,7 +26,7 @@ export const lineNumberMarker: () => MarkdownIt.PluginWithOptions<LineNumberMark
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
md.renderer.rules.codimd_linemarker = (tokens: Token[], index: number): string => {
|
md.renderer.rules.app_linemarker = (tokens: Token[], index: number): string => {
|
||||||
const startLineNumber = tokens[index].attrGet('data-start-line')
|
const startLineNumber = tokens[index].attrGet('data-start-line')
|
||||||
const endLineNumber = tokens[index].attrGet('data-end-line')
|
const endLineNumber = tokens[index].attrGet('data-end-line')
|
||||||
|
|
||||||
|
@ -35,11 +35,11 @@ export const lineNumberMarker: () => MarkdownIt.PluginWithOptions<LineNumberMark
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
// noinspection CheckTagEmptyBody
|
// noinspection CheckTagEmptyBody
|
||||||
return `<codimd-linemarker data-start-line='${startLineNumber}' data-end-line='${endLineNumber}'></codimd-linemarker>`
|
return `<app-linemarker data-start-line='${startLineNumber}' data-end-line='${endLineNumber}'></app-linemarker>`
|
||||||
}
|
}
|
||||||
|
|
||||||
const insertNewLineMarker = (startLineNumber: number, endLineNumber: number, tokenPosition: number, level: number, tokens: Token[]) => {
|
const insertNewLineMarker = (startLineNumber: number, endLineNumber: number, tokenPosition: number, level: number, tokens: Token[]) => {
|
||||||
const startToken = new Token('codimd_linemarker', 'codimd-linemarker', 0)
|
const startToken = new Token('app_linemarker', 'app-linemarker', 0)
|
||||||
startToken.level = level
|
startToken.level = level
|
||||||
startToken.attrPush(['data-start-line', `${startLineNumber}`])
|
startToken.attrPush(['data-start-line', `${startLineNumber}`])
|
||||||
startToken.attrPush(['data-end-line', `${endLineNumber}`])
|
startToken.attrPush(['data-end-line', `${endLineNumber}`])
|
||||||
|
|
|
@ -54,7 +54,7 @@ import { replaceVimeoLink } from './regex-plugins/replace-vimeo-link'
|
||||||
import { replaceYouTubeLink } from './regex-plugins/replace-youtube-link'
|
import { replaceYouTubeLink } from './regex-plugins/replace-youtube-link'
|
||||||
import { buildTransformer, calculateNewLineNumberMapping, LineKeys } from './renderer-utils'
|
import { buildTransformer, calculateNewLineNumberMapping, LineKeys } from './renderer-utils'
|
||||||
import { AsciinemaReplacer } from './replace-components/asciinema/asciinema-replacer'
|
import { AsciinemaReplacer } from './replace-components/asciinema/asciinema-replacer'
|
||||||
import { CodimdLinemarkerReplacer } from './replace-components/codimd-linemarker/codimd-linemarker-replacer'
|
import { LinemarkerReplacer } from './replace-components/linemarker/linemarker-replacer'
|
||||||
import { ComponentReplacer } from './replace-components/ComponentReplacer'
|
import { ComponentReplacer } from './replace-components/ComponentReplacer'
|
||||||
import { CsvReplacer } from './replace-components/csv/csv-replacer'
|
import { CsvReplacer } from './replace-components/csv/csv-replacer'
|
||||||
import { FlowchartReplacer } from './replace-components/flow/flowchart-replacer'
|
import { FlowchartReplacer } from './replace-components/flow/flowchart-replacer'
|
||||||
|
@ -281,12 +281,12 @@ export const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({
|
||||||
permalinkSymbol: '<i class="fa fa-link"></i>'
|
permalinkSymbol: '<i class="fa fa-link"></i>'
|
||||||
})
|
})
|
||||||
md.use(mathJax({
|
md.use(mathJax({
|
||||||
beforeMath: '<codimd-katex>',
|
beforeMath: '<app-katex>',
|
||||||
afterMath: '</codimd-katex>',
|
afterMath: '</app-katex>',
|
||||||
beforeInlineMath: '<codimd-katex inline>',
|
beforeInlineMath: '<app-katex inline>',
|
||||||
afterInlineMath: '</codimd-katex>',
|
afterInlineMath: '</app-katex>',
|
||||||
beforeDisplayMath: '<codimd-katex>',
|
beforeDisplayMath: '<app-katex>',
|
||||||
afterDisplayMath: '</codimd-katex>'
|
afterDisplayMath: '</app-katex>'
|
||||||
}))
|
}))
|
||||||
md.use(markdownItRegex, replaceLegacyYoutubeShortCode)
|
md.use(markdownItRegex, replaceLegacyYoutubeShortCode)
|
||||||
md.use(markdownItRegex, replaceLegacyVimeoShortCode)
|
md.use(markdownItRegex, replaceLegacyVimeoShortCode)
|
||||||
|
@ -339,7 +339,7 @@ export const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({
|
||||||
|
|
||||||
const markdownReactDom: ReactElement[] = useMemo(() => {
|
const markdownReactDom: ReactElement[] = useMemo(() => {
|
||||||
const allReplacers: ComponentReplacer[] = [
|
const allReplacers: ComponentReplacer[] = [
|
||||||
new CodimdLinemarkerReplacer(),
|
new LinemarkerReplacer(),
|
||||||
new PossibleWiderReplacer(),
|
new PossibleWiderReplacer(),
|
||||||
new GistReplacer(),
|
new GistReplacer(),
|
||||||
new YoutubeReplacer(),
|
new YoutubeReplacer(),
|
||||||
|
|
|
@ -13,6 +13,6 @@ export const replaceAsciinemaLink: RegexOptions = {
|
||||||
replace: (match) => {
|
replace: (match) => {
|
||||||
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
||||||
// noinspection CheckTagEmptyBody
|
// noinspection CheckTagEmptyBody
|
||||||
return `<codimd-asciinema id="${match}"></codimd-asciinema>`
|
return `<app-asciinema id="${match}"></app-asciinema>`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,6 @@ export const replaceGistLink: RegexOptions = {
|
||||||
replace: (match) => {
|
replace: (match) => {
|
||||||
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
||||||
// noinspection CheckTagEmptyBody
|
// noinspection CheckTagEmptyBody
|
||||||
return `<codimd-gist id="${match}"></codimd-gist>`
|
return `<app-gist id="${match}"></app-gist>`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,6 @@ export const replaceLegacyGistShortCode: RegexOptions = {
|
||||||
replace: (match) => {
|
replace: (match) => {
|
||||||
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
||||||
// noinspection CheckTagEmptyBody
|
// noinspection CheckTagEmptyBody
|
||||||
return `<codimd-gist id="${match}"></codimd-gist>`
|
return `<app-gist id="${match}"></app-gist>`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,6 @@ export const replaceLegacyVimeoShortCode: RegexOptions = {
|
||||||
replace: (match) => {
|
replace: (match) => {
|
||||||
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
||||||
// noinspection CheckTagEmptyBody
|
// noinspection CheckTagEmptyBody
|
||||||
return `<codimd-vimeo id="${match}"></codimd-vimeo>`
|
return `<app-vimeo id="${match}"></app-vimeo>`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,6 @@ export const replaceLegacyYoutubeShortCode: RegexOptions = {
|
||||||
replace: (match) => {
|
replace: (match) => {
|
||||||
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
||||||
// noinspection CheckTagEmptyBody
|
// noinspection CheckTagEmptyBody
|
||||||
return `<codimd-youtube id="${match}"></codimd-youtube>`
|
return `<app-youtube id="${match}"></app-youtube>`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,6 @@ export const replacePdfShortCode: RegexOptions = {
|
||||||
replace: (match) => {
|
replace: (match) => {
|
||||||
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
||||||
// noinspection CheckTagEmptyBody
|
// noinspection CheckTagEmptyBody
|
||||||
return `<codimd-pdf url="${match}"></codimd-pdf>`
|
return `<app-pdf url="${match}"></app-pdf>`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,6 @@ export const replaceVimeoLink: RegexOptions = {
|
||||||
replace: (match) => {
|
replace: (match) => {
|
||||||
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
||||||
// noinspection CheckTagEmptyBody
|
// noinspection CheckTagEmptyBody
|
||||||
return `<codimd-vimeo id="${match}"></codimd-vimeo>`
|
return `<app-vimeo id="${match}"></app-vimeo>`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,6 @@ export const replaceYouTubeLink: RegexOptions = {
|
||||||
replace: (match) => {
|
replace: (match) => {
|
||||||
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
||||||
// noinspection CheckTagEmptyBody
|
// noinspection CheckTagEmptyBody
|
||||||
return `<codimd-youtube id="${match}"></codimd-youtube>`
|
return `<app-youtube id="${match}"></app-youtube>`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { DomElement } from 'domhandler'
|
import { DomElement } from 'domhandler'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { getAttributesFromCodiMdTag } from '../codi-md-tag-utils'
|
import { getAttributesFromHedgeDocTag } from '../utils'
|
||||||
import { ComponentReplacer } from '../ComponentReplacer'
|
import { ComponentReplacer } from '../ComponentReplacer'
|
||||||
import { AsciinemaFrame } from './asciinema-frame'
|
import { AsciinemaFrame } from './asciinema-frame'
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ export class AsciinemaReplacer extends ComponentReplacer {
|
||||||
private counterMap: Map<string, number> = new Map<string, number>()
|
private counterMap: Map<string, number> = new Map<string, number>()
|
||||||
|
|
||||||
public getReplacement (node: DomElement, index: number): React.ReactElement | undefined {
|
public getReplacement (node: DomElement, index: number): React.ReactElement | undefined {
|
||||||
const attributes = getAttributesFromCodiMdTag(node, 'asciinema')
|
const attributes = getAttributesFromHedgeDocTag(node, 'asciinema')
|
||||||
if (attributes && attributes.id) {
|
if (attributes && attributes.id) {
|
||||||
const asciinemaId = attributes.id
|
const asciinemaId = attributes.id
|
||||||
const count = (this.counterMap.get(asciinemaId) || 0) + 1
|
const count = (this.counterMap.get(asciinemaId) || 0) + 1
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
import { DomElement } from 'domhandler'
|
|
||||||
|
|
||||||
export const getAttributesFromCodiMdTag = (node: DomElement, tagName: string): ({ [s: string]: string; }|undefined) => {
|
|
||||||
if (node.name !== `codimd-${tagName}` || !node.attribs) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return node.attribs
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { DomElement } from 'domhandler'
|
import { DomElement } from 'domhandler'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { getAttributesFromCodiMdTag } from '../codi-md-tag-utils'
|
import { getAttributesFromHedgeDocTag } from '../utils'
|
||||||
import { ComponentReplacer } from '../ComponentReplacer'
|
import { ComponentReplacer } from '../ComponentReplacer'
|
||||||
import { OneClickEmbedding } from '../one-click-frame/one-click-embedding'
|
import { OneClickEmbedding } from '../one-click-frame/one-click-embedding'
|
||||||
import { GistFrame } from './gist-frame'
|
import { GistFrame } from './gist-frame'
|
||||||
|
@ -10,7 +10,7 @@ export class GistReplacer extends ComponentReplacer {
|
||||||
private counterMap: Map<string, number> = new Map<string, number>()
|
private counterMap: Map<string, number> = new Map<string, number>()
|
||||||
|
|
||||||
public getReplacement (node: DomElement, index: number): React.ReactElement | undefined {
|
public getReplacement (node: DomElement, index: number): React.ReactElement | undefined {
|
||||||
const attributes = getAttributesFromCodiMdTag(node, 'gist')
|
const attributes = getAttributesFromHedgeDocTag(node, 'gist')
|
||||||
if (attributes && attributes.id) {
|
if (attributes && attributes.id) {
|
||||||
const gistId = attributes.id
|
const gistId = attributes.id
|
||||||
const count = (this.counterMap.get(gistId) || 0) + 1
|
const count = (this.counterMap.get(gistId) || 0) + 1
|
||||||
|
|
|
@ -9,12 +9,12 @@ const getNodeIfKatexBlock = (node: DomElement): (DomElement|undefined) => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return node.children.find((subnode) => {
|
return node.children.find((subnode) => {
|
||||||
return (subnode.name === 'codimd-katex' && subnode.attribs?.inline === undefined)
|
return (subnode.name === 'app-katex' && subnode.attribs?.inline === undefined)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const getNodeIfInlineKatex = (node: DomElement): (DomElement|undefined) => {
|
const getNodeIfInlineKatex = (node: DomElement): (DomElement|undefined) => {
|
||||||
return (node.name === 'codimd-katex' && node.attribs?.inline !== undefined) ? node : undefined
|
return (node.name === 'app-katex' && node.attribs?.inline !== undefined) ? node : undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
export class KatexReplacer extends ComponentReplacer {
|
export class KatexReplacer extends ComponentReplacer {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { DomElement } from 'domhandler'
|
import { DomElement } from 'domhandler'
|
||||||
import { ComponentReplacer } from '../ComponentReplacer'
|
import { ComponentReplacer } from '../ComponentReplacer'
|
||||||
|
|
||||||
export class CodimdLinemarkerReplacer extends ComponentReplacer {
|
export class LinemarkerReplacer extends ComponentReplacer {
|
||||||
public getReplacement (codeNode: DomElement, index: number): null | undefined {
|
public getReplacement (codeNode: DomElement, index: number): null | undefined {
|
||||||
return codeNode.name === 'codimd-linemarker' ? null : undefined
|
return codeNode.name === 'codimd-linemarker' ? null : undefined
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { DomElement } from 'domhandler'
|
import { DomElement } from 'domhandler'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { getAttributesFromCodiMdTag } from '../codi-md-tag-utils'
|
import { getAttributesFromHedgeDocTag } from '../utils'
|
||||||
import { ComponentReplacer } from '../ComponentReplacer'
|
import { ComponentReplacer } from '../ComponentReplacer'
|
||||||
import { PdfFrame } from './pdf-frame'
|
import { PdfFrame } from './pdf-frame'
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ export class PdfReplacer extends ComponentReplacer {
|
||||||
private counterMap: Map<string, number> = new Map<string, number>()
|
private counterMap: Map<string, number> = new Map<string, number>()
|
||||||
|
|
||||||
public getReplacement (node: DomElement, index: number): React.ReactElement | undefined {
|
public getReplacement (node: DomElement, index: number): React.ReactElement | undefined {
|
||||||
const attributes = getAttributesFromCodiMdTag(node, 'pdf')
|
const attributes = getAttributesFromHedgeDocTag(node, 'pdf')
|
||||||
if (attributes && attributes.url) {
|
if (attributes && attributes.url) {
|
||||||
const pdfUrl = attributes.url
|
const pdfUrl = attributes.url
|
||||||
const count = (this.counterMap.get(pdfUrl) || 0) + 1
|
const count = (this.counterMap.get(pdfUrl) || 0) + 1
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { DomElement } from 'domhandler'
|
||||||
import { ComponentReplacer, NativeRenderer, SubNodeTransform } from '../ComponentReplacer'
|
import { ComponentReplacer, NativeRenderer, SubNodeTransform } from '../ComponentReplacer'
|
||||||
import './possible-wider-replacer.scss'
|
import './possible-wider-replacer.scss'
|
||||||
|
|
||||||
const enabledTags = ['img', 'codimd-youtube', 'codimd-vimeo', 'codimd-asciinema', 'codimd-pdf']
|
const enabledTags = ['img', 'app-youtube', 'app-vimeo', 'app-asciinema', 'app-pdf']
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This replacer doesn't actually replace something.
|
* This replacer doesn't actually replace something.
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { DomElement } from 'domhandler'
|
||||||
|
|
||||||
|
export const getAttributesFromHedgeDocTag = (node: DomElement, tagName: string): ({ [s: string]: string; }|undefined) => {
|
||||||
|
if (node.name !== `app-${tagName}` || !node.attribs) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return node.attribs
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { DomElement } from 'domhandler'
|
import { DomElement } from 'domhandler'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { getAttributesFromCodiMdTag } from '../codi-md-tag-utils'
|
import { getAttributesFromHedgeDocTag } from '../utils'
|
||||||
import { ComponentReplacer } from '../ComponentReplacer'
|
import { ComponentReplacer } from '../ComponentReplacer'
|
||||||
import { VimeoFrame } from './vimeo-frame'
|
import { VimeoFrame } from './vimeo-frame'
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ export class VimeoReplacer extends ComponentReplacer {
|
||||||
private counterMap: Map<string, number> = new Map<string, number>()
|
private counterMap: Map<string, number> = new Map<string, number>()
|
||||||
|
|
||||||
public getReplacement (node: DomElement, index: number): React.ReactElement | undefined {
|
public getReplacement (node: DomElement, index: number): React.ReactElement | undefined {
|
||||||
const attributes = getAttributesFromCodiMdTag(node, 'vimeo')
|
const attributes = getAttributesFromHedgeDocTag(node, 'vimeo')
|
||||||
if (attributes && attributes.id) {
|
if (attributes && attributes.id) {
|
||||||
const videoId = attributes.id
|
const videoId = attributes.id
|
||||||
const count = (this.counterMap.get(videoId) || 0) + 1
|
const count = (this.counterMap.get(videoId) || 0) + 1
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { DomElement } from 'domhandler'
|
import { DomElement } from 'domhandler'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { getAttributesFromCodiMdTag } from '../codi-md-tag-utils'
|
import { getAttributesFromHedgeDocTag } from '../utils'
|
||||||
import { ComponentReplacer } from '../ComponentReplacer'
|
import { ComponentReplacer } from '../ComponentReplacer'
|
||||||
import { YouTubeFrame } from './youtube-frame'
|
import { YouTubeFrame } from './youtube-frame'
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ export class YoutubeReplacer extends ComponentReplacer {
|
||||||
private counterMap: Map<string, number> = new Map<string, number>()
|
private counterMap: Map<string, number> = new Map<string, number>()
|
||||||
|
|
||||||
public getReplacement (node: DomElement, index: number): React.ReactElement | undefined {
|
public getReplacement (node: DomElement, index: number): React.ReactElement | undefined {
|
||||||
const attributes = getAttributesFromCodiMdTag(node, 'youtube')
|
const attributes = getAttributesFromHedgeDocTag(node, 'youtube')
|
||||||
if (attributes && attributes.id) {
|
if (attributes && attributes.id) {
|
||||||
const videoId = attributes.id
|
const videoId = attributes.id
|
||||||
const count = (this.counterMap.get(videoId) || 0) + 1
|
const count = (this.counterMap.get(videoId) || 0) + 1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue