@hosanna/chordpro 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,54 @@
1
+ import {
2
+ ChordFinder,
3
+ Editor,
4
+ preloadEditor,
5
+ registerChordproMode,
6
+ registerChordproSnippets
7
+ } from "./chunk-QZY7KJWK.mjs";
8
+ import {
9
+ convertToChordProDetailed,
10
+ detectSourceFormat,
11
+ slugifyTitle,
12
+ toChordPro
13
+ } from "./chunk-6VAMM7S3.mjs";
14
+ import {
15
+ ChordProRenderer,
16
+ ChordRoll,
17
+ GuitarDiagram,
18
+ PianoDiagram
19
+ } from "./chunk-CTBAE2XK.mjs";
20
+ import {
21
+ DefaultChordDictionary,
22
+ buildChordProText,
23
+ chordDictionary,
24
+ getNoteValue,
25
+ getSuggestedCapo,
26
+ parseChordPro,
27
+ parseLineSegments,
28
+ transposeChord,
29
+ transposeNote
30
+ } from "./chunk-PENNIH4J.mjs";
31
+ export {
32
+ ChordFinder,
33
+ ChordProRenderer,
34
+ ChordRoll,
35
+ DefaultChordDictionary,
36
+ Editor,
37
+ GuitarDiagram,
38
+ PianoDiagram,
39
+ buildChordProText,
40
+ chordDictionary,
41
+ convertToChordProDetailed,
42
+ detectSourceFormat,
43
+ getNoteValue,
44
+ getSuggestedCapo,
45
+ parseChordPro,
46
+ parseLineSegments,
47
+ preloadEditor,
48
+ registerChordproMode,
49
+ registerChordproSnippets,
50
+ slugifyTitle,
51
+ toChordPro,
52
+ transposeChord,
53
+ transposeNote
54
+ };
@@ -0,0 +1,185 @@
1
+ interface SegmentAST {
2
+ chord: string;
3
+ text: string;
4
+ timing?: number;
5
+ }
6
+ interface MeasureAST {
7
+ chords: SegmentAST[];
8
+ endBarline: string;
9
+ }
10
+ interface LineAST {
11
+ type: "lyrics" | "comment" | "comment_box" | "tab" | "empty" | "chord-section";
12
+ text?: string;
13
+ segments?: SegmentAST[];
14
+ measures?: MeasureAST[];
15
+ startBarline?: string;
16
+ }
17
+ interface SectionAST {
18
+ type: "verse" | "chorus" | "bridge" | "tab" | "comment" | "grid" | "new_song";
19
+ label?: string;
20
+ lines: LineAST[];
21
+ repeat?: string;
22
+ }
23
+ interface SongAST {
24
+ metadata: {
25
+ title?: string;
26
+ subtitle?: string;
27
+ artist?: string;
28
+ composer?: string;
29
+ copyright?: string;
30
+ album?: string;
31
+ key?: string;
32
+ originalKey?: string;
33
+ tempo?: string;
34
+ time?: string;
35
+ capo?: string;
36
+ songNumber?: string;
37
+ youtube?: string;
38
+ ccli?: string;
39
+ duration?: string;
40
+ [key: string]: string | undefined;
41
+ };
42
+ sections: SectionAST[];
43
+ }
44
+ declare function parseLineSegments(lineText: string): SegmentAST[];
45
+ declare function parseChordPro(content: string): SongAST;
46
+ declare function buildChordProText(metadata: {
47
+ [key: string]: string | undefined;
48
+ }, bodyContent: string): string;
49
+
50
+ declare function getNoteValue(note: string): number | undefined;
51
+ declare function getSuggestedCapo(originalKey: string | undefined, transposeVal: number): {
52
+ capo: number;
53
+ chordShape: string;
54
+ } | null;
55
+ declare function transposeNote(note: string, semitones: number, preferFlats?: boolean): string;
56
+ declare function transposeChord(chord: string, semitones: number): string;
57
+
58
+ /**
59
+ * Chord Dictionary — interval-driven engine
60
+ * ------------------------------------------
61
+ * Instead of hand-listing a fingering per chord symbol, chords are derived from
62
+ * music theory:
63
+ *
64
+ * 1. Parse "root + quality (+ /bass)" out of the symbol (English or PT-BR/PT-PT
65
+ * note names).
66
+ * 2. Look up the quality's semitone INTERVALS (a registry, not a switch).
67
+ * 3. Piano is 100% computed from those intervals — every quality, any root,
68
+ * no hardcoding, no fallback needed.
69
+ * 4. Guitar fingerings are physical shapes on 6 strings, which can't be
70
+ * derived from pure interval math the way piano can (open strings,
71
+ * playability, hand span). So guitar uses a small, honest hybrid:
72
+ * a) A curated table of well-known open-position shapes (exact, best-sounding).
73
+ * b) Two movable CAGED "barre templates" (E-form / A-form) covering the
74
+ * 7 qualities that have a standard, universally-taught movable shape
75
+ * (major, minor, 7, m7, maj7, sus2, sus4) — these transpose correctly
76
+ * to ANY root via simple math (shift = target - templateRoot).
77
+ * c) A power-chord (5) formula, which is pure math on any string.
78
+ * d) For qualities with no standard movable shape (dim7, aug, 9, 6,
79
+ * extended/altered chords, ...), we fall back to the nearest simpler
80
+ * quality's shape and flag the result as `approximate: true`, rather
81
+ * than silently returning something wrong or nothing at all.
82
+ */
83
+ interface ChordFingering {
84
+ chord: string;
85
+ /** Canonical quality id resolved for this chord, e.g. "m7", "maj7", "9". */
86
+ qualityId: string;
87
+ /** Human readable quality label, e.g. "Minor 7th". */
88
+ qualityLabel: string;
89
+ guitar?: {
90
+ frets: number[];
91
+ fingers?: number[];
92
+ barre?: number;
93
+ /** True when no standard shape exists for this exact quality and we
94
+ * substituted the nearest simpler quality's shape (e.g. dim7 -> minor shape). */
95
+ approximate?: boolean;
96
+ };
97
+ piano: {
98
+ notes: string[];
99
+ highlightKeys: number[];
100
+ };
101
+ }
102
+ interface IChordDictionary {
103
+ getFingering: (chord: string) => ChordFingering | null;
104
+ }
105
+ declare class DefaultChordDictionary implements IChordDictionary {
106
+ getFingering(chord: string): ChordFingering | null;
107
+ }
108
+ declare const chordDictionary: DefaultChordDictionary;
109
+
110
+ /**
111
+ * txtToChordPro.ts
112
+ * ------------------------------------------------------------------------
113
+ * Universal chord-sheet -> ChordPro converter.
114
+ *
115
+ * Handles three input flavours out of the box:
116
+ * - "ultimate-guitar" -> bracket section headers ([Verse], [Chorus 1], [Intro]),
117
+ * English metadata (Capo:, Tuning:, Key:), trailing
118
+ * repeat notation ("... let it be x2").
119
+ * - "cifraclub" -> Portuguese metadata (Tom:, Capotraste:, Intérprete:),
120
+ * syllable-hyphenated lyrics used purely to align
121
+ * chords over multi-syllable Portuguese words
122
+ * (e.g. "Deus-que-tomou-meu-lugar"), Portuguese
123
+ * section labels (Refrão, Verso, Ponte, Introdução...).
124
+ * - "plain" -> generic chord-line-over-lyric-line sheets with no
125
+ * site-specific quirks. Also the safe fallback.
126
+ *
127
+ * Source format is auto-detected by default (source: 'auto'), but can be
128
+ * forced via options.source. Chord <-> lyric alignment is done by column
129
+ * position (not just token order), so mid-word chords and chords that spill
130
+ * past the end of a lyric line are placed exactly like a human would expect:
131
+ *
132
+ * Am C/G F C
133
+ * Let it be, let it be, let it be, let it be
134
+ *
135
+ * -> Let i[Am]t be, let [C/G]it be, let [F]it be, let [C]it be
136
+ *
137
+ * ------------------------------------------------------------------------
138
+ */
139
+ type SourceFormat = "ultimate-guitar" | "cifraclub" | "plain";
140
+ type SourceOption = SourceFormat | "auto";
141
+ interface ConversionOptions {
142
+ /** Force a source format instead of auto-detecting. Default: 'auto'. */
143
+ source?: SourceOption;
144
+ /** Emit {start_of_verse}/{start_of_chorus}/etc. Default: true. */
145
+ detectSections?: boolean;
146
+ /**
147
+ * Require every token on a candidate chord line to be a valid chord
148
+ * (true) vs. a majority (>=80%, false). Default: true. Turning this off
149
+ * helps with messy OCR/paste artifacts but raises false-positive risk.
150
+ */
151
+ strictChordDetection?: boolean;
152
+ /**
153
+ * Undo CifraClub-style syllable hyphenation ("Deus-que-tomou-meu-lugar"
154
+ * -> "Deus que tomou meu lugar") before merging chords in. 'auto' only
155
+ * does this when the detected/forced source is 'cifraclub'. Default: 'auto'.
156
+ */
157
+ dehyphenateSyllables?: boolean | "auto";
158
+ /**
159
+ * Reattach trailing repeat markers ("x2", "2x", "(2x)") to the end of the
160
+ * merged lyric line instead of treating them as stray chord tokens.
161
+ * Default: true.
162
+ */
163
+ keepRepeatMarkers?: boolean;
164
+ /**
165
+ * Tag names used for non-standard section types (intro/outro/solo/etc).
166
+ * Override if your ChordPro/AST parser expects different tag names.
167
+ * Defaults match the {start_of_part}/{end_of_part} convention.
168
+ */
169
+ partTagNames?: {
170
+ start: string;
171
+ end: string;
172
+ };
173
+ }
174
+ interface ConversionResult {
175
+ chordpro: string;
176
+ title: string | null;
177
+ detectedSource: SourceFormat;
178
+ warnings: string[];
179
+ }
180
+ declare function detectSourceFormat(input: string): SourceFormat;
181
+ declare function slugifyTitle(title: string | null): string;
182
+ declare function convertToChordProDetailed(input: string, options?: ConversionOptions): ConversionResult;
183
+ declare function toChordPro(input: string, options?: ConversionOptions): string;
184
+
185
+ export { type ChordFingering, type ConversionOptions, type ConversionResult, DefaultChordDictionary, type IChordDictionary, type LineAST, type MeasureAST, type SectionAST, type SegmentAST, type SongAST, type SourceFormat, type SourceOption, buildChordProText, chordDictionary, convertToChordProDetailed, detectSourceFormat, getNoteValue, getSuggestedCapo, parseChordPro, parseLineSegments, slugifyTitle, toChordPro, transposeChord, transposeNote };
@@ -0,0 +1,185 @@
1
+ interface SegmentAST {
2
+ chord: string;
3
+ text: string;
4
+ timing?: number;
5
+ }
6
+ interface MeasureAST {
7
+ chords: SegmentAST[];
8
+ endBarline: string;
9
+ }
10
+ interface LineAST {
11
+ type: "lyrics" | "comment" | "comment_box" | "tab" | "empty" | "chord-section";
12
+ text?: string;
13
+ segments?: SegmentAST[];
14
+ measures?: MeasureAST[];
15
+ startBarline?: string;
16
+ }
17
+ interface SectionAST {
18
+ type: "verse" | "chorus" | "bridge" | "tab" | "comment" | "grid" | "new_song";
19
+ label?: string;
20
+ lines: LineAST[];
21
+ repeat?: string;
22
+ }
23
+ interface SongAST {
24
+ metadata: {
25
+ title?: string;
26
+ subtitle?: string;
27
+ artist?: string;
28
+ composer?: string;
29
+ copyright?: string;
30
+ album?: string;
31
+ key?: string;
32
+ originalKey?: string;
33
+ tempo?: string;
34
+ time?: string;
35
+ capo?: string;
36
+ songNumber?: string;
37
+ youtube?: string;
38
+ ccli?: string;
39
+ duration?: string;
40
+ [key: string]: string | undefined;
41
+ };
42
+ sections: SectionAST[];
43
+ }
44
+ declare function parseLineSegments(lineText: string): SegmentAST[];
45
+ declare function parseChordPro(content: string): SongAST;
46
+ declare function buildChordProText(metadata: {
47
+ [key: string]: string | undefined;
48
+ }, bodyContent: string): string;
49
+
50
+ declare function getNoteValue(note: string): number | undefined;
51
+ declare function getSuggestedCapo(originalKey: string | undefined, transposeVal: number): {
52
+ capo: number;
53
+ chordShape: string;
54
+ } | null;
55
+ declare function transposeNote(note: string, semitones: number, preferFlats?: boolean): string;
56
+ declare function transposeChord(chord: string, semitones: number): string;
57
+
58
+ /**
59
+ * Chord Dictionary — interval-driven engine
60
+ * ------------------------------------------
61
+ * Instead of hand-listing a fingering per chord symbol, chords are derived from
62
+ * music theory:
63
+ *
64
+ * 1. Parse "root + quality (+ /bass)" out of the symbol (English or PT-BR/PT-PT
65
+ * note names).
66
+ * 2. Look up the quality's semitone INTERVALS (a registry, not a switch).
67
+ * 3. Piano is 100% computed from those intervals — every quality, any root,
68
+ * no hardcoding, no fallback needed.
69
+ * 4. Guitar fingerings are physical shapes on 6 strings, which can't be
70
+ * derived from pure interval math the way piano can (open strings,
71
+ * playability, hand span). So guitar uses a small, honest hybrid:
72
+ * a) A curated table of well-known open-position shapes (exact, best-sounding).
73
+ * b) Two movable CAGED "barre templates" (E-form / A-form) covering the
74
+ * 7 qualities that have a standard, universally-taught movable shape
75
+ * (major, minor, 7, m7, maj7, sus2, sus4) — these transpose correctly
76
+ * to ANY root via simple math (shift = target - templateRoot).
77
+ * c) A power-chord (5) formula, which is pure math on any string.
78
+ * d) For qualities with no standard movable shape (dim7, aug, 9, 6,
79
+ * extended/altered chords, ...), we fall back to the nearest simpler
80
+ * quality's shape and flag the result as `approximate: true`, rather
81
+ * than silently returning something wrong or nothing at all.
82
+ */
83
+ interface ChordFingering {
84
+ chord: string;
85
+ /** Canonical quality id resolved for this chord, e.g. "m7", "maj7", "9". */
86
+ qualityId: string;
87
+ /** Human readable quality label, e.g. "Minor 7th". */
88
+ qualityLabel: string;
89
+ guitar?: {
90
+ frets: number[];
91
+ fingers?: number[];
92
+ barre?: number;
93
+ /** True when no standard shape exists for this exact quality and we
94
+ * substituted the nearest simpler quality's shape (e.g. dim7 -> minor shape). */
95
+ approximate?: boolean;
96
+ };
97
+ piano: {
98
+ notes: string[];
99
+ highlightKeys: number[];
100
+ };
101
+ }
102
+ interface IChordDictionary {
103
+ getFingering: (chord: string) => ChordFingering | null;
104
+ }
105
+ declare class DefaultChordDictionary implements IChordDictionary {
106
+ getFingering(chord: string): ChordFingering | null;
107
+ }
108
+ declare const chordDictionary: DefaultChordDictionary;
109
+
110
+ /**
111
+ * txtToChordPro.ts
112
+ * ------------------------------------------------------------------------
113
+ * Universal chord-sheet -> ChordPro converter.
114
+ *
115
+ * Handles three input flavours out of the box:
116
+ * - "ultimate-guitar" -> bracket section headers ([Verse], [Chorus 1], [Intro]),
117
+ * English metadata (Capo:, Tuning:, Key:), trailing
118
+ * repeat notation ("... let it be x2").
119
+ * - "cifraclub" -> Portuguese metadata (Tom:, Capotraste:, Intérprete:),
120
+ * syllable-hyphenated lyrics used purely to align
121
+ * chords over multi-syllable Portuguese words
122
+ * (e.g. "Deus-que-tomou-meu-lugar"), Portuguese
123
+ * section labels (Refrão, Verso, Ponte, Introdução...).
124
+ * - "plain" -> generic chord-line-over-lyric-line sheets with no
125
+ * site-specific quirks. Also the safe fallback.
126
+ *
127
+ * Source format is auto-detected by default (source: 'auto'), but can be
128
+ * forced via options.source. Chord <-> lyric alignment is done by column
129
+ * position (not just token order), so mid-word chords and chords that spill
130
+ * past the end of a lyric line are placed exactly like a human would expect:
131
+ *
132
+ * Am C/G F C
133
+ * Let it be, let it be, let it be, let it be
134
+ *
135
+ * -> Let i[Am]t be, let [C/G]it be, let [F]it be, let [C]it be
136
+ *
137
+ * ------------------------------------------------------------------------
138
+ */
139
+ type SourceFormat = "ultimate-guitar" | "cifraclub" | "plain";
140
+ type SourceOption = SourceFormat | "auto";
141
+ interface ConversionOptions {
142
+ /** Force a source format instead of auto-detecting. Default: 'auto'. */
143
+ source?: SourceOption;
144
+ /** Emit {start_of_verse}/{start_of_chorus}/etc. Default: true. */
145
+ detectSections?: boolean;
146
+ /**
147
+ * Require every token on a candidate chord line to be a valid chord
148
+ * (true) vs. a majority (>=80%, false). Default: true. Turning this off
149
+ * helps with messy OCR/paste artifacts but raises false-positive risk.
150
+ */
151
+ strictChordDetection?: boolean;
152
+ /**
153
+ * Undo CifraClub-style syllable hyphenation ("Deus-que-tomou-meu-lugar"
154
+ * -> "Deus que tomou meu lugar") before merging chords in. 'auto' only
155
+ * does this when the detected/forced source is 'cifraclub'. Default: 'auto'.
156
+ */
157
+ dehyphenateSyllables?: boolean | "auto";
158
+ /**
159
+ * Reattach trailing repeat markers ("x2", "2x", "(2x)") to the end of the
160
+ * merged lyric line instead of treating them as stray chord tokens.
161
+ * Default: true.
162
+ */
163
+ keepRepeatMarkers?: boolean;
164
+ /**
165
+ * Tag names used for non-standard section types (intro/outro/solo/etc).
166
+ * Override if your ChordPro/AST parser expects different tag names.
167
+ * Defaults match the {start_of_part}/{end_of_part} convention.
168
+ */
169
+ partTagNames?: {
170
+ start: string;
171
+ end: string;
172
+ };
173
+ }
174
+ interface ConversionResult {
175
+ chordpro: string;
176
+ title: string | null;
177
+ detectedSource: SourceFormat;
178
+ warnings: string[];
179
+ }
180
+ declare function detectSourceFormat(input: string): SourceFormat;
181
+ declare function slugifyTitle(title: string | null): string;
182
+ declare function convertToChordProDetailed(input: string, options?: ConversionOptions): ConversionResult;
183
+ declare function toChordPro(input: string, options?: ConversionOptions): string;
184
+
185
+ export { type ChordFingering, type ConversionOptions, type ConversionResult, DefaultChordDictionary, type IChordDictionary, type LineAST, type MeasureAST, type SectionAST, type SegmentAST, type SongAST, type SourceFormat, type SourceOption, buildChordProText, chordDictionary, convertToChordProDetailed, detectSourceFormat, getNoteValue, getSuggestedCapo, parseChordPro, parseLineSegments, slugifyTitle, toChordPro, transposeChord, transposeNote };