« get me outta code hell

track.js « page « src - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/page/track.js
blob: c27b2b65d6a19cdb8e1103bf9b60fb3f8b033b88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
// Track page specification.

// Imports

import fixWS from 'fix-whitespace';

import {
    generateAlbumChronologyLinks,
    generateAlbumNavLinks,
    generateAlbumSidebar
} from './album.js';

import * as html from '../util/html.js';

import {
    OFFICIAL_GROUP_DIRECTORY
} from '../util/magic-constants.js';

import {
    bindOpts
} from '../util/sugar.js';

import {
    getTrackCover,
    getAlbumListTag,
    sortByDate
} from '../util/wiki-data.js';

// Page exports

export function targets({wikiData}) {
    return wikiData.trackData;
}

export function write(track, {wikiData}) {
    const { groupData, wikiInfo } = wikiData;
    const { album, referencedByTracks, referencedTracks, otherReleases } = track;

    const useDividedReferences = groupData.some(group => group.directory === OFFICIAL_GROUP_DIRECTORY);
    const rbtFanon = (useDividedReferences &&
        referencedByTracks.filter(t => t.album.groups.every(group => group.directory !== OFFICIAL_GROUP_DIRECTORY)));
    const rbtOfficial = (useDividedReferences &&
        referencedByTracks.filter(t => t.album.groups.some(group => group.directory === OFFICIAL_GROUP_DIRECTORY)));

    const listTag = getAlbumListTag(album);

    let flashesThatFeature;
    if (wikiInfo.enableFlashesAndGames) {
        flashesThatFeature = sortByDate([track, ...otherReleases]
            .flatMap(track => track.featuredInFlashes.map(flash => ({flash, as: track}))));
    }

    const unbound_generateTrackList = (tracks, {getArtistString, link, strings}) => html.tag('ul',
        tracks.map(track => {
            const line = strings('trackList.item.withArtists', {
                track: link.track(track),
                by: `<span class="by">${strings('trackList.item.withArtists.by', {
                    artists: getArtistString(track.artistContribs)
                })}</span>`
            });
            return (track.aka
                ? `<li class="rerelease">${strings('trackList.item.rerelease', {track: line})}</li>`
                : `<li>${line}</li>`);
        })
    );

    const hasCommentary = track.commentary || otherReleases.some(t => t.commentary);
    const generateCommentary = ({
        link,
        strings,
        transformMultiline
    }) => transformMultiline([
        track.commentary,
        ...otherReleases.map(track =>
            (track.commentary?.split('\n')
                .filter(line => line.replace(/<\/b>/g, '').includes(':</i>'))
                .map(line => fixWS`
                    ${line}
                    ${strings('releaseInfo.artistCommentary.seeOriginalRelease', {
                        original: link.track(track)
                    })}
                `)
                .join('\n')))
    ].filter(Boolean).join('\n'));

    const data = {
        type: 'data',
        path: ['track', track.directory],
        data: ({
            serializeContribs,
            serializeCover,
            serializeGroupsForTrack,
            serializeLink
        }) => ({
            name: track.name,
            directory: track.directory,
            dates: {
                released: track.date,
                originallyReleased: track.originalDate,
                coverArtAdded: track.coverArtDate
            },
            duration: track.duration,
            color: track.color,
            cover: serializeCover(track, getTrackCover),
            artistsContribs: serializeContribs(track.artistContribs),
            contributorContribs: serializeContribs(track.contributorContribs),
            coverArtistContribs: serializeContribs(track.coverArtistContribs || []),
            album: serializeLink(track.album),
            groups: serializeGroupsForTrack(track),
            references: track.references.map(serializeLink),
            referencedBy: track.referencedBy.map(serializeLink),
            alsoReleasedAs: otherReleases.map(track => ({
                track: serializeLink(track),
                album: serializeLink(track.album)
            }))
        })
    };

    const page = {
        type: 'page',
        path: ['track', track.directory],
        page: ({
            fancifyURL,
            generateChronologyLinks,
            generateCoverLink,
            generatePreviousNextLinks,
            getAlbumStylesheet,
            getArtistString,
            getLinkThemeString,
            getThemeString,
            getTrackCover,
            link,
            strings,
            transformInline,
            transformLyrics,
            transformMultiline,
            to
        }) => {
            const generateTrackList = bindOpts(unbound_generateTrackList, {getArtistString, link, strings});
            const cover = getTrackCover(track);

            return {
                title: strings('trackPage.title', {track: track.name}),
                stylesheet: getAlbumStylesheet(album, {to}),
                theme: getThemeString(track.color, [
                    `--album-directory: ${album.directory}`,
                    `--track-directory: ${track.directory}`
                ]),

                // disabled for now! shifting banner position per height of page is disorienting
                /*
                banner: album.bannerArtistContribs.length && {
                    classes: ['dim'],
                    dimensions: album.bannerDimensions,
                    path: ['media.albumBanner', album.directory, album.bannerFileExtension],
                    alt: strings('misc.alt.albumBanner'),
                    position: 'bottom'
                },
                */

                main: {
                    content: fixWS`
                        ${cover && generateCoverLink({
                            src: cover,
                            alt: strings('misc.alt.trackCover'),
                            tags: track.artTags
                        })}
                        <h1>${strings('trackPage.title', {track: track.name})}</h1>
                        <p>
                            ${[
                                strings('releaseInfo.by', {
                                    artists: getArtistString(track.artistContribs, {
                                        showContrib: true,
                                        showIcons: true
                                    })
                                }),
                                track.coverArtistContribs.length && strings('releaseInfo.coverArtBy', {
                                    artists: getArtistString(track.coverArtistContribs, {
                                        showContrib: true,
                                        showIcons: true
                                    })
                                }),
                                track.date && strings('releaseInfo.released', {
                                    date: strings.count.date(track.date)
                                }),
                                (track.coverArtDate &&
                                    +track.coverArtDate !== +track.date &&
                                    strings('releaseInfo.artReleased', {
                                        date: strings.count.date(track.coverArtDate)
                                    })),
                                track.duration && strings('releaseInfo.duration', {
                                    duration: strings.count.duration(track.duration)
                                })
                            ].filter(Boolean).join('<br>\n')}
                        </p>
                        <p>${
                            (track.urls?.length
                                ? strings('releaseInfo.listenOn', {
                                    links: strings.list.or(track.urls.map(url => fancifyURL(url, {strings})))
                                })
                                : strings('releaseInfo.listenOn.noLinks'))
                        }</p>
                        ${otherReleases.length && fixWS`
                            <p>${strings('releaseInfo.alsoReleasedAs')}</p>
                            <ul>
                                ${otherReleases.map(track => fixWS`
                                    <li>${strings('releaseInfo.alsoReleasedAs.item', {
                                        track: link.track(track),
                                        album: link.album(track.album)
                                    })}</li>
                                `).join('\n')}
                            </ul>
                        `}
                        ${track.contributorContribs.length && fixWS`
                            <p>${strings('releaseInfo.contributors')}</p>
                            <ul>
                                ${(track.contributorContribs
                                    .map(contrib => `<li>${getArtistString([contrib], {
                                        showContrib: true,
                                        showIcons: true
                                    })}</li>`)
                                    .join('\n'))}
                            </ul>
                        `}
                        ${referencedTracks.length && fixWS`
                            <p>${strings('releaseInfo.tracksReferenced', {track: `<i>${track.name}</i>`})}</p>
                            ${generateTrackList(referencedTracks)}
                        `}
                        ${referencedByTracks.length && fixWS`
                            <p>${strings('releaseInfo.tracksThatReference', {track: `<i>${track.name}</i>`})}</p>
                            ${useDividedReferences && fixWS`
                                <dl>
                                    ${rbtOfficial.length && fixWS`
                                        <dt>${strings('trackPage.referenceList.official')}</dt>
                                        <dd>${generateTrackList(rbtOfficial)}</dd>
                                    `}
                                    ${rbtFanon.length && fixWS`
                                        <dt>${strings('trackPage.referenceList.fandom')}</dt>
                                        <dd>${generateTrackList(rbtFanon)}</dd>
                                    `}
                                </dl>
                            `}
                            ${!useDividedReferences && generateTrackList(referencedByTracks)}
                        `}
                        ${wikiInfo.enableFlashesAndGames && flashesThatFeature.length && fixWS`
                            <p>${strings('releaseInfo.flashesThatFeature', {track: `<i>${track.name}</i>`})}</p>
                            <ul>
                                ${flashesThatFeature.map(({ flash, as }) => html.tag('li',
                                    {class: as !== track && 'rerelease'},
                                    (as === track
                                        ? strings('releaseInfo.flashesThatFeature.item', {
                                            flash: link.flash(flash)
                                        })
                                        : strings('releaseInfo.flashesThatFeature.item.asDifferentRelease', {
                                            flash: link.flash(flash),
                                            track: link.track(as)
                                        })))).join('\n')}
                            </ul>
                        `}
                        ${track.lyrics && fixWS`
                            <p>${strings('releaseInfo.lyrics')}</p>
                            <blockquote>
                                ${transformLyrics(track.lyrics)}
                            </blockquote>
                        `}
                        ${hasCommentary && fixWS`
                            <p>${strings('releaseInfo.artistCommentary')}</p>
                            <blockquote>
                                ${generateCommentary({link, strings, transformMultiline})}
                            </blockquote>
                        `}
                    `
                },

                sidebarLeft: generateAlbumSidebar(album, track, {
                    fancifyURL,
                    getLinkThemeString,
                    link,
                    strings,
                    transformMultiline,
                    wikiData
                }),

                nav: {
                    links: [
                        {toHome: true},
                        {
                            path: ['localized.album', album.directory],
                            title: album.name
                        },
                        listTag === 'ol' ? {
                            html: strings('trackPage.nav.track.withNumber', {
                                number: album.tracks.indexOf(track) + 1,
                                track: link.track(track, {class: 'current', to})
                            })
                        } : {
                            html: strings('trackPage.nav.track', {
                                track: link.track(track, {class: 'current', to})
                            })
                        },
                        album.tracks.length > 1 &&
                        {
                            divider: false,
                            html: generateAlbumNavLinks(album, track, {
                                generatePreviousNextLinks,
                                strings
                            })
                        }
                    ].filter(Boolean),
                    content: fixWS`
                        <div>
                            ${generateAlbumChronologyLinks(album, track, {generateChronologyLinks})}
                        </div>
                    `
                }
            };
        }
    };

    return [data, page];
}