Skip to content

Commit

Permalink
Update from bettermusic fork (#1559)
Browse files Browse the repository at this point in the history
Co-authored-by: isaiahdahl <isaiahdahl@me.com>
  • Loading branch information
martijnversluis and isaiahdahl authored Jan 28, 2025
1 parent 52eecb1 commit 14d2055
Show file tree
Hide file tree
Showing 22 changed files with 1,439 additions and 72 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Fret } from '../../constants';
import { parse } from '../../parser/chord_definition/peg_parser';
import { Fret } from '../constants';
import { parse } from '../parser/chord_definition/peg_parser';

/**
* Represents a chord definition.
Expand Down
51 changes: 51 additions & 0 deletions src/chord_definition/chord_definition_set.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import ChordDefinition from './chord_definition';
import chordDefinitions from './defaults.json';

export type DefinitionSet = Record<string, ChordDefinition>;

class ChordDefinitionSet {
definitions: DefinitionSet;

constructor(definitions?: DefinitionSet) {
this.definitions = definitions || {};
}

get(chord: string): ChordDefinition | null {
return this.definitions[chord] || null;
}

withDefaults() {
const defaultDefinitions: Record<string, string> = chordDefinitions;
const clone = this.clone();

Object.keys(defaultDefinitions).forEach((chord: string) => {
const definition = ChordDefinition.parse(defaultDefinitions[chord]);

if (!clone.has(chord)) {
clone.add(chord, definition);
}
});

return clone;
}

add(chord: string, definition: ChordDefinition) {
this.definitions[chord] = definition;
}

has(chord: string): boolean {
return chord in this.definitions;
}

clone(): ChordDefinitionSet {
const clone = new ChordDefinitionSet();

Object.keys(this.definitions).forEach((chord: string) => {
clone.add(chord, this.definitions[chord].clone());
});

return clone;
}
}

export default ChordDefinitionSet;
904 changes: 904 additions & 0 deletions src/chord_definition/defaults.json

Large diffs are not rendered by default.

13 changes: 11 additions & 2 deletions src/chord_sheet/line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@ import Tag from './tag';
import Comment from './comment';
import Item from './item';
import Font from './font';
import { ContentType } from '../serialized_types';
import { ContentType, PartTypes } from '../serialized_types';

import {
BRIDGE,
CHORUS,
GRID,
NONE,
PART,
TAB,
VERSE,
} from '../constants';

type MapItemFunc = (_item: Item) => Item | null;

export type LineType = 'bridge' | 'chorus' | 'none' | 'tab' | 'verse' | ContentType | 'indeterminate';
export type LineType = 'bridge' | 'chorus' | 'none' | 'tab' | 'verse' | ContentType | 'indeterminate' | PartTypes;

/**
* Represents a line in a chord sheet, consisting of items of type ChordLyricsPair or Tag
Expand Down Expand Up @@ -175,6 +176,14 @@ class Line {
return this.type === VERSE;
}

/**
* Indicates whether the line type is {@link PART}
* @returns {boolean}
*/
isPart(): boolean {
return this.type === PART;
}

/**
* Indicates whether the line contains items that are renderable. Please use {@link hasRenderableItems}
* @deprecated
Expand Down
7 changes: 6 additions & 1 deletion src/chord_sheet/song.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ import Tag, {
START_OF_CHORUS,
} from './tag';
import SongBuilder from '../song_builder';
import ChordDefinition from './chord_pro/chord_definition';
import ChordDefinition from '../chord_definition/chord_definition';
import Chord from '../chord';
import FormattingContext from '../formatter/formatting_context';
import { testSelector } from '../helpers';
import ChordDefinitionSet from '../chord_definition/chord_definition_set';

type EachItemCallback = (_item: Item) => void;

Expand Down Expand Up @@ -502,6 +503,10 @@ Or set the song key before changing key:
return chordDefinitions;
}

get chordDefinitions(): ChordDefinitionSet {
return new ChordDefinitionSet(this.getChordDefinitions());
}

/**
* Change the song contents inline. Return a new {@link Line} to replace it. Return `null` to remove it.
* @example
Expand Down
86 changes: 35 additions & 51 deletions src/chord_sheet/tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@
*/
import AstComponent from './ast_component';
import TraceInfo from './trace_info';
import ChordDefinition from './chord_pro/chord_definition';

import {
ABC, BRIDGE, GRID, LILYPOND, TAB, VERSE,
} from '../constants';
import ChordDefinition from '../chord_definition/chord_definition';
import TagInterpreter from './tag_interpreter';

export const ALBUM = 'album';

Expand Down Expand Up @@ -96,6 +93,12 @@ export const END_OF_TAB = 'end_of_tab';
*/
export const END_OF_VERSE = 'end_of_verse';

/**
* End of part directive.
* @type {string}
*/
export const END_OF_PART = 'end_of_part';

/**
* Key meta directive. See https://www.chordpro.org/chordpro/directives-key/
* @type {string}
Expand Down Expand Up @@ -163,6 +166,12 @@ export const START_OF_TAB = 'start_of_tab';
*/
export const START_OF_VERSE = 'start_of_verse';

/**
* Start of part
* @type {string}
*/
export const START_OF_PART = 'start_of_part';

