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
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
  | 
import {empty, stitchArrays, unique} from '#sugar';
export default {
  query: (artist) => ({
    trackContributions: [
      ...artist.trackArtistContributions,
      ...artist.trackContributorContributions,
    ],
    artworkContributions: [
      ...artist.albumCoverArtistContributions,
      ...artist.albumWallpaperArtistContributions,
      ...artist.albumBannerArtistContributions,
      ...artist.trackCoverArtistContributions,
    ],
    // Banners and wallpapers don't show up in the artist gallery page, only
    // cover art.
    hasGallery:
      !empty(artist.albumCoverArtistContributions) ||
      !empty(artist.trackCoverArtistContributions),
    aliasLinkedGroups:
      artist.closelyLinkedGroups
        .filter(({annotation}) =>
          annotation === 'alias'),
    generalLinkedGroups:
      artist.closelyLinkedGroups
        .filter(({annotation}) =>
          annotation !== 'alias'),
  }),
  relations: (relation, query, artist) => ({
    layout:
      relation('generatePageLayout'),
    artistNavLinks:
      relation('generateArtistNavLinks', artist),
    artworkColumn:
      relation('generateArtistArtworkColumn', artist),
    contentHeading:
      relation('generateContentHeading'),
    contextNotes:
      relation('transformContent', artist.contextNotes),
    closeGroupLinks:
      query.generalLinkedGroups
        .map(({group}) => relation('linkGroup', group)),
    aliasGroupLinks:
      query.aliasLinkedGroups
        .map(({group}) => relation('linkGroup', group)),
    visitLinks:
      artist.urls
        .map(url => relation('linkExternal', url)),
    tracksChunkedList:
      relation('generateArtistInfoPageTracksChunkedList', artist),
    tracksGroupInfo:
      relation('generateArtistGroupContributionsInfo', query.trackContributions),
    artworksChunkedList:
      relation('generateArtistInfoPageArtworksChunkedList', artist, false),
    editsForWikiArtworksChunkedList:
      relation('generateArtistInfoPageArtworksChunkedList', artist, true),
    artworksGroupInfo:
      relation('generateArtistGroupContributionsInfo', query.artworkContributions),
    artistGalleryLink:
      (query.hasGallery
        ? relation('linkArtistGallery', artist)
        : null),
    flashesChunkedList:
      relation('generateArtistInfoPageFlashesChunkedList', artist),
    commentaryChunkedList:
      relation('generateArtistInfoPageCommentaryChunkedList', artist, false),
    wikiEditorCommentaryChunkedList:
      relation('generateArtistInfoPageCommentaryChunkedList', artist, true),
  }),
  data: (query, artist) => ({
    name:
      artist.name,
    closeGroupAnnotations:
      query.generalLinkedGroups
        .map(({annotation}) => annotation),
    totalTrackCount:
      unique(
        query.trackContributions
          .filter(contrib => contrib.countInContributionTotals)
          .map(contrib => contrib.thing))
        .length,
    totalDuration:
      artist.totalDuration,
  }),
  generate: (data, relations, {html, language}) =>
    language.encapsulate('artistPage', pageCapsule =>
      relations.layout.slots({
        title: data.name,
        headingMode: 'sticky',
        artworkColumnContent:
          relations.artworkColumn,
        mainContent: [
          html.tags([
            html.tag('p',
              {[html.onlyIfSiblings]: true},
              language.$('releaseInfo.note')),
            html.tag('blockquote',
              {[html.onlyIfContent]: true},
              relations.contextNotes),
          ]),
          html.tag('p',
            {[html.onlyIfContent]: true},
            {[html.joinChildren]: html.tag('br')},
            language.encapsulate(pageCapsule, 'closelyLinkedGroups', capsule => [
              language.encapsulate(capsule, capsule => {
                const [workingCapsule, option] =
                  (relations.closeGroupLinks.length === 0
                    ? [null, null]
                 : relations.closeGroupLinks.length === 1
                    ? [language.encapsulate(capsule, 'one'), 'group']
                    : [language.encapsulate(capsule, 'multiple'), 'groups']);
                if (!workingCapsule) return html.blank();
                return language.$(workingCapsule, {
                  [option]:
                    language.formatUnitList(
                      stitchArrays({
                        link: relations.closeGroupLinks,
                        annotation: data.closeGroupAnnotations,
                      }).map(({link, annotation}) =>
                          language.encapsulate(capsule, 'group', workingCapsule => {
                            const workingOptions = {group: link};
                            if (annotation) {
                              workingCapsule += '.withAnnotation';
                              workingOptions.annotation = annotation;
                            }
                            return language.$(workingCapsule, workingOptions);
                          }))),
                });
              }),
              language.$(capsule, 'alias', {
                [language.onlyIfOptions]: ['groups'],
                groups:
                  language.formatConjunctionList(relations.aliasGroupLinks),
              }),
            ])),
          html.tag('p',
            {[html.onlyIfContent]: true},
            language.$('releaseInfo.visitOn', {
              [language.onlyIfOptions]: ['links'],
              links:
                language.formatDisjunctionList(
                  relations.visitLinks
                    .map(link => link.slot('context', 'artist'))),
            })),
          html.tag('p',
            {[html.onlyIfContent]: true},
            language.encapsulate(pageCapsule, 'viewArtGallery', capsule =>
              language.$(capsule, {
                [language.onlyIfOptions]: ['link'],
                link:
                  relations.artistGalleryLink?.slots({
                    content:
                      language.$(capsule, 'link'),
                  }),
              }))),
          html.tag('p',
            {[html.onlyIfContent]: true},
            language.$('misc.jumpTo.withLinks', {
              [language.onlyIfOptions]: ['links'],
              links:
                language.formatUnitList([
                  !html.isBlank(relations.tracksChunkedList) &&
                    html.tag('a',
                      {href: '#tracks'},
                      language.$(pageCapsule, 'trackList.title')),
                  (!html.isBlank(relations.artworksChunkedList) ||
                   !html.isBlank(relations.editsForWikiArtworksChunkedList)) &&
                      html.tag('a',
                        {href: '#art'},
                        language.$(pageCapsule, 'artList.title')),
                  !html.isBlank(relations.flashesChunkedList) &&
                    html.tag('a',
                      {href: '#flashes'},
                      language.$(pageCapsule, 'flashList.title')),
                  (!html.isBlank(relations.commentaryChunkedList) ||
                   !html.isBlank(relations.wikiEditorCommentaryChunkedList)) &&
                    html.tag('a',
                      {href: '#commentary'},
                      language.$(pageCapsule, 'commentaryList.title')),
                ].filter(Boolean)),
            })),
          html.tags([
            relations.contentHeading.clone()
              .slots({
                tag: 'h2',
                attributes: {id: 'tracks'},
                title: language.$(pageCapsule, 'trackList.title'),
              }),
            data.totalDuration > 0 &&
              html.tag('p',
                {[html.onlyIfSiblings]: true},
                language.$(pageCapsule, 'contributedDurationLine', {
                  artist: data.name,
                  duration:
                    language.formatDuration(data.totalDuration, {
                      approximate: data.totalTrackCount > 1,
                      unit: true,
                    }),
                })),
            relations.tracksChunkedList.slots({
              groupInfo:
                language.encapsulate(pageCapsule, 'groupContributions', capsule => [
                  relations.tracksGroupInfo.clone()
                    .slots({
                      title: language.$(capsule, 'title.music'),
                      showSortButton: true,
                      sort: 'count',
                      countUnit: 'tracks',
                      visible: true,
                    }),
                  relations.tracksGroupInfo.clone()
                    .slots({
                      title: language.$(capsule, 'title.music'),
                      showSortButton: true,
                      sort: 'duration',
                      countUnit: 'tracks',
                      visible: false,
                    }),
                ]),
            }),
          ]),
          html.tags([
            relations.contentHeading.clone()
              .slots({
                tag: 'h2',
                attributes: {id: 'art'},
                title: language.$(pageCapsule, 'artList.title'),
              }),
            html.tag('p',
              {[html.onlyIfContent]: true},
              language.encapsulate(pageCapsule, 'viewArtGallery', capsule =>
                language.$(capsule, 'orBrowseList', {
                  [language.onlyIfOptions]: ['link'],
                  link:
                    relations.artistGalleryLink?.slots({
                      content: language.$(capsule, 'link'),
                    }),
                }))),
            relations.artworksChunkedList
              .slots({
                groupInfo:
                  language.encapsulate(pageCapsule, 'groupContributions', capsule =>
                    relations.artworksGroupInfo
                      .slots({
                        title: language.$(capsule, 'title.artworks'),
                        showBothColumns: false,
                        sort: 'count',
                        countUnit: 'artworks',
                      })),
              }),
            html.tags([
              language.encapsulate(pageCapsule, 'wikiEditArtworks', capsule =>
                relations.contentHeading.clone()
                  .slots({
                    tag: 'p',
                    title:
                      language.$(capsule, {artist: data.name}),
                    stickyTitle:
                      language.$(capsule, 'sticky'),
                  })),
              relations.editsForWikiArtworksChunkedList,
            ]),
          ]),
          html.tags([
            relations.contentHeading.clone()
              .slots({
                tag: 'h2',
                attributes: {id: 'flashes'},
                title: language.$(pageCapsule, 'flashList.title'),
              }),
            relations.flashesChunkedList,
          ]),
          html.tags([
            relations.contentHeading.clone()
              .slots({
                tag: 'h2',
                attributes: {id: 'commentary'},
                title: language.$(pageCapsule, 'commentaryList.title'),
              }),
            relations.commentaryChunkedList,
            html.tags([
              language.encapsulate(pageCapsule, 'wikiEditorCommentary', capsule =>
                relations.contentHeading.clone()
                  .slots({
                    tag: 'p',
                    title:
                      language.$(capsule, {artist: data.name}),
                    stickyTitle:
                      language.$(capsule, 'sticky'),
                  })),
              relations.wikiEditorCommentaryChunkedList,
            ]),
          ]),
        ],
        navLinkStyle: 'hierarchical',
        navLinks:
          relations.artistNavLinks
            .slots({
              showExtraLinks: true,
            })
            .content,
      })),
};
  |