lookatstudy-mobile 0.23.0 → 0.24.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/package.json +1 -1
- package/seed-course.json +15 -15
- package/server.cjs +342 -22
- package/web/assets/{CanvasStage-Ba-21anG.js → CanvasStage-u_7YeGk1.js} +1 -1
- package/web/assets/{CommandPalette-SKnzQMcN.js → CommandPalette-Q5j7BQf4.js} +1 -1
- package/web/assets/{CourseSearchPanel-BW3fNReR.js → CourseSearchPanel-BYGHjhnk.js} +1 -1
- package/web/assets/{ExamView-BnH6BraN.js → ExamView-DU5X7LyZ.js} +1 -1
- package/web/assets/{MindmapView-B4SeCLQj.js → MindmapView-C61d4ddf.js} +3 -3
- package/web/assets/{ReviewPanel-DkGT8tNA.js → ReviewPanel-DoLMdlpR.js} +1 -1
- package/web/assets/SettingsView-CD9th6O0.js +7 -0
- package/web/assets/{VoicePanel-CxNeKn4V.js → VoicePanel-Cvl2BLq2.js} +1 -1
- package/web/assets/{abnfDiagram-N423BO3Z-B4kvB05N.js → abnfDiagram-N423BO3Z-BvTcLUtE.js} +1 -1
- package/web/assets/{abnfDiagram-VCTEODGH-ODA7YWAP-B5zhG8XJ.js → abnfDiagram-VCTEODGH-ODA7YWAP-NpbseUTF.js} +1 -1
- package/web/assets/{architectureDiagram-5GKGNRK7-C4PU3XN7-ybcWxxhr.js → architectureDiagram-5GKGNRK7-C4PU3XN7-DGtDmisd.js} +1 -1
- package/web/assets/{architectureDiagram-T3A2C74G-D5eb-etB.js → architectureDiagram-T3A2C74G-huu8moy9.js} +1 -1
- package/web/assets/{arrow-right-D4GV0Gpo.js → arrow-right-B0QrRNSR.js} +1 -1
- package/web/assets/{blockDiagram-NRAW4CY4-UMJ6PMQQ-DwEVReBp.js → blockDiagram-NRAW4CY4-UMJ6PMQQ-BxiaVwV9.js} +1 -1
- package/web/assets/{blockDiagram-VBNYF7ZC-DuM7ndnl.js → blockDiagram-VBNYF7ZC-BAnlmDNm.js} +1 -1
- package/web/assets/{c4Diagram-5PPSVZJV-BQkRaO7S.js → c4Diagram-5PPSVZJV-MUU8xp1X.js} +1 -1
- package/web/assets/{c4Diagram-UCG6FXSJ-75X3U2P3-Di1jNn7S.js → c4Diagram-UCG6FXSJ-75X3U2P3-7rpgYEob.js} +1 -1
- package/web/assets/channel-BJoUn5Z8.js +1 -0
- package/web/assets/{chunk-2GRJ4B5K-C7VAL2Yd.js → chunk-2GRJ4B5K-BZ6Sj0-3.js} +1 -1
- package/web/assets/{chunk-2Q5K7J3B-Jpo34qVL.js → chunk-2Q5K7J3B-BkOSQBqV.js} +1 -1
- package/web/assets/{chunk-5RXB4S5H-CrW8aZl4.js → chunk-5RXB4S5H-DgXJvWY0.js} +1 -1
- package/web/assets/{chunk-5VM5RSS4-Dv4MffdC.js → chunk-5VM5RSS4-D-BptZQ9.js} +1 -1
- package/web/assets/{chunk-6Q2QTUOP-CI07iNTB.js → chunk-6Q2QTUOP-DIJ0lWTD.js} +1 -1
- package/web/assets/{chunk-7XDTSPCN-DsQtrF-N.js → chunk-7XDTSPCN-vxuDBi1y.js} +1 -1
- package/web/assets/{chunk-CTNIYPP6-CpdWBpIN.js → chunk-CTNIYPP6-F5ZMIO6O.js} +1 -1
- package/web/assets/{chunk-CXNFBKHE-BDCDRaZC.js → chunk-CXNFBKHE-CFr1EfBh.js} +1 -1
- package/web/assets/{chunk-GF5L2VYU-DtpZkefy.js → chunk-GF5L2VYU-jqePwawx.js} +1 -1
- package/web/assets/{chunk-ISA7TJRJ-C3LgQ-bA.js → chunk-ISA7TJRJ-DiKuu0wz.js} +1 -1
- package/web/assets/{chunk-JWPE2WC7-DJM1SevB.js → chunk-JWPE2WC7-CLC3hqKr.js} +1 -1
- package/web/assets/{chunk-KBJHAD2P-7KeTMqC1.js → chunk-KBJHAD2P-DSEKcYpO.js} +1 -1
- package/web/assets/{chunk-LV3HUYFY-B2sGhGxz.js → chunk-LV3HUYFY-P2e0-qZ6.js} +1 -1
- package/web/assets/{chunk-M3IUQBOH-Dazbegdb.js → chunk-M3IUQBOH-Bdt4MjFy.js} +1 -1
- package/web/assets/{chunk-NDIOYS4C-Cx7mCz5-.js → chunk-NDIOYS4C-7HlPLAGd.js} +1 -1
- package/web/assets/{chunk-RE4WF27V-BNzpDJts.js → chunk-RE4WF27V-D4vIv_G3.js} +1 -1
- package/web/assets/{chunk-RYQCIY6F-Boq_29rU.js → chunk-RYQCIY6F-tTcuHeqw.js} +1 -1
- package/web/assets/{chunk-VII2H2IX-kQVDZD-x.js → chunk-VII2H2IX-BkXECJ1Z.js} +1 -1
- package/web/assets/{chunk-X5GNSKZ3-DT5Ja5IF.js → chunk-X5GNSKZ3-D7yjZGWk.js} +1 -1
- package/web/assets/{chunk-XCWWM2C3-BAq7zpgL.js → chunk-XCWWM2C3-C_es6n6S.js} +1 -1
- package/web/assets/{chunk-XXDRQBXY-D3vcLngc.js → chunk-XXDRQBXY-Bsuow-B8.js} +1 -1
- package/web/assets/classDiagram-DTDB5LWJ-LWRDKZ5K-B3DqqoSe.js +1 -0
- package/web/assets/classDiagram-JCYQIIEL-C2n-a_rM.js +1 -0
- package/web/assets/classDiagram-v2-JRS7N3AN-2BZHGRP2-B3DqqoSe.js +1 -0
- package/web/assets/classDiagram-v2-OCEON4UE-C2n-a_rM.js +1 -0
- package/web/assets/{core-4d9vIKK9.js → core-Bgf5ngI5.js} +1 -1
- package/web/assets/{cose-bilkent-JH36ORCC-OB24KH3T-DwFzf1xR.js → cose-bilkent-JH36ORCC-OB24KH3T-DM0H6Gci.js} +1 -1
- package/web/assets/{cose-bilkent-JH36ORCC-RoUdcSs7.js → cose-bilkent-JH36ORCC-x05QuEnY.js} +1 -1
- package/web/assets/{cynefin-OW5HDTMX-GVF3BKWE-Bdt2EF7g.js → cynefin-OW5HDTMX-GVF3BKWE-DY90g1OE.js} +1 -1
- package/web/assets/{cynefin-VYW2F7L2-Br1TXK2f.js → cynefin-VYW2F7L2-DjqH_9VW.js} +1 -1
- package/web/assets/{cynefinDiagram-5FMLGOSQ-H3WIRU3N-DFRlDIhn.js → cynefinDiagram-5FMLGOSQ-H3WIRU3N-DoaOZ7iJ.js} +1 -1
- package/web/assets/{cynefinDiagram-MW4NZA55-DeqLH2Db.js → cynefinDiagram-MW4NZA55-DI8ePik6.js} +1 -1
- package/web/assets/{dagre-3AP2YEHR-DCERTXHT-wbCkJQSQ.js → dagre-3AP2YEHR-DCERTXHT-BwLHkvZV.js} +1 -1
- package/web/assets/{dagre-VZM6K2ZE-X3laLObS.js → dagre-VZM6K2ZE-0zjstOys.js} +1 -1
- package/web/assets/{diagram-7IWD3JNH-8bZxUpBi.js → diagram-7IWD3JNH-CoRwcTua.js} +1 -1
- package/web/assets/{diagram-B4RE2ZJO-CsGnKBa4.js → diagram-B4RE2ZJO-Cau1H7nm.js} +1 -1
- package/web/assets/{diagram-LBJQPF4R-CxaNBwKI.js → diagram-LBJQPF4R-CZIgxCTB.js} +1 -1
- package/web/assets/{diagram-Q27KOJAE-CjVLD6gb.js → diagram-Q27KOJAE-B_LnuCra.js} +1 -1
- package/web/assets/{diagram-S7CK7UJ4-MULGZGEL-wKLcWkw4.js → diagram-S7CK7UJ4-MULGZGEL-C7lZT5bQ.js} +1 -1
- package/web/assets/{diagram-UB23O5K3-CUZ34yVE.js → diagram-UB23O5K3-qTFCSozX.js} +1 -1
- package/web/assets/{diagram-UQ7AKVKN-YQBY353J-B_ah6OV8.js → diagram-UQ7AKVKN-YQBY353J-CIootVI_.js} +1 -1
- package/web/assets/{diagram-VSXAHHWV-WLNH2ELY-BhbJ7E_e.js → diagram-VSXAHHWV-WLNH2ELY-BW8LpgQJ.js} +1 -1
- package/web/assets/{diagram-VX7I27RA-XW6YQV5G-DnFEyO87.js → diagram-VX7I27RA-XW6YQV5G-DfhGfGMR.js} +1 -1
- package/web/assets/{diagram-Z3DM3KII-HG7RF65D-Vughovua.js → diagram-Z3DM3KII-HG7RF65D-seunnnEY.js} +1 -1
- package/web/assets/{ebnfDiagram-BXEA7PRR-B2ehf44X.js → ebnfDiagram-BXEA7PRR-ksZAvx5f.js} +1 -1
- package/web/assets/{ebnfDiagram-PWID7BFC-OKY4VHYD-BjbgNq8R.js → ebnfDiagram-PWID7BFC-OKY4VHYD-Bvj1acAA.js} +1 -1
- package/web/assets/{elk.bundled-CktUbZ7z.js → elk.bundled-DP5Rghza.js} +1 -1
- package/web/assets/{erDiagram-JOGREHBK-9wI_YE-7.js → erDiagram-JOGREHBK-Dz3-stVV.js} +1 -1
- package/web/assets/{erDiagram-SSCWMZ5O-PIPKOIK7-V60k7zg6.js → erDiagram-SSCWMZ5O-PIPKOIK7-DoltPq2T.js} +1 -1
- package/web/assets/{flowDiagram-A5DVABFB-2Z4AVO5R-CJdwjvtN.js → flowDiagram-A5DVABFB-2Z4AVO5R-EXpUdCkE.js} +1 -1
- package/web/assets/{flowDiagram-UKHOOZJN-B3XmqjMH.js → flowDiagram-UKHOOZJN--KUxj2rZ.js} +1 -1
- package/web/assets/{ganttDiagram-EL5Y4UJY-JZNG7GOG-2a6TiXM3.js → ganttDiagram-EL5Y4UJY-JZNG7GOG-B3_qeHhv.js} +1 -1
- package/web/assets/{ganttDiagram-PKOTCBZU-B7B9nD6g.js → ganttDiagram-PKOTCBZU-DDw97tpG.js} +1 -1
- package/web/assets/{gitGraphDiagram-DS77QQ5N-VwKL0Ozk.js → gitGraphDiagram-DS77QQ5N-DXUcbzn4.js} +1 -1
- package/web/assets/{gitGraphDiagram-WWUBYQGX-DMWMLL3G-BMs5FYkE.js → gitGraphDiagram-WWUBYQGX-DMWMLL3G-BrLu7NzO.js} +1 -1
- package/web/assets/{index-DFryMRAp.js → index-BUFumkqO.js} +4 -4
- package/web/assets/{index-xynt7zMk.js → index-C-4sKCSr.js} +1 -1
- package/web/assets/{index-DkjixD09.js → index-CODVWHV0.js} +1 -1
- package/web/assets/{index-Vtc_VHiK.js → index-CRlVl931.js} +1 -1
- package/web/assets/{index-D0FRqjBW.js → index-CrB9w7Gs.js} +1 -1
- package/web/assets/{infoDiagram-6WML65LV-CD6GNI7J.js → infoDiagram-6WML65LV-rLhQ8DQz.js} +1 -1
- package/web/assets/{infoDiagram-RXCK75RN-HANS5KVC-k8vzCiSp.js → infoDiagram-RXCK75RN-HANS5KVC-BhbqgWa_.js} +1 -1
- package/web/assets/{ishikawaDiagram-5VMMS53U-7GCIT7WU-Ckl5jIU6.js → ishikawaDiagram-5VMMS53U-7GCIT7WU-DR-PXM0c.js} +1 -1
- package/web/assets/{ishikawaDiagram-WSZJBQD7-CEdvuK4K.js → ishikawaDiagram-WSZJBQD7-Bf-J9Ov1.js} +1 -1
- package/web/assets/{journeyDiagram-EYS64GPL-OAPELBT7-DtCRso4h.js → journeyDiagram-EYS64GPL-OAPELBT7-jFQUZit6.js} +1 -1
- package/web/assets/{journeyDiagram-NVQOT4AX-CxPjI9L-.js → journeyDiagram-NVQOT4AX-CWed0L5n.js} +1 -1
- package/web/assets/{kanban-definition-27J2QSJJ-DnuNCFkl.js → kanban-definition-27J2QSJJ-DhTIozq4.js} +1 -1
- package/web/assets/{kanban-definition-3QL26DDD-I7RKWQQY-yNRn2nj0.js → kanban-definition-3QL26DDD-I7RKWQQY-MOg0W8Vc.js} +1 -1
- package/web/assets/{katex-N6JRN4PM-B9dEOiMG.js → katex-N6JRN4PM-DUl1EV3T.js} +1 -1
- package/web/assets/{main-CGE6fm01.js → main-D3HpSUyK.js} +9 -9
- package/web/assets/{mermaid-layout-elk.core-BUAJJUsd.js → mermaid-layout-elk.core-KBAfwQxu.js} +2 -2
- package/web/assets/{mermaid.core-BD32Za4p.js → mermaid.core-BVbO1Vp8.js} +4 -4
- package/web/assets/{mindmap-definition-FAOFIHXS-DX6VEGs_.js → mindmap-definition-FAOFIHXS-UC1xDIuF.js} +1 -1
- package/web/assets/{mindmap-definition-FBJOCRG2-KIYZG64Y-DYiBZnHG.js → mindmap-definition-FBJOCRG2-KIYZG64Y-DyTkl7Qq.js} +1 -1
- package/web/assets/{pegDiagram-VL7TDLO6-Big72xut.js → pegDiagram-VL7TDLO6-D3DtO4SS.js} +1 -1
- package/web/assets/{pegDiagram-XKGWAZYB-OIP57N6J-N0pgSR7W.js → pegDiagram-XKGWAZYB-OIP57N6J-D6RFGa8P.js} +1 -1
- package/web/assets/{pet-DopPVlAf.js → pet-BawFRWlx.js} +1 -1
- package/web/assets/{pieDiagram-7S7Q4E2Y-BLXLqOCg.js → pieDiagram-7S7Q4E2Y-Bggk64R7.js} +1 -1
- package/web/assets/{pieDiagram-E7YTZNPT-2UOTW327-BuB4rTS2.js → pieDiagram-E7YTZNPT-2UOTW327-DbtP5dKZ.js} +1 -1
- package/web/assets/{quadrantDiagram-AXDQQJYC-SN3ASJJK-4S-5LgOz.js → quadrantDiagram-AXDQQJYC-SN3ASJJK-CbdnLdcx.js} +1 -1
- package/web/assets/{quadrantDiagram-CIZ2JOQS-BUwizsLb.js → quadrantDiagram-CIZ2JOQS-D8oWqljf.js} +1 -1
- package/web/assets/{railroadDiagram-AXF67PYL-D3qxyYSE.js → railroadDiagram-AXF67PYL-DqYMsbyG.js} +1 -1
- package/web/assets/{railroadDiagram-O6MQD6OU-34742W6X-CzT_bN34.js → railroadDiagram-O6MQD6OU-34742W6X-BxDZ-lKK.js} +1 -1
- package/web/assets/{render-O7CIS3YK-DhYmSGoI.js → render-O7CIS3YK-C5zxvpoJ.js} +7 -7
- package/web/assets/{requirementDiagram-EFPCY7ZU-NGAFFSMB-iWwnW8VG.js → requirementDiagram-EFPCY7ZU-NGAFFSMB-vkMFulyy.js} +1 -1
- package/web/assets/{requirementDiagram-LRYGKXZP-Cf95T2or.js → requirementDiagram-LRYGKXZP-4uQ-OIOg.js} +1 -1
- package/web/assets/{rotate-ccw-natFwqj6.js → rotate-ccw-C3k3pTDh.js} +1 -1
- package/web/assets/{sankeyDiagram-P5KCCOFB-3D3M4XPB-CjA_LC6M.js → sankeyDiagram-P5KCCOFB-3D3M4XPB-Ct2_9lW6.js} +1 -1
- package/web/assets/{sankeyDiagram-W5VNT64P-CeGCHk7F.js → sankeyDiagram-W5VNT64P-CdtMmhMM.js} +1 -1
- package/web/assets/{sequenceDiagram-SI44F4Z6-BDsExCj2.js → sequenceDiagram-SI44F4Z6-BTa9vGYr.js} +1 -1
- package/web/assets/{sequenceDiagram-WJ2MYXX4-Q2IOPB4R-DbWhuP8u.js → sequenceDiagram-WJ2MYXX4-Q2IOPB4R-Du5hMpfL.js} +1 -1
- package/web/assets/{sizeCapture-X5ZJPWSS-PSGVOMYM-DB5JtURh.js → sizeCapture-X5ZJPWSS-PSGVOMYM-Dv_CbP4j.js} +1 -1
- package/web/assets/{sizeCapture-X5ZJPWSS-_5trx7u2.js → sizeCapture-X5ZJPWSS-xJHPAAZ7.js} +1 -1
- package/web/assets/{stateDiagram-HBIQ2CUA-4M2S6MAN-CBEhL8_A.js → stateDiagram-HBIQ2CUA-4M2S6MAN-BhhZM57P.js} +1 -1
- package/web/assets/{stateDiagram-OKZ733FA-BPHwMfDA.js → stateDiagram-OKZ733FA-CHCQNs83.js} +1 -1
- package/web/assets/stateDiagram-v2-4QOOHH4V-LBBLA2WV-CNwPFEas.js +1 -0
- package/web/assets/stateDiagram-v2-UEYNNEHI-uaaN79rE.js +1 -0
- package/web/assets/{swimlanes-SLNWSIFB-CDgj9OM9.js → swimlanes-SLNWSIFB-Bste-JE-.js} +2 -2
- package/web/assets/{swimlanes-XN3QIQJK-N6N2CCQ6-D3F0tmOR.js → swimlanes-XN3QIQJK-N6N2CCQ6-03elMVxe.js} +1 -1
- package/web/assets/swimlanesDiagram-ULZ7WXOC-CNw-u2S_.js +8 -0
- package/web/assets/swimlanesDiagram-VK2B7HYN-E6N4H5SY-jhFh1EB2.js +8 -0
- package/web/assets/{timeline-definition-24CTP7MA-KN7RSRVM-C0Ufqqk-.js → timeline-definition-24CTP7MA-KN7RSRVM-Cba_QLsv.js} +1 -1
- package/web/assets/{timeline-definition-Z64GVDOM-81O3UI2y.js → timeline-definition-Z64GVDOM-nDvkF_F-.js} +1 -1
- package/web/assets/{vennDiagram-4TSXK5OY-AKJ7LXAN-Cwa7TjWJ.js → vennDiagram-4TSXK5OY-AKJ7LXAN-Bjm0zDVN.js} +1 -1
- package/web/assets/{vennDiagram-T6HMQDX7-BfOTIcvk.js → vennDiagram-T6HMQDX7-KudBxp6e.js} +1 -1
- package/web/assets/{wardleyDiagram-T6FBY63Y-CYCyu4_S.js → wardleyDiagram-T6FBY63Y-d1R0A5mS.js} +1 -1
- package/web/assets/{wardleyDiagram-VM6X3IG4-3B6A3BN5-CHXrbpNv.js → wardleyDiagram-VM6X3IG4-3B6A3BN5-BOTe--eD.js} +1 -1
- package/web/assets/{xychartDiagram-ELKLHX3M-7mp6PB7p.js → xychartDiagram-ELKLHX3M-ChfX530c.js} +1 -1
- package/web/assets/{xychartDiagram-S5SC5T6Z-OBDNV6WG-Ch73fB_B.js → xychartDiagram-S5SC5T6Z-OBDNV6WG-DcSRUgks.js} +1 -1
- package/web/index.html +2 -2
- package/web/pet.html +2 -2
- package/web/assets/SettingsView-dExmRnIv.js +0 -7
- package/web/assets/channel-KoPlHvUR.js +0 -1
- package/web/assets/classDiagram-DTDB5LWJ-LWRDKZ5K-P8Aw4zHn.js +0 -1
- package/web/assets/classDiagram-JCYQIIEL-Dm2NSERp.js +0 -1
- package/web/assets/classDiagram-v2-JRS7N3AN-2BZHGRP2-P8Aw4zHn.js +0 -1
- package/web/assets/classDiagram-v2-OCEON4UE-Dm2NSERp.js +0 -1
- package/web/assets/stateDiagram-v2-4QOOHH4V-LBBLA2WV-lZeXiw9L.js +0 -1
- package/web/assets/stateDiagram-v2-UEYNNEHI-cH9YNExR.js +0 -1
- package/web/assets/swimlanesDiagram-ULZ7WXOC-C3faa0-8.js +0 -8
- package/web/assets/swimlanesDiagram-VK2B7HYN-E6N4H5SY-D5nVBF4q.js +0 -8
package/server.cjs
CHANGED
|
@@ -62413,6 +62413,16 @@ ${standaloneImages.map((img) => `- "${img.path}" (\u63CF\u8FF0: ${img.alt})`).jo
|
|
|
62413
62413
|
- role \u5B57\u6BB5\u662F Step 2 \u7684\u6587\u4EF6\u7C7B\u578B\uFF08original/practice\uFF09\uFF0C\u4F5C\u4E3A\u53C2\u8003\u4F46\u4E0D\u662F\u552F\u4E00\u4F9D\u636E
|
|
62414
62414
|
- \u5982\u679C\u4ED3\u5E93\u76EE\u5F55\u7ED3\u6784\u5DF2\u6E05\u6670\uFF08\u5982 lessons/N-Topic/\uFF09\uFF0C\u4FDD\u7559\u539F\u6709\u7AE0\u8282\uFF0C\u4E0D\u8FC7\u5EA6\u91CD\u7EC4
|
|
62415
62415
|
- \u6BCF\u4E2A section \u7ED9\u4E2D\u6587\u6807\u9898
|
|
62416
|
+
- **\u7AE0\u8282\u6807\u9898\u5FE0\u5B9E\u539F\u5219(2026-08-23)**:\u6587\u4EF6\u5927\u7EB2\u91CC\u7684\u6807\u9898(\u4E66\u9875\u7AE0\u540D/\u76EE\u5F55\u540D/\u6587\u4EF6 H1)\u662F\u6743\u5A01\u2014\u2014lesson \u6807\u9898\u6CBF\u7528\u5B83\u4EEC
|
|
62417
|
+
(\u53EF\u53BB\u6389\u5197\u4F59\u524D\u7F00),\u4E0D\u8981\u6539\u5199\u6210\u522B\u7684\u4E3B\u9898;\u539F\u4E66/\u4ED3\u5E93\u81EA\u5E26\u7F16\u53F7(Chapter N/CHAPTER XX/\u7B2CN\u56DE)\u5219\u4FDD\u7559\u539F\u7F16\u53F7\u3002
|
|
62418
|
+
\u539F\u4E66\u6CA1\u6709\u7F16\u53F7\u7AE0\u8282\u4F53\u7CFB\u65F6,**\u4E0D\u5F97\u53D1\u660E"\u7B2C N \u7AE0"\u5F0F\u7F16\u53F7**,section \u6309\u5185\u5BB9\u4E3B\u9898\u547D\u540D(\u5982"\u9CB8\u7C7B\u5B66\u4E0E\u6355\u9CB8\u53F2",
|
|
62419
|
+
\u4E0D\u662F"\u7B2C 3 \u7AE0 \u9CB8\u7C7B")\u2014\u2014\u5B66\u4E60\u8005\u8981\u9760\u6807\u9898\u56DE\u5230\u539F\u4E66\u5BF9\u5E94\u4F4D\u7F6E,\u7F16\u9020\u7684\u7F16\u53F7\u4F1A\u8BEF\u5BFC
|
|
62420
|
+
- **\u7F51\u9875\u6765\u6E90\u7684\u6B63\u6587\u8FB9\u754C(2026-08-23)**:\u7F51\u9875\u62BD\u53D6\u7684\u6587\u4EF6(url/arXiv/\u6587\u7AE0\u7C7B)\u5C3E\u90E8\u5E38\u6B8B\u7559\u63A8\u5E7F\u6BB5\u3001\u5173\u6CE8\u5F15\u5BFC\u3001
|
|
62421
|
+
\u76F8\u5173\u9605\u8BFB\u7B49\u975E\u6B63\u6587\u5185\u5BB9\u3002\u5224\u65AD"\u5C3E\u90E8\u4E00\u6BB5\u662F\u5426\u5C5E\u4E8E\u6B63\u6587"\u662F\u8BED\u4E49\u5224\u65AD,\u4EA4\u7ED9\u4F60:\u660E\u663E\u662F\u4F5C\u8005\u884C\u6587\u4E00\u90E8\u5206\u7684\u4FDD\u7559;
|
|
62422
|
+
\u660E\u663E\u662F\u6A21\u677F\u6216\u4E0E\u4E3B\u9898\u65E0\u5173\u7684\u63A8\u5E7F\u5C0F\u6BB5,\u4E0D\u8981\u4E3A\u5B83\u5355\u72EC\u5EFA lesson,anchor \u4E5F\u4E0D\u8981\u622A\u5230\u5B83(\u6B63\u6587\u5728\u54EA\u7ED3\u675F\u4F60\u8BF4\u4E86\u7B97)
|
|
62423
|
+
- **\u4E66\u7C4D\u7684\u524D\u7F6E/\u5916\u56F4\u5C0F\u9875(2026-08-23)**:\u7535\u5B50\u4E66\u6765\u6E90\u53EF\u80FD\u6709\u51FA\u7248\u793E\u5BA3\u4F20\u9875\u3001\u4F5C\u8005/\u8BD1\u8005\u7B80\u4ECB\u3001Digital Lab \u4E4B\u7C7B
|
|
62424
|
+
\u7684\u51FA\u7248\u65B9\u4ECB\u7ECD\u9875\u2014\u2014\u6807\u9898\u53EB"\u672A\u547D\u540D\u7AE0\u8282"\u7684\u6587\u4EF6\u662F\u89E3\u6790\u5C42\u8BDA\u5B9E\u6807\u6CE8"\u65E0\u6807\u9898"(\u4E0D\u662F\u539F\u4E66\u6807\u9898),\u6309\u5185\u5BB9\u4E3B\u9898\u547D\u540D\u3002
|
|
62425
|
+
\u660E\u663E\u4E0E\u4E66\u7684\u5185\u5BB9\u65E0\u5173\u7684\u5916\u56F4\u5C0F\u9875(\u51FA\u7248\u65B9\u4ECB\u7ECD/\u5BA3\u4F20\u8BED),\u4E0D\u8981\u4E3A\u5B83\u5355\u72EC\u5EFA lesson,\u5E76\u5165\u9996\u7AE0\u6216\u5FFD\u7565
|
|
62416
62426
|
- \u4EE3\u7801\u6587\u4EF6(.py/.js/.go \u7B49): \u6559\u7A0B\u578B\u4EE3\u7801(\u5E26\u8BE6\u7EC6\u6CE8\u91CA/docstring) \u2192 study world; \u5DE5\u5177/\u811A\u672C/\u7EC3\u4E60 \u2192 practice world
|
|
62417
62427
|
- \u4EE3\u7801\u6587\u4EF6\u901A\u5E38\u65E0 H2/H3 \u6807\u9898\uFF0CtotalChars \u5C31\u662F\u6587\u4EF6\u5927\u5C0F\uFF0C\u4E0D\u62C6\u5206\uFF0C\u6574\u4F53\u4E00\u4E2A lesson
|
|
62418
62428
|
|
|
@@ -244640,6 +244650,33 @@ var pptx_parser_exports = {};
|
|
|
244640
244650
|
__export(pptx_parser_exports, {
|
|
244641
244651
|
parsePptx: () => parsePptx
|
|
244642
244652
|
});
|
|
244653
|
+
function tableToMarkdown(node) {
|
|
244654
|
+
const rows = /* @__PURE__ */ new Map();
|
|
244655
|
+
const walk = (n) => {
|
|
244656
|
+
if (n?.type === "cell") {
|
|
244657
|
+
const r = Number(n.metadata?.row ?? 0);
|
|
244658
|
+
const c = Number(n.metadata?.col ?? 0);
|
|
244659
|
+
const text3 = String(n.text ?? "").trim().replace(/\|/g, "\\|").replace(/\s+/g, " ");
|
|
244660
|
+
if (!rows.has(r))
|
|
244661
|
+
rows.set(r, []);
|
|
244662
|
+
rows.get(r).push({ col: c, text: text3 });
|
|
244663
|
+
return;
|
|
244664
|
+
}
|
|
244665
|
+
for (const ch2 of n?.children ?? [])
|
|
244666
|
+
walk(ch2);
|
|
244667
|
+
};
|
|
244668
|
+
walk(node);
|
|
244669
|
+
if (rows.size === 0)
|
|
244670
|
+
return "";
|
|
244671
|
+
if ([...rows.values()].every((cells) => cells.every((c) => !c.text)))
|
|
244672
|
+
return "";
|
|
244673
|
+
const sorted = [...rows.entries()].sort((a, b) => a[0] - b[0]).map(([, cells]) => cells.sort((a, b) => a.col - b.col));
|
|
244674
|
+
const width = Math.max(...sorted.map((cs) => cs.length));
|
|
244675
|
+
const line = (texts) => `| ${Array.from({ length: width }, (_, i) => texts[i] ?? "").join(" | ")} |`;
|
|
244676
|
+
const header = line(sorted[0].map((c) => c.text));
|
|
244677
|
+
const sep3 = `| ${Array.from({ length: width }, () => "---").join(" | ")} |`;
|
|
244678
|
+
return [header, sep3, ...sorted.slice(1).map((cs) => line(cs.map((c) => c.text)))].join("\n");
|
|
244679
|
+
}
|
|
244643
244680
|
async function parsePptx(buf) {
|
|
244644
244681
|
const ast = await OfficeParser.parseOffice(buf, {
|
|
244645
244682
|
extractAttachments: true,
|
|
@@ -244670,6 +244707,10 @@ async function parsePptx(buf) {
|
|
|
244670
244707
|
title = child.text;
|
|
244671
244708
|
else
|
|
244672
244709
|
bodyTexts.push(child.text);
|
|
244710
|
+
} else if (child.type === "table") {
|
|
244711
|
+
const md = tableToMarkdown(child);
|
|
244712
|
+
if (md)
|
|
244713
|
+
bodyTexts.push(md);
|
|
244673
244714
|
} else if (child.type === "image") {
|
|
244674
244715
|
const name18 = child.metadata?.attachmentName;
|
|
244675
244716
|
if (name18 && attMap.has(name18) && !seenImg.has(name18)) {
|
|
@@ -485219,8 +485260,14 @@ var require_pdf_parse2 = __commonJS({
|
|
|
485219
485260
|
// src/main/lib/pdf-text.ts
|
|
485220
485261
|
var pdf_text_exports = {};
|
|
485221
485262
|
__export(pdf_text_exports, {
|
|
485263
|
+
normalizeRadicals: () => normalizeRadicals,
|
|
485222
485264
|
parsePdfText: () => parsePdfText
|
|
485223
485265
|
});
|
|
485266
|
+
function normalizeRadicals(md) {
|
|
485267
|
+
if (!md)
|
|
485268
|
+
return md;
|
|
485269
|
+
return /[\u2F00-\u2FDF]/.test(md) ? md.replace(/[\u2F00-\u2FDF]/g, (c) => c.normalize("NFKC")) : md;
|
|
485270
|
+
}
|
|
485224
485271
|
async function parsePdfText(buf) {
|
|
485225
485272
|
if (!process.env.LOOKATSTUDY_NO_PDF_INSPECTOR) {
|
|
485226
485273
|
try {
|
|
@@ -485228,13 +485275,13 @@ async function parsePdfText(buf) {
|
|
|
485228
485275
|
const result = await pi.processPdfAsync(buf);
|
|
485229
485276
|
const md = (result?.markdown ?? "").trim();
|
|
485230
485277
|
if (md)
|
|
485231
|
-
return md;
|
|
485278
|
+
return normalizeRadicals(md);
|
|
485232
485279
|
} catch {
|
|
485233
485280
|
}
|
|
485234
485281
|
}
|
|
485235
485282
|
try {
|
|
485236
485283
|
const pdfParse = require_pdf_parse2();
|
|
485237
|
-
return (await pdfParse(buf)).text.trim();
|
|
485284
|
+
return normalizeRadicals((await pdfParse(buf)).text.trim());
|
|
485238
485285
|
} catch {
|
|
485239
485286
|
return "";
|
|
485240
485287
|
}
|
|
@@ -486386,7 +486433,7 @@ var init_Tokenizer = __esm({
|
|
|
486386
486433
|
// `</xmp`
|
|
486387
486434
|
};
|
|
486388
486435
|
Tokenizer = class {
|
|
486389
|
-
constructor({ xmlMode = false, decodeEntities = true }, cbs) {
|
|
486436
|
+
constructor({ xmlMode = false, decodeEntities: decodeEntities2 = true }, cbs) {
|
|
486390
486437
|
this.cbs = cbs;
|
|
486391
486438
|
this.state = State.Text;
|
|
486392
486439
|
this.buffer = "";
|
|
@@ -486400,7 +486447,7 @@ var init_Tokenizer = __esm({
|
|
|
486400
486447
|
this.currentSequence = void 0;
|
|
486401
486448
|
this.sequenceIndex = 0;
|
|
486402
486449
|
this.xmlMode = xmlMode;
|
|
486403
|
-
this.decodeEntities =
|
|
486450
|
+
this.decodeEntities = decodeEntities2;
|
|
486404
486451
|
this.entityDecoder = new EntityDecoder(xmlMode ? xmlDecodeTree : htmlDecodeTree, (cp, consumed) => this.emitCodePoint(cp, consumed));
|
|
486405
486452
|
}
|
|
486406
486453
|
reset() {
|
|
@@ -518749,7 +518796,28 @@ function extractArticle(html, baseUrl = "") {
|
|
|
518749
518796
|
const md = alreadyHasTitleH1 ? body : `# ${title || "\u65E0\u6807\u9898\u6587\u7AE0"}
|
|
518750
518797
|
|
|
518751
518798
|
${body}`;
|
|
518752
|
-
return { title: title || "\u65E0\u6807\u9898\u6587\u7AE0", markdown: md };
|
|
518799
|
+
return { title: title || "\u65E0\u6807\u9898\u6587\u7AE0", markdown: stripTailNavigation(md) };
|
|
518800
|
+
}
|
|
518801
|
+
function stripTailNavigation(md) {
|
|
518802
|
+
if (!md)
|
|
518803
|
+
return md;
|
|
518804
|
+
for (const suffix of INLINE_NAV_SUFFIXES)
|
|
518805
|
+
md = md.split(suffix).join("");
|
|
518806
|
+
const lines = md.split("\n");
|
|
518807
|
+
let end = lines.length;
|
|
518808
|
+
for (let i = lines.length - 1; i >= Math.max(0, lines.length - 25); i--) {
|
|
518809
|
+
const ln = lines[i].trim();
|
|
518810
|
+
if (!ln)
|
|
518811
|
+
continue;
|
|
518812
|
+
const bare = ln.replace(/^#{1,6}\s*/, "").replace(/^[>\-*]\s*/, "");
|
|
518813
|
+
const isNav = NAV_TAIL_PATTERNS.some((re2) => re2.test(bare) || re2.test(ln));
|
|
518814
|
+
const isBareImage = /^!\[[^\]]*\]\([^)]*\)$/.test(ln) || /^\S+\.(jpeg|jpg|png|gif|webp)\)?$/i.test(ln);
|
|
518815
|
+
if (isNav || isBareImage)
|
|
518816
|
+
continue;
|
|
518817
|
+
end = i + 1;
|
|
518818
|
+
break;
|
|
518819
|
+
}
|
|
518820
|
+
return lines.slice(0, end).join("\n").trimEnd();
|
|
518753
518821
|
}
|
|
518754
518822
|
function htmlToMarkdown(html, opts = {}) {
|
|
518755
518823
|
let { document: document2 } = parseHTML(html);
|
|
@@ -518779,7 +518847,7 @@ function htmlToMarkdown(html, opts = {}) {
|
|
|
518779
518847
|
return "";
|
|
518780
518848
|
return turndown.turndown(body).trim();
|
|
518781
518849
|
}
|
|
518782
|
-
var import_readability, import_turndown, turndown;
|
|
518850
|
+
var import_readability, import_turndown, turndown, NAV_TAIL_PATTERNS, INLINE_NAV_SUFFIXES;
|
|
518783
518851
|
var init_html_article = __esm({
|
|
518784
518852
|
"src/main/services/pure/html-article.ts"() {
|
|
518785
518853
|
"use strict";
|
|
@@ -518791,6 +518859,21 @@ var init_html_article = __esm({
|
|
|
518791
518859
|
codeBlockStyle: "fenced",
|
|
518792
518860
|
bulletListMarker: "-"
|
|
518793
518861
|
});
|
|
518862
|
+
NAV_TAIL_PATTERNS = [
|
|
518863
|
+
/返回\S{0,6}[,,]?\s*查看更多/,
|
|
518864
|
+
// 搜狐模板
|
|
518865
|
+
/点击进入\S{0,8}首页/,
|
|
518866
|
+
// 搜狐模板
|
|
518867
|
+
/^热门文章$/,
|
|
518868
|
+
// 阿里云侧栏
|
|
518869
|
+
/^最新文章$/,
|
|
518870
|
+
// 阿里云侧栏
|
|
518871
|
+
/^目录\s*$/,
|
|
518872
|
+
// 阿里云侧栏(尾部窗口内)
|
|
518873
|
+
/^END\b.*版权/
|
|
518874
|
+
// 公众号转载页模板
|
|
518875
|
+
];
|
|
518876
|
+
INLINE_NAV_SUFFIXES = ["\u76EE\u5F55 \u70ED\u95E8\u6587\u7AE0 \u6700\u65B0\u6587\u7AE0"];
|
|
518794
518877
|
}
|
|
518795
518878
|
});
|
|
518796
518879
|
|
|
@@ -518798,7 +518881,9 @@ var init_html_article = __esm({
|
|
|
518798
518881
|
var epub_parser_exports = {};
|
|
518799
518882
|
__export(epub_parser_exports, {
|
|
518800
518883
|
parseEpub: () => parseEpub,
|
|
518801
|
-
parseEpubFlat: () => parseEpubFlat
|
|
518884
|
+
parseEpubFlat: () => parseEpubFlat,
|
|
518885
|
+
sanitizeEpubBody: () => sanitizeEpubBody,
|
|
518886
|
+
splitChaptersInBody: () => splitChaptersInBody
|
|
518802
518887
|
});
|
|
518803
518888
|
function tags(xml, tagName19) {
|
|
518804
518889
|
const out = [];
|
|
@@ -518859,6 +518944,98 @@ function parseTocLabels(tocXml, isNcx) {
|
|
|
518859
518944
|
function sanitizeFileName(title) {
|
|
518860
518945
|
return (title || "chapter").replace(/[\\/:*?"<>|#\s]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 50) || "chapter";
|
|
518861
518946
|
}
|
|
518947
|
+
function splitChaptersInBody(body, opts) {
|
|
518948
|
+
const lines = body.split("\n");
|
|
518949
|
+
const marks = [];
|
|
518950
|
+
for (let i = 0; i < lines.length; i++) {
|
|
518951
|
+
const ln = lines[i].trimEnd();
|
|
518952
|
+
if (!ln || ln.length > 60)
|
|
518953
|
+
continue;
|
|
518954
|
+
const strip = (s) => s.replace(/^#{1,3}\s*/, "");
|
|
518955
|
+
let m = ln.match(CH_HEADING);
|
|
518956
|
+
if (m) {
|
|
518957
|
+
marks.push({ line: i, title: strip(ln), kind: "ch", seq: 0 });
|
|
518958
|
+
continue;
|
|
518959
|
+
}
|
|
518960
|
+
m = ln.match(LETTER_HEADING);
|
|
518961
|
+
if (m) {
|
|
518962
|
+
marks.push({ line: i, title: strip(ln), kind: "letter", seq: 0 });
|
|
518963
|
+
continue;
|
|
518964
|
+
}
|
|
518965
|
+
m = ln.match(ROMAN_HEADING);
|
|
518966
|
+
if (m && (ln.startsWith("#") || /[—[]/.test(ln))) {
|
|
518967
|
+
marks.push({ line: i, title: strip(ln), kind: "roman", seq: romanValue(m[1]) });
|
|
518968
|
+
continue;
|
|
518969
|
+
}
|
|
518970
|
+
m = ln.match(NUM_HEADING);
|
|
518971
|
+
if (m && (ln.startsWith("#") || /[—[]/.test(ln))) {
|
|
518972
|
+
marks.push({ line: i, title: strip(ln), kind: "num", seq: parseInt(m[1], 10) });
|
|
518973
|
+
continue;
|
|
518974
|
+
}
|
|
518975
|
+
}
|
|
518976
|
+
const minHigh = opts?.minHighConf ?? 2;
|
|
518977
|
+
const highConf = marks.filter((mk) => mk.kind === "ch" || mk.kind === "letter");
|
|
518978
|
+
let splitMarks;
|
|
518979
|
+
if (highConf.length >= minHigh) {
|
|
518980
|
+
splitMarks = highConf;
|
|
518981
|
+
} else {
|
|
518982
|
+
splitMarks = [];
|
|
518983
|
+
for (const kind of ["roman", "num"]) {
|
|
518984
|
+
const seq = marks.filter((mk) => mk.kind === kind);
|
|
518985
|
+
const chain = [];
|
|
518986
|
+
let expect = 0;
|
|
518987
|
+
for (const mk of seq) {
|
|
518988
|
+
if (expect === 0) {
|
|
518989
|
+
if (mk.seq === 1 || mk.seq === 2) {
|
|
518990
|
+
chain.push(mk);
|
|
518991
|
+
expect = mk.seq + 1;
|
|
518992
|
+
}
|
|
518993
|
+
} else if (mk.seq === expect) {
|
|
518994
|
+
chain.push(mk);
|
|
518995
|
+
expect++;
|
|
518996
|
+
}
|
|
518997
|
+
}
|
|
518998
|
+
if (chain.length >= 3)
|
|
518999
|
+
splitMarks.push(...chain);
|
|
519000
|
+
}
|
|
519001
|
+
if (splitMarks.length < 3)
|
|
519002
|
+
return null;
|
|
519003
|
+
}
|
|
519004
|
+
if (splitMarks.length < 1)
|
|
519005
|
+
return null;
|
|
519006
|
+
const out = [];
|
|
519007
|
+
const preamble = lines.slice(0, splitMarks[0].line).join("\n").trim();
|
|
519008
|
+
for (let k = 0; k < splitMarks.length; k++) {
|
|
519009
|
+
const start = splitMarks[k].line;
|
|
519010
|
+
const end = k + 1 < splitMarks.length ? splitMarks[k + 1].line : lines.length;
|
|
519011
|
+
let content = lines.slice(start + 1, end).join("\n").trim();
|
|
519012
|
+
if (k === 0 && preamble && preamble.length < 800) {
|
|
519013
|
+
content = `${preamble}
|
|
519014
|
+
|
|
519015
|
+
${content}`.trim();
|
|
519016
|
+
}
|
|
519017
|
+
out.push({ title: splitMarks[k].title, content });
|
|
519018
|
+
}
|
|
519019
|
+
if (preamble && preamble.length >= 800) {
|
|
519020
|
+
out.unshift({ title: "\u5F15\u8A00", content: preamble });
|
|
519021
|
+
}
|
|
519022
|
+
return out.filter((c) => c.content.replace(/\s/g, "").length > 0);
|
|
519023
|
+
}
|
|
519024
|
+
function sanitizeEpubBody(body) {
|
|
519025
|
+
let md = body;
|
|
519026
|
+
const lines0 = md.split("\n");
|
|
519027
|
+
for (let i = 0; i < lines0.length; i++) {
|
|
519028
|
+
const ln = lines0[i].trim();
|
|
519029
|
+
if (ln.length <= 100 && (/(?:THE\s+)?FULL PROJECT GUTENBERG/i.test(ln) || /END OF THE PROJECT GUTENBERG/i.test(ln) || ln === "START: FULL LICENSE" || ln === "START: THE FULL LICENSE")) {
|
|
519030
|
+
md = lines0.slice(0, i).join("\n");
|
|
519031
|
+
break;
|
|
519032
|
+
}
|
|
519033
|
+
}
|
|
519034
|
+
md = md.replace(/^#{1,3}\s*(?:The Project Gutenberg eBook[^*\n]*|Project Gutenberg[^*\n]*)\n[\s\S]*?\n(?:\n|$)/im, "");
|
|
519035
|
+
md = md.replace(/^#{1,3}[ \t]*$/gm, "");
|
|
519036
|
+
md = md.replace(/\\?\[?\s*_?Copyright 1[6-9]\d\d[^_\n]*_?\s*\\?]?/g, "");
|
|
519037
|
+
return md.trim();
|
|
519038
|
+
}
|
|
518862
519039
|
async function parseEpub(buf) {
|
|
518863
519040
|
const entries3 = unzipSync(buf);
|
|
518864
519041
|
const read2 = (p) => {
|
|
@@ -518891,6 +519068,7 @@ async function parseEpub(buf) {
|
|
|
518891
519068
|
if (tocLabels.size === 0 && spineTocId && manifest.has(spineTocId)) {
|
|
518892
519069
|
tocLabels = parseTocLabels(read2(resolveZipPath(opfPath, manifest.get(spineTocId).href)), true);
|
|
518893
519070
|
}
|
|
519071
|
+
const UNTITLED_MARK = "\u672A\u547D\u540D\u7AE0\u8282";
|
|
518894
519072
|
const opfDirKey = (href) => decodeURIComponent(href.split("#")[0] ?? href).replace(/\\/g, "/");
|
|
518895
519073
|
const chapters = [];
|
|
518896
519074
|
let n = 0;
|
|
@@ -518911,17 +519089,89 @@ async function parseEpub(buf) {
|
|
|
518911
519089
|
if (!md || md.replace(/[#\s>*-]/g, "").length < 8)
|
|
518912
519090
|
continue;
|
|
518913
519091
|
n++;
|
|
518914
|
-
const
|
|
519092
|
+
const body0 = md.startsWith("# ") && md.includes("\n") ? md.slice(md.indexOf("\n") + 1).trim() : md;
|
|
518915
519093
|
const firstHeading = md.startsWith("# ") ? md.split("\n")[0].slice(2).trim() : "";
|
|
518916
|
-
const
|
|
519094
|
+
const fileTitle = tocLabels.get(opfDirKey(item.href)) || firstHeading || UNTITLED_MARK;
|
|
519095
|
+
if (/^(contents|table of contents)$/i.test(fileTitle) && body0.replace(/\s/g, "").length < 4e3)
|
|
519096
|
+
continue;
|
|
519097
|
+
if (body0.replace(/\s/g, "").length < 1500 && /project gutenberg|copyright/i.test(body0))
|
|
519098
|
+
continue;
|
|
519099
|
+
if (/^(版权信息|版权|版权页|著作权|版權)/.test(fileTitle))
|
|
519100
|
+
continue;
|
|
519101
|
+
const colophonFields = (body0.match(/^(书名|作者|译者|编者|丛书|出版社|出版时间|出版年|ISBN|版次|定价|装帧|字数|品牌|出品方)[::]/gm) ?? []).length;
|
|
519102
|
+
if (colophonFields >= 3 && body0.replace(/\s/g, "").length < 2500)
|
|
519103
|
+
continue;
|
|
519104
|
+
if (/^目\s*录$/.test(fileTitle)) {
|
|
519105
|
+
const lines = body0.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
519106
|
+
if (lines.length >= 3 && lines.filter((l) => l.includes("](")).length / lines.length >= 0.6)
|
|
519107
|
+
continue;
|
|
519108
|
+
}
|
|
519109
|
+
const body = sanitizeEpubBody(body0);
|
|
519110
|
+
if (body.replace(/\s/g, "").length < 8)
|
|
519111
|
+
continue;
|
|
519112
|
+
const titleIsLicense = /FULL PROJECT GUTENBERG|LICENSE/i.test(fileTitle);
|
|
519113
|
+
const split = splitChaptersInBody(body, titleIsLicense ? { minHighConf: 1 } : void 0);
|
|
519114
|
+
if (split && split.length >= (titleIsLicense ? 1 : 2)) {
|
|
519115
|
+
for (const seg of split) {
|
|
519116
|
+
chapters.push({
|
|
519117
|
+
path: `chapters/${String(n).padStart(2, "0")}-${sanitizeFileName(seg.title)}.md`,
|
|
519118
|
+
title: seg.title,
|
|
519119
|
+
markdown: `# ${seg.title}
|
|
519120
|
+
|
|
519121
|
+
${seg.content}`
|
|
519122
|
+
});
|
|
519123
|
+
n++;
|
|
519124
|
+
}
|
|
519125
|
+
n--;
|
|
519126
|
+
continue;
|
|
519127
|
+
}
|
|
519128
|
+
if (titleIsLicense) {
|
|
519129
|
+
if (body.replace(/\s/g, "").length > 2e3) {
|
|
519130
|
+
chapters.push({
|
|
519131
|
+
path: `chapters/${String(n).padStart(2, "0")}-appendix.md`,
|
|
519132
|
+
title: "\u9644\u5F55",
|
|
519133
|
+
markdown: `# \u9644\u5F55
|
|
519134
|
+
|
|
519135
|
+
${body}`
|
|
519136
|
+
});
|
|
519137
|
+
}
|
|
519138
|
+
continue;
|
|
519139
|
+
}
|
|
518917
519140
|
chapters.push({
|
|
518918
|
-
path: `chapters/${String(n).padStart(2, "0")}-${sanitizeFileName(
|
|
518919
|
-
title,
|
|
518920
|
-
markdown: `# ${
|
|
519141
|
+
path: `chapters/${String(n).padStart(2, "0")}-${sanitizeFileName(fileTitle)}.md`,
|
|
519142
|
+
title: fileTitle,
|
|
519143
|
+
markdown: `# ${fileTitle}
|
|
518921
519144
|
|
|
518922
519145
|
${body}`
|
|
518923
519146
|
});
|
|
518924
519147
|
}
|
|
519148
|
+
const absorbed = /* @__PURE__ */ new Set();
|
|
519149
|
+
for (let i = 0; i + 1 < chapters.length; i++) {
|
|
519150
|
+
const stub = chapters[i];
|
|
519151
|
+
const next = chapters[i + 1];
|
|
519152
|
+
if (absorbed.has(stub.path))
|
|
519153
|
+
continue;
|
|
519154
|
+
const stubBody = stub.markdown.includes("\n") ? stub.markdown.slice(stub.markdown.indexOf("\n") + 1).trim() : "";
|
|
519155
|
+
if (stub.title === UNTITLED_MARK || stub.title === "\u9644\u5F55")
|
|
519156
|
+
continue;
|
|
519157
|
+
if (stubBody.replace(/\s/g, "").length > 300)
|
|
519158
|
+
continue;
|
|
519159
|
+
if (next.title !== UNTITLED_MARK)
|
|
519160
|
+
continue;
|
|
519161
|
+
const nextBody = next.markdown.includes("\n") ? next.markdown.slice(next.markdown.indexOf("\n") + 1).trim() : next.markdown;
|
|
519162
|
+
chapters[i] = {
|
|
519163
|
+
path: stub.path,
|
|
519164
|
+
title: stub.title,
|
|
519165
|
+
markdown: `# ${stub.title}
|
|
519166
|
+
|
|
519167
|
+
${stubBody}
|
|
519168
|
+
|
|
519169
|
+
${nextBody}`
|
|
519170
|
+
};
|
|
519171
|
+
absorbed.add(stub.path);
|
|
519172
|
+
chapters.splice(i + 1, 1);
|
|
519173
|
+
i--;
|
|
519174
|
+
}
|
|
518925
519175
|
if (chapters.length === 0)
|
|
518926
519176
|
throw new Error("epub \u91CC\u6CA1\u6709\u53EF\u8BC6\u522B\u7684\u7AE0\u8282\u6587\u672C");
|
|
518927
519177
|
return { title: bookTitle, chapters };
|
|
@@ -518930,13 +519180,27 @@ async function parseEpubFlat(buf) {
|
|
|
518930
519180
|
const book = await parseEpub(buf);
|
|
518931
519181
|
return book.chapters.map((c) => c.markdown.replace(/^# /gm, "## ")).join("\n\n");
|
|
518932
519182
|
}
|
|
518933
|
-
var decoder;
|
|
519183
|
+
var decoder, CH_HEADING, LETTER_HEADING, ROMAN_HEADING, NUM_HEADING, romanValue;
|
|
518934
519184
|
var init_epub_parser = __esm({
|
|
518935
519185
|
"src/main/lib/epub-parser.ts"() {
|
|
518936
519186
|
"use strict";
|
|
518937
519187
|
init_esm2();
|
|
518938
519188
|
init_html_article();
|
|
518939
519189
|
decoder = new TextDecoder("utf-8");
|
|
519190
|
+
CH_HEADING = /^(?:#{1,3}\s*)?(?:CHAPTER|Chapter|chap\.)\s+[IVXLC0-9]{1,7}\b[.:)]?\s*(.*)$/;
|
|
519191
|
+
LETTER_HEADING = /^(?:#{1,3}\s*)?(?:Letter|LETTER)\s+\d{1,3}\b[.:)]?\s*(.*)$/;
|
|
519192
|
+
ROMAN_HEADING = /^(?:#{1,3}\s*)?(?:[—[]\s*)?([IVXLC]{1,7})\s*[—\]]?\.?\s*$/;
|
|
519193
|
+
NUM_HEADING = /^(?:#{1,3}\s*)?[—[]?\s*(\d{1,3})\s*[—\]]?\.?\s*$/;
|
|
519194
|
+
romanValue = (s) => {
|
|
519195
|
+
const vals = { I: 1, V: 5, X: 10, L: 50, C: 100 };
|
|
519196
|
+
let v = 0;
|
|
519197
|
+
for (let i = 0; i < s.length; i++) {
|
|
519198
|
+
const cur = vals[s[i]] ?? 0;
|
|
519199
|
+
const next = vals[s[i + 1]] ?? 0;
|
|
519200
|
+
v += cur < next ? -cur : cur;
|
|
519201
|
+
}
|
|
519202
|
+
return v;
|
|
519203
|
+
};
|
|
518940
519204
|
}
|
|
518941
519205
|
});
|
|
518942
519206
|
|
|
@@ -519488,11 +519752,32 @@ var init_bilibili_wbi = __esm({
|
|
|
519488
519752
|
});
|
|
519489
519753
|
|
|
519490
519754
|
// src/main/services/pure/subtitle-parse.ts
|
|
519755
|
+
function decodeEntities(s) {
|
|
519756
|
+
return s.replace(/&([a-z]+);/gi, (m, name18) => ENTITIES[name18.toLowerCase()] ?? m).replace(/&#(\d+);/g, (m, d) => {
|
|
519757
|
+
try {
|
|
519758
|
+
return String.fromCodePoint(Number(d));
|
|
519759
|
+
} catch {
|
|
519760
|
+
return m;
|
|
519761
|
+
}
|
|
519762
|
+
});
|
|
519763
|
+
}
|
|
519764
|
+
function cjkJoin(parts) {
|
|
519765
|
+
let s = "";
|
|
519766
|
+
for (const p of parts) {
|
|
519767
|
+
if (!s) {
|
|
519768
|
+
s = p;
|
|
519769
|
+
continue;
|
|
519770
|
+
}
|
|
519771
|
+
const last = s[s.length - 1];
|
|
519772
|
+
s += CJKISH.test(last) || CJKISH.test(p[0]) ? p : ` ${p}`;
|
|
519773
|
+
}
|
|
519774
|
+
return s;
|
|
519775
|
+
}
|
|
519491
519776
|
function parseSubtitleToText(raw) {
|
|
519492
519777
|
const lines = raw.replace(/\r\n/g, "\n").split("\n");
|
|
519493
519778
|
const out = [];
|
|
519779
|
+
const recent = [];
|
|
519494
519780
|
let inNote = false;
|
|
519495
|
-
let prev = "";
|
|
519496
519781
|
for (const line of lines) {
|
|
519497
519782
|
const t = line.trim();
|
|
519498
519783
|
if (!t) {
|
|
@@ -519513,21 +519798,56 @@ function parseSubtitleToText(raw) {
|
|
|
519513
519798
|
continue;
|
|
519514
519799
|
if (/^(Kind:|Language:|Style:|Region:|NOTE)/i.test(t))
|
|
519515
519800
|
continue;
|
|
519516
|
-
|
|
519801
|
+
let text3 = t.replace(/<[^>]+>/g, "").trim();
|
|
519517
519802
|
if (!text3)
|
|
519518
519803
|
continue;
|
|
519519
|
-
if (text3
|
|
519804
|
+
if (AUTO_MARKERS.test(text3))
|
|
519805
|
+
continue;
|
|
519806
|
+
text3 = decodeEntities(text3);
|
|
519807
|
+
if (recent.includes(text3))
|
|
519520
519808
|
continue;
|
|
519521
|
-
|
|
519522
|
-
|
|
519809
|
+
recent.push(text3);
|
|
519810
|
+
if (recent.length > 2)
|
|
519811
|
+
recent.shift();
|
|
519812
|
+
const spoken = text3.replace(/^>{2,}\s*/, "").trim();
|
|
519813
|
+
if (spoken)
|
|
519814
|
+
out.push(spoken);
|
|
519815
|
+
}
|
|
519816
|
+
return cjkJoin(out).replace(/\s+/g, " ").trim();
|
|
519817
|
+
}
|
|
519818
|
+
function pickSubtitleFile(names) {
|
|
519819
|
+
const rank = (n) => {
|
|
519820
|
+
const m = n.toLowerCase().match(/^sub\.(.+)\.(vtt|srt)$/);
|
|
519821
|
+
if (!m)
|
|
519822
|
+
return 99;
|
|
519823
|
+
const lang = m[1];
|
|
519824
|
+
if (lang === "zh-hans" || lang === "zh-cn" || lang.startsWith("zh-hans") || lang.startsWith("zh-cn"))
|
|
519825
|
+
return 0;
|
|
519826
|
+
if (lang === "zh" || lang.startsWith("zh"))
|
|
519827
|
+
return 1;
|
|
519828
|
+
if (lang === "en" || lang.startsWith("en"))
|
|
519829
|
+
return 2;
|
|
519830
|
+
return 3;
|
|
519831
|
+
};
|
|
519832
|
+
let best = null;
|
|
519833
|
+
let bestRank = 99;
|
|
519834
|
+
for (const n of names) {
|
|
519835
|
+
const r = rank(n);
|
|
519836
|
+
if (r < bestRank) {
|
|
519837
|
+
best = n;
|
|
519838
|
+
bestRank = r;
|
|
519839
|
+
}
|
|
519523
519840
|
}
|
|
519524
|
-
return
|
|
519841
|
+
return bestRank <= 3 ? best : null;
|
|
519525
519842
|
}
|
|
519526
|
-
var CUE_TIMING;
|
|
519843
|
+
var CUE_TIMING, AUTO_MARKERS, ENTITIES, CJKISH;
|
|
519527
519844
|
var init_subtitle_parse = __esm({
|
|
519528
519845
|
"src/main/services/pure/subtitle-parse.ts"() {
|
|
519529
519846
|
"use strict";
|
|
519530
519847
|
CUE_TIMING = /^\d{1,2}:\d{2}(?::\d{2})?[.,]\d{3}\s*-->/;
|
|
519848
|
+
AUTO_MARKERS = /^\[(music|applause|laughter|laughs?|silence|inaudible|cheering|foreign|blank[_\s]?audio|music playing|noise)\]$/i;
|
|
519849
|
+
ENTITIES = { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'", nbsp: " " };
|
|
519850
|
+
CJKISH = /[\u3000-\u303f\u4e00-\u9fff\uff00-\uffef]/;
|
|
519531
519851
|
}
|
|
519532
519852
|
});
|
|
519533
519853
|
|
|
@@ -519669,7 +519989,7 @@ async function fetchViaYtDlp(url2, dataDir, onProgress, signal) {
|
|
|
519669
519989
|
"--no-warnings",
|
|
519670
519990
|
url2
|
|
519671
519991
|
], signal);
|
|
519672
|
-
const subFile = (0, import_node_fs6.readdirSync)(workDir)
|
|
519992
|
+
const subFile = pickSubtitleFile((0, import_node_fs6.readdirSync)(workDir));
|
|
519673
519993
|
if (subFile) {
|
|
519674
519994
|
const text3 = parseSubtitleToText((0, import_node_fs6.readFileSync)((0, import_node_path6.join)(workDir, subFile), "utf8"));
|
|
519675
519995
|
if (text3.length > 50) {
|
|
@@ -557899,7 +558219,7 @@ function loadSeedData() {
|
|
|
557899
558219
|
);
|
|
557900
558220
|
}
|
|
557901
558221
|
var SEED_DATA = loadSeedData();
|
|
557902
|
-
var SEED_VERSION =
|
|
558222
|
+
var SEED_VERSION = 14;
|
|
557903
558223
|
function ensureSeedCourse() {
|
|
557904
558224
|
const result = applySeedData(getDb(), SEED_DATA, SEED_VERSION);
|
|
557905
558225
|
if (!result.skipped)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r,j as h}from"./index-
|
|
1
|
+
import{r,j as h}from"./index-C-4sKCSr.js";import{c as T,u as L,P as D}from"./main-D3HpSUyK.js";/**
|
|
2
2
|
* @license lucide-react v0.468.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as s,j as t}from"./index-
|
|
1
|
+
import{r as s,j as t}from"./index-C-4sKCSr.js";import{c as y,u as v,b as k,L as j,F as N,M as w,G as C,T as M,d as _}from"./main-D3HpSUyK.js";/**
|
|
2
2
|
* @license lucide-react v0.468.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as u,j as t}from"./index-
|
|
1
|
+
import{r as u,j as t}from"./index-C-4sKCSr.js";import{c as C,U as I,u as y,a as L,d as S,X as N,g as M,T as E,C as R}from"./main-D3HpSUyK.js";/**
|
|
2
2
|
* @license lucide-react v0.468.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as o,
|
|
1
|
+
import{r as o,h as U,j as e,c as ie}from"./index-C-4sKCSr.js";import{c as te,u as ce,a as j,h as de,T as z,i as Y,L as V,j as oe,X as xe}from"./main-D3HpSUyK.js";import{R as G}from"./rotate-ccw-C3k3pTDh.js";import{A as q}from"./arrow-right-B0QrRNSR.js";/**
|
|
2
2
|
* @license lucide-react v0.468.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./index-
|
|
2
|
-
import{u as v,_ as d,B as _}from"./main-
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./index-CODVWHV0.js","./index-CU6ublfJ.js","./index-C-4sKCSr.js","./index-DjoBjasB.css","./index-H1bePBGl.js","./transform-CzGDKG_M.js","./min-tv6RD-6E.js","./ordinal-Cboi1Yqb.js","./init-Gi6I4Gst.js","./colors-Cc3OSVma.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{u as v,_ as d,B as _}from"./main-D3HpSUyK.js";import{r as o,j as a}from"./index-C-4sKCSr.js";import{C as w}from"./CanvasStage-u_7YeGk1.js";function b(c){const e=[];let t=null,n=0;for(const r of c.split(`
|
|
3
3
|
`)){const s=/^(\s*)(`{3,}|~{3,})/.exec(r);if(t==null){if(s){t=(s[2]??"")[0]??"`",n=(s[2]??"").length,e.push(`${s[1]??""}- 代码块`);continue}e.push(r)}else new RegExp(`^\\s*\\${t==="~"?"~":"`"}{${n},}\\s*$`).test(r)&&(t=null)}return e.join(`
|
|
4
|
-
`).replace(/!\[([^\]]*)\]\([^)]*\)/g,"$1").replace(/<!--[\s\S]*?-->/g,"")}function E(){if(typeof document>"u")return["#58cc02","#1cb0f6","#ffc800","#a67cd8","#ff7a00"];const c=getComputedStyle(document.documentElement),e=(t,n)=>{const r=c.getPropertyValue(t).trim();return r?`rgb(${r})`:n};return[e("--brand-rgb","#58cc02"),e("--accent-rgb","#1cb0f6"),e("--gold-rgb","#ffc800"),"#a67cd8",e("--warning-rgb","#ff7a00")]}function P({markdown:c}){const e=v(),t=o.useRef(null),n=o.useRef(null),[r,s]=o.useState(!1),i=b(c);return o.useEffect(()=>{let l=!1;return(async()=>{try{const[{Transformer:p},{Markmap:g}]=await Promise.all([d(()=>import("./index-
|
|
4
|
+
`).replace(/!\[([^\]]*)\]\([^)]*\)/g,"$1").replace(/<!--[\s\S]*?-->/g,"")}function E(){if(typeof document>"u")return["#58cc02","#1cb0f6","#ffc800","#a67cd8","#ff7a00"];const c=getComputedStyle(document.documentElement),e=(t,n)=>{const r=c.getPropertyValue(t).trim();return r?`rgb(${r})`:n};return[e("--brand-rgb","#58cc02"),e("--accent-rgb","#1cb0f6"),e("--gold-rgb","#ffc800"),"#a67cd8",e("--warning-rgb","#ff7a00")]}function P({markdown:c}){const e=v(),t=o.useRef(null),n=o.useRef(null),[r,s]=o.useState(!1),i=b(c);return o.useEffect(()=>{let l=!1;return(async()=>{try{const[{Transformer:p},{Markmap:g}]=await Promise.all([d(()=>import("./index-CODVWHV0.js"),__vite__mapDeps([0,1,2,3]),import.meta.url),d(()=>import("./index-H1bePBGl.js"),__vite__mapDeps([4,1,5,6,7,8,9]),import.meta.url)]),u=t.current;if(!u||l)return;if(!n.current){const f=E();n.current=g.create(u,{autoFit:!1,duration:0,pan:!1,zoom:!1,initialExpandLevel:2,maxWidth:260,spacingVertical:10,spacingHorizontal:96,paddingX:12,color:h=>{var m;return f[(((m=h.state)==null?void 0:m.depth)??0)%f.length]??f[0]}})}const{root:x}=new p().transform(i);n.current.setData(x),n.current.fit()}catch{l||s(!0)}})(),()=>{l=!0}},[i]),r?a.jsxs("div",{className:"text-body text-ink-muted flex items-center gap-2 my-4",children:[a.jsx(_,{className:"w-4 h-4"}),e("notebook.content.render_failed")]}):a.jsx("div",{"data-testid":"mindmap-view",className:"mindmap-view h-[68vh] min-h-[420px] my-2",children:a.jsx(w,{grid:!0,testid:"mindmap-stage",children:a.jsx("div",{className:"w-[1280px] h-[760px]",children:a.jsx("svg",{ref:t,className:"w-full h-full block"})})})})}export{P as MindmapView};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r,j as e,c as S}from"./index-
|
|
1
|
+
import{r,j as e,c as S}from"./index-C-4sKCSr.js";import{u as y,a as j,S as M}from"./main-D3HpSUyK.js";function A({tree:c,onReviewNode:d,progressMap:n}){const s=y(),[x,m]=r.useState([]),[u,f]=r.useState(!0),[l,v]=r.useState(null);r.useEffect(()=>{j.getAllSrsItems().then(t=>m(t)).catch(()=>m([])).finally(()=>f(!1))},[]);const N=r.useMemo(()=>new Map(c.map(t=>[t.id,t])),[c]),p=r.useMemo(()=>new Set(x.filter(t=>t.overdue).map(t=>t.nodeId)),[x]),i=r.useMemo(()=>{const t=c.filter(b=>{var w;const o=(w=n[b.id])==null?void 0:w.status;return b.type==="lesson"&&(o==="in_progress"||o==="mastered")}),a=new Map;for(const b of t){const o=b.parentId??"(root)";a.has(o)||a.set(o,[]),a.get(o).push(b)}return a},[c,n]),g=r.useMemo(()=>Array.from(i.values()).flat().filter(t=>p.has(t.id)).length,[i,p]),h=r.useMemo(()=>Array.from(i.values()).flat(),[i]);if(r.useEffect(()=>{if(i.size>0&&(!l||!i.has(l))){const t=i.keys().next().value;t&&v(t)}},[i,l]),u)return e.jsxs("div",{className:"text-center py-12 text-body text-ink-muted flex items-center justify-center gap-2",children:[e.jsx("span",{className:"typing-dot w-1.5 h-1.5 bg-brand rounded-full inline-block"}),s("review.loading")]});if(h.length===0)return e.jsxs("div",{className:"text-center py-16","data-testid":"review-empty",children:[e.jsx("div",{className:"text-4xl mb-3 opacity-30",children:"📖"}),e.jsx("div",{className:"text-body text-ink-muted",children:s("review.empty.title")}),e.jsx("div",{className:"text-label text-ink-faint mt-1",children:s("review.empty.desc")})]});const k=t=>{var a;return((a=N.get(t))==null?void 0:a.title)??t};return e.jsxs("div",{className:"p-5 max-w-2xl mx-auto","data-testid":"review-panel",children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsx("h2",{className:"text-title font-extrabold text-ink-strong",children:s("review.title")}),g>0&&e.jsxs("span",{className:"text-label font-bold text-review","data-testid":"review-due-count",children:[g," ",s("review.due.count")]})]}),e.jsxs("button",{onClick:()=>{const t=h[Math.floor(Math.random()*h.length)];t&&d(t.id)},"data-testid":"review-interleave",className:"btn-3d-neutral w-full py-2.5 text-body mb-5 flex items-center justify-center gap-1.5",children:[e.jsx(M,{className:"w-4 h-4"}),s("review.interleave")]}),e.jsx("div",{className:"text-label font-bold text-ink-muted mb-2",children:s("review.selectSection")}),e.jsx("div",{className:"flex flex-wrap gap-1.5 mb-4",children:Array.from(i.entries()).map(([t,a])=>e.jsxs("button",{onClick:()=>v(t),className:`px-2.5 py-1 rounded-full text-label font-bold transition-colors ${l===t?"bg-brand/15 text-brand ring-1 ring-brand/30":"bg-surface-3 text-ink-muted hover:text-ink-strong"}`,children:[k(t),e.jsxs("span",{className:"ml-1 opacity-60",children:["(",a.length,")"]})]},t))}),l&&i.has(l)&&e.jsx("div",{className:"space-y-1.5","data-testid":"review-lesson-list",children:i.get(l).map(t=>{const a=p.has(t.id);return e.jsxs("div",{className:`flex items-center justify-between gap-2 p-2.5 rounded-lg transition-colors ${a?"bg-review/8 ring-1 ring-review/20":"bg-surface-3 hover:bg-surface-3/80"}`,children:[e.jsxs("div",{className:"flex items-center gap-1.5 truncate flex-1",children:[a&&e.jsx("span",{className:"shrink-0 w-1.5 h-1.5 rounded-full bg-review"}),e.jsx("span",{className:"text-body text-ink-strong truncate",children:t.title})]}),e.jsx("button",{onClick:()=>d(t.id),"data-testid":`review-lesson-${t.id.slice(0,8)}`,className:"shrink-0 px-3 py-1 rounded-lg bg-brand/15 text-brand text-label font-bold hover:bg-brand/25 transition-colors",children:s("review.reviewLesson")})]},t.id)})})]})}function E({nodeId:c,onRated:d}){const n=y(),[s,x]=r.useState(!1),[m,u]=r.useState(!1),f=async l=>{if(!(s||m)){x(!0);try{await j.recordReview(c,l),u(!0),d==null||d(),S(l>=4?"correct":"wrong")}catch{}finally{x(!1)}}};return m?e.jsx("div",{className:"text-center text-body text-brand py-2","data-testid":"self-rated",children:n("review.selfrated")}):e.jsxs("div",{className:"border-t border-[var(--border-faint)] pt-3 mt-3","data-testid":"self-rating",children:[e.jsx("div",{className:"text-caption font-bold text-ink-muted uppercase tracking-wider mb-2 text-center",children:n("review.selfrate.title")}),e.jsxs("div",{className:"grid grid-cols-3 gap-2",children:[e.jsxs("button",{onClick:()=>f(1),disabled:s,"data-testid":"rate-again",className:"py-2 rounded-lg border border-warning/40 text-warning hover:bg-warning/10 transition-colors disabled:opacity-40 flex flex-col items-center gap-0.5",children:[e.jsx("span",{className:"text-body font-bold",children:n("review.selfrate.again")}),e.jsx("span",{className:"text-caption opacity-70",children:n("review.selfrate.again.hint")})]}),e.jsxs("button",{onClick:()=>f(4),disabled:s,"data-testid":"rate-remembered",className:"py-2 rounded-lg border border-accent/40 text-accent hover:bg-accent/10 transition-colors disabled:opacity-40 flex flex-col items-center gap-0.5",children:[e.jsx("span",{className:"text-body font-bold",children:n("review.selfrate.remembered")}),e.jsx("span",{className:"text-caption opacity-70",children:n("review.selfrate.remembered.hint")})]}),e.jsxs("button",{onClick:()=>f(5),disabled:s,"data-testid":"rate-mastered",className:"py-2 rounded-lg border border-brand/40 text-brand hover:bg-brand/10 transition-colors disabled:opacity-40 flex flex-col items-center gap-0.5",children:[e.jsx("span",{className:"text-body font-bold",children:n("review.selfrate.mastered")}),e.jsx("span",{className:"text-caption opacity-70",children:n("review.selfrate.mastered.hint")})]})]})]})}export{A as ReviewPanel,E as SelfRatingCard};
|