Skip to content

Commit 08c476d

Browse files
authored
docs: Add coloring guide (#120)
1 parent 02450c4 commit 08c476d

File tree

17 files changed

+1102
-38
lines changed

17 files changed

+1102
-38
lines changed

.github/workflows/build-pr.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ jobs:
1313
node-version: lts/*
1414
- run: npm install
1515
- run: npm install @coderline/alphatab@alpha
16+
- run: npm run generate-alphatabdoc
1617
- run: npm run build
1718
- run: cp web.config ./build
1819
- uses: actions/upload-artifact@v4

.github/workflows/deploy-develop.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ jobs:
1919
node-version: lts/*
2020
- run: npm install
2121
- run: npm install @coderline/alphatab@alpha
22+
- run: npm run generate-alphatabdoc
2223
- run: npm run build
2324
- run: cp web.config ./build
2425
- name: Package Zip

.github/workflows/deploy-main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ jobs:
1919
node-version: lts/*
2020
- run: npm install
2121
- run: npm install @coderline/alphatab@latest
22+
- run: npm run generate-alphatabdoc
2223
- run: npm run build
2324
- run: cp web.config ./build
2425
- name: Package Zip

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@
1818
npm-debug.log*
1919
yarn-debug.log*
2020
yarn-error.log*
21+
22+
src/alphatabdoc/

docs/guides/breaking-changes-095-096.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
title: Breaking changes on settings between 0.9.5 and 0.9.6
3+
order: 100
34
---
45

56
import { CodeBadge } from '@site/src/components/CodeBadge';

docs/guides/breaking-changes-097-098.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
title: Breaking changes on settings between 0.9.7 and 0.9.8
3+
order: 101
34
---
45

56
import { CodeBadge } from '@site/src/components/CodeBadge';

docs/guides/coloring.mdx

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
---
2+
title: Coloring Music Sheet
3+
since: 1.5.0
4+
---
5+
6+
# Coloring Music Sheet
7+
8+
import { SinceBadge } from '@site/src/components/SinceBadge';
9+
10+
<SinceBadge since="1.5.0" />
11+
12+
13+
import * as alphaTab from '@coderline/alphatab';
14+
import { getDescriptionText } from '@site/src/alphatabdoc';
15+
16+
export function EnumMemberList({ doc }) {
17+
return (
18+
<>
19+
<code>{doc.name}</code>
20+
<ul>
21+
{doc.members.map(n => (<li key={n.name}><code>{n.name}</code> - {getDescriptionText(n.tsdoc)}</li>))}
22+
</ul>
23+
</>
24+
)
25+
}
26+
27+
alphaTab supports individual styling of music notation elements via a special `style` container which is available on
28+
most levels of the [Data Model](../reference/score.mdx). This means you can customize the colors of individual notes being rendered
29+
base on custom logic.
30+
31+
The best place to apply custom coloring is the [`api.scoreLoaded`](../reference/api/scoreloaded.mdx) event which is triggered whenever
32+
a new score is detected. But you can modify the styles later at any time by accessing the [`score`](../reference/api/score.mdx) and then
33+
initiating a re-render via [`render`](../reference/api/render.mdx).
34+
35+
:::important
36+
alphaTab does not detect dynamically any changes made to the data model. Rendering happens in a background worker, and calling `render` will ensure
37+
all updated information is passed to this renderer and the display is updated. Calling `render` will initiate a full re-layout and drawing of
38+
the music sheet to apply any style changes accordingly, hence it is a quite performance intense operation.
39+
:::
40+
41+
The example codes in this Guide are in JavaScript but can be adapted to the other platforms accordingly.
42+
43+
## Quick Start
44+
45+
This code example here should give you a good first idea how you apply custom colors to elements. Depending on the elements you want to color,
46+
you have to traverse the tree of elements. Then on the `style` container you can fill the colors with the particular elements
47+
48+
import { ColoringExample } from '@site/src/components/ColoringExample';
49+
50+
<ColoringExample />
51+
52+
## Styleable elements
53+
54+
alphaTab tries to give fine grained access to coloring music notation elements. Only when it comes to individual effects and annotations things get more coarse.
55+
56+
### Score level
57+
58+
On Score level initialize the `score.style = new alphaTab.model.ScoreStyle()` and then select the element to color via `alphaTab.model.ScoreSubElement`.
59+
60+
import scoreSubElementDoc from '@site/src/alphatabdoc/model/ScoreSubElement';
61+
62+
<EnumMemberList doc={scoreSubElementDoc} />
63+
64+
### Track level
65+
66+
On Track level initialize the `track.style = new alphaTab.model.TrackStyle()` and then select the element to color via `alphaTab.model.TrackSubElement`.
67+
68+
import trackSubElementDoc from '@site/src/alphatabdoc/model/TrackSubElement';
69+
70+
<EnumMemberList doc={trackSubElementDoc} />
71+
72+
### Bar level
73+
74+
On Bar level initialize the `bar.style = new alphaTab.model.BarStyle()` and then select the element to color via `alphaTab.model.BarSubElement`.
75+
76+
import barSubElementDoc from '@site/src/alphatabdoc/model/BarSubElement';
77+
78+
<EnumMemberList doc={barSubElementDoc} />
79+
80+
81+
### Voice level
82+
83+
On Bar level initialize the `voice.style = new alphaTab.model.VoiceStyle()` and then select the element to color via `alphaTab.model.VoiceSubElement`.
84+
85+
import voiceSubElementDoc from '@site/src/alphatabdoc/model/VoiceSubElement';
86+
87+
<EnumMemberList doc={voiceSubElementDoc} />
88+
89+
### Beat level
90+
91+
On Beat level initialize the `beat.style = new alphaTab.model.BeatStyle()` and then select the element to color via `alphaTab.model.BeatSubElement`.
92+
93+
import beatSubElementDoc from '@site/src/alphatabdoc/model/BeatSubElement';
94+
95+
<EnumMemberList doc={beatSubElementDoc} />
96+
97+
### Note level
98+
99+
On Note level initialize the `note.style = new alphaTab.model.NoteStyle()` and then select the element to color via `alphaTab.model.NoteSubElement`.
100+
101+
import noteSubElementDoc from '@site/src/alphatabdoc/model/NoteSubElement';
102+
103+
<EnumMemberList doc={noteSubElementDoc} />

docs/reference/api/enumerateoutputdevices.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { SinceBadge } from '@site/src/components/SinceBadge';
1313
<SinceBadge since="1.5.0" />
1414

1515
import { TypeTable, TypeRow } from '@site/src/components/TypeTable';
16+
import {ParameterTable, ParameterRow} from '@site/src/components/ParameterTable';
1617

1718
## Description
1819
Loads and lists the available output devices which can be used by the player. Will request permissions if needed.

docs/reference/api/setoutputdevice.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { SinceBadge } from '@site/src/components/SinceBadge';
1313
<SinceBadge since="1.5.0" />
1414

1515
import { TypeTable, TypeRow } from '@site/src/components/TypeTable';
16+
import {ParameterTable, ParameterRow} from '@site/src/components/ParameterTable';
1617

1718
## Description
1819
Changes the output device which should be used for playing the audio (player must be enabled).

docusaurus.config.ts

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ function getSortValue(
3232
prop: string,
3333
docs: Map<string, SidebarItemsGeneratorDoc>,
3434
item: NormalizedSidebarItem
35-
): string | number {
35+
): string | number | undefined {
3636
if (prop in item) {
3737
return item[prop];
3838
}
@@ -76,8 +76,8 @@ function getSortValue(
7676
}
7777
}
7878

79-
console.warn(`Could not get sort prop '${prop}' on sidebar item`, item);
80-
return "";
79+
// console.warn(`Could not get sort prop '${prop}' on sidebar item`, item);
80+
return undefined;
8181
}
8282

8383
const config: Config = {
@@ -115,8 +115,12 @@ const config: Config = {
115115
const sidebarItems = await defaultSidebarItemsGenerator(args);
116116

117117
if (Array.isArray(args.item.customProps?.["sort"])) {
118-
const ascending = args.item.customProps?.["sort"][1] !== "desc";
119-
const prop = args.item.customProps?.["sort"][0];
118+
let props = args.item.customProps?.["sort"] as
119+
| [string, string]
120+
| [string, string][];
121+
if (!Array.isArray(props[0])) {
122+
props = [props as [string, string]];
123+
}
120124

121125
const docsLookup = new Map<string, SidebarItemsGeneratorDoc>(
122126
args.docs.map((d) => [d.id, d])
@@ -125,27 +129,45 @@ const config: Config = {
125129
// Reverse items in categories
126130

127131
sidebarItems.sort((a, b) => {
128-
let av = getSortValue(prop, docsLookup, a);
129-
let bv = getSortValue(prop, docsLookup, b);
132+
for (const prop of props) {
133+
const ascending = prop[1] !== "desc";
130134

131-
if (typeof av !== typeof bv) {
132-
av = String(av);
133-
bv = String(bv);
134-
}
135+
let av = getSortValue(prop[0], docsLookup, a);
136+
let bv = getSortValue(prop[0], docsLookup, b);
135137

136-
if (typeof av === "string") {
137-
if (ascending) {
138-
return av.localeCompare(bv as string);
139-
} else {
140-
return (bv as string).localeCompare(av);
138+
if (typeof av !== typeof bv) {
139+
av = av === undefined ? av : String(av);
140+
bv = bv === undefined ? bv : String(bv);
141141
}
142-
} else {
143-
if (ascending) {
144-
return av - (bv as number);
142+
143+
var result = 0;
144+
145+
if (av === undefined && bv === undefined) {
146+
// continue
147+
} else if (av === undefined) {
148+
return -1;
149+
} else if (bv === undefined) {
150+
return 1;
151+
} else if (typeof av === "string") {
152+
if (ascending) {
153+
result = av.localeCompare(bv as string);
154+
} else {
155+
result = (bv as string).localeCompare(av);
156+
}
145157
} else {
146-
return (bv as number) - av;
158+
if (ascending) {
159+
result = av - (bv as number);
160+
} else {
161+
result = (bv as number) - av;
162+
}
163+
}
164+
165+
if (result !== 0) {
166+
return result;
147167
}
148168
}
169+
170+
return 0;
149171
});
150172
}
151173

@@ -319,16 +341,14 @@ const config: Config = {
319341
const sassLoader = sassRule!.use[sassLoaderIndex] as RuleSetRule;
320342
sassLoader.options = {
321343
...((sassLoader.options as object | undefined) ?? {}),
322-
sourceMap: true // force sourcemaps
344+
sourceMap: true, // force sourcemaps
323345
};
324346

325-
326347
// insert resolve-url-loader before SASS loader to fix relative URLs
327348
sassRule!.use.splice(sassLoaderIndex, 0, {
328349
loader: "resolve-url-loader",
329350
});
330351

331-
332352
return {
333353
plugins: [
334354
// Copy the Font and SoundFont Files to the output

0 commit comments

Comments
 (0)