@dheerajsom/pinhub 0.1.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/README.md +152 -0
- package/SETUP.md +126 -0
- package/dist/boards/arduino-uno-r3.d.ts +2 -0
- package/dist/boards/arduino-uno-r3.js +133 -0
- package/dist/boards/esp32-devkit-v1.d.ts +2 -0
- package/dist/boards/esp32-devkit-v1.js +143 -0
- package/dist/boards/index.d.ts +2 -0
- package/dist/boards/index.js +12 -0
- package/dist/boards/pico-shared.d.ts +3 -0
- package/dist/boards/pico-shared.js +108 -0
- package/dist/boards/raspberry-pi-5.d.ts +2 -0
- package/dist/boards/raspberry-pi-5.js +108 -0
- package/dist/boards/raspberry-pi-pico-w.d.ts +2 -0
- package/dist/boards/raspberry-pi-pico-w.js +36 -0
- package/dist/boards/raspberry-pi-pico.d.ts +2 -0
- package/dist/boards/raspberry-pi-pico.js +36 -0
- package/dist/catalog.d.ts +22 -0
- package/dist/catalog.js +74 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +8 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +6 -0
- package/dist/model.d.ts +52 -0
- package/dist/model.js +6 -0
- package/dist/render/board.d.ts +12 -0
- package/dist/render/board.js +194 -0
- package/dist/render/chars.d.ts +16 -0
- package/dist/render/chars.js +28 -0
- package/dist/render/meta.d.ts +6 -0
- package/dist/render/meta.js +62 -0
- package/dist/render/theme.d.ts +9 -0
- package/dist/render/theme.js +37 -0
- package/dist/run.d.ts +18 -0
- package/dist/run.js +167 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +2 -0
- package/package.json +54 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raspberry Pi Pico / Pico W 40-pin castellated DIP edge. Physical pins run
|
|
3
|
+
* 1–20 down the left side and 21–40 back up the right side (USB at the top),
|
|
4
|
+
* so row r pairs physical pin r with physical pin 41−r.
|
|
5
|
+
*/
|
|
6
|
+
function edge(physical, label, category, extra = {}) {
|
|
7
|
+
const left = physical <= 20;
|
|
8
|
+
return {
|
|
9
|
+
physical,
|
|
10
|
+
position: {
|
|
11
|
+
row: left ? physical : 41 - physical,
|
|
12
|
+
column: left ? 1 : 2,
|
|
13
|
+
},
|
|
14
|
+
label,
|
|
15
|
+
category,
|
|
16
|
+
...extra,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const V33 = { voltage: "3.3 V" };
|
|
20
|
+
export function picoEdgeHeader() {
|
|
21
|
+
return {
|
|
22
|
+
id: "dip-edge",
|
|
23
|
+
name: "40-pin castellated DIP edge",
|
|
24
|
+
description: "Viewed from above with the USB connector at the top; pin 1 is top-left, pin 40 top-right.",
|
|
25
|
+
layout: { rows: 20, columns: 2 },
|
|
26
|
+
pins: [
|
|
27
|
+
edge(1, "GP0", "communication", { gpio: "GP0", functions: ["UART0 TX"], ...V33 }),
|
|
28
|
+
edge(2, "GP1", "communication", { gpio: "GP1", functions: ["UART0 RX"], ...V33 }),
|
|
29
|
+
edge(3, "GND", "ground"),
|
|
30
|
+
edge(4, "GP2", "gpio", { gpio: "GP2", ...V33 }),
|
|
31
|
+
edge(5, "GP3", "gpio", { gpio: "GP3", ...V33 }),
|
|
32
|
+
edge(6, "GP4", "communication", { gpio: "GP4", functions: ["I2C0 SDA"], ...V33 }),
|
|
33
|
+
edge(7, "GP5", "communication", { gpio: "GP5", functions: ["I2C0 SCL"], ...V33 }),
|
|
34
|
+
edge(8, "GND", "ground"),
|
|
35
|
+
edge(9, "GP6", "gpio", { gpio: "GP6", ...V33 }),
|
|
36
|
+
edge(10, "GP7", "gpio", { gpio: "GP7", ...V33 }),
|
|
37
|
+
edge(11, "GP8", "communication", { gpio: "GP8", functions: ["SPI1 RX"], ...V33 }),
|
|
38
|
+
edge(12, "GP9", "communication", { gpio: "GP9", functions: ["SPI1 CSn"], ...V33 }),
|
|
39
|
+
edge(13, "GND", "ground"),
|
|
40
|
+
edge(14, "GP10", "communication", { gpio: "GP10", functions: ["SPI1 SCK"], ...V33 }),
|
|
41
|
+
edge(15, "GP11", "communication", { gpio: "GP11", functions: ["SPI1 TX"], ...V33 }),
|
|
42
|
+
edge(16, "GP12", "gpio", { gpio: "GP12", ...V33 }),
|
|
43
|
+
edge(17, "GP13", "gpio", { gpio: "GP13", ...V33 }),
|
|
44
|
+
edge(18, "GND", "ground"),
|
|
45
|
+
edge(19, "GP14", "gpio", { gpio: "GP14", ...V33 }),
|
|
46
|
+
edge(20, "GP15", "gpio", { gpio: "GP15", ...V33 }),
|
|
47
|
+
edge(21, "GP16", "communication", { gpio: "GP16", functions: ["SPI0 RX"], ...V33 }),
|
|
48
|
+
edge(22, "GP17", "communication", { gpio: "GP17", functions: ["SPI0 CSn"], ...V33 }),
|
|
49
|
+
edge(23, "GND", "ground"),
|
|
50
|
+
edge(24, "GP18", "communication", { gpio: "GP18", functions: ["SPI0 SCK"], ...V33 }),
|
|
51
|
+
edge(25, "GP19", "communication", { gpio: "GP19", functions: ["SPI0 TX"], ...V33 }),
|
|
52
|
+
edge(26, "GP20", "communication", { gpio: "GP20", functions: ["I2C0 SDA"], ...V33 }),
|
|
53
|
+
edge(27, "GP21", "communication", { gpio: "GP21", functions: ["I2C0 SCL"], ...V33 }),
|
|
54
|
+
edge(28, "GND", "ground"),
|
|
55
|
+
edge(29, "GP22", "gpio", { gpio: "GP22", ...V33 }),
|
|
56
|
+
edge(30, "RUN", "reserved", {
|
|
57
|
+
notes: ["Reset control: pull low to reset the board"],
|
|
58
|
+
...V33,
|
|
59
|
+
}),
|
|
60
|
+
edge(31, "GP26", "analog", { gpio: "GP26", functions: ["ADC0"], ...V33 }),
|
|
61
|
+
edge(32, "GP27", "analog", { gpio: "GP27", functions: ["ADC1"], ...V33 }),
|
|
62
|
+
edge(33, "AGND", "ground", { notes: ["Analog ground reference"] }),
|
|
63
|
+
edge(34, "GP28", "analog", { gpio: "GP28", functions: ["ADC2"], ...V33 }),
|
|
64
|
+
edge(35, "ADC_VREF", "analog", {
|
|
65
|
+
notes: ["ADC reference voltage input/output"],
|
|
66
|
+
...V33,
|
|
67
|
+
}),
|
|
68
|
+
edge(36, "3V3", "power", { voltage: "3.3 V", functions: ["3V3(OUT)"] }),
|
|
69
|
+
edge(37, "3V3_EN", "reserved", {
|
|
70
|
+
notes: ["Pull low to disable the onboard 3.3 V regulator"],
|
|
71
|
+
}),
|
|
72
|
+
edge(38, "GND", "ground"),
|
|
73
|
+
edge(39, "VSYS", "power", { voltage: "1.8–5.5 V", notes: ["Main system input voltage"] }),
|
|
74
|
+
edge(40, "VBUS", "power", { voltage: "5 V", notes: ["USB bus voltage"] }),
|
|
75
|
+
],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
export function picoDebugHeader(swdName) {
|
|
79
|
+
return {
|
|
80
|
+
id: "swd",
|
|
81
|
+
name: swdName,
|
|
82
|
+
layout: { rows: 3, columns: 1 },
|
|
83
|
+
pins: [
|
|
84
|
+
{
|
|
85
|
+
physical: 1,
|
|
86
|
+
position: { row: 1, column: 1 },
|
|
87
|
+
label: "SWCLK",
|
|
88
|
+
category: "communication",
|
|
89
|
+
functions: ["SWD clock"],
|
|
90
|
+
voltage: "3.3 V",
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
physical: 2,
|
|
94
|
+
position: { row: 2, column: 1 },
|
|
95
|
+
label: "GND",
|
|
96
|
+
category: "ground",
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
physical: 3,
|
|
100
|
+
position: { row: 3, column: 1 },
|
|
101
|
+
label: "SWDIO",
|
|
102
|
+
category: "communication",
|
|
103
|
+
functions: ["SWD data"],
|
|
104
|
+
voltage: "3.3 V",
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 40-pin J8 header pin. Odd physical pins sit in column 1, even in column 2,
|
|
3
|
+
* one pin pair per row — matching the physical header viewed from above.
|
|
4
|
+
*/
|
|
5
|
+
function j8(physical, label, category, extra = {}) {
|
|
6
|
+
return {
|
|
7
|
+
physical,
|
|
8
|
+
position: { row: Math.ceil(physical / 2), column: physical % 2 === 1 ? 1 : 2 },
|
|
9
|
+
label,
|
|
10
|
+
category,
|
|
11
|
+
...extra,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
const V33 = { voltage: "3.3 V" };
|
|
15
|
+
export const raspberryPi5 = {
|
|
16
|
+
id: "raspberry-pi-5",
|
|
17
|
+
name: "Raspberry Pi 5",
|
|
18
|
+
manufacturer: "Raspberry Pi",
|
|
19
|
+
aliases: ["rpi5", "pi5", "raspberry-pi-5", "rpi-5", "pi-5", "raspi5"],
|
|
20
|
+
description: "Current mainstream Raspberry Pi SBC with the standard 40-pin GPIO header (Broadcom BCM2712).",
|
|
21
|
+
revisionNote: "The J8 40-pin header layout shown here is shared by all modern 40-pin Raspberry Pi models.",
|
|
22
|
+
warnings: [
|
|
23
|
+
{
|
|
24
|
+
severity: "danger",
|
|
25
|
+
text: "GPIO uses 3.3 V logic. Do not apply 5 V to any GPIO pin.",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
severity: "warning",
|
|
29
|
+
text: "Physical pins 27 and 28 (GPIO0/GPIO1, ID_SD/ID_SC) are reserved for the HAT ID EEPROM; avoid general-purpose use.",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
severity: "info",
|
|
33
|
+
text: "Pin numbers are the physical J8 header numbers; GPIO numbers are BCM numbering.",
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
sources: [
|
|
37
|
+
{
|
|
38
|
+
title: "Raspberry Pi GPIO documentation",
|
|
39
|
+
url: "https://www.raspberrypi.com/documentation/computers/raspberry-pi.html",
|
|
40
|
+
official: true,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
title: "Raspberry Pi 5 product brief",
|
|
44
|
+
url: "https://datasheets.raspberrypi.com/rpi5/raspberry-pi-5-product-brief.pdf",
|
|
45
|
+
official: true,
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
headers: [
|
|
49
|
+
{
|
|
50
|
+
id: "j8",
|
|
51
|
+
name: "40-pin GPIO header (J8)",
|
|
52
|
+
description: "Viewed from above with pin 1 at the top-left of the header.",
|
|
53
|
+
layout: { rows: 20, columns: 2 },
|
|
54
|
+
pins: [
|
|
55
|
+
j8(1, "3V3", "power", { voltage: "3.3 V" }),
|
|
56
|
+
j8(2, "5V", "power", { voltage: "5 V" }),
|
|
57
|
+
j8(3, "GPIO2", "communication", { gpio: "GPIO2", functions: ["SDA1"], ...V33 }),
|
|
58
|
+
j8(4, "5V", "power", { voltage: "5 V" }),
|
|
59
|
+
j8(5, "GPIO3", "communication", { gpio: "GPIO3", functions: ["SCL1"], ...V33 }),
|
|
60
|
+
j8(6, "GND", "ground"),
|
|
61
|
+
j8(7, "GPIO4", "gpio", { gpio: "GPIO4", functions: ["GPCLK0"], ...V33 }),
|
|
62
|
+
j8(8, "GPIO14", "communication", { gpio: "GPIO14", functions: ["TXD0"], ...V33 }),
|
|
63
|
+
j8(9, "GND", "ground"),
|
|
64
|
+
j8(10, "GPIO15", "communication", { gpio: "GPIO15", functions: ["RXD0"], ...V33 }),
|
|
65
|
+
j8(11, "GPIO17", "gpio", { gpio: "GPIO17", ...V33 }),
|
|
66
|
+
j8(12, "GPIO18", "gpio", { gpio: "GPIO18", functions: ["PWM0", "PCM_CLK"], ...V33 }),
|
|
67
|
+
j8(13, "GPIO27", "gpio", { gpio: "GPIO27", ...V33 }),
|
|
68
|
+
j8(14, "GND", "ground"),
|
|
69
|
+
j8(15, "GPIO22", "gpio", { gpio: "GPIO22", ...V33 }),
|
|
70
|
+
j8(16, "GPIO23", "gpio", { gpio: "GPIO23", ...V33 }),
|
|
71
|
+
j8(17, "3V3", "power", { voltage: "3.3 V" }),
|
|
72
|
+
j8(18, "GPIO24", "gpio", { gpio: "GPIO24", ...V33 }),
|
|
73
|
+
j8(19, "GPIO10", "communication", { gpio: "GPIO10", functions: ["SPI0 MOSI"], ...V33 }),
|
|
74
|
+
j8(20, "GND", "ground"),
|
|
75
|
+
j8(21, "GPIO9", "communication", { gpio: "GPIO9", functions: ["SPI0 MISO"], ...V33 }),
|
|
76
|
+
j8(22, "GPIO25", "gpio", { gpio: "GPIO25", ...V33 }),
|
|
77
|
+
j8(23, "GPIO11", "communication", { gpio: "GPIO11", functions: ["SPI0 SCLK"], ...V33 }),
|
|
78
|
+
j8(24, "GPIO8", "communication", { gpio: "GPIO8", functions: ["SPI0 CE0"], ...V33 }),
|
|
79
|
+
j8(25, "GND", "ground"),
|
|
80
|
+
j8(26, "GPIO7", "communication", { gpio: "GPIO7", functions: ["SPI0 CE1"], ...V33 }),
|
|
81
|
+
j8(27, "GPIO0", "reserved", {
|
|
82
|
+
gpio: "GPIO0",
|
|
83
|
+
functions: ["ID_SD"],
|
|
84
|
+
...V33,
|
|
85
|
+
notes: ["Reserved for HAT ID EEPROM"],
|
|
86
|
+
}),
|
|
87
|
+
j8(28, "GPIO1", "reserved", {
|
|
88
|
+
gpio: "GPIO1",
|
|
89
|
+
functions: ["ID_SC"],
|
|
90
|
+
...V33,
|
|
91
|
+
notes: ["Reserved for HAT ID EEPROM"],
|
|
92
|
+
}),
|
|
93
|
+
j8(29, "GPIO5", "gpio", { gpio: "GPIO5", ...V33 }),
|
|
94
|
+
j8(30, "GND", "ground"),
|
|
95
|
+
j8(31, "GPIO6", "gpio", { gpio: "GPIO6", ...V33 }),
|
|
96
|
+
j8(32, "GPIO12", "gpio", { gpio: "GPIO12", functions: ["PWM0"], ...V33 }),
|
|
97
|
+
j8(33, "GPIO13", "gpio", { gpio: "GPIO13", functions: ["PWM1"], ...V33 }),
|
|
98
|
+
j8(34, "GND", "ground"),
|
|
99
|
+
j8(35, "GPIO19", "gpio", { gpio: "GPIO19", functions: ["PCM_FS"], ...V33 }),
|
|
100
|
+
j8(36, "GPIO16", "gpio", { gpio: "GPIO16", ...V33 }),
|
|
101
|
+
j8(37, "GPIO26", "gpio", { gpio: "GPIO26", ...V33 }),
|
|
102
|
+
j8(38, "GPIO20", "gpio", { gpio: "GPIO20", functions: ["PCM_DIN"], ...V33 }),
|
|
103
|
+
j8(39, "GND", "ground"),
|
|
104
|
+
j8(40, "GPIO21", "gpio", { gpio: "GPIO21", functions: ["PCM_DOUT"], ...V33 }),
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { picoDebugHeader, picoEdgeHeader } from "./pico-shared.js";
|
|
2
|
+
export const raspberryPiPicoW = {
|
|
3
|
+
id: "raspberry-pi-pico-w",
|
|
4
|
+
name: "Raspberry Pi Pico W",
|
|
5
|
+
manufacturer: "Raspberry Pi",
|
|
6
|
+
aliases: ["pico-w", "picow", "rpi-pico-w", "raspberry-pi-pico-w"],
|
|
7
|
+
description: "Wireless (Wi-Fi/Bluetooth) version of the Pico. Same 40-pin edge pinout as the Pico; the SWD debug pads move to the middle of the board.",
|
|
8
|
+
revisionNote: "Edge pinout matches the original Pico, but the onboard LED is driven by the wireless chip (WL_GPIO0), not RP2040 GPIO25.",
|
|
9
|
+
warnings: [
|
|
10
|
+
{
|
|
11
|
+
severity: "danger",
|
|
12
|
+
text: "GPIO uses 3.3 V logic and is not 5 V tolerant.",
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
severity: "warning",
|
|
16
|
+
text: "Some RP2040 GPIO are used internally for the wireless interface; the onboard LED is not on GPIO25 as on the original Pico.",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
severity: "warning",
|
|
20
|
+
text: "ADC inputs (GP26–GP28) must stay within the ADC reference voltage range.",
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
sources: [
|
|
24
|
+
{
|
|
25
|
+
title: "Raspberry Pi Pico W pinout PDF",
|
|
26
|
+
url: "https://pip-assets.raspberrypi.com/categories/686-raspberry-pi-pico-w/documents/RP-008315-DS-1-PicoW-A4-Pinout.pdf",
|
|
27
|
+
official: true,
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
title: "Raspberry Pi Pico documentation",
|
|
31
|
+
url: "https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html",
|
|
32
|
+
official: true,
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
headers: [picoEdgeHeader(), picoDebugHeader("SWD debug pads (mid-board)")],
|
|
36
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { picoDebugHeader, picoEdgeHeader } from "./pico-shared.js";
|
|
2
|
+
export const raspberryPiPico = {
|
|
3
|
+
id: "raspberry-pi-pico",
|
|
4
|
+
name: "Raspberry Pi Pico",
|
|
5
|
+
manufacturer: "Raspberry Pi",
|
|
6
|
+
aliases: ["pico", "rpi-pico", "raspberry-pi-pico", "rp2040-pico"],
|
|
7
|
+
description: "RP2040 microcontroller board with a 40-pin castellated DIP edge, three ADC inputs, and an SWD debug header.",
|
|
8
|
+
revisionNote: "Pin map matches the official Pico R3 pinout. The Pico W shares this edge pinout but differs internally (see `ph pico-w`).",
|
|
9
|
+
warnings: [
|
|
10
|
+
{
|
|
11
|
+
severity: "danger",
|
|
12
|
+
text: "GPIO uses 3.3 V logic and is not 5 V tolerant.",
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
severity: "warning",
|
|
16
|
+
text: "ADC inputs (GP26–GP28) must stay within the ADC reference voltage range.",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
severity: "info",
|
|
20
|
+
text: "RP2040 GPIO23–GPIO25 are used internally (SMPS control, VBUS sense, onboard LED) and are not on the edge header.",
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
sources: [
|
|
24
|
+
{
|
|
25
|
+
title: "Raspberry Pi Pico pinout PDF",
|
|
26
|
+
url: "https://pip-assets.raspberrypi.com/categories/610-raspberry-pi-pico/documents/RP-008309-DS-1-Pico-R3-A4-Pinout.pdf",
|
|
27
|
+
official: true,
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
title: "Raspberry Pi Pico documentation",
|
|
31
|
+
url: "https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html",
|
|
32
|
+
official: true,
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
headers: [picoEdgeHeader(), picoDebugHeader("SWD debug header (board end)")],
|
|
36
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Board } from "./model.js";
|
|
2
|
+
import { boards } from "./boards/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Normalizes a user query or alias: case-insensitive, and spaces, underscores
|
|
5
|
+
* and repeated hyphens all collapse to single hyphens, so "Raspberry Pi 5",
|
|
6
|
+
* "raspberry_pi_5" and "raspberry-pi-5" are equivalent.
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizeQuery(query: string): string;
|
|
9
|
+
export declare function resolveBoard(query: string): Board | undefined;
|
|
10
|
+
export type Suggestion = {
|
|
11
|
+
board: Board;
|
|
12
|
+
/** The closest matching alias — what the user probably meant to type. */
|
|
13
|
+
alias: string;
|
|
14
|
+
distance: number;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Ranks boards by edit distance between the query and their closest alias.
|
|
18
|
+
* Prefix matches count as very close so "rasp" still suggests the Pis.
|
|
19
|
+
*/
|
|
20
|
+
export declare function suggestBoards(query: string, max?: number): Suggestion[];
|
|
21
|
+
export declare function searchBoards(query: string): Board[];
|
|
22
|
+
export { boards };
|
package/dist/catalog.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { boards } from "./boards/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Normalizes a user query or alias: case-insensitive, and spaces, underscores
|
|
4
|
+
* and repeated hyphens all collapse to single hyphens, so "Raspberry Pi 5",
|
|
5
|
+
* "raspberry_pi_5" and "raspberry-pi-5" are equivalent.
|
|
6
|
+
*/
|
|
7
|
+
export function normalizeQuery(query) {
|
|
8
|
+
return query
|
|
9
|
+
.toLowerCase()
|
|
10
|
+
.replace(/[\s_]+/g, "-")
|
|
11
|
+
.replace(/-+/g, "-")
|
|
12
|
+
.replace(/^-|-$/g, "");
|
|
13
|
+
}
|
|
14
|
+
function candidateNames(board) {
|
|
15
|
+
return [board.id, normalizeQuery(board.name), ...board.aliases.map(normalizeQuery)];
|
|
16
|
+
}
|
|
17
|
+
export function resolveBoard(query) {
|
|
18
|
+
const q = normalizeQuery(query);
|
|
19
|
+
if (!q)
|
|
20
|
+
return undefined;
|
|
21
|
+
return boards.find((board) => candidateNames(board).includes(q));
|
|
22
|
+
}
|
|
23
|
+
function levenshtein(a, b) {
|
|
24
|
+
const prev = new Array(b.length + 1);
|
|
25
|
+
for (let j = 0; j <= b.length; j++)
|
|
26
|
+
prev[j] = j;
|
|
27
|
+
for (let i = 1; i <= a.length; i++) {
|
|
28
|
+
let diagonal = prev[0];
|
|
29
|
+
prev[0] = i;
|
|
30
|
+
for (let j = 1; j <= b.length; j++) {
|
|
31
|
+
const insertOrDelete = Math.min(prev[j], prev[j - 1]) + 1;
|
|
32
|
+
const substitute = diagonal + (a[i - 1] === b[j - 1] ? 0 : 1);
|
|
33
|
+
diagonal = prev[j];
|
|
34
|
+
prev[j] = Math.min(insertOrDelete, substitute);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return prev[b.length];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Ranks boards by edit distance between the query and their closest alias.
|
|
41
|
+
* Prefix matches count as very close so "rasp" still suggests the Pis.
|
|
42
|
+
*/
|
|
43
|
+
export function suggestBoards(query, max = 3) {
|
|
44
|
+
const q = normalizeQuery(query);
|
|
45
|
+
if (!q)
|
|
46
|
+
return [];
|
|
47
|
+
const scored = boards.map((board) => {
|
|
48
|
+
let best = { board, alias: board.id, distance: Number.POSITIVE_INFINITY };
|
|
49
|
+
for (const name of candidateNames(board)) {
|
|
50
|
+
const distance = name.startsWith(q) ? 1 : levenshtein(q, name);
|
|
51
|
+
if (distance < best.distance)
|
|
52
|
+
best = { board, alias: name, distance };
|
|
53
|
+
}
|
|
54
|
+
return best;
|
|
55
|
+
});
|
|
56
|
+
const threshold = Math.max(2, Math.floor(q.length / 2));
|
|
57
|
+
return scored
|
|
58
|
+
.filter((s) => s.distance <= threshold)
|
|
59
|
+
.sort((a, b) => a.distance - b.distance)
|
|
60
|
+
.slice(0, max);
|
|
61
|
+
}
|
|
62
|
+
export function searchBoards(query) {
|
|
63
|
+
const q = normalizeQuery(query);
|
|
64
|
+
if (!q)
|
|
65
|
+
return [];
|
|
66
|
+
return boards.filter((board) => [
|
|
67
|
+
board.id,
|
|
68
|
+
normalizeQuery(board.name),
|
|
69
|
+
normalizeQuery(board.manufacturer),
|
|
70
|
+
normalizeQuery(board.description ?? ""),
|
|
71
|
+
...board.aliases.map(normalizeQuery),
|
|
72
|
+
].some((text) => text.includes(q)));
|
|
73
|
+
}
|
|
74
|
+
export { boards };
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type { Board, Header, Pin, PinCategory, Source, Warning, WarningSeverity, } from "./model.js";
|
|
2
|
+
export { boards, normalizeQuery, resolveBoard, searchBoards, suggestBoards } from "./catalog.js";
|
|
3
|
+
export { renderBoard, type RenderOptions } from "./render/board.js";
|
|
4
|
+
export { asciiChars, unicodeChars, type CharSet } from "./render/chars.js";
|
|
5
|
+
export { makeChalk } from "./render/theme.js";
|
|
6
|
+
export { runCli, type RunOptions, type RunResult } from "./run.js";
|
|
7
|
+
export { VERSION } from "./version.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { boards, normalizeQuery, resolveBoard, searchBoards, suggestBoards } from "./catalog.js";
|
|
2
|
+
export { renderBoard } from "./render/board.js";
|
|
3
|
+
export { asciiChars, unicodeChars } from "./render/chars.js";
|
|
4
|
+
export { makeChalk } from "./render/theme.js";
|
|
5
|
+
export { runCli } from "./run.js";
|
|
6
|
+
export { VERSION } from "./version.js";
|
package/dist/model.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed hardware data model shared by all renderers. Designed so the data can
|
|
3
|
+
* eventually be shared with the PinHub Next.js site — no renderer concerns
|
|
4
|
+
* belong in here.
|
|
5
|
+
*/
|
|
6
|
+
export type PinCategory = "power" | "ground" | "gpio" | "analog" | "digital" | "communication" | "reserved" | "nc";
|
|
7
|
+
export type WarningSeverity = "danger" | "warning" | "info";
|
|
8
|
+
export type Warning = {
|
|
9
|
+
severity: WarningSeverity;
|
|
10
|
+
text: string;
|
|
11
|
+
};
|
|
12
|
+
export type Source = {
|
|
13
|
+
title: string;
|
|
14
|
+
url: string;
|
|
15
|
+
official: boolean;
|
|
16
|
+
};
|
|
17
|
+
export type Pin = {
|
|
18
|
+
/** Physical pin number as printed or conventionally counted on the board. */
|
|
19
|
+
physical: number;
|
|
20
|
+
/** Grid position within the header (1-based). */
|
|
21
|
+
position: {
|
|
22
|
+
row: number;
|
|
23
|
+
column: number;
|
|
24
|
+
};
|
|
25
|
+
label: string;
|
|
26
|
+
gpio?: string;
|
|
27
|
+
functions?: string[];
|
|
28
|
+
category: PinCategory;
|
|
29
|
+
voltage?: string;
|
|
30
|
+
notes?: string[];
|
|
31
|
+
};
|
|
32
|
+
export type Header = {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
layout: {
|
|
37
|
+
rows: number;
|
|
38
|
+
columns: number;
|
|
39
|
+
};
|
|
40
|
+
pins: Pin[];
|
|
41
|
+
};
|
|
42
|
+
export type Board = {
|
|
43
|
+
id: string;
|
|
44
|
+
name: string;
|
|
45
|
+
manufacturer: string;
|
|
46
|
+
aliases: string[];
|
|
47
|
+
description?: string;
|
|
48
|
+
revisionNote?: string;
|
|
49
|
+
warnings: Warning[];
|
|
50
|
+
sources: Source[];
|
|
51
|
+
headers: Header[];
|
|
52
|
+
};
|
package/dist/model.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ChalkInstance } from "chalk";
|
|
2
|
+
import type { Board } from "../model.js";
|
|
3
|
+
import type { CharSet } from "./chars.js";
|
|
4
|
+
export type RenderOptions = {
|
|
5
|
+
chalk: ChalkInstance;
|
|
6
|
+
chars: CharSet;
|
|
7
|
+
width: number;
|
|
8
|
+
compact: boolean;
|
|
9
|
+
};
|
|
10
|
+
export declare function wrapText(text: string, width: number, indent: string): string[];
|
|
11
|
+
export declare function renderWarnings(board: Board, opts: RenderOptions): string[];
|
|
12
|
+
export declare function renderBoard(board: Board, opts: RenderOptions): string;
|