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

Configure Feed

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

Add ability to download a playlist as a zip file

+344 -86
+2
package.json
··· 23 23 "@tokenizer/http": "^0.4.0", 24 24 "blockstack": "https://gist.github.com/a888e02d7441aeb2af99263a3add0f73.git", 25 25 "fast-text-encoding": "^1.0.0", 26 + "file-saver": "^2.0.2", 27 + "jszip": "^3.2.2", 26 28 "lunr": "^2.3.8", 27 29 "music-metadata-browser": "^1.9.2", 28 30 "pep": "mpizenberg/elm-pep#071616d75ca61e261fdefc7b55bc46c34e44ea22",
+56
src/Applications/Brain.elm
··· 14 14 import List.Extra as List 15 15 import Maybe.Extra as Maybe 16 16 import Playlists.Encoding as Playlists 17 + import Queue 17 18 import Return2 exposing (..) 18 19 import Return3 19 20 import Settings ··· 122 123 ----------------------------------------- 123 124 -- Sources & Tracks 124 125 ----------------------------------------- 126 + | DownloadTracks Json.Value 125 127 | Process Processing.Arguments 126 128 | RemoveTracksBySourceId String 127 129 ----------------------------------------- ··· 180 182 ----------------------------------------- 181 183 -- Sources & Tracks 182 184 ----------------------------------------- 185 + DownloadTracks json -> 186 + let 187 + decoder = 188 + Json.map2 189 + Tuple.pair 190 + (Json.field "zipName" <| Json.string) 191 + (Json.field "trackIds" <| Json.list Json.string) 192 + 193 + ( zipName, trackIds ) = 194 + json 195 + |> Json.decodeValue decoder 196 + |> Result.withDefault ( "?", [] ) 197 + in 198 + model.hypaethralUserData.tracks 199 + |> Tracks.pick trackIds 200 + |> List.indexedMap Tuple.pair 201 + |> Json.Encode.list 202 + (\( idx, track ) -> 203 + Json.Encode.object 204 + [ ( "filename" 205 + , [ (idx + 1) 206 + |> String.fromInt 207 + |> String.padLeft 2 '0' 208 + , " - " 209 + , track.tags.artist 210 + , " - " 211 + , track.tags.title 212 + ] 213 + |> String.concat 214 + |> Json.Encode.string 215 + ) 216 + 217 + -- 218 + , ( "url" 219 + , track 220 + |> Queue.makeTrackUrl 221 + model.processing.currentTime 222 + model.hypaethralUserData.sources 223 + |> Json.Encode.string 224 + ) 225 + ] 226 + ) 227 + |> (\encodedTracks -> 228 + Json.Encode.object 229 + [ ( "name", Json.Encode.string zipName ) 230 + , ( "tracks", encodedTracks ) 231 + ] 232 + ) 233 + |> Brain.Ports.downloadTracks 234 + |> returnWithModel model 235 + 183 236 Process { origin, sources } -> 184 237 { origin = origin 185 238 , sources = sources ··· 547 600 ----------------------------------------- 548 601 -- From UI 549 602 ----------------------------------------- 603 + Alien.DownloadTracks -> 604 + DownloadTracks data 605 + 550 606 Alien.ImportLegacyData -> 551 607 UserLayerMsg User.RetrieveLegacyHypaethralData 552 608
+4 -1
src/Applications/Brain/Ports.elm
··· 1 - port module Brain.Ports exposing (deconstructBlockstack, deconstructRemoteStorage, fabricateSecretKey, fromAlien, handlePendingBlockstackSignIn, receiveSearchResults, receiveTags, redirectToBlockstackSignIn, removeCache, removeTracksFromCache, requestBlockstack, requestCache, requestDropbox, requestIpfs, requestLegacyLocalData, requestRemoteStorage, requestSearch, requestTags, requestTextile, savedHypaethralBit, storeTracksInCache, toBlockstack, toCache, toDropbox, toIpfs, toRemoteStorage, toTextile, toUI, updateSearchIndex) 1 + port module Brain.Ports exposing (..) 2 2 3 3 import Alien 4 4 import Json.Encode as Json ··· 7 7 8 8 9 9 -- 📣 10 + 11 + 12 + port downloadTracks : Json.Value -> Cmd msg 10 13 11 14 12 15 port fabricateSecretKey : Alien.Event -> Cmd msg
+39 -4
src/Applications/UI.elm
··· 34 34 import Notifications exposing (Notification) 35 35 import Playlists.Encoding as Playlists 36 36 import Process 37 + import Queue 37 38 import Return2 exposing (..) 38 39 import Return3 39 40 import Settings ··· 63 64 import UI.Playlists.Directory 64 65 import UI.Ports as Ports 65 66 import UI.Queue as Queue 66 - import UI.Queue.Common 67 67 import UI.Queue.ContextMenu as Queue 68 68 import UI.Reply as Reply exposing (Reply(..)) 69 69 import UI.Settings as Settings ··· 115 115 , currentTime : Time.Posix 116 116 , darkMode : Bool 117 117 , debounce : Debouncer Msg Msg 118 + , downloading : Maybe { notificationId : Int } 118 119 , focusedOnInput : Bool 119 120 , isDragging : Bool 120 121 , isLoading : Bool ··· 170 171 { contextMenu = Nothing 171 172 , currentTime = Time.millisToPosix flags.initialTime 172 173 , darkMode = flags.darkMode 174 + , downloading = Nothing 173 175 , focusedOnInput = False 174 176 , isDragging = False 175 177 , isLoading = True ··· 237 239 -- 238 240 | Blur 239 241 | Debounce (Debouncer.Msg Msg) 242 + | DownloadTracksFinished 240 243 | FocusedOnInput 241 244 | HideOverlay 242 245 | KeyboardMsg Keyboard.Msg ··· 325 328 { model = model.debounce 326 329 , msg = debouncerMsg 327 330 } 331 + 332 + DownloadTracksFinished -> 333 + case model.downloading of 334 + Just { notificationId } -> 335 + { id = notificationId } 336 + |> DismissNotification 337 + |> translateReplyWithModel { model | downloading = Nothing } 338 + 339 + Nothing -> 340 + return model 328 341 329 342 FocusedOnInput -> 330 343 return { model | focusedOnInput = True } ··· 1283 1296 |> Maybe.map 1284 1297 (.identifiedTrack >> Tuple.second) 1285 1298 |> Maybe.map 1286 - (UI.Queue.Common.makeEngineItem 1299 + (Queue.makeEngineItem 1287 1300 model.currentTime 1288 1301 model.sources.collection 1289 1302 model.tracks.cached ··· 1372 1385 |> TracksMsg 1373 1386 |> updateWithModel model 1374 1387 1388 + DownloadTracks zipName tracks -> 1389 + let 1390 + notification = 1391 + Notifications.stickyWarning "Downloading tracks ..." 1392 + 1393 + downloading = 1394 + Just { notificationId = Notifications.id notification } 1395 + in 1396 + [ ( "zipName", Json.Encode.string zipName ) 1397 + , ( "trackIds" 1398 + , tracks 1399 + |> List.map .id 1400 + |> Json.Encode.list Json.Encode.string 1401 + ) 1402 + ] 1403 + |> Json.Encode.object 1404 + |> Alien.broadcast Alien.DownloadTracks 1405 + |> Ports.toBrain 1406 + |> returnWithModel { model | downloading = downloading } 1407 + |> andThen (showNotification notification) 1408 + 1375 1409 ExternalSourceAuthorization urlBuilder -> 1376 1410 model.url 1377 1411 |> Common.urlOrigin ··· 1398 1432 item 1399 1433 |> .identifiedTrack 1400 1434 |> Tuple.second 1401 - |> UI.Queue.Common.makeEngineItem 1435 + |> Queue.makeEngineItem 1402 1436 model.currentTime 1403 1437 model.sources.collection 1404 1438 model.tracks.cached ··· 1540 1574 ) 1541 1575 , ( "url" 1542 1576 , track 1543 - |> UI.Queue.Common.makeTrackUrl 1577 + |> Queue.makeTrackUrl 1544 1578 model.currentTime 1545 1579 model.sources.collection 1546 1580 |> Json.Encode.string ··· 1824 1858 ) 1825 1859 1826 1860 -- 1861 + , Ports.downloadTracksFinished (always DownloadTracksFinished) 1827 1862 , Ports.preferredColorSchemaChanged PreferredColorSchemaChanged 1828 1863 , Ports.showErrorNotification (Notifications.error >> ShowNotification) 1829 1864 , Ports.setAverageBackgroundColor (Backdrop.BackgroundColor >> BackdropMsg)
+17 -7
src/Applications/UI/Playlists/ContextMenu.elm
··· 20 20 21 21 22 22 listMenu : Playlist -> List IdentifiedTrack -> Coordinates -> ContextMenu Reply 23 - listMenu playlist tracks = 23 + listMenu playlist allTracks = 24 + let 25 + ( identifiedTracksFromPlaylist, _ ) = 26 + Playlists.Matching.match playlist allTracks 27 + 28 + tracksFromPlaylist = 29 + identifiedTracksFromPlaylist 30 + |> List.sortBy (Tuple.first >> .indexInPlaylist >> Maybe.withDefault 0) 31 + |> List.map Tuple.second 32 + in 24 33 ContextMenu 25 34 [ Item 35 + { icon = Icons.archive 36 + , label = "Download as zip file" 37 + , msg = DownloadTracks playlist.name tracksFromPlaylist 38 + , active = False 39 + } 40 + , Item 26 41 { icon = Icons.font_download 27 42 , label = "Rename playlist" 28 43 , msg = ··· 42 57 , Item 43 58 { icon = Icons.offline_bolt 44 59 , label = "Store in cache" 45 - , msg = 46 - tracks 47 - |> Playlists.Matching.match playlist 48 - |> Tuple.first 49 - |> List.map Tuple.second 50 - |> StoreTracksInCache 60 + , msg = StoreTracksInCache tracksFromPlaylist 51 61 , active = False 52 62 } 53 63 ]
+3
src/Applications/UI/Ports.elm
··· 46 46 port activeQueueItemEnded : (() -> msg) -> Sub msg 47 47 48 48 49 + port downloadTracksFinished : (() -> msg) -> Sub msg 50 + 51 + 49 52 port fromAlien : (Alien.Event -> msg) -> Sub msg 50 53 51 54
-1
src/Applications/UI/Queue.elm
··· 26 26 import UI.Navigation exposing (..) 27 27 import UI.Page as Page 28 28 import UI.Ports as Ports 29 - import UI.Queue.Common exposing (makeItem) 30 29 import UI.Queue.Fill as Fill 31 30 import UI.Queue.Page as Queue exposing (Page(..)) 32 31 import UI.Reply exposing (Reply(..))
-53
src/Applications/UI/Queue/Common.elm
··· 1 - module UI.Queue.Common exposing (makeEngineItem, makeItem, makeTrackUrl) 2 - 3 - import Dict exposing (Dict) 4 - import List.Extra as List 5 - import Queue exposing (..) 6 - import Sources exposing (Source) 7 - import Sources.Processing exposing (HttpMethod(..)) 8 - import Sources.Services 9 - import Time 10 - import Tracks exposing (IdentifiedTrack, Track) 11 - 12 - 13 - 14 - -- 🔱 15 - 16 - 17 - makeEngineItem : Time.Posix -> List Source -> List String -> Dict String Float -> Track -> EngineItem 18 - makeEngineItem timestamp sources cachedTrackIds progressTable track = 19 - { isCached = List.member track.id cachedTrackIds 20 - , progress = Dict.get track.id progressTable 21 - , trackId = track.id 22 - , trackTags = track.tags 23 - , url = makeTrackUrl timestamp sources track 24 - } 25 - 26 - 27 - makeItem : Bool -> IdentifiedTrack -> Item 28 - makeItem isManualEntry identifiedTrack = 29 - { manualEntry = isManualEntry 30 - , identifiedTrack = identifiedTrack 31 - } 32 - 33 - 34 - makeTrackUrl : Time.Posix -> List Source -> Track -> String 35 - makeTrackUrl timestamp sources track = 36 - sources 37 - |> List.find (.id >> (==) track.sourceId) 38 - |> Maybe.map (makeTrackUrl_ timestamp track) 39 - |> Maybe.withDefault "<missing-source>" 40 - 41 - 42 - 43 - -- ㊙️ 44 - 45 - 46 - makeTrackUrl_ : Time.Posix -> Track -> Source -> String 47 - makeTrackUrl_ timestamp track source = 48 - Sources.Services.makeTrackUrl 49 - source.service 50 - timestamp 51 - source.data 52 - Get 53 - track.path
+1 -2
src/Applications/UI/Queue/Fill.elm
··· 7 7 import List.Extra as List 8 8 import Maybe.Ext as Maybe 9 9 import Maybe.Extra as Maybe 10 - import Queue exposing (Item) 10 + import Queue exposing (Item, makeItem) 11 11 import Random exposing (Generator, Seed) 12 12 import Time 13 13 import Tracks exposing (IdentifiedTrack) 14 - import UI.Queue.Common exposing (makeItem) 15 14 16 15 17 16
+1
src/Applications/UI/Reply.elm
··· 90 90 | AddSourceToCollection Source 91 91 | ClearTracksCache 92 92 | DisableTracksGrouping 93 + | DownloadTracks String (List Track) 93 94 | ExternalSourceAuthorization (String -> String) 94 95 | ForceTracksRerender 95 96 | GroupTracksBy Tracks.Grouping
+1 -1
src/Applications/UI/Tracks/ContextMenu.elm
··· 8 8 import Material.Icons.Content as Icons 9 9 import Maybe.Extra as Maybe 10 10 import Playlists exposing (Playlist) 11 + import Queue 11 12 import Sources exposing (Source) 12 13 import Time 13 14 import Tracks exposing (Grouping(..), IdentifiedTrack) 14 15 import UI.Queue as Queue 15 - import UI.Queue.Common as Queue 16 16 import UI.Reply exposing (Reply(..)) 17 17 import UI.Tracks as Tracks 18 18
+10 -10
src/Applications/UI/Tracks/Scene/List.elm
··· 132 132 -- 133 133 , C.md__text_almost_sm 134 134 135 + -- TODO 136 + -- , case maybeDnD of 137 + -- Just dnd -> 138 + -- if DnD.isDragging dnd then 139 + -- C.overflow_y_hidden 135 140 -- 136 - , case maybeDnD of 137 - Just dnd -> 138 - if DnD.isDragging dnd then 139 - C.overflow_y_hidden 140 - 141 - else 142 - C.overflow_y_auto 143 - 144 - Nothing -> 145 - C.overflow_y_auto 141 + -- else 142 + -- C.overflow_y_auto 143 + -- 144 + -- Nothing -> 145 + -- C.overflow_y_auto 146 146 ] 147 147 [ -- Shadow 148 148 ---------
+12
src/Javascript/Brain/index.js
··· 134 134 135 135 136 136 137 + // Downloading 138 + // ----------- 139 + 140 + app.ports.downloadTracks.subscribe(group => { 141 + self.postMessage({ 142 + action: "DOWNLOAD_TRACKS", 143 + data: group 144 + }) 145 + }) 146 + 147 + 148 + 137 149 // Search 138 150 // ------ 139 151
+24 -2
src/Javascript/common.js
··· 23 23 } 24 24 25 25 26 - export function mimeType(fileExtension) { 27 - switch (fileExtension) { 26 + export function fileExtension(mimeType) { 27 + const audioId = mimeType.toLowerCase().split("/")[1] 28 + 29 + switch (audioId) { 30 + case "mp3": return "mp3"; 31 + case "mpeg": return "mp3"; 32 + 33 + case "mp4a-latm": return "m4a"; 34 + case "mp4": return "m4a"; 35 + case "x-m4a": return "m4a"; 36 + 37 + case "flac": return "flac"; 38 + case "ogg": return "ogg"; 39 + 40 + case "wav": return "wav"; 41 + case "wave": return "wav"; 42 + 43 + case "webm": return "webm"; 44 + } 45 + } 46 + 47 + 48 + export function mimeType(fileExt) { 49 + switch (fileExt) { 28 50 case "mp3": return "audio/mpeg"; 29 51 case "mp4": return "audio/mp4"; 30 52 case "m4a": return "audio/mp4";
+35 -1
src/Javascript/index.js
··· 7 7 8 8 9 9 import "tocca" 10 + import JSZip from "jszip" 11 + import { saveAs } from "file-saver" 10 12 11 13 import "../../build/vendor/pep" 12 14 13 15 import * as audioEngine from "./audio-engine" 14 - import { debounce } from "./common" 16 + import { debounce, fileExtension } from "./common" 15 17 16 18 17 19 // 🍱 ··· 56 58 57 59 58 60 function handleAction(action, data) { switch (action) { 61 + case "DOWNLOAD_TRACKS": return downloadTracks(data) 59 62 case "REDIRECT_TO_BLOCKSTACK": return redirectToBlockstack(data) 60 63 }} 61 64 ··· 241 244 }) 242 245 243 246 return m 247 + } 248 + 249 + 250 + 251 + // Downloading 252 + // ----------- 253 + 254 + function downloadTracks(group) { 255 + const zip = new JSZip() 256 + const folder = zip.folder("Diffuse - " + group.name) 257 + 258 + return group.tracks.reduce( 259 + (acc, track) => { return acc 260 + .then(_ => fetch(track.url)) 261 + .then(r => { 262 + const mimeType = r.headers.get("content-type") 263 + const fileExt = fileExtension(mimeType) || "unknown" 264 + 265 + return r.blob().then( 266 + b => folder.file(track.filename + "." + fileExt, b) 267 + ) 268 + }) 269 + }, 270 + Promise.resolve() 271 + 272 + ).then(_ => zip.generateAsync({ type: "blob" }) 273 + ).then(zipFile => { 274 + saveAs(zipFile, "Diffuse - " + group.name + ".zip") 275 + app.ports.downloadTracksFinished.send(null) 276 + 277 + }) 244 278 } 245 279 246 280
+2
src/Library/Alien.elm
··· 38 38 ----------------------------------------- 39 39 -- from UI 40 40 ----------------------------------------- 41 + | DownloadTracks 41 42 | ImportLegacyData 42 43 | ProcessSources 43 44 | RedirectToBlockstackSignIn ··· 93 94 ----------------------------------------- 94 95 -- From UI 95 96 ----------------------------------------- 97 + , ( "DOWNLOAD_TRACKS", DownloadTracks ) 96 98 , ( "IMPORT_LEGACY_DATA", ImportLegacyData ) 97 99 , ( "PROCESS_SOURCES", ProcessSources ) 98 100 , ( "REDIRECT_TO_BLOCKSTACK_SIGN_IN", RedirectToBlockstackSignIn )
+51 -2
src/Library/Queue.elm
··· 1 - module Queue exposing (EngineItem, Item) 1 + module Queue exposing (EngineItem, Item, makeEngineItem, makeItem, makeTrackUrl) 2 2 3 - import Tracks exposing (IdentifiedTrack, Tags) 3 + import Dict exposing (Dict) 4 + import List.Extra as List 5 + import Sources exposing (Source) 6 + import Sources.Processing exposing (HttpMethod(..)) 7 + import Sources.Services 8 + import Time 9 + import Tracks exposing (IdentifiedTrack, Tags, Track) 4 10 5 11 6 12 ··· 20 26 , trackTags : Tags 21 27 , url : String 22 28 } 29 + 30 + 31 + 32 + -- 🔱 33 + 34 + 35 + makeEngineItem : Time.Posix -> List Source -> List String -> Dict String Float -> Track -> EngineItem 36 + makeEngineItem timestamp sources cachedTrackIds progressTable track = 37 + { isCached = List.member track.id cachedTrackIds 38 + , progress = Dict.get track.id progressTable 39 + , trackId = track.id 40 + , trackTags = track.tags 41 + , url = makeTrackUrl timestamp sources track 42 + } 43 + 44 + 45 + makeItem : Bool -> IdentifiedTrack -> Item 46 + makeItem isManualEntry identifiedTrack = 47 + { manualEntry = isManualEntry 48 + , identifiedTrack = identifiedTrack 49 + } 50 + 51 + 52 + makeTrackUrl : Time.Posix -> List Source -> Track -> String 53 + makeTrackUrl timestamp sources track = 54 + sources 55 + |> List.find (.id >> (==) track.sourceId) 56 + |> Maybe.map (makeTrackUrl_ timestamp track) 57 + |> Maybe.withDefault "<missing-source>" 58 + 59 + 60 + 61 + -- ㊙️ 62 + 63 + 64 + makeTrackUrl_ : Time.Posix -> Track -> Source -> String 65 + makeTrackUrl_ timestamp track source = 66 + Sources.Services.makeTrackUrl 67 + source.service 68 + timestamp 69 + source.data 70 + Get 71 + track.path
+53 -1
src/Library/Tracks.elm
··· 1 - module Tracks exposing (Collection, CollectionDependencies, Favourite, Grouping(..), IdentifiedTrack, Identifiers, Parcel, SortBy(..), SortDirection(..), Tags, Track, emptyCollection, emptyIdentifiedTrack, emptyIdentifiers, emptyTags, emptyTrack, isNowPlaying, makeTrack, missingId, removeByPaths, removeBySourceId, removeFromPlaylist, toPlaylistTracks) 1 + module Tracks exposing (Collection, CollectionDependencies, Favourite, Grouping(..), IdentifiedTrack, Identifiers, Parcel, SortBy(..), SortDirection(..), Tags, Track, emptyCollection, emptyIdentifiedTrack, emptyIdentifiers, emptyTags, emptyTrack, isNowPlaying, makeTrack, missingId, pick, removeByPaths, removeBySourceId, removeFromPlaylist, toPlaylistTracks) 2 2 3 3 import Base64 4 4 import List.Extra as List ··· 81 81 82 82 -- Filtered by search results, favourites, etc. 83 83 , harvested : List IdentifiedTrack 84 + 85 + -- Contexts 86 + ----------- 87 + , scrollContext : String 84 88 } 85 89 86 90 ··· 178 182 , identified = [] 179 183 , arranged = [] 180 184 , harvested = [] 185 + 186 + -- Contexts 187 + ----------- 188 + , scrollContext = "" 181 189 } 182 190 183 191 ··· 203 211 } 204 212 205 213 214 + {-| Given a collection of tracks, pick out the tracks by id in order. 215 + Note that track ids in the ids list may occur multiple times. 216 + -} 217 + pick : List String -> List Track -> List Track 218 + pick ids collection = 219 + collection 220 + |> List.foldr 221 + (\track -> 222 + List.map 223 + (\picking -> 224 + case picking of 225 + PickId id -> 226 + if id == track.id then 227 + PickTrack track 228 + 229 + else 230 + PickId id 231 + 232 + p -> 233 + p 234 + ) 235 + ) 236 + (List.map PickId ids) 237 + |> List.foldr 238 + (\picking acc -> 239 + case picking of 240 + PickId _ -> 241 + acc 242 + 243 + PickTrack track -> 244 + track :: acc 245 + ) 246 + [] 247 + 248 + 206 249 removeByPaths : { sourceId : String, paths : List String } -> List Track -> { kept : List Track, removed : List Track } 207 250 removeByPaths { sourceId, paths } tracks = 208 251 tracks ··· 269 312 , title = t.tags.title 270 313 } 271 314 ) 315 + 316 + 317 + 318 + -- ㊙️ 319 + 320 + 321 + type Pick 322 + = PickId String 323 + | PickTrack Track
+33 -1
yarn.lock
··· 1705 1705 dependencies: 1706 1706 flat-cache "^2.0.1" 1707 1707 1708 + file-saver@^2.0.2: 1709 + version "2.0.2" 1710 + resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.2.tgz#06d6e728a9ea2df2cce2f8d9e84dfcdc338ec17a" 1711 + integrity sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw== 1712 + 1708 1713 file-type@^12.4.0: 1709 1714 version "12.4.0" 1710 1715 resolved "https://registry.yarnpkg.com/file-type/-/file-type-12.4.0.tgz#a9a399459e1940d9f34b3973039958f1f36a565e" ··· 2231 2236 resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" 2232 2237 integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== 2233 2238 2239 + immediate@~3.0.5: 2240 + version "3.0.6" 2241 + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" 2242 + integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps= 2243 + 2234 2244 import-cwd@^2.0.0: 2235 2245 version "2.1.0" 2236 2246 resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" ··· 2648 2658 json-schema "0.2.3" 2649 2659 verror "1.10.0" 2650 2660 2661 + jszip@^3.2.2: 2662 + version "3.2.2" 2663 + resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.2.2.tgz#b143816df7e106a9597a94c77493385adca5bd1d" 2664 + integrity sha512-NmKajvAFQpbg3taXQXr/ccS2wcucR1AZ+NtyWp2Nq7HHVsXhcJFR8p0Baf32C2yVvBylFWVeKf+WI2AnvlPhpA== 2665 + dependencies: 2666 + lie "~3.3.0" 2667 + pako "~1.0.2" 2668 + readable-stream "~2.3.6" 2669 + set-immediate-shim "~1.0.1" 2670 + 2651 2671 kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: 2652 2672 version "3.2.2" 2653 2673 resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" ··· 2692 2712 prelude-ls "~1.1.2" 2693 2713 type-check "~0.3.2" 2694 2714 2715 + lie@~3.3.0: 2716 + version "3.3.0" 2717 + resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" 2718 + integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== 2719 + dependencies: 2720 + immediate "~3.0.5" 2721 + 2695 2722 loader-runner@^2.4.0: 2696 2723 version "2.4.0" 2697 2724 resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" ··· 3413 3440 resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" 3414 3441 integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== 3415 3442 3416 - pako@~1.0.5: 3443 + pako@~1.0.2, pako@~1.0.5: 3417 3444 version "1.0.10" 3418 3445 resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" 3419 3446 integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== ··· 4149 4176 version "2.0.0" 4150 4177 resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" 4151 4178 integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= 4179 + 4180 + set-immediate-shim@~1.0.1: 4181 + version "1.0.1" 4182 + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" 4183 + integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= 4152 4184 4153 4185 set-value@^2.0.0, set-value@^2.0.1: 4154 4186 version "2.0.1"