From 3d0c2070ebb4441555385d9e0c9c02eaf92f05ca Mon Sep 17 00:00:00 2001 From: kangkang520 Date: Mon, 12 Nov 2018 23:18:51 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BC=96=E7=A0=81+=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +++ .npmignore | 4 +++ README.md | 25 ++++++++++++++ package.json | 25 ++++++++++++++ src/index.ts | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++ test/test.ini | 19 +++++++++++ test/test.ts | 6 ++++ tsconfig.json | 60 +++++++++++++++++++++++++++++++++ 8 files changed, 236 insertions(+) create mode 100644 .gitignore create mode 100644 .npmignore create mode 100644 README.md create mode 100644 package.json create mode 100644 src/index.ts create mode 100644 test/test.ini create mode 100644 test/test.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..546a918 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/node_modules +/dist +/package-lock.json +/typing \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..4286841 --- /dev/null +++ b/.npmignore @@ -0,0 +1,4 @@ +/node_modules +/package-lock.json +/src +/test \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e5ea1c7 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# ini-decode + +ini file decoder for Node.js, using this util, you can read `.ini` file and even parse it to `.d.ts` file + +## installation + +``` +npm install ini-decode +``` + +## usage + +```typescript +import fs from 'fs' +import { decode } from 'ini-decode' + +//parse +const { json: configs, dts } = decode(fs.readFileSync('/path/to/ini')) + +//this is configs +console.log(configs) + +//you can write dts to a .d.ts file +fs.writeFileSync('/path/to/ini.d.ts', dts) +``` \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..506cabe --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "ini-decode", + "version": "1.0.2", + "description": "", + "main": "dist/index.js", + "types": "typing/index.d.ts", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "ini", + "config", + "typescript", + "declare", + "dts", + "parser", + "decode", + "configuration" + ], + "author": "", + "license": "ISC", + "devDependencies": { + "@types/node": "^10.12.5" + } +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..f2eb593 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,93 @@ + +//基础数据转换 +function parseBase(_content: string | Buffer) { + //最终返回结果 + const result = {} as any + //定义块 + let block: any + //此函数用于加入值到结果 + (_content + '') + //删除注释 + .replace(/[;#][\s\S]*?\r?\n/g, '\n') + //按行分割 + .split(/\r?\n/) + //trim + filter + .map(str => str.trim()).filter(str => !!str) + //单个处理 + .forEach(str => { + let match: Array | null + //块 + if (match = str.match(/^\[([\s\S]+)?\]$/)) { + //得到块名称,并按照点分割,并逐个处理 + block = result + match[1].trim().split('.').forEach(item => { + //路径处理 + block = block[item] = block[item] || {} + }) + } + else if (match = str.match(/^([\s\S]+)=([\s\S]+)?$/)) { + let [_, key, value] = match + key = key.trim() + value = value && value.trim() + //块校验 + if (!block) throw new Error(`Can't find block for item [${key}]`) + //存储值 + //1)数组格式1 + if (/\[\]$/.test(key)) { + key = key.substr(0, key.length - 2) + block[key] = block[key] || [] + block[key].push(value) + } + //2)数组格式2 + else if (value && value.indexOf(',') >= 0) { + block[key] = value.split(/,/).map(vi => vi.trim()).filter(vi => !!vi) + } + //3)其他 + else { + block[key] = value + } + } + }) + //现在已经转换完毕了 + return result +} + +//细节处理 +function parseDetail(data: any, parent: any, key: any): string { + if (typeof data == 'string') { + if (data == 'true' || data == 'false') { + if (parent && (key !== undefined || key !== null)) parent[key] = data == 'true' + return 'boolean' + } + if (/^\d+(\.\d+)?$/.test(data)) { + if (parent && (key !== undefined || key !== null)) parent[key] = (data as any) * 1 + return 'number' + } + else { + if (parent && (key !== undefined || key !== null)) parent[key] = data.replace(/^"/, '').replace(/"$/, '') + return 'string' + } + } + else if (data instanceof Array) { + if (data.length <= 0) return 'Array' + return `[${data.map((d, N) => parseDetail(d, data, N)).join(', ')}]` + } + else { + return `{\n\t${Object.keys(data).map(key => { + return `${key}: ${parseDetail(data[key], data, key).replace(/\n/g, '\n\t')}` + }).join('\n\t')}\n` + } +} + +/** + * 解码ini文件 + * @param content 数据内容 + */ +export function decode(content: string | Buffer) { + const base = parseBase(content) + const dts = parseDetail(base, null, null) + return { + json: base, + dts: dts, + } +} \ No newline at end of file diff --git a/test/test.ini b/test/test.ini new file mode 100644 index 0000000..e3c77d9 --- /dev/null +++ b/test/test.ini @@ -0,0 +1,19 @@ +[user.id1] +id = 1 +name = Mimi +gender = female +isAdmin = true + +[user.id2] +id = 2 +name = Mimi +gender = female +isAdmin = true + +[password] +# 注释 +admin = 123 +login = "456" +test[] = 789 +test[] = 789 +test2 = 123,456,"789" diff --git a/test/test.ts b/test/test.ts new file mode 100644 index 0000000..fa66e28 --- /dev/null +++ b/test/test.ts @@ -0,0 +1,6 @@ +import fs from 'fs' +import { decode } from '../src' + +const content = fs.readFileSync(__dirname + '/test.ini') +const res = decode(content) +console.log(res) \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..611ec4f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,60 @@ +{ + "compilerOptions": { + /* Basic Options */ + "target": "esnext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ + "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ + "lib": [ + "es2015" + ], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + "declaration": true, /* Generates corresponding '.d.ts' file. */ + "declarationDir": "./typing", /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./dist", /* Redirect output structure to the directory. */ + "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + }, + "include": [ + "src/**/*.ts" + ] +} \ No newline at end of file