Compare commits
11 Commits
tableclass
...
main
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e1dc531009 | ||
![]() |
35c075e1b5 | ||
![]() |
9b836cc360 | ||
![]() |
8b65a52035 | ||
![]() |
7c7ec2338b | ||
![]() |
c08017bd59 | ||
![]() |
a3f3c2ed09 | ||
![]() |
70e444d6a3 | ||
![]() |
2584a58df2 | ||
![]() |
fb632c1f72 | ||
![]() |
744e48e812 |
@ -1,2 +0,0 @@
|
||||
node_modules/
|
||||
dist/
|
@ -1,18 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
"rules": {
|
||||
"no-console": "off"
|
||||
}
|
||||
}
|
@ -1,7 +1,13 @@
|
||||
# bom2table
|
||||
|
||||
Generate a nicely formatted table from an EAGLE BOM
|
||||
|
||||
## Usage
|
||||
|
||||
Run `npm install` and `npm build`
|
||||
|
||||
Upload a BOM exported in csv format from EAGLE (untick 'List attributes') to get a table and the corresponding HTML.
|
||||
|
||||
## Credits
|
||||
|
||||
Favicon by [Round Icons](https://unsplash.com/illustrations/a-computer-chip-with-a-red-yellow-and-green-color-scheme-otzESK2sBG4?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash) via Unsplash
|
||||
|
17
eslint.config.mjs
Normal file
17
eslint.config.mjs
Normal file
@ -0,0 +1,17 @@
|
||||
// @ts-check
|
||||
|
||||
import eslint from '@eslint/js';
|
||||
import tseslint from 'typescript-eslint';
|
||||
|
||||
export default tseslint.config(
|
||||
{
|
||||
ignores: [
|
||||
'dist/**',
|
||||
'node_modules/**',
|
||||
'webpack.dev.js',
|
||||
'webpack.prod.js',
|
||||
],
|
||||
},
|
||||
eslint.configs.recommended,
|
||||
tseslint.configs.recommended,
|
||||
);
|
BIN
html/android-chrome-192x192.png
Normal file
BIN
html/android-chrome-192x192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.7 KiB |
BIN
html/android-chrome-512x512.png
Normal file
BIN
html/android-chrome-512x512.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
html/apple-touch-icon.png
Normal file
BIN
html/apple-touch-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
BIN
html/favicon-16x16.png
Normal file
BIN
html/favicon-16x16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 675 B |
BIN
html/favicon-32x32.png
Normal file
BIN
html/favicon-32x32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
BIN
html/favicon.ico
Normal file
BIN
html/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
@ -4,6 +4,10 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
<title>Read CSV File</title>
|
||||
</head>
|
||||
<body>
|
||||
|
1
html/site.webmanifest
Normal file
1
html/site.webmanifest
Normal file
@ -0,0 +1 @@
|
||||
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|
2070
package-lock.json
generated
2070
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@ -1,24 +1,29 @@
|
||||
{
|
||||
"name": "bom2table",
|
||||
"version": "1.3.0",
|
||||
"version": "2.1.0",
|
||||
"description": "",
|
||||
"main": "bom2table.js",
|
||||
"scripts": {
|
||||
"serve": "webpack serve --config webpack.dev.js",
|
||||
"build": "webpack --config webpack.prod.js"
|
||||
"build": "webpack --config webpack.prod.js",
|
||||
"lint": "eslint ."
|
||||
},
|
||||
"author": "nplayfair",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"csvtojson": "^2.0.10"
|
||||
"csvtojson": "^2.0.10",
|
||||
"htmlfy": "^0.7.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.28.0",
|
||||
"@types/csvtojson": "^1.1.5",
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"copy-webpack-plugin": "^13.0.0",
|
||||
"eslint": "^9.28.0",
|
||||
"prettier": "^3.5.3",
|
||||
"ts-loader": "^9.5.2",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.34.0",
|
||||
"webpack": "^5.99.9",
|
||||
"webpack-cli": "^6.0.1",
|
||||
"webpack-dev-server": "^5.2.2"
|
||||
|
@ -1,3 +1,4 @@
|
||||
//Array of part names to omit from the BOM
|
||||
export const rejectedParts = [
|
||||
'TP1',
|
||||
'TP2',
|
||||
@ -19,3 +20,14 @@ export const rejectedParts = [
|
||||
'IN',
|
||||
'OUT',
|
||||
];
|
||||
|
||||
//Header titles for the table
|
||||
export const headers: string[] = ['Part', 'Value'];
|
||||
|
||||
//Config object for csv library
|
||||
export const csvConfig = {
|
||||
delimiter: `;`,
|
||||
quote: '"',
|
||||
ignoreEmpty: true,
|
||||
includeColumns: /(Part|Value)/,
|
||||
};
|
||||
|
@ -1,17 +1,9 @@
|
||||
import { CSVParseParam } from '../node_modules/csvtojson/v2/Parameters';
|
||||
import { isJunk } from './utils';
|
||||
const csv = require('csvtojson');
|
||||
|
||||
//CSV Config for EAGLE BOM
|
||||
const csvConfig = {
|
||||
delimiter: `;`,
|
||||
quote: '"',
|
||||
ignoreEmpty: true,
|
||||
includeColumns: /(Part|Value)/,
|
||||
};
|
||||
import { csvConfig, rejectedParts } from './config';
|
||||
// const csv = require('csvtojson');
|
||||
import csv from 'csvtojson';
|
||||
|
||||
export async function getBOM(csvBOM: string) {
|
||||
const rawBOM = await csv(csvConfig).fromString(csvBOM);
|
||||
const bom = rawBOM.filter((part: part) => !isJunk(part));
|
||||
const bom = rawBOM.filter((part: Part) => !rejectedParts.includes(part.Part));
|
||||
return bom;
|
||||
}
|
||||
|
30
src/index.ts
30
src/index.ts
@ -1,16 +1,15 @@
|
||||
//Modules
|
||||
import { getBOM } from './csvToJSON';
|
||||
import {
|
||||
createTableBody,
|
||||
createTableHeader,
|
||||
htmlTable,
|
||||
clearTable,
|
||||
} from './utils';
|
||||
import { PartsTable } from './table';
|
||||
import { headers } from './config';
|
||||
import { printHTMLtable } from './utils';
|
||||
|
||||
//DOM elements
|
||||
const input = document.getElementById('csvInput') as HTMLInputElement;
|
||||
const csvTextOutput = document.getElementById('csvText') as HTMLPreElement;
|
||||
const jsonTextOutput = document.getElementById('partsJSON') as HTMLPreElement;
|
||||
const partsHTML = document.getElementById('partsHTML') as HTMLPreElement;
|
||||
const htmlTable = document.getElementById('partsTable') as HTMLTableElement;
|
||||
|
||||
let csvBOM: string;
|
||||
|
||||
@ -37,35 +36,28 @@ function processCSV(fileReader: Event) {
|
||||
//JSON Object
|
||||
printJSONbom(csvString);
|
||||
//Table
|
||||
clearTable();
|
||||
createTable();
|
||||
//TODO Table HTML code
|
||||
}
|
||||
|
||||
//TODO
|
||||
//Print JSON
|
||||
async function printJSONbom(csvString: string) {
|
||||
const bomJSON = await getBOM(csvString);
|
||||
// console.log(bomJSON);
|
||||
jsonTextOutput.innerText = JSON.stringify(bomJSON, null, 2);
|
||||
return bomJSON;
|
||||
}
|
||||
|
||||
//Construct table
|
||||
async function createTable() {
|
||||
const bomJSON = await getBOM(csvBOM);
|
||||
createTableHeader();
|
||||
createTableBody(htmlTable, bomJSON);
|
||||
const partsTable = new PartsTable(htmlTable, headers, bomJSON);
|
||||
const tableMarkup = await partsTable.createTable();
|
||||
printHTMLtable(tableMarkup as HTMLTableElement, partsHTML);
|
||||
}
|
||||
|
||||
//Add event listener
|
||||
input.addEventListener('change', handleUpload);
|
||||
|
||||
/* TODO
|
||||
// Format the HTML nicely and output to a pre code block
|
||||
function displayMarkup() {
|
||||
const tableCode = document.querySelector('table')!.outerHTML;
|
||||
const markup = document.getElementById('markup') as HTMLElement;
|
||||
markup.innerText = beautify(tableCode);
|
||||
}
|
||||
|
||||
// Create a JSON object for Contentful
|
||||
function makeJSON(csvString: string) {
|
||||
csv({
|
||||
|
20
src/parts.d.ts
vendored
20
src/parts.d.ts
vendored
@ -1,4 +1,4 @@
|
||||
enum PartType {
|
||||
enum ComponentType {
|
||||
R,
|
||||
C,
|
||||
D,
|
||||
@ -7,12 +7,26 @@ enum PartType {
|
||||
COMPONENT,
|
||||
}
|
||||
|
||||
declare interface part {
|
||||
enum Potentiometers {
|
||||
VOL = 'VOL',
|
||||
TONE = 'TONE',
|
||||
GAIN = 'GAIN',
|
||||
RES = 'RES',
|
||||
LEVEL = 'LEVEL',
|
||||
DIST = 'DIST',
|
||||
PRESENCE = 'PRESENCE',
|
||||
}
|
||||
|
||||
declare interface Part {
|
||||
Part: string;
|
||||
PartType?: PartType;
|
||||
Value: string;
|
||||
}
|
||||
|
||||
declare interface Component extends Part {
|
||||
Designator: string; //A letter like R, C, D etc
|
||||
ComponentType: ComponentType;
|
||||
}
|
||||
|
||||
declare interface structuredParts {
|
||||
C: {
|
||||
[key: string]: string;
|
||||
|
10
src/table.ts
10
src/table.ts
@ -2,7 +2,7 @@ export class PartsTable {
|
||||
constructor(
|
||||
public htmlTable: HTMLTableElement,
|
||||
public headers: string[],
|
||||
public jsonBOM: part[],
|
||||
public jsonBOM: Part[],
|
||||
) {}
|
||||
|
||||
//Reset table
|
||||
@ -38,4 +38,12 @@ export class PartsTable {
|
||||
partValue.appendChild(partValText);
|
||||
});
|
||||
}
|
||||
|
||||
//Create full table
|
||||
public createTable(): HTMLElement {
|
||||
this.clearTable();
|
||||
this.createTableHeader();
|
||||
this.createTableBody();
|
||||
return this.htmlTable;
|
||||
}
|
||||
}
|
||||
|
48
src/utils.ts
48
src/utils.ts
@ -1,45 +1,11 @@
|
||||
import { rejectedParts } from './config';
|
||||
import { prettify } from 'htmlfy';
|
||||
|
||||
export function isJunk(element: part): boolean {
|
||||
// Returns true if element is in the rejected list
|
||||
return rejectedParts.includes(element.Part);
|
||||
}
|
||||
|
||||
//Table functions
|
||||
export function clearTable() {
|
||||
document.querySelector('table')!.innerHTML = '';
|
||||
}
|
||||
|
||||
export const htmlTable = document.getElementById(
|
||||
'partsTable',
|
||||
) as HTMLTableElement;
|
||||
const headers: string[] = ['Part', 'Value'];
|
||||
|
||||
export function createTableHeader(): void {
|
||||
const tHead = htmlTable.createTHead();
|
||||
const hRow = tHead.insertRow();
|
||||
//Populate headers with text
|
||||
for (const header of headers) {
|
||||
const th = document.createElement('th');
|
||||
const headerText = document.createTextNode(header);
|
||||
th.appendChild(headerText);
|
||||
hRow.appendChild(th);
|
||||
}
|
||||
}
|
||||
|
||||
export function createTableBody(table: HTMLTableElement, parts: part[]) {
|
||||
parts.map((component) => {
|
||||
//Create a row
|
||||
const tRow = table.insertRow();
|
||||
//Insert part name
|
||||
const partName = tRow.insertCell();
|
||||
const partNameText = document.createTextNode(component.Part);
|
||||
partName.appendChild(partNameText);
|
||||
//Insert part value
|
||||
const partValue = tRow.insertCell();
|
||||
const partValText = document.createTextNode(component.Value);
|
||||
partValue.appendChild(partValText);
|
||||
});
|
||||
//Print HTML code
|
||||
export async function printHTMLtable(
|
||||
table: HTMLTableElement,
|
||||
codeBlock: HTMLPreElement,
|
||||
) {
|
||||
codeBlock.innerText = prettify(table.outerHTML);
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
@ -46,7 +46,7 @@
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
|
||||
|
||||
/* Module Resolution Options */
|
||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
"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. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user