diff --git a/package.json b/package.json index 720981e90..acd4148d7 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@types/uuid": "8.3.0", "@typescript-eslint/eslint-plugin": "3.10.1", "@typescript-eslint/parser": "3.10.1", + "abcjs": "5.12.0", "bootstrap": "4.5.2", "codemirror": "5.57.0", "diff": "4.0.2", diff --git a/src/components/editor/editorTestContent.ts b/src/components/editor/editorTestContent.ts index faa8cf81d..f3af38815 100644 --- a/src/components/editor/editorTestContent.ts +++ b/src/components/editor/editorTestContent.ts @@ -38,6 +38,20 @@ cond(yes)->e cond(no)->op2 \`\`\` +## ABC + +\`\`\`abc +X:1 +T:Speed the Plough +M:4/4 +C:Trad. +K:G +|:GABc dedB|dedB dedB|c2ec B2dB|c2A2 A2BA| +GABc dedB|dedB dedB|c2ec B2dB|A2F2 G4:| +|:g2gf gdBd|g2f2 e2d2|c2ec B2dB|c2A2 A2df| +g2gf g2Bd|g2f2 e2d2|c2ec B2dB|A2F2 G4:| +\`\`\` + ## CSV \`\`\`csv delimiter=; header diff --git a/src/components/markdown-renderer/markdown-renderer.tsx b/src/components/markdown-renderer/markdown-renderer.tsx index 283b001f7..8755c73c4 100644 --- a/src/components/markdown-renderer/markdown-renderer.tsx +++ b/src/components/markdown-renderer/markdown-renderer.tsx @@ -53,6 +53,7 @@ import { replaceQuoteExtraTime } from './regex-plugins/replace-quote-extra-time' import { replaceVimeoLink } from './regex-plugins/replace-vimeo-link' import { replaceYouTubeLink } from './regex-plugins/replace-youtube-link' import { buildTransformer, calculateNewLineNumberMapping, LineKeys } from './renderer-utils' +import { AbcReplacer } from './replace-components/abc/abc-replacer' import { AsciinemaReplacer } from './replace-components/asciinema/asciinema-replacer' import { LinemarkerReplacer } from './replace-components/linemarker/linemarker-replacer' import { ComponentReplacer } from './replace-components/ComponentReplacer' @@ -346,6 +347,7 @@ export const MarkdownRenderer: React.FC = ({ new YoutubeReplacer(), new VimeoReplacer(), new AsciinemaReplacer(), + new AbcReplacer(), new PdfReplacer(), new ImageReplacer(), new CsvReplacer(), diff --git a/src/components/markdown-renderer/replace-components/abc/abc-frame.tsx b/src/components/markdown-renderer/replace-components/abc/abc-frame.tsx new file mode 100644 index 000000000..1b61c864f --- /dev/null +++ b/src/components/markdown-renderer/replace-components/abc/abc-frame.tsx @@ -0,0 +1,19 @@ +import React, { useEffect, useRef } from 'react' +import { renderAbc } from 'abcjs' + +export interface AbcFrameProps { + code: string +} +export const AbcFrame: React.FC = ({ code }) => { + const container = useRef(null) + + useEffect(() => { + if (container.current) { + renderAbc(container.current, code) + } + }, [code]) + + return ( +
+ ) +} diff --git a/src/components/markdown-renderer/replace-components/abc/abc-replacer.tsx b/src/components/markdown-renderer/replace-components/abc/abc-replacer.tsx new file mode 100644 index 000000000..ab9e82ed0 --- /dev/null +++ b/src/components/markdown-renderer/replace-components/abc/abc-replacer.tsx @@ -0,0 +1,16 @@ +import { DomElement } from 'domhandler' +import React from 'react' +import { ComponentReplacer } from '../ComponentReplacer' +import { AbcFrame } from './abc-frame' + +export class AbcReplacer implements ComponentReplacer { + getReplacement (codeNode: DomElement, index: number): React.ReactElement | undefined { + if (codeNode.name !== 'code' || !codeNode.attribs || !codeNode.attribs['data-highlight-language'] || codeNode.attribs['data-highlight-language'] !== 'abc' || !codeNode.children || !codeNode.children[0]) { + return + } + + const code = codeNode.children[0].data as string + + return + } +} diff --git a/src/external-types/abcjs/abcjs.d.ts b/src/external-types/abcjs/abcjs.d.ts new file mode 100644 index 000000000..678f5d8fe --- /dev/null +++ b/src/external-types/abcjs/abcjs.d.ts @@ -0,0 +1,3 @@ +declare module 'abcjs' { + export function renderAbc(target: string|HTMLElement, code: string) +} diff --git a/yarn.lock b/yarn.lock index 1c8491fc1..7f2f79935 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2385,6 +2385,29 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abcjs@5.10.3: + version "5.10.3" + resolved "https://registry.yarnpkg.com/abcjs/-/abcjs-5.10.3.tgz#294702140ec1caa292859ba9d2af0452f7e9e046" + integrity sha512-YGmW4CUWd7T2/HqZa/SQOTE+lXg7Z68HwwpJhHJBvdHqLi1uLCiYva1ZRGhB/MPyl1QKqJMfF+LQ1jGAEK69XQ== + dependencies: + midi "https://github.com/paulrosen/MIDI.js.git#abcjs" + +abcjs@5.11.0: + version "5.11.0" + resolved "https://registry.yarnpkg.com/abcjs/-/abcjs-5.11.0.tgz#397592ea6a56948aee64a8364f9a7a589e254300" + integrity sha512-kLehHwwttcTCVhKQaDkmqYbWBLAWmfyzYSbUQoEDAOTOX5RzDGakX8tXpzlsNHw6Lh8W8odZw44e0siwbG4TKA== + dependencies: + abcjs "5.10.3" + midi "https://github.com/paulrosen/MIDI.js.git#abcjs" + +abcjs@^5.12.0: + version "5.12.0" + resolved "https://registry.yarnpkg.com/abcjs/-/abcjs-5.12.0.tgz#06fec076d570821309b0a12598cd356cd589eb08" + integrity sha512-pvi7SjOAKT7cRyRtywUSwYB0SNtRHKLxZUZ9Oc4E+nvpBHr8Z2/M9Pfyv3oIaiEpxlWTFK+B/H5t/DckiNFgpg== + dependencies: + abcjs "5.11.0" + midi "https://github.com/paulrosen/MIDI.js.git#abcjs" + accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: version "1.3.7" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" @@ -8732,6 +8755,10 @@ micromatch@^4.0.0: braces "^3.0.1" picomatch "^2.0.5" +"midi@git+https://github.com/paulrosen/MIDI.js.git#abcjs": + version "0.4.2" + resolved "git+https://github.com/paulrosen/MIDI.js.git#e593ffef81a0350f99448e3ab8111957145ff6b2" + miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"