@clubs.place/cli 0.0.0-stage → 0.1.17
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/.env.example +88 -0
- package/LICENSE +21 -0
- package/PROVENANCE.json +77 -0
- package/README.md +70 -2
- package/bin/clubs-nippo +7 -0
- package/bin/clubs-nippo-web.mjs +338 -0
- package/bin/clubs-nippo.mjs +527 -0
- package/docs/events-schema.md +76 -0
- package/examples/hermes-events.sample.jsonl +8 -0
- package/package.json +48 -4
- package/src/aggregate.mjs +105 -0
- package/src/autorun.mjs +25 -0
- package/src/autorun.test.mjs +43 -0
- package/src/cards.mjs +406 -0
- package/src/collect.mjs +111 -0
- package/src/config.mjs +173 -0
- package/src/generators/claude.mjs +31 -0
- package/src/generators/cli.mjs +81 -0
- package/src/generators/codex.mjs +28 -0
- package/src/generators/copilot.mjs +21 -0
- package/src/generators/gemini.mjs +20 -0
- package/src/generators/openai-compat.mjs +79 -0
- package/src/generators/openrouter.mjs +65 -0
- package/src/history.mjs +66 -0
- package/src/ingest.mjs +78 -0
- package/src/lemma.docHash.test.mjs +37 -0
- package/src/lemma.mjs +303 -0
- package/src/mask.mjs +45 -0
- package/src/mcp.mjs +269 -0
- package/src/narrative.mjs +191 -0
- package/src/prompt.mjs +184 -0
- package/src/prompt.test.mjs +146 -0
- package/src/remote-config.mjs +72 -0
- package/src/render.mjs +467 -0
- package/src/send.mjs +36 -0
- package/src/settings.mjs +54 -0
- package/src/sources/claude-code.mjs +174 -0
- package/src/sources/codex-cli.mjs +182 -0
- package/src/sources/copilot-cli.mjs +125 -0
- package/src/sources/cowork.mjs +193 -0
- package/src/sources/events-file.mjs +120 -0
- package/src/sources/gemini-cli.mjs +128 -0
- package/src/sources/hermes.mjs +427 -0
- package/src/store.mjs +227 -0
- package/src/tasks.mjs +229 -0
- package/src/tool-name.mjs +28 -0
- package/templates/report-v3.reference.html +162 -0
- package/web/assets/logo-clubs-white.png +0 -0
- package/web/assets/logo-clubs-white.svg +7 -0
- package/web/assets/logo-clubs-white.svg.tmp +30 -0
- package/web/assets/logo-clubs.svg +30 -0
- package/web/assets/qr.js +411 -0
- package/web/assets/sidebar.js +154 -0
- package/web/assets/twemoji.js +34 -0
- package/web/cards/achievements.html +230 -0
- package/web/cards/catalog.json +217 -0
- package/web/email/hero-v3.reference.html +123 -0
- package/web/home/index.html +269 -0
- package/web/preview.json +301 -0
- package/web/qr-selftest.html +46 -0
- package/web/reports/edit.html +255 -0
- package/web/reports/edit.reference.html +257 -0
- package/web/reports/index.html +196 -0
- package/web/settings/index.html +219 -0
- package/web/share/cards-reference.html +228 -0
- package/web/share/passport.html +214 -0
- package/web/share/teianbako.html +177 -0
- package/web/signup/index.html +326 -0
- package/web/tasks/index.html +229 -0
- package/web/verify/index.html +248 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<svg width="1514" height="361" viewBox="0 0 1514 361" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M1396.17 0C1370.79 0 1347.55 6.47289 1327.59 18.9656C1307.99 31.2323 1294.89 47.2002 1286.39 61.5209C1278.02 75.6295 1273.53 89.0826 1271.08 98.5517C1269.82 103.415 1269.01 107.585 1268.49 110.752C1268.23 112.345 1268.05 113.71 1267.91 114.811C1267.84 115.363 1267.78 115.851 1267.74 116.27C1267.72 116.48 1267.7 116.674 1267.68 116.849L1267.65 117.1L1267.64 117.271L1267.63 117.379L1267.61 117.55L1267.59 117.8C1267.58 117.937 1267.57 118.085 1267.56 118.242L1267.55 118.379C1267.51 118.799 1267.48 119.287 1267.45 119.838C1267.39 120.94 1267.33 122.305 1267.3 123.898C1267.23 127.065 1267.28 131.235 1267.65 136.098C1268.37 145.567 1270.42 159.02 1276.22 173.129C1282.1 187.45 1292.29 203.418 1309.65 215.684C1327.33 228.177 1349.39 234.65 1374.77 234.65C1378.39 234.65 1380.27 235.114 1381.05 235.392C1381.16 235.575 1381.31 235.867 1381.49 236.304C1382.18 237.989 1382.66 240.33 1382.84 242.706C1382.87 243.065 1382.89 243.391 1382.9 243.675C1382.84 243.959 1382.76 244.285 1382.67 244.644C1382.05 247.02 1381.15 249.361 1380.15 251.046C1379.89 251.483 1379.68 251.775 1379.54 251.958C1378.71 252.236 1376.74 252.7 1373.12 252.7H1255.29L1245.41 361H1363.24C1388.62 361 1411.86 354.527 1431.82 342.034C1451.42 329.768 1464.52 313.8 1473.01 299.479C1481.39 285.37 1485.88 271.917 1488.33 262.448C1489.59 257.585 1490.4 253.414 1490.92 250.247C1491.17 248.655 1491.36 247.29 1491.5 246.188C1491.57 245.637 1491.63 245.149 1491.67 244.729C1491.69 244.519 1491.71 244.326 1491.73 244.15L1491.76 243.9L1491.77 243.729L1491.78 243.621L1491.8 243.45L1491.82 243.199C1491.83 243.023 1491.85 242.83 1491.86 242.62C1491.9 242.201 1491.93 241.713 1491.96 241.161C1492.02 240.06 1492.08 238.695 1492.11 237.102C1492.18 233.935 1492.13 229.764 1491.76 224.902C1491.04 215.433 1488.99 201.979 1483.19 187.871C1477.31 173.55 1467.12 157.582 1449.76 145.315C1432.08 132.823 1410.02 126.35 1384.64 126.35C1381.02 126.35 1379.14 125.886 1378.36 125.608C1378.25 125.425 1378.1 125.133 1377.92 124.696C1377.23 123.011 1376.75 120.67 1376.57 118.294C1376.54 117.935 1376.52 117.609 1376.51 117.325C1376.57 117.041 1376.65 116.715 1376.74 116.356C1377.36 113.98 1378.26 111.639 1379.26 109.954C1379.52 109.517 1379.73 109.225 1379.87 109.042C1380.7 108.764 1382.67 108.3 1386.29 108.3H1504.12L1514 0H1396.17ZM1381.5 235.595C1381.5 235.6 1381.42 235.569 1381.3 235.487C1381.44 235.549 1381.51 235.59 1381.5 235.595ZM1380.89 235.15C1380.9 235.158 1380.91 235.169 1380.92 235.181C1380.89 235.144 1380.88 235.129 1380.88 235.129C1380.88 235.129 1380.88 235.137 1380.89 235.15ZM1379.32 252.221C1379.32 252.221 1379.33 252.2 1379.37 252.169C1379.34 252.207 1379.32 252.221 1379.32 252.221ZM1380.03 251.755C1380.02 251.75 1379.95 251.781 1379.81 251.862C1379.89 251.828 1379.95 251.801 1379.99 251.782C1380.02 251.767 1380.03 251.755 1380.03 251.755ZM1377.91 125.405C1377.91 125.4 1377.99 125.431 1378.11 125.513C1377.97 125.451 1377.9 125.41 1377.91 125.405ZM1378.52 125.847C1378.51 125.839 1378.5 125.83 1378.49 125.819C1378.52 125.856 1378.53 125.871 1378.53 125.871C1378.53 125.871 1378.53 125.862 1378.52 125.847ZM1380.09 108.779C1380.09 108.779 1380.08 108.8 1380.04 108.831C1380.07 108.794 1380.09 108.779 1380.09 108.779ZM1379.38 109.245C1379.39 109.25 1379.46 109.219 1379.6 109.137C1379.54 109.165 1379.48 109.188 1379.45 109.206C1379.4 109.228 1379.38 109.245 1379.38 109.245Z" fill="black"/>
|
|
3
|
+
<path d="M1120.62 0C1138.47 1.99503e-05 1155.89 2.91807 1171.86 8.58741C1187.84 14.2568 1202.07 22.566 1213.74 33.0416C1225.41 43.5171 1234.29 55.9537 1239.88 69.6407C1245.46 83.3276 1247.64 97.9975 1246.29 112.812C1244.94 127.627 1240.08 142.297 1232 155.984C1226.84 164.728 1220.42 172.961 1212.92 180.5C1219.05 188.039 1223.96 196.271 1227.53 205.016C1233.12 218.703 1235.3 233.373 1233.94 248.188C1232.59 263.002 1227.74 277.672 1219.66 291.359C1211.58 305.046 1200.43 317.483 1186.85 327.958C1173.27 338.434 1157.52 346.743 1140.51 352.412C1124.03 357.905 1106.67 360.815 1089.37 360.991L1087.69 361H935.417L968.34 0H1120.62ZM1052.42 270.75H1095.92C1099.5 270.75 1103.09 270.167 1106.49 269.033C1109.89 267.899 1113.04 266.236 1115.76 264.141C1118.47 262.046 1120.7 259.559 1122.32 256.822C1123.93 254.085 1124.9 251.151 1125.17 248.188C1125.45 245.225 1125.01 242.29 1123.89 239.553C1122.78 236.815 1121 234.328 1118.67 232.233C1116.33 230.138 1113.49 228.476 1110.29 227.343C1107.29 226.28 1104.05 225.7 1100.71 225.632L1100.04 225.625H1056.53L1052.42 270.75ZM1068.88 90.2504L1064.76 135.375H1108.27L1108.94 135.368C1112.29 135.3 1115.64 134.72 1118.83 133.657C1122.24 132.523 1125.39 130.861 1128.1 128.766C1130.82 126.671 1133.05 124.184 1134.66 121.447C1136.28 118.71 1137.25 115.775 1137.52 112.812C1137.79 109.849 1137.36 106.915 1136.24 104.178C1135.12 101.441 1133.35 98.9538 1131.01 96.8588C1128.68 94.7637 1125.83 93.1008 1122.64 91.967C1119.44 90.8331 1115.96 90.2505 1112.39 90.2504H1068.88Z" fill="black"/>
|
|
4
|
+
<path d="M619.475 207.575L638.406 0H747.176L728.245 207.575H728.248C727.707 213.5 728.344 219.368 730.122 224.842C731.9 230.317 734.785 235.291 738.612 239.481C742.438 243.671 747.13 246.995 752.422 249.262C757.713 251.53 763.499 252.697 769.45 252.697C775.401 252.697 781.401 251.53 787.106 249.262C792.811 246.995 798.11 243.671 802.7 239.481C807.29 235.291 811.082 230.317 813.859 224.842C816.635 219.368 818.343 213.501 818.884 207.575H818.886L837.816 0H946.586L927.655 207.575C925.818 227.723 920.012 247.674 910.571 266.288C901.13 284.903 888.237 301.816 872.629 316.062C857.021 330.309 839.004 341.61 819.606 349.321C800.208 357.031 779.808 361 759.573 361C739.338 361 719.662 357.031 701.67 349.321C683.679 341.61 667.722 330.309 654.713 316.062C641.704 301.816 631.896 284.903 625.85 266.288C619.993 248.256 617.777 228.968 619.315 209.463L619.475 207.575Z" fill="black"/>
|
|
5
|
+
<path d="M466.709 252.7H629.863L619.986 361H348.062L380.985 0H489.755L466.709 252.7Z" fill="black"/>
|
|
6
|
+
<path d="M166.725 6.15031C206.21 -4.13357 246.844 -1.46567 282.326 13.7399C317.808 28.9455 346.154 55.8389 362.969 90.2495L263.834 144.4C257.108 130.636 245.769 119.879 231.577 113.796C217.384 107.714 201.13 106.647 185.336 110.76C169.542 114.874 155.091 123.938 144.224 136.548C133.356 149.157 126.68 164.606 125.231 180.5C123.781 196.394 127.639 211.843 136.207 224.452C144.774 237.062 157.572 246.126 172.616 250.24C187.659 254.353 204.108 253.286 219.41 247.204C234.712 241.121 248.013 230.364 257.249 216.6L346.508 270.749C323.416 305.16 290.164 332.054 251.909 347.26C213.654 362.466 172.533 365.134 134.924 354.85C97.3151 344.566 65.3195 321.905 43.901 290.382C22.4824 258.859 12.8375 220.234 16.4612 180.5C20.085 140.766 36.7752 102.142 63.9433 70.6191C91.1118 39.0958 127.241 16.4343 166.725 6.15031Z" fill="black"/>
|
|
7
|
+
<path d="M362.969 90.2499C346.155 55.8391 317.808 28.9453 282.326 13.7397C246.844 -1.46589 206.21 -4.13358 166.725 6.15039C127.24 16.4344 91.1122 39.0953 63.9438 70.6186C36.7754 102.142 20.085 140.766 16.4613 180.5L125.231 180.5C126.68 164.606 133.356 149.157 144.224 136.547C155.091 123.938 169.542 114.874 185.336 110.76C201.13 106.647 217.384 107.714 231.576 113.796C245.769 119.878 257.108 130.636 263.834 144.4L362.969 90.2499Z" fill="url(#paint0_radial_337_177)"/>
|
|
8
|
+
<rect width="108.769" height="253.749" transform="matrix(1 0 -0.0908231 0.995867 380.985 0)" fill="url(#paint1_linear_337_177)"/>
|
|
9
|
+
<path d="M1108.27 135.375C1126.13 135.375 1143.54 138.293 1159.52 143.962C1175.5 149.632 1189.73 157.941 1201.4 168.417C1213.07 178.892 1221.95 191.329 1227.53 205.016C1233.12 218.703 1235.29 233.372 1233.94 248.187C1232.59 263.002 1227.74 277.672 1219.66 291.359C1211.58 305.045 1200.43 317.482 1186.85 327.958C1173.27 338.433 1157.52 346.743 1140.51 352.413C1124.03 357.905 1106.67 360.815 1089.37 360.991L1087.69 361H1044.19L1052.42 270.75H1095.92C1099.5 270.75 1103.08 270.166 1106.49 269.032C1109.89 267.898 1113.04 266.236 1115.75 264.141C1118.47 262.046 1120.7 259.559 1122.32 256.822C1123.93 254.085 1124.9 251.15 1125.17 248.187C1125.44 245.224 1125.01 242.29 1123.89 239.553C1122.77 236.816 1121 234.329 1118.66 232.234C1116.33 230.139 1113.49 228.476 1110.29 227.342C1107.29 226.279 1104.04 225.701 1100.71 225.632L1100.04 225.625H1056.53L1064.76 135.375H1108.27Z" fill="url(#paint2_radial_337_177)"/>
|
|
10
|
+
<defs>
|
|
11
|
+
<radialGradient id="paint0_radial_337_177" cx="0" cy="0" r="1" gradientTransform="matrix(-155.739 -11.7325 28.6954 -172.168 296.619 120.032)" gradientUnits="userSpaceOnUse">
|
|
12
|
+
<stop stop-color="#D39AFF"/>
|
|
13
|
+
<stop offset="0.166666" stop-color="#ED7FFF"/>
|
|
14
|
+
<stop offset="0.441666" stop-color="#8E66FF"/>
|
|
15
|
+
<stop offset="1" stop-color="#E372FF" stop-opacity="0"/>
|
|
16
|
+
</radialGradient>
|
|
17
|
+
<linearGradient id="paint1_linear_337_177" x1="108.769" y1="0" x2="16.1075" y2="238.902" gradientUnits="userSpaceOnUse">
|
|
18
|
+
<stop stop-color="#DFFFFD"/>
|
|
19
|
+
<stop offset="0.121666" stop-color="#B479FF"/>
|
|
20
|
+
<stop offset="0.326666" stop-color="#023AFF" stop-opacity="0.66"/>
|
|
21
|
+
<stop offset="1" stop-color="#A9A3F3" stop-opacity="0"/>
|
|
22
|
+
</linearGradient>
|
|
23
|
+
<radialGradient id="paint2_radial_337_177" cx="0" cy="0" r="1" gradientTransform="matrix(102.012 -147.108 241.037 115.568 1059.83 361)" gradientUnits="userSpaceOnUse">
|
|
24
|
+
<stop stop-color="#D39AFF"/>
|
|
25
|
+
<stop offset="0.146666" stop-color="#ED7FFF"/>
|
|
26
|
+
<stop offset="0.361666" stop-color="#8E66FF"/>
|
|
27
|
+
<stop offset="1" stop-color="#E372FF" stop-opacity="0"/>
|
|
28
|
+
</radialGradient>
|
|
29
|
+
</defs>
|
|
30
|
+
</svg>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<svg width="1514" height="361" viewBox="0 0 1514 361" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M1396.17 0C1370.79 0 1347.55 6.47289 1327.59 18.9656C1307.99 31.2323 1294.89 47.2002 1286.39 61.5209C1278.02 75.6295 1273.53 89.0826 1271.08 98.5517C1269.82 103.415 1269.01 107.585 1268.49 110.752C1268.23 112.345 1268.05 113.71 1267.91 114.811C1267.84 115.363 1267.78 115.851 1267.74 116.27C1267.72 116.48 1267.7 116.674 1267.68 116.849L1267.65 117.1L1267.64 117.271L1267.63 117.379L1267.61 117.55L1267.59 117.8C1267.58 117.937 1267.57 118.085 1267.56 118.242L1267.55 118.379C1267.51 118.799 1267.48 119.287 1267.45 119.838C1267.39 120.94 1267.33 122.305 1267.3 123.898C1267.23 127.065 1267.28 131.235 1267.65 136.098C1268.37 145.567 1270.42 159.02 1276.22 173.129C1282.1 187.45 1292.29 203.418 1309.65 215.684C1327.33 228.177 1349.39 234.65 1374.77 234.65C1378.39 234.65 1380.27 235.114 1381.05 235.392C1381.16 235.575 1381.31 235.867 1381.49 236.304C1382.18 237.989 1382.66 240.33 1382.84 242.706C1382.87 243.065 1382.89 243.391 1382.9 243.675C1382.84 243.959 1382.76 244.285 1382.67 244.644C1382.05 247.02 1381.15 249.361 1380.15 251.046C1379.89 251.483 1379.68 251.775 1379.54 251.958C1378.71 252.236 1376.74 252.7 1373.12 252.7H1255.29L1245.41 361H1363.24C1388.62 361 1411.86 354.527 1431.82 342.034C1451.42 329.768 1464.52 313.8 1473.01 299.479C1481.39 285.37 1485.88 271.917 1488.33 262.448C1489.59 257.585 1490.4 253.414 1490.92 250.247C1491.17 248.655 1491.36 247.29 1491.5 246.188C1491.57 245.637 1491.63 245.149 1491.67 244.729C1491.69 244.519 1491.71 244.326 1491.73 244.15L1491.76 243.9L1491.77 243.729L1491.78 243.621L1491.8 243.45L1491.82 243.199C1491.83 243.023 1491.85 242.83 1491.86 242.62C1491.9 242.201 1491.93 241.713 1491.96 241.161C1492.02 240.06 1492.08 238.695 1492.11 237.102C1492.18 233.935 1492.13 229.764 1491.76 224.902C1491.04 215.433 1488.99 201.979 1483.19 187.871C1477.31 173.55 1467.12 157.582 1449.76 145.315C1432.08 132.823 1410.02 126.35 1384.64 126.35C1381.02 126.35 1379.14 125.886 1378.36 125.608C1378.25 125.425 1378.1 125.133 1377.92 124.696C1377.23 123.011 1376.75 120.67 1376.57 118.294C1376.54 117.935 1376.52 117.609 1376.51 117.325C1376.57 117.041 1376.65 116.715 1376.74 116.356C1377.36 113.98 1378.26 111.639 1379.26 109.954C1379.52 109.517 1379.73 109.225 1379.87 109.042C1380.7 108.764 1382.67 108.3 1386.29 108.3H1504.12L1514 0H1396.17ZM1381.5 235.595C1381.5 235.6 1381.42 235.569 1381.3 235.487C1381.44 235.549 1381.51 235.59 1381.5 235.595ZM1380.89 235.15C1380.9 235.158 1380.91 235.169 1380.92 235.181C1380.89 235.144 1380.88 235.129 1380.88 235.129C1380.88 235.129 1380.88 235.137 1380.89 235.15ZM1379.32 252.221C1379.32 252.221 1379.33 252.2 1379.37 252.169C1379.34 252.207 1379.32 252.221 1379.32 252.221ZM1380.03 251.755C1380.02 251.75 1379.95 251.781 1379.81 251.862C1379.89 251.828 1379.95 251.801 1379.99 251.782C1380.02 251.767 1380.03 251.755 1380.03 251.755ZM1377.91 125.405C1377.91 125.4 1377.99 125.431 1378.11 125.513C1377.97 125.451 1377.9 125.41 1377.91 125.405ZM1378.52 125.847C1378.51 125.839 1378.5 125.83 1378.49 125.819C1378.52 125.856 1378.53 125.871 1378.53 125.871C1378.53 125.871 1378.53 125.862 1378.52 125.847ZM1380.09 108.779C1380.09 108.779 1380.08 108.8 1380.04 108.831C1380.07 108.794 1380.09 108.779 1380.09 108.779ZM1379.38 109.245C1379.39 109.25 1379.46 109.219 1379.6 109.137C1379.54 109.165 1379.48 109.188 1379.45 109.206C1379.4 109.228 1379.38 109.245 1379.38 109.245Z" fill="black"/>
|
|
3
|
+
<path d="M1120.62 0C1138.47 1.99503e-05 1155.89 2.91807 1171.86 8.58741C1187.84 14.2568 1202.07 22.566 1213.74 33.0416C1225.41 43.5171 1234.29 55.9537 1239.88 69.6407C1245.46 83.3276 1247.64 97.9975 1246.29 112.812C1244.94 127.627 1240.08 142.297 1232 155.984C1226.84 164.728 1220.42 172.961 1212.92 180.5C1219.05 188.039 1223.96 196.271 1227.53 205.016C1233.12 218.703 1235.3 233.373 1233.94 248.188C1232.59 263.002 1227.74 277.672 1219.66 291.359C1211.58 305.046 1200.43 317.483 1186.85 327.958C1173.27 338.434 1157.52 346.743 1140.51 352.412C1124.03 357.905 1106.67 360.815 1089.37 360.991L1087.69 361H935.417L968.34 0H1120.62ZM1052.42 270.75H1095.92C1099.5 270.75 1103.09 270.167 1106.49 269.033C1109.89 267.899 1113.04 266.236 1115.76 264.141C1118.47 262.046 1120.7 259.559 1122.32 256.822C1123.93 254.085 1124.9 251.151 1125.17 248.188C1125.45 245.225 1125.01 242.29 1123.89 239.553C1122.78 236.815 1121 234.328 1118.67 232.233C1116.33 230.138 1113.49 228.476 1110.29 227.343C1107.29 226.28 1104.05 225.7 1100.71 225.632L1100.04 225.625H1056.53L1052.42 270.75ZM1068.88 90.2504L1064.76 135.375H1108.27L1108.94 135.368C1112.29 135.3 1115.64 134.72 1118.83 133.657C1122.24 132.523 1125.39 130.861 1128.1 128.766C1130.82 126.671 1133.05 124.184 1134.66 121.447C1136.28 118.71 1137.25 115.775 1137.52 112.812C1137.79 109.849 1137.36 106.915 1136.24 104.178C1135.12 101.441 1133.35 98.9538 1131.01 96.8588C1128.68 94.7637 1125.83 93.1008 1122.64 91.967C1119.44 90.8331 1115.96 90.2505 1112.39 90.2504H1068.88Z" fill="black"/>
|
|
4
|
+
<path d="M619.475 207.575L638.406 0H747.176L728.245 207.575H728.248C727.707 213.5 728.344 219.368 730.122 224.842C731.9 230.317 734.785 235.291 738.612 239.481C742.438 243.671 747.13 246.995 752.422 249.262C757.713 251.53 763.499 252.697 769.45 252.697C775.401 252.697 781.401 251.53 787.106 249.262C792.811 246.995 798.11 243.671 802.7 239.481C807.29 235.291 811.082 230.317 813.859 224.842C816.635 219.368 818.343 213.501 818.884 207.575H818.886L837.816 0H946.586L927.655 207.575C925.818 227.723 920.012 247.674 910.571 266.288C901.13 284.903 888.237 301.816 872.629 316.062C857.021 330.309 839.004 341.61 819.606 349.321C800.208 357.031 779.808 361 759.573 361C739.338 361 719.662 357.031 701.67 349.321C683.679 341.61 667.722 330.309 654.713 316.062C641.704 301.816 631.896 284.903 625.85 266.288C619.993 248.256 617.777 228.968 619.315 209.463L619.475 207.575Z" fill="black"/>
|
|
5
|
+
<path d="M466.709 252.7H629.863L619.986 361H348.062L380.985 0H489.755L466.709 252.7Z" fill="black"/>
|
|
6
|
+
<path d="M166.725 6.15031C206.21 -4.13357 246.844 -1.46567 282.326 13.7399C317.808 28.9455 346.154 55.8389 362.969 90.2495L263.834 144.4C257.108 130.636 245.769 119.879 231.577 113.796C217.384 107.714 201.13 106.647 185.336 110.76C169.542 114.874 155.091 123.938 144.224 136.548C133.356 149.157 126.68 164.606 125.231 180.5C123.781 196.394 127.639 211.843 136.207 224.452C144.774 237.062 157.572 246.126 172.616 250.24C187.659 254.353 204.108 253.286 219.41 247.204C234.712 241.121 248.013 230.364 257.249 216.6L346.508 270.749C323.416 305.16 290.164 332.054 251.909 347.26C213.654 362.466 172.533 365.134 134.924 354.85C97.3151 344.566 65.3195 321.905 43.901 290.382C22.4824 258.859 12.8375 220.234 16.4612 180.5C20.085 140.766 36.7752 102.142 63.9433 70.6191C91.1118 39.0958 127.241 16.4343 166.725 6.15031Z" fill="black"/>
|
|
7
|
+
<path d="M362.969 90.2499C346.155 55.8391 317.808 28.9453 282.326 13.7397C246.844 -1.46589 206.21 -4.13358 166.725 6.15039C127.24 16.4344 91.1122 39.0953 63.9438 70.6186C36.7754 102.142 20.085 140.766 16.4613 180.5L125.231 180.5C126.68 164.606 133.356 149.157 144.224 136.547C155.091 123.938 169.542 114.874 185.336 110.76C201.13 106.647 217.384 107.714 231.576 113.796C245.769 119.878 257.108 130.636 263.834 144.4L362.969 90.2499Z" fill="url(#paint0_radial_337_177)"/>
|
|
8
|
+
<rect width="108.769" height="253.749" transform="matrix(1 0 -0.0908231 0.995867 380.985 0)" fill="url(#paint1_linear_337_177)"/>
|
|
9
|
+
<path d="M1108.27 135.375C1126.13 135.375 1143.54 138.293 1159.52 143.962C1175.5 149.632 1189.73 157.941 1201.4 168.417C1213.07 178.892 1221.95 191.329 1227.53 205.016C1233.12 218.703 1235.29 233.372 1233.94 248.187C1232.59 263.002 1227.74 277.672 1219.66 291.359C1211.58 305.045 1200.43 317.482 1186.85 327.958C1173.27 338.433 1157.52 346.743 1140.51 352.413C1124.03 357.905 1106.67 360.815 1089.37 360.991L1087.69 361H1044.19L1052.42 270.75H1095.92C1099.5 270.75 1103.08 270.166 1106.49 269.032C1109.89 267.898 1113.04 266.236 1115.75 264.141C1118.47 262.046 1120.7 259.559 1122.32 256.822C1123.93 254.085 1124.9 251.15 1125.17 248.187C1125.44 245.224 1125.01 242.29 1123.89 239.553C1122.77 236.816 1121 234.329 1118.66 232.234C1116.33 230.139 1113.49 228.476 1110.29 227.342C1107.29 226.279 1104.04 225.701 1100.71 225.632L1100.04 225.625H1056.53L1064.76 135.375H1108.27Z" fill="url(#paint2_radial_337_177)"/>
|
|
10
|
+
<defs>
|
|
11
|
+
<radialGradient id="paint0_radial_337_177" cx="0" cy="0" r="1" gradientTransform="matrix(-155.739 -11.7325 28.6954 -172.168 296.619 120.032)" gradientUnits="userSpaceOnUse">
|
|
12
|
+
<stop stop-color="#D39AFF"/>
|
|
13
|
+
<stop offset="0.166666" stop-color="#ED7FFF"/>
|
|
14
|
+
<stop offset="0.441666" stop-color="#8E66FF"/>
|
|
15
|
+
<stop offset="1" stop-color="#E372FF" stop-opacity="0"/>
|
|
16
|
+
</radialGradient>
|
|
17
|
+
<linearGradient id="paint1_linear_337_177" x1="108.769" y1="0" x2="16.1075" y2="238.902" gradientUnits="userSpaceOnUse">
|
|
18
|
+
<stop stop-color="#DFFFFD"/>
|
|
19
|
+
<stop offset="0.121666" stop-color="#B479FF"/>
|
|
20
|
+
<stop offset="0.326666" stop-color="#023AFF" stop-opacity="0.66"/>
|
|
21
|
+
<stop offset="1" stop-color="#A9A3F3" stop-opacity="0"/>
|
|
22
|
+
</linearGradient>
|
|
23
|
+
<radialGradient id="paint2_radial_337_177" cx="0" cy="0" r="1" gradientTransform="matrix(102.012 -147.108 241.037 115.568 1059.83 361)" gradientUnits="userSpaceOnUse">
|
|
24
|
+
<stop stop-color="#D39AFF"/>
|
|
25
|
+
<stop offset="0.146666" stop-color="#ED7FFF"/>
|
|
26
|
+
<stop offset="0.361666" stop-color="#8E66FF"/>
|
|
27
|
+
<stop offset="1" stop-color="#E372FF" stop-opacity="0"/>
|
|
28
|
+
</radialGradient>
|
|
29
|
+
</defs>
|
|
30
|
+
</svg>
|
package/web/assets/qr.js
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
// clubs-nippo — AI業務日報 (CLUBS)
|
|
2
|
+
// Copyright (c) 2026 FRAME00 Inc.
|
|
3
|
+
// SPDX-License-Identifier: MIT
|
|
4
|
+
// https://github.com/frame00/clubs-nippo
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* QR コード生成(依存ゼロ・バイトモード・誤り訂正レベル M)。
|
|
8
|
+
*
|
|
9
|
+
* 名刺に載せる QR は印刷して実際に読まれる。読めない絵を「QR」と称するのは、
|
|
10
|
+
* 誰も確認できない ✓ を出すのと同じなので、規格どおりに実装する。
|
|
11
|
+
* 検証は Chrome の BarcodeDetector で実際にデコードして行う。
|
|
12
|
+
*
|
|
13
|
+
* 対応: バイトモード(UTF-8)、バージョン1〜10、ECC レベル M。
|
|
14
|
+
* パスポート URL(数十文字)はこの範囲に収まる。
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// ── ガロア体 GF(256) ─────────────────────────────────────
|
|
18
|
+
const EXP = new Uint8Array(512);
|
|
19
|
+
const LOG = new Uint8Array(256);
|
|
20
|
+
(() => {
|
|
21
|
+
let x = 1;
|
|
22
|
+
for (let i = 0; i < 255; i += 1) {
|
|
23
|
+
EXP[i] = x;
|
|
24
|
+
LOG[x] = i;
|
|
25
|
+
x <<= 1;
|
|
26
|
+
if (x & 0x100) x ^= 0x11d; // 原始多項式 x^8+x^4+x^3+x^2+1
|
|
27
|
+
}
|
|
28
|
+
for (let i = 255; i < 512; i += 1) EXP[i] = EXP[i - 255];
|
|
29
|
+
})();
|
|
30
|
+
|
|
31
|
+
const gfMul = (a, b) => (a === 0 || b === 0 ? 0 : EXP[LOG[a] + LOG[b]]);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 生成多項式 g(x) = Π (x - α^i)。係数は降べきの順(poly[0] が最高次)。
|
|
35
|
+
*
|
|
36
|
+
* poly * (x + α^i) = poly*x + poly*α^i。
|
|
37
|
+
* 降べき配列では poly*x が「その場」(next[j])、poly*α^i が「1つ下」(next[j+1])に乗る。
|
|
38
|
+
* ここを取り違えると生成多項式が反転し、ECC が丸ごとでたらめになる。
|
|
39
|
+
* データビットの往復テストでは気づけない(実デコーダだけが ECC を検算するため)。
|
|
40
|
+
*/
|
|
41
|
+
const rsGenerator = (degree) => {
|
|
42
|
+
let poly = [1];
|
|
43
|
+
for (let i = 0; i < degree; i += 1) {
|
|
44
|
+
const next = new Array(poly.length + 1).fill(0);
|
|
45
|
+
for (let j = 0; j < poly.length; j += 1) {
|
|
46
|
+
next[j] ^= poly[j];
|
|
47
|
+
next[j + 1] ^= gfMul(poly[j], EXP[i]);
|
|
48
|
+
}
|
|
49
|
+
poly = next;
|
|
50
|
+
}
|
|
51
|
+
return poly;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const rsEncode = (data, eccLen) => {
|
|
55
|
+
const gen = rsGenerator(eccLen);
|
|
56
|
+
const res = new Array(eccLen).fill(0);
|
|
57
|
+
for (const byte of data) {
|
|
58
|
+
const factor = byte ^ res[0];
|
|
59
|
+
res.shift();
|
|
60
|
+
res.push(0);
|
|
61
|
+
for (let i = 0; i < eccLen; i += 1) res[i] ^= gfMul(gen[i + 1], factor);
|
|
62
|
+
}
|
|
63
|
+
return res;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// ── バージョン表(ECC=M のみ)────────────────────────────
|
|
67
|
+
// [総コードワード数, ECCコードワード/ブロック, グループ1ブロック数, グループ2ブロック数]
|
|
68
|
+
const VERSIONS_M = {
|
|
69
|
+
1: [26, 10, 1, 0],
|
|
70
|
+
2: [44, 16, 1, 0],
|
|
71
|
+
3: [70, 26, 1, 0],
|
|
72
|
+
4: [100, 18, 2, 0],
|
|
73
|
+
5: [134, 24, 2, 0],
|
|
74
|
+
6: [172, 16, 4, 0],
|
|
75
|
+
7: [196, 18, 4, 0],
|
|
76
|
+
8: [242, 22, 2, 2],
|
|
77
|
+
9: [292, 22, 3, 2],
|
|
78
|
+
10: [346, 26, 4, 1],
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/** 型番情報 18 ビット(データ6+BCH12)。生成多項式 0b1111100100101 */
|
|
82
|
+
const versionBits = (version) => {
|
|
83
|
+
let rem = version << 12;
|
|
84
|
+
for (let i = 17; i >= 12; i -= 1) {
|
|
85
|
+
if ((rem >> i) & 1) rem ^= 0b1111100100101 << (i - 12);
|
|
86
|
+
}
|
|
87
|
+
return (version << 12) | rem;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const ALIGN_POS = {
|
|
91
|
+
1: [], 2: [6, 18], 3: [6, 22], 4: [6, 26], 5: [6, 30],
|
|
92
|
+
6: [6, 34], 7: [6, 22, 38], 8: [6, 24, 42], 9: [6, 26, 46], 10: [6, 28, 50],
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const dataCapacity = (v) => {
|
|
96
|
+
const [total, eccPerBlock, g1, g2] = VERSIONS_M[v];
|
|
97
|
+
return total - eccPerBlock * (g1 + g2);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// ── ビット列 ─────────────────────────────────────────────
|
|
101
|
+
const bits = () => {
|
|
102
|
+
const arr = [];
|
|
103
|
+
return {
|
|
104
|
+
push: (value, len) => {
|
|
105
|
+
for (let i = len - 1; i >= 0; i -= 1) arr.push((value >> i) & 1);
|
|
106
|
+
},
|
|
107
|
+
get: () => arr,
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/** データコードワード(モード・長さ・本体・パディング)を作る。 */
|
|
112
|
+
const buildData = (text, version) => {
|
|
113
|
+
const bytes = new TextEncoder().encode(text);
|
|
114
|
+
const capacity = dataCapacity(version);
|
|
115
|
+
const b = bits();
|
|
116
|
+
|
|
117
|
+
b.push(0b0100, 4); // バイトモード
|
|
118
|
+
b.push(bytes.length, version <= 9 ? 8 : 16); // 文字数指示子
|
|
119
|
+
for (const byte of bytes) b.push(byte, 8);
|
|
120
|
+
|
|
121
|
+
const arr = b.get();
|
|
122
|
+
// 終端子(最大4ビット)
|
|
123
|
+
for (let i = 0; i < 4 && arr.length < capacity * 8; i += 1) arr.push(0);
|
|
124
|
+
// バイト境界まで 0 埋め
|
|
125
|
+
while (arr.length % 8 !== 0) arr.push(0);
|
|
126
|
+
|
|
127
|
+
const words = [];
|
|
128
|
+
for (let i = 0; i < arr.length; i += 8) {
|
|
129
|
+
words.push(arr.slice(i, i + 8).reduce((acc, bit) => (acc << 1) | bit, 0));
|
|
130
|
+
}
|
|
131
|
+
// 埋め草コードワード。必ず 0xEC から始め、0x11 と交互に置く。
|
|
132
|
+
// words.length の偶奇で決めると、データ長によって 0x11 から始まってしまう。
|
|
133
|
+
const PAD = [0xec, 0x11];
|
|
134
|
+
for (let i = 0; words.length < capacity; i += 1) words.push(PAD[i % 2]);
|
|
135
|
+
return words;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
/** ブロックに分けて RS 符号を付け、インターリーブする。 */
|
|
139
|
+
const interleave = (words, version) => {
|
|
140
|
+
const [, eccPerBlock, g1, g2] = VERSIONS_M[version];
|
|
141
|
+
const totalBlocks = g1 + g2;
|
|
142
|
+
const g1Size = Math.floor(words.length / totalBlocks);
|
|
143
|
+
|
|
144
|
+
const dataBlocks = [];
|
|
145
|
+
const eccBlocks = [];
|
|
146
|
+
let offset = 0;
|
|
147
|
+
for (let i = 0; i < totalBlocks; i += 1) {
|
|
148
|
+
const size = i < g1 ? g1Size : g1Size + 1;
|
|
149
|
+
const block = words.slice(offset, offset + size);
|
|
150
|
+
offset += size;
|
|
151
|
+
dataBlocks.push(block);
|
|
152
|
+
eccBlocks.push(rsEncode(block, eccPerBlock));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const out = [];
|
|
156
|
+
const maxData = Math.max(...dataBlocks.map((b) => b.length));
|
|
157
|
+
for (let i = 0; i < maxData; i += 1) {
|
|
158
|
+
for (const block of dataBlocks) if (i < block.length) out.push(block[i]);
|
|
159
|
+
}
|
|
160
|
+
for (let i = 0; i < eccPerBlock; i += 1) {
|
|
161
|
+
for (const block of eccBlocks) out.push(block[i]);
|
|
162
|
+
}
|
|
163
|
+
return out;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// ── モジュール配置 ───────────────────────────────────────
|
|
167
|
+
const buildMatrix = (version) => {
|
|
168
|
+
const size = version * 4 + 17;
|
|
169
|
+
const m = Array.from({ length: size }, () => new Array(size).fill(null));
|
|
170
|
+
const reserved = Array.from({ length: size }, () => new Array(size).fill(false));
|
|
171
|
+
|
|
172
|
+
const setFn = (r, c, v) => {
|
|
173
|
+
m[r][c] = v;
|
|
174
|
+
reserved[r][c] = true;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// 位置検出パターン(3隅)+分離パターン
|
|
178
|
+
for (const [br, bc] of [[0, 0], [0, size - 7], [size - 7, 0]]) {
|
|
179
|
+
for (let r = -1; r <= 7; r += 1) {
|
|
180
|
+
for (let c = -1; c <= 7; c += 1) {
|
|
181
|
+
const rr = br + r;
|
|
182
|
+
const cc = bc + c;
|
|
183
|
+
if (rr < 0 || rr >= size || cc < 0 || cc >= size) continue;
|
|
184
|
+
const inner = r >= 0 && r <= 6 && c >= 0 && c <= 6;
|
|
185
|
+
const dark =
|
|
186
|
+
inner &&
|
|
187
|
+
((r === 0 || r === 6 || c === 0 || c === 6) ||
|
|
188
|
+
(r >= 2 && r <= 4 && c >= 2 && c <= 4));
|
|
189
|
+
setFn(rr, cc, dark ? 1 : 0);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// タイミングパターン
|
|
195
|
+
for (let i = 8; i < size - 8; i += 1) {
|
|
196
|
+
setFn(6, i, i % 2 === 0 ? 1 : 0);
|
|
197
|
+
setFn(i, 6, i % 2 === 0 ? 1 : 0);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// 位置合わせパターン。
|
|
201
|
+
// 除外するのは「位置検出パターンと重なるもの」だけ。中心が予約済みかで判定すると、
|
|
202
|
+
// タイミング列と重なるだけの正当なパターン(v7 の (6,22) と (22,6) など)まで捨ててしまう。
|
|
203
|
+
const pos = ALIGN_POS[version];
|
|
204
|
+
const overlapsFinder = (r, c) =>
|
|
205
|
+
(r <= 8 && c <= 8) || (r <= 8 && c >= size - 9) || (r >= size - 9 && c <= 8);
|
|
206
|
+
for (const r of pos) {
|
|
207
|
+
for (const c of pos) {
|
|
208
|
+
if (overlapsFinder(r, c)) continue;
|
|
209
|
+
for (let dr = -2; dr <= 2; dr += 1) {
|
|
210
|
+
for (let dc = -2; dc <= 2; dc += 1) {
|
|
211
|
+
const dark = Math.max(Math.abs(dr), Math.abs(dc)) !== 1;
|
|
212
|
+
setFn(r + dr, c + dc, dark ? 1 : 0);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// 型番情報(バージョン7以上のみ)。BCH(18,6)。
|
|
219
|
+
// これが無いとデコーダはバージョンを確定できず、読めない。
|
|
220
|
+
if (version >= 7) {
|
|
221
|
+
const v = versionBits(version);
|
|
222
|
+
for (let i = 0; i < 18; i += 1) {
|
|
223
|
+
const bit = (v >> i) & 1;
|
|
224
|
+
const r = Math.floor(i / 3);
|
|
225
|
+
const c = i % 3;
|
|
226
|
+
setFn(r, size - 11 + c, bit); // 右上
|
|
227
|
+
setFn(size - 11 + c, r, bit); // 左下
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// 形式情報の領域を予約。
|
|
232
|
+
// 行6・列6 はタイミングパターンなので値は上書きしない(潰すと読めなくなる)。
|
|
233
|
+
for (let i = 0; i < 9; i += 1) {
|
|
234
|
+
if (!reserved[8][i]) setFn(8, i, 0);
|
|
235
|
+
if (!reserved[i][8]) setFn(i, 8, 0);
|
|
236
|
+
}
|
|
237
|
+
for (let i = 0; i < 8; i += 1) {
|
|
238
|
+
if (!reserved[8][size - 1 - i]) setFn(8, size - 1 - i, 0);
|
|
239
|
+
if (!reserved[size - 1 - i][8]) setFn(size - 1 - i, 8, 0);
|
|
240
|
+
}
|
|
241
|
+
setFn(size - 8, 8, 1); // 常に暗
|
|
242
|
+
|
|
243
|
+
return { m, reserved, size };
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
/** ジグザグにデータを流し込む。 */
|
|
247
|
+
const placeData = (m, reserved, size, codewords) => {
|
|
248
|
+
const bitsArr = [];
|
|
249
|
+
for (const w of codewords) for (let i = 7; i >= 0; i -= 1) bitsArr.push((w >> i) & 1);
|
|
250
|
+
|
|
251
|
+
let idx = 0;
|
|
252
|
+
let upward = true;
|
|
253
|
+
// タイミング列(6)に来たら col 自体をずらす。ずらさずに c だけ 5 にすると、
|
|
254
|
+
// 次の反復(col-=2 → 4)で 4 列目をもう一度処理してしまう。
|
|
255
|
+
for (let col = size - 1; col > 0; col -= 2) {
|
|
256
|
+
if (col === 6) col = 5;
|
|
257
|
+
for (let i = 0; i < size; i += 1) {
|
|
258
|
+
const row = upward ? size - 1 - i : i;
|
|
259
|
+
for (const cc of [col, col - 1]) {
|
|
260
|
+
if (reserved[row][cc]) continue;
|
|
261
|
+
m[row][cc] = idx < bitsArr.length ? bitsArr[idx] : 0;
|
|
262
|
+
idx += 1;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
upward = !upward;
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
const MASKS = [
|
|
270
|
+
(r, c) => (r + c) % 2 === 0,
|
|
271
|
+
(r) => r % 2 === 0,
|
|
272
|
+
(_r, c) => c % 3 === 0,
|
|
273
|
+
(r, c) => (r + c) % 3 === 0,
|
|
274
|
+
(r, c) => (Math.floor(r / 2) + Math.floor(c / 3)) % 2 === 0,
|
|
275
|
+
(r, c) => ((r * c) % 2) + ((r * c) % 3) === 0,
|
|
276
|
+
(r, c) => (((r * c) % 2) + ((r * c) % 3)) % 2 === 0,
|
|
277
|
+
(r, c) => (((r + c) % 2) + ((r * c) % 3)) % 2 === 0,
|
|
278
|
+
];
|
|
279
|
+
|
|
280
|
+
/** 形式情報(ECC=M は 00)+ BCH(15,5) + マスク 0x5412 */
|
|
281
|
+
const formatBits = (maskIdx) => {
|
|
282
|
+
const data = (0b00 << 3) | maskIdx;
|
|
283
|
+
let rem = data << 10;
|
|
284
|
+
for (let i = 14; i >= 10; i -= 1) {
|
|
285
|
+
if ((rem >> i) & 1) rem ^= 0b10100110111 << (i - 10);
|
|
286
|
+
}
|
|
287
|
+
return ((data << 10) | rem) ^ 0b101010000010010;
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* 形式情報を書く。
|
|
292
|
+
*
|
|
293
|
+
* ここは行と列を取り違えやすい。ビット 0〜5 は「列8・行0〜5」であって
|
|
294
|
+
* 「行8・列0〜5」ではない。取り違えても自作のデコーダとは辻褄が合ってしまうため、
|
|
295
|
+
* 自前の往復テストでは絶対に気づけない(実デコーダだけが落ちる)。
|
|
296
|
+
*/
|
|
297
|
+
const applyFormat = (m, size, maskIdx) => {
|
|
298
|
+
const f = formatBits(maskIdx);
|
|
299
|
+
const bit = (i) => (f >> i) & 1;
|
|
300
|
+
|
|
301
|
+
// 1枚目(位置検出パターンの周り)
|
|
302
|
+
for (let i = 0; i <= 5; i += 1) m[i][8] = bit(i);
|
|
303
|
+
m[7][8] = bit(6);
|
|
304
|
+
m[8][8] = bit(7);
|
|
305
|
+
m[8][7] = bit(8);
|
|
306
|
+
for (let i = 9; i <= 14; i += 1) m[8][14 - i] = bit(i);
|
|
307
|
+
|
|
308
|
+
// 2枚目。1枚目とビットの向きが逆になる(規格どおり)。
|
|
309
|
+
// 列8: 下から上へ b14…b8(7個)
|
|
310
|
+
// 行8: 左から右へ b7…b0(8個)
|
|
311
|
+
// (size-8, 8) は暗モジュールであって形式情報ではない。ここを形式ビットに使うと1ビットずれる。
|
|
312
|
+
for (let i = 0; i <= 6; i += 1) m[size - 1 - i][8] = bit(14 - i);
|
|
313
|
+
for (let j = 0; j <= 7; j += 1) m[8][size - 8 + j] = bit(7 - j);
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
/** ペナルティ評価(規則1〜4)。低いマスクを選ぶ。 */
|
|
317
|
+
const penalty = (m, size) => {
|
|
318
|
+
let score = 0;
|
|
319
|
+
|
|
320
|
+
const runScore = (line) => {
|
|
321
|
+
let s = 0;
|
|
322
|
+
let run = 1;
|
|
323
|
+
for (let i = 1; i < line.length; i += 1) {
|
|
324
|
+
if (line[i] === line[i - 1]) {
|
|
325
|
+
run += 1;
|
|
326
|
+
} else {
|
|
327
|
+
if (run >= 5) s += 3 + (run - 5);
|
|
328
|
+
run = 1;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (run >= 5) s += 3 + (run - 5);
|
|
332
|
+
return s;
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
for (let r = 0; r < size; r += 1) score += runScore(m[r]);
|
|
336
|
+
for (let c = 0; c < size; c += 1) score += runScore(m.map((row) => row[c]));
|
|
337
|
+
|
|
338
|
+
for (let r = 0; r < size - 1; r += 1) {
|
|
339
|
+
for (let c = 0; c < size - 1; c += 1) {
|
|
340
|
+
const v = m[r][c];
|
|
341
|
+
if (v === m[r][c + 1] && v === m[r + 1][c] && v === m[r + 1][c + 1]) score += 3;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const PATTERN = [1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0];
|
|
346
|
+
const hasPattern = (line, start) =>
|
|
347
|
+
PATTERN.every((v, i) => line[start + i] === v);
|
|
348
|
+
for (let r = 0; r < size; r += 1) {
|
|
349
|
+
for (let c = 0; c + 11 <= size; c += 1) {
|
|
350
|
+
if (hasPattern(m[r], c)) score += 40;
|
|
351
|
+
const col = m.map((row) => row[c]);
|
|
352
|
+
if (hasPattern(col, r) && r + 11 <= size) score += 40;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const dark = m.flat().filter((v) => v === 1).length;
|
|
357
|
+
const ratio = (dark * 100) / (size * size);
|
|
358
|
+
score += Math.floor(Math.abs(ratio - 50) / 5) * 10;
|
|
359
|
+
|
|
360
|
+
return score;
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
/** テキストから QR の行列(0/1 の二次元配列)を作る。 */
|
|
364
|
+
export const qrMatrix = (text) => {
|
|
365
|
+
const needed = new TextEncoder().encode(text).length;
|
|
366
|
+
const version = Object.keys(VERSIONS_M)
|
|
367
|
+
.map(Number)
|
|
368
|
+
.find((v) => dataCapacity(v) - (v <= 9 ? 2 : 3) >= needed);
|
|
369
|
+
if (!version) throw new Error(`QR: 長すぎます(${needed} bytes)`);
|
|
370
|
+
|
|
371
|
+
const codewords = interleave(buildData(text, version), version);
|
|
372
|
+
|
|
373
|
+
let best = null;
|
|
374
|
+
for (let mask = 0; mask < 8; mask += 1) {
|
|
375
|
+
const { m, reserved, size } = buildMatrix(version);
|
|
376
|
+
placeData(m, reserved, size, codewords);
|
|
377
|
+
for (let r = 0; r < size; r += 1) {
|
|
378
|
+
for (let c = 0; c < size; c += 1) {
|
|
379
|
+
if (!reserved[r][c] && MASKS[mask](r, c)) m[r][c] ^= 1;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
applyFormat(m, size, mask);
|
|
383
|
+
const score = penalty(m, size);
|
|
384
|
+
if (!best || score < best.score) best = { score, m, size };
|
|
385
|
+
}
|
|
386
|
+
return best.m;
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
/** QR の SVG 文字列。quiet zone(余白4モジュール)は規格上必須。 */
|
|
390
|
+
export const qrSvg = (text, { color = "#161A26", quiet = 4 } = {}) => {
|
|
391
|
+
const m = qrMatrix(text);
|
|
392
|
+
const size = m.length;
|
|
393
|
+
const total = size + quiet * 2;
|
|
394
|
+
|
|
395
|
+
const rects = [];
|
|
396
|
+
for (let r = 0; r < size; r += 1) {
|
|
397
|
+
for (let c = 0; c < size; c += 1) {
|
|
398
|
+
if (m[r][c] === 1) rects.push(`<rect x="${c + quiet}" y="${r + quiet}" width="1" height="1"/>`);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// width/height を必ず入れる。省くとブラウザは既定サイズ(300x150)で読み込み、
|
|
403
|
+
// canvas に描いたときに縦横比が崩れて QR が歪む(=読めなくなる)。
|
|
404
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${total}" height="${total}" viewBox="0 0 ${total} ${total}" shape-rendering="crispEdges">
|
|
405
|
+
<rect width="${total}" height="${total}" fill="#fff"/>
|
|
406
|
+
<g fill="${color}">${rects.join("")}</g>
|
|
407
|
+
</svg>`;
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
// テスト専用の口。実装の内部を検証で直接叩くため(本番コードからは使わない)。
|
|
411
|
+
export const __test = { buildMatrix, placeData, MASKS, formatBits, buildData, interleave, VERSIONS_M, dataCapacity };
|