lookatstudy-mobile 0.22.1 → 0.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/seed-course.json +15 -15
- package/server.cjs +309 -28
- package/web/assets/{CanvasStage--cO-dGou.js → CanvasStage-Ba-21anG.js} +1 -1
- package/web/assets/{CommandPalette-B9yujZKA.js → CommandPalette-SKnzQMcN.js} +1 -1
- package/web/assets/{CourseSearchPanel-C7Mz8cwp.js → CourseSearchPanel-BW3fNReR.js} +1 -1
- package/web/assets/{ExamView-CxgAmCWD.js → ExamView-BnH6BraN.js} +1 -1
- package/web/assets/{MindmapView-D2NywTY1.js → MindmapView-B4SeCLQj.js} +3 -3
- package/web/assets/{ReviewPanel-CLOe8uSS.js → ReviewPanel-DkGT8tNA.js} +1 -1
- package/web/assets/{SettingsView-Crx4fWxj.js → SettingsView-dExmRnIv.js} +3 -3
- package/web/assets/{VoicePanel-B9o8PTlU.js → VoicePanel-CxNeKn4V.js} +2 -7
- package/web/assets/{abnfDiagram-N423BO3Z-DlR3JtCi.js → abnfDiagram-N423BO3Z-B4kvB05N.js} +1 -1
- package/web/assets/{abnfDiagram-VCTEODGH-ODA7YWAP-Cc60_NCH.js → abnfDiagram-VCTEODGH-ODA7YWAP-B5zhG8XJ.js} +1 -1
- package/web/assets/{architectureDiagram-5GKGNRK7-C4PU3XN7-DxA8-TH0.js → architectureDiagram-5GKGNRK7-C4PU3XN7-ybcWxxhr.js} +1 -1
- package/web/assets/{architectureDiagram-T3A2C74G-b87f0Zfh.js → architectureDiagram-T3A2C74G-D5eb-etB.js} +1 -1
- package/web/assets/{arrow-right-B_6KkCJV.js → arrow-right-D4GV0Gpo.js} +1 -1
- package/web/assets/{blockDiagram-NRAW4CY4-UMJ6PMQQ-DujiZmu6.js → blockDiagram-NRAW4CY4-UMJ6PMQQ-DwEVReBp.js} +1 -1
- package/web/assets/{blockDiagram-VBNYF7ZC-BVvgfsGF.js → blockDiagram-VBNYF7ZC-DuM7ndnl.js} +1 -1
- package/web/assets/{c4Diagram-5PPSVZJV-5YSQGEVW.js → c4Diagram-5PPSVZJV-BQkRaO7S.js} +1 -1
- package/web/assets/{c4Diagram-UCG6FXSJ-75X3U2P3-DOEKYDP0.js → c4Diagram-UCG6FXSJ-75X3U2P3-Di1jNn7S.js} +1 -1
- package/web/assets/channel-KoPlHvUR.js +1 -0
- package/web/assets/{chunk-2GRJ4B5K-7x3UypsR.js → chunk-2GRJ4B5K-C7VAL2Yd.js} +1 -1
- package/web/assets/{chunk-2Q5K7J3B-5RQfakW9.js → chunk-2Q5K7J3B-Jpo34qVL.js} +1 -1
- package/web/assets/{chunk-5RXB4S5H-CX91mO_w.js → chunk-5RXB4S5H-CrW8aZl4.js} +1 -1
- package/web/assets/{chunk-5VM5RSS4-DhfIWqOK.js → chunk-5VM5RSS4-Dv4MffdC.js} +1 -1
- package/web/assets/{chunk-6Q2QTUOP-DyBMkImn.js → chunk-6Q2QTUOP-CI07iNTB.js} +1 -1
- package/web/assets/{chunk-7XDTSPCN-l_wcpmq6.js → chunk-7XDTSPCN-DsQtrF-N.js} +1 -1
- package/web/assets/{chunk-CTNIYPP6-Bej-ifE4.js → chunk-CTNIYPP6-CpdWBpIN.js} +1 -1
- package/web/assets/{chunk-CXNFBKHE-BymXgi-y.js → chunk-CXNFBKHE-BDCDRaZC.js} +1 -1
- package/web/assets/{chunk-GF5L2VYU-DeTnv5Qk.js → chunk-GF5L2VYU-DtpZkefy.js} +1 -1
- package/web/assets/{chunk-ISA7TJRJ-CFmR6SoA.js → chunk-ISA7TJRJ-C3LgQ-bA.js} +1 -1
- package/web/assets/{chunk-JWPE2WC7-BU-fMtWi.js → chunk-JWPE2WC7-DJM1SevB.js} +1 -1
- package/web/assets/{chunk-KBJHAD2P-BjlTMp1m.js → chunk-KBJHAD2P-7KeTMqC1.js} +1 -1
- package/web/assets/{chunk-LV3HUYFY-riE_n54k.js → chunk-LV3HUYFY-B2sGhGxz.js} +1 -1
- package/web/assets/{chunk-M3IUQBOH-DYx0J19K.js → chunk-M3IUQBOH-Dazbegdb.js} +1 -1
- package/web/assets/{chunk-NDIOYS4C-D34dHdEf.js → chunk-NDIOYS4C-Cx7mCz5-.js} +1 -1
- package/web/assets/{chunk-RE4WF27V-qx7CV25O.js → chunk-RE4WF27V-BNzpDJts.js} +1 -1
- package/web/assets/{chunk-RYQCIY6F-AqdEeieF.js → chunk-RYQCIY6F-Boq_29rU.js} +1 -1
- package/web/assets/{chunk-VII2H2IX-CzkbeZYY.js → chunk-VII2H2IX-kQVDZD-x.js} +1 -1
- package/web/assets/{chunk-X5GNSKZ3-DVqvzTCj.js → chunk-X5GNSKZ3-DT5Ja5IF.js} +1 -1
- package/web/assets/{chunk-XCWWM2C3-BJLKBAh0.js → chunk-XCWWM2C3-BAq7zpgL.js} +1 -1
- package/web/assets/{chunk-XXDRQBXY-Nz1f1JPS.js → chunk-XXDRQBXY-D3vcLngc.js} +1 -1
- package/web/assets/classDiagram-DTDB5LWJ-LWRDKZ5K-P8Aw4zHn.js +1 -0
- package/web/assets/classDiagram-JCYQIIEL-Dm2NSERp.js +1 -0
- package/web/assets/classDiagram-v2-JRS7N3AN-2BZHGRP2-P8Aw4zHn.js +1 -0
- package/web/assets/classDiagram-v2-OCEON4UE-Dm2NSERp.js +1 -0
- package/web/assets/{core-5AezUpt1.js → core-4d9vIKK9.js} +4 -4
- package/web/assets/{cose-bilkent-JH36ORCC-OB24KH3T-B46Ih9E8.js → cose-bilkent-JH36ORCC-OB24KH3T-DwFzf1xR.js} +1 -1
- package/web/assets/{cose-bilkent-JH36ORCC-Bwf1adzB.js → cose-bilkent-JH36ORCC-RoUdcSs7.js} +1 -1
- package/web/assets/{cynefin-OW5HDTMX-GVF3BKWE-DcR0n-8p.js → cynefin-OW5HDTMX-GVF3BKWE-Bdt2EF7g.js} +1 -1
- package/web/assets/{cynefin-VYW2F7L2-BtjjXqMe.js → cynefin-VYW2F7L2-Br1TXK2f.js} +1 -1
- package/web/assets/{cynefinDiagram-5FMLGOSQ-H3WIRU3N-CecBQ3WS.js → cynefinDiagram-5FMLGOSQ-H3WIRU3N-DFRlDIhn.js} +1 -1
- package/web/assets/{cynefinDiagram-MW4NZA55-CeLD6_7i.js → cynefinDiagram-MW4NZA55-DeqLH2Db.js} +1 -1
- package/web/assets/{dagre-3AP2YEHR-DCERTXHT-I_531Mm0.js → dagre-3AP2YEHR-DCERTXHT-wbCkJQSQ.js} +1 -1
- package/web/assets/{dagre-VZM6K2ZE-BYSfxtKs.js → dagre-VZM6K2ZE-X3laLObS.js} +1 -1
- package/web/assets/{diagram-7IWD3JNH-CfUUB3zT.js → diagram-7IWD3JNH-8bZxUpBi.js} +1 -1
- package/web/assets/{diagram-B4RE2ZJO-B4h2KVGE.js → diagram-B4RE2ZJO-CsGnKBa4.js} +1 -1
- package/web/assets/{diagram-LBJQPF4R-BycPUMao.js → diagram-LBJQPF4R-CxaNBwKI.js} +1 -1
- package/web/assets/{diagram-Q27KOJAE-nUmmLOWc.js → diagram-Q27KOJAE-CjVLD6gb.js} +1 -1
- package/web/assets/{diagram-S7CK7UJ4-MULGZGEL-YmP_5pu9.js → diagram-S7CK7UJ4-MULGZGEL-wKLcWkw4.js} +1 -1
- package/web/assets/{diagram-UB23O5K3-AbqPe_Lw.js → diagram-UB23O5K3-CUZ34yVE.js} +1 -1
- package/web/assets/{diagram-UQ7AKVKN-YQBY353J-CSBHhT_p.js → diagram-UQ7AKVKN-YQBY353J-B_ah6OV8.js} +1 -1
- package/web/assets/{diagram-VSXAHHWV-WLNH2ELY-BIWRzcG_.js → diagram-VSXAHHWV-WLNH2ELY-BhbJ7E_e.js} +1 -1
- package/web/assets/{diagram-VX7I27RA-XW6YQV5G-DOIsDS0u.js → diagram-VX7I27RA-XW6YQV5G-DnFEyO87.js} +1 -1
- package/web/assets/{diagram-Z3DM3KII-HG7RF65D-CL_RkrR1.js → diagram-Z3DM3KII-HG7RF65D-Vughovua.js} +1 -1
- package/web/assets/{ebnfDiagram-BXEA7PRR-CiCY0Nb_.js → ebnfDiagram-BXEA7PRR-B2ehf44X.js} +1 -1
- package/web/assets/{ebnfDiagram-PWID7BFC-OKY4VHYD-30_W7bxy.js → ebnfDiagram-PWID7BFC-OKY4VHYD-BjbgNq8R.js} +1 -1
- package/web/assets/{elk.bundled-CoJK8Y5o.js → elk.bundled-CktUbZ7z.js} +1 -1
- package/web/assets/{erDiagram-JOGREHBK-CiMrd6Dm.js → erDiagram-JOGREHBK-9wI_YE-7.js} +1 -1
- package/web/assets/{erDiagram-SSCWMZ5O-PIPKOIK7-DR-Xlax4.js → erDiagram-SSCWMZ5O-PIPKOIK7-V60k7zg6.js} +1 -1
- package/web/assets/{flowDiagram-A5DVABFB-2Z4AVO5R-Bm2DnZWS.js → flowDiagram-A5DVABFB-2Z4AVO5R-CJdwjvtN.js} +1 -1
- package/web/assets/{flowDiagram-UKHOOZJN-DlA7YU9i.js → flowDiagram-UKHOOZJN-B3XmqjMH.js} +1 -1
- package/web/assets/{ganttDiagram-EL5Y4UJY-JZNG7GOG-CycOiHbj.js → ganttDiagram-EL5Y4UJY-JZNG7GOG-2a6TiXM3.js} +1 -1
- package/web/assets/{ganttDiagram-PKOTCBZU-BT4d6R51.js → ganttDiagram-PKOTCBZU-B7B9nD6g.js} +1 -1
- package/web/assets/{gitGraphDiagram-DS77QQ5N-DyUz04eh.js → gitGraphDiagram-DS77QQ5N-VwKL0Ozk.js} +1 -1
- package/web/assets/{gitGraphDiagram-WWUBYQGX-DMWMLL3G-Cp635UIu.js → gitGraphDiagram-WWUBYQGX-DMWMLL3G-BMs5FYkE.js} +1 -1
- package/web/assets/{index-D619gSoN.js → index-D0FRqjBW.js} +2 -2
- package/web/assets/{index-ClPJ1xdX.js → index-DFryMRAp.js} +6 -6
- package/web/assets/{index-c6Br465X.css → index-DjoBjasB.css} +1 -1
- package/web/assets/{index-8JL6mw1y.js → index-DkjixD09.js} +1 -1
- package/web/assets/{index-BSXjRLsf.js → index-Vtc_VHiK.js} +1 -1
- package/web/assets/{infoDiagram-6WML65LV-rj50EKNC.js → infoDiagram-6WML65LV-CD6GNI7J.js} +1 -1
- package/web/assets/{infoDiagram-RXCK75RN-HANS5KVC-BHovTPxo.js → infoDiagram-RXCK75RN-HANS5KVC-k8vzCiSp.js} +1 -1
- package/web/assets/{ishikawaDiagram-5VMMS53U-7GCIT7WU-B0aX9dg0.js → ishikawaDiagram-5VMMS53U-7GCIT7WU-Ckl5jIU6.js} +1 -1
- package/web/assets/{ishikawaDiagram-WSZJBQD7-Cs68VzMS.js → ishikawaDiagram-WSZJBQD7-CEdvuK4K.js} +1 -1
- package/web/assets/{journeyDiagram-EYS64GPL-OAPELBT7-BaF1Okyl.js → journeyDiagram-EYS64GPL-OAPELBT7-DtCRso4h.js} +1 -1
- package/web/assets/{journeyDiagram-NVQOT4AX-CxamcAfg.js → journeyDiagram-NVQOT4AX-CxPjI9L-.js} +1 -1
- package/web/assets/{kanban-definition-27J2QSJJ-CqkEoxuc.js → kanban-definition-27J2QSJJ-DnuNCFkl.js} +1 -1
- package/web/assets/{kanban-definition-3QL26DDD-I7RKWQQY-KQq8LJIu.js → kanban-definition-3QL26DDD-I7RKWQQY-yNRn2nj0.js} +1 -1
- package/web/assets/{katex-N6JRN4PM-BRgAOu7M.js → katex-N6JRN4PM-B9dEOiMG.js} +1 -1
- package/web/assets/main-CGE6fm01.js +462 -0
- package/web/assets/{mermaid-layout-elk.core-CS6tfHSb.js → mermaid-layout-elk.core-BUAJJUsd.js} +2 -2
- package/web/assets/{mermaid.core-D_Bznvdr.js → mermaid.core-BD32Za4p.js} +4 -4
- package/web/assets/{mindmap-definition-FAOFIHXS-h9YeSHf4.js → mindmap-definition-FAOFIHXS-DX6VEGs_.js} +1 -1
- package/web/assets/{mindmap-definition-FBJOCRG2-KIYZG64Y-DT9Y6a9o.js → mindmap-definition-FBJOCRG2-KIYZG64Y-DYiBZnHG.js} +1 -1
- package/web/assets/{pegDiagram-VL7TDLO6-C--Hsstu.js → pegDiagram-VL7TDLO6-Big72xut.js} +1 -1
- package/web/assets/{pegDiagram-XKGWAZYB-OIP57N6J-CXtA7B8B.js → pegDiagram-XKGWAZYB-OIP57N6J-N0pgSR7W.js} +1 -1
- package/web/assets/{pet-BWlfq4I-.js → pet-DopPVlAf.js} +1 -1
- package/web/assets/{pieDiagram-7S7Q4E2Y-CVnsOokB.js → pieDiagram-7S7Q4E2Y-BLXLqOCg.js} +1 -1
- package/web/assets/{pieDiagram-E7YTZNPT-2UOTW327-DkYfAF2K.js → pieDiagram-E7YTZNPT-2UOTW327-BuB4rTS2.js} +1 -1
- package/web/assets/{quadrantDiagram-AXDQQJYC-SN3ASJJK-B3grZeFo.js → quadrantDiagram-AXDQQJYC-SN3ASJJK-4S-5LgOz.js} +1 -1
- package/web/assets/{quadrantDiagram-CIZ2JOQS-i1yx34JH.js → quadrantDiagram-CIZ2JOQS-BUwizsLb.js} +1 -1
- package/web/assets/{railroadDiagram-AXF67PYL-DJuiGlbf.js → railroadDiagram-AXF67PYL-D3qxyYSE.js} +1 -1
- package/web/assets/{railroadDiagram-O6MQD6OU-34742W6X-up2Y0ZV_.js → railroadDiagram-O6MQD6OU-34742W6X-CzT_bN34.js} +1 -1
- package/web/assets/{render-O7CIS3YK-Dn1e27o_.js → render-O7CIS3YK-DhYmSGoI.js} +7 -7
- package/web/assets/{requirementDiagram-EFPCY7ZU-NGAFFSMB-BI_BSQB1.js → requirementDiagram-EFPCY7ZU-NGAFFSMB-iWwnW8VG.js} +1 -1
- package/web/assets/{requirementDiagram-LRYGKXZP-nFTGE1MQ.js → requirementDiagram-LRYGKXZP-Cf95T2or.js} +1 -1
- package/web/assets/{rotate-ccw-nkiipcxH.js → rotate-ccw-natFwqj6.js} +1 -1
- package/web/assets/{sankeyDiagram-P5KCCOFB-3D3M4XPB-Bqf3rmL6.js → sankeyDiagram-P5KCCOFB-3D3M4XPB-CjA_LC6M.js} +1 -1
- package/web/assets/{sankeyDiagram-W5VNT64P-BIhgGHwI.js → sankeyDiagram-W5VNT64P-CeGCHk7F.js} +1 -1
- package/web/assets/{sequenceDiagram-SI44F4Z6-BASko1ED.js → sequenceDiagram-SI44F4Z6-BDsExCj2.js} +1 -1
- package/web/assets/{sequenceDiagram-WJ2MYXX4-Q2IOPB4R-BiNVA6gm.js → sequenceDiagram-WJ2MYXX4-Q2IOPB4R-DbWhuP8u.js} +1 -1
- package/web/assets/{sizeCapture-X5ZJPWSS-PSGVOMYM-TxBOTj1p.js → sizeCapture-X5ZJPWSS-PSGVOMYM-DB5JtURh.js} +1 -1
- package/web/assets/{sizeCapture-X5ZJPWSS-CGWs4y9a.js → sizeCapture-X5ZJPWSS-_5trx7u2.js} +1 -1
- package/web/assets/{stateDiagram-HBIQ2CUA-4M2S6MAN-BdhmANKG.js → stateDiagram-HBIQ2CUA-4M2S6MAN-CBEhL8_A.js} +1 -1
- package/web/assets/{stateDiagram-OKZ733FA-CkUDyLVf.js → stateDiagram-OKZ733FA-BPHwMfDA.js} +1 -1
- package/web/assets/stateDiagram-v2-4QOOHH4V-LBBLA2WV-lZeXiw9L.js +1 -0
- package/web/assets/stateDiagram-v2-UEYNNEHI-cH9YNExR.js +1 -0
- package/web/assets/{swimlanes-SLNWSIFB-CZxwkAvO.js → swimlanes-SLNWSIFB-CDgj9OM9.js} +2 -2
- package/web/assets/{swimlanes-XN3QIQJK-N6N2CCQ6-Zac8KNFb.js → swimlanes-XN3QIQJK-N6N2CCQ6-D3F0tmOR.js} +1 -1
- package/web/assets/swimlanesDiagram-ULZ7WXOC-C3faa0-8.js +8 -0
- package/web/assets/swimlanesDiagram-VK2B7HYN-E6N4H5SY-D5nVBF4q.js +8 -0
- package/web/assets/{timeline-definition-24CTP7MA-KN7RSRVM-DCu4MVvb.js → timeline-definition-24CTP7MA-KN7RSRVM-C0Ufqqk-.js} +1 -1
- package/web/assets/{timeline-definition-Z64GVDOM-DEFnQeMY.js → timeline-definition-Z64GVDOM-81O3UI2y.js} +1 -1
- package/web/assets/{vennDiagram-4TSXK5OY-AKJ7LXAN-Bi1vBY1O.js → vennDiagram-4TSXK5OY-AKJ7LXAN-Cwa7TjWJ.js} +1 -1
- package/web/assets/{vennDiagram-T6HMQDX7-Wls_-1IU.js → vennDiagram-T6HMQDX7-BfOTIcvk.js} +1 -1
- package/web/assets/{wardleyDiagram-T6FBY63Y-BSjNiv26.js → wardleyDiagram-T6FBY63Y-CYCyu4_S.js} +1 -1
- package/web/assets/{wardleyDiagram-VM6X3IG4-3B6A3BN5-BWtS3yVZ.js → wardleyDiagram-VM6X3IG4-3B6A3BN5-CHXrbpNv.js} +1 -1
- package/web/assets/{xychartDiagram-ELKLHX3M-B5qgODUp.js → xychartDiagram-ELKLHX3M-7mp6PB7p.js} +1 -1
- package/web/assets/{xychartDiagram-S5SC5T6Z-OBDNV6WG-j0XdC2zd.js → xychartDiagram-S5SC5T6Z-OBDNV6WG-Ch73fB_B.js} +1 -1
- package/web/index.html +3 -3
- package/web/pet.html +3 -3
- package/web/assets/channel-CWI530Vq.js +0 -1
- package/web/assets/classDiagram-DTDB5LWJ-LWRDKZ5K---3y6DiQ.js +0 -1
- package/web/assets/classDiagram-JCYQIIEL-CKDJ6TE8.js +0 -1
- package/web/assets/classDiagram-v2-JRS7N3AN-2BZHGRP2---3y6DiQ.js +0 -1
- package/web/assets/classDiagram-v2-OCEON4UE-CKDJ6TE8.js +0 -1
- package/web/assets/main-BBu4fQk-.js +0 -457
- package/web/assets/stateDiagram-v2-4QOOHH4V-LBBLA2WV-DLoWKuNC.js +0 -1
- package/web/assets/stateDiagram-v2-UEYNNEHI-C4uNy_P4.js +0 -1
- package/web/assets/swimlanesDiagram-ULZ7WXOC-Ch9trOTe.js +0 -8
- package/web/assets/swimlanesDiagram-VK2B7HYN-E6N4H5SY-DBYYfTTt.js +0 -8
- /package/web/assets/{index-C5s4t4ce.js → index-xynt7zMk.js} +0 -0
package/server.cjs
CHANGED
|
@@ -62413,6 +62413,13 @@ ${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)
|
|
62416
62423
|
- \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
62424
|
- \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
62425
|
|
|
@@ -244640,6 +244647,33 @@ var pptx_parser_exports = {};
|
|
|
244640
244647
|
__export(pptx_parser_exports, {
|
|
244641
244648
|
parsePptx: () => parsePptx
|
|
244642
244649
|
});
|
|
244650
|
+
function tableToMarkdown(node) {
|
|
244651
|
+
const rows = /* @__PURE__ */ new Map();
|
|
244652
|
+
const walk = (n) => {
|
|
244653
|
+
if (n?.type === "cell") {
|
|
244654
|
+
const r = Number(n.metadata?.row ?? 0);
|
|
244655
|
+
const c = Number(n.metadata?.col ?? 0);
|
|
244656
|
+
const text3 = String(n.text ?? "").trim().replace(/\|/g, "\\|").replace(/\s+/g, " ");
|
|
244657
|
+
if (!rows.has(r))
|
|
244658
|
+
rows.set(r, []);
|
|
244659
|
+
rows.get(r).push({ col: c, text: text3 });
|
|
244660
|
+
return;
|
|
244661
|
+
}
|
|
244662
|
+
for (const ch2 of n?.children ?? [])
|
|
244663
|
+
walk(ch2);
|
|
244664
|
+
};
|
|
244665
|
+
walk(node);
|
|
244666
|
+
if (rows.size === 0)
|
|
244667
|
+
return "";
|
|
244668
|
+
if ([...rows.values()].every((cells) => cells.every((c) => !c.text)))
|
|
244669
|
+
return "";
|
|
244670
|
+
const sorted = [...rows.entries()].sort((a, b) => a[0] - b[0]).map(([, cells]) => cells.sort((a, b) => a.col - b.col));
|
|
244671
|
+
const width = Math.max(...sorted.map((cs) => cs.length));
|
|
244672
|
+
const line = (texts) => `| ${Array.from({ length: width }, (_, i) => texts[i] ?? "").join(" | ")} |`;
|
|
244673
|
+
const header = line(sorted[0].map((c) => c.text));
|
|
244674
|
+
const sep3 = `| ${Array.from({ length: width }, () => "---").join(" | ")} |`;
|
|
244675
|
+
return [header, sep3, ...sorted.slice(1).map((cs) => line(cs.map((c) => c.text)))].join("\n");
|
|
244676
|
+
}
|
|
244643
244677
|
async function parsePptx(buf) {
|
|
244644
244678
|
const ast = await OfficeParser.parseOffice(buf, {
|
|
244645
244679
|
extractAttachments: true,
|
|
@@ -244670,6 +244704,10 @@ async function parsePptx(buf) {
|
|
|
244670
244704
|
title = child.text;
|
|
244671
244705
|
else
|
|
244672
244706
|
bodyTexts.push(child.text);
|
|
244707
|
+
} else if (child.type === "table") {
|
|
244708
|
+
const md = tableToMarkdown(child);
|
|
244709
|
+
if (md)
|
|
244710
|
+
bodyTexts.push(md);
|
|
244673
244711
|
} else if (child.type === "image") {
|
|
244674
244712
|
const name18 = child.metadata?.attachmentName;
|
|
244675
244713
|
if (name18 && attMap.has(name18) && !seenImg.has(name18)) {
|
|
@@ -485219,8 +485257,14 @@ var require_pdf_parse2 = __commonJS({
|
|
|
485219
485257
|
// src/main/lib/pdf-text.ts
|
|
485220
485258
|
var pdf_text_exports = {};
|
|
485221
485259
|
__export(pdf_text_exports, {
|
|
485260
|
+
normalizeRadicals: () => normalizeRadicals,
|
|
485222
485261
|
parsePdfText: () => parsePdfText
|
|
485223
485262
|
});
|
|
485263
|
+
function normalizeRadicals(md) {
|
|
485264
|
+
if (!md)
|
|
485265
|
+
return md;
|
|
485266
|
+
return /[\u2F00-\u2FDF]/.test(md) ? md.replace(/[\u2F00-\u2FDF]/g, (c) => c.normalize("NFKC")) : md;
|
|
485267
|
+
}
|
|
485224
485268
|
async function parsePdfText(buf) {
|
|
485225
485269
|
if (!process.env.LOOKATSTUDY_NO_PDF_INSPECTOR) {
|
|
485226
485270
|
try {
|
|
@@ -485228,13 +485272,13 @@ async function parsePdfText(buf) {
|
|
|
485228
485272
|
const result = await pi.processPdfAsync(buf);
|
|
485229
485273
|
const md = (result?.markdown ?? "").trim();
|
|
485230
485274
|
if (md)
|
|
485231
|
-
return md;
|
|
485275
|
+
return normalizeRadicals(md);
|
|
485232
485276
|
} catch {
|
|
485233
485277
|
}
|
|
485234
485278
|
}
|
|
485235
485279
|
try {
|
|
485236
485280
|
const pdfParse = require_pdf_parse2();
|
|
485237
|
-
return (await pdfParse(buf)).text.trim();
|
|
485281
|
+
return normalizeRadicals((await pdfParse(buf)).text.trim());
|
|
485238
485282
|
} catch {
|
|
485239
485283
|
return "";
|
|
485240
485284
|
}
|
|
@@ -486386,7 +486430,7 @@ var init_Tokenizer = __esm({
|
|
|
486386
486430
|
// `</xmp`
|
|
486387
486431
|
};
|
|
486388
486432
|
Tokenizer = class {
|
|
486389
|
-
constructor({ xmlMode = false, decodeEntities = true }, cbs) {
|
|
486433
|
+
constructor({ xmlMode = false, decodeEntities: decodeEntities2 = true }, cbs) {
|
|
486390
486434
|
this.cbs = cbs;
|
|
486391
486435
|
this.state = State.Text;
|
|
486392
486436
|
this.buffer = "";
|
|
@@ -486400,7 +486444,7 @@ var init_Tokenizer = __esm({
|
|
|
486400
486444
|
this.currentSequence = void 0;
|
|
486401
486445
|
this.sequenceIndex = 0;
|
|
486402
486446
|
this.xmlMode = xmlMode;
|
|
486403
|
-
this.decodeEntities =
|
|
486447
|
+
this.decodeEntities = decodeEntities2;
|
|
486404
486448
|
this.entityDecoder = new EntityDecoder(xmlMode ? xmlDecodeTree : htmlDecodeTree, (cp, consumed) => this.emitCodePoint(cp, consumed));
|
|
486405
486449
|
}
|
|
486406
486450
|
reset() {
|
|
@@ -518749,7 +518793,28 @@ function extractArticle(html, baseUrl = "") {
|
|
|
518749
518793
|
const md = alreadyHasTitleH1 ? body : `# ${title || "\u65E0\u6807\u9898\u6587\u7AE0"}
|
|
518750
518794
|
|
|
518751
518795
|
${body}`;
|
|
518752
|
-
return { title: title || "\u65E0\u6807\u9898\u6587\u7AE0", markdown: md };
|
|
518796
|
+
return { title: title || "\u65E0\u6807\u9898\u6587\u7AE0", markdown: stripTailNavigation(md) };
|
|
518797
|
+
}
|
|
518798
|
+
function stripTailNavigation(md) {
|
|
518799
|
+
if (!md)
|
|
518800
|
+
return md;
|
|
518801
|
+
for (const suffix of INLINE_NAV_SUFFIXES)
|
|
518802
|
+
md = md.split(suffix).join("");
|
|
518803
|
+
const lines = md.split("\n");
|
|
518804
|
+
let end = lines.length;
|
|
518805
|
+
for (let i = lines.length - 1; i >= Math.max(0, lines.length - 25); i--) {
|
|
518806
|
+
const ln = lines[i].trim();
|
|
518807
|
+
if (!ln)
|
|
518808
|
+
continue;
|
|
518809
|
+
const bare = ln.replace(/^#{1,6}\s*/, "").replace(/^[>\-*]\s*/, "");
|
|
518810
|
+
const isNav = NAV_TAIL_PATTERNS.some((re2) => re2.test(bare) || re2.test(ln));
|
|
518811
|
+
const isBareImage = /^!\[[^\]]*\]\([^)]*\)$/.test(ln) || /^\S+\.(jpeg|jpg|png|gif|webp)\)?$/i.test(ln);
|
|
518812
|
+
if (isNav || isBareImage)
|
|
518813
|
+
continue;
|
|
518814
|
+
end = i + 1;
|
|
518815
|
+
break;
|
|
518816
|
+
}
|
|
518817
|
+
return lines.slice(0, end).join("\n").trimEnd();
|
|
518753
518818
|
}
|
|
518754
518819
|
function htmlToMarkdown(html, opts = {}) {
|
|
518755
518820
|
let { document: document2 } = parseHTML(html);
|
|
@@ -518779,7 +518844,7 @@ function htmlToMarkdown(html, opts = {}) {
|
|
|
518779
518844
|
return "";
|
|
518780
518845
|
return turndown.turndown(body).trim();
|
|
518781
518846
|
}
|
|
518782
|
-
var import_readability, import_turndown, turndown;
|
|
518847
|
+
var import_readability, import_turndown, turndown, NAV_TAIL_PATTERNS, INLINE_NAV_SUFFIXES;
|
|
518783
518848
|
var init_html_article = __esm({
|
|
518784
518849
|
"src/main/services/pure/html-article.ts"() {
|
|
518785
518850
|
"use strict";
|
|
@@ -518791,6 +518856,21 @@ var init_html_article = __esm({
|
|
|
518791
518856
|
codeBlockStyle: "fenced",
|
|
518792
518857
|
bulletListMarker: "-"
|
|
518793
518858
|
});
|
|
518859
|
+
NAV_TAIL_PATTERNS = [
|
|
518860
|
+
/返回\S{0,6}[,,]?\s*查看更多/,
|
|
518861
|
+
// 搜狐模板
|
|
518862
|
+
/点击进入\S{0,8}首页/,
|
|
518863
|
+
// 搜狐模板
|
|
518864
|
+
/^热门文章$/,
|
|
518865
|
+
// 阿里云侧栏
|
|
518866
|
+
/^最新文章$/,
|
|
518867
|
+
// 阿里云侧栏
|
|
518868
|
+
/^目录\s*$/,
|
|
518869
|
+
// 阿里云侧栏(尾部窗口内)
|
|
518870
|
+
/^END\b.*版权/
|
|
518871
|
+
// 公众号转载页模板
|
|
518872
|
+
];
|
|
518873
|
+
INLINE_NAV_SUFFIXES = ["\u76EE\u5F55 \u70ED\u95E8\u6587\u7AE0 \u6700\u65B0\u6587\u7AE0"];
|
|
518794
518874
|
}
|
|
518795
518875
|
});
|
|
518796
518876
|
|
|
@@ -518798,7 +518878,9 @@ var init_html_article = __esm({
|
|
|
518798
518878
|
var epub_parser_exports = {};
|
|
518799
518879
|
__export(epub_parser_exports, {
|
|
518800
518880
|
parseEpub: () => parseEpub,
|
|
518801
|
-
parseEpubFlat: () => parseEpubFlat
|
|
518881
|
+
parseEpubFlat: () => parseEpubFlat,
|
|
518882
|
+
sanitizeEpubBody: () => sanitizeEpubBody,
|
|
518883
|
+
splitChaptersInBody: () => splitChaptersInBody
|
|
518802
518884
|
});
|
|
518803
518885
|
function tags(xml, tagName19) {
|
|
518804
518886
|
const out = [];
|
|
@@ -518859,6 +518941,98 @@ function parseTocLabels(tocXml, isNcx) {
|
|
|
518859
518941
|
function sanitizeFileName(title) {
|
|
518860
518942
|
return (title || "chapter").replace(/[\\/:*?"<>|#\s]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 50) || "chapter";
|
|
518861
518943
|
}
|
|
518944
|
+
function splitChaptersInBody(body, opts) {
|
|
518945
|
+
const lines = body.split("\n");
|
|
518946
|
+
const marks = [];
|
|
518947
|
+
for (let i = 0; i < lines.length; i++) {
|
|
518948
|
+
const ln = lines[i].trimEnd();
|
|
518949
|
+
if (!ln || ln.length > 60)
|
|
518950
|
+
continue;
|
|
518951
|
+
const strip = (s) => s.replace(/^#{1,3}\s*/, "");
|
|
518952
|
+
let m = ln.match(CH_HEADING);
|
|
518953
|
+
if (m) {
|
|
518954
|
+
marks.push({ line: i, title: strip(ln), kind: "ch", seq: 0 });
|
|
518955
|
+
continue;
|
|
518956
|
+
}
|
|
518957
|
+
m = ln.match(LETTER_HEADING);
|
|
518958
|
+
if (m) {
|
|
518959
|
+
marks.push({ line: i, title: strip(ln), kind: "letter", seq: 0 });
|
|
518960
|
+
continue;
|
|
518961
|
+
}
|
|
518962
|
+
m = ln.match(ROMAN_HEADING);
|
|
518963
|
+
if (m && (ln.startsWith("#") || /[—[]/.test(ln))) {
|
|
518964
|
+
marks.push({ line: i, title: strip(ln), kind: "roman", seq: romanValue(m[1]) });
|
|
518965
|
+
continue;
|
|
518966
|
+
}
|
|
518967
|
+
m = ln.match(NUM_HEADING);
|
|
518968
|
+
if (m && (ln.startsWith("#") || /[—[]/.test(ln))) {
|
|
518969
|
+
marks.push({ line: i, title: strip(ln), kind: "num", seq: parseInt(m[1], 10) });
|
|
518970
|
+
continue;
|
|
518971
|
+
}
|
|
518972
|
+
}
|
|
518973
|
+
const minHigh = opts?.minHighConf ?? 2;
|
|
518974
|
+
const highConf = marks.filter((mk) => mk.kind === "ch" || mk.kind === "letter");
|
|
518975
|
+
let splitMarks;
|
|
518976
|
+
if (highConf.length >= minHigh) {
|
|
518977
|
+
splitMarks = highConf;
|
|
518978
|
+
} else {
|
|
518979
|
+
splitMarks = [];
|
|
518980
|
+
for (const kind of ["roman", "num"]) {
|
|
518981
|
+
const seq = marks.filter((mk) => mk.kind === kind);
|
|
518982
|
+
const chain = [];
|
|
518983
|
+
let expect = 0;
|
|
518984
|
+
for (const mk of seq) {
|
|
518985
|
+
if (expect === 0) {
|
|
518986
|
+
if (mk.seq === 1 || mk.seq === 2) {
|
|
518987
|
+
chain.push(mk);
|
|
518988
|
+
expect = mk.seq + 1;
|
|
518989
|
+
}
|
|
518990
|
+
} else if (mk.seq === expect) {
|
|
518991
|
+
chain.push(mk);
|
|
518992
|
+
expect++;
|
|
518993
|
+
}
|
|
518994
|
+
}
|
|
518995
|
+
if (chain.length >= 3)
|
|
518996
|
+
splitMarks.push(...chain);
|
|
518997
|
+
}
|
|
518998
|
+
if (splitMarks.length < 3)
|
|
518999
|
+
return null;
|
|
519000
|
+
}
|
|
519001
|
+
if (splitMarks.length < 1)
|
|
519002
|
+
return null;
|
|
519003
|
+
const out = [];
|
|
519004
|
+
const preamble = lines.slice(0, splitMarks[0].line).join("\n").trim();
|
|
519005
|
+
for (let k = 0; k < splitMarks.length; k++) {
|
|
519006
|
+
const start = splitMarks[k].line;
|
|
519007
|
+
const end = k + 1 < splitMarks.length ? splitMarks[k + 1].line : lines.length;
|
|
519008
|
+
let content = lines.slice(start + 1, end).join("\n").trim();
|
|
519009
|
+
if (k === 0 && preamble && preamble.length < 800) {
|
|
519010
|
+
content = `${preamble}
|
|
519011
|
+
|
|
519012
|
+
${content}`.trim();
|
|
519013
|
+
}
|
|
519014
|
+
out.push({ title: splitMarks[k].title, content });
|
|
519015
|
+
}
|
|
519016
|
+
if (preamble && preamble.length >= 800) {
|
|
519017
|
+
out.unshift({ title: "\u5F15\u8A00", content: preamble });
|
|
519018
|
+
}
|
|
519019
|
+
return out.filter((c) => c.content.replace(/\s/g, "").length > 0);
|
|
519020
|
+
}
|
|
519021
|
+
function sanitizeEpubBody(body) {
|
|
519022
|
+
let md = body;
|
|
519023
|
+
const lines0 = md.split("\n");
|
|
519024
|
+
for (let i = 0; i < lines0.length; i++) {
|
|
519025
|
+
const ln = lines0[i].trim();
|
|
519026
|
+
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")) {
|
|
519027
|
+
md = lines0.slice(0, i).join("\n");
|
|
519028
|
+
break;
|
|
519029
|
+
}
|
|
519030
|
+
}
|
|
519031
|
+
md = md.replace(/^#{1,3}\s*(?:The Project Gutenberg eBook[^*\n]*|Project Gutenberg[^*\n]*)\n[\s\S]*?\n(?:\n|$)/im, "");
|
|
519032
|
+
md = md.replace(/^#{1,3}[ \t]*$/gm, "");
|
|
519033
|
+
md = md.replace(/\\?\[?\s*_?Copyright 1[6-9]\d\d[^_\n]*_?\s*\\?]?/g, "");
|
|
519034
|
+
return md.trim();
|
|
519035
|
+
}
|
|
518862
519036
|
async function parseEpub(buf) {
|
|
518863
519037
|
const entries3 = unzipSync(buf);
|
|
518864
519038
|
const read2 = (p) => {
|
|
@@ -518911,13 +519085,48 @@ async function parseEpub(buf) {
|
|
|
518911
519085
|
if (!md || md.replace(/[#\s>*-]/g, "").length < 8)
|
|
518912
519086
|
continue;
|
|
518913
519087
|
n++;
|
|
518914
|
-
const
|
|
519088
|
+
const body0 = md.startsWith("# ") && md.includes("\n") ? md.slice(md.indexOf("\n") + 1).trim() : md;
|
|
518915
519089
|
const firstHeading = md.startsWith("# ") ? md.split("\n")[0].slice(2).trim() : "";
|
|
518916
|
-
const
|
|
519090
|
+
const fileTitle = tocLabels.get(opfDirKey(item.href)) || firstHeading || `\u7B2C ${n} \u7AE0`;
|
|
519091
|
+
if (/^(contents|table of contents)$/i.test(fileTitle) && body0.replace(/\s/g, "").length < 4e3)
|
|
519092
|
+
continue;
|
|
519093
|
+
if (body0.replace(/\s/g, "").length < 1500 && /project gutenberg|copyright/i.test(body0))
|
|
519094
|
+
continue;
|
|
519095
|
+
const body = sanitizeEpubBody(body0);
|
|
519096
|
+
if (body.replace(/\s/g, "").length < 8)
|
|
519097
|
+
continue;
|
|
519098
|
+
const titleIsLicense = /FULL PROJECT GUTENBERG|LICENSE/i.test(fileTitle);
|
|
519099
|
+
const split = splitChaptersInBody(body, titleIsLicense ? { minHighConf: 1 } : void 0);
|
|
519100
|
+
if (split && split.length >= (titleIsLicense ? 1 : 2)) {
|
|
519101
|
+
for (const seg of split) {
|
|
519102
|
+
chapters.push({
|
|
519103
|
+
path: `chapters/${String(n).padStart(2, "0")}-${sanitizeFileName(seg.title)}.md`,
|
|
519104
|
+
title: seg.title,
|
|
519105
|
+
markdown: `# ${seg.title}
|
|
519106
|
+
|
|
519107
|
+
${seg.content}`
|
|
519108
|
+
});
|
|
519109
|
+
n++;
|
|
519110
|
+
}
|
|
519111
|
+
n--;
|
|
519112
|
+
continue;
|
|
519113
|
+
}
|
|
519114
|
+
if (titleIsLicense) {
|
|
519115
|
+
if (body.replace(/\s/g, "").length > 2e3) {
|
|
519116
|
+
chapters.push({
|
|
519117
|
+
path: `chapters/${String(n).padStart(2, "0")}-appendix.md`,
|
|
519118
|
+
title: "\u9644\u5F55",
|
|
519119
|
+
markdown: `# \u9644\u5F55
|
|
519120
|
+
|
|
519121
|
+
${body}`
|
|
519122
|
+
});
|
|
519123
|
+
}
|
|
519124
|
+
continue;
|
|
519125
|
+
}
|
|
518917
519126
|
chapters.push({
|
|
518918
|
-
path: `chapters/${String(n).padStart(2, "0")}-${sanitizeFileName(
|
|
518919
|
-
title,
|
|
518920
|
-
markdown: `# ${
|
|
519127
|
+
path: `chapters/${String(n).padStart(2, "0")}-${sanitizeFileName(fileTitle)}.md`,
|
|
519128
|
+
title: fileTitle,
|
|
519129
|
+
markdown: `# ${fileTitle}
|
|
518921
519130
|
|
|
518922
519131
|
${body}`
|
|
518923
519132
|
});
|
|
@@ -518930,13 +519139,27 @@ async function parseEpubFlat(buf) {
|
|
|
518930
519139
|
const book = await parseEpub(buf);
|
|
518931
519140
|
return book.chapters.map((c) => c.markdown.replace(/^# /gm, "## ")).join("\n\n");
|
|
518932
519141
|
}
|
|
518933
|
-
var decoder;
|
|
519142
|
+
var decoder, CH_HEADING, LETTER_HEADING, ROMAN_HEADING, NUM_HEADING, romanValue;
|
|
518934
519143
|
var init_epub_parser = __esm({
|
|
518935
519144
|
"src/main/lib/epub-parser.ts"() {
|
|
518936
519145
|
"use strict";
|
|
518937
519146
|
init_esm2();
|
|
518938
519147
|
init_html_article();
|
|
518939
519148
|
decoder = new TextDecoder("utf-8");
|
|
519149
|
+
CH_HEADING = /^(?:#{1,3}\s*)?(?:CHAPTER|Chapter|chap\.)\s+[IVXLC0-9]{1,7}\b[.:)]?\s*(.*)$/;
|
|
519150
|
+
LETTER_HEADING = /^(?:#{1,3}\s*)?(?:Letter|LETTER)\s+\d{1,3}\b[.:)]?\s*(.*)$/;
|
|
519151
|
+
ROMAN_HEADING = /^(?:#{1,3}\s*)?(?:[—[]\s*)?([IVXLC]{1,7})\s*[—\]]?\.?\s*$/;
|
|
519152
|
+
NUM_HEADING = /^(?:#{1,3}\s*)?[—[]?\s*(\d{1,3})\s*[—\]]?\.?\s*$/;
|
|
519153
|
+
romanValue = (s) => {
|
|
519154
|
+
const vals = { I: 1, V: 5, X: 10, L: 50, C: 100 };
|
|
519155
|
+
let v = 0;
|
|
519156
|
+
for (let i = 0; i < s.length; i++) {
|
|
519157
|
+
const cur = vals[s[i]] ?? 0;
|
|
519158
|
+
const next = vals[s[i + 1]] ?? 0;
|
|
519159
|
+
v += cur < next ? -cur : cur;
|
|
519160
|
+
}
|
|
519161
|
+
return v;
|
|
519162
|
+
};
|
|
518940
519163
|
}
|
|
518941
519164
|
});
|
|
518942
519165
|
|
|
@@ -519488,11 +519711,32 @@ var init_bilibili_wbi = __esm({
|
|
|
519488
519711
|
});
|
|
519489
519712
|
|
|
519490
519713
|
// src/main/services/pure/subtitle-parse.ts
|
|
519714
|
+
function decodeEntities(s) {
|
|
519715
|
+
return s.replace(/&([a-z]+);/gi, (m, name18) => ENTITIES[name18.toLowerCase()] ?? m).replace(/&#(\d+);/g, (m, d) => {
|
|
519716
|
+
try {
|
|
519717
|
+
return String.fromCodePoint(Number(d));
|
|
519718
|
+
} catch {
|
|
519719
|
+
return m;
|
|
519720
|
+
}
|
|
519721
|
+
});
|
|
519722
|
+
}
|
|
519723
|
+
function cjkJoin(parts) {
|
|
519724
|
+
let s = "";
|
|
519725
|
+
for (const p of parts) {
|
|
519726
|
+
if (!s) {
|
|
519727
|
+
s = p;
|
|
519728
|
+
continue;
|
|
519729
|
+
}
|
|
519730
|
+
const last = s[s.length - 1];
|
|
519731
|
+
s += CJKISH.test(last) || CJKISH.test(p[0]) ? p : ` ${p}`;
|
|
519732
|
+
}
|
|
519733
|
+
return s;
|
|
519734
|
+
}
|
|
519491
519735
|
function parseSubtitleToText(raw) {
|
|
519492
519736
|
const lines = raw.replace(/\r\n/g, "\n").split("\n");
|
|
519493
519737
|
const out = [];
|
|
519738
|
+
const recent = [];
|
|
519494
519739
|
let inNote = false;
|
|
519495
|
-
let prev = "";
|
|
519496
519740
|
for (const line of lines) {
|
|
519497
519741
|
const t = line.trim();
|
|
519498
519742
|
if (!t) {
|
|
@@ -519513,21 +519757,56 @@ function parseSubtitleToText(raw) {
|
|
|
519513
519757
|
continue;
|
|
519514
519758
|
if (/^(Kind:|Language:|Style:|Region:|NOTE)/i.test(t))
|
|
519515
519759
|
continue;
|
|
519516
|
-
|
|
519760
|
+
let text3 = t.replace(/<[^>]+>/g, "").trim();
|
|
519517
519761
|
if (!text3)
|
|
519518
519762
|
continue;
|
|
519519
|
-
if (text3
|
|
519763
|
+
if (AUTO_MARKERS.test(text3))
|
|
519764
|
+
continue;
|
|
519765
|
+
text3 = decodeEntities(text3);
|
|
519766
|
+
if (recent.includes(text3))
|
|
519520
519767
|
continue;
|
|
519521
|
-
|
|
519522
|
-
|
|
519768
|
+
recent.push(text3);
|
|
519769
|
+
if (recent.length > 2)
|
|
519770
|
+
recent.shift();
|
|
519771
|
+
const spoken = text3.replace(/^>{2,}\s*/, "").trim();
|
|
519772
|
+
if (spoken)
|
|
519773
|
+
out.push(spoken);
|
|
519774
|
+
}
|
|
519775
|
+
return cjkJoin(out).replace(/\s+/g, " ").trim();
|
|
519776
|
+
}
|
|
519777
|
+
function pickSubtitleFile(names) {
|
|
519778
|
+
const rank = (n) => {
|
|
519779
|
+
const m = n.toLowerCase().match(/^sub\.(.+)\.(vtt|srt)$/);
|
|
519780
|
+
if (!m)
|
|
519781
|
+
return 99;
|
|
519782
|
+
const lang = m[1];
|
|
519783
|
+
if (lang === "zh-hans" || lang === "zh-cn" || lang.startsWith("zh-hans") || lang.startsWith("zh-cn"))
|
|
519784
|
+
return 0;
|
|
519785
|
+
if (lang === "zh" || lang.startsWith("zh"))
|
|
519786
|
+
return 1;
|
|
519787
|
+
if (lang === "en" || lang.startsWith("en"))
|
|
519788
|
+
return 2;
|
|
519789
|
+
return 3;
|
|
519790
|
+
};
|
|
519791
|
+
let best = null;
|
|
519792
|
+
let bestRank = 99;
|
|
519793
|
+
for (const n of names) {
|
|
519794
|
+
const r = rank(n);
|
|
519795
|
+
if (r < bestRank) {
|
|
519796
|
+
best = n;
|
|
519797
|
+
bestRank = r;
|
|
519798
|
+
}
|
|
519523
519799
|
}
|
|
519524
|
-
return
|
|
519800
|
+
return bestRank <= 3 ? best : null;
|
|
519525
519801
|
}
|
|
519526
|
-
var CUE_TIMING;
|
|
519802
|
+
var CUE_TIMING, AUTO_MARKERS, ENTITIES, CJKISH;
|
|
519527
519803
|
var init_subtitle_parse = __esm({
|
|
519528
519804
|
"src/main/services/pure/subtitle-parse.ts"() {
|
|
519529
519805
|
"use strict";
|
|
519530
519806
|
CUE_TIMING = /^\d{1,2}:\d{2}(?::\d{2})?[.,]\d{3}\s*-->/;
|
|
519807
|
+
AUTO_MARKERS = /^\[(music|applause|laughter|laughs?|silence|inaudible|cheering|foreign|blank[_\s]?audio|music playing|noise)\]$/i;
|
|
519808
|
+
ENTITIES = { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'", nbsp: " " };
|
|
519809
|
+
CJKISH = /[\u3000-\u303f\u4e00-\u9fff\uff00-\uffef]/;
|
|
519531
519810
|
}
|
|
519532
519811
|
});
|
|
519533
519812
|
|
|
@@ -519669,7 +519948,7 @@ async function fetchViaYtDlp(url2, dataDir, onProgress, signal) {
|
|
|
519669
519948
|
"--no-warnings",
|
|
519670
519949
|
url2
|
|
519671
519950
|
], signal);
|
|
519672
|
-
const subFile = (0, import_node_fs6.readdirSync)(workDir)
|
|
519951
|
+
const subFile = pickSubtitleFile((0, import_node_fs6.readdirSync)(workDir));
|
|
519673
519952
|
if (subFile) {
|
|
519674
519953
|
const text3 = parseSubtitleToText((0, import_node_fs6.readFileSync)((0, import_node_path6.join)(workDir, subFile), "utf8"));
|
|
519675
519954
|
if (text3.length > 50) {
|
|
@@ -555090,9 +555369,10 @@ async function handleAgentChat(win, nodeId, userMessage, locale) {
|
|
|
555090
555369
|
onProposalCreated: (id, summary) => {
|
|
555091
555370
|
win?.send("chat:proposal", id, summary, "pending");
|
|
555092
555371
|
},
|
|
555093
|
-
onError: (msg) => win?.send("chat:error", msg),
|
|
555372
|
+
onError: (msg) => win?.send("chat:error", msg, nodeId),
|
|
555094
555373
|
// v0.2 parts 协议:把 reasoning/tool-start/tool-result/tool-error 透传给渲染层
|
|
555095
|
-
|
|
555374
|
+
// (v0.23 第二参带会话标识,旧接口用 nodeId 充当;第三参同)
|
|
555375
|
+
onPart: (part) => win?.send("chat:part", part, nodeId, nodeId)
|
|
555096
555376
|
},
|
|
555097
555377
|
controller.signal,
|
|
555098
555378
|
locale
|
|
@@ -555101,7 +555381,7 @@ async function handleAgentChat(win, nodeId, userMessage, locale) {
|
|
|
555101
555381
|
history2.push({ role: "assistant", content: reply });
|
|
555102
555382
|
saveChatHistory(db, nodeId, history2);
|
|
555103
555383
|
markDirty();
|
|
555104
|
-
win?.send("chat:done", reply, {});
|
|
555384
|
+
win?.send("chat:done", reply, {}, nodeId);
|
|
555105
555385
|
return reply;
|
|
555106
555386
|
}
|
|
555107
555387
|
function abortAgentChat(nodeId) {
|
|
@@ -555205,8 +555485,9 @@ ${s}` : s;
|
|
|
555205
555485
|
onProposalCreated: (id, summary) => {
|
|
555206
555486
|
win?.send("chat:proposal", id, summary, "pending");
|
|
555207
555487
|
},
|
|
555208
|
-
onError: (msg) => win?.send("chat:error", msg),
|
|
555209
|
-
|
|
555488
|
+
onError: (msg) => win?.send("chat:error", msg, threadId),
|
|
555489
|
+
// v0.23: part 带 threadId(渲染层按 thread 分发)+focusNodeId(地图球后台指示)
|
|
555490
|
+
onPart: (part) => win?.send("chat:part", part, threadId, focusNodeId)
|
|
555210
555491
|
},
|
|
555211
555492
|
controller.signal,
|
|
555212
555493
|
locale,
|
|
@@ -555223,7 +555504,7 @@ ${s}` : s;
|
|
|
555223
555504
|
win?.send("chat:done", reply, {
|
|
555224
555505
|
userMessageId: savedUserMsg.id,
|
|
555225
555506
|
assistantMessageId: savedAssistantMsg.id
|
|
555226
|
-
});
|
|
555507
|
+
}, threadId);
|
|
555227
555508
|
return reply;
|
|
555228
555509
|
}
|
|
555229
555510
|
function abortAgentChatThread(threadId) {
|
|
@@ -557897,7 +558178,7 @@ function loadSeedData() {
|
|
|
557897
558178
|
);
|
|
557898
558179
|
}
|
|
557899
558180
|
var SEED_DATA = loadSeedData();
|
|
557900
|
-
var SEED_VERSION =
|
|
558181
|
+
var SEED_VERSION = 14;
|
|
557901
558182
|
function ensureSeedCourse() {
|
|
557902
558183
|
const result = applySeedData(getDb(), SEED_DATA, SEED_VERSION);
|
|
557903
558184
|
if (!result.skipped)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r,j as h}from"./index-
|
|
1
|
+
import{r,j as h}from"./index-xynt7zMk.js";import{c as T,u as L,P as D}from"./main-CGE6fm01.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-xynt7zMk.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-CGE6fm01.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-xynt7zMk.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-CGE6fm01.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,k as U,j as e,c as ie}from"./index-
|
|
1
|
+
import{r as o,k as U,j as e,c as ie}from"./index-xynt7zMk.js";import{c as te,u as ce,a as j,l as de,T as z,p as Y,L as V,k as oe,X as xe}from"./main-CGE6fm01.js";import{R as G}from"./rotate-ccw-natFwqj6.js";import{A as q}from"./arrow-right-D4GV0Gpo.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-DkjixD09.js","./index-CU6ublfJ.js","./index-xynt7zMk.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-CGE6fm01.js";import{r as o,j as a}from"./index-xynt7zMk.js";import{C as w}from"./CanvasStage-Ba-21anG.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-DkjixD09.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-xynt7zMk.js";import{u as y,a as j,S as M}from"./main-CGE6fm01.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};
|