fodec 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Kris Papercut
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Fodec
2
+
3
+ ## Installation
4
+
5
+ ```shell
6
+ npm install -g fodec
7
+ ```
8
+
9
+ ## Initialization
10
+
11
+ This command generates a `fodec.json` file. You can further edit this file and add elements to the `resources` array.
12
+
13
+ ```shell
14
+ fodec init
15
+ ```
16
+
17
+ ## Key generation
18
+
19
+ This command generates a `fodec.key` file for your project.
20
+
21
+ ```shell
22
+ fodec gen
23
+ ```
24
+
25
+ ## Build
26
+
27
+ This command performs a build based on the provided `fodec.json` and `fodec.key` files. The build process takes the specifications and keys defined in these files to build the final output.
28
+
29
+ ```shell
30
+ fodec build
31
+ ```
package/bin/fodec.js ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+
3
+ const {app} = require("../lib/cli/index.js");
4
+
5
+ app.run().then((res) => {
6
+ if(!res) {
7
+ return;
8
+ }
9
+
10
+ process.stdout.write(res);
11
+ process.stdout.write("\n");
12
+ }).catch((err) => {
13
+ process.stderr.write(err.message);
14
+ });
package/lib/Fodec.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ export declare class Fodec {
2
+ protected key: string;
3
+ constructor(key: string);
4
+ transformText(str: string): string;
5
+ transformJson(data: any): Promise<any>;
6
+ transformFont(fontPath: string): Promise<string | ArrayBuffer | undefined>;
7
+ transformFontV1(fontPath: string): Promise<string | ArrayBuffer | undefined>;
8
+ }
package/lib/Fodec.js ADDED
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Fodec = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const fs_1 = require("fs");
9
+ const fonteditor_core_1 = require("fonteditor-core");
10
+ class Fodec {
11
+ constructor(key) {
12
+ this.key = key;
13
+ }
14
+ transformText(str) {
15
+ return str.split("").map((char) => {
16
+ const index = this.key.indexOf(char);
17
+ return index !== -1 ? this.key.charAt(index + 1 + (this.key.length - 1) / 2) : char;
18
+ }).join("");
19
+ }
20
+ async transformJson(data) {
21
+ return data;
22
+ }
23
+ async transformFont(fontPath) {
24
+ return this.transformFontV1(fontPath);
25
+ }
26
+ async transformFontV1(fontPath) {
27
+ const ext = path_1.default.extname(fontPath).slice(1);
28
+ if (ext !== "ttf") {
29
+ return;
30
+ }
31
+ const font = fonteditor_core_1.Font.create(await fs_1.promises.readFile(fontPath), {
32
+ type: ext
33
+ });
34
+ const { glyf: list, } = font.get();
35
+ const glyphs = [];
36
+ for (let i = 0; i < list.length; i++) {
37
+ const glyph = list[i];
38
+ const char = glyph.unicode
39
+ ? String.fromCharCode(glyph.unicode[0])
40
+ : null;
41
+ if (!char) {
42
+ glyphs.push(glyph);
43
+ continue;
44
+ }
45
+ if (this.key.indexOf(char) === -1) {
46
+ glyphs.push(glyph);
47
+ continue;
48
+ }
49
+ const index = this.key.indexOf(char);
50
+ const transformUnicode = this.key.charCodeAt((this.key.length - 1) / 2 + 1 + index);
51
+ const rand = list.find((item) => {
52
+ if (!item.unicode) {
53
+ return;
54
+ }
55
+ return item.unicode[0] === transformUnicode;
56
+ });
57
+ if (!rand) {
58
+ glyphs.push(glyph);
59
+ continue;
60
+ }
61
+ glyphs.push({
62
+ ...glyph,
63
+ name: rand.name,
64
+ unicode: rand.unicode
65
+ });
66
+ }
67
+ font.set({
68
+ ...font.get(),
69
+ glyf: glyphs
70
+ });
71
+ return font.write({
72
+ type: ext
73
+ });
74
+ }
75
+ }
76
+ exports.Fodec = Fodec;
@@ -0,0 +1,12 @@
1
+ import { Cli } from "@kearisp/cli";
2
+ import { Config } from "../types/Config";
3
+ export declare class App {
4
+ protected cli: Cli;
5
+ constructor();
6
+ protected getConfig(): Promise<Config>;
7
+ protected getKey(): Promise<string>;
8
+ init(): Promise<void>;
9
+ generate(): Promise<void>;
10
+ build(): Promise<void>;
11
+ run(): Promise<any>;
12
+ }
package/lib/cli/App.js ADDED
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.App = void 0;
7
+ const cli_1 = require("@kearisp/cli");
8
+ const fs_1 = require("fs");
9
+ const path_1 = __importDefault(require("path"));
10
+ const utils_1 = require("@wocker/utils");
11
+ const Fodec_1 = require("../Fodec");
12
+ const generateKey_1 = require("../utils/generateKey");
13
+ class App {
14
+ constructor() {
15
+ this.cli = new cli_1.Cli();
16
+ this.cli.command("init")
17
+ .action(() => this.init());
18
+ this.cli.command("gen")
19
+ .action(() => this.generate());
20
+ this.cli.command("build")
21
+ .action(() => this.build());
22
+ }
23
+ async getConfig() {
24
+ const configPath = "fodec.json";
25
+ if (!(0, fs_1.existsSync)(configPath)) {
26
+ throw new Error("Config not found");
27
+ }
28
+ const res = await fs_1.promises.readFile(configPath);
29
+ return JSON.parse(res.toString());
30
+ }
31
+ async getKey() {
32
+ const res = await fs_1.promises.readFile("fodec.key");
33
+ return res.toString();
34
+ }
35
+ async init() {
36
+ const configPath = "./fodec-2.json";
37
+ if ((0, fs_1.existsSync)(configPath)) {
38
+ throw new Error("Config already exists");
39
+ }
40
+ let config = {};
41
+ config.basePath = await (0, utils_1.promptText)({
42
+ required: true,
43
+ type: "string",
44
+ message: "Base Path:",
45
+ default: "src"
46
+ });
47
+ config.output = {
48
+ path: await (0, utils_1.promptText)({
49
+ required: true,
50
+ type: "string",
51
+ message: "Output path:",
52
+ default: "build"
53
+ })
54
+ };
55
+ config.alphabets = await (0, utils_1.promptSelect)({
56
+ multiple: true,
57
+ options: [
58
+ "cyrillic",
59
+ "latin"
60
+ ]
61
+ });
62
+ config.resources = [];
63
+ await fs_1.promises.writeFile(configPath, JSON.stringify(config, null, 4));
64
+ }
65
+ async generate() {
66
+ const { alphabets } = await this.getConfig();
67
+ const key = (0, generateKey_1.generateKey)({
68
+ alphabets
69
+ });
70
+ console.log(key);
71
+ await fs_1.promises.writeFile("fodec.key", key);
72
+ }
73
+ async build() {
74
+ const key = await this.getKey();
75
+ const { basePath = "./", output: { path: outPath = "./build" } = {}, fonts, resources } = await this.getConfig();
76
+ const fodec = new Fodec_1.Fodec(key);
77
+ for (const resource of resources) {
78
+ let res;
79
+ if (resource.type === "font") {
80
+ const transformedFont = await fodec.transformFont(path_1.default.join(basePath, resource.path));
81
+ if (!transformedFont || transformedFont instanceof ArrayBuffer) {
82
+ continue;
83
+ }
84
+ res = transformedFont;
85
+ }
86
+ else if (resource.type === "json") {
87
+ const json = await fs_1.promises.readFile(path_1.default.join(basePath, resource.path));
88
+ const data = JSON.parse(json.toString());
89
+ res = JSON.stringify(data, (key, value) => {
90
+ if (typeof value === "string") {
91
+ return fodec.transformText(value);
92
+ }
93
+ return value;
94
+ }, 4);
95
+ }
96
+ if (res) {
97
+ const outFullPath = path_1.default.join(outPath, path_1.default.dirname(resource.output || resource.path));
98
+ (0, fs_1.mkdirSync)(outFullPath, {
99
+ recursive: true
100
+ });
101
+ await fs_1.promises.writeFile(path_1.default.join(outPath, resource.output || resource.path), res);
102
+ }
103
+ }
104
+ }
105
+ async run() {
106
+ return this.cli.run(process.argv);
107
+ }
108
+ }
109
+ exports.App = App;
@@ -0,0 +1,2 @@
1
+ import { App } from "./App";
2
+ export declare const app: App;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.app = void 0;
4
+ const App_1 = require("./App");
5
+ exports.app = new App_1.App();
package/lib/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { Fodec } from "./Fodec";
package/lib/index.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Fodec = void 0;
4
+ var Fodec_1 = require("./Fodec");
5
+ Object.defineProperty(exports, "Fodec", { enumerable: true, get: function () { return Fodec_1.Fodec; } });
@@ -0,0 +1,26 @@
1
+ import { AlphabetType } from "./MapAlphabets";
2
+ export type Config = {
3
+ basePath?: string;
4
+ output?: {
5
+ path: string;
6
+ };
7
+ alphabets: AlphabetType[];
8
+ fonts: {
9
+ name: string;
10
+ path: string;
11
+ }[];
12
+ resources: (FontResource | JsonResource)[];
13
+ };
14
+ type FontResource = {
15
+ type: "font";
16
+ format: string;
17
+ name: string;
18
+ path: string;
19
+ output?: string;
20
+ };
21
+ type JsonResource = {
22
+ type: "json";
23
+ path: string;
24
+ output?: string;
25
+ };
26
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,27 @@
1
+ export declare const MapAlphabets: {
2
+ latin: {
3
+ lowerStart: number;
4
+ lowerLength: number;
5
+ upperStart: number;
6
+ upperLength: number;
7
+ };
8
+ cyrillic: {
9
+ lowerStart: number;
10
+ lowerLength: number;
11
+ upperStart: number;
12
+ upperLength: number;
13
+ };
14
+ arabic: {
15
+ lowerStart: number;
16
+ lowerLength: number;
17
+ upperStart: number;
18
+ upperLength: number;
19
+ };
20
+ greek: {
21
+ lowerStart: number;
22
+ lowerLength: number;
23
+ upperStart: number;
24
+ upperLength: number;
25
+ };
26
+ };
27
+ export type AlphabetType = keyof typeof MapAlphabets;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MapAlphabets = void 0;
4
+ exports.MapAlphabets = {
5
+ latin: {
6
+ lowerStart: 0x61,
7
+ lowerLength: 26,
8
+ upperStart: 0x41,
9
+ upperLength: 26
10
+ },
11
+ cyrillic: {
12
+ lowerStart: 0x430,
13
+ lowerLength: 32,
14
+ upperStart: 0x410,
15
+ upperLength: 32
16
+ },
17
+ arabic: {
18
+ lowerStart: 0x0620,
19
+ lowerLength: 36,
20
+ upperStart: 0x0620,
21
+ upperLength: 36
22
+ },
23
+ greek: {
24
+ lowerStart: 0x03B1,
25
+ lowerLength: 25,
26
+ upperStart: 0x0391,
27
+ upperLength: 25
28
+ }
29
+ };
@@ -0,0 +1,6 @@
1
+ import { AlphabetType } from "../types/MapAlphabets";
2
+ type Options = {
3
+ alphabets: AlphabetType[];
4
+ };
5
+ export declare const generateKey: (options: Options) => string;
6
+ export {};
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateKey = void 0;
4
+ const shuffle_1 = require("./shuffle");
5
+ const MapAlphabets_1 = require("../types/MapAlphabets");
6
+ const generateKey = (options) => {
7
+ const { alphabets } = options;
8
+ return Object.keys(MapAlphabets_1.MapAlphabets).reduce((res, key) => {
9
+ if (!alphabets.includes(key)) {
10
+ return res;
11
+ }
12
+ const { lowerStart, lowerLength, upperStart, upperLength } = MapAlphabets_1.MapAlphabets[key];
13
+ const indexes = [
14
+ ...Array.from({ length: lowerLength }, (_, i) => lowerStart + i),
15
+ ...Array.from({ length: upperLength }, (_, i) => upperStart + i)
16
+ ];
17
+ const moved = indexes.slice();
18
+ (0, shuffle_1.shuffle)(moved);
19
+ return [
20
+ res[0] + String.fromCharCode(...indexes),
21
+ res[1] + String.fromCharCode(...moved)
22
+ ];
23
+ }, ["", ""]).join("\n");
24
+ };
25
+ exports.generateKey = generateKey;
@@ -0,0 +1 @@
1
+ export declare const shuffle: (arr: unknown[]) => void;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.shuffle = void 0;
4
+ const shuffle = (arr) => {
5
+ for (let i = arr.length - 1; i > 0; i--) {
6
+ let j = Math.floor(Math.random() * (i + 1));
7
+ [arr[i], arr[j]] = [arr[j], arr[i]];
8
+ }
9
+ };
10
+ exports.shuffle = shuffle;
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "fodec",
3
+ "version": "1.0.0",
4
+ "author": "Kris Papercut <krispcut@gmail.com>",
5
+ "description": "",
6
+ "license": "MIT",
7
+ "main": "lib/index.js",
8
+ "types": "lib/index.d.ts",
9
+ "directories": {
10
+ "cli": "./lib/cli"
11
+ },
12
+ "bin": {
13
+ "fodec": "./bin/fodec.js"
14
+ },
15
+ "scripts": {
16
+ "prepare": "npm run build",
17
+ "build": "tsc --build",
18
+ "watch": "tsc --watch",
19
+ "test": "echo \"Error: no test specified\" && exit 1"
20
+ },
21
+ "homepage": "https://github.com/kearisp/fodec#readme",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/kearisp/fodec.git"
25
+ },
26
+ "bugs": {
27
+ "url": "https://github.com/kearisp/fodec/issues"
28
+ },
29
+ "dependencies": {
30
+ "@kearisp/cli": "^1.0.4",
31
+ "@wocker/utils": "^1.0.2",
32
+ "fonteditor-core": "^2.3.2",
33
+ "fs": "^0.0.1-security",
34
+ "path": "^0.12.7"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^20.11.5",
38
+ "typescript": "^5.3.3"
39
+ }
40
+ }
package/src/Fodec.ts ADDED
@@ -0,0 +1,89 @@
1
+ import Path from "path";
2
+ import {promises as FS} from "fs";
3
+ import {Font, TTF} from "fonteditor-core";
4
+
5
+
6
+ export class Fodec {
7
+ public constructor(
8
+ protected key: string
9
+ ) {}
10
+
11
+ public transformText(str: string): string {
12
+ return str.split("").map((char) => {
13
+ const index = this.key.indexOf(char);
14
+
15
+ return index !== -1 ? this.key.charAt(index + 1 + (this.key.length - 1) / 2) : char;
16
+ }).join("");
17
+ }
18
+
19
+ public async transformJson(data: any) {
20
+ return data;
21
+ }
22
+
23
+ public async transformFont(fontPath: string) {
24
+ return this.transformFontV1(fontPath);
25
+ }
26
+
27
+ public async transformFontV1(fontPath: string) {
28
+ const ext = Path.extname(fontPath).slice(1);
29
+
30
+ if(ext !== "ttf") {
31
+ return;
32
+ }
33
+
34
+ const font = Font.create(await FS.readFile(fontPath), {
35
+ type: ext
36
+ });
37
+
38
+ const {glyf: list,} = font.get();
39
+ const glyphs: TTF.Glyph[] = [];
40
+
41
+ for(let i = 0; i < list.length; i++) {
42
+ const glyph = list[i];
43
+ const char = glyph.unicode
44
+ ? String.fromCharCode(glyph.unicode[0])
45
+ : null;
46
+
47
+ if(!char) {
48
+ glyphs.push(glyph);
49
+ continue;
50
+ }
51
+
52
+ if(this.key.indexOf(char) === -1) {
53
+ glyphs.push(glyph);
54
+ continue;
55
+ }
56
+
57
+ const index = this.key.indexOf(char);
58
+ const transformUnicode = this.key.charCodeAt((this.key.length - 1) / 2 + 1 + index);
59
+
60
+ const rand = list.find((item) => {
61
+ if(!item.unicode) {
62
+ return;
63
+ }
64
+
65
+ return item.unicode[0] === transformUnicode;
66
+ });
67
+
68
+ if(!rand) {
69
+ glyphs.push(glyph);
70
+ continue;
71
+ }
72
+
73
+ glyphs.push({
74
+ ...glyph,
75
+ name: rand.name,
76
+ unicode: rand.unicode
77
+ });
78
+ }
79
+
80
+ font.set({
81
+ ...font.get(),
82
+ glyf: glyphs
83
+ });
84
+
85
+ return font.write({
86
+ type: ext
87
+ });
88
+ }
89
+ }
package/src/cli/App.ts ADDED
@@ -0,0 +1,155 @@
1
+ import {Cli} from "@kearisp/cli";
2
+ import {promises as FS, existsSync, mkdirSync} from "fs";
3
+ import Path from "path";
4
+ import {promptText, promptSelect} from "@wocker/utils";
5
+ import {Fodec} from "../Fodec";
6
+ import {generateKey} from "../utils/generateKey";
7
+ import {Config} from "../types/Config";
8
+
9
+
10
+ export class App {
11
+ protected cli: Cli;
12
+
13
+ public constructor() {
14
+ this.cli = new Cli();
15
+
16
+ this.cli.command("init")
17
+ .action(() => this.init());
18
+
19
+ this.cli.command("gen")
20
+ .action(() => this.generate());
21
+
22
+ this.cli.command("build")
23
+ .action(() => this.build());
24
+ }
25
+
26
+ protected async getConfig(): Promise<Config> {
27
+ const configPath = "fodec.json";
28
+
29
+ if(!existsSync(configPath)) {
30
+ throw new Error("Config not found");
31
+ }
32
+
33
+ const res = await FS.readFile(configPath);
34
+
35
+ return JSON.parse(res.toString());
36
+ }
37
+
38
+ protected async getKey(): Promise<string> {
39
+ const res = await FS.readFile("fodec.key");
40
+
41
+ return res.toString();
42
+ }
43
+
44
+ public async init() {
45
+ const configPath = "./fodec-2.json";
46
+
47
+ if(existsSync(configPath)) {
48
+ throw new Error("Config already exists");
49
+ }
50
+
51
+ let config: Config = {} as Config;
52
+
53
+ config.basePath = await promptText({
54
+ required: true,
55
+ type: "string",
56
+ message: "Base Path:",
57
+ default: "src"
58
+ });
59
+
60
+ config.output = {
61
+ path: await promptText({
62
+ required: true,
63
+ type: "string",
64
+ message: "Output path:",
65
+ default: "build"
66
+ })
67
+ };
68
+
69
+ config.alphabets = await promptSelect({
70
+ multiple: true,
71
+ options: [
72
+ "cyrillic",
73
+ "latin"
74
+ ]
75
+ }) as Config["alphabets"];
76
+
77
+ config.resources = [];
78
+
79
+ await FS.writeFile(configPath, JSON.stringify(config, null, 4));
80
+ }
81
+
82
+ public async generate() {
83
+ const {alphabets} = await this.getConfig();
84
+
85
+ const key = generateKey({
86
+ alphabets
87
+ });
88
+
89
+ console.log(key);
90
+
91
+ await FS.writeFile("fodec.key", key);
92
+ }
93
+
94
+ public async build(): Promise<void> {
95
+ const key = await this.getKey();
96
+ const {
97
+ basePath = "./",
98
+ output: {
99
+ path: outPath = "./build"
100
+ } = {},
101
+ fonts,
102
+ resources
103
+ } = await this.getConfig();
104
+
105
+ const fodec = new Fodec(key);
106
+
107
+ for(const resource of resources) {
108
+ let res: any;
109
+
110
+ if(resource.type === "font") {
111
+ const transformedFont = await fodec.transformFont(
112
+ Path.join(basePath, resource.path)
113
+ );
114
+
115
+ if(!transformedFont || transformedFont instanceof ArrayBuffer) {
116
+ continue;
117
+ }
118
+
119
+ res = transformedFont;
120
+ }
121
+ else if(resource.type === "json") {
122
+ const json = await FS.readFile(
123
+ Path.join(basePath, resource.path)
124
+ );
125
+
126
+ const data = JSON.parse(json.toString());
127
+
128
+ res = JSON.stringify(data, (key, value) => {
129
+ if(typeof value === "string") {
130
+ return fodec.transformText(value);
131
+ }
132
+
133
+ return value;
134
+ }, 4);
135
+ }
136
+
137
+ if(res) {
138
+ const outFullPath = Path.join(outPath, Path.dirname(resource.output || resource.path));
139
+
140
+ mkdirSync(outFullPath, {
141
+ recursive: true
142
+ });
143
+
144
+ await FS.writeFile(
145
+ Path.join(outPath, resource.output || resource.path),
146
+ res
147
+ );
148
+ }
149
+ }
150
+ }
151
+
152
+ public async run() {
153
+ return this.cli.run(process.argv);
154
+ }
155
+ }
@@ -0,0 +1,4 @@
1
+ import {App} from "./App";
2
+
3
+
4
+ export const app = new App();
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export {Fodec} from "./Fodec";
@@ -0,0 +1,28 @@
1
+ import {AlphabetType} from "./MapAlphabets";
2
+
3
+ export type Config = {
4
+ basePath?: string;
5
+ output?: {
6
+ path: string;
7
+ };
8
+ alphabets: AlphabetType[];
9
+ fonts: {
10
+ name: string;
11
+ path: string;
12
+ }[];
13
+ resources: (FontResource | JsonResource)[];
14
+ };
15
+
16
+ type FontResource = {
17
+ type: "font",
18
+ format: string;
19
+ name: string;
20
+ path: string;
21
+ output?: string;
22
+ };
23
+
24
+ type JsonResource = {
25
+ type: "json",
26
+ path: string;
27
+ output?: string;
28
+ };
@@ -0,0 +1,28 @@
1
+ export const MapAlphabets = {
2
+ latin: {
3
+ lowerStart: 0x61,
4
+ lowerLength: 26,
5
+ upperStart: 0x41,
6
+ upperLength: 26
7
+ },
8
+ cyrillic: {
9
+ lowerStart: 0x430,
10
+ lowerLength: 32,
11
+ upperStart: 0x410,
12
+ upperLength: 32
13
+ },
14
+ arabic: {
15
+ lowerStart: 0x0620,
16
+ lowerLength: 36,
17
+ upperStart: 0x0620,
18
+ upperLength: 36
19
+ },
20
+ greek: {
21
+ lowerStart: 0x03B1,
22
+ lowerLength: 25,
23
+ upperStart: 0x0391,
24
+ upperLength: 25
25
+ }
26
+ };
27
+
28
+ export type AlphabetType = keyof typeof MapAlphabets;
@@ -0,0 +1,39 @@
1
+ import {shuffle} from "./shuffle";
2
+ import {MapAlphabets, AlphabetType} from "../types/MapAlphabets";
3
+
4
+
5
+ type Options = {
6
+ alphabets: AlphabetType[];
7
+ };
8
+
9
+ export const generateKey = (options: Options): string => {
10
+ const {
11
+ alphabets
12
+ } = options;
13
+
14
+ return Object.keys(MapAlphabets).reduce((res: string[], key: string) => {
15
+ if(!alphabets.includes(key as AlphabetType)) {
16
+ return res;
17
+ }
18
+
19
+ const {
20
+ lowerStart,
21
+ lowerLength,
22
+ upperStart,
23
+ upperLength
24
+ } = MapAlphabets[key];
25
+
26
+ const indexes = [
27
+ ...Array.from({length: lowerLength}, (_, i) => lowerStart + i),
28
+ ...Array.from({length: upperLength}, (_, i) => upperStart + i)
29
+ ];
30
+ const moved = indexes.slice();
31
+
32
+ shuffle(moved);
33
+
34
+ return [
35
+ res[0] + String.fromCharCode(...indexes),
36
+ res[1] + String.fromCharCode(...moved)
37
+ ];
38
+ }, ["", ""]).join("\n");
39
+ };
@@ -0,0 +1,7 @@
1
+ export const shuffle = (arr: unknown[]) => {
2
+ for(let i = arr.length - 1; i > 0; i--) {
3
+ let j = Math.floor(Math.random() * (i + 1));
4
+
5
+ [arr[i], arr[j]] = [arr[j], arr[i]];
6
+ }
7
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "compilerOptions": {
3
+ "allowJs": true,
4
+ "allowSyntheticDefaultImports": true,
5
+ "baseUrl": ".",
6
+ "declaration": true,
7
+ "esModuleInterop": true,
8
+ "forceConsistentCasingInFileNames": true,
9
+ "isolatedModules": true,
10
+ "lib": [
11
+ "dom",
12
+ "dom.iterable",
13
+ "esnext"
14
+ ],
15
+ "module": "CommonJS",
16
+ "moduleResolution": "node",
17
+ "noEmit": false,
18
+ "noFallthroughCasesInSwitch": true,
19
+ "noImplicitAny": false,
20
+ "outDir": "./lib",
21
+ "resolveJsonModule": true,
22
+ "skipLibCheck": true,
23
+ "strict": true,
24
+ "target": "ES2020",
25
+ "typeRoots": [
26
+ "./node_modules/@types"
27
+ ]
28
+ },
29
+ "exclude": [
30
+ "node_modules",
31
+ "lib",
32
+ "./**/__tests__/*"
33
+ ],
34
+ "include": [
35
+ "src/**/*"
36
+ ]
37
+ }