@bobfrankston/extractids 1.0.0 → 1.0.2

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/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # extractids
2
+
3
+ `extractids` is a TypeScript utility that scans your `index.html` and all CSS files in your project to automatically generate type definitions for HTML IDs and CSS classes. These types allow you to perform type-checked DOM and class operations in your code, improving safety and developer experience.
4
+
5
+ ## How It Works
6
+ - Scans `index.html` for all `id` attributes.
7
+ - Scans all `.css` files for class names.
8
+ - Generates a `generated-types.ts` file containing:
9
+ - `htmlIDs` type: all HTML IDs found
10
+ - `cssClasses` type: all CSS class names found
11
+
12
+ You can then import these types in your TypeScript code:
13
+
14
+ ```typescript
15
+ import { type htmlIDs, type cssClasses } from './generated-types.js';
16
+ ```
17
+
18
+
19
+ ## Automatic Generation with VS Code Tasks
20
+ Install using
21
+ ```shell
22
+ npm install -g @bobfrankston/extractids
23
+ ```
24
+
25
+
26
+ If `extractids` is installed as a CLI app, you can run it automatically on startup by adding it to your `.vscode/tasks.json`. Here is an example:
27
+
28
+ ```jsonc
29
+ {
30
+ "version": "2.0.0",
31
+ "tasks": [
32
+ {
33
+ "label": "extractids: watch",
34
+ "type": "shell",
35
+ "command": "extractids",
36
+ "args": [],
37
+ "runOptions": {
38
+ "runOn": "folderOpen"
39
+ },
40
+ "isBackground": true,
41
+ "group": {
42
+ "kind": "build",
43
+ "isDefault": false
44
+ }
45
+ }
46
+ ]
47
+ }
48
+ ```
49
+
50
+ This will run `extractids` automatically when you open your project in VS Code, keeping your type definitions up to date.
51
+
52
+ ## Usage Example
53
+ ```typescript
54
+ import { htmlIDs, cssClasses } from './generated-types';
55
+
56
+ function setClass(elementId: htmlIDs, className: cssClasses) {
57
+ const el = document.getElementById(elementId);
58
+ if (el) el.classList.add(className);
59
+ }
60
+ ```
61
+
62
+ ## Benefits
63
+ - Type safety for DOM operations
64
+ - Autocomplete for IDs and class names
65
+ - Automatic updates when HTML or CSS changes
66
+
67
+ ---
68
+
69
+ Feel free to customize the task label and command to fit your workflow.
package/index.js CHANGED
@@ -1,17 +1,15 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
1
  // scripts/generateTypes.ts
4
- var fs = require("node:fs");
5
- var path = require("node:path");
6
- var cheerio = require("cheerio");
7
- var chokidar_1 = require("chokidar");
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
4
+ import * as cheerio from 'cheerio';
5
+ import chokidar from 'chokidar';
8
6
  // import * as glob from 'glob';
9
7
  // Helper function to extract all id attributes from HTML
