A music player that connects to your cloud/distributed storage.
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

chore: `elements.txt`

+242 -217
+190
src/_data/elements.yaml
··· 1 + artwork: 2 + - url: "components/artwork/audio-metadata/element.js" 3 + title: "Audio Metadata" 4 + desc: "Extracts embedded artwork from audio files using the music-metadata library." 5 + - url: "components/artwork/input/element.js" 6 + title: "Input" 7 + desc: "Fetches artwork by delegating to the configured input element's artwork method." 8 + - url: "components/artwork/last.fm/element.js" 9 + title: "Last.fm" 10 + desc: "Fetches cover art from the Last.fm API using track artist and album tags." 11 + - url: "components/artwork/musicbrainz/element.js" 12 + title: "MusicBrainz" 13 + desc: "Fetches cover art from MusicBrainz and the Cover Art Archive using track artist and album tags." 14 + 15 + configurators: 16 + - url: "components/configurator/artwork/element.js" 17 + title: "Artwork" 18 + desc: "Takes artwork components as children and tries each in sequence, returning the first non-null result." 19 + - url: "components/configurator/input/element.js" 20 + title: "Input" 21 + desc: "Allows for multiple inputs to be used at once." 22 + - url: "components/configurator/metadata/element.js" 23 + title: "Metadata" 24 + desc: "Takes metadata components as children and chains their patches in sequence." 25 + - url: "components/configurator/output/element.js" 26 + title: "Output" 27 + desc: "Enables the user to configure a specific output. If no default output is set, it creates a temporary session by storing everything in memory." 28 + - url: "components/configurator/scrobbles/element.js" 29 + title: "Scrobbles" 30 + desc: "Configure multiple scrobblers (music trackers)." 31 + 32 + engines: 33 + - url: "components/engine/audio/element.js" 34 + title: "Audio" 35 + desc: "Plays audio through audio elements." 36 + - url: "components/engine/queue/element.js" 37 + title: "Queue" 38 + desc: "A queue for tracks." 39 + - url: "components/engine/repeat-shuffle/element.js" 40 + title: "Repeat & Shuffle" 41 + desc: "Signals synced with local storage (classified by group) that decide if audio should be repeated and if the queue should be shuffled when filling it." 42 + - url: "components/engine/scope/element.js" 43 + title: "Scope" 44 + desc: "Signals that could influence the scope of a set of tracks." 45 + 46 + input: 47 + - url: "components/input/dropbox/element.js" 48 + title: "Dropbox" 49 + desc: "Audio files from Dropbox, using the Dropbox v2 HTTP API." 50 + - url: "components/input/ephemeral-cache/element.js" 51 + title: "Ephemeral Cache" 52 + desc: "Wraps another input and caches its track listing in memory for the duration of the session." 53 + - url: "components/input/https/element.js" 54 + title: "HTTPS" 55 + desc: "HTTPS URLs to audio files or streams." 56 + - url: "components/input/icecast/element.js" 57 + title: "Icecast" 58 + desc: "Icecast internet radio streams. Fetches ICY metadata to populate track information." 59 + - url: "components/input/local/element.js" 60 + title: "Local" 61 + desc: "Audio files or directories from your local device, using the browser's File System Access API." 62 + - url: "components/input/opensubsonic/element.js" 63 + title: "Opensubsonic" 64 + desc: "Add any (open)subsonic server." 65 + - url: "components/input/s3/element.js" 66 + title: "S3" 67 + desc: "AWS S3 and services that provide the same surface API such as Cloudflare R2." 68 + - url: "components/input/webdav/element.js" 69 + title: "WebDAV" 70 + desc: "Add any WebDAV server." 71 + 72 + metadata: 73 + - url: "components/metadata/audio-file/element.js" 74 + title: "Audio File" 75 + desc: "Extracts tags and audio stats from audio files using the music-metadata library." 76 + 77 + orchestrators: 78 + - url: "components/orchestrator/artwork/element.js" 79 + title: "Artwork" 80 + desc: "Fetches cover art for a given set of tracks, stored locally in indexedDB. Uses the artwork configurator to try each configured source in sequence." 81 + - url: "components/orchestrator/auto-queue/element.js" 82 + title: "Automatic Queue" 83 + desc: "Fill the queue automatically with non-manual items (shuffled or regular, based on repeat-shuffle engine)." 84 + - url: "components/orchestrator/controller/element.js" 85 + title: "Controller" 86 + desc: "Provides commonly used computed signals derived from the audio engine, queue engine, and output. Exposes currentTrack(), isPlaying(), and references to the underlying engines." 87 + - url: "components/orchestrator/cover-groups/element.js" 88 + title: "Cover Groups" 89 + desc: "Groups tracks by cover art to form collections." 90 + - url: "components/orchestrator/favourites/element.js" 91 + title: "Favourites" 92 + desc: "Mark tracks as favourites. Automatically creates an unordered 'Favourites' playlist." 93 + - url: "components/orchestrator/media-session/element.js" 94 + title: "Media Session" 95 + desc: "Keeps the browser/os media session in sync with queue and audio state. Adds handlers for previous, next, seek to, etc." 96 + - url: "components/orchestrator/offline/element.js" 97 + title: "Offline" 98 + desc: "Registers a service worker that makes the page available offline. Resources (except audio & video) are cached as they load and served from cache when offline." 99 + - url: "components/orchestrator/output/element.js" 100 + title: "Output" 101 + desc: "A default output configuration. Contains all the outputs provided here along with the relevant transformers." 102 + - url: "components/orchestrator/path-collections/element.js" 103 + title: "Path Collections" 104 + desc: "Wraps an output element to generate ephemeral playlists based on the first path segment of each track's URI. Ephemeral items are excluded from storage." 105 + - url: "components/orchestrator/process-tracks/element.js" 106 + title: "Process Inputs Into Tracks" 107 + desc: "Whenever the cached tracks are initially loaded through the passed output element it will list tracks by using the passed input element. Afterwards it loops over all tracks and checks if metadata needs to be fetched. If anything has changed, it'll pass the results to the output element." 108 + - url: "components/orchestrator/queue-audio/element.js" 109 + title: "Queue ⭤ Audio" 110 + desc: "Connects the given queue engine to the given audio engine." 111 + - url: "components/orchestrator/scoped-tracks/element.js" 112 + title: "Scoped Tracks" 113 + desc: "Watches the given output's tracks collection and runs them through a built-in search index. Can perform a search and other ways to reduce the scope of tracks based on the given scope engine. Provides a tracks signal similar to output.tracks.collection." 114 + - url: "components/orchestrator/scrobble-audio/element.js" 115 + title: "Scrobble ⭤ Audio" 116 + desc: "Connects the audio engine with a scrobbler element. Calls nowPlaying when a track starts playing and scrobble once the user has listened long enough." 117 + - url: "components/orchestrator/sources/element.js" 118 + title: "Sources" 119 + desc: "Monitor tracks from the given output to form a list of sources based on the input's sources return value." 120 + 121 + output: 122 + - url: "components/output/polymorphic/indexed-db/element.js" 123 + title: "Polymorphic / IndexedDB" 124 + desc: "Stores output into the local indexedDB. Supports any type of data that indexedDB supports." 125 + - url: "components/output/bytes/s3/element.js" 126 + title: "Bytes / S3" 127 + desc: "Store output data on AWS S3 or compatible services such as Cloudflare R2." 128 + - url: "components/output/raw/atproto/element.js" 129 + title: "Raw / AT Protocol" 130 + desc: "Store your user data on the storage associated with your ATProtocol identity. Data is lexicon shaped by default so this element takes in that data directly without any transformations." 131 + 132 + supplements: 133 + - url: "components/supplement/last.fm/element.js" 134 + title: "Last.fm Scrobbler" 135 + desc: "Scrobbles track plays to Last.fm." 136 + - url: "components/supplement/listenbrainz/element.js" 137 + title: "ListenBrainz Scrobbler" 138 + desc: "Scrobbles track plays to ListenBrainz." 139 + todo: true 140 + - url: "components/supplement/rocksky/element.js" 141 + title: "Rocksky Scrobbler" 142 + desc: "Scrobbles track plays to Rocksky." 143 + todo: true 144 + 145 + transformers: 146 + - url: "components/transformer/output/bytes/automerge/element.js" 147 + title: "Output / Bytes / Automerge" 148 + desc: "Translate data to and from an Automerge CRDT." 149 + todo: true 150 + - url: "components/transformer/output/bytes/dasl-sync/element.js" 151 + title: "Output / Bytes / DASL Sync" 152 + desc: "Syncs data between local and remote using CID-based diffing and performs union merges with tombstone tracking when both sides have diverged." 153 + - url: "components/transformer/output/bytes/json/element.js" 154 + title: "Output / Bytes / JSON" 155 + desc: "Raw data schema output to and from JSON Uint8Array." 156 + - url: "components/transformer/output/raw/atproto-sync/element.js" 157 + title: "Output / Raw / AT Protocol Sync" 158 + desc: "Wraps an AT Protocol output with a local IndexedDB cache. Uses the repo revision to skip unnecessary fetches and performs union merges with tombstone tracking when both local and remote have diverged." 159 + - url: "components/transformer/output/refiner/default/element.js" 160 + title: "Output / Refiner / Default" 161 + desc: "Removes output state that is not meant to be saved to storage, such as ephemeral tracks. Ideally part of every theme." 162 + - url: "components/transformer/output/refiner/initial-contents/element.js" 163 + title: "Output / Refiner / Initial Contents" 164 + desc: "Sets the initial contents for an output on first load." 165 + - url: "components/transformer/output/refiner/passkey-encryption/element.js" 166 + title: "Output / Refiner / Track URI Passkey" 167 + desc: "Encrypts track URIs using a passkey-derived PRF key. On read, decrypts encrypted:// URIs transparently; on write, re-encrypts all URIs before passing downstream." 168 + - url: "components/transformer/output/string/json/element.js" 169 + title: "Output / String / JSON" 170 + desc: "Raw data schema output to and from JSON UTF8 string." 171 + 172 + definitions: 173 + - title: "Output / Collaboration" 174 + desc: "Represents a collaboration between multiple collaborators on a subject, such as a playlist." 175 + url: "definitions/output/collaboration.json" 176 + - title: "Output / Facet" 177 + desc: "Facet pointer or HTML snippet." 178 + url: "definitions/output/facet.json" 179 + - title: "Output / Playlist Item" 180 + desc: "Represents a single item in a playlist. Tracks are matched based on the given criteria. A playlist is formed by grouping items by their playlist property." 181 + url: "definitions/output/playlistItem.json" 182 + - title: "Output / Progress" 183 + desc: "Used to track progress of (long) audio playback." 184 + todo: true 185 + - title: "Output / Track" 186 + desc: "Represents audio that can be played, or a placeholder for a source of tracks. Contains a URI that will resolve to the audio." 187 + url: "definitions/output/track.json" 188 + - title: "Output / Track Bundle" 189 + desc: "A bundle of tracks." 190 + url: "definitions/output/trackBundle.json"
+14
src/_data/elements/sources.js
··· 1 + import { walk } from "@std/fs/walk"; 2 + 3 + const srcDir = new URL("../../", import.meta.url).pathname; 4 + const sources = {}; 5 + 6 + for await ( 7 + const entry of walk(srcDir + "components", { match: [/element\.js$/] }) 8 + ) { 9 + const content = await Deno.readTextFile(entry.path); 10 + const key = entry.path.slice(srcDir.length); 11 + sources[key] = content; 12 + } 13 + 14 + export default sources;
+1 -1
src/components/transformer/output/bytes/json/element.js
··· 126 126 //////////////////////////////////////////// 127 127 128 128 export const CLASS = JsonStringOutputTransformer; 129 - export const NAME = "dtos-json"; 129 + export const NAME = "dtob-json"; 130 130 131 131 defineElement(NAME, CLASS);
+27
src/elements.txt.vto
··· 1 + --- 2 + url: /elements.txt 3 + layout: false 4 + --- 5 + # Diffuse Elements 6 + 7 + {{ for group of [ 8 + { name: "Artwork", items: elements.artwork }, 9 + { name: "Configurators", items: elements.configurators }, 10 + { name: "Engines", items: elements.engines }, 11 + { name: "Input", items: elements.input }, 12 + { name: "Metadata", items: elements.metadata }, 13 + { name: "Orchestrators", items: elements.orchestrators }, 14 + { name: "Output", items: elements.output }, 15 + { name: "Supplements", items: elements.supplements }, 16 + { name: "Transformers", items: elements.transformers }, 17 + ] }} 18 + ## {{ group.name }} 19 + {{ for item of group.items }}{{ if item.url }} 20 + ### {{ item.title }} 21 + 22 + {{ item.desc }} 23 + 24 + ```js 25 + {{ elements.sources[item.url] }}``` 26 + {{ /if }}{{ /for }} 27 + {{ /for }}
+10 -216
src/elements.vto
··· 8 8 - styles/diffuse/page.css 9 9 - vendor/@phosphor-icons/web/bold/style.css 10 10 - vendor/@phosphor-icons/web/fill/style.css 11 - 12 - # ELEMENTS 13 - 14 - artwork: 15 - - url: "components/artwork/audio-metadata/element.js" 16 - title: "Audio Metadata" 17 - desc: "Extracts embedded artwork from audio files using the music-metadata library." 18 - - url: "components/artwork/last.fm/element.js" 19 - title: "Last.fm" 20 - desc: "Fetches cover art from the Last.fm API using track artist and album tags." 21 - - url: "components/artwork/musicbrainz/element.js" 22 - title: "MusicBrainz" 23 - desc: "Fetches cover art from MusicBrainz and the Cover Art Archive using track artist and album tags." 24 - 25 - configurators: 26 - - url: "components/configurator/artwork/element.js" 27 - title: "Artwork" 28 - desc: "Takes artwork components as children and tries each in sequence, returning the first non-null result." 29 - - url: "components/configurator/input/element.js" 30 - title: "Input" 31 - desc: "Allows for multiple inputs to be used at once." 32 - - url: "components/configurator/metadata/element.js" 33 - title: "Metadata" 34 - desc: "Takes metadata components as children and chains their patches in sequence." 35 - - url: "components/configurator/output/element.js" 36 - title: "Output" 37 - desc: "Enables the user to configure a specific output. If no default output is set, it creates a temporary session by storing everything in memory." 38 - - url: "components/configurator/scrobbles/element.js" 39 - title: "Scrobbles" 40 - desc: "Configure multiple scrobblers (music trackers)." 41 - 42 - engines: 43 - - url: "components/engine/audio/element.js" 44 - title: "Audio" 45 - desc: "Plays audio through audio elements." 46 - - url: "components/engine/queue/element.js" 47 - title: "Queue" 48 - desc: "A queue for tracks." 49 - - url: "components/engine/repeat-shuffle/element.js" 50 - title: "Repeat & Shuffle" 51 - desc: "Signals synced with local storage (classified by group) that decide if audio should be repeated and if the queue should be shuffled when filling it." 52 - - url: "components/engine/scope/element.js" 53 - title: "Scope" 54 - desc: > 55 - Signals that could influence the scope of a set of tracks. 56 - 57 - input: 58 - - url: "components/input/dropbox/element.js" 59 - title: "Dropbox" 60 - desc: > 61 - Audio files from Dropbox, using the Dropbox v2 HTTP API. 62 - - url: "components/input/https/element.js" 63 - title: "HTTPS" 64 - desc: > 65 - HTTPS URLs to audio files or streams. 66 - - title: "HTTPS (JSON)" 67 - desc: > 68 - Generate tracks based on HTTPS servers that provide JSON (directory) listings. 69 - todo: true 70 - - url: "components/input/icecast/element.js" 71 - title: "Icecast" 72 - desc: > 73 - Icecast internet radio streams. Fetches ICY metadata to populate track information. 74 - - url: "components/input/local/element.js" 75 - title: "Local" 76 - desc: > 77 - Audio files or directories from your local device, using the browser's File System Access API. 78 - - url: "components/input/opensubsonic/element.js" 79 - title: "Opensubsonic" 80 - desc: > 81 - Add any (open)subsonic server. 82 - - url: "components/input/s3/element.js" 83 - title: "S3" 84 - desc: > 85 - AWS S3 and services that provide the same surface API such as Cloudflare R2. 86 - - title: "WebDAV" 87 - desc: > 88 - Add any WebDAV server. 89 - todo: true 90 - 91 - orchestrators: 92 - - url: "components/orchestrator/auto-queue/element.js" 93 - title: "Automatic Queue" 94 - desc: > 95 - Fill the queue automatically with non-manual items (shuffled or regular, based on repeat-shuffle engine). 96 - - url: "components/orchestrator/favourites/element.js" 97 - title: "Favourites" 98 - desc: > 99 - Mark tracks as favourites. Automatically creates an unordered 'Favourites' playlist. 100 - - url: "components/orchestrator/input/element.js" 101 - title: "Input" 102 - desc: "**A default input configuration.** Contains all the inputs provided here." 103 - - url: "components/orchestrator/media-session/element.js" 104 - title: "Media Session" 105 - desc: "Keeps the browser/os media session in sync with queue and audio state. Adds handlers for previous, next, seek to, etc." 106 - - url: "components/orchestrator/offline/element.js" 107 - title: "Offline" 108 - desc: "Registers a service worker that makes the page available offline. Resources (except audio & video) are cached as they load and served from cache when offline." 109 - - url: "components/orchestrator/output/element.js" 110 - title: "Output" 111 - desc: "**A default output configuration.** Contains all the outputs provided here along with the relevant transformers." 112 - - url: "components/orchestrator/path-collections/element.js" 113 - title: "Path Collections" 114 - desc: "Wraps an output element to generate ephemeral playlists based on the first path segment of each track's URI. Ephemeral items are excluded from storage." 115 - - url: "components/orchestrator/process-tracks/element.js" 116 - title: "Process Inputs Into Tracks" 117 - desc: "Whenever the cached tracks are initially loaded through the passed output element it will list tracks by using the passed input element. Afterwards it loops over all tracks and checks if metadata needs to be fetched. If anything has changed, it'll pass the results to the output element." 118 - - url: "components/orchestrator/queue-audio/element.js" 119 - title: "Queue ⭤ Audio" 120 - desc: "Connects the given queue engine to the given audio engine." 121 - - url: "components/orchestrator/scrobble-audio/element.js" 122 - title: "Scrobble ⭤ Audio" 123 - desc: "Connects the audio engine with a scrobbler element. Calls `nowPlaying` when a track starts playing and `scrobble` once the user has listened long enough." 124 - - url: "components/orchestrator/sources/element.js" 125 - title: "Sources" 126 - desc: "Monitor tracks from the given output to form a list of sources based on the input's sources return value." 127 - - url: "components/orchestrator/artwork/element.js" 128 - title: "Artwork" 129 - desc: "Fetches cover art for a given set of tracks, stored locally in indexedDB. Uses the artwork configurator to try each configured source in sequence." 130 - - url: "components/orchestrator/scoped-tracks/element.js" 131 - title: "Scoped Tracks" 132 - desc: "Watches the given output's tracks collection and runs them through a built-in search index. Can perform a search and other ways to reduce the scope of tracks based on the given scope engine. Provides a `tracks` signal similar to `output.tracks.collection`" 133 - 134 - output: 135 - - url: "components/output/polymorphic/indexed-db/element.js" 136 - title: "Polymorphic / IndexedDB" 137 - desc: "Stores output into the local indexedDB. Supports any type of data that indexedDB supports." 138 - - url: "components/output/bytes/s3/element.js" 139 - title: "Bytes / S3" 140 - desc: > 141 - Store output data on AWS S3 or compatible services such as Cloudflare R2. 142 - - url: "components/output/raw/atproto/element.js" 143 - title: "Raw / AT Protocol" 144 - desc: > 145 - Store your user data on the storage associated with your ATProtocol identity. Data is lexicon shaped by default so this element takes in that data directly without any transformations. 146 - 147 - metadata: 148 - - url: "components/metadata/audio-file/element.js" 149 - title: "Audio File" 150 - desc: "Extracts tags and audio stats from audio files using the music-metadata library." 151 - 152 - supplements: 153 - - url: "components/supplement/last.fm/element.js" 154 - title: "Last.fm Scrobbler" 155 - - title: "ListenBrainz Scrobbler" 156 - todo: true 157 - - title: "Rocksky Scrobbler" 158 - todo: true 159 - - title: "Teal.fm Scrobbler" 160 - todo: true 161 - 162 - transformers: 163 - - title: "Output / Bytes / Automerge" 164 - desc: "Translate data to and from an Automerge CRDT." 165 - url: "components/transformer/output/bytes/automerge/element.js" 166 - todo: true 167 - - title: "Output / Bytes / Cambria Lenses" 168 - desc: "Uses the Cambria library to seamlessly translate between data schemas so that no data migration is needed." 169 - todo: true 170 - - title: "Output / Bytes / DASL Sync" 171 - desc: "Syncs data between local and remote using CID-based diffing and performs union merges with tombstone tracking when both sides have diverged." 172 - url: "components/transformer/output/bytes/dasl-sync/element.js" 173 - - title: "Output / Bytes / JSON" 174 - desc: "Raw data schema output ⇄ JSON Uint8Array." 175 - url: "components/transformer/output/bytes/json/element.js" 176 - - title: "Output / Raw / AT Protocol Sync" 177 - desc: "Wraps an AT Protocol output with a local IndexedDB cache. Uses the repo revision to skip unnecessary fetches and performs union merges with tombstone tracking when both local and remote have diverged." 178 - url: "components/transformer/output/raw/atproto-sync/element.js" 179 - - title: "Output / Refiner / Default" 180 - desc: "The task of a refiner transformer is to remove the output state that is not meant to be saved to storage. For example, ephemeral tracks; this transformer will keep them in memory, but they will not be present in the output. **Ideally this is part of every theme, but you may swap it out with another transformer that might provide better defaults.**" 181 - url: "components/transformer/output/refiner/default/element.js" 182 - - title: "Output / Refiner / Track URI Passkey" 183 - desc: "Encrypts track URIs using a passkey-derived PRF key. On read, decrypts `encrypted://` URIs transparently; on write, re-encrypts all URIs before passing downstream. Tracks that cannot be decrypted are held separately and excluded from the visible collection." 184 - url: "components/transformer/output/refiner/passkey-encryption/element.js" 185 - - title: "Output / String / JSON" 186 - desc: "Raw data schema output ⇄ JSON UTF8 string." 187 - url: "components/transformer/output/string/json/element.js" 188 - 189 - # DEFINITIONS 190 - 191 - definitions: 192 - - title: "Output / Collaboration" 193 - desc: > 194 - Represents a collaboration between multiple collaborators on a subject, such as a playlist. 195 - url: "definitions/output/collaboration.json" 196 - - title: "Output / Facet" 197 - desc: > 198 - Facet pointer or HTML snippet. 199 - url: "definitions/output/facet.json" 200 - - title: "Output / Playlist Item" 201 - desc: > 202 - Represents a single item in a playlist. Tracks are matched based on the given criteria. A playlist is formed by grouping items by their playlist property. 203 - url: "definitions/output/playlistItem.json" 204 - - title: "Output / Progress" 205 - desc: > 206 - Used to track progress of (long) audio playback. 207 - todo: true 208 - - title: "Output / Track" 209 - desc: > 210 - Represents audio that can be played, or a placeholder for a source of tracks. Contains a URI that will resolve to the audio. 211 - url: "definitions/output/track.json" 212 - - title: "Output / Track Bundle" 213 - desc: > 214 - A bundle of tracks. 215 - url: "definitions/output/trackBundle.json" 216 - 217 11 --- 218 12 219 13 <header> ··· 252 46 <div class="columns"> 253 47 {{ await comp.element({ 254 48 title: "Artwork", 255 - items: artwork, 49 + items: elements.artwork, 256 50 content: ` 257 51 Elements that provide artwork for tracks. 258 52 ` ··· 260 54 261 55 {{ await comp.element({ 262 56 title: "Configurators", 263 - items: configurators, 57 + items: elements.configurators, 264 58 content: ` 265 59 Intermediates in order to make a particular kind of element configurable. In other words, these allow for an element to be swapped out with another that takes the same set of the actions and data output. 266 60 ` ··· 268 62 269 63 {{ await comp.element({ 270 64 title: "Engines", 271 - items: engines, 65 + items: elements.engines, 272 66 content: ` 273 67 Elements with each a singular purpose. There are orchestrator elements that control these. 274 68 ` ··· 276 70 277 71 {{ await comp.element({ 278 72 title: "Input", 279 - items: input, 73 + items: elements.input, 280 74 content: ` 281 75 Inputs are sources of audio tracks. Each track is an entry in the list of possible items to play. These can be files or streams, static or dynamic. 282 76 ` ··· 284 78 285 79 {{ await comp.element({ 286 80 title: "Metadata", 287 - items: metadata, 81 + items: elements.metadata, 288 82 content: ` 289 83 Elements that provide metadata for tracks. 290 84 ` ··· 292 86 293 87 {{ await comp.element({ 294 88 title: "Orchestrators", 295 - items: orchestrators, 89 + items: elements.orchestrators, 296 90 content: ` 297 91 These are element compositions, logic only. Mostly exist in order to construct sensible defaults. 298 92 ` ··· 300 94 301 95 {{ await comp.element({ 302 96 title: "Output", 303 - items: output, 97 + items: elements.output, 304 98 content: ` 305 99 Output is application-derived data such as playlists. These elements can receive such data and keep it around. These are categorised by the type of data they ingest, or many types in the case of polymorphic. Optionally use transformers to convert output into the expected format. 306 100 ` ··· 308 102 309 103 {{ await comp.element({ 310 104 title: "Supplements", 311 - items: supplements, 105 + items: elements.supplements, 312 106 content: ` 313 107 Additional elements, such as scrobblers. 314 108 ` ··· 316 110 317 111 {{ await comp.element({ 318 112 title: "Transformers", 319 - items: transformers, 113 + items: elements.transformers, 320 114 content: ` 321 115 Transform data from one format or schema into another. See the definitions section below for more information. Just as configurators, these are intermediates and require to have the same set of actions as the element it targets. 322 116 ` ··· 330 124 331 125 <p>All of the elements here are built with these data definitions in mind. That said, you can mix elements that use different definitions; you just have to put a transformer between them in order to translate between them, if needed.</p> 332 126 333 - {{ await comp.list({ items: definitions }) }} 127 + {{ await comp.list({ items: elements.definitions }) }} 334 128 </section> 335 129 </main> 336 130