Merge pull request #96 from ful1e5/dev

Bibata v1.1.1
This commit is contained in:
Kaiz Khatri 2021-03-26 11:10:46 +05:30 committed by GitHub
commit 1d04c411fb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 512 additions and 543 deletions

View file

@ -7,13 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [unreleased] ## [unreleased]
## [Bibata v1.1.1] - 26 Mar 2021
### Added
- use `clickgen.packagers` for packaging **X11/UNIX** cursors
- typing supports from `clickgen` (v1.1.9)
- Set clickgen version to v1.1.9 inside `builder/setup.py`
- `Pillow` version locked at **8.1.1** by clickgen **v1.1.9**
- **2 Space** format in `bitmapper`
- Sphinx based docsstring in `builder/bbpkg`
### Changed ### Changed
- Clean builder cache on every `make` commands
- Bibata builder `bbpkg` install as system level
- Removed python3 virtual environment from `builder/Makefile`
- **clean** target fixed in `builder/Makefile`
- Bibata Rainbow packages move to [own](https://github.com/ful1e5/Bibata_Cursor_Rainbow) repo - Bibata Rainbow packages move to [own](https://github.com/ful1e5/Bibata_Cursor_Rainbow) repo
- puppeteer `svg` element timeout fixed - puppeteer `svg` element timeout fixed
- optional options typing in `BitmapGenerator.ts` - optional options typing in `BitmapGenerator.ts`
- Format `svg` files - Format `svg` files
- Remove old username of author with Contributors table - Remove old username of an author with Contributors table
## [Bibata v1.1.0] - 26 Feb 2021 ## [Bibata v1.1.0] - 26 Feb 2021
@ -180,7 +195,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Initial release 🎊 - Initial release 🎊
[unreleased]: https://github.com/ful1e5/Bibata_Cursor/compare/v1.1.0...main [unreleased]: https://github.com/ful1e5/Bibata_Cursor/compare/v1.1.1...main
[bibata v1.1.1]: https://github.com/ful1e5/Bibata_Cursor/compare/v1.1.0...v1.1.1
[bibata v1.1.0]: https://github.com/ful1e5/Bibata_Cursor/compare/v1.0.3...v1.1.0 [bibata v1.1.0]: https://github.com/ful1e5/Bibata_Cursor/compare/v1.0.3...v1.1.0
[bibata v1.0.3]: https://github.com/ful1e5/Bibata_Cursor/compare/v1.0.2...v1.0.3 [bibata v1.0.3]: https://github.com/ful1e5/Bibata_Cursor/compare/v1.0.2...v1.0.3
[bibata v1.0.2]: https://github.com/ful1e5/Bibata_Cursor/compare/v1.0.1...v1.0.2 [bibata v1.0.2]: https://github.com/ful1e5/Bibata_Cursor/compare/v1.0.1...v1.0.2
@ -193,3 +209,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[bibata v.0.4.1]: https://github.com/ful1e5/Bibata_Cursor/compare/v0.3.1...v0.4.1 [bibata v.0.4.1]: https://github.com/ful1e5/Bibata_Cursor/compare/v0.3.1...v0.4.1
[bibata v0.3.1]: https://github.com/ful1e5/Bibata_Cursor/compare/v0.3...v0.3.1 [bibata v0.3.1]: https://github.com/ful1e5/Bibata_Cursor/compare/v0.3...v0.3.1
[bibata v0.3]: https://github.com/ful1e5/Bibata_Cursor/tree/v0.3 [bibata v0.3]: https://github.com/ful1e5/Bibata_Cursor/tree/v0.3
[bibata v0.3]: https://github.com/ful1e5/Bibata_Cursor/tree/v0.3

View file

@ -32,21 +32,21 @@ render_modern: bitmapper svg
# #
build: bitmaps build: bitmaps
@cd builder && make setup build @cd builder && make setup build clean
build_unix: bitmaps build_unix: bitmaps
@rm -rf themes @rm -rf themes
@cd builder && make setup build_unix @cd builder && make setup build_unix clean
build_windows: bitmaps build_windows: bitmaps
@rm -rf themes @rm -rf themes
@cd builder && make setup build_windows @cd builder && make setup build_windows clean
build_modern: bitmaps build_modern: bitmaps
@cd builder && make setup build_modern @cd builder && make setup build_modern clean
build_original: bitmaps build_original: bitmaps
@cd builder && make setup build_original @cd builder && make setup build_original clean
# #
# Installation # Installation

View file

@ -72,27 +72,18 @@
--- ---
<!-- Sub Projects -->
<details>
<summary><strong>Sub Projects</strong> (click to expand)</summary>
- [Bibata Rainbow](./bitmapper/packages/rainbow)
</details>
# Bibata ? # Bibata ?
Bibata is **OpenSource**, Compact and Material Designed Cursor set. This project masterelop for improve `Cursor` Experience. Bibata is **OpenSource**, Compact and Material Designed Cursor set. This project masterelop for improve `Cursor` Experience.
- **Bibata Amber :** Yellowish Theme. - **Bibata Amber :** Yellowish Theme.
- **Bibata Classic :** Solid Black Theme. - **Bibata Classic :** Solid Black Theme.
- **Bibata Ice :** Light Theme. - **Bibata Ice :** Light Theme.
## Bibata Styles ## Bibata Styles
- **Bibata Original :** Sharp edge Bibata Cursors - **Bibata Original :** Sharp edge Bibata Cursors
- **Bibata Modern :** Round edge Bibata Cursors - **Bibata Modern :** Round edge Bibata Cursors
## Cursor Sizes ## Cursor Sizes
@ -230,9 +221,9 @@ sudo mv Bibata-* /usr/share/icons/
## External Libraries ## External Libraries
- libxcursor-dev - libxcursor-dev
- libx11-dev - libx11-dev
- libpng-dev (<=1.6) - libpng-dev (<=1.6)
#### Install External Libraries #### Install External Libraries
@ -263,22 +254,22 @@ sudo dnf install libX11-devel libXcursor-devel libpng-devel
## Build Dependencies ## Build Dependencies
- [gcc](https://gcc.gnu.org/install/) - [gcc](https://gcc.gnu.org/install/)
- [make](https://www.gnu.org/software/make/) - [make](https://www.gnu.org/software/make/)
- [nodejs](https://nodejs.org/en/) (<=12.x.x) - [nodejs](https://nodejs.org/en/) (<=12.x.x)
- [yarn](https://classic.yarnpkg.com/en/docs/install/) - [yarn](https://classic.yarnpkg.com/en/docs/install/)
- [python](https://www.python.org/downloads/) (<=3.8) - [python](https://www.python.org/downloads/) (<=3.8)
- [pip3](https://pip.pypa.io/en/stable/installing/) - [pip3](https://pip.pypa.io/en/stable/installing/)
### Node Packages ### Node Packages
- [puppeteer](https://www.npmjs.com/package/puppeteer) - [puppeteer](https://www.npmjs.com/package/puppeteer)
- [pngjs](https://www.npmjs.com/package/pngjs) - [pngjs](https://www.npmjs.com/package/pngjs)
- [pixelmatch](https://www.npmjs.com/package/pixelmatch) - [pixelmatch](https://www.npmjs.com/package/pixelmatch)
### PyPi Packages ### PyPi Packages
- [clickgen](https://pypi.org/project/clickgen/s) - [clickgen](https://pypi.org/project/clickgen/s)
## Build From Scratch ## Build From Scratch
@ -333,9 +324,10 @@ make windows WIN_SIZE=96 # Supports only one pixel-size
# You may also like... # You may also like...
- [**Bibata Extra**](https://github.com/ful1e5/Bibata_Extra_Cursor) - More Bibata! - [**Bibata Adapta**](https://gitlab.com/cscs/Bibata_AdaptaBreath_Cursors) - Bibata Based Cursor Made for AdaptaBreath and Manjaro.
- [**Bibata Adapta**](https://gitlab.com/cscs/Bibata_AdaptaBreath_Cursors) - Bibata Based Cursor Made for AdaptaBreath and Manjaro. - [**Bibata Extra**](https://github.com/ful1e5/Bibata_Extra_Cursor) - More Bibata!
- [**Bibata Translucent**](https://github.com/Silicasandwhich/Bibata_Cursor_Translucent) - Bibata translucent is a translucent flavor of the Bibata. - [**Bibata Rainbow**](https://github.com/ful1e5/Bibata_Cursor_Rainbow) - 'Semi-Animated' Bibata cursors with rainbow colors
- [**Bibata Translucent**](https://github.com/Silicasandwhich/Bibata_Cursor_Translucent) - Bibata translucent is a translucent flavor of the Bibata.
<!-- Bug Report --> <!-- Bug Report -->
@ -359,11 +351,11 @@ Check [CONTRIBUTING.md](CONTRIBUTING.md), any suggestions for features and contr
# Credit # Credit
- [Adwaita](https://github.com/GNOME/adwaita-icon-theme) - [Adwaita](https://github.com/GNOME/adwaita-icon-theme)
- [Dmz](https://github.com/GalliumOS/dmz-cursor-theme) - [Dmz](https://github.com/GalliumOS/dmz-cursor-theme)
- [Yaru](https://github.com/ubuntu/yaru) - [Yaru](https://github.com/ubuntu/yaru)
- Emojis are taken from [here](https://emojipedia.org/) - Emojis are taken from [here](https://emojipedia.org/)
- Wedge loading from [loading.io](https://loading.io/spinner/wedges/-pie-wedge-pizza-circle-round-rotate) with **Microsoft** colors - Wedge loading from [loading.io](https://loading.io/spinner/wedges/-pie-wedge-pizza-circle-round-rotate) with **Microsoft** colors
<!-- Support --> <!-- Support -->

View file

@ -1,15 +1,15 @@
{ {
"name": "bibata-cursor", "name": "bibata-cursor",
"version": "1.1.0", "version": "1.1.1",
"description": "Material Based Cursors", "description": "Material Based Cursors",
"main": "index.js", "main": "index.js",
"author": "Kaiz Khatri", "author": "Kaiz Khatri",
"license": "GPL-3.0", "license": "GPL-3.0",
"private": true, "private": true,
"scripts": { "scripts": {
"render:bibata-modern": "yarn workspace bibata-modern render", "render:bibata-modern": "yarn workspace bibata-modern render",
"render:bibata-original": "yarn workspace bibata-original render", "render:bibata-original": "yarn workspace bibata-original render",
"render:bibata-rainbow": "yarn workspace bibata-rainbow render" "render:bibata-rainbow": "yarn workspace bibata-rainbow render"
}, },
"workspaces": ["packages/*"] "workspaces": ["packages/*"]
} }

View file

@ -1,22 +1,22 @@
{ {
"name": "bibata-core", "name": "bibata-core",
"version": "1.1.0", "version": "1.1.0",
"description": "Bibata bitmapper's core modules", "description": "Bibata bitmapper's core modules",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
"author": "Kaiz Khatri", "author": "Kaiz Khatri",
"license": "GPL-3.0", "license": "GPL-3.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"pixelmatch": "^5.2.1", "pixelmatch": "^5.2.1",
"pngjs": "^6.0.0", "pngjs": "^6.0.0",
"puppeteer": "^7.1.0" "puppeteer": "^7.1.0"
}, },
"devDependencies": { "devDependencies": {
"@types/pixelmatch": "^5.2.2", "@types/pixelmatch": "^5.2.2",
"@types/pngjs": "^6.0.0", "@types/pngjs": "^6.0.0",
"@types/puppeteer": "^5.4.3", "@types/puppeteer": "^5.4.3",
"ts-node": "^9.1.1", "ts-node": "^9.1.1",
"typescript": "^4.1.5" "typescript": "^4.1.5"
} }
} }

View file

@ -8,148 +8,154 @@ import { matchImages } from "./util/matchImages";
import { toHTML } from "./util/toHTML"; import { toHTML } from "./util/toHTML";
class BitmapsGenerator { class BitmapsGenerator {
/** /**
* Generate Png files from svg code. * Generate Png files from svg code.
* @param themeName Give name, So all bitmaps files are organized in one directory. * @param themeName Give name, So all bitmaps files are organized in one directory.
* @param bitmapsDir `absolute` or `relative` path, Where `.png` files will store. * @param bitmapsDir `absolute` or `relative` path, Where `.png` files will store.
*/ */
constructor(private bitmapsDir: string) { constructor(private bitmapsDir: string) {
this.bitmapsDir = path.resolve(bitmapsDir); this.bitmapsDir = path.resolve(bitmapsDir);
this.createDir(this.bitmapsDir); this.createDir(this.bitmapsDir);
} }
/** /**
* Create directory if it doesn't exists. * Create directory if it doesn't exists.
* @param dirPath directory `absolute` path. * @param dirPath directory `absolute` path.
*/ */
private createDir(dirPath: string) { private createDir(dirPath: string) {
if (!fs.existsSync(dirPath)) { if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true }); fs.mkdirSync(dirPath, { recursive: true });
} }
} }
/** /**
* Prepare headless browser. * Prepare headless browser.
*/ */
public async getBrowser(): Promise<Browser> { public async getBrowser(): Promise<Browser> {
return await puppeteer.launch({ return await puppeteer.launch({
ignoreDefaultArgs: ["--no-sandbox"], ignoreDefaultArgs: ["--no-sandbox"],
headless: true, headless: true,
}); });
} }
private async getSvgElement( private async getSvgElement(
page: Page, page: Page,
content: string content: string
): Promise<ElementHandle<Element>> { ): Promise<ElementHandle<Element>> {
if (!content) { if (!content) {
throw new Error(`${content} File Read error`); throw new Error(`${content} File Read error`);
} }
const html = toHTML(content); const html = toHTML(content);
await page.setContent(html, { timeout: 0 }); await page.setContent(html, { timeout: 0 });
const svg = await page.$("#container svg"); const svg = await page.$("#container svg");
if (!svg) { if (!svg) {
throw new Error("svg element not found!"); throw new Error("svg element not found!");
} }
return svg; return svg;
} }
public async generateStatic(browser: Browser, content: string, key: string) { public async generateStatic(browser: Browser, content: string, key: string) {
const page = await browser.newPage(); const page = await browser.newPage();
const svg = await this.getSvgElement(page, content); const svg = await this.getSvgElement(page, content);
const out = path.resolve(this.bitmapsDir, `${key}.png`); const out = path.resolve(this.bitmapsDir, `${key}.png`);
await svg.screenshot({ omitBackground: true, path: out }); await svg.screenshot({ omitBackground: true, path: out });
await page.close(); await page.close();
} }
private async screenshot( private async screenshot(
element: ElementHandle<Element> element: ElementHandle<Element>
): Promise<Buffer | string> { ): Promise<Buffer | string> {
const buffer = await element.screenshot({ const buffer = await element.screenshot({
encoding: "binary", encoding: "binary",
omitBackground: true, omitBackground: true,
}); });
if (!buffer) { if (!buffer) {
throw new Error("SVG element screenshot not working"); throw new Error("SVG element screenshot not working");
} }
return buffer; return buffer;
} }
private async stopAnimation(page: Page) { private async stopAnimation(page: Page) {
const client = await page.target().createCDPSession(); const client = await page.target().createCDPSession();
await client.send("Animation.setPlaybackRate", { await client.send("Animation.setPlaybackRate", {
playbackRate: 0, playbackRate: 0,
}); });
} }
private async resumeAnimation(page: Page, playbackRate: number) { private async resumeAnimation(page: Page, playbackRate: number) {
const client = await page.target().createCDPSession(); const client = await page.target().createCDPSession();
await client.send("Animation.setPlaybackRate", { await client.send("Animation.setPlaybackRate", {
playbackRate, playbackRate,
}); });
} }
private async saveFrameImage(key: string, frame: Buffer | string) { private async saveFrameImage(key: string, frame: Buffer | string) {
const out_path = path.resolve(this.bitmapsDir, key); const out_path = path.resolve(this.bitmapsDir, key);
fs.writeFileSync(out_path, frame); fs.writeFileSync(out_path, frame);
} }
public async generateAnimated( public async generateAnimated(
browser: Browser, browser: Browser,
content: string, content: string,
key: string, key: string,
options?: { options?: {
playbackRate?: number; playbackRate?: number;
diff?: number; diff?: number;
frameLimit?: number; frameLimit?: number;
framePadding?: number; framePadding?: number;
} }
) { ) {
const opt = Object.assign( const opt = Object.assign(
{ playbackRate: 0.1, diff: 0, frameLimit: 300, framePadding: 4 }, {
options playbackRate: 0.3,
); diff: 0,
frameLimit: 300,
framePadding: 4,
},
options
);
const page = await browser.newPage(); const page = await browser.newPage();
const svg = await this.getSvgElement(page, content); const svg = await this.getSvgElement(page, content);
await this.stopAnimation(page); await this.stopAnimation(page);
let index = 1; let index = 1;
let breakRendering = false; let breakRendering = false;
let prevImg: Buffer | string; let prevImg: Buffer | string;
// Rendering frames till `imgN` matched to `imgN-1` (When Animation is done) // Rendering frames till `imgN` matched to `imgN-1` (When Animation is done)
while (!breakRendering) { while (!breakRendering) {
if (index > opt.frameLimit) { if (index > opt.frameLimit) {
throw new Error("Reached the frame limit."); throw new Error("Reached the frame limit.");
} }
await this.resumeAnimation(page, opt.playbackRate); await this.resumeAnimation(page, opt.playbackRate);
const img: string | Buffer = await this.screenshot(svg); const img: string | Buffer = await this.screenshot(svg);
await this.stopAnimation(page); await this.stopAnimation(page);
if (index > 1) { if (index > 1) {
// @ts-ignore // @ts-ignore
const diff = matchImages(prevImg, img); const diff = matchImages(prevImg, img);
if (diff <= opt.diff) { if (diff <= opt.diff) {
breakRendering = !breakRendering; breakRendering = !breakRendering;
} }
} }
const number = frameNumber(index, opt.framePadding); const number = frameNumber(index, opt.framePadding);
const frame = `${key}-${number}.png`; const frame = `${key}-${number}.png`;
this.saveFrameImage(frame, img); this.saveFrameImage(frame, img);
prevImg = img; prevImg = img;
++index; ++index;
} }
await page.close(); await page.close();
} }
} }
export { BitmapsGenerator }; export { BitmapsGenerator };

View file

@ -2,76 +2,76 @@ import fs from "fs";
import path from "path"; import path from "path";
interface Svg { interface Svg {
key: string; key: string;
content: string; content: string;
} }
class SvgDirectoryParser { class SvgDirectoryParser {
/** /**
* Manage and Parse SVG file path in `absolute` fashion. * Manage and Parse SVG file path in `absolute` fashion.
* This Parser look svg files as below fashion: * This Parser look svg files as below fashion:
* ` * `
* <@svgDir>/static * <@svgDir>/static
* <@svgDir>/animated * <@svgDir>/animated
* ` * `
* @param svgDir is relative/absolute path, Where `SVG` files are stored. * @param svgDir is relative/absolute path, Where `SVG` files are stored.
*/ */
semiAnimated: boolean = false; semiAnimated: boolean = false;
constructor(private svgDir: string) { constructor(private svgDir: string) {
if (!fs.existsSync(this.svgDir)) { if (!fs.existsSync(this.svgDir)) {
throw new Error(`SVG files not found in ${this.svgDir}`); throw new Error(`SVG files not found in ${this.svgDir}`);
} }
} }
private readData(f: string): Svg { private readData(f: string): Svg {
const content = fs.readFileSync(f, "utf-8"); const content = fs.readFileSync(f, "utf-8");
const key = path.basename(f, ".svg"); const key = path.basename(f, ".svg");
return { content, key }; return { content, key };
} }
/** /**
* Return absolute paths array of SVG files data located inside '@svgDir/static' * Return absolute paths array of SVG files data located inside '@svgDir/static'
*/ */
public getStatic(): Svg[] { public getStatic(): Svg[] {
const staticDir = path.resolve(this.svgDir, "static"); const staticDir = path.resolve(this.svgDir, "static");
if (!fs.existsSync(staticDir)) { if (!fs.existsSync(staticDir)) {
console.log(`${this.svgDir} contains semi-animated .svg files`); console.log(`${this.svgDir} contains semi-animated .svg files`);
this.semiAnimated = true; this.semiAnimated = true;
return []; return [];
} else { } else {
const svgs = fs const svgs = fs
.readdirSync(staticDir) .readdirSync(staticDir)
.map((f) => this.readData(path.resolve(staticDir, f))); .map((f) => this.readData(path.resolve(staticDir, f)));
if (svgs.length == 0) { if (svgs.length == 0) {
throw new Error("Static Cursors directory is empty"); throw new Error("Static Cursors directory is empty");
} }
return svgs; return svgs;
} }
} }
/** /**
* Return absolute paths array of SVG files data located inside '@svgDir/animated' * Return absolute paths array of SVG files data located inside '@svgDir/animated'
*/ */
public getAnimated(): Svg[] { public getAnimated(): Svg[] {
const animatedDir = path.resolve(this.svgDir, "animated"); const animatedDir = path.resolve(this.svgDir, "animated");
if (!fs.existsSync(animatedDir)) { if (!fs.existsSync(animatedDir)) {
throw new Error("Animated Cursors directory not found"); throw new Error("Animated Cursors directory not found");
} }
const svgs = fs const svgs = fs
.readdirSync(animatedDir) .readdirSync(animatedDir)
.map((f) => this.readData(path.resolve(animatedDir, f))); .map((f) => this.readData(path.resolve(animatedDir, f)));
if (svgs.length == 0 && this.semiAnimated) { if (svgs.length == 0 && this.semiAnimated) {
throw new Error( throw new Error(
`Can't parse svg directory ${this.svgDir} as semi-animated theme` `Can't parse svg directory ${this.svgDir} as semi-animated theme`
); );
} }
return svgs; return svgs;
} }
} }
export { SvgDirectoryParser }; export { SvgDirectoryParser };

View file

@ -7,11 +7,11 @@ import { Colors } from "../types";
* watch.background="#FF0000" (Red) * watch.background="#FF0000" (Red)
* */ * */
const defaultKeyColors: Colors = { const defaultKeyColors: Colors = {
base: "#00FF00", base: "#00FF00",
outline: "#0000FF", outline: "#0000FF",
watch: { watch: {
background: "#FF0000", background: "#FF0000",
}, },
}; };
/** /**
@ -22,31 +22,31 @@ const defaultKeyColors: Colors = {
* @returns {string} SVG code with colors. * @returns {string} SVG code with colors.
*/ */
const colorSvg = ( const colorSvg = (
content: string, content: string,
colors: Colors, colors: Colors,
keys: Colors = defaultKeyColors keys: Colors = defaultKeyColors
): string => { ): string => {
content = content content = content
.replace(new RegExp(keys.base, "ig"), colors.base) .replace(new RegExp(keys.base, "ig"), colors.base)
.replace(new RegExp(keys.outline, "ig"), colors.outline); .replace(new RegExp(keys.outline, "ig"), colors.outline);
try { try {
// === trying to replace `watch` color === // === trying to replace `watch` color ===
if (!colors.watch?.background) { if (!colors.watch?.background) {
throw new Error(""); throw new Error("");
} }
const { background: b } = colors.watch; const { background: b } = colors.watch;
content = content.replace(new RegExp(keys.watch!.background, "ig"), b); // Watch Background content = content.replace(new RegExp(keys.watch!.background, "ig"), b); // Watch Background
} catch (error) { } catch (error) {
// === on error => replace `watch` color as `base` === // === on error => replace `watch` color as `base` ===
content = content.replace( content = content.replace(
new RegExp(keys.watch!.background, "ig"), new RegExp(keys.watch!.background, "ig"),
colors.base colors.base
); );
} }
return content; return content;
}; };
export { colorSvg }; export { colorSvg };

View file

@ -10,11 +10,11 @@ type HexColor = string;
* @default background is `base` color. * @default background is `base` color.
*/ */
type Colors = { type Colors = {
base: HexColor; base: HexColor;
outline: HexColor; outline: HexColor;
watch?: { watch?: {
background: HexColor; background: HexColor;
}; };
}; };
export { Colors }; export { Colors };

View file

@ -1,7 +1,7 @@
export const frameNumber = (index: number, padding: number) => { export const frameNumber = (index: number, padding: number) => {
let result = "" + index; let result = "" + index;
while (result.length < padding) { while (result.length < padding) {
result = "0" + result; result = "0" + result;
} }
return result; return result;
}; };

View file

@ -2,10 +2,10 @@ import Pixelmatch from "pixelmatch";
import { PNG } from "pngjs"; import { PNG } from "pngjs";
export const matchImages = (img1: Buffer, img2: Buffer): number => { export const matchImages = (img1: Buffer, img2: Buffer): number => {
const { data: img1Data, width, height } = PNG.sync.read(img1); const { data: img1Data, width, height } = PNG.sync.read(img1);
const { data: imgNData } = PNG.sync.read(img2); const { data: imgNData } = PNG.sync.read(img2);
return Pixelmatch(img1Data, imgNData, null, width, height, { return Pixelmatch(img1Data, imgNData, null, width, height, {
threshold: 0.1, threshold: 0.1,
}); });
}; };

View file

@ -16,4 +16,4 @@ export const template = `
`; `;
export const toHTML = (svgData: string): string => export const toHTML = (svgData: string): string =>
template.replace("<svginjection>", svgData); template.replace("<svginjection>", svgData);

View file

@ -1,12 +1,12 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"declaration": true, "declaration": true,
"declarationMap": true, "declarationMap": true,
"sourceMap": true, "sourceMap": true,
"composite": true, "composite": true,
"outDir": "dist", "outDir": "dist",
"rootDir": "src" "rootDir": "src"
}, },
"include": ["src"] "include": ["src"]
} }

View file

@ -1,17 +1,17 @@
{ {
"name": "bibata-modern", "name": "bibata-modern",
"version": "1.1.0", "version": "1.1.1",
"description": "Rounded edges bibata cursors", "description": "Rounded edges bibata cursors",
"main": "dist/index.js", "main": "dist/index.js",
"scripts": { "scripts": {
"build": "npx tsc --build", "build": "npx tsc --build",
"render": "yarn build && node dist/index.js" "render": "yarn build && node dist/index.js"
}, },
"author": "Kaiz Khatri", "author": "Kaiz Khatri",
"license": "GPL-3.0", "license": "GPL-3.0",
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"ts-node": "^9.1.1", "ts-node": "^9.1.1",
"typescript": "^4.1.5" "typescript": "^4.1.5"
} }
} }

View file

@ -1,8 +1,8 @@
import { Colors } from "bibata-core/src/types"; import { Colors } from "bibata-core/src/types";
interface Config { interface Config {
themeName: string; themeName: string;
color: Colors; color: Colors;
} }
const black = "#000000"; const black = "#000000";
@ -11,30 +11,30 @@ const amber = "#FF8300";
const richBlack = "#001524"; const richBlack = "#001524";
const config: Config[] = [ const config: Config[] = [
{ {
themeName: "Bibata-Modern-Amber", themeName: "Bibata-Modern-Amber",
color: { color: {
base: amber, base: amber,
outline: white, outline: white,
watch: { watch: {
background: richBlack, background: richBlack,
}, },
}, },
}, },
{ {
themeName: "Bibata-Modern-Classic", themeName: "Bibata-Modern-Classic",
color: { color: {
base: black, base: black,
outline: white, outline: white,
}, },
}, },
{ {
themeName: "Bibata-Modern-Ice", themeName: "Bibata-Modern-Ice",
color: { color: {
base: white, base: white,
outline: black, outline: black,
}, },
}, },
]; ];
export { config }; export { config };

View file

@ -7,31 +7,31 @@ const root = path.resolve(__dirname, "../../../../");
const svgDir = path.resolve(root, "svg", "modern"); const svgDir = path.resolve(root, "svg", "modern");
const main = async () => { const main = async () => {
for (const { themeName, color } of config) { for (const { themeName, color } of config) {
console.log("=>", themeName); console.log("=>", themeName);
const bitmapsDir = path.resolve(root, "bitmaps", themeName); const bitmapsDir = path.resolve(root, "bitmaps", themeName);
const svg = new SVGHandler.SvgDirectoryParser(svgDir); const svg = new SVGHandler.SvgDirectoryParser(svgDir);
const png = new BitmapsGenerator(bitmapsDir); const png = new BitmapsGenerator(bitmapsDir);
const browser = await png.getBrowser(); const browser = await png.getBrowser();
for (let { key, content } of svg.getStatic()) { for (let { key, content } of svg.getStatic()) {
console.log(" -> Saving", key, "..."); console.log(" -> Saving", key, "...");
content = SVGHandler.colorSvg(content, color); content = SVGHandler.colorSvg(content, color);
await png.generateStatic(browser, content, key); await png.generateStatic(browser, content, key);
} }
for (let { key, content } of svg.getAnimated()) { for (let { key, content } of svg.getAnimated()) {
console.log(" -> Saving", key, "..."); console.log(" -> Saving", key, "...");
content = SVGHandler.colorSvg(content, color); content = SVGHandler.colorSvg(content, color);
await png.generateAnimated(browser, content, key); await png.generateAnimated(browser, content, key);
} }
await browser.close(); await browser.close();
} }
}; };
main(); main();

View file

@ -1,9 +1,9 @@
{ {
"references": [{ "path": "../core" }], "references": [{ "path": "../core" }],
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"rootDir": "src", "rootDir": "src",
"outDir": "dist" "outDir": "dist"
}, },
"include": ["src"] "include": ["src"]
} }

View file

@ -1,17 +1,17 @@
{ {
"name": "bibata-original", "name": "bibata-original",
"version": "1.1.0", "version": "1.1.1",
"description": "Sharp edges bibata cursors", "description": "Sharp edges bibata cursors",
"main": "dist/index.js", "main": "dist/index.js",
"scripts": { "scripts": {
"build": "npx tsc --build", "build": "npx tsc --build",
"render": "yarn build && node dist/index.js" "render": "yarn build && node dist/index.js"
}, },
"author": "Kaiz Khatri", "author": "Kaiz Khatri",
"license": "GPL-3.0", "license": "GPL-3.0",
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"ts-node": "^9.1.1", "ts-node": "^9.1.1",
"typescript": "^4.1.5" "typescript": "^4.1.5"
} }
} }

View file

@ -1,8 +1,8 @@
import { Colors } from "bibata-core/src/types"; import { Colors } from "bibata-core/src/types";
interface Config { interface Config {
themeName: string; themeName: string;
color: Colors; color: Colors;
} }
const black = "#000000"; const black = "#000000";
@ -11,30 +11,30 @@ const amber = "#FF8300";
const richBlack = "#001524"; const richBlack = "#001524";
const config: Config[] = [ const config: Config[] = [
{ {
themeName: "Bibata-Original-Amber", themeName: "Bibata-Original-Amber",
color: { color: {
base: amber, base: amber,
outline: white, outline: white,
watch: { watch: {
background: richBlack, background: richBlack,
}, },
}, },
}, },
{ {
themeName: "Bibata-Original-Classic", themeName: "Bibata-Original-Classic",
color: { color: {
base: black, base: black,
outline: white, outline: white,
}, },
}, },
{ {
themeName: "Bibata-Original-Ice", themeName: "Bibata-Original-Ice",
color: { color: {
base: white, base: white,
outline: black, outline: black,
}, },
}, },
]; ];
export { config }; export { config };

View file

@ -7,31 +7,31 @@ const root = path.resolve(__dirname, "../../../../");
const svgDir = path.resolve(root, "svg", "original"); const svgDir = path.resolve(root, "svg", "original");
const main = async () => { const main = async () => {
for (const { themeName, color } of config) { for (const { themeName, color } of config) {
console.log("=>", themeName); console.log("=>", themeName);
const bitmapsDir = path.resolve(root, "bitmaps", themeName); const bitmapsDir = path.resolve(root, "bitmaps", themeName);
const svg = new SVGHandler.SvgDirectoryParser(svgDir); const svg = new SVGHandler.SvgDirectoryParser(svgDir);
const png = new BitmapsGenerator(bitmapsDir); const png = new BitmapsGenerator(bitmapsDir);
const browser = await png.getBrowser(); const browser = await png.getBrowser();
for (let { key, content } of svg.getStatic()) { for (let { key, content } of svg.getStatic()) {
console.log(" -> Saving", key, "..."); console.log(" -> Saving", key, "...");
content = SVGHandler.colorSvg(content, color); content = SVGHandler.colorSvg(content, color);
await png.generateStatic(browser, content, key); await png.generateStatic(browser, content, key);
} }
for (let { key, content } of svg.getAnimated()) { for (let { key, content } of svg.getAnimated()) {
console.log(" -> Saving", key, "..."); console.log(" -> Saving", key, "...");
content = SVGHandler.colorSvg(content, color); content = SVGHandler.colorSvg(content, color);
await png.generateAnimated(browser, content, key); await png.generateAnimated(browser, content, key);
} }
await browser.close(); await browser.close();
} }
}; };
main(); main();

View file

@ -414,17 +414,6 @@ through@^2.3.8:
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
ts-node@^8.10.2:
version "8.10.2"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d"
integrity sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==
dependencies:
arg "^4.1.0"
diff "^4.0.1"
make-error "^1.1.1"
source-map-support "^0.5.17"
yn "3.1.1"
ts-node@^9.1.1: ts-node@^9.1.1:
version "9.1.1" version "9.1.1"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d"
@ -437,7 +426,7 @@ ts-node@^9.1.1:
source-map-support "^0.5.17" source-map-support "^0.5.17"
yn "3.1.1" yn "3.1.1"
typescript@^4.0.5, typescript@^4.1.5: typescript@^4.1.5:
version "4.1.5" version "4.1.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.5.tgz#123a3b214aaff3be32926f0d8f1f6e704eb89a72" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.5.tgz#123a3b214aaff3be32926f0d8f1f6e704eb89a72"
integrity sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA== integrity sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA==

View file

@ -7,14 +7,14 @@ bitmaps_dir = "../bitmaps"
.ONESHELL: .ONESHELL:
SHELL:=/bin/bash SHELL:=/bin/bash
X_SIZES ?=22 24 28 32 40 48 56 64 72 80 88 96 THEMES = Amber Classic Ice
X_SIZES ?= 22 24 28 32 40 48 56 64 72 80 88 96
WIN_CANVAS_SIZE ?= 32 WIN_CANVAS_SIZE ?= 32
WIN_SIZE ?= 24 WIN_SIZE ?= 24
clean: clean:
@rm -rf applbuild.egg-info build dist @rm -rf bbpkg.egg-info build dist
@find -iname "*.pyc" -delete @find -iname "*.pyc" -delete
# Removing setup.py package files if installed # Removing setup.py package files if installed
@if [ -f "files.txt" ]; then @if [ -f "files.txt" ]; then
@xargs rm -rf < files.txt @xargs rm -rf < files.txt
@ -22,41 +22,31 @@ clean:
@fi @fi
setup: setup.py setup: setup.py
@test -d venv || python3 -m venv venv @python3 setup.py install --user --record files.txt
@. venv/bin/activate; python3 setup.py install --record files.txt
build: build_modern build_original build: build_modern build_original
build_modern: build.py build_modern: build.py
@. venv/bin/activate; python3 build.py -p "$(bitmaps_dir)/Bibata-Modern-Amber" --xsizes $(X_SIZES) --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE) @$(foreach theme,$(THEMES), python3 build.py -p "$(bitmaps_dir)/Bibata-Modern-$(theme)" --xsizes $(X_SIZES) --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE);)
@. venv/bin/activate; python3 build.py -p "$(bitmaps_dir)/Bibata-Modern-Classic" --xsizes $(X_SIZES) --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE)
@. venv/bin/activate; python3 build.py -p "$(bitmaps_dir)/Bibata-Modern-Ice" --xsizes $(X_SIZES) --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE)
build_original: build.py build_original: build.py
@. venv/bin/activate; python3 build.py -p "$(bitmaps_dir)/Bibata-Original-Amber" --xsizes $(X_SIZES) --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE) @$(foreach theme,$(THEMES), python3 build.py -p "$(bitmaps_dir)/Bibata-Original-$(theme)" --xsizes $(X_SIZES) --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE);)
@. venv/bin/activate; python3 build.py -p "$(bitmaps_dir)/Bibata-Original-Classic" --xsizes $(X_SIZES) --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE)
@. venv/bin/activate; python3 build.py -p "$(bitmaps_dir)/Bibata-Original-Ice" --xsizes $(X_SIZES) --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE)
build_unix: build_modern_unix build_original_unix build_unix: build_modern_unix build_original_unix
build_modern_unix: build.py build_modern_unix: build.py
@. venv/bin/activate; python3 build.py unix -p "$(bitmaps_dir)/Bibata-Modern-Amber" --xsizes $(X_SIZES) @$(foreach theme,$(THEMES), python3 build.py unix -p "$(bitmaps_dir)/Bibata-Modern-$(theme)" --xsizes $(X_SIZES);)
@. venv/bin/activate; python3 build.py unix -p "$(bitmaps_dir)/Bibata-Modern-Classic" --xsizes $(X_SIZES)
@. venv/bin/activate; python3 build.py unix -p "$(bitmaps_dir)/Bibata-Modern-Ice" --xsizes $(X_SIZES)
build_original_unix: build.py build_original_unix: build.py
@. venv/bin/activate; python3 build.py unix -p "$(bitmaps_dir)/Bibata-Original-Amber" --xsizes $(X_SIZES) @$(foreach theme,$(THEMES), python3 build.py unix -p "$(bitmaps_dir)/Bibata-Original-$(theme)" --xsizes $(X_SIZES);)
@. venv/bin/activate; python3 build.py unix -p "$(bitmaps_dir)/Bibata-Original-Classic" --xsizes $(X_SIZES)
@. venv/bin/activate; python3 build.py unix -p "$(bitmaps_dir)/Bibata-Original-Ice" --xsizes $(X_SIZES)
build_windows: build_modern_windows build_original_windows build_windows: build_modern_windows build_original_windows
build_modern_windows: build.py build_modern_windows: build.py
@. venv/bin/activate; python3 build.py windows -p "$(bitmaps_dir)/Bibata-Modern-Amber" --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE) @$(foreach theme,$(THEMES), python3 build.py windows -p "$(bitmaps_dir)/Bibata-Modern-$(theme)" --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE);)
@. venv/bin/activate; python3 build.py windows -p "$(bitmaps_dir)/Bibata-Modern-Classic" --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE)
@. venv/bin/activate; python3 build.py windows -p "$(bitmaps_dir)/Bibata-Modern-Ice" --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE)
build_original_windows: build.py build_original_windows: build.py
@. venv/bin/activate; python3 build.py windows -p "$(bitmaps_dir)/Bibata-Original-Amber" --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE) @$(foreach theme,$(THEMES), python3 build.py windows -p "$(bitmaps_dir)/Bibata-Original-$(theme)" --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE);)
@. venv/bin/activate; python3 build.py windows -p "$(bitmaps_dir)/Bibata-Original-Classic" --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE)
@. venv/bin/activate; python3 build.py windows -p "$(bitmaps_dir)/Bibata-Original-Ice" --win-size $(WIN_SIZE) --win-canvas-size $(WIN_CANVAS_SIZE)

View file

@ -1,7 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from typing import Any, Dict, Tuple, TypeVar from pathlib import Path
from typing import Any, Dict, Tuple, TypeVar, Union
from clickgen.util import PNGProvider from clickgen.util import PNGProvider
@ -15,24 +16,20 @@ def to_tuple(x: X) -> Tuple[X, X]:
return (x, x) return (x, x)
def get_config(bitmaps_dir, **kwargs) -> Dict[str, Any]: def get_config(bitmaps_dir: Union[str, Path], **kwargs) -> Dict[str, Any]:
"""Return configuration of `Bibata` pointers. """Return configuration of `Bibata`.
``` :param bitmaps_dir: Path to .png file's directory.
Args: :type bitmaps_dir: Union[str, Path]
:bitmaps_dir: (str | Path) Path to .png file's directory. :param x_sizes: List of pixel-sizes for xcursors.
:type x_sizes: List[int]
:param win_canvas_size: Windows cursor's canvas pixel-size.
:type win_canvas_size: int
Keywords Args: :param win_size: Pixel-size for Windows cursor.
:type win_size: int
: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: Example:

View file

@ -10,7 +10,6 @@ URL = "https://github.com/ful1e5/Bibata_Cursor"
# XCursor # XCursor
X_DELAY: int = 13 X_DELAY: int = 13
# Windows Cursor # Windows Cursor
WIN_DELAY = 1 WIN_DELAY = 1

View file

@ -4,16 +4,16 @@
from pathlib import Path from pathlib import Path
from typing import Any, Dict, NamedTuple from typing import Any, Dict, NamedTuple
from bbpkg.constants import AUTHOR, URL
from bbpkg.symlinks import add_missing_xcursor
from clickgen.builders import WindowsCursor, XCursor from clickgen.builders import WindowsCursor, XCursor
from clickgen.core import CursorAlias from clickgen.core import CursorAlias
from clickgen.packagers import WindowsPackager from clickgen.packagers import WindowsPackager, XPackager
from bbpkg.constants import AUTHOR, URL
from bbpkg.packager import XPackager
from bbpkg.symlinks import add_missing_xcursor
class Info(NamedTuple): class Info(NamedTuple):
"""Important cursor package's information field"""
name: str name: str
comment: str comment: str
@ -21,14 +21,16 @@ class Info(NamedTuple):
def xbuild(config: Dict[str, Dict[str, Any]], x_out_dir: Path, info: Info) -> None: def xbuild(config: Dict[str, Dict[str, Any]], x_out_dir: Path, info: Info) -> None:
"""Build `Bibata` cursor theme for only `X11`(UNIX) platform. """Build `Bibata` cursor theme for only `X11`(UNIX) platform.
``` :param config: `Bibata` configuration.
:config: (Dict) `Bibata` configuration. :type config: Dict[str, Dict[str, Any]]
:x_out_dir: (Path) Path to the output directory, :param x_out_dir: Path to the output directory, \
Where the `X11` cursor theme package will generate. Where the `X11` cursor theme package will generate.\
It also creates a directory if not exists. It also creates a directory if not exists.
:info: (Dict) Content theme name & comment :type x_out_dir: Path
```
:param info: Content theme name & comment
:type info: Info
""" """
for _, item in config.items(): for _, item in config.items():
@ -49,14 +51,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: def wbuild(config: Dict[str, Dict[str, Any]], win_out_dir: Path, info: Info) -> None:
"""Build `Bibata` cursor theme for only `Windows` platforms. """Build `Bibata` cursor theme for only `Windows` platforms.
``` :param config: `Bibata` configuration.
:config: (Dict) `Bibata` configuration. :type config: Dict[str, Dict[str, Any]]
:win_out_dir: (Path) Path to the output directory, :param win_out_dir: Path to the output directory,\
Where the `Windows` cursor theme package will generate. Where the `Windows` cursor theme package will \
It also creates a directory if not exists. generate. It also creates a directory if not exists.
:info: (Dict) Content theme name & comment :type win_out_dir: Path
```
:param info: Content theme name & comment
:type info: Dict
""" """
for _, item in config.items(): for _, item in config.items():
@ -89,18 +93,16 @@ def build(
) -> None: ) -> None:
"""Build `Bibata` cursor theme for `X11` & `Windows` platforms. """Build `Bibata` cursor theme for `X11` & `Windows` platforms.
``` :param config: `Bibata` configuration.
:config: (Dict) `Bibata` configuration. :type config: Dict[str, Dict[str, Any]]
:x_out_dir: (Path) Path to the output directory, :param win_out_dir: Path to the output directory,\
Where the `X11` cursor theme package will generate. Where the `Windows` cursor theme package will \
It also creates a directory if not exists. generate. It also creates a directory if not exists.
:type win_out_dir: Path
:win_out_dir: (Path) Path to the output directory, :param info: Content theme name & comment
Where the `Windows` cursor theme package will generate. :type info: Dict
It also creates a directory if not exists.
:info: (Dict) Content theme name & comment
```
""" """
def win_build(item: Dict[str, Any], alias: CursorAlias) -> None: def win_build(item: Dict[str, Any], alias: CursorAlias) -> None:

View file

@ -1,26 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pathlib import Path
from string import Template
from typing import Dict
THEME_FILES_TEMPLATES: Dict[str, Template] = {
"cursor.theme": Template("[Icon Theme]\nName=$theme_name\nInherits=$theme_name"),
"index.theme": Template(
'[Icon Theme]\nName=$theme_name\nComment=$comment\nInherits="hicolor"'
),
}
def XPackager(directory: Path, theme_name: str, comment: str) -> None:
""" Create a crispy `XCursors` theme package. """
# Writing all .theme files
files: Dict[str, str] = {}
for file, template in THEME_FILES_TEMPLATES.items():
files[file] = template.safe_substitute(theme_name=theme_name, comment=comment)
for f, data in files.items():
fp: Path = directory / f
fp.write_text(data)

View file

@ -2,14 +2,17 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os import os
from pathlib import Path
from typing import Union
from clickgen.util import chdir from clickgen.util import chdir
def add_missing_xcursor(directory) -> None: def add_missing_xcursor(directory: Union[str, Path]) -> None:
"""Add missing `XCursor` to the Unix cursor package. """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 = [ symlinks = [

View file

@ -5,14 +5,14 @@ from setuptools import setup
setup( setup(
name="bbpkg", name="bbpkg",
version="1.1.0", version="1.1.1",
description="Generate 'Bibata' cursor theme from PNGs file", description="Generate 'Bibata' cursor theme from PNGs file",
url="https://github.com/ful1e5/Bibata_Cursor", url="https://github.com/ful1e5/Bibata_Cursor",
packages=["bbpkg"], packages=["bbpkg"],
package_dir={"bbpkg": "bbpkg"}, package_dir={"bbpkg": "bbpkg"},
author="Kaiz Khatri", author="Kaiz Khatri",
author_email="kaizmandhu@gamil.com", author_email="kaizmandhu@gamil.com",
install_requires=["clickgen==1.1.8"], install_requires=["clickgen==1.1.9"],
classifiers=[ classifiers=[
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",