diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f833627..e285ef9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -56,7 +56,8 @@ jobs: - name: Compressing UNIX theme run: | tar -cvzf GoogleDot-Blue.tar.gz themes/GoogleDot-Blue - tar -cvzf GoogleDot-Black.tar.gz themes/GoogleDot-Blue + tar -cvzf GoogleDot-Black.tar.gz themes/GoogleDot-Black + tar -cvzf GoogleDot-White.tar.gz themes/GoogleDot-White - name: Uploading `bitmaps` artifact uses: actions/upload-artifact@v2 @@ -76,6 +77,12 @@ jobs: name: GoogleDot-Black path: GoogleDot-Black.tar.gz + - name: Uploading `GoogleDot-White` UNIX Theme artifact + uses: actions/upload-artifact@v2 + with: + name: GoogleDot-White + path: GoogleDot-White.tar.gz + - name: Uploading `GoogleDot-Blue` Windows Theme artifact uses: actions/upload-artifact@v2 with: @@ -87,3 +94,9 @@ jobs: with: name: GoogleDot-Black-Windows path: themes/GoogleDot-Black-Windows/* + + - name: Uploading `GoogleDot-White` Windows Theme artifact + uses: actions/upload-artifact@v2 + with: + name: GoogleDot-White-Windows + path: themes/GoogleDot-White-Windows/* diff --git a/CHANGELOG.md b/CHANGELOG.md index 6141280..b13fd76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [unreleased] +## [v1.1.1] - 29 Mar 2021 + +### Added + +- **GoogleDot White** version added +- Clean `builder` cache on every build (supported in `Makefile`) +- Dynamic build using **Make variables** inside `builder/Makefile` +- **2-Space** format for `bitmapper` +- Sphinx `reST` docstring in `builder/gbpkg` + +### Changed + +- GoogleDot logo updated with white split +- Preview section updated in **[README.md](./README.md)** +- gbpkg supports **clickgen v1.1.9** +- Install `gbpkg` builder python package as user +- Removed python3 `virtualenv` commands from `builder/Makefile` + ## [v1.1.0] - 08 Mar 2021 ### Added @@ -49,7 +67,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Logo and badges - CI/CD Pipelines -[unreleased]: https://github.com/ful1e5/Google_Cursor/compare/v1.1.0...main +[unreleased]: https://github.com/ful1e5/Google_Cursor/compare/v1.1.1...main +[v1.1.1]: https://github.com/ful1e5/Google_Cursor/compare/v1.1.0...v1.1.1 [v1.1.0]: https://github.com/ful1e5/Google_Cursor/compare/v1.0.1...v1.1.0 [v1.0.1]: https://github.com/ful1e5/Google_Cursor/compare/v1.0.0...v1.0.1 [v1.0.0]: https://github.com/ful1e5/Google_Cursor/tree/v1.0.0 diff --git a/Makefile b/Makefile index 2d64842..fef206b 100644 --- a/Makefile +++ b/Makefile @@ -10,10 +10,10 @@ root_dest := $(root)/$(theme) all: clean render build unix: clean render bitmaps - @cd builder && make build_unix + @cd builder && make build_unix clean windows: clean render bitmaps - @cd builder && make build_windows + @cd builder && make build_windows clean .PHONY: all @@ -24,7 +24,7 @@ render: bitmapper svg @cd bitmapper && $(MAKE) build: bitmaps - @cd builder && $(MAKE) + @cd builder && make build clean .ONESHELL: SHELL:=/bin/bash diff --git a/README.md b/README.md index e2881ab..9fbd48f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- GoogleDot + GoogleDot

@@ -114,7 +114,13 @@ Cursor theme inspired on **google material design** for `Windows` and `Linux` wi


- BlackBlue GoogleDot Cursors 🍭 + Black GoogleDot Cursors 🍭 +

+ +

+ +
+ White GoogleDot Cursors 🍭

### Manual Install diff --git a/bitmapper/package.json b/bitmapper/package.json index 6df6d10..82e3dbd 100644 --- a/bitmapper/package.json +++ b/bitmapper/package.json @@ -1,32 +1,32 @@ { - "name": "google_cursor", - "version": "1.1.0", - "description": "🍭 Cursor theme inspired on Google", - "main": "index.js", - "repository": "git@github.com:ful1e5/Google_Cursor.git", - "author": "Kaiz Khatri", - "license": "GPL-3.0", - "private": true, - "scripts": { - "clean": "rm -rf bitmaps themes", - "dev": "nodemon src/index.ts", - "watch": "nodemon --inspect src/index.ts", - "py_install": "pip install -r requirements.txt", - "render": "npx ts-node src/index.ts", - "build": "python build.py", - "compile": "yarn clean && yarn render && yarn build" - }, - "devDependencies": { - "@types/pixelmatch": "^5.2.2", - "@types/pngjs": "^3.4.2", - "@types/puppeteer": "^5.4.2", - "nodemon": "^2.0.7", - "ts-node": "^9.1.1", - "typescript": "^4.1.3" - }, - "dependencies": { - "pixelmatch": "^5.2.1", - "pngjs": "^6.0.0", - "puppeteer": "^5.5.0" - } + "name": "google_cursor", + "version": "1.1.1", + "description": "🍭 Cursor theme inspired on Google", + "main": "index.js", + "repository": "git@github.com:ful1e5/Google_Cursor.git", + "author": "Kaiz Khatri", + "license": "GPL-3.0", + "private": true, + "scripts": { + "clean": "rm -rf bitmaps themes", + "dev": "nodemon src/index.ts", + "watch": "nodemon --inspect src/index.ts", + "py_install": "pip install -r requirements.txt", + "render": "npx ts-node src/index.ts", + "build": "python build.py", + "compile": "yarn clean && yarn render && yarn build" + }, + "devDependencies": { + "@types/pixelmatch": "^5.2.2", + "@types/pngjs": "^3.4.2", + "@types/puppeteer": "^5.4.2", + "nodemon": "^2.0.7", + "ts-node": "^9.1.1", + "typescript": "^4.1.3" + }, + "dependencies": { + "pixelmatch": "^5.2.1", + "pngjs": "^6.0.0", + "puppeteer": "^5.5.0" + } } diff --git a/bitmapper/src/config.ts b/bitmapper/src/config.ts index e56a352..ef89ae4 100644 --- a/bitmapper/src/config.ts +++ b/bitmapper/src/config.ts @@ -1,8 +1,8 @@ import { Colors } from "./core/types"; interface Config { - themeName: string; - color: Colors; + themeName: string; + color: Colors; } const black = "#000000"; @@ -10,20 +10,27 @@ const blue = "#4285F4"; const white = "#FFFFFF"; const config: Config[] = [ - { - themeName: "GoogleDot-Blue", - color: { - base: blue, - outline: white, - }, - }, - { - themeName: "GoogleDot-Black", - color: { - base: black, - outline: white, - }, - }, + { + themeName: "GoogleDot-Blue", + color: { + base: blue, + outline: white, + }, + }, + { + themeName: "GoogleDot-Black", + color: { + base: black, + outline: white, + }, + }, + { + themeName: "GoogleDot-White", + color: { + base: white, + outline: black, + }, + }, ]; export { config }; diff --git a/bitmapper/src/core/BitmapsGenerator.ts b/bitmapper/src/core/BitmapsGenerator.ts index 7a017ba..c9017a0 100644 --- a/bitmapper/src/core/BitmapsGenerator.ts +++ b/bitmapper/src/core/BitmapsGenerator.ts @@ -8,148 +8,148 @@ import { matchImages } from "./util/matchImages"; import { toHTML } from "./util/toHTML"; class BitmapsGenerator { - /** - * Generate Png files from svg code. - * @param themeName Give name, So all bitmaps files are organized in one directory. - * @param bitmapsDir `absolute` or `relative` path, Where `.png` files will store. - */ - constructor(private bitmapsDir: string) { - this.bitmapsDir = path.resolve(bitmapsDir); - this.createDir(this.bitmapsDir); - } - - /** - * Create directory if it doesn't exists. - * @param dirPath directory `absolute` path. - */ - private createDir(dirPath: string) { - if (!fs.existsSync(dirPath)) { - fs.mkdirSync(dirPath, { recursive: true }); - } - } - - /** - * Prepare headless browser. - */ - public async getBrowser(): Promise { - return await puppeteer.launch({ - ignoreDefaultArgs: ["--no-sandbox"], - headless: true, - }); - } - - private async getSvgElement( - page: Page, - content: string - ): Promise> { - if (!content) { - throw new Error(`${content} File Read error`); - } - - const html = toHTML(content); - await page.setContent(html, { timeout: 0 }); - - const svg = await page.$("#container svg"); - - if (!svg) { - throw new Error("svg element not found!"); - } - return svg; - } - - public async generateStatic(browser: Browser, content: string, key: string) { - const page = await browser.newPage(); - const svg = await this.getSvgElement(page, content); - - const out = path.resolve(this.bitmapsDir, `${key}.png`); - - await svg.screenshot({ omitBackground: true, path: out }); - await page.close(); - } - - private async screenshot( - element: ElementHandle - ): Promise { - const buffer = await element.screenshot({ - encoding: "binary", - omitBackground: true, - }); - - if (!buffer) { - throw new Error("SVG element screenshot not working"); - } - return buffer; - } - - private async stopAnimation(page: Page) { - const client = await page.target().createCDPSession(); - await client.send("Animation.setPlaybackRate", { - playbackRate: 0, - }); - } - - private async resumeAnimation(page: Page, playbackRate: number) { - const client = await page.target().createCDPSession(); - await client.send("Animation.setPlaybackRate", { - playbackRate, - }); - } - - private async saveFrameImage(key: string, frame: Buffer | string) { - const out_path = path.resolve(this.bitmapsDir, key); - fs.writeFileSync(out_path, frame); - } - - public async generateAnimated( - browser: Browser, - content: string, - key: string, - options?: { - playbackRate?: number; - diff?: number; - frameLimit?: number; - framePadding?: number; - } - ) { - const opt = Object.assign( - { playbackRate: 0.1, diff: 0, frameLimit: 300, framePadding: 4 }, - options - ); - - const page = await browser.newPage(); - const svg = await this.getSvgElement(page, content); - await this.stopAnimation(page); - - let index = 1; - let breakRendering = false; - let prevImg: Buffer | string; - - // Rendering frames till `imgN` matched to `imgN-1` (When Animation is done) - while (!breakRendering) { - if (index > opt.frameLimit) { - throw new Error("Reached the frame limit."); - } - - await this.resumeAnimation(page, opt.playbackRate); - const img: string | Buffer = await this.screenshot(svg); - await this.stopAnimation(page); - - if (index > 1) { - // @ts-ignore - const diff = matchImages(prevImg, img); - if (diff <= opt.diff) { - breakRendering = !breakRendering; - } - } - const number = frameNumber(index, opt.framePadding); - const frame = `${key}-${number}.png`; - - this.saveFrameImage(frame, img); - - prevImg = img; - ++index; - } - await page.close(); - } + /** + * Generate Png files from svg code. + * @param themeName Give name, So all bitmaps files are organized in one directory. + * @param bitmapsDir `absolute` or `relative` path, Where `.png` files will store. + */ + constructor(private bitmapsDir: string) { + this.bitmapsDir = path.resolve(bitmapsDir); + this.createDir(this.bitmapsDir); + } + + /** + * Create directory if it doesn't exists. + * @param dirPath directory `absolute` path. + */ + private createDir(dirPath: string) { + if (!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath, { recursive: true }); + } + } + + /** + * Prepare headless browser. + */ + public async getBrowser(): Promise { + return await puppeteer.launch({ + ignoreDefaultArgs: ["--no-sandbox"], + headless: true, + }); + } + + private async getSvgElement( + page: Page, + content: string + ): Promise> { + if (!content) { + throw new Error(`${content} File Read error`); + } + + const html = toHTML(content); + await page.setContent(html, { timeout: 0 }); + + const svg = await page.$("#container svg"); + + if (!svg) { + throw new Error("svg element not found!"); + } + return svg; + } + + public async generateStatic(browser: Browser, content: string, key: string) { + const page = await browser.newPage(); + const svg = await this.getSvgElement(page, content); + + const out = path.resolve(this.bitmapsDir, `${key}.png`); + + await svg.screenshot({ omitBackground: true, path: out }); + await page.close(); + } + + private async screenshot( + element: ElementHandle + ): Promise { + const buffer = await element.screenshot({ + encoding: "binary", + omitBackground: true, + }); + + if (!buffer) { + throw new Error("SVG element screenshot not working"); + } + return buffer; + } + + private async stopAnimation(page: Page) { + const client = await page.target().createCDPSession(); + await client.send("Animation.setPlaybackRate", { + playbackRate: 0, + }); + } + + private async resumeAnimation(page: Page, playbackRate: number) { + const client = await page.target().createCDPSession(); + await client.send("Animation.setPlaybackRate", { + playbackRate, + }); + } + + private async saveFrameImage(key: string, frame: Buffer | string) { + const out_path = path.resolve(this.bitmapsDir, key); + fs.writeFileSync(out_path, frame); + } + + public async generateAnimated( + browser: Browser, + content: string, + key: string, + options?: { + playbackRate?: number; + diff?: number; + frameLimit?: number; + framePadding?: number; + } + ) { + const opt = Object.assign( + { playbackRate: 0.1, diff: 0, frameLimit: 300, framePadding: 4 }, + options + ); + + const page = await browser.newPage(); + const svg = await this.getSvgElement(page, content); + await this.stopAnimation(page); + + let index = 1; + let breakRendering = false; + let prevImg: Buffer | string; + + // Rendering frames till `imgN` matched to `imgN-1` (When Animation is done) + while (!breakRendering) { + if (index > opt.frameLimit) { + throw new Error("Reached the frame limit."); + } + + await this.resumeAnimation(page, opt.playbackRate); + const img: string | Buffer = await this.screenshot(svg); + await this.stopAnimation(page); + + if (index > 1) { + // @ts-ignore + const diff = matchImages(prevImg, img); + if (diff <= opt.diff) { + breakRendering = !breakRendering; + } + } + const number = frameNumber(index, opt.framePadding); + const frame = `${key}-${number}.png`; + + this.saveFrameImage(frame, img); + + prevImg = img; + ++index; + } + await page.close(); + } } export { BitmapsGenerator }; diff --git a/bitmapper/src/core/SVGHandler/SvgDirectoryParser.ts b/bitmapper/src/core/SVGHandler/SvgDirectoryParser.ts index 65756da..516c69b 100644 --- a/bitmapper/src/core/SVGHandler/SvgDirectoryParser.ts +++ b/bitmapper/src/core/SVGHandler/SvgDirectoryParser.ts @@ -2,76 +2,76 @@ import fs from "fs"; import path from "path"; interface Svg { - key: string; - content: string; + key: string; + content: string; } class SvgDirectoryParser { - /** - * Manage and Parse SVG file path in `absolute` fashion. - * This Parser look svg files as below fashion: - * ` - * <@svgDir>/static - * <@svgDir>/animated - * ` - * @param svgDir is relative/absolute path, Where `SVG` files are stored. - */ - semiAnimated: boolean = false; - constructor(private svgDir: string) { - if (!fs.existsSync(this.svgDir)) { - throw new Error(`SVG files not found in ${this.svgDir}`); - } - } + /** + * Manage and Parse SVG file path in `absolute` fashion. + * This Parser look svg files as below fashion: + * ` + * <@svgDir>/static + * <@svgDir>/animated + * ` + * @param svgDir is relative/absolute path, Where `SVG` files are stored. + */ + semiAnimated: boolean = false; + constructor(private svgDir: string) { + if (!fs.existsSync(this.svgDir)) { + throw new Error(`SVG files not found in ${this.svgDir}`); + } + } - private readData(f: string): Svg { - const content = fs.readFileSync(f, "utf-8"); - const key = path.basename(f, ".svg"); - return { content, key }; - } + private readData(f: string): Svg { + const content = fs.readFileSync(f, "utf-8"); + const key = path.basename(f, ".svg"); + return { content, key }; + } - /** - * Return absolute paths array of SVG files data located inside '@svgDir/static' - */ - public getStatic(): Svg[] { - const staticDir = path.resolve(this.svgDir, "static"); + /** + * Return absolute paths array of SVG files data located inside '@svgDir/static' + */ + public getStatic(): Svg[] { + const staticDir = path.resolve(this.svgDir, "static"); - if (!fs.existsSync(staticDir)) { - console.log(`${this.svgDir} contains semi-animated .svg files`); - this.semiAnimated = true; - return []; - } else { - const svgs = fs - .readdirSync(staticDir) - .map((f) => this.readData(path.resolve(staticDir, f))); + if (!fs.existsSync(staticDir)) { + console.log(`${this.svgDir} contains semi-animated .svg files`); + this.semiAnimated = true; + return []; + } else { + const svgs = fs + .readdirSync(staticDir) + .map((f) => this.readData(path.resolve(staticDir, f))); - if (svgs.length == 0) { - throw new Error("Static Cursors directory is empty"); - } - return svgs; - } - } - /** - * Return absolute paths array of SVG files data located inside '@svgDir/animated' - */ - public getAnimated(): Svg[] { - const animatedDir = path.resolve(this.svgDir, "animated"); + if (svgs.length == 0) { + throw new Error("Static Cursors directory is empty"); + } + return svgs; + } + } + /** + * Return absolute paths array of SVG files data located inside '@svgDir/animated' + */ + public getAnimated(): Svg[] { + const animatedDir = path.resolve(this.svgDir, "animated"); - if (!fs.existsSync(animatedDir)) { - throw new Error("Animated Cursors directory not found"); - } + if (!fs.existsSync(animatedDir)) { + throw new Error("Animated Cursors directory not found"); + } - const svgs = fs - .readdirSync(animatedDir) - .map((f) => this.readData(path.resolve(animatedDir, f))); + const svgs = fs + .readdirSync(animatedDir) + .map((f) => this.readData(path.resolve(animatedDir, f))); - if (svgs.length == 0 && this.semiAnimated) { - throw new Error( - `Can't parse svg directory ${this.svgDir} as semi-animated theme` - ); - } + if (svgs.length == 0 && this.semiAnimated) { + throw new Error( + `Can't parse svg directory ${this.svgDir} as semi-animated theme` + ); + } - return svgs; - } + return svgs; + } } export { SvgDirectoryParser }; diff --git a/bitmapper/src/core/SVGHandler/colorSvg.ts b/bitmapper/src/core/SVGHandler/colorSvg.ts index 148dcd2..49a0b50 100644 --- a/bitmapper/src/core/SVGHandler/colorSvg.ts +++ b/bitmapper/src/core/SVGHandler/colorSvg.ts @@ -7,11 +7,11 @@ import { Colors } from "../types"; * watch.background="#FF0000" (Red) * */ const defaultKeyColors: Colors = { - base: "#00FF00", - outline: "#0000FF", - watch: { - background: "#FF0000", - }, + base: "#00FF00", + outline: "#0000FF", + watch: { + background: "#FF0000", + }, }; /** @@ -22,31 +22,31 @@ const defaultKeyColors: Colors = { * @returns {string} SVG code with colors. */ const colorSvg = ( - content: string, - colors: Colors, - keys: Colors = defaultKeyColors + content: string, + colors: Colors, + keys: Colors = defaultKeyColors ): string => { - content = content - .replace(new RegExp(keys.base, "ig"), colors.base) - .replace(new RegExp(keys.outline, "ig"), colors.outline); + content = content + .replace(new RegExp(keys.base, "ig"), colors.base) + .replace(new RegExp(keys.outline, "ig"), colors.outline); - try { - // === trying to replace `watch` color === + try { + // === trying to replace `watch` color === - if (!colors.watch?.background) { - throw new Error(""); - } - const { background: b } = colors.watch; - content = content.replace(new RegExp(keys.watch!.background, "ig"), b); // Watch Background - } catch (error) { - // === on error => replace `watch` color as `base` === + if (!colors.watch?.background) { + throw new Error(""); + } + const { background: b } = colors.watch; + content = content.replace(new RegExp(keys.watch!.background, "ig"), b); // Watch Background + } catch (error) { + // === on error => replace `watch` color as `base` === - content = content.replace( - new RegExp(keys.watch!.background, "ig"), - colors.base - ); - } - return content; + content = content.replace( + new RegExp(keys.watch!.background, "ig"), + colors.base + ); + } + return content; }; export { colorSvg }; diff --git a/bitmapper/src/core/types.ts b/bitmapper/src/core/types.ts index cd5ddb3..da9fb1c 100644 --- a/bitmapper/src/core/types.ts +++ b/bitmapper/src/core/types.ts @@ -10,11 +10,11 @@ type HexColor = string; * @default background is `base` color. */ type Colors = { - base: HexColor; - outline: HexColor; - watch?: { - background: HexColor; - }; + base: HexColor; + outline: HexColor; + watch?: { + background: HexColor; + }; }; export { Colors }; diff --git a/bitmapper/src/core/util/matchImages.ts b/bitmapper/src/core/util/matchImages.ts index 625d2bd..6d09a95 100644 --- a/bitmapper/src/core/util/matchImages.ts +++ b/bitmapper/src/core/util/matchImages.ts @@ -2,10 +2,10 @@ import Pixelmatch from "pixelmatch"; import { PNG } from "pngjs"; export const matchImages = (img1: Buffer, img2: Buffer): number => { - const { data: img1Data, width, height } = PNG.sync.read(img1); - const { data: imgNData } = PNG.sync.read(img2); + const { data: img1Data, width, height } = PNG.sync.read(img1); + const { data: imgNData } = PNG.sync.read(img2); - return Pixelmatch(img1Data, imgNData, null, width, height, { - threshold: 0.1, - }); + return Pixelmatch(img1Data, imgNData, null, width, height, { + threshold: 0.1, + }); }; diff --git a/bitmapper/src/core/util/toHTML.ts b/bitmapper/src/core/util/toHTML.ts index aecb3d7..36fbbf4 100644 --- a/bitmapper/src/core/util/toHTML.ts +++ b/bitmapper/src/core/util/toHTML.ts @@ -16,4 +16,4 @@ export const template = ` `; export const toHTML = (svgData: string): string => - template.replace("", svgData); + template.replace("", svgData); diff --git a/bitmapper/src/index.ts b/bitmapper/src/index.ts index 75dbfdc..7873c9e 100644 --- a/bitmapper/src/index.ts +++ b/bitmapper/src/index.ts @@ -7,31 +7,31 @@ const root = path.resolve(__dirname, "../../"); const svgDir = path.resolve(root, "svg"); const main = async () => { - for (const { themeName, color } of config) { - console.log("=>", themeName); + for (const { themeName, color } of config) { + console.log("=>", themeName); - const bitmapsDir = path.resolve(root, "bitmaps", themeName); - const svg = new SVGHandler.SvgDirectoryParser(svgDir); + const bitmapsDir = path.resolve(root, "bitmaps", themeName); + const svg = new SVGHandler.SvgDirectoryParser(svgDir); - const png = new BitmapsGenerator(bitmapsDir); - const browser = await png.getBrowser(); + const png = new BitmapsGenerator(bitmapsDir); + const browser = await png.getBrowser(); - for (let { key, content } of svg.getStatic()) { - console.log(" -> Saving", key, "..."); + for (let { key, content } of svg.getStatic()) { + console.log(" -> Saving", key, "..."); - content = SVGHandler.colorSvg(content, color); - await png.generateStatic(browser, content, key); - } + content = SVGHandler.colorSvg(content, color); + await png.generateStatic(browser, content, key); + } - for (let { key, content } of svg.getAnimated()) { - console.log(" -> Saving", key, "..."); + for (let { key, content } of svg.getAnimated()) { + console.log(" -> Saving", key, "..."); - content = SVGHandler.colorSvg(content, color); - await png.generateAnimated(browser, content, key); - } + content = SVGHandler.colorSvg(content, color); + await png.generateAnimated(browser, content, key); + } - await browser.close(); - } + await browser.close(); + } }; main(); diff --git a/bitmapper/yarn.lock b/bitmapper/yarn.lock index df97966..da4af69 100644 --- a/bitmapper/yarn.lock +++ b/bitmapper/yarn.lock @@ -15,9 +15,9 @@ defer-to-connect "^1.0.1" "@types/node@*": - version "14.14.22" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.22.tgz#0d29f382472c4ccf3bd96ff0ce47daf5b7b84b18" - integrity sha512-g+f/qj/cNcqKkc3tFqlXOYjrmZA+jNBiDzbP3kH+B+otKFqAdPgVTGP1IeKRdMml/aE69as5S4FqtxAbl+LaMw== + version "14.14.37" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.37.tgz#a3dd8da4eb84a996c36e331df98d82abd76b516e" + integrity sha512-XYmBiy+ohOR4Lh5jE379fV2IU+6Jn4g5qASinhitfyO71b/sCo6MKsMLF5tc7Zf2CE8hViVQyYSobJNke8OvUw== "@types/pixelmatch@^5.2.2": version "5.2.2" @@ -34,9 +34,9 @@ "@types/node" "*" "@types/puppeteer@^5.4.2": - version "5.4.2" - resolved "https://registry.yarnpkg.com/@types/puppeteer/-/puppeteer-5.4.2.tgz#80f3a1f54dedbbf750779716de81401549062072" - integrity sha512-yjbHoKjZFOGqA6bIEI2dfBE5UPqU0YGWzP+ipDVP1iGzmlhksVKTBVZfT3Aj3wnvmcJ2PQ9zcncwOwyavmafBw== + version "5.4.3" + resolved "https://registry.yarnpkg.com/@types/puppeteer/-/puppeteer-5.4.3.tgz#cdca84aa7751d77448d8a477dbfa0af1f11485f2" + integrity sha512-3nE8YgR9DIsgttLW+eJf6mnXxq8Ge+27m5SU3knWmrlfl6+KOG0Bf9f7Ua7K+C4BnaTMAh3/UpySqdAYvrsvjg== dependencies: "@types/node" "*" @@ -110,9 +110,9 @@ binary-extensions@^2.0.0: integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== bl@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.3.tgz#12d6287adc29080e22a705e5764b2a9522cdc489" - integrity sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg== + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== dependencies: buffer "^5.5.0" inherits "^2.0.4" @@ -393,9 +393,9 @@ fs.realpath@^1.0.0: integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@~2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.1.tgz#b209ab14c61012636c8863507edf7fb68cc54e9f" - integrity sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw== + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== get-stream@^4.1.0: version "4.1.0" @@ -412,9 +412,9 @@ get-stream@^5.1.0: pump "^3.0.0" glob-parent@~5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" - integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" @@ -455,9 +455,9 @@ got@^9.6.0: url-parse-lax "^3.0.0" graceful-fs@^4.1.2: - version "4.2.4" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" - integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + version "4.2.6" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" + integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== has-flag@^3.0.0: version "3.0.0" @@ -590,9 +590,9 @@ is-obj@^2.0.0: integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== is-path-inside@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" - integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg== + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== is-typedarray@^1.0.0: version "1.0.0" @@ -969,9 +969,9 @@ string-width@^3.0.0: strip-ansi "^5.1.0" string-width@^4.0.0, string-width@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + version "4.2.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" + integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" @@ -1092,9 +1092,9 @@ typedarray-to-buffer@^3.1.5: is-typedarray "^1.0.0" typescript@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7" - integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== + version "4.2.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.3.tgz#39062d8019912d43726298f09493d598048c1ce3" + integrity sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw== unbzip2-stream@^1.3.3: version "1.4.3" @@ -1172,9 +1172,9 @@ write-file-atomic@^3.0.0: typedarray-to-buffer "^3.1.5" ws@^7.2.3: - version "7.4.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.2.tgz#782100048e54eb36fe9843363ab1c68672b261dd" - integrity sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA== + version "7.4.4" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.4.tgz#383bc9742cb202292c9077ceab6f6047b17f2d59" + integrity sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw== xdg-basedir@^4.0.0: version "4.0.0" diff --git a/builder/Makefile b/builder/Makefile index 11b0def..f4cd129 100644 --- a/builder/Makefile +++ b/builder/Makefile @@ -7,6 +7,7 @@ all: clean setup build .ONESHELL: SHELL:=/bin/bash +THEMES = Blue Black White X_SIZES ?=22 24 28 32 40 48 56 64 72 80 88 96 WIN_CANVAS_SIZE ?= 32 WIN_SIZE ?= 24 @@ -22,18 +23,13 @@ clean: @fi setup: setup.py - @test -d venv || python3 -m venv venv - @. venv/bin/activate; python3 setup.py install --record files.txt + @python3 setup.py install --user --record files.txt build: setup build.py - @. venv/bin/activate; python3 build.py -p "$(bitmaps_dir)/GoogleDot-Blue" --xsizes $(X_SIZES) --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE) - @. venv/bin/activate; python3 build.py -p "$(bitmaps_dir)/GoogleDot-Black" --xsizes $(X_SIZES) --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE) + @$(foreach theme,$(THEMES), python3 build.py -p "$(bitmaps_dir)/GoogleDot-$(theme)" --xsizes $(X_SIZES) --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE);) build_unix: setup build.py - @. venv/bin/activate; python3 build.py unix -p "$(bitmaps_dir)/GoogleDot-Blue" --xsizes $(X_SIZES) - @. venv/bin/activate; python3 build.py unix -p "$(bitmaps_dir)/GoogleDot-Black" --xsizes $(X_SIZES) + @$(foreach theme,$(THEMES), python3 build.py unix -p "$(bitmaps_dir)/GoogleDot-$(theme)" --xsizes $(X_SIZES);) build_windows: setup build.py - @. venv/bin/activate; python3 build.py windows -p "$(bitmaps_dir)/GoogleDot-Blue" --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE) - @. venv/bin/activate; python3 build.py windows -p "$(bitmaps_dir)/GoogleDot-Black" --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE) - + @$(foreach theme,$(THEMES), python3 build.py windows -p "$(bitmaps_dir)/GoogleDot-$(theme)" --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE);) diff --git a/builder/gbpkg/configure.py b/builder/gbpkg/configure.py index 0e7309d..5dfe5ee 100644 --- a/builder/gbpkg/configure.py +++ b/builder/gbpkg/configure.py @@ -16,31 +16,25 @@ def to_tuple(x: X) -> Tuple[X, X]: def get_config(bitmaps_dir, **kwargs) -> Dict[str, Any]: """Return configuration of `GoogleDot` pointers. - ``` - Args: - - :bitmaps_dir: (str | Path) Path to .png file's directory. - - Keywords Args: + :param bitmaps_dir: Path to .png file's directory. + :type bitmaps_dir: Union[str, Path] - :x_sizes: (List[int]) List of pixel-sizes for xcursors. + :param \**kwargs: + See below - :win_canvas_size: (int) Windows cursor's canvas pixel-size. - - :win_size: (int) Pixel-size for Windows cursor. - - ``` + :Keyword Arguments: + * *x_sizes* (``List[int]``) -- + List of pixel-sizes for xcursors. + * *win_canvas_size* (``int``) -- + Windows cursor's canvas pixel-size. + * *win_size* (``int``) -- + Pixel-size for Windows cursor. Example: ```python - get_config( - "./bitmaps", - x_sizes=[(24, 24), (32, 32)], - win_canvas_size=(32, 32), - win_size=(24, 24), - ) + get_config("./bitmaps", x_sizes=[24, 32], win_canvas_size=32, win_size=24) ``` """ diff --git a/builder/gbpkg/generator.py b/builder/gbpkg/generator.py index c82830d..3820762 100644 --- a/builder/gbpkg/generator.py +++ b/builder/gbpkg/generator.py @@ -19,14 +19,16 @@ class Info(NamedTuple): def xbuild(config: Dict[str, Dict[str, Any]], x_out_dir: Path, info: Info) -> None: """Build `GoogleDot` cursor theme for only `X11`(UNIX) platform. - ``` - :config: (Dict) `GoogleDot` configuration. - - :x_out_dir: (Path) Path to the output directory, - Where the `X11` cursor theme package will generate. - It also creates a directory if not exists. - :info: (Dict) Content theme name & comment - ``` + :param config: `GoogleDot` configuration. + :type config: Dict + + :param x_out_dir: Path to the output directory,\ + Where the `X11` cursor theme package will generate.\ + It also creates a directory if not exists. + :type x_out_dir: Path + + :param info: Content theme name & comment + :type info: Info """ for _, item in config.items(): @@ -47,14 +49,16 @@ def xbuild(config: Dict[str, Dict[str, Any]], x_out_dir: Path, info: Info) -> No def wbuild(config: Dict[str, Dict[str, Any]], win_out_dir: Path, info: Info) -> None: """Build `GoogleDot` cursor theme for only `Windows` platforms. - ``` - :config: (Dict) `GoogleDot` configuration. + :param config: `GoogleDot` configuration. + :type config: Dict - :win_out_dir: (Path) Path to the output directory, - Where the `Windows` cursor theme package will generate. - It also creates a directory if not exists. - :info: (Dict) Content theme name & comment - ``` + :param win_out_dir: Path to the output directory,\ + Where the `Windows` cursor theme package will generate.\ + It also creates a directory if not exists. + :type win_out_dir: Path + + :param info: Content theme name & comment + :type info: Info """ for _, item in config.items(): @@ -87,18 +91,21 @@ def build( ) -> None: """Build `GoogleDot` cursor theme for `X11` & `Windows` platforms. - ``` - :config: (Dict) `GoogleDot` configuration. + :param config: `GoogleDot` configuration. + :type config: Dict + + :param x_out_dir: Path to the output directory,\ + Where the `X11` cursor theme package will generate.\ + It also creates a directory if not exists. + :type x_out_dir: Path - :x_out_dir: (Path) Path to the output directory, - Where the `X11` cursor theme package will generate. - It also creates a directory if not exists. + :param win_out_dir: Path to the output directory,\ + Where the `Windows` cursor theme package will generate.\ + It also creates a directory if not exists. + :type win_out_dir: Path - :win_out_dir: (Path) Path to the output directory, - Where the `Windows` cursor theme package will generate. - It also creates a directory if not exists. - :info: (Dict) Content theme name & comment - ``` + :param info: Content theme name & comment + :type info: Info """ def win_build(item: Dict[str, Any], alias: CursorAlias) -> None: diff --git a/builder/gbpkg/symlinks.py b/builder/gbpkg/symlinks.py index b745d69..d80480d 100644 --- a/builder/gbpkg/symlinks.py +++ b/builder/gbpkg/symlinks.py @@ -10,7 +10,8 @@ def add_missing_xcursor(directory) -> None: """Add missing `XCursor` to the Unix cursor package. - :directory: (Path|str) directory where XCursors are available. + :param directory: directory where XCursors are available. + :type directory: Union[str, Path] """ symlinks: List[Dict[str, Union[str, List[str]]]] = [ @@ -181,7 +182,7 @@ def add_missing_xcursor(directory) -> None: with chdir(directory): for item in symlinks: - src = item.get("src") + src = str(item["src"]) for link in item.get("links"): print(f"Creating symlink {src} -> {link}") os.symlink(src, link) diff --git a/builder/setup.py b/builder/setup.py index b0e6efb..2168891 100644 --- a/builder/setup.py +++ b/builder/setup.py @@ -5,14 +5,14 @@ setup( name="gbpkg", - version="1.1.0", + version="1.1.1", description="Generate 'GoogleDot' cursor theme from PNGs file", url="https://github.com/ful1e5/Google_Cursor", packages=["gbpkg"], package_dir={"gbpkg": "gbpkg"}, author="Kaiz Khatri", author_email="kaizmandhu@gamil.com", - install_requires=["clickgen==1.1.8"], + install_requires=["clickgen==1.1.9"], classifiers=[ "Programming Language :: Python :: 3", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",