« get me outta code hell

album.js « files « data « src - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/data/files/album.js
blob: da687ddf470bf5965a0ee5c8d289abf2916404f0 (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
import * as path from 'node:path';

import {traverse} from '#node-utils';
import {sortAlbumsTracksChronologically, sortChronologically} from '#sort';
import {empty} from '#sugar';
import Thing from '#thing';

export default ({
  documentModes: {headerAndEntries},
  thingConstructors: {
    Album,
    Track,
    TrackSection,

    AsideTrackSection,
    CloseAsideTrackSection,
  },
}) => ({
  title: `Process album files`,

  files: dataPath =>
    traverse(path.join(dataPath, 'album'), {
      filterFile: name => path.extname(name) === '.yaml',
      prefixPath: 'album',
    }),

  documentMode: headerAndEntries,
  headerDocumentThing: Album,
  entryDocumentThing: document =>
    ('Section' in document
      ? TrackSection
   : 'Aside Section' in document
      ? AsideTrackSection
   : 'Close Aside Section' in document
      ? CloseAsideTrackSection
      : Track),

  connect({header: album, entries}) {
    const trackSections = [];

    let currentTrackSection = new TrackSection();
    let currentTrackSectionTracks = [];

    let latestNonAsideTrackSection = currentTrackSection;

    Object.assign(currentTrackSection, {
      name: `Default Track Section`,
      isDefaultTrackSection: true,
    });

    const closeCurrentTrackSection = () => {
      if (
        currentTrackSection.isDefaultTrackSection &&
        empty(currentTrackSectionTracks)
      ) {
        return;
      }

      currentTrackSection.tracks = currentTrackSectionTracks;
      currentTrackSection.album = album;

      trackSections.push(currentTrackSection);
    };

    for (const entry of entries) {
      if (entry instanceof TrackSection) {
        closeCurrentTrackSection();
        currentTrackSection = entry;
        currentTrackSectionTracks = [];

        if (entry.style !== 'aside') {
          latestNonAsideTrackSection = entry;
        }

        continue;
      }

      if (entry instanceof CloseAsideTrackSection) {
        if (currentTrackSection.style !== 'aside') {
          throw new Error(`Current track section "${currentTrackSection.name}" is not an aside`);
        }

        if (entry.name !== currentTrackSection.name) {
          throw new Error(`Expected "Close Aside Section: ${currentTrackSection.name}", got "${entry.name}"`);
        }

        closeCurrentTrackSection();
        currentTrackSection = Thing.clone(latestNonAsideTrackSection);
        currentTrackSection.tracks = [];
        currentTrackSectionTracks = [];

        continue;
      }

      entry.album = album;
      entry.trackSection = currentTrackSection;

      currentTrackSectionTracks.push(entry);
    }

    closeCurrentTrackSection();

    album.trackSections = trackSections;
  },

  sort({albumData, trackData}) {
    sortChronologically(albumData);
    sortAlbumsTracksChronologically(trackData);
  },
});