Last active
September 13, 2018 11:50
-
-
Save ivanbanov/a7c18f0ccf14ed3e1f5a3a19a3887dc7 to your computer and use it in GitHub Desktop.
ELM + SVG Store + SVGO + HTML injection
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(() => { | |
const icons = document.createElement('div'); | |
icons.innerHTML = require('images/icons.svg').match(/<svg.*<\/svg>/, '')[0]; | |
icons.style.display = 'none'; | |
document.body.appendChild(icons); | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Icon exposing (view) | |
import Html | |
import Html.Attributes | |
import Svg exposing (..) | |
import Svg.Attributes exposing (..) | |
import Icons | |
view : List (Html.Attribute msg) -> (Icons.Icons -> String) -> Html.Html msg | |
view attributes icon = | |
Html.span | |
(attributes ++ [ Html.class "icon" ] ) | |
[ svg [] | |
[ use | |
[ xlinkHref <| "#" ++ icon Icons.icons ] | |
[] | |
] | |
] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'); | |
const svgstore = require('svgstore'); | |
var SVGO = require('svgo'); | |
const ICONS_PATH = 'images/icons'; // svg icons folder | |
const ICON_MODULE_PATH = 'elm'; // export path for the elm file | |
const SRC_IMG_PATH = 'images'; // export path for the icons sprite | |
// Get all the icons | |
// ----------------------------------------------------------------------------- | |
const iconsFileName = fs.readdirSync(ICONS_PATH, 'utf-8').filter(file => /\.svg/.test(file)); | |
const icons = iconsFileName.map(icon => { | |
const file = fs.readFileSync(`${ICONS_PATH}/${icon}`, 'utf8'); | |
return { | |
name: icon.split('.')[0], | |
file, | |
}; | |
}); | |
// Generated files banner | |
// ----------------------------------------------------------------------------- | |
const warningBanner =` | |
██╗ ██╗ █████╗ ██████╗ ███╗ ██╗██╗███╗ ██╗ ██████╗ | |
██║ ██║██╔══██╗██╔══██╗████╗ ██║██║████╗ ██║██╔════╝ | |
██║ █╗ ██║███████║██████╔╝██╔██╗ ██║██║██╔██╗ ██║██║ ███╗ | |
██║███╗██║██╔══██║██╔══██╗██║╚██╗██║██║██║╚██╗██║██║ ██║ | |
╚███╔███╔╝██║ ██║██║ ██║██║ ╚████║██║██║ ╚████║╚██████╔╝ | |
╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═══╝ ╚═════╝ | |
This file is generated in runtime, any change shall be done in the script | |
webpack/scripts/icons-build.js | |
`; | |
// Read and optimize all icons and then add to the store with the icon name | |
// ----------------------------------------------------------------------------- | |
const svgo = new SVGO({ | |
plugins: [ | |
{ removeAttrs: { attrs: 'fill|stroke' } }, | |
{ removeViewBox: false }, | |
], | |
}); | |
let store = svgstore(); | |
const optimizedIcons = icons.map(icon => { | |
svgo | |
.optimize(icon.file) | |
.then(result => { | |
store.add(icon.name, result.data); | |
}); | |
}); | |
// String helpers | |
// ----------------------------------------------------------------------------- | |
function toCamelCase(str) { | |
return str.replace( | |
/[_.-](\w|$)/g, | |
(_, x) => x.toUpperCase() | |
); | |
} | |
// Create needed files and folders if it don't exist | |
// ----------------------------------------------------------------------------- | |
for (let dir of [paths.dist, SRC_IMG_PATH, ICON_MODULE_PATH]) { | |
if (!fs.existsSync(dir)) { | |
fs.mkdirSync(dir); | |
} | |
} | |
fs.writeFileSync(`${SRC_IMG_PATH}/icons.svg`, '<svg></svg>'); | |
// create Elm module UI.Icon.Icons | |
// ----------------------------------------------------------------------------- | |
const elmModuleFile = fs.readFileSync(`${paths.webpack}/scripts/ui-icons-elm-template.elm`, 'utf8'); | |
const elmIconsRecord = icons.reduce((record, icon) => { | |
record[toCamelCase(icon.name)] = icon.name; | |
return record; | |
}, {}); | |
const elmIconsTypeRecord = | |
JSON.stringify(elmIconsRecord) | |
.replace(/"/g, '') | |
.replace('{', ' ') | |
.replace(/,/g, '\n , ') | |
.replace(/:.*"?/g, ' : String') | |
+ '\n '; | |
const elmIcons = | |
JSON.stringify(elmIconsRecord) | |
.replace(/"/g, '') | |
.replace('{', ' ') | |
.replace(/,/g, '"\n , ') | |
.replace(/:/g, ' = "') | |
.replace('}', '"') | |
+ '\n '; | |
fs.writeFileSync( | |
`${ICON_MODULE_PATH}/Icons.elm`, `{-${warningBanner}-}\n\n\n` + ( | |
elmModuleFile | |
.replace('{- ICONS_TYPE_RECORD_PLACEHOLDER -}', elmIconsTypeRecord) | |
.replace('{- ICONS_PLACEHOLDER -}', elmIcons) | |
) | |
); | |
// Create the icons sprite | |
// ----------------------------------------------------------------------------- | |
Promise | |
.all(optimizedIcons) | |
.then(() => fs.writeFileSync( | |
`${SRC_IMG_PATH}/icons.svg`, | |
store.toString().replace(/(^<\?xml.*\?>)/, `$1\n<!--${warningBanner}-->\n\n\n`) | |
)); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.icon { | |
vertical-align: baseline; | |
fill: currentColor; | |
position: relative; | |
display: inline-flex; | |
} | |
.icon svg { | |
display: block; | |
overflow: visible; | |
transform: translateZ(0); | |
width: 1em; | |
height: 1em; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Icons exposing (Icons) | |
type alias Icons = | |
{{- ICONS_TYPE_RECORD_PLACEHOLDER -}} | |
icon : Icons | |
icon = | |
{{- ICONS_RECORD_PLACEHOLDER -}} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment