{"tag":"npm","articles":{"blog\/technology\/self-hosting-font-awesome-5-pro-for-yarn-npm":{"key":"blog\/technology\/self-hosting-font-awesome-5-pro-for-yarn-npm","type":"article","published":true,"meta":{"createdAt":"2020-07-27T20:05:47+02:00","publishedAt":"2020-07-27T20:05:47+02:00","group":null,"category":"blog","subcategory":"technology","slug":"self-hosting-font-awesome-5-pro-for-yarn-npm"},"content":{"en":{"slug":"self-hosting-font-awesome-5-pro-for-yarn-npm","title":"Self-hosting Font Awesome 5 Pro for yarn\/npm","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/fontawesome6_small.png\u0022 alt=\u0022Your year of Pro services for backing FA5 expire on August 1! Subscribe to the all-new Font Awesome 6 to extend your services and get the new version. Subscribe now for half the price. Just $49\/year!\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022136.66666666667\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAKCAYAAADcpvzeAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB\/ElEQVQ4jc2Tu46TMRCFvxnb\/5\/LLlBw03IRDQJKKCgoeAY6hCgpeAqejBdAFFQIKCmQENoQdkM2\/yW2h8LZTVIAKwQSR5rC42PP8fGMdG+fGoCZETM4AQOWEYIHsxIikDNkg+DKOq3WdRD+FjzAq\/eJ6cy4f9sxOTScA+8gxlI0+CIQAacQozGohEVnVEG4dK7wRIpAlRLLVPhOoe3Lmd3RtvjZkZHNCF4YDwTp3j2z9bZtkbHtjMjareLqOv8zHPPX537tpuSc7eM0Ukniwq4DM1S12Oc9y5jIOW8UMJxTvHMbQgWz7cfYxj2nwXK5xHtfvqyLgCQmk2+ICCllzIyrV\/bIOdP1PYKgTk9scap0fQ9myMqiEAKLpmFQD+j7nvF4dGpBbduxs+ORJ89f2O\/p\/x6fPu+zd\/k8cu3uI2u7npwzdRW4c\/MGANmMnDOz70eMR0OGw5qcMl2\/ZNG07H89+OPiTmF3uJ2LGebNaspq1\/HwXuDlm8SX\/enJ39dVIMbE9GCGzhSnStv1jIY1Z3bGqAoiJULwqCoxRlQVVSWlhHMKBk3bUVWBpulwsmBUC0etMR4IlYd5C\/PGiqBF73n9oTTraDRAEJq2o2k7RIXgHSkbIiuRKaEqGKAixFQa\/2A2P5VDZ8dw\/aKwOXFtD5NDQ249ePxf9NAxfgCKbvUuzuwSpgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/fontawesome6_small.png\u0022 alt=\u0022Your year of Pro services for backing FA5 expire on August 1! Subscribe to the all-new Font Awesome 6 to extend your services and get the new version. Subscribe now for half the price. Just $49\/year!\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022136.66666666667\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFour years ago I backed Font Awesome 5 on Kickstarter,\nand in return I received a license to use it and to access the pro features.\nThe license might be perpetual, but the pro features, sadly, are not \ud83d\ude22\u003C\/p\u003E\n\u003Cblockquote class=\u0022blockquote ml-4 pl-4 border-left\u0022\u003E\n\u003Cp\u003EIf you don\u0027t subscribe to a Pro plan, you won\u0027t be able to install Font Awesome Pro using npm or yarn.\u003C\/p\u003E\n\u003C\/blockquote\u003E\n\u003Cp\u003EThat\u0027s the one feature I need! And on August 1\u003Csup\u003Est\u003C\/sup\u003E it will be gone!\nMy dev setup, my deployment setup, of multiple projects,\neverything depends on fetching Font Awesome from the npm registry.\u003C\/p\u003E\n\u003Cp\u003ELuckily, there\u0027s a simple way around it \ud83d\ude09\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/fontawesome6_big.png\u0022 alt=\u0022Your year of Pro services for backing FA5 expire on August 1! Subscribe to the all-new Font Awesome 6 to extend your services and get the new version. Subscribe now for half the price. Just $49\/year!\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022273.33333333333\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAKCAYAAADcpvzeAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB\/ElEQVQ4jc2Tu46TMRCFvxnb\/5\/LLlBw03IRDQJKKCgoeAY6hCgpeAqejBdAFFQIKCmQENoQdkM2\/yW2h8LZTVIAKwQSR5rC42PP8fGMdG+fGoCZETM4AQOWEYIHsxIikDNkg+DKOq3WdRD+FjzAq\/eJ6cy4f9sxOTScA+8gxlI0+CIQAacQozGohEVnVEG4dK7wRIpAlRLLVPhOoe3Lmd3RtvjZkZHNCF4YDwTp3j2z9bZtkbHtjMjareLqOv8zHPPX537tpuSc7eM0Ukniwq4DM1S12Oc9y5jIOW8UMJxTvHMbQgWz7cfYxj2nwXK5xHtfvqyLgCQmk2+ICCllzIyrV\/bIOdP1PYKgTk9scap0fQ9myMqiEAKLpmFQD+j7nvF4dGpBbduxs+ORJ89f2O\/p\/x6fPu+zd\/k8cu3uI2u7npwzdRW4c\/MGANmMnDOz70eMR0OGw5qcMl2\/ZNG07H89+OPiTmF3uJ2LGebNaspq1\/HwXuDlm8SX\/enJ39dVIMbE9GCGzhSnStv1jIY1Z3bGqAoiJULwqCoxRlQVVSWlhHMKBk3bUVWBpulwsmBUC0etMR4IlYd5C\/PGiqBF73n9oTTraDRAEJq2o2k7RIXgHSkbIiuRKaEqGKAixFQa\/2A2P5VDZ8dw\/aKwOXFtD5NDQ249ePxf9NAxfgCKbvUuzuwSpgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/fontawesome6_big.png\u0022 alt=\u0022Your year of Pro services for backing FA5 expire on August 1! Subscribe to the all-new Font Awesome 6 to extend your services and get the new version. Subscribe now for half the price. Just $49\/year!\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022273.33333333333\u0022\u003E\u003C\/span\u003E\n                \u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/fontawesome.com\/icons?d=gallery\u0026s=brands,light\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\n                        \u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E\n                        fontawesome.com\/icons\n                    \u003C\/a\u003E\n                \u003C\/figcaption\u003E\n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFour years ago I backed Font Awesome 5 on Kickstarter,\nand in return I received a license to use it and to access the pro features.\nThe license might be perpetual, but the pro features, sadly, are not \ud83d\ude22\u003C\/p\u003E\n\u003Cblockquote class=\u0022blockquote ml-4 pl-4 border-left\u0022\u003E\n\u003Cp\u003EIf you don\u0027t subscribe to a Pro plan, you won\u0027t be able to install Font Awesome Pro using npm or yarn.\u003C\/p\u003E\n\u003C\/blockquote\u003E\n\u003Cp\u003EThat\u0027s the one feature I need! And on August 1\u003Csup\u003Est\u003C\/sup\u003E it will be gone!\nMy dev setup, my deployment setup, of multiple projects,\neverything depends on fetching Font Awesome from the npm registry.\u003C\/p\u003E\n\u003Cp\u003ELuckily, there\u0027s a simple way around it \ud83d\ude09\u003C\/p\u003E\n\u003Cp\u003EI\u0027m allowed by the license to download the project and create backups,\nbut obviously not to share it with others \u2013 so it\u0027s all done in a \u003Cstrong\u003Eprivate repository\u003C\/strong\u003E.\u003C\/p\u003E\n\u003Cp\u003EFirst, I fetched the latest version of the project:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyarn add @fortawesome\/fontawesome-pro\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EThen, I just went to \u003Ccode\u003Enode_modules\/@fortawesome\/fontawesome-pro\u003C\/code\u003E,\ninitialised a fresh git repository there and pushed it to gitlab.com\/Avris\/FontAwesomePro.\u003C\/p\u003E\n\u003Cp\u003ENow, whenever I want to use FontAwesome 5 in a project, I just go:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyarn add git+ssh:\/\/git@gitlab.com:Avris\/FontAwesomePro.git\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAnd that\u0027s it!\u003C\/p\u003E\n\u003Cp\u003EI was surprised that it\u0027s so simple.\nOf course my repository won\u0027t get automatically updated with the project,\nbut since version 5 won\u0027t be developed anymore, it doesn\u0027t matter at all.\nAnd it works like a charm!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["fontawesome","icons","web development","hosting","gitlab","git","yarn","npm"],"hasMore":true,"image":"https:\/\/avris.it\/image\/fontawesome6_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/fontawesome6_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/fontawesome6_mini.png\u0022 alt=\u0022Your year of Pro services for backing FA5 expire on August 1! Subscribe to the all-new Font Awesome 6 to extend your services and get the new version. Subscribe now for half the price. Just $49\/year!\u0022 width=\u0022240\u0022 height=\u002268.333333333333\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFour years ago I backed Font Awesome 5 on Kickstarter,\nand in return I received a license to use it and to access the pro features.\nThe license might be perpetual, but the pro features, sadly, are not \ud83d\ude22\u003C\/p\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003EIf you don\u0027t subscribe to a Pro plan, you won\u0027t be able to install Font Awesome Pro using npm or yarn.\u003C\/p\u003E\n\u003C\/blockquote\u003E\n\u003Cp\u003EThat\u0027s the one feature I need! And on August 1\u003Csup\u003Est\u003C\/sup\u003E it will be gone!\nMy dev setup, my deployment setup, of multiple projects,\neverything depends on fetching Font Awesome from the npm registry.\u003C\/p\u003E\n\u003Cp\u003ELuckily, there\u0027s a simple way around it \ud83d\ude09\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/fontawesome6_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/fontawesome6_mini.png\u0022 alt=\u0022Your year of Pro services for backing FA5 expire on August 1! Subscribe to the all-new Font Awesome 6 to extend your services and get the new version. Subscribe now for half the price. Just $49\/year!\u0022 width=\u0022240\u0022 height=\u002268.333333333333\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/fontawesome.com\/icons?d=gallery\u0026s=brands,light\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csmall\u003Efontawesome.com\/icons\u003C\/small\u003E\u003C\/a\u003E\n                \u003C\/figcaption\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFour years ago I backed Font Awesome 5 on Kickstarter,\nand in return I received a license to use it and to access the pro features.\nThe license might be perpetual, but the pro features, sadly, are not \ud83d\ude22\u003C\/p\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003EIf you don\u0027t subscribe to a Pro plan, you won\u0027t be able to install Font Awesome Pro using npm or yarn.\u003C\/p\u003E\n\u003C\/blockquote\u003E\n\u003Cp\u003EThat\u0027s the one feature I need! And on August 1\u003Csup\u003Est\u003C\/sup\u003E it will be gone!\nMy dev setup, my deployment setup, of multiple projects,\neverything depends on fetching Font Awesome from the npm registry.\u003C\/p\u003E\n\u003Cp\u003ELuckily, there\u0027s a simple way around it \ud83d\ude09\u003C\/p\u003E\n\u003Cp\u003EI\u0027m allowed by the license to download the project and create backups,\nbut obviously not to share it with others \u2013 so it\u0027s all done in a \u003Cstrong\u003Eprivate repository\u003C\/strong\u003E.\u003C\/p\u003E\n\u003Cp\u003EFirst, I fetched the latest version of the project:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyarn add @fortawesome\/fontawesome-pro\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EThen, I just went to \u003Ccode\u003Enode_modules\/@fortawesome\/fontawesome-pro\u003C\/code\u003E,\ninitialised a fresh git repository there and pushed it to gitlab.com\/Avris\/FontAwesomePro.\u003C\/p\u003E\n\u003Cp\u003ENow, whenever I want to use FontAwesome 5 in a project, I just go:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyarn add git+ssh:\/\/git@gitlab.com:Avris\/FontAwesomePro.git\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAnd that\u0027s it!\u003C\/p\u003E\n\u003Cp\u003EI was surprised that it\u0027s so simple.\nOf course my repository won\u0027t get automatically updated with the project,\nbut since version 5 won\u0027t be developed anymore, it doesn\u0027t matter at all.\nAnd it works like a charm!\u003C\/p\u003E","words":227,"readTime":null,"lang":"en"}}},"projects\/columnist":{"key":"projects\/columnist","type":"article","published":true,"meta":{"createdAt":"2019-08-26T15:07:32+02:00","publishedAt":"2019-08-26T17:48:00+02:00","group":null,"links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/columnist.avris.it\/","displayUrl":"Demo"},{"icon":"brands gitlab","colour":"secondary","url":"https:\/\/gitlab.com\/Avris\/Columnist","displayUrl":null},{"icon":"globe-europe","colour":"secondary","url":"https:\/\/www.npmjs.com\/package\/avris-columnist","displayUrl":null}],"category":"projects","subcategory":null,"slug":"columnist"},"content":{"en":{"slug":"columnist","title":"Columnist \u2013 Simple and lightweight multi-column design","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/columnist_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022244.29473684211\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACMklEQVRIicWVQXPTMBCFv5WtNMRNmik\/iekU\/iX3\/hdOHGE40XOZkDSurF0OshzHiZ0OdIZ3sawn62mfdteiqkYPIoLZ0dSr599iTTkk+otjVB4ffxKaSOGEEBqiKqvVkpn3IML729uTzf8FMnSoj5fwQhMiaooTAQQA7z3en8TyJg6JnWNbbLdb6n1NVMV7T9SICGDJSTNwTpjNrri+ri5G\/xqUE+cBIDQNaoqaUlUVmLURCiLZsfJs1H+DSYf+B04ToYfPX+DhaxrfLiAq7AKECJ6aj80DALOZxzlHjJEQGgB+fP9GXe8pipLFYs5m8xuAT\/d33N996DTMrHMaBg4NyUvzfR7o1uT1\/e9eu6Y8J5jfVXU0N8aqJXOqOso550aDm8yh0DTkrrDdbqmqipTOqboy97zbIa5gPr+CHpfWGk9Pv1iv1x3ny\/FMmexDUZUx2okQNZ7nnEvukjvXMVcWxelBxjp1H6nXJOuf93vezecHThzJ26Gktd+mhtVmzpTMEcqpZG2VAdCo3ThDRLI+na5JulI5fxARGS0QEbncGE0Sv1gsunFWz\/Ef6UrmDggh4L1vN2SyiV50KMVrdP+M3gmS9nDeeodJv5fd7pmbmzLPTLaQySqLMRJHkrpwMso5EZp4vuyLYrrKJq9MzbC2WjabDavlsqscFdclfF3XFKWnLFJ\/MXHdhWYvDirj\/asNprV\/5IkIiLBcrtLuR8kqmAll6TEdFrkcHu0eTGjl8R8MrVmKlGbrrwAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/columnist_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022244.29473684211\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI like multi-column design. Unfortunately, it\u2019s really annoying to work with. If your tiles don\u2019t all have the same height, it looks awful.\u003C\/p\u003E\n\u003Cp\u003EThat\u2019s why we have \u003Ca href=\u0022https:\/\/masonry.desandro.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Masonry\u003C\/a\u003E (and \u003Ca href=\u0022https:\/\/alternativeto.net\/software\/masonry\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E alternatives\u003C\/a\u003E) \u2013 but they all use absolute positioning, which can be problematic for lazy loading of images, dynamically adding more elements, etc. We can \u003Ca href=\u0022https:\/\/tobiasahlin.com\/blog\/masonry-with-css\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E try doing it with plain CSS\u003C\/a\u003E \u2013 alas, it either breaks the order of tiles or requires knowing the height of the container in advance.\u003C\/p\u003E\n\u003Cp\u003EBut I think I might have a solution to that: \u003Ca href=\u0022https:\/\/columnist.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E DEMO\u003C\/a\u003E\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/columnist_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022488.58947368421\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACMklEQVRIicWVQXPTMBCFv5WtNMRNmik\/iekU\/iX3\/hdOHGE40XOZkDSurF0OshzHiZ0OdIZ3sawn62mfdteiqkYPIoLZ0dSr599iTTkk+otjVB4ffxKaSOGEEBqiKqvVkpn3IML729uTzf8FMnSoj5fwQhMiaooTAQQA7z3en8TyJg6JnWNbbLdb6n1NVMV7T9SICGDJSTNwTpjNrri+ri5G\/xqUE+cBIDQNaoqaUlUVmLURCiLZsfJs1H+DSYf+B04ToYfPX+DhaxrfLiAq7AKECJ6aj80DALOZxzlHjJEQGgB+fP9GXe8pipLFYs5m8xuAT\/d33N996DTMrHMaBg4NyUvzfR7o1uT1\/e9eu6Y8J5jfVXU0N8aqJXOqOso550aDm8yh0DTkrrDdbqmqipTOqboy97zbIa5gPr+CHpfWGk9Pv1iv1x3ny\/FMmexDUZUx2okQNZ7nnEvukjvXMVcWxelBxjp1H6nXJOuf93vezecHThzJ26Gktd+mhtVmzpTMEcqpZG2VAdCo3ThDRLI+na5JulI5fxARGS0QEbncGE0Sv1gsunFWz\/Ef6UrmDggh4L1vN2SyiV50KMVrdP+M3gmS9nDeeodJv5fd7pmbmzLPTLaQySqLMRJHkrpwMso5EZp4vuyLYrrKJq9MzbC2WjabDavlsqscFdclfF3XFKWnLFJ\/MXHdhWYvDirj\/asNprV\/5IkIiLBcrtLuR8kqmAll6TEdFrkcHu0eTGjl8R8MrVmKlGbrrwAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/columnist_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022488.58947368421\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI like multi-column design. Unfortunately, it\u2019s really annoying to work with. If your tiles don\u2019t all have the same height, it looks awful.\u003C\/p\u003E\n\u003Cp\u003EThat\u2019s why we have \u003Ca href=\u0022https:\/\/masonry.desandro.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Masonry\u003C\/a\u003E (and \u003Ca href=\u0022https:\/\/alternativeto.net\/software\/masonry\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E alternatives\u003C\/a\u003E) \u2013 but they all use absolute positioning, which can be problematic for lazy loading of images, dynamically adding more elements, etc. We can \u003Ca href=\u0022https:\/\/tobiasahlin.com\/blog\/masonry-with-css\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E try doing it with plain CSS\u003C\/a\u003E \u2013 alas, it either breaks the order of tiles or requires knowing the height of the container in advance.\u003C\/p\u003E\n\u003Cp\u003EBut I think I might have a solution to that: \u003Ca href=\u0022https:\/\/columnist.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E DEMO\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003ETake a look at this graphic:\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/columnist-how_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022475.49103330487\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACAElEQVRIiZVV207jMBA9M3ZWon0Csd\/B\/\/8E8MAPIMGudgtFglawJJ7ZB8d3h4ZRk9rj4zP2GTtDIqLT5ADCSSMQmAlO5DQYABNDoVDVVXhrDBgAnAhEtHh2u6fG50Qgqo3\/4\/0Du6d941cVSIf74eFX4\/N4hQ2rq3ex2WwbHxF1seM4YrvZdJTo47fbHnaeISI6ThMoz9nLi\/8\/P2\/4iQiTc4D6cIqUbU0wKAGWOSq6hCFNvh+D9QoNNgrl7XgAXl+Bn5fNDpyIZ4JGojqcYo6W2RImsXizIQ2FnZ0B+z3QG0PuDhoVo42vpenNmxfUzeXFBXA8Agt5Vsw6R72z\/IVAlCUz9yNvt\/x9heJGlsYo\/Pw5CPQd+GAt6hiqWvjyfl+hFDbeBiJK7RPfFapavRi1L\/S\/VggodhLbRPF65ZkhoLx21fw8+PcUensDDodFheI7HoXqUitiunP+guNbCj0+Avf3wNVVoxATwTKVMiRE0WPmRqGwqKXMkIjov8+xpFL1D3NDxobhJtclq80YA1GByrpaNgwWKSKFXRNAhNu7u9SfH+1hQXjeP+P3n78lnvJvTYm\/vrn1IxUPkCm0xogIxjCmlQpZk0rHGoulIwRbtSgAvBLrb+PyeelZUcT8Sfd3eRYw1ppQfJkZxpjm9qT55eY+RYpDnDC+vpGW1ew\/BCdqPrjZC2cAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/columnist-how_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022475.49103330487\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EOur main job is to make the empty space marked with the red arrow disappear. If we can calculate its height, we can give the tile right below it a negative \u003Ccode\u003Emargin-top\u003C\/code\u003E to compensate for the height of the empty space.\u003C\/p\u003E\n\u003Cp\u003EAnd we can! All we need is to make sure that the column only has one child element. The difference between the height of the column and of that child is what we need to compensate for.\u003C\/p\u003E\n\u003Cp\u003EWe can find the tile right below from it (\u003Ccode\u003Ei + numberOfColumns\u003C\/code\u003E), give it \u003Ccode\u003Emargin-top: -${diff}px\u003C\/code\u003E et voil\u00e0!\u003C\/p\u003E\n\u003Ch3\u003ELimitations\u003C\/h3\u003E\n\u003Cp\u003EMy script does not do any maths fancier than this. If your first column contains a very tall tile A and a small tile B, and your second column only contains a small tile C, it would look nicer, if B were moved to the second column. My script doesn\u2019t do that. That\u2019s the price of simplicity.\u003C\/p\u003E\n\u003Ch3\u003EFuture work\u003C\/h3\u003E\n\u003Cp\u003ECurrent implementation relies a \u003Ccode\u003EsetInterval\u003C\/code\u003E that reapplies the layout every 300 ms. Firstly, because a couple of iterations are needed to get the final layout, and secondly, because the DOM and window can change.\u003C\/p\u003E\n\u003Cp\u003EObviously, I can get rid of both those problems. Applying the layout in a loop or in some smarter way, adding event listeners, etc.\u003C\/p\u003E\n\u003Cp\u003EBut that\u2019s a job for the next free evening \/ weekend.\u003C\/p\u003E\n\u003Cp\u003EAnyways, check out the links below and enjoy \ud83d\ude09\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["column","design","javascript","layout","library","masonry","multi-column","npm"],"hasMore":true,"image":"https:\/\/avris.it\/image\/columnist_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/columnist_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/columnist_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022122.14736842105\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI like multi-column design. Unfortunately, it\u2019s really annoying to work with. If your tiles don\u2019t all have the same height, it looks awful.\u003C\/p\u003E\n\u003Cp\u003EThat\u2019s why we have \u003Ca href=\u0022https:\/\/masonry.desandro.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Masonry\u003C\/a\u003E (and \u003Ca href=\u0022https:\/\/alternativeto.net\/software\/masonry\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E alternatives\u003C\/a\u003E) \u2013 but they all use absolute positioning, which can be problematic for lazy loading of images, dynamically adding more elements, etc. We can \u003Ca href=\u0022https:\/\/tobiasahlin.com\/blog\/masonry-with-css\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E try doing it with plain CSS\u003C\/a\u003E \u2013 alas, it either breaks the order of tiles or requires knowing the height of the container in advance.\u003C\/p\u003E\n\u003Cp\u003EBut I think I might have a solution to that: \u003Ca href=\u0022https:\/\/columnist.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E DEMO\u003C\/a\u003E\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/columnist_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/columnist_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022122.14736842105\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI like multi-column design. Unfortunately, it\u2019s really annoying to work with. If your tiles don\u2019t all have the same height, it looks awful.\u003C\/p\u003E\n\u003Cp\u003EThat\u2019s why we have \u003Ca href=\u0022https:\/\/masonry.desandro.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Masonry\u003C\/a\u003E (and \u003Ca href=\u0022https:\/\/alternativeto.net\/software\/masonry\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E alternatives\u003C\/a\u003E) \u2013 but they all use absolute positioning, which can be problematic for lazy loading of images, dynamically adding more elements, etc. We can \u003Ca href=\u0022https:\/\/tobiasahlin.com\/blog\/masonry-with-css\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E try doing it with plain CSS\u003C\/a\u003E \u2013 alas, it either breaks the order of tiles or requires knowing the height of the container in advance.\u003C\/p\u003E\n\u003Cp\u003EBut I think I might have a solution to that: \u003Ca href=\u0022https:\/\/columnist.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E DEMO\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003ETake a look at this graphic:\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/columnist-how_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/columnist-how_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022118.87275832622\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EOur main job is to make the empty space marked with the red arrow disappear. If we can calculate its height, we can give the tile right below it a negative \u003Ccode\u003Emargin-top\u003C\/code\u003E to compensate for the height of the empty space.\u003C\/p\u003E\n\u003Cp\u003EAnd we can! All we need is to make sure that the column only has one child element. The difference between the height of the column and of that child is what we need to compensate for.\u003C\/p\u003E\n\u003Cp\u003EWe can find the tile right below from it (\u003Ccode\u003Ei + numberOfColumns\u003C\/code\u003E), give it \u003Ccode\u003Emargin-top: -${diff}px\u003C\/code\u003E et voil\u00e0!\u003C\/p\u003E\n\u003Ch3\u003ELimitations\u003C\/h3\u003E\n\u003Cp\u003EMy script does not do any maths fancier than this. If your first column contains a very tall tile A and a small tile B, and your second column only contains a small tile C, it would look nicer, if B were moved to the second column. My script doesn\u2019t do that. That\u2019s the price of simplicity.\u003C\/p\u003E\n\u003Ch3\u003EFuture work\u003C\/h3\u003E\n\u003Cp\u003ECurrent implementation relies a \u003Ccode\u003EsetInterval\u003C\/code\u003E that reapplies the layout every 300 ms. Firstly, because a couple of iterations are needed to get the final layout, and secondly, because the DOM and window can change.\u003C\/p\u003E\n\u003Cp\u003EObviously, I can get rid of both those problems. Applying the layout in a loop or in some smarter way, adding event listeners, etc.\u003C\/p\u003E\n\u003Cp\u003EBut that\u2019s a job for the next free evening \/ weekend.\u003C\/p\u003E\n\u003Cp\u003EAnyways, check out the links below and enjoy \ud83d\ude09\u003C\/p\u003E","words":331,"readTime":2,"lang":"en"}}},"projects\/avris-fs":{"key":"projects\/avris-fs","type":"article","published":true,"meta":{"createdAt":"2019-01-01T18:53:52+01:00","publishedAt":"2019-01-01T18:51:00+01:00","group":null,"links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/www.npmjs.com\/package\/avris-fs","displayUrl":"npm: avris-fs"},{"icon":"brands gitlab","colour":"secondary","url":"https:\/\/gitlab.com\/Avris\/Filesystem","displayUrl":null}],"category":"projects","subcategory":null,"slug":"avris-fs"},"content":{"en":{"slug":"avris-fs","title":"avris-fs","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-fs_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHoUlEQVRIiX2Xy69lRRXGf+tRtfe595776u4LTQMNNLQCIpFgJEEDkiAQgwaNDzQhOtCBxoF\/gnNnDozGsY6IE8REoxFIIFE0PqBFIo9uumlIN933ce7r7F21HOzTF6PGyn4lu2rXV99Xa61vy\/U33B5RKkIQtUJUzJ1aCkGgIrgapkpyZzrdp9YKERCBACKCMDQRQUSA4EqLiNlZD+5ERQRUBHPHRGiaER4hRASlFiRAgFIKwvBhVR2AikKtJFX62QSIzPpx0F8EQFCV9yeXK89C1IKoEfH+OENIamgt+JUBghJUIkBDEB0mIwRVB4S+VAxBEUIUU52xMSwEGd7NjtnFcDem0w4RiBgWKKLobKyp4mYkVTxEoZYZwQMjRCAhqBpuiolgorgpEpVaK7WW4QPuw+prRdUOpFIRolaCYGl5mfVLl4EKIYhD1IKqQICZksxIfgWQACpQZ2wJiOhMBkNRzIxsibmmgejZ2d2lcadJTvZErZVSevpSQBj2S60AHL1qjf2tCVAH0iJQzTNQiukgcTbFRRMRHRIGUtGDTSqo2UCtJVQUFUPFmW\/mWRktcXmygYYSJWg8oZ4hCiFC33cDQwLHr7+ed948g0ggAaaCEEBCJGaSKckU15Tpg1nE2JVYAdWBHTVMjexOtoRiiCSanLjxyALbOxP2u46rrl5jurvDZHMLEyG7UqNy76fu47VTr7CYG4IYIgtQHURRBRFIpmQ3PDQhaSYXQg0wUVQNFcXNcTWyZ1yEZE6SRNKG1dUlPve1L7C6sszvnvwlb51+C2sWSD5E03hpgXsfuI+Xn3me5XYEFCJiAKOCCpgJpgNr7oKTG6R3ao2ZvgCKqKHmiBhujmrCzWZn4v5HPsHj3\/4Sr774d576wc9IFE4evYaola3tCZ6Nr37vu7z486e5dnGRaemo0RNRBul0Fl1p2EM5Kabg0s5Tu4LUOuShAMQQcdQSyRxVI5nTpsycO1\/\/1ud56LH7mVze4ukfPUXWEStzLSduvobtjYts7OzxwHe+QlKhnj7LB4+uMdndYa+fUmpPqR1oJblhJrgryYWUDJe5RWTaQ6kEDHsERSShYognsjptSsylxONPPMhDj90PwF+fe4lEw3hhzMJcw9alXY7f\/WE+9ei9eNvwwvd\/wtrhJTQ6NjaDvk+UGACFVFSDlB13ISXFs+AyGkPuoYCEQiiCgjhowtRJ5uSUuPPOG\/nMFz95UBI2351w6KojHDu+xvHbr+O6u25i\/vAiEcFbv3qW+VGm1AXapic3FaRSo6Pvp0TtUAPVwNzIjeNJcMZL0BciZAATQ3QZjmtCcWSWAJ\/45iMHmRng4W88yH+2iODcs39keuEiR244xP5GptteZ1E7xCpiQa0dtd9H6FETzJWUM940uI7HpMJQZ1A8lISRxclhZDUyyl13Xs+xY6v\/BeDfWy2F1379B7ZefY12XmmX5jhy67X0G\/NsnhdUpggdSCZKQqQOEZYcyxlrRvh4eUwpwIwhQ\/BwWjFalBajqcI9H7v5\/4KZXNjg1C+eZ\/reBUYNoNDt7rDzXofLlLmlhtqVIfcYqCRkJpe6Y7lFmxF+9eqIvg9qgRqKhqIYKYSE0YbSFOHkTYf\/J5DdzR3+8dxLnPvTK2TpGLV1KB0VooO6b9AoeaREUkxiJlNCTbGU0dwgqYE8wj+01rCz1zHdL0z7SimVUisSgkTFimAiHF6ZOwCxPdnl9KvnePMvr3Pu5TdoomPOC5EKTiVrJTTAAqZDrZQUJA\/cBDNBU0JyC8kgZ8gNeIs\/uvI223uVyaRjc7sy6YOtfdiZwl4H014oPfz4hz9ld3uX9YubbF\/aJJdCopCotFoZWc98ChbbynSuwjhIIbQ22AwpHeqBZcNq0HWGMabbN7RNbFyeo6NF7r\/9cCy2ib29wSq5ZUKcihOSKDhVM32FEAV1RBTXIWtnd1aXlpjubtMonDxxjM13z3FkPji6Ulg7bMzPC2fOrzPZ3aXkjuVrjvHMb37Pm+f3WWwra2tj9rvghVPbyMLyamjKiBqWEt60iBqeGzxlLDWoGrlpMU8kz7glHvr43Zw9f4nrjl7N1tYuV60sc\/70Oe647Wbq9oSLr7\/BcguHFpSVeUjak6xneb7n5J1zrJ+fcOH8JuMRuPQcuedBdv72W\/zWz36ZZmGRvkI7P8ZTg6oj5iRPiBjCUHckBCkVSuHQLSeoqxtsbG3D0hhZXmLj\/DZnNgtrS0fYH0\/Zd2E7KTkZbapUq+w1lc6WWf0ArE9eJ42Exnv6yzss3PYQXjAmO7tgienWFiLbgA5eKAYDPnghZmAqUitPPv061EI2Q0pwKgKrhfcuvI3WwlzKjJMzdmepScwlwbUwl2Gy1\/HROxY5e1mpl3oWRzBef5tbHv4Ifvn0P5l2HeqZWirejOD9fwgE8JRQVSSCqIFGIBForUjfHxj82u3jYqy\/e4Y2t7gISwuLHFpcxqOys7PJyuKYP7\/ivHN6xLsbe7z53h6jHDQ65dP9WeTwiVujlkI\/nVK7fdL8GAmhTPfQ1AzloPZ4bgEGzw1oDRRB4oqHHry4RiBUTARXwQWUSjZDNej7DqGwNnaWWuPS7mBzG4d7jsO\/AOFtP6chpFTOAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-fs_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA filesystem management abstraction layer for JavaScript.\nManage files on local filesystem, on FTP server, on Amazon S3, etc. all through the same interface.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EWarning!\u003C\/strong\u003E It\u2019s a \u003Cem\u003Every\u003C\/em\u003E early version!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-fs_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHoUlEQVRIiX2Xy69lRRXGf+tRtfe595776u4LTQMNNLQCIpFgJEEDkiAQgwaNDzQhOtCBxoF\/gnNnDozGsY6IE8REoxFIIFE0PqBFIo9uumlIN933ce7r7F21HOzTF6PGyn4lu2rXV99Xa61vy\/U33B5RKkIQtUJUzJ1aCkGgIrgapkpyZzrdp9YKERCBACKCMDQRQUSA4EqLiNlZD+5ERQRUBHPHRGiaER4hRASlFiRAgFIKwvBhVR2AikKtJFX62QSIzPpx0F8EQFCV9yeXK89C1IKoEfH+OENIamgt+JUBghJUIkBDEB0mIwRVB4S+VAxBEUIUU52xMSwEGd7NjtnFcDem0w4RiBgWKKLobKyp4mYkVTxEoZYZwQMjRCAhqBpuiolgorgpEpVaK7WW4QPuw+prRdUOpFIRolaCYGl5mfVLl4EKIYhD1IKqQICZksxIfgWQACpQZ2wJiOhMBkNRzIxsibmmgejZ2d2lcadJTvZErZVSevpSQBj2S60AHL1qjf2tCVAH0iJQzTNQiukgcTbFRRMRHRIGUtGDTSqo2UCtJVQUFUPFmW\/mWRktcXmygYYSJWg8oZ4hCiFC33cDQwLHr7+ed948g0ggAaaCEEBCJGaSKckU15Tpg1nE2JVYAdWBHTVMjexOtoRiiCSanLjxyALbOxP2u46rrl5jurvDZHMLEyG7UqNy76fu47VTr7CYG4IYIgtQHURRBRFIpmQ3PDQhaSYXQg0wUVQNFcXNcTWyZ1yEZE6SRNKG1dUlPve1L7C6sszvnvwlb51+C2sWSD5E03hpgXsfuI+Xn3me5XYEFCJiAKOCCpgJpgNr7oKTG6R3ao2ZvgCKqKHmiBhujmrCzWZn4v5HPsHj3\/4Sr774d576wc9IFE4evYaola3tCZ6Nr37vu7z486e5dnGRaemo0RNRBul0Fl1p2EM5Kabg0s5Tu4LUOuShAMQQcdQSyRxVI5nTpsycO1\/\/1ud56LH7mVze4ukfPUXWEStzLSduvobtjYts7OzxwHe+QlKhnj7LB4+uMdndYa+fUmpPqR1oJblhJrgryYWUDJe5RWTaQ6kEDHsERSShYognsjptSsylxONPPMhDj90PwF+fe4lEw3hhzMJcw9alXY7f\/WE+9ei9eNvwwvd\/wtrhJTQ6NjaDvk+UGACFVFSDlB13ISXFs+AyGkPuoYCEQiiCgjhowtRJ5uSUuPPOG\/nMFz95UBI2351w6KojHDu+xvHbr+O6u25i\/vAiEcFbv3qW+VGm1AXapic3FaRSo6Pvp0TtUAPVwNzIjeNJcMZL0BciZAATQ3QZjmtCcWSWAJ\/45iMHmRng4W88yH+2iODcs39keuEiR244xP5GptteZ1E7xCpiQa0dtd9H6FETzJWUM940uI7HpMJQZ1A8lISRxclhZDUyyl13Xs+xY6v\/BeDfWy2F1379B7ZefY12XmmX5jhy67X0G\/NsnhdUpggdSCZKQqQOEZYcyxlrRvh4eUwpwIwhQ\/BwWjFalBajqcI9H7v5\/4KZXNjg1C+eZ\/reBUYNoNDt7rDzXofLlLmlhtqVIfcYqCRkJpe6Y7lFmxF+9eqIvg9qgRqKhqIYKYSE0YbSFOHkTYf\/J5DdzR3+8dxLnPvTK2TpGLV1KB0VooO6b9AoeaREUkxiJlNCTbGU0dwgqYE8wj+01rCz1zHdL0z7SimVUisSgkTFimAiHF6ZOwCxPdnl9KvnePMvr3Pu5TdoomPOC5EKTiVrJTTAAqZDrZQUJA\/cBDNBU0JyC8kgZ8gNeIs\/uvI223uVyaRjc7sy6YOtfdiZwl4H014oPfz4hz9ld3uX9YubbF\/aJJdCopCotFoZWc98ChbbynSuwjhIIbQ22AwpHeqBZcNq0HWGMabbN7RNbFyeo6NF7r\/9cCy2ib29wSq5ZUKcihOSKDhVM32FEAV1RBTXIWtnd1aXlpjubtMonDxxjM13z3FkPji6Ulg7bMzPC2fOrzPZ3aXkjuVrjvHMb37Pm+f3WWwra2tj9rvghVPbyMLyamjKiBqWEt60iBqeGzxlLDWoGrlpMU8kz7glHvr43Zw9f4nrjl7N1tYuV60sc\/70Oe647Wbq9oSLr7\/BcguHFpSVeUjak6xneb7n5J1zrJ+fcOH8JuMRuPQcuedBdv72W\/zWz36ZZmGRvkI7P8ZTg6oj5iRPiBjCUHckBCkVSuHQLSeoqxtsbG3D0hhZXmLj\/DZnNgtrS0fYH0\/Zd2E7KTkZbapUq+w1lc6WWf0ArE9eJ42Exnv6yzss3PYQXjAmO7tgienWFiLbgA5eKAYDPnghZmAqUitPPv061EI2Q0pwKgKrhfcuvI3WwlzKjJMzdmepScwlwbUwl2Gy1\/HROxY5e1mpl3oWRzBef5tbHv4Ifvn0P5l2HeqZWirejOD9fwgE8JRQVSSCqIFGIBForUjfHxj82u3jYqy\/e4Y2t7gISwuLHFpcxqOys7PJyuKYP7\/ivHN6xLsbe7z53h6jHDQ65dP9WeTwiVujlkI\/nVK7fdL8GAmhTPfQ1AzloPZ4bgEGzw1oDRRB4oqHHry4RiBUTARXwQWUSjZDNej7DqGwNnaWWuPS7mBzG4d7jsO\/AOFtP6chpFTOAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-fs_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA filesystem management abstraction layer for JavaScript.\nManage files on local filesystem, on FTP server, on Amazon S3, etc. all through the same interface.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EWarning!\u003C\/strong\u003E It\u2019s a \u003Cem\u003Every\u003C\/em\u003E early version!\u003C\/p\u003E\n\u003Ch3\u003EExample\u003C\/h3\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eimport\u003C\/span\u003E {AvrisFilesystem} \u003Cspan class=\u0022hljs-keyword\u0022\u003Efrom\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022avris-fs\u0022\u003C\/span\u003E;\n\u003Cspan class=\u0022hljs-keyword\u0022\u003Eimport\u003C\/span\u003E {LocalAdapter} \u003Cspan class=\u0022hljs-keyword\u0022\u003Efrom\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022avris-fs\/dist\/adapter\/LocalAdapter\u0022\u003C\/span\u003E;\n\n\u003Cspan class=\u0022hljs-keyword\u0022\u003Econst\u003C\/span\u003E afs = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E AvrisFilesystem(\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E LocalAdapter(__dirname + \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\/data\/\u0027\u003C\/span\u003E)\n);\n\nafs.put(                    \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ put = create or update\u003C\/span\u003E\n    \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027dir\/subdir\/foo.txt\u0027\u003C\/span\u003E,\n     \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027OSIEM!\u0027\u003C\/span\u003E\n).then(\u003Cspan class=\u0022hljs-function\u0022\u003E(\u003Cspan class=\u0022hljs-params\u0022\u003Emeta\u003C\/span\u003E) =\u0026gt;\u003C\/span\u003E {\n    afs.read(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027dir\/subdir\/foo.txt\u0027\u003C\/span\u003E).then(\u003Cspan class=\u0022hljs-function\u0022\u003E(\u003Cspan class=\u0022hljs-params\u0022\u003Econtent\u003C\/span\u003E) =\u0026gt;\u003C\/span\u003E {\n        \u003Cspan class=\u0022hljs-built_in\u0022\u003Econsole\u003C\/span\u003E.log(content);  \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ \u0027OSIEM!\u0027\u003C\/span\u003E\n    });\n})\n\nafs.create(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027dir\/bar.txt\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027OK!\u0027\u003C\/span\u003E).then(\u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E()\u003C\/span\u003E =\u0026gt;\u003C\/span\u003E {\n    afs.list(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027dir\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-literal\u0022\u003Etrue\u003C\/span\u003E).then(\u003Cspan class=\u0022hljs-function\u0022\u003E(\u003Cspan class=\u0022hljs-params\u0022\u003Eobjects\u003C\/span\u003E) =\u0026gt;\u003C\/span\u003E {\n        \u003Cspan class=\u0022hljs-built_in\u0022\u003Econsole\u003C\/span\u003E.log(objects);\n    });\n});\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch3\u003EAvailable adapters\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ccode\u003ELocalAdapter\u003C\/code\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003EMemoryAdapter\u003C\/code\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003ENullAdapter\u003C\/code\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003ES3Adapter\u003C\/code\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003ESftpAdapter\u003C\/code\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003EBrowserStorageAdapter\u003C\/code\u003E (\u003Ccode\u003ElocalStorage\u003C\/code\u003E or \u003Ccode\u003EsessionStorage\u003C\/code\u003E)\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3\u003EAPI\u003C\/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Elist(directory: string = \u0027\u0027, recursive: boolean = false): Promise\u0026lt;{ [path: string]: Metadata }\u0026gt;;\nhas(path: string): Promise\u0026lt;boolean\u0026gt;;\ngetMetadata(path: string): Promise\u0026lt;Metadata\u0026gt;;\nread(path: string): Promise\u0026lt;Buffer\u0026gt;;\ncreate(path: string, content: Buffer): Promise\u0026lt;Metadata\u0026gt;;\nupdate(path: string, content: Buffer): Promise\u0026lt;Metadata\u0026gt;;\nput(path: string, content: Buffer): Promise\u0026lt;Metadata\u0026gt;;\nmove(path: string, newPath: string): Promise\u0026lt;Metadata\u0026gt;;\ncopy(path: string, newPath: string): Promise\u0026lt;Metadata\u0026gt;;\nremove(path: string): Promise\u0026lt;void\u0026gt;;\npublish(path: string): Promise\u0026lt;Metadata\u0026gt;;\nunpublish(path: string): Promise\u0026lt;Metadata\u0026gt;;\ncreateDir(path: string): Promise\u0026lt;Metadata\u0026gt;;\nremoveDir(path: string): Promise\u0026lt;void\u0026gt;;\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch3\u003ECredits\u003C\/h3\u003E\n\u003Cp\u003EGreatly inspired by \u003Ca href=\u0022https:\/\/flysystem.thephpleague.com\/docs\/\u0022\u003EFlysystem\u003C\/a\u003E, a similar project for PHP.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["filesystem","javascript","local","localstorage","npm","s3","sessionstorage","typescript"],"hasMore":true,"image":"https:\/\/avris.it\/image\/avris-fs_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-fs_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-fs_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA filesystem management abstraction layer for JavaScript.\nManage files on local filesystem, on FTP server, on Amazon S3, etc. all through the same interface.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EWarning!\u003C\/strong\u003E It\u2019s a \u003Cem\u003Every\u003C\/em\u003E early version!\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-fs_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-fs_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA filesystem management abstraction layer for JavaScript.\nManage files on local filesystem, on FTP server, on Amazon S3, etc. all through the same interface.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EWarning!\u003C\/strong\u003E It\u2019s a \u003Cem\u003Every\u003C\/em\u003E early version!\u003C\/p\u003E\n\u003Ch3\u003EExample\u003C\/h3\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-js\u0022\u003Eimport {AvrisFilesystem} from \u0022avris-fs\u0022;\nimport {LocalAdapter} from \u0022avris-fs\/dist\/adapter\/LocalAdapter\u0022;\n\nconst afs = new AvrisFilesystem(\n    new LocalAdapter(__dirname + \u0027\/data\/\u0027)\n);\n\nafs.put(                    \/\/ put = create or update\n    \u0027dir\/subdir\/foo.txt\u0027,\n     \u0027OSIEM!\u0027\n).then((meta) =\u0026gt; {\n    afs.read(\u0027dir\/subdir\/foo.txt\u0027).then((content) =\u0026gt; {\n        console.log(content);  \/\/ \u0027OSIEM!\u0027\n    });\n})\n\nafs.create(\u0027dir\/bar.txt\u0027, \u0027OK!\u0027).then(() =\u0026gt; {\n    afs.list(\u0027dir\u0027, true).then((objects) =\u0026gt; {\n        console.log(objects);\n    });\n});\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch3\u003EAvailable adapters\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ccode\u003ELocalAdapter\u003C\/code\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003EMemoryAdapter\u003C\/code\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003ENullAdapter\u003C\/code\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003ES3Adapter\u003C\/code\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003ESftpAdapter\u003C\/code\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003EBrowserStorageAdapter\u003C\/code\u003E (\u003Ccode\u003ElocalStorage\u003C\/code\u003E or \u003Ccode\u003EsessionStorage\u003C\/code\u003E)\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3\u003EAPI\u003C\/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Elist(directory: string = \u0027\u0027, recursive: boolean = false): Promise\u0026lt;{ [path: string]: Metadata }\u0026gt;;\nhas(path: string): Promise\u0026lt;boolean\u0026gt;;\ngetMetadata(path: string): Promise\u0026lt;Metadata\u0026gt;;\nread(path: string): Promise\u0026lt;Buffer\u0026gt;;\ncreate(path: string, content: Buffer): Promise\u0026lt;Metadata\u0026gt;;\nupdate(path: string, content: Buffer): Promise\u0026lt;Metadata\u0026gt;;\nput(path: string, content: Buffer): Promise\u0026lt;Metadata\u0026gt;;\nmove(path: string, newPath: string): Promise\u0026lt;Metadata\u0026gt;;\ncopy(path: string, newPath: string): Promise\u0026lt;Metadata\u0026gt;;\nremove(path: string): Promise\u0026lt;void\u0026gt;;\npublish(path: string): Promise\u0026lt;Metadata\u0026gt;;\nunpublish(path: string): Promise\u0026lt;Metadata\u0026gt;;\ncreateDir(path: string): Promise\u0026lt;Metadata\u0026gt;;\nremoveDir(path: string): Promise\u0026lt;void\u0026gt;;\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch3\u003ECredits\u003C\/h3\u003E\n\u003Cp\u003EGreatly inspired by \u003Ca href=\u0022https:\/\/flysystem.thephpleague.com\/docs\/\u0022\u003EFlysystem\u003C\/a\u003E, a similar project for PHP.\u003C\/p\u003E","words":238,"readTime":null,"lang":"en"}}}}}