/**
* Subtitle meta directive. See https://www.chordpro.org/chordpro/directives-subtitle/
* @type {string}
Expand Down Expand Up @@ -283,16 +292,20 @@ const END_OF_CHORUS_SHORT = 'eoc';
const END_OF_GRID_SHORT = 'eog';
const END_OF_TAB_SHORT = 'eot';
const END_OF_VERSE_SHORT = 'eov';
const END_OF_PART_SHORT = 'eop';
const NEW_KEY_SHORT = 'nk';
const START_OF_BRIDGE_SHORT = 'sob';
const START_OF_CHORUS_SHORT = 'soc';
const START_OF_GRID_SHORT = 'sog';
const START_OF_TAB_SHORT = 'sot';
const START_OF_VERSE_SHORT = 'sov';
const START_OF_PART_SHORT = 'sop';
const SUBTITLE_SHORT = 'st';
const TEXTFONT_SHORT = 'tf';
const TEXTSIZE_SHORT = 'ts';
const TITLE_SHORT = 't';
const START_OF_PART_SHORTER = 'p';
const END_OF_PART_SHORTER = 'ep';

const RENDERABLE_TAGS = [COMMENT];

Expand Down Expand Up @@ -328,6 +341,14 @@ const INLINE_FONT_TAGS = [

const DIRECTIVES_WITH_RENDERABLE_LABEL = [
CHORUS,
START_OF_ABC,
START_OF_BRIDGE,
START_OF_CHORUS,
START_OF_GRID,
START_OF_LY,
START_OF_TAB,
START_OF_VERSE,
START_OF_PART,
];

const ALIASES: Record<string, string> = {
Expand All @@ -339,12 +360,16 @@ const ALIASES: Record<string, string> = {
[END_OF_GRID_SHORT]: END_OF_GRID,
[END_OF_TAB_SHORT]: END_OF_TAB,
[END_OF_VERSE_SHORT]: END_OF_VERSE,
[END_OF_PART_SHORT]: END_OF_PART,
[END_OF_PART_SHORTER]: END_OF_PART,
[NEW_KEY_SHORT]: NEW_KEY,
[START_OF_BRIDGE_SHORT]: START_OF_BRIDGE,
[START_OF_CHORUS_SHORT]: START_OF_CHORUS,
[START_OF_GRID_SHORT]: START_OF_GRID,
[START_OF_TAB_SHORT]: START_OF_TAB,
[START_OF_VERSE_SHORT]: START_OF_VERSE,
[START_OF_PART_SHORT]: START_OF_PART,
[START_OF_PART_SHORTER]: START_OF_PART,
[SUBTITLE_SHORT]: SUBTITLE,
[TEXTFONT_SHORT]: TEXTFONT,
[TEXTSIZE_SHORT]: TEXTSIZE,
Expand All @@ -354,30 +379,9 @@ const ALIASES: Record<string, string> = {
const TAG_REGEX = /^([^:\s]+)(:?\s*(.+))?$/;
const CUSTOM_META_TAG_NAME_REGEX = /^x_(.+)$/;

const START_TAG_TO_SECTION_TYPE = {
[START_OF_ABC]: ABC,
[START_OF_BRIDGE]: BRIDGE,
[START_OF_CHORUS]: CHORUS,
[START_OF_GRID]: GRID,
[START_OF_LY]: LILYPOND,
[START_OF_TAB]: TAB,
[START_OF_VERSE]: VERSE,
};

const END_TAG_TO_SECTION_TYPE = {
[END_OF_ABC]: ABC,
[END_OF_BRIDGE]: BRIDGE,
[END_OF_CHORUS]: CHORUS,
[END_OF_GRID]: GRID,
[END_OF_LY]: LILYPOND,
[END_OF_TAB]: TAB,
[END_OF_VERSE]: VERSE,
};

export const START_TAG = 'start_tag';
export const END_TAG = 'end_tag';
const SECTION_START_REGEX = /^start_of_(.+)$/;
const SECTION_END_REGEX = /^end_of_(.+)$/;
export const AUTO = 'auto';

export function isReadonlyTag(tagName: string) {
return READ_ONLY_TAGS.includes(tagName);
Expand Down Expand Up @@ -485,28 +489,8 @@ class Tag extends AstComponent {
return parsed;
}

static recognizeSectionTag(tagName: string): [string | null, string | null] {
if (tagName in START_TAG_TO_SECTION_TYPE) {
return [START_TAG, START_TAG_TO_SECTION_TYPE[tagName]];
}

if (tagName in END_TAG_TO_SECTION_TYPE) {
return [END_TAG, END_TAG_TO_SECTION_TYPE[tagName]];
}

const parseStartResult = SECTION_START_REGEX.exec(tagName);

if (parseStartResult) {
return [START_TAG, parseStartResult[1]];
}

const parseEndResult = SECTION_END_REGEX.exec(tagName);

if (parseEndResult) {
return [END_TAG, parseEndResult[1]];
}

return [null, null];
static recognizeSectionTag(tag: Tag): [string | null, string | null] {
return TagInterpreter.interpret(tag.name, tag.value);
}

get label() {
Expand All @@ -524,12 +508,12 @@ class Tag extends AstComponent {
}

isSectionStart(): boolean {
const [tagType] = Tag.recognizeSectionTag(this.name);
const [tagType] = Tag.recognizeSectionTag(this);
return tagType === START_TAG;
}

isSectionEnd(): boolean {
const [tagType] = Tag.recognizeSectionTag(this.name);
const [tagType] = Tag.recognizeSectionTag(this);
return tagType === END_TAG;
}

Expand Down
Loading

0 comments on commit 14d2055

Please # to comment.