From bb4f05e6c5c3a00ee88a4ef829e7555f7975454f Mon Sep 17 00:00:00 2001 From: Eric Fennis Date: Sun, 21 Nov 2021 20:27:15 +0100 Subject: [PATCH] lucide-static (#401) * Add lucide static * add render files * add read scripts * Add sprite generator * start with documentation * Add docs * adding documentation * fix build command * Add some extra static files * bump version * Update packages/lucide-static/README.md Co-authored-by: Kathryn Reeve <67553+BinaryKitten@users.noreply.github.com> * Fix sprite generation * update readme * Add lucide static workflow * adjust readme * Add font to release yml * Temporary turn of new versioning for lucide-static Co-authored-by: Kathryn Reeve <67553+BinaryKitten@users.noreply.github.com> --- .github/workflows/release.yml | 55 +++-- icons/alarm-clock-off.svg | 10 +- icons/list-plus.svg | 4 +- icons/piggy-bank.svg | 4 +- package.json | 1 + packages/lucide-static/.gitignore | 5 + packages/lucide-static/.npmignore | 10 + packages/lucide-static/LICENSE | 15 ++ packages/lucide-static/README.md | 196 ++++++++++++++++++ packages/lucide-static/package.json | 24 +++ packages/lucide-static/scripts/buildLib.js | 47 +++++ .../scripts/generateIconNodes.js | 13 ++ .../lucide-static/scripts/generateSprite.js | 39 ++++ packages/lucide-static/scripts/readSvgs.js | 17 ++ sprite-1.svg | 1 + yarn.lock | 14 ++ 16 files changed, 430 insertions(+), 25 deletions(-) create mode 100644 packages/lucide-static/.gitignore create mode 100644 packages/lucide-static/.npmignore create mode 100644 packages/lucide-static/LICENSE create mode 100644 packages/lucide-static/README.md create mode 100644 packages/lucide-static/package.json create mode 100644 packages/lucide-static/scripts/buildLib.js create mode 100644 packages/lucide-static/scripts/generateIconNodes.js create mode 100644 packages/lucide-static/scripts/generateSprite.js create mode 100644 packages/lucide-static/scripts/readSvgs.js create mode 100644 sprite-1.svg diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 53f97333f..54ba671d2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -37,6 +37,7 @@ jobs: with: node-version: "14" cache: yarn + cache-dependency-path: 'yarn.lock' - name: Install dependencies run: yarn --prefer-offline @@ -237,6 +238,41 @@ jobs: name: lucide-preact-package-json path: packages/lucide-preact/package.json + lucide-static: + if: github.repository == 'lucide-icons/lucide' + runs-on: ubuntu-latest + needs: [pre-build, lucide-font] + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2.4.0 + with: + node-version: "14" + cache: yarn + + - name: Install dependencies + run: yarn --prefer-offline + + - name: Set Auth Token + run: npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }} + + # - name: Set new version + # run: yarn workspace lucide-static version --new-version ${{ needs.pre-build.outputs.VERSION }} --no-git-tag-version + + - name: Move Font + run: cp -r lucide-font packages/lucide-static/font + + - name: Build + run: yarn workspace lucide-static build + + - name: Publish + run: yarn workspace lucide-static publish + + - name: Upload package.json + uses: actions/upload-artifact@v2 + with: + name: lucide-static-package-json + path: packages/lucide-static/package.json + lucide-font: if: github.repository == 'lucide-icons/lucide' runs-on: ubuntu-latest @@ -277,27 +313,14 @@ jobs: - name: Build Icon Font run: | - mkdir build - list=(-200 -300 "" -500 -600) - command='' - for name in "${list[@]}" - do - subcommand="(yarn build:outline-icons --outputDir=converted_icons${name} && fontcustom compile "./converted_icons${name}" -h -n "lucide${name}" -o ./build -F)" - if [ -z "$command" ] - then - command="$subcommand"; - else - command="$command & $subcommand"; - fi - done - - eval $command + mkdir lucide-font + yarn build:outline-icons --outputDir=converted_icons && fontcustom compile "./converted_icons" -h -n "lucide" -o ./lucide-font -F - name: "Upload to Artifacts" uses: actions/upload-artifact@v1 with: name: lucide-font - path: build + path: lucide-font lucide-flutter: if: github.repository == 'lucide-icons/lucide' diff --git a/icons/alarm-clock-off.svg b/icons/alarm-clock-off.svg index 99fbb762e..9cecaf32d 100644 --- a/icons/alarm-clock-off.svg +++ b/icons/alarm-clock-off.svg @@ -9,9 +9,9 @@ stroke-linecap="round" stroke-linejoin="round" > - - - - - + + + + + diff --git a/icons/list-plus.svg b/icons/list-plus.svg index 7794df2f4..acc00c419 100644 --- a/icons/list-plus.svg +++ b/icons/list-plus.svg @@ -12,6 +12,6 @@ - - + + diff --git a/icons/piggy-bank.svg b/icons/piggy-bank.svg index 7a243526b..54e013954 100644 --- a/icons/piggy-bank.svg +++ b/icons/piggy-bank.svg @@ -9,7 +9,7 @@ stroke-linecap="round" stroke-linejoin="round" > - - + + diff --git a/package.json b/package.json index 6c8bf32b3..c3673e887 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "lucide-preact": "yarn workspace lucide-preact", "lucide-vue": "yarn workspace lucide-vue", "lucide-vue-next": "yarn workspace lucide-vue-next", + "lucide-static": "yarn workspace lucide-static", "build:icons": "babel-node ./scripts/buildIcons.js --presets @babel/env", "build:outline-icons": "babel-node ./scripts/outlineSvg.js --presets @babel/env", "optimize": "babel-node ./scripts/optimizeSvgs.js --presets @babel/env", diff --git a/packages/lucide-static/.gitignore b/packages/lucide-static/.gitignore new file mode 100644 index 000000000..77978b18c --- /dev/null +++ b/packages/lucide-static/.gitignore @@ -0,0 +1,5 @@ +icons +lib +sprite.svg +tags.json +icon-nodes.json diff --git a/packages/lucide-static/.npmignore b/packages/lucide-static/.npmignore new file mode 100644 index 000000000..fc28543eb --- /dev/null +++ b/packages/lucide-static/.npmignore @@ -0,0 +1,10 @@ +stats +node_modules +tests +scripts +build +src +babel.config.js +jest.config.js +rollup.config.js +yarn.error.log diff --git a/packages/lucide-static/LICENSE b/packages/lucide-static/LICENSE new file mode 100644 index 000000000..66cc02207 --- /dev/null +++ b/packages/lucide-static/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2020, Lucide Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/packages/lucide-static/README.md b/packages/lucide-static/README.md new file mode 100644 index 000000000..76ec99882 --- /dev/null +++ b/packages/lucide-static/README.md @@ -0,0 +1,196 @@ +# Lucide Static + +This package include the following lucide implementations: + +- All svg files +- Javascript library containing strings of svgs. +- Icon fonts +- Svg sprite + +> What is lucide? Read it [here](https://github.com/lucide-icons/lucide#what-is-lucide). + +## Why lucide-static? + +This package is suitable for very specific use cases for example if you want to use icon fonts, svg sprites, normal svgs or Common.js Svg strings in your javascript project. + +> ⚠️ It is not recommended to use this package for svg sprites or icon fonts for web pages/applications, for prototyping it is ok. We recommend to bundlers for web applications to make sure you only bundle the used icons from this icon library (Threeshaking). Otherwise it will load all the icons, making you webpage loading slower. Threeshaking is only available in the packages: [lucide](https://github.com/lucide-icons/lucide/tree/master/packages/lucide), [lucide-react](https://github.com/lucide-icons/lucide/tree/master/packages/lucide-react), [lucide-vue](https://github.com/lucide-icons/lucide/tree/master/packages/lucide-vue), [lucide-vue-next](https://github.com/lucide-icons/lucide/tree/master/packages/lucide-vue-next), [lucide-angular](https://github.com/lucide-icons/lucide/tree/master/packages/lucide-angular), [lucide-preact](https://github.com/lucide-icons/lucide/tree/master/packages/lucide-preact) + +## Installation + +## Package Managers + +```sh +yarn add lucide-static + +# or + +npm install lucide-static +``` + +### CDN + +``` html + + + + + +``` + +## Usage + +Checkout the [codesandbox examples](https://codesandbox.io/s/using-the-svg-sprite-lz1kk). + +### SVG Files + +#### Svg file as image + +To use it in for example html: + +``` html + + +``` + +``` css +.home-icon { + background-image: url(~lucide-static/icons/home.svg) +} +``` +Make sure you have the correct webpack loaders to make this work. [url-loader](https://v4.webpack.js.org/loaders/url-loader/) + +#### Svg file Inline + +You can simply import each svg by targeting `lucide-static/icons/{icon-name}.svg`. +To use svgs in your project you can for example use a [svg loader](https://v4.webpack.js.org/loaders/svg-inline-loader/). + +```js +import arrowRightIcon from 'lucide-static/icons/arrow-right' + +// return string of a svg +``` + +### SVG Sprite + +You may need additional loader for this. + +```html + + + + + + + + + + ...sprite svg + +``` + +If you'd prefer, you can use CSS to hold your base SVG properties + +```css +.lucide-icon { + width: 24px; + height: 24px; + stroke: currentColor; + fill: none; + stroke-width: 2; + stroke-linecap: round; + stroke-linejoin: round; +} +``` + +and update the svg as follows + +```svg + + + + + ...sprite svg + +``` + +### Icon Font + +```css +@import("~lucide-static/font/Lucide.css") +``` + +```html +
+``` + + +### Node.js + +To use lucide icons in your Nodejs project you can import each icon as: + +```js +const { messageSquare } = require('lucide-static/lib') +``` + +> Note: Each icon name is in camelCase. + +#### Example in node.js project + +```js +const express = require('express') +const { messageSquare } = require('lucide-static/lib') +const app = express() +const port = 3000 + +app.get('/', (req, res) => { + res.send(` + + + + Page Title + + +

Lucide Icons

+

This is a lucide icon ${messageSquare}

+ + + + `) +}) + +app.listen(port, () => { + console.log(`Example app listening at http://localhost:${port}`) +}) +``` + +## Contributing + +For more info on how to contribute please see the [contribution guidelines](https://github.com/lucide-icons/lucide/blob/master/CONTRIBUTING.md). + +Caught a mistake or want to contribute to the documentation? [Edit this page on Github](https://github.com/lucide-icons/lucide/blob/master/README.md) + +## Community + +Join the community on our [Discord](https://discord.gg/EH6nSts) server! + +## License + +Lucide is totally free for commercial use and personally use, this software is licensed under the [ISC License](https://github.com/lucide-icons/lucide/blob/master/LICENSE). diff --git a/packages/lucide-static/package.json b/packages/lucide-static/package.json new file mode 100644 index 000000000..ccf143869 --- /dev/null +++ b/packages/lucide-static/package.json @@ -0,0 +1,24 @@ +{ + "name": "lucide-static", + "description": "Lucide is a community-run fork of Feather Icons, open for anyone to contribute icons.", + "version": "0.16.18-rc.0", + "license": "ISC", + "homepage": "https://lucide.dev", + "bugs": "https://github.com/lucide-icons/lucide/issues", + "repository": { + "type": "git", + "url": "https://github.com/lucide-icons/lucide.git" + }, + "main": "lib/index.js", + "scripts": { + "move:icons": "cp -r ../../icons icons", + "move:tags": "cp ../../tags.json tags.json", + "build": "yarn clean && yarn move:icons && yarn move:tags && yarn build:lib", + "build:lib": "yarn --cwd ../../ babel-node packages/lucide-static/scripts/buildLib.js", + "clean": "rm -rf lib && rm -rf build && rm -rf icons && rm -f sprite.svg && rm -f tags.json" + }, + "devDependencies": { + "prettier": "^2.3.2", + "svgson": "^5.2.1" + } +} diff --git a/packages/lucide-static/scripts/buildLib.js b/packages/lucide-static/scripts/buildLib.js new file mode 100644 index 000000000..49f3fe8ae --- /dev/null +++ b/packages/lucide-static/scripts/buildLib.js @@ -0,0 +1,47 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import fs from 'fs'; +import path from 'path'; +import getArgumentOptions from 'minimist'; +import { parseSync } from 'svgson'; + +// import renderIconsObject from '../../../scripts/render/renderIconsObject'; +import { appendFile, readSvgDirectory, toCamelCase } from '../../../scripts/helpers'; +import readSvgs from './readSvgs'; +import generateSprite from './generateSprite'; +import generateIconNodes from './generateIconNodes'; + +const cliArguments = getArgumentOptions(process.argv.slice(2)); +const createDirectory = dir => { + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir); + } +}; + +const PACKAGE_DIR = path.resolve(__dirname, '../'); +const ICONS_DIR = path.join(PACKAGE_DIR, 'icons'); +const LIB_DIR = path.join(PACKAGE_DIR, cliArguments.output || 'lib'); +const ICON_MODULE_DIR = path.join(LIB_DIR, 'icons'); + +createDirectory(LIB_DIR); +createDirectory(ICON_MODULE_DIR); + +const svgFiles = readSvgDirectory(ICONS_DIR); +const svgs = readSvgs(svgFiles, ICONS_DIR); + +svgs.forEach(({ name, contents }) => { + const componentName = toCamelCase(name); + const importString = `module.exports.${componentName} = require('./icons/${name}');\n`; + appendFile(importString, `index.js`, LIB_DIR); + + const exportString = `module.exports = \`${contents}\`;\n`; + appendFile(exportString, `${name}.js`, ICON_MODULE_DIR); +}); + +const parsedSvgs = svgs.map(({ name, contents }) => ({ + name, + contents, + parsedSvg: parseSync(contents), +})); + +generateSprite(parsedSvgs, PACKAGE_DIR); +generateIconNodes(parsedSvgs, PACKAGE_DIR); diff --git a/packages/lucide-static/scripts/generateIconNodes.js b/packages/lucide-static/scripts/generateIconNodes.js new file mode 100644 index 000000000..b4c1e955b --- /dev/null +++ b/packages/lucide-static/scripts/generateIconNodes.js @@ -0,0 +1,13 @@ +import { writeFile } from '../../../scripts/helpers'; + +export default function generateIconNodes(parsedSvgs, packageDir) { + const iconNodes = parsedSvgs.reduce((acc, { name, parsedSvg }) => { + acc[name] = parsedSvg.children.map(({ name, attributes }) => [name, attributes]); + + return acc; + }, {}); + + const iconNodesStringified = JSON.stringify(iconNodes, null, 2); + + writeFile(iconNodesStringified, 'icon-nodes.json', packageDir); +} diff --git a/packages/lucide-static/scripts/generateSprite.js b/packages/lucide-static/scripts/generateSprite.js new file mode 100644 index 000000000..0461b5431 --- /dev/null +++ b/packages/lucide-static/scripts/generateSprite.js @@ -0,0 +1,39 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { stringify } from 'svgson'; +import { format } from 'prettier'; +import { appendFile } from '../../../scripts/helpers'; + +export default function generateSprite(svgs, packageDir) { + const symbols = svgs.map(({ name, parsedSvg }) => ({ + name: 'symbol', + type: 'element', + attributes: { + id: name, + }, + children: parsedSvg.children, + })); + + const spriteSvgObject = { + name: 'svg', + type: 'element', + attributes: { + xmlns: 'http://www.w3.org/2000/svg', + version: '1.1', + }, + children: [ + { + name: 'defs', + type: 'element', + children: symbols, + }, + ], + }; + + const spriteSvg = stringify(spriteSvgObject); + const prettifiedSprite = format(spriteSvg, { parser: 'babel' }).replace(/;/g, ''); + + const xmlMeta = `\n`; + + appendFile(xmlMeta, `sprite.svg`, packageDir); + appendFile(prettifiedSprite, `sprite.svg`, packageDir); +} diff --git a/packages/lucide-static/scripts/readSvgs.js b/packages/lucide-static/scripts/readSvgs.js new file mode 100644 index 000000000..efd3d3bf6 --- /dev/null +++ b/packages/lucide-static/scripts/readSvgs.js @@ -0,0 +1,17 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { basename } from 'path'; +import { readSvg } from '../../../scripts/helpers'; + +/** + * Build an object in the format: `{ : }`. + * @param {string[]} svgFiles - A list of filenames. + * @param {Function} getSvg - A function that returns the contents of an SVG file given a filename. + * @returns {Object} + */ +export default (svgFiles, iconsDirectory) => + svgFiles.map(svgFile => { + const name = basename(svgFile, '.svg'); + const contents = readSvg(svgFile, iconsDirectory); + + return { name, contents }; + }); diff --git a/sprite-1.svg b/sprite-1.svg new file mode 100644 index 000000000..950ddbbd8 --- /dev/null +++ b/sprite-1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 664f11b17..9ea7c4cf1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11557,6 +11557,11 @@ prettier@1.17.1: resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.17.1.tgz#ed64b4e93e370cb8a25b9ef7fef3e4fd1c0995db" integrity sha512-TzGRNvuUSmPgwivDqkZ9tM/qTGW9hqDKWOE9YHiyQdixlKbv7kvEqsmDPrcHJTKwthU774TQwZXVtaQ/mMsvjg== +prettier@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.2.tgz#ef280a05ec253712e486233db5c6f23441e7342d" + integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ== + pretty-bytes@^5.3.0: version "5.6.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" @@ -13579,6 +13584,15 @@ svgson@^4.1.0: omit-deep "0.3.0" xml-reader "2.4.3" +svgson@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/svgson/-/svgson-5.2.1.tgz#7481fb1af4a58be542a6bd2020c168c6b71381cb" + integrity sha512-nbM6QuyZiKzQ0Uo51VDta93YJAr96ikyT40PsgJRrzynOGsOlnmJ6zAK5hUFyE5gnxcg7yuOPUWbUlmV9K0+Dg== + dependencies: + deep-rename-keys "^0.2.1" + omit-deep "0.3.0" + xml-reader "2.4.3" + symbol-observable@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-3.0.0.tgz#eea8f6478c651018e059044268375c408c15c533"