-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat: New song format, update grouping, change from heading to index,…
… textarea highlight, etc
- Loading branch information
Showing
17 changed files
with
3,249 additions
and
2,818 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
export const convertMWLData = (content: string) => { | ||
return convertHeading( | ||
removeAuxiliaryText( | ||
cleanWhiteSpace(convertChords(content.split(/<br>|\n/gm) ?? [])), | ||
), | ||
).join("\n"); | ||
}; | ||
|
||
const convertChords = (content: string[]) => { | ||
return content.map((val) => { | ||
return val.match(/x[01]/) ? "." + val : val; | ||
}); | ||
}; | ||
const cleanWhiteSpace = (content: string[]) => { | ||
return content.map((x) => x.replace(/\s+/g, " ").trim()); | ||
}; | ||
const removeAuxiliaryText = (content: string[]) => { | ||
return content.filter((songLine) => { | ||
const match1 = songLine.match( | ||
/^(\s*)repeat(\s*)(verse|bridge|pre-? ?chorus|chorus|end|tag|intro)? ?(\d+)?(.*)$/i, | ||
); | ||
|
||
if (match1 && match1?.length > 0) { | ||
return false; | ||
} | ||
|
||
const match2 = songLine.match(/^(\s*)solo(\s*)$/i); | ||
|
||
if (match2 && match2?.length > 0) { | ||
return false; | ||
} | ||
|
||
return true; | ||
}); | ||
}; | ||
const convertHeading = (content: string[]) => { | ||
return content.map((val) => { | ||
const matches = val.match( | ||
/^(\s*)\[?(verse|bridge|pre-? ?chorus|chorus|end|ending|outro|tag|instrumental|interlude) ?(\d+)?\]?(\s*)$/i, | ||
); | ||
return matches ? "[" + val.replace(/[\[\]]/g, "") + "]" : val; | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
plugins/myworshiplist/view/MWLRemote/MWLRemoteEditSongModal/SongEditEditor.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { Box } from "@chakra-ui/react"; | ||
import Document from "@tiptap/extension-document"; | ||
import History from "@tiptap/extension-history"; | ||
import Paragraph from "@tiptap/extension-paragraph"; | ||
import TextExtension from "@tiptap/extension-text"; | ||
import { EditorContent, useEditor } from "@tiptap/react"; | ||
import { useEffect } from "react"; | ||
|
||
import { CustomDecorationPlugin } from "./customDecorationPlugin"; | ||
|
||
const SongEditEditor = ({ | ||
initialContent, | ||
onChange, | ||
}: { | ||
initialContent: string; | ||
onChange: (text: string) => void; | ||
}) => { | ||
const editor = useEditor({ | ||
onUpdate: (e) => { | ||
onChange(e.editor.getText({ blockSeparator: "\n" })); | ||
}, | ||
extensions: [ | ||
Document, | ||
Paragraph.extend({ | ||
priority: 8000, | ||
group: "block", | ||
inline: false, | ||
addProseMirrorPlugins() { | ||
return [ | ||
...(this.parent?.() || []), | ||
CustomDecorationPlugin({ | ||
name: this.name, | ||
}), | ||
]; | ||
}, | ||
}), | ||
TextExtension, | ||
History, | ||
], | ||
}); | ||
|
||
useEffect(() => { | ||
if (editor && initialContent !== editor.getHTML()) { | ||
editor?.commands.setContent(initialContent); | ||
} | ||
}, [editor, initialContent]); | ||
|
||
return ( | ||
<Box | ||
rounded="md" | ||
border="1px solid" | ||
borderColor="gray.200" | ||
px={3} | ||
py={2} | ||
w="100%" | ||
> | ||
<EditorContent editor={editor} /> | ||
</Box> | ||
); | ||
}; | ||
|
||
export default SongEditEditor; |
52 changes: 52 additions & 0 deletions
52
plugins/myworshiplist/view/MWLRemote/MWLRemoteEditSongModal/SongEditInfo.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { | ||
ListItem, | ||
OrderedList, | ||
PopoverArrow, | ||
PopoverBody, | ||
PopoverCloseButton, | ||
PopoverContent, | ||
PopoverHeader, | ||
Text, | ||
} from "@chakra-ui/react"; | ||
|
||
export const SongEditInfo = () => { | ||
return ( | ||
<PopoverContent | ||
width="100%" | ||
maxW="lg" | ||
color="white" | ||
bg="blue.800" | ||
borderColor="blue.800" | ||
> | ||
<PopoverHeader pt={4} fontWeight="bold" border="0"> | ||
Formatting songs | ||
</PopoverHeader> | ||
<PopoverArrow bg="blue.800" /> | ||
<PopoverCloseButton /> | ||
<PopoverBody mb={3}> | ||
We use quite a simple format to show songs inspired by OpenSong. <br /> | ||
<br /> | ||
Here are some of the basic rules: <br /> | ||
<OrderedList> | ||
<ListItem> | ||
Separate sections with square brackets(<Text as="b">[ ]</Text>) like{" "} | ||
<Text as="b">[Verse 1]</Text>. | ||
<br /> | ||
This can be anything from Verse, Chorus, Bridge, and any text you | ||
like. | ||
</ListItem> | ||
<ListItem> | ||
Use a single dash(<Text as="b">-</Text>) to split your section into | ||
multiple slides. | ||
</ListItem> | ||
<ListItem> | ||
Add a dot(<Text as="b">.</Text>) in front of a line to indicate that | ||
it is a chord line. | ||
<br /> | ||
Note: At this time, we do not support showing chords yet. | ||
</ListItem> | ||
</OrderedList> | ||
</PopoverBody> | ||
</PopoverContent> | ||
); | ||
}; |
38 changes: 0 additions & 38 deletions
38
plugins/myworshiplist/view/MWLRemote/MWLRemoteEditSongModal/TextareaControl.tsx
This file was deleted.
Oops, something went wrong.
115 changes: 115 additions & 0 deletions
115
plugins/myworshiplist/view/MWLRemote/MWLRemoteEditSongModal/customDecorationPlugin.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import { findChildren } from "@tiptap/core"; | ||
import { Node as ProsemirrorNode } from "@tiptap/pm/model"; | ||
import { Plugin, PluginKey } from "@tiptap/pm/state"; | ||
import { Decoration, DecorationSet } from "@tiptap/pm/view"; | ||
|
||
function getDecorations({ doc, name }: { doc: ProsemirrorNode; name: string }) { | ||
const decorations: Decoration[] = []; | ||
|
||
findChildren(doc, (node) => node.type.name === name).forEach((block) => { | ||
if (block.node.textContent.startsWith(".")) { | ||
const decoration = Decoration.inline( | ||
block.pos, | ||
block.pos + block.node.textContent.length + 1, | ||
{ | ||
class: "chord", | ||
}, | ||
); | ||
decorations.push(decoration); | ||
} else if (block.node.textContent === "-") { | ||
const decoration = Decoration.inline( | ||
block.pos, | ||
block.pos + block.node.textContent.length + 1, | ||
{ | ||
class: "lineBreak", | ||
}, | ||
); | ||
decorations.push(decoration); | ||
} else if ( | ||
block.node.textContent.startsWith("[") && | ||
block.node.textContent.endsWith("]") | ||
) { | ||
const decoration = Decoration.inline( | ||
block.pos, | ||
block.pos + block.node.textContent.length + 1, | ||
{ | ||
class: "heading", | ||
}, | ||
); | ||
decorations.push(decoration); | ||
} | ||
}); | ||
|
||
return DecorationSet.create(doc, decorations); | ||
} | ||
|
||
export function CustomDecorationPlugin({ name }: { name: string }) { | ||
const customDecorationPlugin: Plugin<any> = new Plugin({ | ||
key: new PluginKey("customDecoration"), | ||
|
||
state: { | ||
init: (_, { doc }) => | ||
getDecorations({ | ||
doc, | ||
name, | ||
}), | ||
apply: (transaction, decorationSet, oldState, newState) => { | ||
const oldNodeName = oldState.selection.$head.parent.type.name; | ||
const newNodeName = newState.selection.$head.parent.type.name; | ||
const oldNodes = findChildren( | ||
oldState.doc, | ||
(node) => node.type.name === name, | ||
); | ||
const newNodes = findChildren( | ||
newState.doc, | ||
(node) => node.type.name === name, | ||
); | ||
|
||
if ( | ||
transaction.docChanged && | ||
// Apply decorations if: | ||
// selection includes named node, | ||
([oldNodeName, newNodeName].includes(name) || | ||
// OR transaction adds/removes named node, | ||
newNodes.length !== oldNodes.length || | ||
// OR transaction has changes that completely encapsulte a node | ||
// (for example, a transaction that affects the entire document). | ||
// Such transactions can happen during collab syncing via y-prosemirror, for example. | ||
transaction.steps.some((step) => { | ||
// @ts-ignore | ||
return ( | ||
// @ts-ignore | ||
step.from !== undefined && | ||
// @ts-ignore | ||
step.to !== undefined && | ||
oldNodes.some((node) => { | ||
// @ts-ignore | ||
return ( | ||
// @ts-ignore | ||
node.pos >= step.from && | ||
// @ts-ignore | ||
node.pos + node.node.nodeSize <= step.to | ||
); | ||
}) | ||
); | ||
})) | ||
) { | ||
return getDecorations({ | ||
doc: transaction.doc, | ||
name, | ||
}); | ||
} | ||
|
||
return decorationSet.map(transaction.mapping, transaction.doc); | ||
}, | ||
}, | ||
|
||
props: { | ||
decorations(state) { | ||
return customDecorationPlugin.getState(state); | ||
}, | ||
}, | ||
}); | ||
|
||
return customDecorationPlugin; | ||
} |
Oops, something went wrong.