schematic-symbols 0.0.1
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/.github/CODEOWNERS +1 -0
- package/.github/workflows/bun-pver-release.yml +25 -0
- package/README.md +88 -0
- package/assets/symbols-svg-json/boxresistor.json +90 -0
- package/assets/symbols-svg-json/capacitor.json +76 -0
- package/assets/symbols-svg-json/capacitor_polarized.json +83 -0
- package/assets/symbols-svg-json/diode.json +91 -0
- package/assets/symbols-svg-json/diode_bipolar_zener.json +166 -0
- package/assets/symbols-svg-json/diode_schottky.json +76 -0
- package/assets/symbols-svg-json/diode_zener.json +31 -0
- package/assets/symbols-svg-json/fuse.json +84 -0
- package/assets/symbols-svg-json/led.json +205 -0
- package/assets/symbols-svg-json/mosfet_depletion_normally_on.json +267 -0
- package/assets/symbols-svg-json/potentiometer.json +137 -0
- package/assets/symbols-svg-json/potentiometer2.json +160 -0
- package/assets/symbols-svg-json/testshape.json +35 -0
- package/assets/symbols-svg-json/varistor.json +129 -0
- package/assets/symbols.svg +965 -0
- package/biome.json +44 -0
- package/bun.lockb +0 -0
- package/dev-server.ts +22 -0
- package/drawing/arrow.ts +41 -0
- package/drawing/box.ts +5 -0
- package/drawing/circle.ts +7 -0
- package/drawing/defineSymbol.ts +5 -0
- package/drawing/getBoundsOfSvgJson.ts +44 -0
- package/drawing/getSvg.ts +133 -0
- package/drawing/index.ts +11 -0
- package/drawing/mapColor.ts +10 -0
- package/drawing/ninePointAnchorToSvgAnchor.ts +11 -0
- package/drawing/path.ts +5 -0
- package/drawing/pathToSvgD.ts +9 -0
- package/drawing/resizeSymbol.ts +66 -0
- package/drawing/rotateSymbol.ts +94 -0
- package/drawing/svgPathToPoints.ts +50 -0
- package/drawing/text.ts +8 -0
- package/drawing/types.ts +90 -0
- package/index.ts +1 -0
- package/package.json +25 -0
- package/scripts/build.ts +18 -0
- package/scripts/convertToObjectWithOrderedPositionIds.ts +52 -0
- package/scripts/generate-symbols-from-asset-svgs.ts +145 -0
- package/scripts/lib/applyGroupTransformsToChildren.ts +118 -0
- package/scripts/lib/findInnerText.ts +11 -0
- package/scripts/lib/generate-web-page.ts +60 -0
- package/scripts/lib/getTsFileContentForSvgGroup.ts +33 -0
- package/scripts/lib/serializeSvgPathCommands.ts +47 -0
- package/symbols/boxresistor_horz.ts +35 -0
- package/symbols/boxresistor_vert.ts +4 -0
- package/symbols/fuse_horz.ts +24 -0
- package/symbols/fuse_vert.ts +4 -0
- package/symbols/index.ts +31 -0
- package/symbols/led_horz.ts +18 -0
- package/symbols/led_vert.ts +4 -0
- package/symbols/mosfet_depletion_normally_on_horz.ts +19 -0
- package/symbols/mosfet_depletion_normally_on_vert.ts +21 -0
- package/symbols/potentiometer2_horz.ts +14 -0
- package/symbols/potentiometer2_vert.ts +4 -0
- package/symbols/potentiometer_horz.ts +18 -0
- package/symbols/potentiometer_vert.ts +6 -0
- package/symbols/varistor_horz.ts +24 -0
- package/symbols/varistor_vert.ts +4 -0
- package/tests/assets/boxresistor-untransformed.json +187 -0
- package/tests/assets/testshape-untransformed.json +25 -0
- package/tests/normalize-svg.test.ts +29 -0
- package/tsconfig.json +28 -0
package/package.json
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
{
|
2
|
+
"name": "schematic-symbols",
|
3
|
+
"main": "./dist/index.cjs",
|
4
|
+
"version": "0.0.1",
|
5
|
+
"type": "module",
|
6
|
+
"scripts": {
|
7
|
+
"start": "bun run build && bun --hot run dev-server.ts",
|
8
|
+
"build": "rm symbols/index.ts && bunx make-vfs ./symbols --content-format import-default --outfile ./symbols/index.ts && tsup ./index.ts --dts --sourcemap",
|
9
|
+
"generate": "bun run scripts/generate-symbols-from-asset-svgs.ts",
|
10
|
+
"vercel-build": "bun run ./scripts/build.ts"
|
11
|
+
},
|
12
|
+
"devDependencies": {
|
13
|
+
"@types/bun": "latest",
|
14
|
+
"@types/svg-path-parser": "^1.1.6",
|
15
|
+
"make-vfs": "1.0.10",
|
16
|
+
"svg-path-parser": "^1.1.0",
|
17
|
+
"svgson": "^5.3.1",
|
18
|
+
"transformation-matrix": "^2.16.1",
|
19
|
+
"tsup": "^8.2.4"
|
20
|
+
},
|
21
|
+
"peerDependencies": {
|
22
|
+
"typescript": "^5.0.0"
|
23
|
+
},
|
24
|
+
"dependencies": {}
|
25
|
+
}
|
package/scripts/build.ts
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
import { generateWebPage } from "./lib/generate-web-page"
|
2
|
+
import fs from "fs"
|
3
|
+
import path from "path"
|
4
|
+
|
5
|
+
const distDir = path.join(process.cwd(), "public")
|
6
|
+
|
7
|
+
// Ensure the dist directory exists
|
8
|
+
if (!fs.existsSync(distDir)) {
|
9
|
+
fs.mkdirSync(distDir, { recursive: true })
|
10
|
+
}
|
11
|
+
|
12
|
+
// Generate the HTML content
|
13
|
+
const htmlContent = generateWebPage()
|
14
|
+
|
15
|
+
// Write the HTML content to dist/index.html
|
16
|
+
fs.writeFileSync(path.join(distDir, "index.html"), htmlContent)
|
17
|
+
|
18
|
+
console.log("Static HTML file generated at public/index.html")
|
@@ -0,0 +1,52 @@
|
|
1
|
+
export const convertToObjectWithOrderedPositionIds = <
|
2
|
+
T extends { x: number; y: number },
|
3
|
+
>(
|
4
|
+
points: T[],
|
5
|
+
): Record<string, T> => {
|
6
|
+
const result: Record<string, T> = {}
|
7
|
+
|
8
|
+
const sides = {
|
9
|
+
top: [] as T[],
|
10
|
+
bottom: [] as T[],
|
11
|
+
left: [] as T[],
|
12
|
+
right: [] as T[],
|
13
|
+
unknown: [] as T[],
|
14
|
+
}
|
15
|
+
|
16
|
+
for (const point of points) {
|
17
|
+
const dx = point.x
|
18
|
+
const dy = point.y
|
19
|
+
|
20
|
+
const dominantSide = Math.abs(dx) > Math.abs(dy) ? "x" : "y"
|
21
|
+
|
22
|
+
let side: "top" | "bottom" | "left" | "right" | "unknown"
|
23
|
+
if (dominantSide === "x" && dx > 0) {
|
24
|
+
side = "right"
|
25
|
+
} else if (dominantSide === "x" && dx < 0) {
|
26
|
+
side = "left"
|
27
|
+
} else if (dominantSide === "y" && dy > 0) {
|
28
|
+
side = "bottom"
|
29
|
+
} else if (dominantSide === "y" && dy < 0) {
|
30
|
+
side = "top"
|
31
|
+
} else {
|
32
|
+
side = "unknown"
|
33
|
+
}
|
34
|
+
|
35
|
+
sides[side].push(point)
|
36
|
+
}
|
37
|
+
|
38
|
+
// Sort each side according to x or y
|
39
|
+
sides.top.sort((a, b) => a.x - b.x)
|
40
|
+
sides.bottom.sort((a, b) => a.x - b.x)
|
41
|
+
sides.left.sort((a, b) => a.y - b.y)
|
42
|
+
sides.right.sort((a, b) => a.y - b.y)
|
43
|
+
|
44
|
+
// Assign position ids to each point
|
45
|
+
for (const side of Object.keys(sides)) {
|
46
|
+
for (let i = 0; i < sides[side as keyof typeof sides].length; i++) {
|
47
|
+
result[`${side}${i + 1}`] = sides[side as keyof typeof sides][i]
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
return result
|
52
|
+
}
|
@@ -0,0 +1,145 @@
|
|
1
|
+
import symbolsSvg from "../assets/symbols.svg" with { type: "text" }
|
2
|
+
import { parse, type INode } from "svgson"
|
3
|
+
import fs from "node:fs"
|
4
|
+
import { applyGroupTransformsToChildren } from "./lib/applyGroupTransformsToChildren"
|
5
|
+
import { getBoundsOfSvgJson } from "drawing/getBoundsOfSvgJson"
|
6
|
+
import { compose, translate, toSVG, scale } from "transformation-matrix"
|
7
|
+
import { convertToObjectWithOrderedPositionIds } from "./convertToObjectWithOrderedPositionIds"
|
8
|
+
import { findInnerText } from "./lib/findInnerText"
|
9
|
+
import { svgPathToPoints, type SvgData } from "drawing"
|
10
|
+
import { getTsFileContentForSvgGroup } from "./lib/getTsFileContentForSvgGroup"
|
11
|
+
|
12
|
+
const SOURCE_IGNORE_LIST = ["testshape"]
|
13
|
+
|
14
|
+
async function processSvg() {
|
15
|
+
try {
|
16
|
+
// Parse the entire SVG file once
|
17
|
+
const parsedSvg = await parse(symbolsSvg)
|
18
|
+
|
19
|
+
// Find the root group
|
20
|
+
const rootGroup = parsedSvg.children.find(
|
21
|
+
(child) => child.name === "g" && child.attributes.id === "root",
|
22
|
+
)
|
23
|
+
|
24
|
+
if (!rootGroup) {
|
25
|
+
console.error("Root group not found")
|
26
|
+
return
|
27
|
+
}
|
28
|
+
|
29
|
+
// Process each subgroup under the root
|
30
|
+
rootGroup.children
|
31
|
+
.filter((child) => child.name === "g")
|
32
|
+
.forEach((group, index) => {
|
33
|
+
const groupId = group.attributes.id
|
34
|
+
try {
|
35
|
+
const filePath = `./assets/symbols-svg-json/${groupId}.json`
|
36
|
+
let groupWithTransformApplied = applyGroupTransformsToChildren(group)
|
37
|
+
|
38
|
+
// Recenter the group (makes it easier to read)
|
39
|
+
let bounds = getBoundsOfSvgJson(groupWithTransformApplied as any)
|
40
|
+
groupWithTransformApplied.attributes.transform = toSVG(
|
41
|
+
compose(
|
42
|
+
scale(0.1, 0.1),
|
43
|
+
translate(-bounds.centerX, -bounds.centerY),
|
44
|
+
),
|
45
|
+
)
|
46
|
+
groupWithTransformApplied = applyGroupTransformsToChildren(
|
47
|
+
groupWithTransformApplied,
|
48
|
+
)
|
49
|
+
|
50
|
+
bounds = getBoundsOfSvgJson(groupWithTransformApplied as any)
|
51
|
+
|
52
|
+
const refblocks = convertToObjectWithOrderedPositionIds(
|
53
|
+
groupWithTransformApplied.children
|
54
|
+
.filter(
|
55
|
+
(child) =>
|
56
|
+
child.name === "circle" &&
|
57
|
+
(child.attributes["inkscape:label"]?.includes("refblock") ||
|
58
|
+
child.attributes.id?.includes("refblock")),
|
59
|
+
)
|
60
|
+
.map((child) => ({
|
61
|
+
x: parseFloat(child.attributes.cx),
|
62
|
+
y: parseFloat(child.attributes.cy),
|
63
|
+
})),
|
64
|
+
)
|
65
|
+
|
66
|
+
const textChildren = groupWithTransformApplied.children.filter(
|
67
|
+
(text) => text.name === "text",
|
68
|
+
)
|
69
|
+
const texts = convertToObjectWithOrderedPositionIds(
|
70
|
+
textChildren.map((text) => ({
|
71
|
+
type: "text",
|
72
|
+
text: findInnerText(text),
|
73
|
+
x: parseFloat(text.attributes.x),
|
74
|
+
y: parseFloat(text.attributes.y),
|
75
|
+
})),
|
76
|
+
)
|
77
|
+
|
78
|
+
const pathChildren = groupWithTransformApplied.children.filter(
|
79
|
+
(path) => path.name === "path",
|
80
|
+
)
|
81
|
+
const paths = Object.fromEntries(
|
82
|
+
pathChildren.map((path) => [
|
83
|
+
path.attributes.id!,
|
84
|
+
{
|
85
|
+
type: "path",
|
86
|
+
points: svgPathToPoints(path.attributes.d!),
|
87
|
+
color: "primary",
|
88
|
+
fill:
|
89
|
+
path.attributes.fill === "true" &&
|
90
|
+
!path.attributes.style?.includes("fill:none"),
|
91
|
+
},
|
92
|
+
]),
|
93
|
+
)
|
94
|
+
|
95
|
+
const svgData = {
|
96
|
+
// only for debugging
|
97
|
+
// svg: groupWithTransformApplied,
|
98
|
+
paths,
|
99
|
+
texts,
|
100
|
+
refblocks,
|
101
|
+
bounds,
|
102
|
+
}
|
103
|
+
|
104
|
+
console.log(`Writing to file: ${filePath}`)
|
105
|
+
fs.writeFileSync(filePath, JSON.stringify(svgData, null, 2))
|
106
|
+
|
107
|
+
if (SOURCE_IGNORE_LIST.includes(groupId)) {
|
108
|
+
return
|
109
|
+
}
|
110
|
+
|
111
|
+
// Check if there's a source file for this symbol
|
112
|
+
const outputPath = `./symbols/${groupId}_horz.ts`
|
113
|
+
const hasSourceFile = fs.existsSync(outputPath)
|
114
|
+
const isReadyForGen =
|
115
|
+
Object.keys(texts).length > 0 &&
|
116
|
+
Object.keys(paths).length > 0 &&
|
117
|
+
Object.keys(refblocks).length > 0
|
118
|
+
|
119
|
+
if (!hasSourceFile && !isReadyForGen) {
|
120
|
+
console.log(
|
121
|
+
`Skipping ${groupId} because it's not ready for generation (missing some elements)`,
|
122
|
+
)
|
123
|
+
console.log(` - texts: ${Object.keys(texts).length}`)
|
124
|
+
console.log(` - paths: ${Object.keys(paths).length}`)
|
125
|
+
console.log(` - refblocks: ${Object.keys(refblocks).length}`)
|
126
|
+
} else if (!hasSourceFile && isReadyForGen) {
|
127
|
+
console.log(`Creating horz source file: ${outputPath}`)
|
128
|
+
const content = getTsFileContentForSvgGroup(groupId, svgData as any)
|
129
|
+
fs.writeFileSync(outputPath, content)
|
130
|
+
// Write the vert file
|
131
|
+
const vertOutputPath = `./symbols/${groupId}_vert.ts`
|
132
|
+
console.log(`Creating vert source file: ${vertOutputPath}`)
|
133
|
+
const contentVert = `import { rotateSymbol } from "drawing/rotateSymbol"\nimport ${groupId}_horz from "./${groupId}_horz"\n\nexport default rotateSymbol(${groupId}_horz)`
|
134
|
+
fs.writeFileSync(vertOutputPath, contentVert)
|
135
|
+
}
|
136
|
+
} catch (err: any) {
|
137
|
+
console.log(`Error processing ${groupId}: ${err.message}`)
|
138
|
+
}
|
139
|
+
})
|
140
|
+
} catch (error) {
|
141
|
+
console.error("Error processing SVG:", error)
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
145
|
+
processSvg()
|
@@ -0,0 +1,118 @@
|
|
1
|
+
import {
|
2
|
+
fromDefinition,
|
3
|
+
compose,
|
4
|
+
applyToPoint,
|
5
|
+
toString,
|
6
|
+
type Matrix,
|
7
|
+
fromTransformAttribute,
|
8
|
+
identity,
|
9
|
+
} from "transformation-matrix"
|
10
|
+
import type { INode } from "svgson"
|
11
|
+
import { parseSVG, makeAbsolute, type LineToCommand } from "svg-path-parser"
|
12
|
+
import { serializeSvgPathCommands } from "./serializeSvgPathCommands"
|
13
|
+
|
14
|
+
export function applyGroupTransformsToChildren(group: INode) {
|
15
|
+
if (!group.attributes.transform) {
|
16
|
+
return group // No transformation to apply
|
17
|
+
}
|
18
|
+
|
19
|
+
const groupTransform = parseTransform(group.attributes.transform)
|
20
|
+
|
21
|
+
group.children = group.children
|
22
|
+
.map((child) => {
|
23
|
+
const transform = compose(
|
24
|
+
groupTransform,
|
25
|
+
parseTransform(child.attributes.transform),
|
26
|
+
)
|
27
|
+
delete child.attributes.transform
|
28
|
+
|
29
|
+
if (child.name === "rect") {
|
30
|
+
// convert to path, it's easier to transform via rotations
|
31
|
+
return null
|
32
|
+
child = convertRectToPath(child)
|
33
|
+
}
|
34
|
+
if (child.name === "path") {
|
35
|
+
child.attributes.d = transformPath(child.attributes.d, transform)
|
36
|
+
const hasFill =
|
37
|
+
child.attributes.fill && child.attributes.fill !== "none"
|
38
|
+
child.attributes.fill = hasFill ? "true" : "false"
|
39
|
+
} else if (child.name === "text") {
|
40
|
+
const { x, y } = applyToPoint(transform, {
|
41
|
+
x: parseFloat(child.attributes.x),
|
42
|
+
y: parseFloat(child.attributes.y),
|
43
|
+
})
|
44
|
+
child.attributes.x = x.toString()
|
45
|
+
child.attributes.y = y.toString()
|
46
|
+
} else if (child.name === "circle") {
|
47
|
+
let { cx, cy, r } = child.attributes as any
|
48
|
+
cx = parseFloat(cx)
|
49
|
+
cy = parseFloat(cy)
|
50
|
+
r = parseFloat(r)
|
51
|
+
|
52
|
+
const { x, y } = applyToPoint(transform, { x: cx, y: cy })
|
53
|
+
r = r * groupTransform.a
|
54
|
+
|
55
|
+
child.attributes.cx = x.toString()
|
56
|
+
child.attributes.cy = y.toString()
|
57
|
+
child.attributes.r = r.toString()
|
58
|
+
} else {
|
59
|
+
return null
|
60
|
+
}
|
61
|
+
|
62
|
+
return child
|
63
|
+
})
|
64
|
+
.filter((c: INode | null): INode => c as INode)
|
65
|
+
|
66
|
+
// Remove the transform from the group since it's now applied to children
|
67
|
+
delete group.attributes.transform
|
68
|
+
|
69
|
+
return group
|
70
|
+
}
|
71
|
+
|
72
|
+
function parseTransform(transform: string): Matrix {
|
73
|
+
if (!transform) return identity()
|
74
|
+
return compose(fromDefinition(fromTransformAttribute(transform)))
|
75
|
+
}
|
76
|
+
|
77
|
+
export function transformPath(pathData: string, matrix: Matrix): string {
|
78
|
+
let parsedPath = parseSVG(pathData)
|
79
|
+
|
80
|
+
parsedPath = makeAbsolute(parsedPath)
|
81
|
+
|
82
|
+
// convert V and H commands to L commands so that rotations can be applied
|
83
|
+
parsedPath = parsedPath.map((command) => {
|
84
|
+
const { x0, y0 } = command as any
|
85
|
+
if (command.code === "V") {
|
86
|
+
return { code: "L", x: x0, y: command.y } as LineToCommand
|
87
|
+
} else if (command.code === "H") {
|
88
|
+
return { code: "L", x: command.x, y: y0 } as LineToCommand
|
89
|
+
}
|
90
|
+
return command
|
91
|
+
})
|
92
|
+
|
93
|
+
const transformedPath = parsedPath.map((command) => {
|
94
|
+
if ("x" in command && "y" in command) {
|
95
|
+
const { x, y } = applyToPoint(matrix, { x: command.x, y: command.y })
|
96
|
+
command.x = x
|
97
|
+
command.y = y
|
98
|
+
}
|
99
|
+
if ("x1" in command && "y1" in command) {
|
100
|
+
const { x, y } = applyToPoint(matrix, { x: command.x1, y: command.y1 })
|
101
|
+
command.x1 = x
|
102
|
+
command.y1 = y
|
103
|
+
}
|
104
|
+
if ("x2" in command && "y2" in command) {
|
105
|
+
const { x, y } = applyToPoint(matrix, { x: command.x2, y: command.y2 })
|
106
|
+
command.x2 = x
|
107
|
+
command.y2 = y
|
108
|
+
}
|
109
|
+
return command
|
110
|
+
})
|
111
|
+
|
112
|
+
return serializeSvgPathCommands(transformedPath)
|
113
|
+
}
|
114
|
+
|
115
|
+
export function convertRectToPath(child: INode): INode {
|
116
|
+
const { x, y, width, height } = child.attributes as any
|
117
|
+
return null
|
118
|
+
}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import { getSvg } from "../../drawing/getSvg"
|
2
|
+
import symbols from "../../symbols"
|
3
|
+
|
4
|
+
export function generateWebPage(): string {
|
5
|
+
const symbolEntries = Object.entries(symbols).sort((a, b) =>
|
6
|
+
a[0].localeCompare(b[0]),
|
7
|
+
)
|
8
|
+
|
9
|
+
const svgGrid = symbolEntries
|
10
|
+
.map(([name, symbol]) => {
|
11
|
+
const svg = getSvg(symbol, { width: 150, height: 150, debug: true })
|
12
|
+
return `
|
13
|
+
<div class="symbol-container" style="padding-bottom:28px;">
|
14
|
+
<div style="font-size: 12px;word-break: break-all; text-align: left;padding-bottom: 16px;">${name}</div>
|
15
|
+
${svg}
|
16
|
+
</div>
|
17
|
+
`
|
18
|
+
})
|
19
|
+
.join("")
|
20
|
+
|
21
|
+
const html = `
|
22
|
+
<!DOCTYPE html>
|
23
|
+
<html lang="en">
|
24
|
+
<head>
|
25
|
+
<meta charset="UTF-8">
|
26
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
27
|
+
<title>Schematic Symbols Grid</title>
|
28
|
+
<style>
|
29
|
+
body {
|
30
|
+
font-family: Arial, sans-serif;
|
31
|
+
margin: 0;
|
32
|
+
padding: 20px;
|
33
|
+
}
|
34
|
+
.grid {
|
35
|
+
display: grid;
|
36
|
+
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
37
|
+
gap: 20px;
|
38
|
+
}
|
39
|
+
.symbol-container {
|
40
|
+
border: 1px solid #ccc;
|
41
|
+
padding: 10px;
|
42
|
+
text-align: center;
|
43
|
+
}
|
44
|
+
svg {
|
45
|
+
max-width: 100%;
|
46
|
+
height: auto;
|
47
|
+
}
|
48
|
+
</style>
|
49
|
+
</head>
|
50
|
+
<body>
|
51
|
+
<h1>Schematic Symbols</h1>
|
52
|
+
<div class="grid">
|
53
|
+
${svgGrid}
|
54
|
+
</div>
|
55
|
+
</body>
|
56
|
+
</html>
|
57
|
+
`
|
58
|
+
|
59
|
+
return html
|
60
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import type { SvgData } from "drawing"
|
2
|
+
|
3
|
+
export const getTsFileContentForSvgGroup = (
|
4
|
+
groupId: string,
|
5
|
+
svgData: SvgData,
|
6
|
+
) => {
|
7
|
+
return `
|
8
|
+
import { defineSymbol } from "drawing/defineSymbol"
|
9
|
+
import svgJson from "assets/symbols-svg-json/${groupId}.json"
|
10
|
+
|
11
|
+
const { paths, texts, bounds, refblocks } = svgJson
|
12
|
+
|
13
|
+
export default defineSymbol({
|
14
|
+
primitives: [
|
15
|
+
...Object.values(paths),
|
16
|
+
${Object.entries(svgData.texts)
|
17
|
+
.map(([key, text]) => {
|
18
|
+
return `{ ...texts.${key}, anchor: "middle_left" },`
|
19
|
+
})
|
20
|
+
.join("\n")}
|
21
|
+
] as any,
|
22
|
+
ports: [
|
23
|
+
${Object.entries(svgData.refblocks)
|
24
|
+
.map(([key, point], i) => {
|
25
|
+
return `{ ...refblocks.${key}, labels: ["${i + 1}"] }, // TODO add more "standard" labels`
|
26
|
+
})
|
27
|
+
.join("\n")}
|
28
|
+
],
|
29
|
+
size: { width: bounds.width, height: bounds.height },
|
30
|
+
center: { x: bounds.centerX, y: bounds.centerY },
|
31
|
+
})
|
32
|
+
`
|
33
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
import type { Command } from "svg-path-parser"
|
2
|
+
|
3
|
+
export function serializeSvgPathCommands(pathData: Command[]): string {
|
4
|
+
return pathData
|
5
|
+
.map((command: Command) => {
|
6
|
+
let result = command.code
|
7
|
+
|
8
|
+
switch (command.code) {
|
9
|
+
case "M":
|
10
|
+
case "m":
|
11
|
+
case "L":
|
12
|
+
case "l":
|
13
|
+
case "T":
|
14
|
+
case "t":
|
15
|
+
result += `${command.x},${command.y}`
|
16
|
+
break
|
17
|
+
case "H":
|
18
|
+
case "h":
|
19
|
+
result += command.x
|
20
|
+
break
|
21
|
+
case "V":
|
22
|
+
case "v":
|
23
|
+
result += command.y
|
24
|
+
break
|
25
|
+
case "C":
|
26
|
+
case "c":
|
27
|
+
result += `${command.x1},${command.y1} ${command.x2},${command.y2} ${command.x},${command.y}`
|
28
|
+
break
|
29
|
+
case "S":
|
30
|
+
case "s":
|
31
|
+
case "Q":
|
32
|
+
case "q":
|
33
|
+
result += `${command.x1},${command.y1} ${command.x},${command.y}`
|
34
|
+
break
|
35
|
+
case "A":
|
36
|
+
case "a":
|
37
|
+
result += `${command.rx},${command.ry} ${command.xAxisRotation} ${command.largeArc ? "1" : "0"},${command.sweep ? "1" : "0"} ${command.x},${command.y}`
|
38
|
+
break
|
39
|
+
case "Z":
|
40
|
+
case "z":
|
41
|
+
break
|
42
|
+
}
|
43
|
+
|
44
|
+
return result
|
45
|
+
})
|
46
|
+
.join(" ")
|
47
|
+
}
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import { path } from "drawing/path"
|
2
|
+
import { text } from "drawing/text"
|
3
|
+
import { defineSymbol } from "drawing/defineSymbol"
|
4
|
+
|
5
|
+
export default defineSymbol({
|
6
|
+
primitives: [
|
7
|
+
path({
|
8
|
+
points: [
|
9
|
+
{ x: 0, y: 0 },
|
10
|
+
{ x: 0.2, y: 0 },
|
11
|
+
{ x: 0.2, y: -0.12 },
|
12
|
+
{ x: 0.8, y: -0.12 },
|
13
|
+
{ x: 0.8, y: 0.12 },
|
14
|
+
{ x: 0.2, y: 0.12 },
|
15
|
+
{ x: 0.2, y: 0 },
|
16
|
+
],
|
17
|
+
color: "primary",
|
18
|
+
}),
|
19
|
+
path({
|
20
|
+
points: [
|
21
|
+
{ x: 0.8, y: 0 },
|
22
|
+
{ x: 1, y: 0 },
|
23
|
+
],
|
24
|
+
color: "primary",
|
25
|
+
}),
|
26
|
+
text("{REF}", { x: 0.5, y: -0.2, anchor: "middle_bottom" }),
|
27
|
+
text("{VAL}", { x: 0.5, y: 0.2, anchor: "middle_top" }),
|
28
|
+
],
|
29
|
+
ports: [
|
30
|
+
{ x: 0, y: 0, labels: ["1", "-"] },
|
31
|
+
{ x: 1, y: 0, labels: ["2", "+"] },
|
32
|
+
],
|
33
|
+
center: { x: 0.5, y: 0 },
|
34
|
+
size: { width: 1, height: 0.55 },
|
35
|
+
})
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import { defineSymbol } from "drawing/defineSymbol"
|
2
|
+
import svgJson from "assets/symbols-svg-json/fuse.json"
|
3
|
+
|
4
|
+
const { paths, texts, bounds, refblocks } = svgJson
|
5
|
+
|
6
|
+
export default defineSymbol({
|
7
|
+
primitives: [
|
8
|
+
...Object.values(paths),
|
9
|
+
{ ...texts.top1, anchor: "middle_bottom" },
|
10
|
+
{
|
11
|
+
type: "text",
|
12
|
+
text: "{VAL}",
|
13
|
+
x: 0,
|
14
|
+
y: 0.2,
|
15
|
+
anchor: "middle_top",
|
16
|
+
},
|
17
|
+
] as any,
|
18
|
+
ports: [
|
19
|
+
{ ...refblocks.left1, labels: ["1"] }, // TODO add more "standard" labels
|
20
|
+
{ ...refblocks.right1, labels: ["2"] }, // TODO add more "standard" labels
|
21
|
+
],
|
22
|
+
size: { width: bounds.width, height: bounds.height },
|
23
|
+
center: { x: bounds.centerX, y: bounds.centerY },
|
24
|
+
})
|
package/symbols/index.ts
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
import _boxresistor_horz from "./boxresistor_horz"
|
2
|
+
import _boxresistor_vert from "./boxresistor_vert"
|
3
|
+
import _fuse_horz from "./fuse_horz"
|
4
|
+
import _fuse_vert from "./fuse_vert"
|
5
|
+
import _led_horz from "./led_horz"
|
6
|
+
import _led_vert from "./led_vert"
|
7
|
+
import _mosfet_depletion_normally_on_horz from "./mosfet_depletion_normally_on_horz"
|
8
|
+
import _mosfet_depletion_normally_on_vert from "./mosfet_depletion_normally_on_vert"
|
9
|
+
import _potentiometer_horz from "./potentiometer_horz"
|
10
|
+
import _potentiometer_vert from "./potentiometer_vert"
|
11
|
+
import _potentiometer2_horz from "./potentiometer2_horz"
|
12
|
+
import _potentiometer2_vert from "./potentiometer2_vert"
|
13
|
+
import _varistor_horz from "./varistor_horz"
|
14
|
+
import _varistor_vert from "./varistor_vert"
|
15
|
+
|
16
|
+
export default {
|
17
|
+
"boxresistor_horz": _boxresistor_horz,
|
18
|
+
"boxresistor_vert": _boxresistor_vert,
|
19
|
+
"fuse_horz": _fuse_horz,
|
20
|
+
"fuse_vert": _fuse_vert,
|
21
|
+
"led_horz": _led_horz,
|
22
|
+
"led_vert": _led_vert,
|
23
|
+
"mosfet_depletion_normally_on_horz": _mosfet_depletion_normally_on_horz,
|
24
|
+
"mosfet_depletion_normally_on_vert": _mosfet_depletion_normally_on_vert,
|
25
|
+
"potentiometer_horz": _potentiometer_horz,
|
26
|
+
"potentiometer_vert": _potentiometer_vert,
|
27
|
+
"potentiometer2_horz": _potentiometer2_horz,
|
28
|
+
"potentiometer2_vert": _potentiometer2_vert,
|
29
|
+
"varistor_horz": _varistor_horz,
|
30
|
+
"varistor_vert": _varistor_vert
|
31
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import { defineSymbol } from "drawing/defineSymbol"
|
2
|
+
import svgJson from "assets/symbols-svg-json/led.json"
|
3
|
+
|
4
|
+
const { paths, texts, bounds, refblocks } = svgJson
|
5
|
+
|
6
|
+
export default defineSymbol({
|
7
|
+
primitives: [
|
8
|
+
...Object.values(paths),
|
9
|
+
{ ...texts.bottom1, anchor: "middle_left" },
|
10
|
+
{ ...texts.right1, anchor: "middle_left" },
|
11
|
+
] as any,
|
12
|
+
ports: [
|
13
|
+
{ ...refblocks.left1, labels: ["1"] }, // TODO add more "standard" labels
|
14
|
+
{ ...refblocks.right1, labels: ["2"] }, // TODO add more "standard" labels
|
15
|
+
],
|
16
|
+
size: { width: bounds.width, height: bounds.height },
|
17
|
+
center: { x: bounds.centerX, y: bounds.centerY + 0.1 },
|
18
|
+
})
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import { defineSymbol } from "drawing/defineSymbol"
|
2
|
+
import svgJson from "assets/symbols-svg-json/mosfet_depletion_normally_on.json"
|
3
|
+
|
4
|
+
const { paths, texts, bounds, refblocks } = svgJson
|
5
|
+
|
6
|
+
export default defineSymbol({
|
7
|
+
primitives: [
|
8
|
+
...Object.values(paths),
|
9
|
+
{ ...texts.right1, anchor: "middle_left" },
|
10
|
+
{ ...texts.right2, anchor: "middle_left" },
|
11
|
+
] as any,
|
12
|
+
ports: [
|
13
|
+
{ ...refblocks.top1, labels: ["1"] }, // TODO add more "standard" labels
|
14
|
+
{ ...refblocks.bottom1, labels: ["2"] }, // TODO add more "standard" labels
|
15
|
+
{ ...refblocks.left1, labels: ["3"] }, // TODO add more "standard" labels
|
16
|
+
],
|
17
|
+
size: { width: bounds.width + 0.4, height: bounds.height },
|
18
|
+
center: { x: bounds.centerX + 0.2, y: bounds.centerY },
|
19
|
+
})
|