10
8
  function getHtmlIDs(html) {
11
- var $ = cheerio.load(html);
12
- var ids = new Set();
13
- $('[id]').each(function (_, elem) {
14
- var id = $(elem).attr('id');
9
+ const $ = cheerio.load(html);
10
+ const ids = new Set();
11
+ $('[id]').each((_, elem) => {
12
+ const id = $(elem).attr('id');
15
13
  if (id)
16
14
  ids.add(id);
17
15
  });
@@ -20,9 +18,9 @@ function getHtmlIDs(html) {
20
18
  // Helper function to extract all class names from CSS files
21
19
  function getCssClasses(css) {
22
20
  // Match any .classname { or .classname,
23
- var classPattern = /\.([a-zA-Z0-9_-]+)\s*[{,]/g;
24
- var classes = new Set();
25
- var match;
21
+ const classPattern = /\.([a-zA-Z0-9_-]+)\s*[{,]/g;
22
+ const classes = new Set();
23
+ let match;
26
24
  while ((match = classPattern.exec(css))) {
27
25
  classes.add(match[1]);
28
26
  }
@@ -30,12 +28,11 @@ function getCssClasses(css) {
30
28
  }
31
29
  function globReadCssFiles() {
32
30
  // Recursively find all .css files in project folder, ignoring node_modules
33
- var result = [];
31
+ const result = [];
34
32
  function walk(dir) {
35
- var entries = fs.readdirSync(dir, { withFileTypes: true });
36
- for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {
37
- var entry = entries_1[_i];
38
- var fullPath = path.join(dir, entry.name);
33
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
34
+ for (const entry of entries) {
35
+ const fullPath = path.join(dir, entry.name);
39
36
  if (entry.isDirectory()) {
40
37
  if (entry.name === 'node_modules')
41
38
  continue;
@@ -50,28 +47,29 @@ function globReadCssFiles() {
50
47
  return result;
51
48
  }
52
49
  function generateTypes(ids, classes) {
53
- var idType = ids.length > 0
54
- ? "export type htmlIDs = ".concat(ids.map(function (id) { return "\"".concat(id, "\""); }).join(' | '), ";\n")
55
- : "export type htmlIDs = never;\n";
56
- var classType = classes.length > 0
57
- ? "export type cssClasses = ".concat(classes.map(function (cls) { return "\"".concat(cls, "\""); }).join(' | '), ";\n")
58
- : "export type cssClasses = never;\n";
50
+ const idType = ids.length > 0
51
+ ? `export type htmlIDs = ${ids.map(id => `"${id}"`).join(' | ')};\n`
52
+ : `export type htmlIDs = never;\n`;
53
+ const classType = classes.length > 0
54
+ ? `export type cssClasses = ${classes.map(cls => `"${cls}"`).join(' | ')};\n`
55
+ : `export type cssClasses = never;\n`;
59
56
  return idType + classType;
60
57
  }
61
58
  function updateTypesFile() {
62
- var html = fs.readFileSync('index.html', 'utf8');
63
- var ids = getHtmlIDs(html);
64
- var cssFiles = globReadCssFiles();
65
- var allClasses = new Set();
66
- cssFiles.forEach(function (file) {
67
- var css = fs.readFileSync(file, 'utf8');
68
- getCssClasses(css).forEach(function (cls) { return allClasses.add(cls); });
59
+ const html = fs.readFileSync('index.html', 'utf8');
60
+ const ids = getHtmlIDs(html);
61
+ const cssFiles = globReadCssFiles();
62
+ const allClasses = new Set();
63
+ cssFiles.forEach(file => {
64
+ const css = fs.readFileSync(file, 'utf8');
65
+ getCssClasses(css).forEach(cls => allClasses.add(cls));
69
66
  });
70
- var types = generateTypes(ids, Array.from(allClasses));
67
+ const types = generateTypes(ids, Array.from(allClasses));
71
68
  fs.writeFileSync('generated-types.ts', types);
72
69
  console.log('[Type generation] Updated generated-types.ts');
73
70
  }
74
71
  // Initial run
75
72
  updateTypesFile();
76
73
  // Watch for changes on HTML and CSS
77
- chokidar_1.default.watch(['index.html', '**/*.css'], { ignored: /node_modules/ }).on('change', function () { return updateTypesFile(); });
74
+ chokidar.watch(['index.html', '**/*.css'], { ignored: /node_modules/ }).on('change', () => updateTypesFile());
75
+ //# sourceMappingURL=index.js.map
package/index.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@bobfrankston/extractids",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "",
5
5
  "main": "index.js",
6
+ "bin": "index.js",
6
7
  "scripts": {
7
8
  "test": "echo \"Error: no test specified\" && exit 1"
8
9
  },
@@ -18,4 +19,4 @@
18
19
  "devDependencies": {
19
20
  "@types/node": "^24.5.2"
20
21
  }
21
- }
22
+ }
package/tsconfig.json CHANGED
@@ -3,9 +3,9 @@
3
3
  "target": "esnext",
4
4
  "module": "NodeNext",
5
5
  "moduleResolution": "NodeNext",
6
- "allowImportingTsExtensions": true,
6
+ // "allowImportingTsExtensions": true,
7
7
  "sourceMap": true,
8
- "noEmit": true,
8
+ // "noEmit": true,
9
9
  "esModuleInterop": true,
10
10
  "forceConsistentCasingInFileNames": true,
11
11
  "strict": true,