md-task-viewer 0.1.8 → 0.1.9

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.
@@ -1 +1 @@
1
- :root{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--bg:#0a0e14;--bg-strong:#0d1117;--panel:#131920;--panel-border:#21262d;--text:#e6edf3;--muted:#7d8590;--accent:#3fb950;--accent-strong:#2ea043;--danger:#f85149;--shadow:0 2px 8px #0006;color:var(--text);background:var(--bg);font-family:JetBrains Mono,IBM Plex Mono,Fira Code,SF Mono,Cascadia Code,monospace;line-height:1.6}*{box-sizing:border-box}body{height:100vh;margin:0;overflow:hidden}#root{height:100vh;overflow:hidden}button,input,select,textarea{font:inherit}button{cursor:pointer}.app-shell{flex-direction:column;gap:12px;height:100vh;padding:12px 16px 16px;display:flex;overflow:hidden}.app-header{border-bottom:1px solid var(--panel-border);flex-shrink:0;justify-content:space-between;align-items:center;gap:16px;padding-bottom:12px;display:flex}.app-header-left{align-items:baseline;gap:12px;min-width:0;display:flex}.app-header h1{letter-spacing:-.02em;white-space:nowrap;color:var(--accent);margin:0;font-family:inherit;font-size:1.1rem;font-weight:700;line-height:1.2}.app-header h1:before{content:"> ";color:var(--muted)}.eyebrow{color:var(--muted);text-transform:uppercase;letter-spacing:.12em;white-space:nowrap;margin:0;font-size:.65rem;font-weight:600}.layout-grid{background:var(--panel-border);flex:1;grid-template-columns:minmax(260px,320px) minmax(0,1fr);gap:1px;min-height:0;display:grid}.panel{background:var(--panel);border:none;border-radius:0;flex-direction:column;min-height:0;padding:14px 16px;display:flex;overflow:hidden}.panel-header{border-bottom:1px solid var(--panel-border);flex-shrink:0;justify-content:space-between;align-items:center;gap:12px;margin-bottom:12px;padding-bottom:8px;display:flex}.panel-header h2{letter-spacing:.04em;text-transform:uppercase;color:var(--muted);margin:0;font-family:inherit;font-size:.85rem;font-weight:700}.panel-header span{color:var(--muted);font-size:.75rem}.panel-header-right{align-items:center;gap:12px;display:flex}.filter-toggle{cursor:pointer;-webkit-user-select:none;user-select:none;align-items:center;gap:4px;display:flex}.filter-toggle input[type=checkbox]{accent-color:var(--accent);cursor:pointer}.sidebar-scroll{flex:1;min-height:0;margin:0 -4px;padding:0 4px;overflow-y:auto}.sidebar-scroll::-webkit-scrollbar{width:4px}.sidebar-scroll::-webkit-scrollbar-track{background:0 0}.sidebar-scroll::-webkit-scrollbar-thumb{background:var(--panel-border);border-radius:0}.task-list{gap:2px;display:grid}.empty-list{border:1px dashed var(--panel-border);color:var(--muted);background:#ffffff08;border-radius:0;margin:0;padding:14px;font-size:.82rem}.task-row{text-align:left;background:#ffffff05;border:1px solid #0000;border-left-width:2px;border-radius:0;gap:3px;width:100%;padding:8px 10px;transition:background .1s,border-color .1s;display:grid}.task-row:hover{border-left-color:var(--muted);background:#ffffff0d}.task-row-selected{border-left-color:var(--accent);border-color:#3fb95026;border-left-color:var(--accent);background:#3fb9500f}.task-row-badges{align-items:center;gap:6px;display:flex}.task-row strong{font-size:.82rem;font-weight:600;line-height:1.3}.task-row small{color:var(--muted);font-size:.72rem}.badge{letter-spacing:.06em;text-transform:uppercase;border:1px solid;border-radius:0;justify-content:center;width:fit-content;padding:1px 6px;font-size:.6rem;font-weight:700;display:inline-flex}.badge-must{color:#f85149;background:#f851491a;border-color:#f851494d}.badge-want{color:#3fb950;background:#3fb9501a;border-color:#3fb9504d}.badge-todo{color:#58a6ff;background:#58a6ff1a;border-color:#58a6ff4d}.badge-wip{color:#d29922;background:#d299221a;border-color:#d299224d}.badge-done{color:#2ea043;background:#3fb95014;border-color:#2ea0434d}.editor-panel{overflow:hidden}.editor-scroll{flex:1;min-height:0;margin:0 -4px;padding:0 4px;overflow-y:auto}.editor-scroll::-webkit-scrollbar{width:4px}.editor-scroll::-webkit-scrollbar-track{background:0 0}.editor-scroll::-webkit-scrollbar-thumb{background:var(--panel-border);border-radius:0}.task-form{flex-direction:column;gap:12px;height:100%;display:flex}.task-form label{gap:4px;display:grid}.task-form span{color:var(--muted);text-transform:uppercase;letter-spacing:.08em;font-size:.72rem;font-weight:600}.task-form input,.task-form select,.task-form textarea{border:1px solid var(--panel-border);background:var(--bg);width:100%;color:var(--text);border-radius:0;padding:7px 10px;font-size:.88rem;transition:border-color .1s}.task-form input:focus,.task-form select:focus,.task-form textarea:focus{border-color:var(--accent);outline:none}.task-form textarea{resize:none;flex:1;min-height:120px}.editor-label{flex-direction:column;flex:1;min-height:0;display:flex!important}.editor-label-header{align-items:center;gap:8px;display:flex}.editor-label-header .body-fullheight-button.ghost-button{align-items:center;gap:4px;padding:1px 6px;font-size:.65rem;line-height:1;display:inline-flex}.markdown-preview{border:1px solid var(--panel-border);background:var(--bg);border-radius:6px;flex:1;min-height:120px;padding:8px 12px;font-size:.85rem;line-height:1.6;overflow-y:auto}.markdown-preview h1,.markdown-preview h2,.markdown-preview h3,.markdown-preview h4,.markdown-preview h5,.markdown-preview h6{margin-top:1em;margin-bottom:.5em;line-height:1.3}.markdown-preview h1{font-size:1.4em}.markdown-preview h2{font-size:1.2em}.markdown-preview h3{font-size:1.05em}.markdown-preview p{margin:.5em 0}.markdown-preview ul,.markdown-preview ol{margin:.5em 0;padding-left:1.5em}.markdown-preview li{margin:.25em 0}.markdown-preview li>input[type=checkbox]{pointer-events:none;margin-right:.4em}.markdown-preview code{background:var(--panel-border);border-radius:3px;padding:.15em .4em;font-size:.9em}.markdown-preview pre{background:var(--panel-border);border-radius:6px;margin:.5em 0;padding:.75em 1em;overflow-x:auto}.markdown-preview pre code{background:0 0;padding:0}.markdown-preview blockquote{border-left:3px solid var(--accent);color:var(--muted);margin:.5em 0;padding:.25em .75em}.markdown-preview hr{border:none;border-top:1px solid var(--panel-border);margin:1em 0}.markdown-preview table{border-collapse:collapse;width:100%;margin:.5em 0}.markdown-preview th,.markdown-preview td{border:1px solid var(--panel-border);text-align:left;padding:.4em .75em}.markdown-preview th{background:var(--panel-border)}.markdown-preview a{color:var(--accent)}.markdown-preview img{max-width:100%}.field-row{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;display:grid}.field-row-top{border-bottom:1px solid var(--panel-border);padding-bottom:12px}.meta-strip{color:var(--muted);gap:16px;font-size:.72rem;display:flex}.form-actions{flex-shrink:0;gap:8px;padding-top:4px;display:flex}.primary-button,.danger-button,.ghost-button{letter-spacing:.03em;text-transform:uppercase;border:1px solid;border-radius:0;padding:6px 14px;font-size:.8rem;font-weight:700;transition:background .1s,color .1s}.primary-button{color:var(--bg);background:var(--accent);border-color:var(--accent)}.primary-button:hover{background:var(--accent-strong);border-color:var(--accent-strong)}.danger-button{color:var(--danger);background:#f851491a;border-color:#f8514966}.danger-button:hover{background:#f8514933}.ghost-button{color:var(--muted);border-color:var(--panel-border);background:0 0}.ghost-button:hover{color:var(--text);border-color:var(--muted);background:#ffffff0d}.primary-button:active,.danger-button:active,.ghost-button:active{transform:scale(.98)}.primary-button:disabled,.danger-button:disabled{opacity:.4;cursor:not-allowed}.dirty-state{color:var(--accent);white-space:nowrap;font-size:.72rem;font-weight:700}.notice{color:var(--accent);flex-shrink:0;height:1.5rem;margin:0;padding-top:6px;font-size:.8rem}.empty-editor{color:var(--muted);flex:1;place-items:center;font-size:.85rem;display:grid}.empty-editor p{margin:0}.error-panel{background:#f8514914;border:1px solid #f8514933;border-radius:0;flex-shrink:0;margin-top:12px;padding:10px 12px}.error-panel h3{color:var(--danger);margin:0;font-family:inherit;font-size:.82rem}.error-panel p{margin:8px 0 0;font-size:.78rem;display:grid}.app-header-actions{align-items:center;gap:8px;display:flex}.settings-button{color:var(--muted);background:0 0;border:1px solid #0000;justify-content:center;align-items:center;padding:6px;transition:color .1s,border-color .1s;display:inline-flex}.settings-button:hover{color:var(--text);border-color:var(--panel-border)}.settings-overlay{z-index:100;background:#0009;place-items:center;display:grid;position:fixed;inset:0}.settings-modal{background:var(--panel);border:1px solid var(--panel-border);box-shadow:var(--shadow);border-radius:0;flex-direction:column;gap:16px;width:90%;max-width:480px;padding:20px;display:flex}.settings-body{flex-direction:column;gap:10px;display:flex}.settings-label{color:var(--muted);text-transform:uppercase;letter-spacing:.08em;font-size:.75rem;font-weight:600}.settings-hint{color:var(--muted);margin-top:2px;font-size:.72rem;display:block}.settings-dir-list{flex-direction:column;gap:6px;display:flex}.settings-dir-row{align-items:center;gap:6px;display:flex}.settings-dir-row input{border:1px solid var(--panel-border);background:var(--bg);color:var(--text);border-radius:0;flex:1;padding:7px 10px;font-size:.88rem;transition:border-color .1s}.settings-dir-row input:focus{border-color:var(--accent);outline:none}.settings-remove-button{color:var(--muted);flex-shrink:0;padding:6px!important}.settings-remove-button:disabled{opacity:.3;cursor:not-allowed}.tab-bar{border-bottom:1px solid var(--panel-border);flex-shrink:0;gap:0;margin-bottom:12px;display:flex}.tab-button{color:var(--muted);letter-spacing:.06em;text-transform:uppercase;cursor:pointer;background:0 0;border:none;border-bottom:2px solid #0000;border-radius:0;padding:6px 16px;font-size:.75rem;font-weight:700;transition:color .1s,border-color .1s}.tab-button:hover{color:var(--text)}.tab-button.active{color:var(--accent);border-bottom-color:var(--accent)}.execute-panel{flex-direction:column;gap:12px;height:100%;display:flex}.execute-commands{flex-direction:column;gap:6px;display:flex}.execute-command-item{background:var(--bg);border:1px solid var(--panel-border);align-items:center;gap:8px;padding:6px 10px;font-size:.82rem;display:flex}.execute-command-item .command-index{color:var(--muted);flex-shrink:0;font-size:.72rem;font-weight:700}.execute-command-item code{word-break:break-all;flex:1}.execute-command-item .pass-body-badge{color:var(--accent);text-transform:uppercase;border:1px solid #3fb9504d;flex-shrink:0;padding:1px 4px;font-size:.6rem;font-weight:700}.execute-no-commands{color:var(--muted);border:1px dashed var(--panel-border);padding:14px;font-size:.82rem}.execution-result{flex-direction:column;flex:1;gap:8px;min-height:0;display:flex}.execution-result-header{flex-shrink:0;justify-content:space-between;align-items:center;display:flex}.execution-result-meta{color:var(--muted);gap:12px;font-size:.72rem;display:flex}.execution-result-meta .exit-code-error{color:var(--danger)}.execution-result pre{background:var(--bg);border:1px solid var(--panel-border);color:var(--text);white-space:pre-wrap;word-break:break-all;flex:1;min-height:80px;margin:0;padding:10px 12px;font-size:.82rem;line-height:1.5;overflow:auto}.execution-stderr{color:var(--danger)!important;border-color:#f851494d!important}.copy-button{padding:4px 10px!important;font-size:.7rem!important}.collapsible-header{color:var(--muted);letter-spacing:.06em;text-transform:uppercase;cursor:pointer;text-align:left;background:0 0;border:none;align-items:center;gap:6px;width:100%;padding:6px 0;font-size:.75rem;font-weight:700;display:flex}.collapsible-header:hover{color:var(--text)}.collapsible-chevron{font-size:.6rem;transition:transform .15s;display:inline-block}.collapsible-chevron.open{transform:rotate(90deg)}.collapsible-body{flex-direction:column;gap:8px;padding:8px 0;display:flex}.command-step-row{align-items:center;gap:6px;display:flex}.command-step-row input,.task-form .command-step-row input{border:1px solid var(--panel-border);background:var(--bg);width:auto;min-width:0;color:var(--text);border-radius:0;flex:1;padding:7px 10px;font-size:.82rem;transition:border-color .1s}.command-step-row input:focus,.task-form .command-step-row input:focus{border-color:var(--accent);outline:none}.command-step-row select,.task-form .command-step-row select{border:1px solid var(--panel-border);background:var(--bg);width:auto;min-width:0;color:var(--text);border-radius:0;flex-shrink:0;padding:7px 6px;font-size:.75rem}.command-step-row select:focus,.task-form .command-step-row select:focus{border-color:var(--accent);outline:none}@media (width<=900px){.app-shell{height:auto;min-height:100vh;padding:10px;overflow:auto}body,#root{height:auto;overflow:auto}.layout-grid{flex:none;grid-template-columns:1fr}.panel{min-height:auto;max-height:none;overflow:visible}.sidebar-scroll,.editor-scroll{max-height:none;overflow:visible}.app-header{flex-direction:column;align-items:stretch;gap:10px}.app-header-left{flex-direction:column;gap:4px}.field-row{grid-template-columns:1fr}.task-form textarea,.markdown-preview{flex:none;min-height:200px}}
1
+ :root{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--bg:#0a0e14;--bg-strong:#0d1117;--panel:#131920;--panel-border:#21262d;--text:#e6edf3;--muted:#7d8590;--accent:#3fb950;--accent-strong:#2ea043;--danger:#f85149;--shadow:0 2px 8px #0006;color:var(--text);background:var(--bg);font-family:JetBrains Mono,IBM Plex Mono,Fira Code,SF Mono,Cascadia Code,monospace;line-height:1.6}*{box-sizing:border-box}body{height:100vh;margin:0;overflow:hidden}#root{height:100vh;overflow:hidden}button,input,select,textarea{font:inherit}button{cursor:pointer}.app-shell{flex-direction:column;gap:12px;height:100vh;padding:12px 16px 16px;display:flex;overflow:hidden}.app-header{border-bottom:1px solid var(--panel-border);flex-shrink:0;justify-content:space-between;align-items:center;gap:16px;padding-bottom:12px;display:flex}.app-header-left{align-items:baseline;gap:12px;min-width:0;display:flex}.app-header h1{letter-spacing:-.02em;white-space:nowrap;color:var(--accent);margin:0;font-family:inherit;font-size:1.1rem;font-weight:700;line-height:1.2}.app-header h1:before{content:"> ";color:var(--muted)}.eyebrow{color:var(--muted);text-transform:uppercase;letter-spacing:.12em;white-space:nowrap;margin:0;font-size:.65rem;font-weight:600}.layout-grid{background:var(--panel-border);flex:1;grid-template-columns:minmax(260px,320px) minmax(0,1fr);gap:1px;min-height:0;display:grid}.panel{background:var(--panel);border:none;border-radius:0;flex-direction:column;min-height:0;padding:14px 16px;display:flex;overflow:hidden}.panel-header{border-bottom:1px solid var(--panel-border);flex-shrink:0;justify-content:space-between;align-items:center;gap:12px;margin-bottom:12px;padding-bottom:8px;display:flex}.panel-header h2{letter-spacing:.04em;text-transform:uppercase;color:var(--muted);margin:0;font-family:inherit;font-size:.85rem;font-weight:700}.panel-header span{color:var(--muted);font-size:.75rem}.panel-header-right{align-items:center;gap:12px;display:flex}.filter-toggle{cursor:pointer;-webkit-user-select:none;user-select:none;align-items:center;gap:4px;display:flex}.filter-toggle input[type=checkbox]{accent-color:var(--accent);cursor:pointer}.sidebar-scroll{flex:1;min-height:0;margin:0 -4px;padding:0 4px;overflow-y:auto}.sidebar-scroll::-webkit-scrollbar{width:4px}.sidebar-scroll::-webkit-scrollbar-track{background:0 0}.sidebar-scroll::-webkit-scrollbar-thumb{background:var(--panel-border);border-radius:0}.task-list{gap:2px;display:grid}.empty-list{border:1px dashed var(--panel-border);color:var(--muted);background:#ffffff08;border-radius:0;margin:0;padding:14px;font-size:.82rem}.task-row{text-align:left;background:#ffffff05;border:1px solid #0000;border-left-width:2px;border-radius:0;gap:3px;width:100%;padding:8px 10px;transition:background .1s,border-color .1s;display:grid}.task-row:hover{border-left-color:var(--muted);background:#ffffff0d}.task-row-selected{border-left-color:var(--accent);border-color:#3fb95026;border-left-color:var(--accent);background:#3fb9500f}.task-row-badges{align-items:center;gap:6px;display:flex}.task-row strong{font-size:.82rem;font-weight:600;line-height:1.3}.task-row small{color:var(--muted);font-size:.72rem}.badge{letter-spacing:.06em;text-transform:uppercase;border:1px solid;border-radius:0;justify-content:center;width:fit-content;padding:1px 6px;font-size:.6rem;font-weight:700;display:inline-flex}.badge-must{color:#f85149;background:#f851491a;border-color:#f851494d}.badge-want{color:#3fb950;background:#3fb9501a;border-color:#3fb9504d}.badge-todo{color:#58a6ff;background:#58a6ff1a;border-color:#58a6ff4d}.badge-wip{color:#d29922;background:#d299221a;border-color:#d299224d}.badge-done{color:#2ea043;background:#3fb95014;border-color:#2ea0434d}.editor-panel{overflow:hidden}.editor-scroll{flex:1;min-height:0;margin:0 -4px;padding:0 4px;overflow-y:auto}.editor-scroll::-webkit-scrollbar{width:4px}.editor-scroll::-webkit-scrollbar-track{background:0 0}.editor-scroll::-webkit-scrollbar-thumb{background:var(--panel-border);border-radius:0}.task-form{flex-direction:column;gap:12px;height:100%;display:flex}.task-form label{gap:4px;display:grid}.task-form span{color:var(--muted);text-transform:uppercase;letter-spacing:.08em;font-size:.72rem;font-weight:600}.task-form input,.task-form select,.task-form textarea{border:1px solid var(--panel-border);background:var(--bg);width:100%;color:var(--text);border-radius:0;padding:7px 10px;font-size:.88rem;transition:border-color .1s}.task-form input:focus,.task-form select:focus,.task-form textarea:focus{border-color:var(--accent);outline:none}.task-form textarea{resize:none;flex:1;min-height:120px}.editor-label{flex-direction:column;flex:1;min-height:0;display:flex!important}.editor-label-header{align-items:center;gap:8px;display:flex}.editor-label-header .body-fullheight-button.ghost-button{align-items:center;gap:4px;padding:1px 6px;font-size:.65rem;line-height:1;display:inline-flex}.markdown-preview{border:1px solid var(--panel-border);background:var(--bg);border-radius:6px;flex:1;min-height:120px;padding:8px 12px;font-size:.85rem;line-height:1.6;overflow-y:auto}.markdown-preview h1,.markdown-preview h2,.markdown-preview h3,.markdown-preview h4,.markdown-preview h5,.markdown-preview h6{margin-top:1em;margin-bottom:.5em;line-height:1.3}.markdown-preview h1{font-size:1.4em}.markdown-preview h2{font-size:1.2em}.markdown-preview h3{font-size:1.05em}.markdown-preview p{margin:.5em 0}.markdown-preview ul,.markdown-preview ol{margin:.5em 0;padding-left:1.5em}.markdown-preview li{margin:.25em 0}.markdown-preview li>input[type=checkbox]{pointer-events:none;margin-right:.4em}.markdown-preview code{background:var(--panel-border);border-radius:3px;padding:.15em .4em;font-size:.9em}.markdown-preview pre{background:var(--panel-border);border-radius:6px;margin:.5em 0;padding:.75em 1em;overflow-x:auto}.markdown-preview pre code{background:0 0;padding:0}.markdown-preview blockquote{border-left:3px solid var(--accent);color:var(--muted);margin:.5em 0;padding:.25em .75em}.markdown-preview hr{border:none;border-top:1px solid var(--panel-border);margin:1em 0}.markdown-preview table{border-collapse:collapse;width:100%;margin:.5em 0}.markdown-preview th,.markdown-preview td{border:1px solid var(--panel-border);text-align:left;padding:.4em .75em}.markdown-preview th{background:var(--panel-border)}.markdown-preview a{color:var(--accent)}.markdown-preview img{max-width:100%}.field-row{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;display:grid}.field-row-top{border-bottom:1px solid var(--panel-border);padding-bottom:12px}.meta-strip{color:var(--muted);gap:16px;font-size:.72rem;display:flex}.form-actions{flex-shrink:0;gap:8px;padding-top:4px;display:flex}.primary-button,.danger-button,.ghost-button{letter-spacing:.03em;text-transform:uppercase;border:1px solid;border-radius:0;padding:6px 14px;font-size:.8rem;font-weight:700;transition:background .1s,color .1s}.primary-button{color:var(--bg);background:var(--accent);border-color:var(--accent)}.primary-button:hover{background:var(--accent-strong);border-color:var(--accent-strong)}.danger-button{color:var(--danger);background:#f851491a;border-color:#f8514966}.danger-button:hover{background:#f8514933}.ghost-button{color:var(--muted);border-color:var(--panel-border);background:0 0}.ghost-button:hover{color:var(--text);border-color:var(--muted);background:#ffffff0d}.primary-button:active,.danger-button:active,.ghost-button:active{transform:scale(.98)}.primary-button:disabled,.danger-button:disabled{opacity:.4;cursor:not-allowed}.dirty-state{color:var(--accent);white-space:nowrap;font-size:.72rem;font-weight:700}.notice{color:var(--accent);flex-shrink:0;align-items:center;gap:6px;min-height:1.5rem;margin:0;padding-top:6px;font-size:.8rem;display:flex}.notice--success{color:var(--accent)}.notice--error{color:var(--danger);background:#f851491a;border:1px solid #f8514966;border-radius:4px;margin-top:6px;padding:6px 10px;font-weight:600}.notice-icon{background:var(--danger);width:1.1rem;height:1.1rem;color:var(--bg);border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;font-size:.75rem;font-weight:700;display:inline-flex}.empty-editor{color:var(--muted);flex:1;place-items:center;font-size:.85rem;display:grid}.empty-editor p{margin:0}.error-panel{background:#f8514914;border:1px solid #f8514933;border-radius:0;flex-shrink:0;margin-top:12px;padding:10px 12px}.error-panel h3{color:var(--danger);margin:0;font-family:inherit;font-size:.82rem}.error-panel p{margin:8px 0 0;font-size:.78rem;display:grid}.app-header-actions{align-items:center;gap:8px;display:flex}.settings-button{color:var(--muted);background:0 0;border:1px solid #0000;justify-content:center;align-items:center;padding:6px;transition:color .1s,border-color .1s;display:inline-flex}.settings-button:hover{color:var(--text);border-color:var(--panel-border)}.settings-overlay{z-index:100;background:#0009;place-items:center;display:grid;position:fixed;inset:0}.settings-modal{background:var(--panel);border:1px solid var(--panel-border);box-shadow:var(--shadow);border-radius:0;flex-direction:column;gap:16px;width:90%;max-width:480px;padding:20px;display:flex}.settings-body{flex-direction:column;gap:10px;display:flex}.settings-label{color:var(--muted);text-transform:uppercase;letter-spacing:.08em;font-size:.75rem;font-weight:600}.settings-hint{color:var(--muted);margin-top:2px;font-size:.72rem;display:block}.settings-dir-list{flex-direction:column;gap:6px;display:flex}.settings-dir-row{align-items:center;gap:6px;display:flex}.settings-dir-row input{border:1px solid var(--panel-border);background:var(--bg);color:var(--text);border-radius:0;flex:1;padding:7px 10px;font-size:.88rem;transition:border-color .1s}.settings-dir-row input:focus{border-color:var(--accent);outline:none}.settings-remove-button{color:var(--muted);flex-shrink:0;padding:6px!important}.settings-remove-button:disabled{opacity:.3;cursor:not-allowed}.tab-bar{border-bottom:1px solid var(--panel-border);flex-shrink:0;gap:0;margin-bottom:12px;display:flex}.tab-button{color:var(--muted);letter-spacing:.06em;text-transform:uppercase;cursor:pointer;background:0 0;border:none;border-bottom:2px solid #0000;border-radius:0;padding:6px 16px;font-size:.75rem;font-weight:700;transition:color .1s,border-color .1s}.tab-button:hover{color:var(--text)}.tab-button.active{color:var(--accent);border-bottom-color:var(--accent)}.execute-panel{flex-direction:column;gap:12px;height:100%;display:flex}.execute-commands{flex-direction:column;gap:6px;display:flex}.execute-command-item{background:var(--bg);border:1px solid var(--panel-border);align-items:center;gap:8px;padding:6px 10px;font-size:.82rem;display:flex}.execute-command-item .command-index{color:var(--muted);flex-shrink:0;font-size:.72rem;font-weight:700}.execute-command-item code{word-break:break-all;flex:1}.execute-command-item .pass-body-badge{color:var(--accent);text-transform:uppercase;border:1px solid #3fb9504d;flex-shrink:0;padding:1px 4px;font-size:.6rem;font-weight:700}.execute-no-commands{color:var(--muted);border:1px dashed var(--panel-border);padding:14px;font-size:.82rem}.execution-result{flex-direction:column;flex:1;gap:8px;min-height:0;display:flex}.execution-result-header{flex-shrink:0;justify-content:space-between;align-items:center;display:flex}.execution-result-meta{color:var(--muted);gap:12px;font-size:.72rem;display:flex}.execution-result-meta .exit-code-error{color:var(--danger)}.execution-result pre{background:var(--bg);border:1px solid var(--panel-border);color:var(--text);white-space:pre-wrap;word-break:break-all;flex:1;min-height:80px;margin:0;padding:10px 12px;font-size:.82rem;line-height:1.5;overflow:auto}.execution-stderr{color:var(--danger)!important;border-color:#f851494d!important}.copy-button{padding:4px 10px!important;font-size:.7rem!important}.collapsible-header{color:var(--muted);letter-spacing:.06em;text-transform:uppercase;cursor:pointer;text-align:left;background:0 0;border:none;align-items:center;gap:6px;width:100%;padding:6px 0;font-size:.75rem;font-weight:700;display:flex}.collapsible-header:hover{color:var(--text)}.collapsible-chevron{font-size:.6rem;transition:transform .15s;display:inline-block}.collapsible-chevron.open{transform:rotate(90deg)}.collapsible-body{flex-direction:column;gap:8px;padding:8px 0;display:flex}.command-step-row{align-items:center;gap:6px;display:flex}.command-step-row input,.task-form .command-step-row input{border:1px solid var(--panel-border);background:var(--bg);width:auto;min-width:0;color:var(--text);border-radius:0;flex:1;padding:7px 10px;font-size:.82rem;transition:border-color .1s}.command-step-row input:focus,.task-form .command-step-row input:focus{border-color:var(--accent);outline:none}.command-step-row select,.task-form .command-step-row select{border:1px solid var(--panel-border);background:var(--bg);width:auto;min-width:0;color:var(--text);border-radius:0;flex-shrink:0;padding:7px 6px;font-size:.75rem}.command-step-row select:focus,.task-form .command-step-row select:focus{border-color:var(--accent);outline:none}@media (width<=900px){.app-shell{height:auto;min-height:100vh;padding:10px;overflow:auto}body,#root{height:auto;overflow:auto}.layout-grid{flex:none;grid-template-columns:1fr}.panel{min-height:auto;max-height:none;overflow:visible}.sidebar-scroll,.editor-scroll{max-height:none;overflow:visible}.app-header{flex-direction:column;align-items:stretch;gap:10px}.app-header-left{flex-direction:column;gap:4px}.field-row{grid-template-columns:1fr}.task-form textarea,.markdown-preview{flex:none;min-height:200px}}
@@ -4,8 +4,8 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Markdown Task Viewer</title>
7
- <script type="module" crossorigin src="/assets/index-DDUTU9wi.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-BfBV_hRv.css">
7
+ <script type="module" crossorigin src="/assets/index-CczpSlHS.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-u2_Kc4rH.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
package/dist/server.js CHANGED
@@ -279,17 +279,19 @@ async function createTask(rootDir, input) {
279
279
  const now = asUtcISOString(/* @__PURE__ */ new Date());
280
280
  const relativePath = input.path?.trim() ? await ensureDirectoryForFile(rootDir, input.path) : await nextAvailablePath(rootDir, input.directory ?? "", input.title);
281
281
  const absolutePath = path.join(rootDir, relativePath);
282
+ let targetExists = false;
282
283
  try {
283
284
  await fs.access(absolutePath);
285
+ targetExists = true;
284
286
  } catch (error) {
285
287
  const maybeError = error;
286
- if (maybeError.code === "ENOENT") {
287
- } else if (maybeError.code) {
288
+ if (maybeError.code !== "ENOENT") {
288
289
  throw error;
289
- } else {
290
- throw new ValidationError("A task already exists at that path.");
291
290
  }
292
291
  }
292
+ if (targetExists) {
293
+ throw new ValidationError("A task already exists at that path.");
294
+ }
293
295
  const record = {
294
296
  path: relativePath,
295
297
  content: input.content ?? "",
@@ -306,8 +308,9 @@ async function createTask(rootDir, input) {
306
308
  };
307
309
  await fs.mkdir(path.dirname(absolutePath), { recursive: true });
308
310
  await fs.writeFile(absolutePath, serializeTask(record), "utf8");
309
- const current = await listTasks(rootDir);
310
- await saveOrder(rootDir, current.tasks.map((task) => task.path).concat(relativePath));
311
+ const config = await readConfig(rootDir);
312
+ const filteredOrder = config.order.filter((item) => item !== relativePath);
313
+ await saveOrder(rootDir, [relativePath, ...filteredOrder]);
311
314
  return parseTask(rootDir, relativePath);
312
315
  }
313
316
  async function updateTask(rootDir, currentPath, input) {
@@ -329,17 +332,19 @@ async function updateTask(rootDir, currentPath, input) {
329
332
  const nextPath = input.path?.trim() ? await ensureDirectoryForFile(rootDir, input.path) : normalizedCurrentPath;
330
333
  const absoluteNextPath = path.join(rootDir, nextPath);
331
334
  if (nextPath !== normalizedCurrentPath) {
335
+ let targetExists = false;
332
336
  try {
333
337
  await fs.access(absoluteNextPath);
338
+ targetExists = true;
334
339
  } catch (error) {
335
340
  const maybeError = error;
336
- if (maybeError.code === "ENOENT") {
337
- } else if (maybeError.code) {
341
+ if (maybeError.code !== "ENOENT") {
338
342
  throw error;
339
- } else {
340
- throw new ValidationError("A task already exists at the target path.");
341
343
  }
342
344
  }
345
+ if (targetExists) {
346
+ throw new ValidationError("A task already exists at the target path.");
347
+ }
343
348
  }
344
349
  const record = {
345
350
  path: nextPath,
@@ -546,7 +551,7 @@ function sendJsonError(reply, error) {
546
551
  reply.code(500).send({ error: error instanceof Error ? error.message : "Internal server error" });
547
552
  }
548
553
  async function createServer(options) {
549
- const app = Fastify({ logger: false });
554
+ const app = Fastify({ logger: false, forceCloseConnections: true });
550
555
  const listeners = /* @__PURE__ */ new Set();
551
556
  const clientDir = resolveClientDir(options.clientDir);
552
557
  app.addHook("onClose", async () => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts","../src/taskStore.ts","../src/types.ts","../src/slugify.ts","../src/commandExecutor.ts"],"sourcesContent":["import Fastify, { type FastifyInstance } from \"fastify\";\nimport fastifyStatic from \"@fastify/static\";\nimport chokidar from \"chokidar\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n ConflictError,\n ValidationError,\n createTask,\n deleteTask,\n listTasks,\n parseOrderPayload,\n parseTask,\n patchTaskFields,\n readConfig,\n saveConfig,\n saveOrder,\n updateTask\n} from \"./taskStore.js\";\nimport type { CommandStep } from \"./types.js\";\nimport { executeCommandPipeline } from \"./commandExecutor.js\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nexport interface CreateServerOptions {\n rootDir: string;\n clientDir?: string | null;\n}\n\nfunction resolveClientDir(explicitClientDir?: string | null): string | null {\n if (explicitClientDir === null) {\n return null;\n }\n if (explicitClientDir) {\n return explicitClientDir;\n }\n return path.resolve(__dirname, \"client\");\n}\n\nfunction sendJsonError(reply: { code: (statusCode: number) => { send: (payload: unknown) => void } }, error: unknown): void {\n if (error instanceof ValidationError) {\n reply.code(400).send({ error: error.message });\n return;\n }\n if (error instanceof ConflictError) {\n reply.code(409).send({ error: error.message });\n return;\n }\n reply.code(500).send({ error: error instanceof Error ? error.message : \"Internal server error\" });\n}\n\nexport async function createServer(options: CreateServerOptions): Promise<FastifyInstance> {\n const app = Fastify({ logger: false });\n const listeners = new Set<{ send: (payload: string) => void; close: () => void }>();\n const clientDir = resolveClientDir(options.clientDir);\n\n app.addHook(\"onClose\", async () => {\n for (const listener of listeners) {\n listener.close();\n }\n });\n\n app.get(\"/api/tasks\", async () => listTasks(options.rootDir));\n\n app.post(\"/api/tasks\", async (request, reply) => {\n try {\n const task = await createTask(options.rootDir, (request.body ?? {}) as never);\n return reply.code(201).send(task);\n } catch (error) {\n sendJsonError(reply, error);\n }\n });\n\n app.patch(\"/api/tasks/*\", async (request, reply) => {\n const currentPath = decodeURIComponent((request.params as { \"*\": string })[\"*\"] ?? \"\");\n try {\n const task = await updateTask(options.rootDir, currentPath, (request.body ?? {}) as never);\n return reply.send(task);\n } catch (error) {\n sendJsonError(reply, error);\n }\n });\n\n app.delete(\"/api/tasks/*\", async (request, reply) => {\n const currentPath = decodeURIComponent((request.params as { \"*\": string })[\"*\"] ?? \"\");\n try {\n await deleteTask(options.rootDir, currentPath);\n return reply.code(204).send();\n } catch (error) {\n sendJsonError(reply, error);\n }\n });\n\n app.patch(\"/api/task-fields/*\", async (request, reply) => {\n const currentPath = decodeURIComponent((request.params as { \"*\": string })[\"*\"] ?? \"\");\n try {\n const task = await patchTaskFields(options.rootDir, currentPath, (request.body ?? {}) as never);\n return reply.send(task);\n } catch (error) {\n sendJsonError(reply, error);\n }\n });\n\n app.put(\"/api/order\", async (request, reply) => {\n try {\n const order = parseOrderPayload((request.body as { order?: unknown } | null)?.order ?? []);\n await saveOrder(options.rootDir, order);\n return reply.code(204).send();\n } catch (error) {\n sendJsonError(reply, error);\n }\n });\n\n app.get(\"/api/config\", async () => {\n try {\n return await readConfig(options.rootDir);\n } catch (error) {\n return { version: 1, taskDirs: [\".\"], order: [] };\n }\n });\n\n app.put(\"/api/config\", async (request, reply) => {\n try {\n const body = request.body as { taskDirs?: unknown; ignorePaths?: unknown; commands?: unknown } | null;\n const taskDirs = body?.taskDirs;\n if (!Array.isArray(taskDirs) || taskDirs.some((item) => typeof item !== \"string\")) {\n throw new ValidationError(\"taskDirs must be an array of strings.\");\n }\n let ignorePaths: string[] | undefined;\n if (body?.ignorePaths !== undefined) {\n if (!Array.isArray(body.ignorePaths) || body.ignorePaths.some((item) => typeof item !== \"string\")) {\n throw new ValidationError(\"ignorePaths must be an array of strings.\");\n }\n ignorePaths = body.ignorePaths as string[];\n }\n let commands: CommandStep[] | undefined;\n if (body?.commands !== undefined) {\n if (!Array.isArray(body.commands)) {\n throw new ValidationError(\"commands must be an array.\");\n }\n commands = body.commands as CommandStep[];\n }\n const config = await saveConfig(options.rootDir, taskDirs as string[], ignorePaths, commands);\n return reply.send(config);\n } catch (error) {\n sendJsonError(reply, error);\n }\n });\n\n app.post(\"/api/execute\", async (request, reply) => {\n try {\n const body = request.body as { taskPath?: string; commands?: CommandStep[] } | null;\n const taskPath = body?.taskPath;\n if (!taskPath || typeof taskPath !== \"string\") {\n throw new ValidationError(\"taskPath is required.\");\n }\n\n let task;\n try {\n task = await parseTask(options.rootDir, taskPath);\n } catch (error) {\n const maybeError = error as NodeJS.ErrnoException;\n if (maybeError.code === \"ENOENT\") {\n return reply.code(404).send({ error: \"Task not found.\" });\n }\n throw error;\n }\n\n // Resolve commands: request body > task extraFrontmatter > global config\n let commands = body?.commands;\n if (!commands || commands.length === 0) {\n const taskCommands = task.extraFrontmatter.commands;\n if (Array.isArray(taskCommands) && taskCommands.length > 0) {\n commands = taskCommands as CommandStep[];\n }\n }\n if (!commands || commands.length === 0) {\n const config = await readConfig(options.rootDir);\n commands = config.commands;\n }\n if (!commands || commands.length === 0) {\n throw new ValidationError(\"No commands configured.\");\n }\n\n const result = await executeCommandPipeline(options.rootDir, commands, task);\n return reply.send(result);\n } catch (error) {\n sendJsonError(reply, error);\n }\n });\n\n app.get(\"/api/events\", async (_request, reply) => {\n reply.raw.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\"\n });\n reply.raw.write(\"\\n\");\n\n const listener = {\n send(payload: string) {\n reply.raw.write(`data: ${payload}\\n\\n`);\n },\n close() {\n reply.raw.end();\n }\n };\n\n listeners.add(listener);\n reply.raw.on(\"close\", () => {\n listeners.delete(listener);\n });\n\n return reply.hijack();\n });\n\n const watcher = chokidar.watch(options.rootDir, {\n ignoreInitial: true,\n ignored: (watchPath) => watchPath.includes(`${path.sep}.git`) || watchPath.includes(`${path.sep}node_modules`)\n });\n\n watcher.on(\"all\", (eventName, changedPath) => {\n const isMarkdown = changedPath.endsWith(\".md\") || changedPath.endsWith(\".markdown\");\n const isConfigFile = path.basename(changedPath) === \".md-task-viewer.json\";\n if (!isMarkdown && !isConfigFile) {\n return;\n }\n\n const payload = JSON.stringify({\n type: \"tasks-changed\",\n eventName,\n path: path.relative(options.rootDir, changedPath)\n });\n\n for (const listener of listeners) {\n listener.send(payload);\n }\n });\n\n app.addHook(\"onClose\", async () => {\n await watcher.close();\n });\n\n if (clientDir) {\n await app.register(fastifyStatic, {\n root: clientDir,\n prefix: \"/\"\n });\n\n app.setNotFoundHandler(async (request, reply) => {\n if (request.raw.url?.startsWith(\"/api/\")) {\n return reply.code(404).send({ error: \"Not found\" });\n }\n return reply.sendFile(\"index.html\");\n });\n }\n\n return app;\n}\n","import matter from \"gray-matter\";\nimport picomatch from \"picomatch\";\nimport path from \"node:path\";\nimport { promises as fs } from \"node:fs\";\nimport {\n CONFIG_FILE_NAME,\n type CommandStep,\n type ConfigFile,\n type CreateTaskInput,\n type PatchTaskFieldsInput,\n type TaskFrontmatter,\n type TaskListResponse,\n type TaskParseError,\n type TaskPriority,\n type TaskRecord,\n type TaskStatus,\n type UpdateTaskInput\n} from \"./types.js\";\nimport { slugify } from \"./slugify.js\";\n\nconst MARKDOWN_EXTENSIONS = new Set([\".md\", \".markdown\"]);\nconst REQUIRED_PRIORITY: TaskPriority[] = [\"MUST\", \"WANT\"];\nconst REQUIRED_STATUS: TaskStatus[] = [\"TODO\", \"WIP\", \"DONE\"];\n\nexport class ConflictError extends Error {}\nexport class ValidationError extends Error {}\n\nfunction toPosixPath(filePath: string): string {\n return filePath.split(path.sep).join(\"/\");\n}\n\nfunction normalizeRelativePath(candidate: string): string {\n const normalized = toPosixPath(path.posix.normalize(candidate.trim()));\n if (!normalized || normalized === \".\" || normalized.startsWith(\"../\") || normalized.includes(\"/../\")) {\n throw new ValidationError(\"Path must stay within the workspace root.\");\n }\n\n return normalized.replace(/^\\.\\/+/, \"\");\n}\n\nfunction ensureMarkdownExtension(filePath: string): string {\n return path.posix.extname(filePath) ? filePath : `${filePath}.md`;\n}\n\nfunction asUtcISOString(date: Date): string {\n return date.toISOString();\n}\n\nfunction buildDefaults(filePath: string, stats: { birthtime: Date; mtime: Date }): TaskFrontmatter {\n const basename = path.basename(filePath, path.extname(filePath));\n const title = basename.replace(/[-_]+/g, \" \").replace(/\\b\\w/g, (char) => char.toUpperCase());\n\n return {\n title,\n priority: \"WANT\",\n status: \"TODO\",\n createdAt: asUtcISOString(stats.birthtime),\n updatedAt: asUtcISOString(stats.mtime)\n };\n}\n\nfunction splitFrontmatter(data: Record<string, unknown>, statsDefaults: TaskFrontmatter): {\n frontmatter: TaskFrontmatter;\n extraFrontmatter: Record<string, unknown>;\n normalized: boolean;\n} {\n const extraFrontmatter: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(data)) {\n if (![\"title\", \"priority\", \"status\", \"createdAt\", \"updatedAt\"].includes(key)) {\n extraFrontmatter[key] = value;\n }\n }\n\n const title = typeof data.title === \"string\" && data.title.trim() ? data.title : statsDefaults.title;\n const priority = REQUIRED_PRIORITY.includes(data.priority as TaskPriority)\n ? (data.priority as TaskPriority)\n : statsDefaults.priority;\n const status = REQUIRED_STATUS.includes(data.status as TaskStatus)\n ? (data.status as TaskStatus)\n : statsDefaults.status;\n const createdAt =\n typeof data.createdAt === \"string\" && !Number.isNaN(Date.parse(data.createdAt))\n ? new Date(data.createdAt).toISOString()\n : statsDefaults.createdAt;\n const updatedAt =\n typeof data.updatedAt === \"string\" && !Number.isNaN(Date.parse(data.updatedAt))\n ? new Date(data.updatedAt).toISOString()\n : statsDefaults.updatedAt;\n\n const normalized =\n title !== data.title ||\n priority !== data.priority ||\n status !== data.status ||\n createdAt !== data.createdAt ||\n updatedAt !== data.updatedAt;\n\n return {\n frontmatter: { title, priority, status, createdAt, updatedAt },\n extraFrontmatter,\n normalized\n };\n}\n\nexport function serializeTask(record: TaskRecord): string {\n const data = {\n ...record.extraFrontmatter,\n title: record.frontmatter.title,\n priority: record.frontmatter.priority,\n status: record.frontmatter.status,\n createdAt: record.frontmatter.createdAt,\n updatedAt: record.frontmatter.updatedAt\n };\n\n return matter.stringify(record.content, data);\n}\n\nasync function readDirectoryRecursive(rootDir: string, currentDir: string, results: string[]): Promise<void> {\n const entries = await fs.readdir(currentDir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.name === \".git\" || entry.name === \"node_modules\") {\n continue;\n }\n\n const absolutePath = path.join(currentDir, entry.name);\n if (entry.isDirectory()) {\n await readDirectoryRecursive(rootDir, absolutePath, results);\n continue;\n }\n\n if (entry.name === CONFIG_FILE_NAME) {\n continue;\n }\n\n if (!MARKDOWN_EXTENSIONS.has(path.extname(entry.name).toLowerCase())) {\n continue;\n }\n\n results.push(toPosixPath(path.relative(rootDir, absolutePath)));\n }\n}\n\nasync function listMarkdownFiles(rootDir: string, taskDirs: string[], ignorePaths: string[]): Promise<string[]> {\n const results: string[] = [];\n const seen = new Set<string>();\n\n const isIgnored = ignorePaths.length > 0 ? picomatch(ignorePaths) : null;\n\n for (const taskDir of taskDirs) {\n const scanDir = path.resolve(rootDir, taskDir);\n try {\n await fs.access(scanDir);\n } catch {\n continue;\n }\n const dirResults: string[] = [];\n await readDirectoryRecursive(rootDir, scanDir, dirResults);\n for (const filePath of dirResults) {\n if (!seen.has(filePath)) {\n seen.add(filePath);\n if (isIgnored && isIgnored(filePath)) {\n continue;\n }\n results.push(filePath);\n }\n }\n }\n\n return results.sort();\n}\n\nexport async function parseTask(rootDir: string, relativePath: string): Promise<TaskRecord> {\n const absolutePath = path.join(rootDir, relativePath);\n const raw = await fs.readFile(absolutePath, \"utf8\");\n const stats = await fs.stat(absolutePath);\n const parsed = matter(raw);\n const defaults = buildDefaults(relativePath, stats);\n const { frontmatter, extraFrontmatter, normalized } = splitFrontmatter(parsed.data, defaults);\n\n return {\n path: toPosixPath(relativePath),\n content: parsed.content,\n frontmatter,\n extraFrontmatter,\n raw,\n normalized\n };\n}\n\nexport async function readConfig(rootDir: string): Promise<ConfigFile> {\n const configFilePath = path.join(rootDir, CONFIG_FILE_NAME);\n\n try {\n const raw = await fs.readFile(configFilePath, \"utf8\");\n const parsed = JSON.parse(raw) as Partial<ConfigFile>;\n const taskDirs = Array.isArray(parsed.taskDirs)\n ? parsed.taskDirs.filter((item): item is string => typeof item === \"string\")\n : [\".\"];\n const ignorePaths = Array.isArray(parsed.ignorePaths)\n ? parsed.ignorePaths.filter((item): item is string => typeof item === \"string\")\n : [];\n const order = Array.isArray(parsed.order)\n ? parsed.order.filter((item): item is string => typeof item === \"string\")\n : [];\n const commands = Array.isArray(parsed.commands)\n ? (parsed.commands as CommandStep[])\n : undefined;\n return { version: parsed.version ?? 1, taskDirs, ignorePaths, order, commands };\n } catch (error) {\n const maybeError = error as NodeJS.ErrnoException;\n if (maybeError.code !== \"ENOENT\") {\n throw error;\n }\n return { version: 1, taskDirs: [\".\"], ignorePaths: [], order: [] };\n }\n}\n\nasync function reconcileOrder(rootDir: string, taskPaths: string[]): Promise<{ order: string[]; changed: boolean }> {\n const config = await readConfig(rootDir);\n const order = config.order;\n\n const known = new Set(taskPaths);\n const orderSet = new Set(order);\n\n const newItems = taskPaths.filter((p) => !orderSet.has(p));\n const removedCount = order.reduce((count, item) => (known.has(item) ? count : count + 1), 0);\n const canReplace = newItems.length > 0 && newItems.length === removedCount;\n\n // Build next order:\n // - Always keep existing items in their original relative positions.\n // - Only replace removed slots with new items when the number of removed\n // items exactly matches the number of new items (rename-like scenario).\n // - Otherwise, skip removed items and append all new items at the end to\n // avoid unexpected reordering.\n const nextOrder: string[] = [];\n let newItemCursor = 0;\n for (let i = 0; i < order.length; i++) {\n if (known.has(order[i])) {\n nextOrder.push(order[i]);\n } else if (canReplace && newItemCursor < newItems.length) {\n nextOrder.push(newItems[newItemCursor++]);\n }\n // else: removed item with no replacement — skip\n }\n // Append any remaining new items (all of them when we are not in a replace scenario)\n while (newItemCursor < newItems.length) {\n nextOrder.push(newItems[newItemCursor++]);\n }\n\n const changed = nextOrder.length !== order.length || nextOrder.some((item, index) => item !== order[index]);\n return { order: nextOrder, changed };\n}\n\nexport async function saveOrder(rootDir: string, order: string[]): Promise<void> {\n const normalized = Array.from(\n new Set(\n order.map((item) => ensureMarkdownExtension(normalizeRelativePath(item)))\n )\n );\n const existing = await readConfig(rootDir);\n const payload: ConfigFile = { version: 1, taskDirs: existing.taskDirs, ignorePaths: existing.ignorePaths, order: normalized, commands: existing.commands };\n await fs.writeFile(path.join(rootDir, CONFIG_FILE_NAME), `${JSON.stringify(payload, null, 2)}\\n`, \"utf8\");\n}\n\nexport async function saveConfig(rootDir: string, taskDirs: string[], ignorePaths?: string[], commands?: CommandStep[]): Promise<ConfigFile> {\n const validated = taskDirs.map((dir) => {\n const normalized = dir.trim().replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\") || \".\";\n if (normalized.startsWith(\"../\") || normalized.includes(\"/../\")) {\n throw new ValidationError(\"taskDirs must stay within the workspace root.\");\n }\n return normalized;\n });\n if (validated.length === 0) {\n throw new ValidationError(\"taskDirs must contain at least one directory.\");\n }\n const existing = await readConfig(rootDir);\n const validatedIgnorePaths = ignorePaths ?? existing.ignorePaths;\n const validatedCommands = commands !== undefined ? commands : existing.commands;\n const payload: ConfigFile = { version: 1, taskDirs: validated, ignorePaths: validatedIgnorePaths, order: existing.order, commands: validatedCommands };\n await fs.writeFile(path.join(rootDir, CONFIG_FILE_NAME), `${JSON.stringify(payload, null, 2)}\\n`, \"utf8\");\n return payload;\n}\n\nexport async function listTasks(rootDir: string): Promise<TaskListResponse> {\n const config = await readConfig(rootDir);\n const files = await listMarkdownFiles(rootDir, config.taskDirs, config.ignorePaths);\n const errors: TaskParseError[] = [];\n const tasks = await Promise.all(\n files.map(async (relativePath) => {\n try {\n return await parseTask(rootDir, relativePath);\n } catch (error) {\n errors.push({\n path: relativePath,\n message: error instanceof Error ? error.message : \"Unknown parse error\"\n });\n return null;\n }\n })\n );\n\n const taskRecords = tasks.filter((task): task is TaskRecord => task !== null);\n const { order, changed } = await reconcileOrder(\n rootDir,\n taskRecords.map((task) => task.path)\n );\n\n if (changed) {\n await saveOrder(rootDir, order);\n }\n\n const orderIndex = new Map(order.map((item, index) => [item, index]));\n taskRecords.sort((left, right) => {\n const leftIndex = orderIndex.get(left.path) ?? Number.MAX_SAFE_INTEGER;\n const rightIndex = orderIndex.get(right.path) ?? Number.MAX_SAFE_INTEGER;\n return leftIndex - rightIndex || left.path.localeCompare(right.path);\n });\n\n return { tasks: taskRecords, errors };\n}\n\nasync function ensureDirectoryForFile(rootDir: string, relativeFilePath: string): Promise<string> {\n const normalized = ensureMarkdownExtension(normalizeRelativePath(relativeFilePath));\n const absolutePath = path.join(rootDir, normalized);\n const directory = path.dirname(absolutePath);\n await fs.mkdir(directory, { recursive: true });\n return normalized;\n}\n\nasync function nextAvailablePath(rootDir: string, directory: string, title: string): Promise<string> {\n const safeDirectory = directory ? normalizeRelativePath(directory) : \"\";\n const slug = slugify(title);\n const base = safeDirectory ? `${safeDirectory}/${slug}` : slug;\n\n let attempt = 0;\n while (true) {\n const candidate = ensureMarkdownExtension(attempt === 0 ? base : `${base}-${attempt + 1}`);\n try {\n await fs.access(path.join(rootDir, candidate));\n attempt += 1;\n } catch {\n return candidate;\n }\n }\n}\n\nexport async function createTask(rootDir: string, input: CreateTaskInput): Promise<TaskRecord> {\n if (!input.title.trim()) {\n throw new ValidationError(\"Title is required.\");\n }\n\n const now = asUtcISOString(new Date());\n const relativePath = input.path?.trim()\n ? await ensureDirectoryForFile(rootDir, input.path)\n : await nextAvailablePath(rootDir, input.directory ?? \"\", input.title);\n const absolutePath = path.join(rootDir, relativePath);\n\n try {\n await fs.access(absolutePath);\n } catch (error) {\n const maybeError = error as NodeJS.ErrnoException;\n if (maybeError.code === \"ENOENT\") {\n // The target path is available.\n } else if (maybeError.code) {\n throw error;\n } else {\n throw new ValidationError(\"A task already exists at that path.\");\n }\n }\n\n const record: TaskRecord = {\n path: relativePath,\n content: input.content ?? \"\",\n raw: \"\",\n normalized: false,\n extraFrontmatter: input.extraFrontmatter ?? {},\n frontmatter: {\n title: input.title.trim(),\n priority: input.priority ?? \"MUST\",\n status: input.status ?? \"TODO\",\n createdAt: now,\n updatedAt: now\n }\n };\n\n await fs.mkdir(path.dirname(absolutePath), { recursive: true });\n await fs.writeFile(absolutePath, serializeTask(record), \"utf8\");\n\n const current = await listTasks(rootDir);\n await saveOrder(rootDir, current.tasks.map((task) => task.path).concat(relativePath));\n return parseTask(rootDir, relativePath);\n}\n\nexport async function updateTask(rootDir: string, currentPath: string, input: UpdateTaskInput): Promise<TaskRecord> {\n const normalizedCurrentPath = ensureMarkdownExtension(normalizeRelativePath(currentPath));\n const absoluteCurrentPath = path.join(rootDir, normalizedCurrentPath);\n\n let existing: TaskRecord;\n try {\n existing = await parseTask(rootDir, normalizedCurrentPath);\n } catch (error) {\n const maybeError = error as NodeJS.ErrnoException;\n if (maybeError.code === \"ENOENT\") {\n throw new ConflictError(\"The task no longer exists.\");\n }\n throw error;\n }\n\n if (input.baseUpdatedAt && existing.frontmatter.updatedAt !== input.baseUpdatedAt) {\n throw new ConflictError(\"The task changed on disk. Reload before saving.\");\n }\n\n const nextPath = input.path?.trim()\n ? await ensureDirectoryForFile(rootDir, input.path)\n : normalizedCurrentPath;\n const absoluteNextPath = path.join(rootDir, nextPath);\n\n if (nextPath !== normalizedCurrentPath) {\n try {\n await fs.access(absoluteNextPath);\n } catch (error) {\n const maybeError = error as NodeJS.ErrnoException;\n if (maybeError.code === \"ENOENT\") {\n // The target path is available.\n } else if (maybeError.code) {\n throw error;\n } else {\n throw new ValidationError(\"A task already exists at the target path.\");\n }\n }\n }\n\n const record: TaskRecord = {\n path: nextPath,\n raw: existing.raw,\n normalized: false,\n content: input.content,\n extraFrontmatter: input.extraFrontmatter ?? existing.extraFrontmatter,\n frontmatter: {\n title: input.title.trim(),\n priority: input.priority,\n status: input.status,\n createdAt: existing.frontmatter.createdAt,\n updatedAt: asUtcISOString(new Date())\n }\n };\n\n await fs.writeFile(absoluteCurrentPath, serializeTask(record), \"utf8\");\n if (nextPath !== normalizedCurrentPath) {\n await fs.mkdir(path.dirname(absoluteNextPath), { recursive: true });\n await fs.rename(absoluteCurrentPath, absoluteNextPath);\n }\n\n if (nextPath !== normalizedCurrentPath) {\n const config = await readConfig(rootDir);\n const filteredOrder = config.order.filter((item) => item !== nextPath);\n const index = filteredOrder.indexOf(normalizedCurrentPath);\n\n let updatedOrder: string[];\n if (index === -1) {\n // If the old path is not present, just append the new path.\n updatedOrder = [...filteredOrder, nextPath];\n } else {\n // Replace the old path with the new path at the same position.\n updatedOrder = [...filteredOrder];\n updatedOrder[index] = nextPath;\n }\n await saveOrder(rootDir, updatedOrder);\n }\n return parseTask(rootDir, nextPath);\n}\n\nexport async function deleteTask(rootDir: string, relativePath: string): Promise<void> {\n const normalizedPath = ensureMarkdownExtension(normalizeRelativePath(relativePath));\n const absolutePath = path.join(rootDir, normalizedPath);\n\n try {\n await fs.unlink(absolutePath);\n } catch (error) {\n const maybeError = error as NodeJS.ErrnoException;\n if (maybeError.code === \"ENOENT\") {\n throw new ConflictError(\"The task no longer exists.\");\n }\n throw error;\n }\n\n const current = await listTasks(rootDir);\n await saveOrder(\n rootDir,\n current.tasks.map((task) => task.path)\n );\n}\n\nexport async function patchTaskFields(rootDir: string, currentPath: string, input: PatchTaskFieldsInput): Promise<TaskRecord> {\n const normalizedCurrentPath = ensureMarkdownExtension(normalizeRelativePath(currentPath));\n const absoluteCurrentPath = path.join(rootDir, normalizedCurrentPath);\n\n let existing: TaskRecord;\n try {\n existing = await parseTask(rootDir, normalizedCurrentPath);\n } catch (error) {\n const maybeError = error as NodeJS.ErrnoException;\n if (maybeError.code === \"ENOENT\") {\n throw new ConflictError(\"The task no longer exists.\");\n }\n throw error;\n }\n\n const priority = input.priority && REQUIRED_PRIORITY.includes(input.priority) ? input.priority : existing.frontmatter.priority;\n const status = input.status && REQUIRED_STATUS.includes(input.status) ? input.status : existing.frontmatter.status;\n\n if (priority === existing.frontmatter.priority && status === existing.frontmatter.status) {\n return existing;\n }\n\n const record: TaskRecord = {\n path: normalizedCurrentPath,\n raw: existing.raw,\n normalized: false,\n content: existing.content,\n extraFrontmatter: existing.extraFrontmatter,\n frontmatter: {\n ...existing.frontmatter,\n priority,\n status,\n updatedAt: asUtcISOString(new Date())\n }\n };\n\n await fs.writeFile(absoluteCurrentPath, serializeTask(record), \"utf8\");\n return parseTask(rootDir, normalizedCurrentPath);\n}\n\nexport function parseOrderPayload(input: unknown): string[] {\n if (!Array.isArray(input)) {\n throw new ValidationError(\"Order payload must be an array.\");\n }\n\n return input.map((item) => ensureMarkdownExtension(normalizeRelativePath(String(item))));\n}\n\nexport async function readOrder(rootDir: string): Promise<ConfigFile> {\n const config = await readConfig(rootDir);\n const { order } = await reconcileOrder(\n rootDir,\n (await listTasks(rootDir)).tasks.map((task) => task.path)\n );\n return { version: 1, taskDirs: config.taskDirs, ignorePaths: config.ignorePaths, order, commands: config.commands };\n}\n\nexport const taskStoreUtils = {\n slugify,\n normalizeRelativePath,\n ensureMarkdownExtension,\n splitFrontmatter,\n buildDefaults\n};\n","export const CONFIG_FILE_NAME = \".md-task-viewer.json\";\n\nexport type TaskPriority = \"MUST\" | \"WANT\";\nexport type TaskStatus = \"TODO\" | \"WIP\" | \"DONE\";\n\nexport interface TaskFrontmatter {\n title: string;\n priority: TaskPriority;\n status: TaskStatus;\n createdAt: string;\n updatedAt: string;\n [key: string]: unknown;\n}\n\nexport interface TaskRecord {\n path: string;\n content: string;\n frontmatter: TaskFrontmatter;\n extraFrontmatter: Record<string, unknown>;\n raw: string;\n normalized: boolean;\n}\n\nexport interface TaskParseError {\n path: string;\n message: string;\n}\n\nexport interface TaskListResponse {\n tasks: TaskRecord[];\n errors: TaskParseError[];\n}\n\nexport interface CreateTaskInput {\n title: string;\n priority?: TaskPriority;\n status?: TaskStatus;\n content?: string;\n directory?: string;\n path?: string;\n extraFrontmatter?: Record<string, unknown>;\n}\n\nexport interface UpdateTaskInput {\n path?: string;\n title: string;\n priority: TaskPriority;\n status: TaskStatus;\n content: string;\n extraFrontmatter?: Record<string, unknown>;\n baseUpdatedAt?: string;\n}\n\nexport interface PatchTaskFieldsInput {\n priority?: TaskPriority;\n status?: TaskStatus;\n}\n\nexport interface CommandStep {\n command: string;\n passBody?: \"arg\" | \"stdin\" | false;\n}\n\nexport interface CommandExecutionResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n duration: number;\n}\n\nexport interface ConfigFile {\n version: number;\n taskDirs: string[];\n ignorePaths: string[];\n order: string[];\n commands?: CommandStep[];\n}\n","export function slugify(value: string): string {\n const slug = value\n // Unicode結合文字列を正規合成形に統一(例: か+濁点 → が)\n .normalize(\"NFC\")\n // 半角・全角スペース(U+3000)など空白文字をハイフンに変換。近年では \\s は U+3000 にもマッチするが、明示的に記載\n .replace(/[\\s\\u3000]+/g, \"-\")\n // Unicode文字(L)・数字(N)・ハイフン以外を除去(記号や句読点など)\n .replace(/[^\\p{L}\\p{N}-]+/gu, \"\")\n // 先頭・末尾の余分なハイフンを除去\n .replace(/^-+|-+$/g, \"\");\n return slug || \"untitled-task\";\n}\n","import { spawn } from \"node:child_process\";\nimport path from \"node:path\";\nimport type { CommandStep, CommandExecutionResult, TaskRecord } from \"./types.js\";\n\nconst TIMEOUT_MS = 30_000;\n\nconst VARIABLE_PATTERN = /\\$\\{?(TASK_TITLE|TASK_FILEPATH|TASK_BODY)\\}?/g;\n\nexport function substituteVariables(command: string, vars: Record<string, string>): string {\n return command.replace(VARIABLE_PATTERN, (_match, name: string) => vars[name] ?? \"\");\n}\n\nexport async function executeCommandPipeline(\n rootDir: string,\n steps: CommandStep[],\n task: TaskRecord\n): Promise<CommandExecutionResult> {\n if (steps.length === 0) {\n return { stdout: \"\", stderr: \"\", exitCode: 0, duration: 0 };\n }\n\n const absoluteFilePath = path.resolve(rootDir, task.path);\n const vars: Record<string, string> = {\n TASK_TITLE: task.frontmatter.title,\n TASK_FILEPATH: absoluteFilePath,\n TASK_BODY: task.content\n };\n\n const startTime = Date.now();\n\n return new Promise<CommandExecutionResult>((resolve) => {\n const resolvedCommands = steps.map((step, index) => {\n let cmd = substituteVariables(step.command, vars);\n if (index === 0 && step.passBody === \"arg\") {\n const escaped = task.content.replace(/'/g, \"'\\\\''\");\n cmd = `${cmd} '${escaped}'`;\n }\n return cmd;\n });\n\n const processes: ReturnType<typeof spawn>[] = [];\n for (let index = 0; index < resolvedCommands.length; index++) {\n const proc = spawn(resolvedCommands[index], {\n shell: true,\n cwd: rootDir,\n stdio: [\"pipe\", \"pipe\", \"pipe\"]\n });\n\n // pipe stdout of previous process to stdin of current\n if (index > 0) {\n const prev = processes[index - 1];\n if (prev?.stdout) {\n prev.stdout.pipe(proc.stdin!);\n }\n }\n\n processes.push(proc);\n }\n\n // Handle first command's passBody option\n const firstStep = steps[0];\n const firstProc = processes[0];\n if (firstStep.passBody === \"stdin\" && firstProc.stdin) {\n firstProc.stdin.write(task.content);\n }\n // Always close first process stdin (body written above if passBody is stdin)\n firstProc.stdin?.end();\n\n const lastProc = processes[processes.length - 1];\n const stdoutChunks: Buffer[] = [];\n const stderrChunks: Buffer[] = [];\n\n lastProc.stdout?.on(\"data\", (chunk: Buffer) => stdoutChunks.push(chunk));\n lastProc.stderr?.on(\"data\", (chunk: Buffer) => stderrChunks.push(chunk));\n\n // Collect stderr from all intermediate processes too\n for (let i = 0; i < processes.length - 1; i++) {\n processes[i].stderr?.on(\"data\", (chunk: Buffer) => stderrChunks.push(chunk));\n }\n\n const timeout = setTimeout(() => {\n for (const proc of processes) {\n proc.kill(\"SIGTERM\");\n }\n }, TIMEOUT_MS);\n\n lastProc.on(\"close\", (code) => {\n clearTimeout(timeout);\n resolve({\n stdout: Buffer.concat(stdoutChunks).toString(\"utf8\"),\n stderr: Buffer.concat(stderrChunks).toString(\"utf8\"),\n exitCode: code ?? 1,\n duration: Date.now() - startTime\n });\n });\n\n lastProc.on(\"error\", (err) => {\n clearTimeout(timeout);\n resolve({\n stdout: \"\",\n stderr: err.message,\n exitCode: 1,\n duration: Date.now() - startTime\n });\n });\n\n // Handle errors on intermediate processes\n for (let i = 0; i < processes.length - 1; i++) {\n processes[i].on(\"error\", (err) => {\n stderrChunks.push(Buffer.from(err.message));\n });\n }\n });\n}\n"],"mappings":"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","names":["path","path","path"]}
1
+ {"version":3,"sources":["../src/server.ts","../src/taskStore.ts","../src/types.ts","../src/slugify.ts","../src/commandExecutor.ts"],"sourcesContent":["import Fastify, { type FastifyInstance } from \"fastify\";\nimport fastifyStatic from \"@fastify/static\";\nimport chokidar from \"chokidar\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n ConflictError,\n ValidationError,\n createTask,\n deleteTask,\n listTasks,\n parseOrderPayload,\n parseTask,\n patchTaskFields,\n readConfig,\n saveConfig,\n saveOrder,\n updateTask\n} from \"./taskStore.js\";\nimport type { CommandStep } from \"./types.js\";\nimport { executeCommandPipeline } from \"./commandExecutor.js\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nexport interface CreateServerOptions {\n rootDir: string;\n clientDir?: string | null;\n}\n\nfunction resolveClientDir(explicitClientDir?: string | null): string | null {\n if (explicitClientDir === null) {\n return null;\n }\n if (explicitClientDir) {\n return explicitClientDir;\n }\n return path.resolve(__dirname, \"client\");\n}\n\nfunction sendJsonError(reply: { code: (statusCode: number) => { send: (payload: unknown) => void } }, error: unknown): void {\n if (error instanceof ValidationError) {\n reply.code(400).send({ error: error.message });\n return;\n }\n if (error instanceof ConflictError) {\n reply.code(409).send({ error: error.message });\n return;\n }\n reply.code(500).send({ error: error instanceof Error ? error.message : \"Internal server error\" });\n}\n\nexport async function createServer(options: CreateServerOptions): Promise<FastifyInstance> {\n const app = Fastify({ logger: false, forceCloseConnections: true });\n const listeners = new Set<{ send: (payload: string) => void; close: () => void }>();\n const clientDir = resolveClientDir(options.clientDir);\n\n app.addHook(\"onClose\", async () => {\n for (const listener of listeners) {\n listener.close();\n }\n });\n\n app.get(\"/api/tasks\", async () => listTasks(options.rootDir));\n\n app.post(\"/api/tasks\", async (request, reply) => {\n try {\n const task = await createTask(options.rootDir, (request.body ?? {}) as never);\n return reply.code(201).send(task);\n } catch (error) {\n sendJsonError(reply, error);\n }\n });\n\n app.patch(\"/api/tasks/*\", async (request, reply) => {\n const currentPath = decodeURIComponent((request.params as { \"*\": string })[\"*\"] ?? \"\");\n try {\n const task = await updateTask(options.rootDir, currentPath, (request.body ?? {}) as never);\n return reply.send(task);\n } catch (error) {\n sendJsonError(reply, error);\n }\n });\n\n app.delete(\"/api/tasks/*\", async (request, reply) => {\n const currentPath = decodeURIComponent((request.params as { \"*\": string })[\"*\"] ?? \"\");\n try {\n await deleteTask(options.rootDir, currentPath);\n return reply.code(204).send();\n } catch (error) {\n sendJsonError(reply, error);\n }\n });\n\n app.patch(\"/api/task-fields/*\", async (request, reply) => {\n const currentPath = decodeURIComponent((request.params as { \"*\": string })[\"*\"] ?? \"\");\n try {\n const task = await patchTaskFields(options.rootDir, currentPath, (request.body ?? {}) as never);\n return reply.send(task);\n } catch (error) {\n sendJsonError(reply, error);\n }\n });\n\n app.put(\"/api/order\", async (request, reply) => {\n try {\n const order = parseOrderPayload((request.body as { order?: unknown } | null)?.order ?? []);\n await saveOrder(options.rootDir, order);\n return reply.code(204).send();\n } catch (error) {\n sendJsonError(reply, error);\n }\n });\n\n app.get(\"/api/config\", async () => {\n try {\n return await readConfig(options.rootDir);\n } catch (error) {\n return { version: 1, taskDirs: [\".\"], order: [] };\n }\n });\n\n app.put(\"/api/config\", async (request, reply) => {\n try {\n const body = request.body as { taskDirs?: unknown; ignorePaths?: unknown; commands?: unknown } | null;\n const taskDirs = body?.taskDirs;\n if (!Array.isArray(taskDirs) || taskDirs.some((item) => typeof item !== \"string\")) {\n throw new ValidationError(\"taskDirs must be an array of strings.\");\n }\n let ignorePaths: string[] | undefined;\n if (body?.ignorePaths !== undefined) {\n if (!Array.isArray(body.ignorePaths) || body.ignorePaths.some((item) => typeof item !== \"string\")) {\n throw new ValidationError(\"ignorePaths must be an array of strings.\");\n }\n ignorePaths = body.ignorePaths as string[];\n }\n let commands: CommandStep[] | undefined;\n if (body?.commands !== undefined) {\n if (!Array.isArray(body.commands)) {\n throw new ValidationError(\"commands must be an array.\");\n }\n commands = body.commands as CommandStep[];\n }\n const config = await saveConfig(options.rootDir, taskDirs as string[], ignorePaths, commands);\n return reply.send(config);\n } catch (error) {\n sendJsonError(reply, error);\n }\n });\n\n app.post(\"/api/execute\", async (request, reply) => {\n try {\n const body = request.body as { taskPath?: string; commands?: CommandStep[] } | null;\n const taskPath = body?.taskPath;\n if (!taskPath || typeof taskPath !== \"string\") {\n throw new ValidationError(\"taskPath is required.\");\n }\n\n let task;\n try {\n task = await parseTask(options.rootDir, taskPath);\n } catch (error) {\n const maybeError = error as NodeJS.ErrnoException;\n if (maybeError.code === \"ENOENT\") {\n return reply.code(404).send({ error: \"Task not found.\" });\n }\n throw error;\n }\n\n // Resolve commands: request body > task extraFrontmatter > global config\n let commands = body?.commands;\n if (!commands || commands.length === 0) {\n const taskCommands = task.extraFrontmatter.commands;\n if (Array.isArray(taskCommands) && taskCommands.length > 0) {\n commands = taskCommands as CommandStep[];\n }\n }\n if (!commands || commands.length === 0) {\n const config = await readConfig(options.rootDir);\n commands = config.commands;\n }\n if (!commands || commands.length === 0) {\n throw new ValidationError(\"No commands configured.\");\n }\n\n const result = await executeCommandPipeline(options.rootDir, commands, task);\n return reply.send(result);\n } catch (error) {\n sendJsonError(reply, error);\n }\n });\n\n app.get(\"/api/events\", async (_request, reply) => {\n reply.raw.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\"\n });\n reply.raw.write(\"\\n\");\n\n const listener = {\n send(payload: string) {\n reply.raw.write(`data: ${payload}\\n\\n`);\n },\n close() {\n reply.raw.end();\n }\n };\n\n listeners.add(listener);\n reply.raw.on(\"close\", () => {\n listeners.delete(listener);\n });\n\n return reply.hijack();\n });\n\n const watcher = chokidar.watch(options.rootDir, {\n ignoreInitial: true,\n ignored: (watchPath) => watchPath.includes(`${path.sep}.git`) || watchPath.includes(`${path.sep}node_modules`)\n });\n\n watcher.on(\"all\", (eventName, changedPath) => {\n const isMarkdown = changedPath.endsWith(\".md\") || changedPath.endsWith(\".markdown\");\n const isConfigFile = path.basename(changedPath) === \".md-task-viewer.json\";\n if (!isMarkdown && !isConfigFile) {\n return;\n }\n\n const payload = JSON.stringify({\n type: \"tasks-changed\",\n eventName,\n path: path.relative(options.rootDir, changedPath)\n });\n\n for (const listener of listeners) {\n listener.send(payload);\n }\n });\n\n app.addHook(\"onClose\", async () => {\n await watcher.close();\n });\n\n if (clientDir) {\n await app.register(fastifyStatic, {\n root: clientDir,\n prefix: \"/\"\n });\n\n app.setNotFoundHandler(async (request, reply) => {\n if (request.raw.url?.startsWith(\"/api/\")) {\n return reply.code(404).send({ error: \"Not found\" });\n }\n return reply.sendFile(\"index.html\");\n });\n }\n\n return app;\n}\n","import matter from \"gray-matter\";\nimport picomatch from \"picomatch\";\nimport path from \"node:path\";\nimport { promises as fs } from \"node:fs\";\nimport {\n CONFIG_FILE_NAME,\n type CommandStep,\n type ConfigFile,\n type CreateTaskInput,\n type PatchTaskFieldsInput,\n type TaskFrontmatter,\n type TaskListResponse,\n type TaskParseError,\n type TaskPriority,\n type TaskRecord,\n type TaskStatus,\n type UpdateTaskInput\n} from \"./types.js\";\nimport { slugify } from \"./slugify.js\";\n\nconst MARKDOWN_EXTENSIONS = new Set([\".md\", \".markdown\"]);\nconst REQUIRED_PRIORITY: TaskPriority[] = [\"MUST\", \"WANT\"];\nconst REQUIRED_STATUS: TaskStatus[] = [\"TODO\", \"WIP\", \"DONE\"];\n\nexport class ConflictError extends Error {}\nexport class ValidationError extends Error {}\n\nfunction toPosixPath(filePath: string): string {\n return filePath.split(path.sep).join(\"/\");\n}\n\nfunction normalizeRelativePath(candidate: string): string {\n const normalized = toPosixPath(path.posix.normalize(candidate.trim()));\n if (!normalized || normalized === \".\" || normalized.startsWith(\"../\") || normalized.includes(\"/../\")) {\n throw new ValidationError(\"Path must stay within the workspace root.\");\n }\n\n return normalized.replace(/^\\.\\/+/, \"\");\n}\n\nfunction ensureMarkdownExtension(filePath: string): string {\n return path.posix.extname(filePath) ? filePath : `${filePath}.md`;\n}\n\nfunction asUtcISOString(date: Date): string {\n return date.toISOString();\n}\n\nfunction buildDefaults(filePath: string, stats: { birthtime: Date; mtime: Date }): TaskFrontmatter {\n const basename = path.basename(filePath, path.extname(filePath));\n const title = basename.replace(/[-_]+/g, \" \").replace(/\\b\\w/g, (char) => char.toUpperCase());\n\n return {\n title,\n priority: \"WANT\",\n status: \"TODO\",\n createdAt: asUtcISOString(stats.birthtime),\n updatedAt: asUtcISOString(stats.mtime)\n };\n}\n\nfunction splitFrontmatter(data: Record<string, unknown>, statsDefaults: TaskFrontmatter): {\n frontmatter: TaskFrontmatter;\n extraFrontmatter: Record<string, unknown>;\n normalized: boolean;\n} {\n const extraFrontmatter: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(data)) {\n if (![\"title\", \"priority\", \"status\", \"createdAt\", \"updatedAt\"].includes(key)) {\n extraFrontmatter[key] = value;\n }\n }\n\n const title = typeof data.title === \"string\" && data.title.trim() ? data.title : statsDefaults.title;\n const priority = REQUIRED_PRIORITY.includes(data.priority as TaskPriority)\n ? (data.priority as TaskPriority)\n : statsDefaults.priority;\n const status = REQUIRED_STATUS.includes(data.status as TaskStatus)\n ? (data.status as TaskStatus)\n : statsDefaults.status;\n const createdAt =\n typeof data.createdAt === \"string\" && !Number.isNaN(Date.parse(data.createdAt))\n ? new Date(data.createdAt).toISOString()\n : statsDefaults.createdAt;\n const updatedAt =\n typeof data.updatedAt === \"string\" && !Number.isNaN(Date.parse(data.updatedAt))\n ? new Date(data.updatedAt).toISOString()\n : statsDefaults.updatedAt;\n\n const normalized =\n title !== data.title ||\n priority !== data.priority ||\n status !== data.status ||\n createdAt !== data.createdAt ||\n updatedAt !== data.updatedAt;\n\n return {\n frontmatter: { title, priority, status, createdAt, updatedAt },\n extraFrontmatter,\n normalized\n };\n}\n\nexport function serializeTask(record: TaskRecord): string {\n const data = {\n ...record.extraFrontmatter,\n title: record.frontmatter.title,\n priority: record.frontmatter.priority,\n status: record.frontmatter.status,\n createdAt: record.frontmatter.createdAt,\n updatedAt: record.frontmatter.updatedAt\n };\n\n return matter.stringify(record.content, data);\n}\n\nasync function readDirectoryRecursive(rootDir: string, currentDir: string, results: string[]): Promise<void> {\n const entries = await fs.readdir(currentDir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.name === \".git\" || entry.name === \"node_modules\") {\n continue;\n }\n\n const absolutePath = path.join(currentDir, entry.name);\n if (entry.isDirectory()) {\n await readDirectoryRecursive(rootDir, absolutePath, results);\n continue;\n }\n\n if (entry.name === CONFIG_FILE_NAME) {\n continue;\n }\n\n if (!MARKDOWN_EXTENSIONS.has(path.extname(entry.name).toLowerCase())) {\n continue;\n }\n\n results.push(toPosixPath(path.relative(rootDir, absolutePath)));\n }\n}\n\nasync function listMarkdownFiles(rootDir: string, taskDirs: string[], ignorePaths: string[]): Promise<string[]> {\n const results: string[] = [];\n const seen = new Set<string>();\n\n const isIgnored = ignorePaths.length > 0 ? picomatch(ignorePaths) : null;\n\n for (const taskDir of taskDirs) {\n const scanDir = path.resolve(rootDir, taskDir);\n try {\n await fs.access(scanDir);\n } catch {\n continue;\n }\n const dirResults: string[] = [];\n await readDirectoryRecursive(rootDir, scanDir, dirResults);\n for (const filePath of dirResults) {\n if (!seen.has(filePath)) {\n seen.add(filePath);\n if (isIgnored && isIgnored(filePath)) {\n continue;\n }\n results.push(filePath);\n }\n }\n }\n\n return results.sort();\n}\n\nexport async function parseTask(rootDir: string, relativePath: string): Promise<TaskRecord> {\n const absolutePath = path.join(rootDir, relativePath);\n const raw = await fs.readFile(absolutePath, \"utf8\");\n const stats = await fs.stat(absolutePath);\n const parsed = matter(raw);\n const defaults = buildDefaults(relativePath, stats);\n const { frontmatter, extraFrontmatter, normalized } = splitFrontmatter(parsed.data, defaults);\n\n return {\n path: toPosixPath(relativePath),\n content: parsed.content,\n frontmatter,\n extraFrontmatter,\n raw,\n normalized\n };\n}\n\nexport async function readConfig(rootDir: string): Promise<ConfigFile> {\n const configFilePath = path.join(rootDir, CONFIG_FILE_NAME);\n\n try {\n const raw = await fs.readFile(configFilePath, \"utf8\");\n const parsed = JSON.parse(raw) as Partial<ConfigFile>;\n const taskDirs = Array.isArray(parsed.taskDirs)\n ? parsed.taskDirs.filter((item): item is string => typeof item === \"string\")\n : [\".\"];\n const ignorePaths = Array.isArray(parsed.ignorePaths)\n ? parsed.ignorePaths.filter((item): item is string => typeof item === \"string\")\n : [];\n const order = Array.isArray(parsed.order)\n ? parsed.order.filter((item): item is string => typeof item === \"string\")\n : [];\n const commands = Array.isArray(parsed.commands)\n ? (parsed.commands as CommandStep[])\n : undefined;\n return { version: parsed.version ?? 1, taskDirs, ignorePaths, order, commands };\n } catch (error) {\n const maybeError = error as NodeJS.ErrnoException;\n if (maybeError.code !== \"ENOENT\") {\n throw error;\n }\n return { version: 1, taskDirs: [\".\"], ignorePaths: [], order: [] };\n }\n}\n\nasync function reconcileOrder(rootDir: string, taskPaths: string[]): Promise<{ order: string[]; changed: boolean }> {\n const config = await readConfig(rootDir);\n const order = config.order;\n\n const known = new Set(taskPaths);\n const orderSet = new Set(order);\n\n const newItems = taskPaths.filter((p) => !orderSet.has(p));\n const removedCount = order.reduce((count, item) => (known.has(item) ? count : count + 1), 0);\n const canReplace = newItems.length > 0 && newItems.length === removedCount;\n\n // Build next order:\n // - Always keep existing items in their original relative positions.\n // - Only replace removed slots with new items when the number of removed\n // items exactly matches the number of new items (rename-like scenario).\n // - Otherwise, skip removed items and append all new items at the end to\n // avoid unexpected reordering.\n const nextOrder: string[] = [];\n let newItemCursor = 0;\n for (let i = 0; i < order.length; i++) {\n if (known.has(order[i])) {\n nextOrder.push(order[i]);\n } else if (canReplace && newItemCursor < newItems.length) {\n nextOrder.push(newItems[newItemCursor++]);\n }\n // else: removed item with no replacement — skip\n }\n // Append any remaining new items (all of them when we are not in a replace scenario)\n while (newItemCursor < newItems.length) {\n nextOrder.push(newItems[newItemCursor++]);\n }\n\n const changed = nextOrder.length !== order.length || nextOrder.some((item, index) => item !== order[index]);\n return { order: nextOrder, changed };\n}\n\nexport async function saveOrder(rootDir: string, order: string[]): Promise<void> {\n const normalized = Array.from(\n new Set(\n order.map((item) => ensureMarkdownExtension(normalizeRelativePath(item)))\n )\n );\n const existing = await readConfig(rootDir);\n const payload: ConfigFile = { version: 1, taskDirs: existing.taskDirs, ignorePaths: existing.ignorePaths, order: normalized, commands: existing.commands };\n await fs.writeFile(path.join(rootDir, CONFIG_FILE_NAME), `${JSON.stringify(payload, null, 2)}\\n`, \"utf8\");\n}\n\nexport async function saveConfig(rootDir: string, taskDirs: string[], ignorePaths?: string[], commands?: CommandStep[]): Promise<ConfigFile> {\n const validated = taskDirs.map((dir) => {\n const normalized = dir.trim().replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\") || \".\";\n if (normalized.startsWith(\"../\") || normalized.includes(\"/../\")) {\n throw new ValidationError(\"taskDirs must stay within the workspace root.\");\n }\n return normalized;\n });\n if (validated.length === 0) {\n throw new ValidationError(\"taskDirs must contain at least one directory.\");\n }\n const existing = await readConfig(rootDir);\n const validatedIgnorePaths = ignorePaths ?? existing.ignorePaths;\n const validatedCommands = commands !== undefined ? commands : existing.commands;\n const payload: ConfigFile = { version: 1, taskDirs: validated, ignorePaths: validatedIgnorePaths, order: existing.order, commands: validatedCommands };\n await fs.writeFile(path.join(rootDir, CONFIG_FILE_NAME), `${JSON.stringify(payload, null, 2)}\\n`, \"utf8\");\n return payload;\n}\n\nexport async function listTasks(rootDir: string): Promise<TaskListResponse> {\n const config = await readConfig(rootDir);\n const files = await listMarkdownFiles(rootDir, config.taskDirs, config.ignorePaths);\n const errors: TaskParseError[] = [];\n const tasks = await Promise.all(\n files.map(async (relativePath) => {\n try {\n return await parseTask(rootDir, relativePath);\n } catch (error) {\n errors.push({\n path: relativePath,\n message: error instanceof Error ? error.message : \"Unknown parse error\"\n });\n return null;\n }\n })\n );\n\n const taskRecords = tasks.filter((task): task is TaskRecord => task !== null);\n const { order, changed } = await reconcileOrder(\n rootDir,\n taskRecords.map((task) => task.path)\n );\n\n if (changed) {\n await saveOrder(rootDir, order);\n }\n\n const orderIndex = new Map(order.map((item, index) => [item, index]));\n taskRecords.sort((left, right) => {\n const leftIndex = orderIndex.get(left.path) ?? Number.MAX_SAFE_INTEGER;\n const rightIndex = orderIndex.get(right.path) ?? Number.MAX_SAFE_INTEGER;\n return leftIndex - rightIndex || left.path.localeCompare(right.path);\n });\n\n return { tasks: taskRecords, errors };\n}\n\nasync function ensureDirectoryForFile(rootDir: string, relativeFilePath: string): Promise<string> {\n const normalized = ensureMarkdownExtension(normalizeRelativePath(relativeFilePath));\n const absolutePath = path.join(rootDir, normalized);\n const directory = path.dirname(absolutePath);\n await fs.mkdir(directory, { recursive: true });\n return normalized;\n}\n\nasync function nextAvailablePath(rootDir: string, directory: string, title: string): Promise<string> {\n const safeDirectory = directory ? normalizeRelativePath(directory) : \"\";\n const slug = slugify(title);\n const base = safeDirectory ? `${safeDirectory}/${slug}` : slug;\n\n let attempt = 0;\n while (true) {\n const candidate = ensureMarkdownExtension(attempt === 0 ? base : `${base}-${attempt + 1}`);\n try {\n await fs.access(path.join(rootDir, candidate));\n attempt += 1;\n } catch {\n return candidate;\n }\n }\n}\n\nexport async function createTask(rootDir: string, input: CreateTaskInput): Promise<TaskRecord> {\n if (!input.title.trim()) {\n throw new ValidationError(\"Title is required.\");\n }\n\n const now = asUtcISOString(new Date());\n const relativePath = input.path?.trim()\n ? await ensureDirectoryForFile(rootDir, input.path)\n : await nextAvailablePath(rootDir, input.directory ?? \"\", input.title);\n const absolutePath = path.join(rootDir, relativePath);\n\n let targetExists = false;\n try {\n await fs.access(absolutePath);\n targetExists = true;\n } catch (error) {\n const maybeError = error as NodeJS.ErrnoException;\n if (maybeError.code !== \"ENOENT\") {\n throw error;\n }\n }\n if (targetExists) {\n throw new ValidationError(\"A task already exists at that path.\");\n }\n\n const record: TaskRecord = {\n path: relativePath,\n content: input.content ?? \"\",\n raw: \"\",\n normalized: false,\n extraFrontmatter: input.extraFrontmatter ?? {},\n frontmatter: {\n title: input.title.trim(),\n priority: input.priority ?? \"MUST\",\n status: input.status ?? \"TODO\",\n createdAt: now,\n updatedAt: now\n }\n };\n\n await fs.mkdir(path.dirname(absolutePath), { recursive: true });\n await fs.writeFile(absolutePath, serializeTask(record), \"utf8\");\n\n const config = await readConfig(rootDir);\n const filteredOrder = config.order.filter((item) => item !== relativePath);\n await saveOrder(rootDir, [relativePath, ...filteredOrder]);\n return parseTask(rootDir, relativePath);\n}\n\nexport async function updateTask(rootDir: string, currentPath: string, input: UpdateTaskInput): Promise<TaskRecord> {\n const normalizedCurrentPath = ensureMarkdownExtension(normalizeRelativePath(currentPath));\n const absoluteCurrentPath = path.join(rootDir, normalizedCurrentPath);\n\n let existing: TaskRecord;\n try {\n existing = await parseTask(rootDir, normalizedCurrentPath);\n } catch (error) {\n const maybeError = error as NodeJS.ErrnoException;\n if (maybeError.code === \"ENOENT\") {\n throw new ConflictError(\"The task no longer exists.\");\n }\n throw error;\n }\n\n if (input.baseUpdatedAt && existing.frontmatter.updatedAt !== input.baseUpdatedAt) {\n throw new ConflictError(\"The task changed on disk. Reload before saving.\");\n }\n\n const nextPath = input.path?.trim()\n ? await ensureDirectoryForFile(rootDir, input.path)\n : normalizedCurrentPath;\n const absoluteNextPath = path.join(rootDir, nextPath);\n\n if (nextPath !== normalizedCurrentPath) {\n let targetExists = false;\n try {\n await fs.access(absoluteNextPath);\n targetExists = true;\n } catch (error) {\n const maybeError = error as NodeJS.ErrnoException;\n if (maybeError.code !== \"ENOENT\") {\n throw error;\n }\n }\n if (targetExists) {\n throw new ValidationError(\"A task already exists at the target path.\");\n }\n }\n\n const record: TaskRecord = {\n path: nextPath,\n raw: existing.raw,\n normalized: false,\n content: input.content,\n extraFrontmatter: input.extraFrontmatter ?? existing.extraFrontmatter,\n frontmatter: {\n title: input.title.trim(),\n priority: input.priority,\n status: input.status,\n createdAt: existing.frontmatter.createdAt,\n updatedAt: asUtcISOString(new Date())\n }\n };\n\n await fs.writeFile(absoluteCurrentPath, serializeTask(record), \"utf8\");\n if (nextPath !== normalizedCurrentPath) {\n await fs.mkdir(path.dirname(absoluteNextPath), { recursive: true });\n await fs.rename(absoluteCurrentPath, absoluteNextPath);\n }\n\n if (nextPath !== normalizedCurrentPath) {\n const config = await readConfig(rootDir);\n const filteredOrder = config.order.filter((item) => item !== nextPath);\n const index = filteredOrder.indexOf(normalizedCurrentPath);\n\n let updatedOrder: string[];\n if (index === -1) {\n // If the old path is not present, just append the new path.\n updatedOrder = [...filteredOrder, nextPath];\n } else {\n // Replace the old path with the new path at the same position.\n updatedOrder = [...filteredOrder];\n updatedOrder[index] = nextPath;\n }\n await saveOrder(rootDir, updatedOrder);\n }\n return parseTask(rootDir, nextPath);\n}\n\nexport async function deleteTask(rootDir: string, relativePath: string): Promise<void> {\n const normalizedPath = ensureMarkdownExtension(normalizeRelativePath(relativePath));\n const absolutePath = path.join(rootDir, normalizedPath);\n\n try {\n await fs.unlink(absolutePath);\n } catch (error) {\n const maybeError = error as NodeJS.ErrnoException;\n if (maybeError.code === \"ENOENT\") {\n throw new ConflictError(\"The task no longer exists.\");\n }\n throw error;\n }\n\n const current = await listTasks(rootDir);\n await saveOrder(\n rootDir,\n current.tasks.map((task) => task.path)\n );\n}\n\nexport async function patchTaskFields(rootDir: string, currentPath: string, input: PatchTaskFieldsInput): Promise<TaskRecord> {\n const normalizedCurrentPath = ensureMarkdownExtension(normalizeRelativePath(currentPath));\n const absoluteCurrentPath = path.join(rootDir, normalizedCurrentPath);\n\n let existing: TaskRecord;\n try {\n existing = await parseTask(rootDir, normalizedCurrentPath);\n } catch (error) {\n const maybeError = error as NodeJS.ErrnoException;\n if (maybeError.code === \"ENOENT\") {\n throw new ConflictError(\"The task no longer exists.\");\n }\n throw error;\n }\n\n const priority = input.priority && REQUIRED_PRIORITY.includes(input.priority) ? input.priority : existing.frontmatter.priority;\n const status = input.status && REQUIRED_STATUS.includes(input.status) ? input.status : existing.frontmatter.status;\n\n if (priority === existing.frontmatter.priority && status === existing.frontmatter.status) {\n return existing;\n }\n\n const record: TaskRecord = {\n path: normalizedCurrentPath,\n raw: existing.raw,\n normalized: false,\n content: existing.content,\n extraFrontmatter: existing.extraFrontmatter,\n frontmatter: {\n ...existing.frontmatter,\n priority,\n status,\n updatedAt: asUtcISOString(new Date())\n }\n };\n\n await fs.writeFile(absoluteCurrentPath, serializeTask(record), \"utf8\");\n return parseTask(rootDir, normalizedCurrentPath);\n}\n\nexport function parseOrderPayload(input: unknown): string[] {\n if (!Array.isArray(input)) {\n throw new ValidationError(\"Order payload must be an array.\");\n }\n\n return input.map((item) => ensureMarkdownExtension(normalizeRelativePath(String(item))));\n}\n\nexport async function readOrder(rootDir: string): Promise<ConfigFile> {\n const config = await readConfig(rootDir);\n const { order } = await reconcileOrder(\n rootDir,\n (await listTasks(rootDir)).tasks.map((task) => task.path)\n );\n return { version: 1, taskDirs: config.taskDirs, ignorePaths: config.ignorePaths, order, commands: config.commands };\n}\n\nexport const taskStoreUtils = {\n slugify,\n normalizeRelativePath,\n ensureMarkdownExtension,\n splitFrontmatter,\n buildDefaults\n};\n","export const CONFIG_FILE_NAME = \".md-task-viewer.json\";\n\nexport type TaskPriority = \"MUST\" | \"WANT\";\nexport type TaskStatus = \"TODO\" | \"WIP\" | \"DONE\";\n\nexport interface TaskFrontmatter {\n title: string;\n priority: TaskPriority;\n status: TaskStatus;\n createdAt: string;\n updatedAt: string;\n [key: string]: unknown;\n}\n\nexport interface TaskRecord {\n path: string;\n content: string;\n frontmatter: TaskFrontmatter;\n extraFrontmatter: Record<string, unknown>;\n raw: string;\n normalized: boolean;\n}\n\nexport interface TaskParseError {\n path: string;\n message: string;\n}\n\nexport interface TaskListResponse {\n tasks: TaskRecord[];\n errors: TaskParseError[];\n}\n\nexport interface CreateTaskInput {\n title: string;\n priority?: TaskPriority;\n status?: TaskStatus;\n content?: string;\n directory?: string;\n path?: string;\n extraFrontmatter?: Record<string, unknown>;\n}\n\nexport interface UpdateTaskInput {\n path?: string;\n title: string;\n priority: TaskPriority;\n status: TaskStatus;\n content: string;\n extraFrontmatter?: Record<string, unknown>;\n baseUpdatedAt?: string;\n}\n\nexport interface PatchTaskFieldsInput {\n priority?: TaskPriority;\n status?: TaskStatus;\n}\n\nexport interface CommandStep {\n command: string;\n passBody?: \"arg\" | \"stdin\" | false;\n}\n\nexport interface CommandExecutionResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n duration: number;\n}\n\nexport interface ConfigFile {\n version: number;\n taskDirs: string[];\n ignorePaths: string[];\n order: string[];\n commands?: CommandStep[];\n}\n","export function slugify(value: string): string {\n const slug = value\n // Unicode結合文字列を正規合成形に統一(例: か+濁点 → が)\n .normalize(\"NFC\")\n // 半角・全角スペース(U+3000)など空白文字をハイフンに変換。近年では \\s は U+3000 にもマッチするが、明示的に記載\n .replace(/[\\s\\u3000]+/g, \"-\")\n // Unicode文字(L)・数字(N)・ハイフン以外を除去(記号や句読点など)\n .replace(/[^\\p{L}\\p{N}-]+/gu, \"\")\n // 先頭・末尾の余分なハイフンを除去\n .replace(/^-+|-+$/g, \"\");\n return slug || \"untitled-task\";\n}\n","import { spawn } from \"node:child_process\";\nimport path from \"node:path\";\nimport type { CommandStep, CommandExecutionResult, TaskRecord } from \"./types.js\";\n\nconst TIMEOUT_MS = 30_000;\n\nconst VARIABLE_PATTERN = /\\$\\{?(TASK_TITLE|TASK_FILEPATH|TASK_BODY)\\}?/g;\n\nexport function substituteVariables(command: string, vars: Record<string, string>): string {\n return command.replace(VARIABLE_PATTERN, (_match, name: string) => vars[name] ?? \"\");\n}\n\nexport async function executeCommandPipeline(\n rootDir: string,\n steps: CommandStep[],\n task: TaskRecord\n): Promise<CommandExecutionResult> {\n if (steps.length === 0) {\n return { stdout: \"\", stderr: \"\", exitCode: 0, duration: 0 };\n }\n\n const absoluteFilePath = path.resolve(rootDir, task.path);\n const vars: Record<string, string> = {\n TASK_TITLE: task.frontmatter.title,\n TASK_FILEPATH: absoluteFilePath,\n TASK_BODY: task.content\n };\n\n const startTime = Date.now();\n\n return new Promise<CommandExecutionResult>((resolve) => {\n const resolvedCommands = steps.map((step, index) => {\n let cmd = substituteVariables(step.command, vars);\n if (index === 0 && step.passBody === \"arg\") {\n const escaped = task.content.replace(/'/g, \"'\\\\''\");\n cmd = `${cmd} '${escaped}'`;\n }\n return cmd;\n });\n\n const processes: ReturnType<typeof spawn>[] = [];\n for (let index = 0; index < resolvedCommands.length; index++) {\n const proc = spawn(resolvedCommands[index], {\n shell: true,\n cwd: rootDir,\n stdio: [\"pipe\", \"pipe\", \"pipe\"]\n });\n\n // pipe stdout of previous process to stdin of current\n if (index > 0) {\n const prev = processes[index - 1];\n if (prev?.stdout) {\n prev.stdout.pipe(proc.stdin!);\n }\n }\n\n processes.push(proc);\n }\n\n // Handle first command's passBody option\n const firstStep = steps[0];\n const firstProc = processes[0];\n if (firstStep.passBody === \"stdin\" && firstProc.stdin) {\n firstProc.stdin.write(task.content);\n }\n // Always close first process stdin (body written above if passBody is stdin)\n firstProc.stdin?.end();\n\n const lastProc = processes[processes.length - 1];\n const stdoutChunks: Buffer[] = [];\n const stderrChunks: Buffer[] = [];\n\n lastProc.stdout?.on(\"data\", (chunk: Buffer) => stdoutChunks.push(chunk));\n lastProc.stderr?.on(\"data\", (chunk: Buffer) => stderrChunks.push(chunk));\n\n // Collect stderr from all intermediate processes too\n for (let i = 0; i < processes.length - 1; i++) {\n processes[i].stderr?.on(\"data\", (chunk: Buffer) => stderrChunks.push(chunk));\n }\n\n const timeout = setTimeout(() => {\n for (const proc of processes) {\n proc.kill(\"SIGTERM\");\n }\n }, TIMEOUT_MS);\n\n lastProc.on(\"close\", (code) => {\n clearTimeout(timeout);\n resolve({\n stdout: Buffer.concat(stdoutChunks).toString(\"utf8\"),\n stderr: Buffer.concat(stderrChunks).toString(\"utf8\"),\n exitCode: code ?? 1,\n duration: Date.now() - startTime\n });\n });\n\n lastProc.on(\"error\", (err) => {\n clearTimeout(timeout);\n resolve({\n stdout: \"\",\n stderr: err.message,\n exitCode: 1,\n duration: Date.now() - startTime\n });\n });\n\n // Handle errors on intermediate processes\n for (let i = 0; i < processes.length - 1; i++) {\n processes[i].on(\"error\", (err) => {\n stderrChunks.push(Buffer.from(err.message));\n });\n }\n });\n}\n"],"mappings":"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","names":["path","path","path"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "md-task-viewer",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Launch a local task viewer/editor for markdown files with frontmatter",
5
5
  "license": "MIT",
6
6
  "repository": {