First version of app, by GPT5

This commit is contained in:
2025-10-07 13:32:22 +01:00
parent 68aefead19
commit 50190d002d
8 changed files with 2845 additions and 4 deletions

1232
data/nextreg.txt Normal file

File diff suppressed because it is too large Load Diff

1239
data/nextreg_bare.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -9,17 +9,19 @@
"lint": "eslint"
},
"dependencies": {
"bootstrap": "^5.3.8",
"next": "15.5.4",
"react": "19.1.0",
"react-dom": "19.1.0",
"next": "15.5.4"
"react-bootstrap": "^2.10.10",
"react-dom": "19.1.0"
},
"devDependencies": {
"typescript": "^5",
"@eslint/eslintrc": "^3",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "15.5.4",
"@eslint/eslintrc": "^3"
"typescript": "^5"
}
}

212
pnpm-lock.yaml generated
View File

@@ -8,12 +8,18 @@ importers:
.:
dependencies:
bootstrap:
specifier: ^5.3.8
version: 5.3.8(@popperjs/core@2.11.8)
next:
specifier: 15.5.4
version: 15.5.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react:
specifier: 19.1.0
version: 19.1.0
react-bootstrap:
specifier: ^2.10.10
version: 2.10.10(@types/react@19.2.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react-dom:
specifier: 19.1.0
version: 19.1.0(react@19.1.0)
@@ -42,6 +48,10 @@ importers:
packages:
'@babel/runtime@7.28.4':
resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==}
engines: {node: '>=6.9.0'}
'@emnapi/core@1.5.0':
resolution: {integrity: sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==}
@@ -304,6 +314,31 @@ packages:
resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==}
engines: {node: '>=12.4.0'}
'@popperjs/core@2.11.8':
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
'@react-aria/ssr@3.9.10':
resolution: {integrity: sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ==}
engines: {node: '>= 12'}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
'@restart/hooks@0.4.16':
resolution: {integrity: sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==}
peerDependencies:
react: '>=16.8.0'
'@restart/hooks@0.5.1':
resolution: {integrity: sha512-EMoH04NHS1pbn07iLTjIjgttuqb7qu4+/EyhAx27MHpoENcB2ZdSsLTNxmKD+WEPnZigo62Qc8zjGnNxoSE/5Q==}
peerDependencies:
react: '>=16.8.0'
'@restart/ui@1.9.4':
resolution: {integrity: sha512-N4C7haUc3vn4LTwVUPlkJN8Ach/+yIMvRuTVIhjilNHqegY60SGLrzud6errOMNJwSnmYFnt1J0H/k8FE3A4KA==}
peerDependencies:
react: '>=16.14.0'
react-dom: '>=16.14.0'
'@rtsao/scc@1.1.0':
resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
@@ -328,14 +363,25 @@ packages:
'@types/node@20.19.19':
resolution: {integrity: sha512-pb1Uqj5WJP7wrcbLU7Ru4QtA0+3kAXrkutGiD26wUKzSMgNNaPARTUDQmElUXp64kh3cWdou3Q0C7qwwxqSFmg==}
'@types/prop-types@15.7.15':
resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==}
'@types/react-dom@19.2.1':
resolution: {integrity: sha512-/EEvYBdT3BflCWvTMO7YkYBHVE9Ci6XdqZciZANQgKpaiDRGOLIlRo91jbTNRQjgPFWVaRxcYc0luVNFitz57A==}
peerDependencies:
'@types/react': ^19.2.0
'@types/react-transition-group@4.4.12':
resolution: {integrity: sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==}
peerDependencies:
'@types/react': '*'
'@types/react@19.2.2':
resolution: {integrity: sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==}
'@types/warning@3.0.3':
resolution: {integrity: sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==}
'@typescript-eslint/eslint-plugin@8.46.0':
resolution: {integrity: sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -568,6 +614,11 @@ packages:
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
bootstrap@5.3.8:
resolution: {integrity: sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==}
peerDependencies:
'@popperjs/core': ^2.11.8
brace-expansion@1.1.12:
resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
@@ -601,6 +652,9 @@ packages:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
classnames@2.5.1:
resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==}
client-only@0.0.1:
resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
@@ -664,6 +718,10 @@ packages:
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
engines: {node: '>= 0.4'}
dequal@2.0.3:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'}
detect-libc@2.1.2:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
@@ -672,6 +730,9 @@ packages:
resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
engines: {node: '>=0.10.0'}
dom-helpers@5.2.1:
resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==}
dunder-proto@1.0.1:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'}
@@ -982,6 +1043,9 @@ packages:
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
engines: {node: '>= 0.4'}
invariant@2.2.4:
resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==}
is-array-buffer@3.0.5:
resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
engines: {node: '>= 0.4'}
@@ -1289,6 +1353,11 @@ packages:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
prop-types-extra@1.1.1:
resolution: {integrity: sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==}
peerDependencies:
react: '>=0.14.0'
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
@@ -1299,6 +1368,16 @@ packages:
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
react-bootstrap@2.10.10:
resolution: {integrity: sha512-gMckKUqn8aK/vCnfwoBpBVFUGT9SVQxwsYrp9yDHt0arXMamxALerliKBxr1TPbntirK/HGrUAHYbAeQTa9GHQ==}
peerDependencies:
'@types/react': '>=16.14.8'
react: '>=16.14.0'
react-dom: '>=16.14.0'
peerDependenciesMeta:
'@types/react':
optional: true
react-dom@19.1.0:
resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==}
peerDependencies:
@@ -1307,6 +1386,15 @@ packages:
react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
react-lifecycles-compat@3.0.4:
resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==}
react-transition-group@4.4.5:
resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==}
peerDependencies:
react: '>=16.6.0'
react-dom: '>=16.6.0'
react@19.1.0:
resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==}
engines: {node: '>=0.10.0'}
@@ -1518,6 +1606,16 @@ packages:
resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==}
engines: {node: '>= 0.4'}
uncontrollable@7.2.1:
resolution: {integrity: sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==}
peerDependencies:
react: '>=15.0.0'
uncontrollable@8.0.4:
resolution: {integrity: sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==}
peerDependencies:
react: '>=16.14.0'
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
@@ -1527,6 +1625,9 @@ packages:
uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
warning@4.0.3:
resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==}
which-boxed-primitive@1.1.1:
resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
engines: {node: '>= 0.4'}
@@ -1558,6 +1659,8 @@ packages:
snapshots:
'@babel/runtime@7.28.4': {}
'@emnapi/core@1.5.0':
dependencies:
'@emnapi/wasi-threads': 1.1.0
@@ -1771,6 +1874,37 @@ snapshots:
'@nolyfill/is-core-module@1.0.39': {}
'@popperjs/core@2.11.8': {}
'@react-aria/ssr@3.9.10(react@19.1.0)':
dependencies:
'@swc/helpers': 0.5.15
react: 19.1.0
'@restart/hooks@0.4.16(react@19.1.0)':
dependencies:
dequal: 2.0.3
react: 19.1.0
'@restart/hooks@0.5.1(react@19.1.0)':
dependencies:
dequal: 2.0.3
react: 19.1.0
'@restart/ui@1.9.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@babel/runtime': 7.28.4
'@popperjs/core': 2.11.8
'@react-aria/ssr': 3.9.10(react@19.1.0)
'@restart/hooks': 0.5.1(react@19.1.0)
'@types/warning': 3.0.3
dequal: 2.0.3
dom-helpers: 5.2.1
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
uncontrollable: 8.0.4(react@19.1.0)
warning: 4.0.3
'@rtsao/scc@1.1.0': {}
'@rushstack/eslint-patch@1.13.0': {}
@@ -1794,14 +1928,22 @@ snapshots:
dependencies:
undici-types: 6.21.0
'@types/prop-types@15.7.15': {}
'@types/react-dom@19.2.1(@types/react@19.2.2)':
dependencies:
'@types/react': 19.2.2
'@types/react-transition-group@4.4.12(@types/react@19.2.2)':
dependencies:
'@types/react': 19.2.2
'@types/react@19.2.2':
dependencies:
csstype: 3.1.3
'@types/warning@3.0.3': {}
'@typescript-eslint/eslint-plugin@8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0)(typescript@5.9.3))(eslint@9.37.0)(typescript@5.9.3)':
dependencies:
'@eslint-community/regexpp': 4.12.1
@@ -2056,6 +2198,10 @@ snapshots:
balanced-match@1.0.2: {}
bootstrap@5.3.8(@popperjs/core@2.11.8):
dependencies:
'@popperjs/core': 2.11.8
brace-expansion@1.1.12:
dependencies:
balanced-match: 1.0.2
@@ -2095,6 +2241,8 @@ snapshots:
ansi-styles: 4.3.0
supports-color: 7.2.0
classnames@2.5.1: {}
client-only@0.0.1: {}
color-convert@2.0.1:
@@ -2155,6 +2303,8 @@ snapshots:
has-property-descriptors: 1.0.2
object-keys: 1.1.1
dequal@2.0.3: {}
detect-libc@2.1.2:
optional: true
@@ -2162,6 +2312,11 @@ snapshots:
dependencies:
esutils: 2.0.3
dom-helpers@5.2.1:
dependencies:
'@babel/runtime': 7.28.4
csstype: 3.1.3
dunder-proto@1.0.1:
dependencies:
call-bind-apply-helpers: 1.0.2
@@ -2623,6 +2778,10 @@ snapshots:
hasown: 2.0.2
side-channel: 1.1.0
invariant@2.2.4:
dependencies:
loose-envify: 1.4.0
is-array-buffer@3.0.5:
dependencies:
call-bind: 1.0.8
@@ -2937,6 +3096,12 @@ snapshots:
prelude-ls@1.2.1: {}
prop-types-extra@1.1.1(react@19.1.0):
dependencies:
react: 19.1.0
react-is: 16.13.1
warning: 4.0.3
prop-types@15.8.1:
dependencies:
loose-envify: 1.4.0
@@ -2947,6 +3112,26 @@ snapshots:
queue-microtask@1.2.3: {}
react-bootstrap@2.10.10(@types/react@19.2.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
'@babel/runtime': 7.28.4
'@restart/hooks': 0.4.16(react@19.1.0)
'@restart/ui': 1.9.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@types/prop-types': 15.7.15
'@types/react-transition-group': 4.4.12(@types/react@19.2.2)
classnames: 2.5.1
dom-helpers: 5.2.1
invariant: 2.2.4
prop-types: 15.8.1
prop-types-extra: 1.1.1(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
react-transition-group: 4.4.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
uncontrollable: 7.2.1(react@19.1.0)
warning: 4.0.3
optionalDependencies:
'@types/react': 19.2.2
react-dom@19.1.0(react@19.1.0):
dependencies:
react: 19.1.0
@@ -2954,6 +3139,17 @@ snapshots:
react-is@16.13.1: {}
react-lifecycles-compat@3.0.4: {}
react-transition-group@4.4.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
'@babel/runtime': 7.28.4
dom-helpers: 5.2.1
loose-envify: 1.4.0
prop-types: 15.8.1
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
react@19.1.0: {}
reflect.getprototypeof@1.0.10:
@@ -3251,6 +3447,18 @@ snapshots:
has-symbols: 1.1.0
which-boxed-primitive: 1.1.1
uncontrollable@7.2.1(react@19.1.0):
dependencies:
'@babel/runtime': 7.28.4
'@types/react': 19.2.2
invariant: 2.2.4
react: 19.1.0
react-lifecycles-compat: 3.0.4
uncontrollable@8.0.4(react@19.1.0):
dependencies:
react: 19.1.0
undici-types@6.21.0: {}
unrs-resolver@1.11.1:
@@ -3281,6 +3489,10 @@ snapshots:
dependencies:
punycode: 2.3.1
warning@4.0.3:
dependencies:
loose-envify: 1.4.0
which-boxed-primitive@1.1.1:
dependencies:
is-bigint: 1.1.0

View File

@@ -18,6 +18,9 @@ export default function Home() {
Get started by editing <code>src/app/page.tsx</code>.
</li>
<li>Save and see your changes instantly.</li>
<li>
Explore the <a href="/registers">Spectrum Next Registers</a>.
</li>
</ol>
<div className={styles.ctas}>

View File

@@ -0,0 +1,45 @@
'use client';
import { useState } from 'react';
import { Register } from './types';
import { Form, Card, Container, Row, Col } from 'react-bootstrap';
interface RegisterBrowserProps {
registers: Register[];
}
export default function RegisterBrowser({ registers }: RegisterBrowserProps) {
const [searchTerm, setSearchTerm] = useState('');
const filteredRegisters = registers.filter(register =>
register.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
register.description.toLowerCase().includes(searchTerm.toLowerCase())
);
return (
<Container fluid>
<Form.Group className="mb-3">
<Form.Control
type="text"
placeholder="Search registers..."
value={searchTerm}
onChange={e => setSearchTerm(e.target.value)}
/>
</Form.Group>
<Row>
{filteredRegisters.map(register => (
<Col key={register.hex_address} xs={12} md={6} lg={4} className="mb-4">
<Card>
<Card.Header>
<strong>{register.name}</strong> ({register.hex_address} / {register.dec_address})
</Card.Header>
<Card.Body>
<pre style={{ whiteSpace: 'pre-wrap' }}>{register.description}</pre>
</Card.Body>
</Card>
</Col>
))}
</Row>
</Container>
);
}

View File

@@ -0,0 +1,87 @@
import { promises as fs } from 'fs';
import path from 'path';
import RegisterBrowser from './RegisterBrowser';
import { Register } from './types';
async function parseNextReg(fileContent: string): Promise<Register[]> {
const registers: Register[] = [];
const paragraphs = fileContent.split(/\n\s*\n/);
for (const paragraph of paragraphs) {
if (!paragraph.trim()) {
continue;
}
const lines = paragraph.trim().split('\n');
processRegisterBlock(lines, registers);
}
return registers;
}
function processRegisterBlock(lines: string[], registers: Register[]) {
const firstLine = lines[0];
const restOfLines = lines.slice(1);
const multiRegisterMatch = firstLine.match(/([0-9a-fA-F,x]+)\s*\(.*?\)\s*=>\s*(.*)/);
if (multiRegisterMatch) {
const hexAddresses = multiRegisterMatch[1].trim();
const decAddresses = multiRegisterMatch[2].trim();
const name = multiRegisterMatch[3] ? multiRegisterMatch[3].trim() : '';
const description = restOfLines.join('\n').trim();
const hexList = hexAddresses.split(',').map(h => h.trim());
const decList = decAddresses.includes('-') ? decAddresses.split('-') : decAddresses.split(',').map(d => d.trim());
if (hexList.length > 1) {
for (let i = 0; i < hexList.length; i++) {
const hexAddr = hexList[i];
const decAddr = decList[i] || decAddresses;
registers.push({
hex_address: hexAddr,
dec_address: isNaN(parseInt(decAddr, 10)) ? decAddr : parseInt(decAddr, 10),
name: `${name} (${hexAddr})`,
description: description,
});
}
} else {
registers.push({
hex_address: hexAddresses,
dec_address: isNaN(parseInt(decAddresses, 10)) ? decAddresses : parseInt(decAddresses, 10),
name: name,
description: description,
});
}
return;
}
const singleRegisterMatch = lines[0].match(/(0x[0-9a-fA-F]{2})\s+(\d+)\s+=>\s+(.*)/);
if(singleRegisterMatch) {
const description = lines.slice(1).join('\n').trim();
const hexAddr = singleRegisterMatch[1].trim();
const decAddr = singleRegisterMatch[2].trim();
const name = singleRegisterMatch[3].trim();
registers.push({
hex_address: hexAddr,
dec_address: parseInt(decAddr, 10),
name: name,
description: description,
});
}
}
export default async function RegistersPage() {
const filePath = path.join(process.cwd(), 'data', 'nextreg_bare.txt');
const fileContent = await fs.readFile(filePath, 'utf8');
const registers = await parseNextReg(fileContent);
return (
<div>
<h1>Spectrum Next Registers</h1>
<RegisterBrowser registers={registers} />
</div>
);
}

View File

@@ -0,0 +1,21 @@
export interface BitwiseOperation {
bits: string;
description: string;
value?: string;
notes?: string[];
}
export interface RegisterAccess {
description?: string;
operations: BitwiseOperation[];
}
export interface Register {
hex_address: string;
dec_address: number | string;
name: string;
description: string;
read?: RegisterAccess;
write?: RegisterAccess;
notes?: string[];
}