diff --git a/.gitignore b/.gitignore index 6af9062..d0976fe 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,7 @@ coverage/ npm-debug.log package-lock.json .nyc_output +.idea +.vscode +.DS_Store +coverage.lcov \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index b58b603..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index 1498927..0000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123..0000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 0be03f4..0000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index a0733a5..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/project.iml b/.idea/project.iml deleted file mode 100644 index 24643cc..0000000 --- a/.idea/project.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.npmignore b/.npmignore index 16cbd3b..8b4d37f 100644 --- a/.npmignore +++ b/.npmignore @@ -1,6 +1,15 @@ .editorconfig .npmignore +.vscode +.eslintrc +.nycrc .travis.yml +.bower.json +.nyc_output package-lock.json -docs/ -jest_result.png \ No newline at end of file +test-result.png +tests +example +coverage +node_modules +coverage.lcov \ No newline at end of file diff --git a/.nycrc b/.nycrc new file mode 100644 index 0000000..aa53c2d --- /dev/null +++ b/.nycrc @@ -0,0 +1,13 @@ +{ + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "tests/*.test.js" + ], + "all": true, + "sourceMap": true, + "cache": false, + "check-coverage": true, + "extension": [".ts"] +} \ No newline at end of file diff --git a/README.md b/README.md index fd5c34a..57e8403 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -![](https://socialify.git.ci/jukbot/thai-citizen-id-validator/image?description=1&language=1&pattern=Signal&theme=Light) - # Thai Citizen ID Validator +![thai-citizen-id-validator](https://socialify.git.ci/jukbot/thai-citizen-id-validator/image?description=1&font=Inter&language=1&name=1&pattern=Signal&stargazers=1&theme=Light) + [![Codacy Badge](https://app.codacy.com/project/badge/Grade/d49ee28fb17b476baeb9387e6888b751)](https://app.codacy.com/gh/jukbot/thai-citizen-id-validator/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) [![Codacy Badge](https://app.codacy.com/project/badge/Coverage/d49ee28fb17b476baeb9387e6888b751)](https://app.codacy.com/gh/jukbot/thai-citizen-id-validator/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage) [![NPM Download](https://img.shields.io/npm/dt/thai-id-validator.svg)](https://www.npmjs.com/package/thai-id-validator) @@ -10,9 +10,14 @@ A simpler way to validate Thai Citizen Card ID. 🇹🇭 -## Further Plans +## Minimum Node.js Version ⚠️ + +This package requires Node.js version 16 or later. + +## Future Roadmap - Go Language Implementation Example +- .NET Language Implementation Example - Thai Passport Number Validation ## Read the article @@ -39,31 +44,17 @@ $ bun add thai-id-validator ## Usage -### Javascipt ES5 - -Just import script with commonjs - -```javascript -var validateThaiID = require('thai-id-validator') // for ES5 - -var result = validateThaiID(‘1101700207030’); - -console.log(result); -// return true -``` - -### Javascript ES6 Module +### Javascript In Javascript file, you can use import, export modules ```javascript -'use strict'; import validateThaiID from 'thai-id-validator'; let result = validateThaiID(‘1101700207030’); console.log(result); -// return true +// true ``` ## Test @@ -71,7 +62,7 @@ console.log(result); To run all test cases run the following command ```bash -npm run test +bun run test ``` You can edit validator.test.js too add your custom test case. @@ -121,6 +112,6 @@ If you found any 🐞 or feedback, please report the issue [here](https://github ## License -[Apache2.0](https://www.apache.org/licenses/LICENSE-2.0) +[MIt](https://opensource.org/license/mit) Code with love 🦉 diff --git a/bun.lockb b/bun.lockb index 73052f2..8d516a0 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/bunfig.toml b/bunfig.toml deleted file mode 100644 index 119113b..0000000 --- a/bunfig.toml +++ /dev/null @@ -1,4 +0,0 @@ -[test] - -# always enable coverage -coverage = true \ No newline at end of file diff --git a/dist/assets/index-Bjn-ATP8.css b/dist/assets/index-Bjn-ATP8.css new file mode 100644 index 0000000..70964da --- /dev/null +++ b/dist/assets/index-Bjn-ATP8.css @@ -0,0 +1 @@ +*{box-sizing:border-box;margin:0;padding:0;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{max-height:100vh;font-family:-apple-system,BlinkMacSystemFont,Arial,sans-serif;font-size:1rem;color:#333;background:#ece9e6;background:-webkit-linear-gradient(to right,#ece9e6,#ffffff);background:linear-gradient(to right,#ece9e6,#fff)}input,select,textarea{appearance:none;border:none;box-sizing:border-box;display:block;outline:none;width:100%;-webkit-appearance:none;-moz-appearance:none}h1,h2,p{text-align:center}section{margin:6rem 0;padding:16px}form{margin:16px auto;max-width:700px}button{position:relative;background-color:#fff;border:1px solid #e4e4e4;border-radius:5px;display:block;font-size:1rem;margin:0 auto;color:#333;padding:12px 40px;box-shadow:0 1px 2px #0000001a;-webkit-transition:all .6s cubic-bezier(.165,.84,.44,1);transition:all .6s cubic-bezier(.165,.84,.44,1)}button:after:not([disabled]){content:"";border-radius:5px;position:absolute;z-index:-1;top:0;left:0;width:100%;height:100%;box-shadow:0 5px 15px #0000004d;opacity:0;-webkit-transition:all .6s cubic-bezier(.165,.84,.44,1);transition:all .6s cubic-bezier(.165,.84,.44,1)}button:hover:after{opacity:1}button:hover:not([disabled]){border:1px solid #e4e4e4;cursor:pointer;-webkit-transform:scale(1.1,1.1);transform:scale(1.1)}button:disabled{color:silver;background-color:#eee;cursor:not-allowed}.label{display:block;margin-bottom:1em;text-align:center}.input{padding:10px;border:1px solid #e4e4e4;border-radius:4px;background-color:#fff;font-size:1.25rem;text-align:center;margin-bottom:1rem}.input:focus{border-color:silver}.input::placeholder{color:#ddd}.text{max-width:700px;margin:2rem auto;padding:1.5rem;line-height:0}.error{color:#b22222;background-color:#fa000012}.success{color:green;background-color:#00c80017}#errorMessage,#successMessage{display:none} diff --git a/dist/assets/index-ByB4O58P.js b/dist/assets/index-ByB4O58P.js new file mode 100644 index 0000000..de7f4df --- /dev/null +++ b/dist/assets/index-ByB4O58P.js @@ -0,0 +1 @@ +(function(){const n=document.createElement("link").relList;if(n&&n.supports&&n.supports("modulepreload"))return;for(const e of document.querySelectorAll('link[rel="modulepreload"]'))i(e);new MutationObserver(e=>{for(const t of e)if(t.type==="childList")for(const a of t.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&i(a)}).observe(document,{childList:!0,subtree:!0});function o(e){const t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin==="use-credentials"?t.credentials="include":e.crossOrigin==="anonymous"?t.credentials="omit":t.credentials="same-origin",t}function i(e){if(e.ep)return;e.ep=!0;const t=o(e);fetch(e.href,t)}})();var p=(r,n)=>()=>(n||r((n={exports:{}}).exports,n),n.exports),g=p((r,n)=>{function o(i){if(typeof i=="number"&&(i=i.toString()),!/^\d{13}$/.test(i))return!1;let e=0;for(let t=0;t<12;t++)e+=Number(i[t])*(13-t);return(11-e%11)%10===Number(i[12])}typeof n<"u"&&typeof n.exports<"u"?(n.exports=o,r.default=o,r.isValidThaiID=o):typeof window<"u"&&(window.isValidThaiID=o)});const y=g();document.addEventListener("DOMContentLoaded",()=>{const r=document.getElementById("citizenid"),n=document.getElementById("button"),o=document.getElementById("errorMessage"),i=document.getElementById("successMessage"),e=IMask(r,{mask:"0-0000-00000-00-0"});r.addEventListener("input",t),r.addEventListener("keypress",a),n.addEventListener("click",c);function t(){const s=e.unmaskedValue,l=13,f=/^[0-9]\d*$/,u=s.length===l,m=f.test(s),d=y(s);n.disabled=!(u&&m&&d),r.setAttribute("aria-invalid",String(!d)),o.setAttribute("aria-hidden",String(d)),i.setAttribute("aria-hidden",String(!d)),o.style.display=u?d?"none":"block":"none",i.style.display=u&&d?"block":"none"}function a(s){if(s.code==="Enter")return s.preventDefault(),!1}function c(s){s.preventDefault(),s.stopImmediatePropagation(),window.alert("Your citizen ID submit value is: "+e.unmaskedValue)}}); diff --git a/dist/browser/validator.js b/dist/browser/validator.js new file mode 100644 index 0000000..e1c1ad9 --- /dev/null +++ b/dist/browser/validator.js @@ -0,0 +1 @@ +var C=(j,k)=>()=>(k||j((k={exports:{}}).exports,k),k.exports);var E=C((B,A)=>{function z(j){if(typeof j==="number")j=j.toString();if(!/^\d{13}$/.test(j))return!1;let k=0;for(let q=0;q<12;q++)k+=Number(j[q])*(13-q);return(11-k%11)%10===Number(j[12])}if(typeof A!=="undefined"&&typeof A.exports!=="undefined")A.exports=z,B.default=z,B.isValidThaiID=z;else if(typeof window!=="undefined")window.isValidThaiID=z});export default E(); diff --git a/dist/esm/validator.js b/dist/esm/validator.js new file mode 100644 index 0000000..e1c1ad9 --- /dev/null +++ b/dist/esm/validator.js @@ -0,0 +1 @@ +var C=(j,k)=>()=>(k||j((k={exports:{}}).exports,k),k.exports);var E=C((B,A)=>{function z(j){if(typeof j==="number")j=j.toString();if(!/^\d{13}$/.test(j))return!1;let k=0;for(let q=0;q<12;q++)k+=Number(j[q])*(13-q);return(11-k%11)%10===Number(j[12])}if(typeof A!=="undefined"&&typeof A.exports!=="undefined")A.exports=z,B.default=z,B.isValidThaiID=z;else if(typeof window!=="undefined")window.isValidThaiID=z});export default E(); diff --git a/dist/index.html b/dist/index.html new file mode 100644 index 0000000..0fefad4 --- /dev/null +++ b/dist/index.html @@ -0,0 +1,139 @@ + + + + + + + + Thai Citizen ID Input Validation + + + + + + + + + + +
+

Thai Citizen ID Validation with WCAG Standard

+ +

ตรวจสอบความถูกต้องเลขบัตรประชาชน

+ +
+ + + +
+ + +
+ + diff --git a/dist/validator.es.js b/dist/validator.es.js deleted file mode 100644 index 6911a55..0000000 --- a/dist/validator.es.js +++ /dev/null @@ -1,12 +0,0 @@ -function t(i) { - if (!/^\d{13}$/.test(i)) - return !1; - let o = 0; - for (let e = 0; e < 12; e++) - o += Number(i[e]) * (13 - e); - return (11 - o % 11) % 10 === Number(i[12]); -} -typeof module < "u" && typeof module.exports < "u" ? (module.exports = t, exports.default = t, exports.isValidThaiID = t) : typeof window < "u" && (window.isValidThaiID = t); -export { - t as default -}; diff --git a/dist/validator.umd.js b/dist/validator.umd.js deleted file mode 100644 index 20ce0a6..0000000 --- a/dist/validator.umd.js +++ /dev/null @@ -1 +0,0 @@ -(function(e,i){typeof exports=="object"&&typeof module<"u"?module.exports=i():typeof define=="function"&&define.amd?define(i):(e=typeof globalThis<"u"?globalThis:e||self,e.validateThaiID=i())})(this,function(){"use strict";function e(i){if(!/^\d{13}$/.test(i))return!1;let n=0;for(let t=0;t<12;t++)n+=Number(i[t])*(13-t);return(11-n%11)%10===Number(i[12])}return typeof module<"u"&&typeof module.exports<"u"?(module.exports=e,exports.default=e,exports.isValidThaiID=e):typeof window<"u"&&(window.isValidThaiID=e),e}); diff --git a/docs/js/script.js b/docs/js/script.js index 7277731..9f00fe2 100644 --- a/docs/js/script.js +++ b/docs/js/script.js @@ -1,4 +1,4 @@ -import validateThaiID from '../../lib/validator' +import validateThaiID from '../../dist/browser/validator.js' document.addEventListener('DOMContentLoaded', () => { const input = document.getElementById('citizenid') diff --git a/global.d.ts b/global.d.ts deleted file mode 100644 index dd9b16c..0000000 --- a/global.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare global { - interface Window { - isValidThaiID: (id: string) => boolean; - } -} diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..13b1fea --- /dev/null +++ b/index.d.ts @@ -0,0 +1,9 @@ +declare function isValidThaiID(input: string | number): boolean; + +export interface Window { + isValidThaiID: typeof isValidThaiID; +} + +export as namespace isValidThaiID; +export { isValidThaiID }; +export default isValidThaiID; \ No newline at end of file diff --git a/jsr.json b/jsr.json new file mode 100644 index 0000000..053d63b --- /dev/null +++ b/jsr.json @@ -0,0 +1,9 @@ +{ + "name": "@jukbot/thai-id-validator", + "version": "1.1.5", + "exports": { + ".": { + "import": "./dist/validator.js" + } + } + } \ No newline at end of file diff --git a/package.json b/package.json index c66d7d7..5127fe3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "thai-id-validator", - "version": "1.1.5", - "description": "Thai Citizen ID validator with zero dependencies", + "version": "1.1.6", + "description": "Thai Citizen ID validator with 0 dependencies", "keywords": [ "thai-citizen-id", "id-validator", @@ -11,53 +11,58 @@ "files": [ "dist" ], - "main": "./dist/validator.umd.js", - "module": "./dist/validator.es.js", + "type": "module", + "types": "./index.d.ts", + "main": "./dist/esm/validator.js", + "module": "./dist/esm/validator.js", "exports": { ".": { - "import": "./dist/validator.es.js", - "require": "./dist/validator.umd.js" + "import": "./dist/esm/validator.js" } }, + "homepage": "https://github.com/jukbot/thai-citizen-id-validator#readme", "repository": { "type": "git", - "url": "git+https://github.com/jukbot/thai-citizen-id-validatorr.git" + "url": "git+https://github.com/jukbot/thai-citizen-id-validator.git" }, "bugs": { "url": "https://github.com/jukbot/thai-citizen-id-validator/issues" }, - "homepage": "https://github.com/jukbot/thai-citizen-id-validator#readme", "directories": { "dist": "dist", - "lib": "lib", - "test": "test" + "src": "src", + "test": "tests" }, "scripts": { - "dev": "vite --config vite-docs.config.js", - "build": "vite build", - "build:lib": "vite build", - "build:docs": "vite build --config vite-docs.config.js", + "build": "bun run build:browser && bun run build:node", + "build:browser": "bun build ./src/validator.ts --outdir dist/browser --target browser --minify", + "build:node": "bun build ./src/validator.ts --outdir dist/esm --target node --format esm --minify", + "dev:docs": "vite --config vite-docs.config.cjs", + "build:docs": "vite build --config vite-docs.config.cjs", "lint": "standard", "test": "bun test", - "coverage": "nyc --reporter=lcov --reporter=text-summary bun test --coverage" + "coverage": "nyc --reporter=lcov --reporter=text-summary bun test --coverage", + "type-check": "tsc --noEmit" }, - "author": "Juk V.", + "author": "Juk V. ", "license": "MIT", "devDependencies": { - "eslint": "^9.2.0", - "nyc": "^15.1.0", + "@istanbuljs/nyc-config-typescript": "^1.0.2", + "@types/node": "^22.3.0", + "eslint": "^9.9.0", + "nyc": "^17.0.0", "standard": "^17.1.0", - "vite": "^5.2.11" + "typescript": "^5.5.4", + "vite": "^5.4.0" }, - "browserslist": [ - "last 1 version", - "> 1%", - "not dead" - ], "standard": { "ignore": [ "dist/**", "docs/**" ] - } -} + }, + "browserslist": [ + "last 1 version", + "> 1%" + ] +} \ No newline at end of file diff --git a/lib/validator.js b/src/validator.ts similarity index 67% rename from lib/validator.js rename to src/validator.ts index ba9cc50..022427e 100644 --- a/lib/validator.js +++ b/src/validator.ts @@ -1,13 +1,13 @@ -// @ts-check -'use strict' - /** - * Checks if a Thai ID is valid. - * - * @param {string} id - The Thai ID to validate, a 13-digit string. - * @returns {boolean} True if the Thai ID is valid, false otherwise. + * @author Juk V. + * @see {@link https://github.com/jukbot/thai-citizen-id-validator|GitHub} */ -function isValidThaiID (id) { + +function isValidThaiID(id: string | number): boolean { + // Convert number to string if the ID is a number. + if (typeof id === 'number') { + id = id.toString() + } // Check if the ID is a valid string of 13 digits. if (!/^\d{13}$/.test(id)) { return false @@ -30,8 +30,7 @@ if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { exports.default = isValidThaiID exports.isValidThaiID = isValidThaiID } else if (typeof window !== 'undefined') { + // Support legacy version of the browser. // @ts-ignore window.isValidThaiID = isValidThaiID } - -export default isValidThaiID diff --git a/test/validator.test.js b/tests/validator.test.js similarity index 96% rename from test/validator.test.js rename to tests/validator.test.js index a3582cd..3b653fb 100644 --- a/test/validator.test.js +++ b/tests/validator.test.js @@ -1,5 +1,5 @@ import { describe, it, expect } from 'bun:test' -import validateThaiID from '../lib/validator' +import validateThaiID from '../src/validator' describe('validateThaiID Function', () => { it('Case 1: Valid ID Correct pattern', () => { diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..c9fb976 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2022", // Target latest ECMAScript version + "module": "ESNext", // Use the latest module system + "declaration": true, // Generate declaration files + "outDir": "./dist", // Output directory for compiled files + "rootDir": "./src", // Root directory of input files + "sourceMap": true, // Generate source maps + "strict": true, // Enable all strict type-checking options + "removeComments": true, // Remove comments from the output + "esModuleInterop": true, // Enable interoperability between CommonJS and ES Modules + "skipLibCheck": true, // Skip type checking of declaration files + "forceConsistentCasingInFileNames": true // Ensure consistent casing in file names + }, + "include": ["src/**/*"], // Include all TypeScript files in the src directory + "exclude": ["node_modules", "dist", "tests"] // Exclude node_modules and dist directories +} \ No newline at end of file diff --git a/vite-docs.config.js b/vite-docs.config.cjs similarity index 97% rename from vite-docs.config.js rename to vite-docs.config.cjs index 4df2679..8ae979b 100644 --- a/vite-docs.config.js +++ b/vite-docs.config.cjs @@ -4,4 +4,4 @@ module.exports = { build: { outDir: '../dist' } -} +} \ No newline at end of file