@rogatio/cli 6.17.0 → 6.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/editor/index.css +120 -27
- package/dist/editor/index.js +182 -86
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -109,7 +109,7 @@ rogatio ai delete
|
|
|
109
109
|
|
|
110
110
|
Configuration is stored at `~/.config/rogatio/provider.json` (Linux), `~/Library/Application Support/rogatio/provider.json` (macOS), or `%LOCALAPPDATA%\rogatio\provider.json` (Windows) with `600` permissions.
|
|
111
111
|
|
|
112
|
-
When AI is configured, `rogatio edit` shows an **AI Assist** button
|
|
112
|
+
When AI is configured, `rogatio edit` shows an **AI Assist** button on the project title row. Click it to:
|
|
113
113
|
- Generate rules from natural language
|
|
114
114
|
- Fix validation errors by repairing the offending rules in place (keeping their rule ids; max 3 auto-fix iterations)
|
|
115
115
|
|
package/dist/editor/index.css
CHANGED
|
@@ -213,8 +213,8 @@
|
|
|
213
213
|
font-weight: 600;
|
|
214
214
|
}
|
|
215
215
|
.rogatio-editor [data-search-wrap] {
|
|
216
|
-
|
|
217
|
-
flex: 0
|
|
216
|
+
position: relative;
|
|
217
|
+
flex: 0 1 18rem;
|
|
218
218
|
width: min(18rem, 100%);
|
|
219
219
|
min-width: 0;
|
|
220
220
|
}
|
|
@@ -223,11 +223,20 @@
|
|
|
223
223
|
padding: 1rem clamp(1rem, 3vw, 3rem) 3rem;
|
|
224
224
|
}
|
|
225
225
|
.rogatio-editor [data-editor-header] {
|
|
226
|
-
display:
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
226
|
+
display: flex;
|
|
227
|
+
flex-wrap: wrap;
|
|
228
|
+
align-items: center;
|
|
229
|
+
justify-content: space-between;
|
|
230
|
+
gap: 0.75rem 1.5rem;
|
|
231
|
+
margin-bottom: 1.25rem;
|
|
232
|
+
}
|
|
233
|
+
.rogatio-editor [data-editor-header-actions] {
|
|
234
|
+
display: flex;
|
|
235
|
+
flex-wrap: wrap;
|
|
236
|
+
align-items: center;
|
|
237
|
+
justify-content: flex-end;
|
|
238
|
+
gap: 0.5rem 0.65rem;
|
|
239
|
+
margin-left: auto;
|
|
231
240
|
}
|
|
232
241
|
.rogatio-editor [data-editor-header] h1,
|
|
233
242
|
.rogatio-editor [data-editor-form] h2,
|
|
@@ -302,29 +311,12 @@
|
|
|
302
311
|
text-align: left;
|
|
303
312
|
text-decoration: underline;
|
|
304
313
|
}
|
|
305
|
-
.rogatio-editor [data-editor-command-bar] button[aria-current=page] {
|
|
306
|
-
border-color: rgba(59, 158, 255, 0.45);
|
|
307
|
-
background: var(--rogatio-primary-bg);
|
|
308
|
-
font-weight: 700;
|
|
309
|
-
}
|
|
310
314
|
.rogatio-editor [data-project-actions] {
|
|
311
315
|
display: flex;
|
|
312
316
|
flex-wrap: wrap;
|
|
313
317
|
gap: 0.5rem;
|
|
314
318
|
margin-top: 0.75rem;
|
|
315
319
|
}
|
|
316
|
-
.rogatio-editor [data-editor-command-bar] {
|
|
317
|
-
display: flex;
|
|
318
|
-
flex-wrap: wrap;
|
|
319
|
-
align-items: center;
|
|
320
|
-
justify-content: space-between;
|
|
321
|
-
gap: 0.75rem 1rem;
|
|
322
|
-
margin-block: 1rem;
|
|
323
|
-
padding: 0.65rem 0.75rem;
|
|
324
|
-
border: 1px solid var(--rogatio-border);
|
|
325
|
-
border-radius: var(--rogatio-radius);
|
|
326
|
-
background: var(--rogatio-surface-raised);
|
|
327
|
-
}
|
|
328
320
|
.rogatio-editor [data-action-cluster] {
|
|
329
321
|
display: flex;
|
|
330
322
|
flex-wrap: wrap;
|
|
@@ -708,6 +700,25 @@
|
|
|
708
700
|
.rogatio-editor [data-search-wrap] {
|
|
709
701
|
position: relative;
|
|
710
702
|
}
|
|
703
|
+
.rogatio-editor [data-rail-tools] {
|
|
704
|
+
display: flex;
|
|
705
|
+
flex: 0 1 auto;
|
|
706
|
+
align-items: flex-end;
|
|
707
|
+
justify-content: flex-end;
|
|
708
|
+
gap: 0.65rem;
|
|
709
|
+
margin-left: auto;
|
|
710
|
+
min-width: 0;
|
|
711
|
+
max-width: 100%;
|
|
712
|
+
}
|
|
713
|
+
.rogatio-editor [data-rail-tools] [data-route=test] {
|
|
714
|
+
flex: none;
|
|
715
|
+
margin-bottom: 0.05rem;
|
|
716
|
+
}
|
|
717
|
+
.rogatio-editor [data-rail-tools] [data-route=test][aria-expanded=true] {
|
|
718
|
+
border-color: rgba(46, 196, 182, 0.55);
|
|
719
|
+
background: rgba(46, 196, 182, 0.14);
|
|
720
|
+
color: var(--rogatio-text);
|
|
721
|
+
}
|
|
711
722
|
.rogatio-editor [data-search-label] {
|
|
712
723
|
display: flex;
|
|
713
724
|
flex-direction: column;
|
|
@@ -755,7 +766,10 @@
|
|
|
755
766
|
display: block;
|
|
756
767
|
}
|
|
757
768
|
.rogatio-editor [data-editor-header] {
|
|
758
|
-
|
|
769
|
+
align-items: flex-start;
|
|
770
|
+
}
|
|
771
|
+
.rogatio-editor [data-editor-header-actions] {
|
|
772
|
+
width: 100%;
|
|
759
773
|
}
|
|
760
774
|
.rogatio-editor [data-rule-heading],
|
|
761
775
|
.rogatio-editor [data-group-heading],
|
|
@@ -805,7 +819,8 @@
|
|
|
805
819
|
.rogatio-editor [data-group-row],
|
|
806
820
|
.rogatio-editor [data-editor-check-group],
|
|
807
821
|
.rogatio-editor [data-action-dock],
|
|
808
|
-
.rogatio-editor [data-action-cluster=danger]
|
|
822
|
+
.rogatio-editor [data-action-cluster=danger],
|
|
823
|
+
.rogatio-editor [data-test-dialog] {
|
|
809
824
|
border-color: ButtonText;
|
|
810
825
|
background: Canvas;
|
|
811
826
|
}
|
|
@@ -828,7 +843,85 @@
|
|
|
828
843
|
transition: none;
|
|
829
844
|
}
|
|
830
845
|
}
|
|
831
|
-
.rogatio-editor [data-
|
|
846
|
+
.rogatio-editor [data-editor-confirmation] {
|
|
847
|
+
z-index: 4;
|
|
848
|
+
}
|
|
849
|
+
.rogatio-editor [data-test-console] {
|
|
850
|
+
position: fixed;
|
|
851
|
+
inset: 0;
|
|
852
|
+
z-index: 3;
|
|
853
|
+
display: grid;
|
|
854
|
+
place-items: center;
|
|
855
|
+
padding: clamp(0.75rem, 3vw, 2rem);
|
|
856
|
+
background: rgb(6 8 12 / 72%);
|
|
857
|
+
backdrop-filter: blur(8px);
|
|
858
|
+
}
|
|
859
|
+
.rogatio-editor [data-test-dialog] {
|
|
860
|
+
display: grid;
|
|
861
|
+
grid-template-rows: auto minmax(0, 1fr);
|
|
862
|
+
width: min(68rem, 100%);
|
|
863
|
+
max-height: min(86vh, 52rem);
|
|
864
|
+
overflow: hidden;
|
|
865
|
+
border: 1px solid var(--rogatio-border);
|
|
866
|
+
border-top: 3px solid var(--rogatio-card-rule-edge);
|
|
867
|
+
border-radius: var(--rogatio-radius);
|
|
868
|
+
background:
|
|
869
|
+
linear-gradient(
|
|
870
|
+
180deg,
|
|
871
|
+
rgba(46, 196, 182, 0.08) 0%,
|
|
872
|
+
transparent 4.5rem),
|
|
873
|
+
var(--rogatio-surface-raised);
|
|
874
|
+
box-shadow: 0 28px 80px rgb(0 0 0 / 55%);
|
|
875
|
+
}
|
|
876
|
+
.rogatio-editor [data-test-dialog-head] {
|
|
877
|
+
display: flex;
|
|
878
|
+
align-items: flex-start;
|
|
879
|
+
justify-content: space-between;
|
|
880
|
+
gap: 1rem;
|
|
881
|
+
padding: 1.1rem 1.25rem 0.9rem;
|
|
882
|
+
border-bottom: 1px solid var(--rogatio-border);
|
|
883
|
+
}
|
|
884
|
+
.rogatio-editor [data-test-dialog-head] h2 {
|
|
885
|
+
margin: 0;
|
|
886
|
+
font-size: 1.65rem;
|
|
887
|
+
letter-spacing: -0.03em;
|
|
888
|
+
}
|
|
889
|
+
.rogatio-editor [data-test-kicker] {
|
|
890
|
+
margin: 0 0 0.2rem;
|
|
891
|
+
color: var(--rogatio-card-rule-edge);
|
|
892
|
+
font-family: var(--rogatio-font-mono);
|
|
893
|
+
font-size: 0.6875rem;
|
|
894
|
+
font-weight: 700;
|
|
895
|
+
letter-spacing: 0.12em;
|
|
896
|
+
text-transform: uppercase;
|
|
897
|
+
}
|
|
898
|
+
.rogatio-editor [data-test-dialog] [data-test-description] {
|
|
899
|
+
margin: 0.35rem 0 0;
|
|
900
|
+
max-width: 40rem;
|
|
901
|
+
color: var(--rogatio-muted);
|
|
902
|
+
}
|
|
903
|
+
.rogatio-editor [data-test-dialog-body] {
|
|
904
|
+
overflow: auto;
|
|
905
|
+
padding: 1.1rem 1.25rem 1.35rem;
|
|
906
|
+
}
|
|
907
|
+
.rogatio-editor [data-test-status] {
|
|
908
|
+
margin: 0;
|
|
909
|
+
color: var(--rogatio-muted);
|
|
910
|
+
}
|
|
911
|
+
@media (min-width: 52rem) {
|
|
912
|
+
.rogatio-editor [data-test-dialog] [data-test-panel] {
|
|
913
|
+
grid-template-columns: minmax(0, 1.45fr) minmax(16rem, 0.7fr);
|
|
914
|
+
align-items: start;
|
|
915
|
+
}
|
|
916
|
+
.rogatio-editor [data-test-dialog] [data-test-panel] > fieldset {
|
|
917
|
+
grid-row: 1 / span 3;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
@media (prefers-reduced-motion: reduce) {
|
|
921
|
+
.rogatio-editor [data-test-console] {
|
|
922
|
+
backdrop-filter: none;
|
|
923
|
+
}
|
|
924
|
+
}
|
|
832
925
|
.rogatio-editor [data-test-checking] {
|
|
833
926
|
color: var(--rogatio-muted);
|
|
834
927
|
margin-block: 0 1rem;
|
package/dist/editor/index.js
CHANGED
|
@@ -2517,12 +2517,12 @@ var EditorControllerImpl = class {
|
|
|
2517
2517
|
extensions;
|
|
2518
2518
|
instanceId;
|
|
2519
2519
|
host;
|
|
2520
|
+
layout;
|
|
2520
2521
|
rail;
|
|
2521
2522
|
main;
|
|
2522
2523
|
header;
|
|
2523
2524
|
status;
|
|
2524
2525
|
summary;
|
|
2525
|
-
commandBar;
|
|
2526
2526
|
form;
|
|
2527
2527
|
searchResults;
|
|
2528
2528
|
draft;
|
|
@@ -2540,6 +2540,7 @@ var EditorControllerImpl = class {
|
|
|
2540
2540
|
extensionCleanups = [];
|
|
2541
2541
|
confirmation;
|
|
2542
2542
|
groupPickerOpen = false;
|
|
2543
|
+
testConsoleOpen = false;
|
|
2543
2544
|
projectActions;
|
|
2544
2545
|
focusRequest;
|
|
2545
2546
|
saving = false;
|
|
@@ -2553,6 +2554,7 @@ var EditorControllerImpl = class {
|
|
|
2553
2554
|
testResourceType = "main_frame";
|
|
2554
2555
|
testResult = void 0;
|
|
2555
2556
|
testRunning = false;
|
|
2557
|
+
testNotice = "";
|
|
2556
2558
|
testRequestId = 0;
|
|
2557
2559
|
aiAssistPanel = null;
|
|
2558
2560
|
aiAssistInFlight = false;
|
|
@@ -2597,8 +2599,8 @@ var EditorControllerImpl = class {
|
|
|
2597
2599
|
this.host = this.document.createElement("div");
|
|
2598
2600
|
this.host.className = "rogatio-editor";
|
|
2599
2601
|
this.host.dataset.rogatioEditor = "true";
|
|
2600
|
-
|
|
2601
|
-
layout.dataset.editorLayout = "true";
|
|
2602
|
+
this.layout = this.document.createElement("div");
|
|
2603
|
+
this.layout.dataset.editorLayout = "true";
|
|
2602
2604
|
this.rail = this.document.createElement("nav");
|
|
2603
2605
|
this.rail.dataset.desktopRouteRail = "true";
|
|
2604
2606
|
this.rail.setAttribute("aria-label", "Project sections");
|
|
@@ -2613,10 +2615,6 @@ var EditorControllerImpl = class {
|
|
|
2613
2615
|
this.summary = this.document.createElement("section");
|
|
2614
2616
|
this.summary.dataset.editorSummary = "true";
|
|
2615
2617
|
this.summary.setAttribute("role", "alert");
|
|
2616
|
-
this.commandBar = this.document.createElement("div");
|
|
2617
|
-
this.commandBar.dataset.editorCommandBar = "true";
|
|
2618
|
-
this.commandBar.setAttribute("role", "toolbar");
|
|
2619
|
-
this.commandBar.setAttribute("aria-label", "Project actions");
|
|
2620
2618
|
this.form = this.document.createElement("form");
|
|
2621
2619
|
this.form.dataset.editorForm = "true";
|
|
2622
2620
|
this.form.noValidate = true;
|
|
@@ -2631,15 +2629,9 @@ var EditorControllerImpl = class {
|
|
|
2631
2629
|
this.searchQuery = "";
|
|
2632
2630
|
this.render();
|
|
2633
2631
|
});
|
|
2634
|
-
this.main.append(
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
this.summary,
|
|
2638
|
-
this.commandBar,
|
|
2639
|
-
this.form
|
|
2640
|
-
);
|
|
2641
|
-
layout.append(this.rail, this.main);
|
|
2642
|
-
this.host.append(layout);
|
|
2632
|
+
this.main.append(this.header, this.status, this.summary, this.form);
|
|
2633
|
+
this.layout.append(this.rail, this.main);
|
|
2634
|
+
this.host.append(this.layout);
|
|
2643
2635
|
this.root.append(this.host);
|
|
2644
2636
|
this.host.addEventListener("click", this.handleClick);
|
|
2645
2637
|
this.host.addEventListener("input", this.handleInput);
|
|
@@ -2688,6 +2680,10 @@ var EditorControllerImpl = class {
|
|
|
2688
2680
|
if (this.destroyed) return;
|
|
2689
2681
|
const target = event.target;
|
|
2690
2682
|
if (!(target instanceof Element)) return;
|
|
2683
|
+
if (this.testConsoleOpen && target instanceof HTMLElement && target.dataset.testConsole !== void 0 && event.target === target) {
|
|
2684
|
+
this.closeTestConsole();
|
|
2685
|
+
return;
|
|
2686
|
+
}
|
|
2691
2687
|
if (this.groupPickerOpen && target instanceof HTMLElement && target.dataset.groupPicker !== void 0 && event.target === target) {
|
|
2692
2688
|
this.closeGroupPicker();
|
|
2693
2689
|
return;
|
|
@@ -2804,6 +2800,14 @@ var EditorControllerImpl = class {
|
|
|
2804
2800
|
this.closeGroupPicker();
|
|
2805
2801
|
return;
|
|
2806
2802
|
}
|
|
2803
|
+
if (event.key === "Escape" && this.testConsoleOpen) {
|
|
2804
|
+
event.preventDefault();
|
|
2805
|
+
this.closeTestConsole();
|
|
2806
|
+
return;
|
|
2807
|
+
}
|
|
2808
|
+
if (event.key === "Tab" && this.testConsoleOpen && !this.confirmation) {
|
|
2809
|
+
this.trapTestConsoleFocus(event);
|
|
2810
|
+
}
|
|
2807
2811
|
const target = event.target;
|
|
2808
2812
|
const inRenameInput = target instanceof HTMLElement && target.dataset.renameInput !== void 0;
|
|
2809
2813
|
if (!inRenameInput) return;
|
|
@@ -2951,6 +2955,7 @@ var EditorControllerImpl = class {
|
|
|
2951
2955
|
return;
|
|
2952
2956
|
}
|
|
2953
2957
|
if (command === "test:open-rule") {
|
|
2958
|
+
this.testConsoleOpen = false;
|
|
2954
2959
|
this.navigateToRule(element.dataset.groupId, element.dataset.ruleId);
|
|
2955
2960
|
return;
|
|
2956
2961
|
}
|
|
@@ -2968,6 +2973,10 @@ var EditorControllerImpl = class {
|
|
|
2968
2973
|
}
|
|
2969
2974
|
if (command === "close-group-picker") {
|
|
2970
2975
|
this.closeGroupPicker();
|
|
2976
|
+
return;
|
|
2977
|
+
}
|
|
2978
|
+
if (command === "close-test-console") {
|
|
2979
|
+
this.closeTestConsole();
|
|
2971
2980
|
}
|
|
2972
2981
|
}
|
|
2973
2982
|
collectDiagnostics(value) {
|
|
@@ -3697,11 +3706,13 @@ var EditorControllerImpl = class {
|
|
|
3697
3706
|
showDryRunDiagnostics(diagnostics) {
|
|
3698
3707
|
this.testResult = void 0;
|
|
3699
3708
|
this.testRunning = false;
|
|
3709
|
+
this.testNotice = "";
|
|
3700
3710
|
this.errors = [...diagnostics];
|
|
3701
3711
|
const count = diagnostics.length;
|
|
3702
3712
|
this.statusMessage = count === 0 ? "The project could not be tested." : `${count} validation error${count === 1 ? "" : "s"} found.`;
|
|
3703
3713
|
const first = diagnostics[0];
|
|
3704
3714
|
if (first) {
|
|
3715
|
+
this.testConsoleOpen = false;
|
|
3705
3716
|
this.navigateToPath(first.path);
|
|
3706
3717
|
return;
|
|
3707
3718
|
}
|
|
@@ -3709,27 +3720,27 @@ var EditorControllerImpl = class {
|
|
|
3709
3720
|
}
|
|
3710
3721
|
async runTest() {
|
|
3711
3722
|
if (!this.options.dryRun) {
|
|
3712
|
-
this.
|
|
3723
|
+
this.testNotice = "Dry-run is not configured for this editor instance.";
|
|
3713
3724
|
this.render();
|
|
3714
3725
|
return;
|
|
3715
3726
|
}
|
|
3716
3727
|
if (this.ruleCount() === 0) {
|
|
3717
3728
|
this.testResult = void 0;
|
|
3718
3729
|
this.testRunning = false;
|
|
3719
|
-
this.
|
|
3730
|
+
this.testNotice = "";
|
|
3720
3731
|
this.render();
|
|
3721
3732
|
return;
|
|
3722
3733
|
}
|
|
3723
3734
|
const lines = this.testLines();
|
|
3724
3735
|
if (lines.length === 0) {
|
|
3725
|
-
this.
|
|
3736
|
+
this.testNotice = "Please enter at least one URL to test.";
|
|
3726
3737
|
this.render();
|
|
3727
3738
|
return;
|
|
3728
3739
|
}
|
|
3729
3740
|
if (lines.length > TEST_CASE_LIMIT) {
|
|
3730
3741
|
this.testResult = void 0;
|
|
3731
3742
|
this.testRunning = false;
|
|
3732
|
-
this.
|
|
3743
|
+
this.testNotice = "Only 256 URLs can be checked at once.";
|
|
3733
3744
|
this.render();
|
|
3734
3745
|
return;
|
|
3735
3746
|
}
|
|
@@ -3743,7 +3754,7 @@ var EditorControllerImpl = class {
|
|
|
3743
3754
|
});
|
|
3744
3755
|
const requestId = ++this.testRequestId;
|
|
3745
3756
|
this.testRunning = true;
|
|
3746
|
-
this.
|
|
3757
|
+
this.testNotice = "";
|
|
3747
3758
|
this.render();
|
|
3748
3759
|
try {
|
|
3749
3760
|
const outcome = await this.options.dryRun(this.getDraft(), cases);
|
|
@@ -3752,7 +3763,7 @@ var EditorControllerImpl = class {
|
|
|
3752
3763
|
if (isDryRunResult(outcome)) {
|
|
3753
3764
|
this.testResult = outcome;
|
|
3754
3765
|
const checked = outcome.summary.urlCount;
|
|
3755
|
-
this.
|
|
3766
|
+
this.testNotice = outcome.errors.length > 0 ? `Checked ${checked} URL${checked === 1 ? "" : "s"}. Some lines are not http(s) URLs.` : `Checked ${checked} URL${checked === 1 ? "" : "s"}.`;
|
|
3756
3767
|
this.render();
|
|
3757
3768
|
return;
|
|
3758
3769
|
}
|
|
@@ -3765,12 +3776,12 @@ var EditorControllerImpl = class {
|
|
|
3765
3776
|
this.testResult = void 0;
|
|
3766
3777
|
this.testRunning = false;
|
|
3767
3778
|
const message = e instanceof Error ? e.message : "Test failed";
|
|
3768
|
-
this.
|
|
3779
|
+
this.testNotice = `Test error: ${message}`;
|
|
3769
3780
|
this.render();
|
|
3770
3781
|
}
|
|
3771
3782
|
}
|
|
3772
|
-
renderTestResults(result) {
|
|
3773
|
-
const resultsSection =
|
|
3783
|
+
renderTestResults(result, scope = this.host) {
|
|
3784
|
+
const resultsSection = scope.querySelector(
|
|
3774
3785
|
"[data-test-results]"
|
|
3775
3786
|
);
|
|
3776
3787
|
if (!resultsSection || !isDryRunResult(result)) return;
|
|
@@ -3946,16 +3957,19 @@ var EditorControllerImpl = class {
|
|
|
3946
3957
|
return enablement.isEnabled(id) !== true;
|
|
3947
3958
|
}
|
|
3948
3959
|
navigate(route, groupId) {
|
|
3960
|
+
if (route === "test") {
|
|
3961
|
+
this.openTestConsole();
|
|
3962
|
+
return;
|
|
3963
|
+
}
|
|
3949
3964
|
const returnFocusToGroups = this.groupPickerOpen;
|
|
3950
3965
|
if (route === "project") {
|
|
3951
3966
|
this.route = { kind: "project" };
|
|
3952
|
-
} else if (route === "test") {
|
|
3953
|
-
this.route = { kind: "test" };
|
|
3954
3967
|
} else if (route === "group" && groupId && this.groupById(groupId)) {
|
|
3955
3968
|
this.route = { kind: "group", groupId };
|
|
3956
3969
|
} else {
|
|
3957
3970
|
return;
|
|
3958
3971
|
}
|
|
3972
|
+
this.testConsoleOpen = false;
|
|
3959
3973
|
this.groupPickerOpen = false;
|
|
3960
3974
|
if (returnFocusToGroups) this.focusRequest = "route:groups";
|
|
3961
3975
|
this.closeRenameOnLeave();
|
|
@@ -3984,6 +3998,7 @@ var EditorControllerImpl = class {
|
|
|
3984
3998
|
}
|
|
3985
3999
|
navigateToGroup(groupId) {
|
|
3986
4000
|
this.groupPickerOpen = false;
|
|
4001
|
+
this.testConsoleOpen = false;
|
|
3987
4002
|
const groupIds = new Set(
|
|
3988
4003
|
this.draft.groups.map((group) => typeof group.id === "string" ? group.id : "").filter((id) => id.length > 0)
|
|
3989
4004
|
);
|
|
@@ -4057,6 +4072,7 @@ var EditorControllerImpl = class {
|
|
|
4057
4072
|
}
|
|
4058
4073
|
navigateToSearchResult(path) {
|
|
4059
4074
|
this.groupPickerOpen = false;
|
|
4075
|
+
this.testConsoleOpen = false;
|
|
4060
4076
|
const segments = decodePointer(path);
|
|
4061
4077
|
if (segments?.[0] !== "groups") {
|
|
4062
4078
|
this.route = { kind: "project" };
|
|
@@ -4081,6 +4097,7 @@ var EditorControllerImpl = class {
|
|
|
4081
4097
|
const segments = decodePointer(path);
|
|
4082
4098
|
if (segments?.[0] !== "groups") {
|
|
4083
4099
|
this.route = { kind: "project" };
|
|
4100
|
+
this.testConsoleOpen = false;
|
|
4084
4101
|
this.focusRequest = path;
|
|
4085
4102
|
this.render();
|
|
4086
4103
|
return;
|
|
@@ -4090,6 +4107,7 @@ var EditorControllerImpl = class {
|
|
|
4090
4107
|
const group = this.draft.groups[groupIndex];
|
|
4091
4108
|
if (!group || typeof group.id !== "string") return;
|
|
4092
4109
|
this.route = { kind: "group", groupId: group.id };
|
|
4110
|
+
this.testConsoleOpen = false;
|
|
4093
4111
|
const last = segments[segments.length - 1];
|
|
4094
4112
|
const ruleIndex = arrayIndex(segments[3] ?? "");
|
|
4095
4113
|
const entityPath = last === "name" ? path : segments.length === 2 ? pointer("groups", groupIndex, "name") : segments.length === 4 && ruleIndex !== void 0 ? pointer("groups", groupIndex, "rules", ruleIndex, "name") : path;
|
|
@@ -4134,12 +4152,9 @@ var EditorControllerImpl = class {
|
|
|
4134
4152
|
}
|
|
4135
4153
|
this.renderHeader();
|
|
4136
4154
|
this.renderRail();
|
|
4137
|
-
this.renderCommandBar();
|
|
4138
4155
|
this.form.replaceChildren();
|
|
4139
4156
|
if (this.route.kind === "project") {
|
|
4140
4157
|
this.renderProject();
|
|
4141
|
-
} else if (this.route.kind === "test") {
|
|
4142
|
-
this.renderTest();
|
|
4143
4158
|
} else {
|
|
4144
4159
|
this.renderGroup(this.route.groupId);
|
|
4145
4160
|
}
|
|
@@ -4151,6 +4166,7 @@ var EditorControllerImpl = class {
|
|
|
4151
4166
|
if (this.confirmation) this.groupPickerOpen = false;
|
|
4152
4167
|
this.renderConfirmation();
|
|
4153
4168
|
this.renderGroupPicker();
|
|
4169
|
+
this.renderTestConsole();
|
|
4154
4170
|
this.restoreFocus();
|
|
4155
4171
|
this.focusRequest = void 0;
|
|
4156
4172
|
}
|
|
@@ -4163,7 +4179,13 @@ var EditorControllerImpl = class {
|
|
|
4163
4179
|
dirty.dataset.dirtyState = "true";
|
|
4164
4180
|
dirty.textContent = this.isDirty() ? "Unsaved changes" : "All changes saved";
|
|
4165
4181
|
titleBlock.append(title, dirty);
|
|
4166
|
-
this.
|
|
4182
|
+
const actions = this.document.createElement("div");
|
|
4183
|
+
actions.dataset.editorHeaderActions = "true";
|
|
4184
|
+
actions.setAttribute("role", "toolbar");
|
|
4185
|
+
actions.setAttribute("aria-label", "Project actions");
|
|
4186
|
+
actions.setAttribute("aria-busy", this.saving ? "true" : "false");
|
|
4187
|
+
this.appendProjectActions(actions);
|
|
4188
|
+
this.header.append(titleBlock, actions);
|
|
4167
4189
|
this.status.textContent = this.statusMessage;
|
|
4168
4190
|
this.status.setAttribute("aria-busy", this.saving ? "true" : "false");
|
|
4169
4191
|
}
|
|
@@ -4219,12 +4241,24 @@ var EditorControllerImpl = class {
|
|
|
4219
4241
|
search.setAttribute("aria-controls", "rogatio-search-results");
|
|
4220
4242
|
searchLabel.append(search);
|
|
4221
4243
|
searchWrap.append(searchLabel, this.searchResults);
|
|
4222
|
-
this.
|
|
4244
|
+
const railTools = this.document.createElement("div");
|
|
4245
|
+
railTools.dataset.railTools = "true";
|
|
4246
|
+
const testBtn = this.createButton("Console", "route:test");
|
|
4247
|
+
testBtn.dataset.route = "test";
|
|
4248
|
+
testBtn.dataset.editorKey = "route:test";
|
|
4249
|
+
testBtn.dataset.btn = "secondary";
|
|
4250
|
+
testBtn.disabled = this.saving;
|
|
4251
|
+
testBtn.setAttribute("aria-label", "Test console");
|
|
4252
|
+
testBtn.setAttribute("aria-haspopup", "dialog");
|
|
4253
|
+
testBtn.setAttribute(
|
|
4254
|
+
"aria-expanded",
|
|
4255
|
+
this.testConsoleOpen ? "true" : "false"
|
|
4256
|
+
);
|
|
4257
|
+
testBtn.setAttribute("aria-controls", `${this.instanceId}-test-console`);
|
|
4258
|
+
railTools.append(testBtn, searchWrap);
|
|
4259
|
+
this.rail.append(railTools);
|
|
4223
4260
|
}
|
|
4224
|
-
|
|
4225
|
-
this.commandBar.replaceChildren();
|
|
4226
|
-
this.commandBar.setAttribute("aria-busy", this.saving ? "true" : "false");
|
|
4227
|
-
this.commandBar.setAttribute("aria-label", "Project actions");
|
|
4261
|
+
appendProjectActions(actions) {
|
|
4228
4262
|
const tools = this.document.createElement("div");
|
|
4229
4263
|
tools.dataset.actionCluster = "tools";
|
|
4230
4264
|
if (this.aiAssistPanel) {
|
|
@@ -4232,18 +4266,7 @@ var EditorControllerImpl = class {
|
|
|
4232
4266
|
this.createCommandButton("AI Assist", "ai-assist", this.saving)
|
|
4233
4267
|
);
|
|
4234
4268
|
}
|
|
4235
|
-
|
|
4236
|
-
testBtn.dataset.route = "test";
|
|
4237
|
-
testBtn.dataset.editorKey = "route:test";
|
|
4238
|
-
testBtn.dataset.btn = "secondary";
|
|
4239
|
-
testBtn.disabled = this.saving;
|
|
4240
|
-
if (this.route.kind === "test") {
|
|
4241
|
-
testBtn.setAttribute("aria-current", "page");
|
|
4242
|
-
}
|
|
4243
|
-
tools.append(
|
|
4244
|
-
testBtn,
|
|
4245
|
-
this.createCommandButton("Validate", "validate", this.saving)
|
|
4246
|
-
);
|
|
4269
|
+
tools.append(this.createCommandButton("Validate", "validate", this.saving));
|
|
4247
4270
|
const commit = this.document.createElement("div");
|
|
4248
4271
|
commit.dataset.actionCluster = "commit";
|
|
4249
4272
|
commit.append(
|
|
@@ -4256,7 +4279,7 @@ var EditorControllerImpl = class {
|
|
|
4256
4279
|
"primary"
|
|
4257
4280
|
)
|
|
4258
4281
|
);
|
|
4259
|
-
|
|
4282
|
+
actions.append(tools, commit);
|
|
4260
4283
|
}
|
|
4261
4284
|
createGroupEnableButton(savedGroupId, groupName) {
|
|
4262
4285
|
const enablement = this.options.groupEnablement;
|
|
@@ -4325,27 +4348,7 @@ var EditorControllerImpl = class {
|
|
|
4325
4348
|
}
|
|
4326
4349
|
createProjectActionRow() {
|
|
4327
4350
|
const actions = this.document.createElement("div");
|
|
4328
|
-
|
|
4329
|
-
tools.dataset.actionCluster = "tools";
|
|
4330
|
-
if (this.aiAssistPanel) {
|
|
4331
|
-
tools.append(
|
|
4332
|
-
this.createCommandButton("AI Assist", "ai-assist", this.saving)
|
|
4333
|
-
);
|
|
4334
|
-
}
|
|
4335
|
-
tools.append(this.createCommandButton("Validate", "validate", this.saving));
|
|
4336
|
-
const commit = this.document.createElement("div");
|
|
4337
|
-
commit.dataset.actionCluster = "commit";
|
|
4338
|
-
commit.append(
|
|
4339
|
-
this.createCommandButton("Cancel", "cancel", this.saving),
|
|
4340
|
-
this.createCommandButton(
|
|
4341
|
-
"Save",
|
|
4342
|
-
"save",
|
|
4343
|
-
this.saving || !this.isDirty(),
|
|
4344
|
-
{},
|
|
4345
|
-
"primary"
|
|
4346
|
-
)
|
|
4347
|
-
);
|
|
4348
|
-
actions.append(tools, commit);
|
|
4351
|
+
this.appendProjectActions(actions);
|
|
4349
4352
|
return actions;
|
|
4350
4353
|
}
|
|
4351
4354
|
appendDockRow(dock, label, actions) {
|
|
@@ -4359,9 +4362,9 @@ var EditorControllerImpl = class {
|
|
|
4359
4362
|
dock.append(row);
|
|
4360
4363
|
}
|
|
4361
4364
|
/**
|
|
4362
|
-
* Repeats the actions a long page would otherwise hide
|
|
4363
|
-
*
|
|
4364
|
-
*
|
|
4365
|
+
* Repeats the actions a long group page would otherwise hide, under the last
|
|
4366
|
+
* rule. The project page stays short, so Add group lives on the Groups
|
|
4367
|
+
* heading and that route has no ledger.
|
|
4365
4368
|
*/
|
|
4366
4369
|
renderActionDock() {
|
|
4367
4370
|
if (this.route.kind === "project") return;
|
|
@@ -4539,14 +4542,7 @@ var EditorControllerImpl = class {
|
|
|
4539
4542
|
rulesSection.append(list);
|
|
4540
4543
|
this.form.append(rulesSection);
|
|
4541
4544
|
}
|
|
4542
|
-
|
|
4543
|
-
const heading = this.document.createElement("h2");
|
|
4544
|
-
heading.textContent = "Test console";
|
|
4545
|
-
this.form.append(heading);
|
|
4546
|
-
const description = this.document.createElement("p");
|
|
4547
|
-
description.dataset.testDescription = "true";
|
|
4548
|
-
description.textContent = "Check whether these URLs match your rules. Nothing is contacted, and nothing is saved.";
|
|
4549
|
-
this.form.append(description);
|
|
4545
|
+
renderTestBody(parent) {
|
|
4550
4546
|
const panel = this.document.createElement("div");
|
|
4551
4547
|
panel.dataset.testPanel = "true";
|
|
4552
4548
|
const urlsFieldset = this.document.createElement("fieldset");
|
|
@@ -4626,26 +4622,33 @@ var EditorControllerImpl = class {
|
|
|
4626
4622
|
);
|
|
4627
4623
|
runBtn.dataset.testRun = "true";
|
|
4628
4624
|
panel.append(runBtn);
|
|
4629
|
-
|
|
4625
|
+
parent.append(panel);
|
|
4626
|
+
if (this.testNotice.length > 0 && !this.testRunning && this.testNotice !== "Only 256 URLs can be checked at once.") {
|
|
4627
|
+
const note = this.document.createElement("p");
|
|
4628
|
+
note.dataset.testStatus = "true";
|
|
4629
|
+
note.setAttribute("role", "status");
|
|
4630
|
+
note.textContent = this.testNotice;
|
|
4631
|
+
parent.append(note);
|
|
4632
|
+
}
|
|
4630
4633
|
const resultsSection = this.document.createElement("section");
|
|
4631
4634
|
resultsSection.dataset.testResults = "true";
|
|
4632
|
-
|
|
4635
|
+
parent.append(resultsSection);
|
|
4633
4636
|
if (this.ruleCount() === 0) {
|
|
4634
4637
|
const empty = this.document.createElement("p");
|
|
4635
4638
|
empty.dataset.testEmpty = "true";
|
|
4636
4639
|
empty.textContent = "This project has no rules to test.";
|
|
4637
4640
|
resultsSection.append(empty);
|
|
4638
4641
|
} else if (this.testResult) {
|
|
4639
|
-
this.renderTestResults(this.testResult);
|
|
4642
|
+
this.renderTestResults(this.testResult, parent);
|
|
4640
4643
|
} else if (this.testRunning) {
|
|
4641
4644
|
const pending = this.document.createElement("p");
|
|
4642
4645
|
pending.dataset.testPending = "true";
|
|
4643
4646
|
pending.textContent = "Checking URLs...";
|
|
4644
4647
|
resultsSection.append(pending);
|
|
4645
|
-
} else if (this.
|
|
4648
|
+
} else if (this.testNotice === "Only 256 URLs can be checked at once.") {
|
|
4646
4649
|
const limit = this.document.createElement("p");
|
|
4647
4650
|
limit.dataset.testLimit = "true";
|
|
4648
|
-
limit.textContent = this.
|
|
4651
|
+
limit.textContent = this.testNotice;
|
|
4649
4652
|
resultsSection.append(limit);
|
|
4650
4653
|
}
|
|
4651
4654
|
}
|
|
@@ -5602,7 +5605,100 @@ var EditorControllerImpl = class {
|
|
|
5602
5605
|
}
|
|
5603
5606
|
fields.append(group);
|
|
5604
5607
|
}
|
|
5608
|
+
openTestConsole() {
|
|
5609
|
+
this.groupPickerOpen = false;
|
|
5610
|
+
this.testConsoleOpen = true;
|
|
5611
|
+
this.focusRequest = "test-urls";
|
|
5612
|
+
this.render();
|
|
5613
|
+
}
|
|
5614
|
+
closeTestConsole() {
|
|
5615
|
+
if (this.testRunning) {
|
|
5616
|
+
this.testRequestId += 1;
|
|
5617
|
+
this.testRunning = false;
|
|
5618
|
+
this.testNotice = "";
|
|
5619
|
+
}
|
|
5620
|
+
this.testConsoleOpen = false;
|
|
5621
|
+
this.focusRequest = "route:test";
|
|
5622
|
+
this.render();
|
|
5623
|
+
}
|
|
5624
|
+
trapTestConsoleFocus(event) {
|
|
5625
|
+
const dialog = this.host.querySelector("[data-test-dialog]");
|
|
5626
|
+
if (!(dialog instanceof HTMLElement)) return;
|
|
5627
|
+
const focusable = Array.from(
|
|
5628
|
+
dialog.querySelectorAll(
|
|
5629
|
+
"button, input, select, textarea, summary, a[href]"
|
|
5630
|
+
)
|
|
5631
|
+
).filter((element) => {
|
|
5632
|
+
if (element.hidden) return false;
|
|
5633
|
+
const closedDetails = element.closest("details:not([open])");
|
|
5634
|
+
if (closedDetails && element !== closedDetails.querySelector("summary")) {
|
|
5635
|
+
return false;
|
|
5636
|
+
}
|
|
5637
|
+
if (element instanceof HTMLButtonElement || element instanceof HTMLInputElement || element instanceof HTMLSelectElement || element instanceof HTMLTextAreaElement) {
|
|
5638
|
+
return !element.disabled;
|
|
5639
|
+
}
|
|
5640
|
+
return true;
|
|
5641
|
+
});
|
|
5642
|
+
const first = focusable[0];
|
|
5643
|
+
const last = focusable[focusable.length - 1];
|
|
5644
|
+
if (!first || !last) return;
|
|
5645
|
+
const active = this.document.activeElement;
|
|
5646
|
+
const inside = active instanceof Node && dialog.contains(active);
|
|
5647
|
+
if (!inside) {
|
|
5648
|
+
event.preventDefault();
|
|
5649
|
+
(event.shiftKey ? last : first).focus();
|
|
5650
|
+
return;
|
|
5651
|
+
}
|
|
5652
|
+
if (event.shiftKey && active === first) {
|
|
5653
|
+
event.preventDefault();
|
|
5654
|
+
last.focus();
|
|
5655
|
+
return;
|
|
5656
|
+
}
|
|
5657
|
+
if (!event.shiftKey && active === last) {
|
|
5658
|
+
event.preventDefault();
|
|
5659
|
+
first.focus();
|
|
5660
|
+
}
|
|
5661
|
+
}
|
|
5662
|
+
renderTestConsole() {
|
|
5663
|
+
this.host.querySelector("[data-test-console]")?.remove();
|
|
5664
|
+
if ("inert" in this.layout) this.layout.inert = this.testConsoleOpen;
|
|
5665
|
+
if (!this.testConsoleOpen) return;
|
|
5666
|
+
const overlay = this.document.createElement("div");
|
|
5667
|
+
overlay.dataset.testConsole = "true";
|
|
5668
|
+
overlay.setAttribute("role", "presentation");
|
|
5669
|
+
const dialog = this.document.createElement("section");
|
|
5670
|
+
dialog.dataset.testDialog = "true";
|
|
5671
|
+
dialog.id = `${this.instanceId}-test-console`;
|
|
5672
|
+
dialog.setAttribute("role", "dialog");
|
|
5673
|
+
dialog.setAttribute("aria-modal", "true");
|
|
5674
|
+
const head = this.document.createElement("div");
|
|
5675
|
+
head.dataset.testDialogHead = "true";
|
|
5676
|
+
const titles = this.document.createElement("div");
|
|
5677
|
+
const kicker = this.document.createElement("p");
|
|
5678
|
+
kicker.dataset.testKicker = "true";
|
|
5679
|
+
kicker.textContent = "Offline match";
|
|
5680
|
+
const heading = this.document.createElement("h2");
|
|
5681
|
+
heading.id = `${this.instanceId}-test-console-title`;
|
|
5682
|
+
heading.textContent = "Test console";
|
|
5683
|
+
dialog.setAttribute("aria-labelledby", heading.id);
|
|
5684
|
+
const description = this.document.createElement("p");
|
|
5685
|
+
description.dataset.testDescription = "true";
|
|
5686
|
+
description.textContent = "Check whether these URLs match your rules. Nothing is contacted, and nothing is saved.";
|
|
5687
|
+
titles.append(kicker, heading, description);
|
|
5688
|
+
const close = this.createButton("Close", "test-console-close");
|
|
5689
|
+
close.dataset.command = "close-test-console";
|
|
5690
|
+
close.dataset.editorKey = "test-console-close";
|
|
5691
|
+
close.dataset.btn = "secondary";
|
|
5692
|
+
head.append(titles, close);
|
|
5693
|
+
const body = this.document.createElement("div");
|
|
5694
|
+
body.dataset.testDialogBody = "true";
|
|
5695
|
+
this.renderTestBody(body);
|
|
5696
|
+
dialog.append(head, body);
|
|
5697
|
+
overlay.append(dialog);
|
|
5698
|
+
this.host.append(overlay);
|
|
5699
|
+
}
|
|
5605
5700
|
openGroupPicker() {
|
|
5701
|
+
this.testConsoleOpen = false;
|
|
5606
5702
|
this.groupPickerOpen = true;
|
|
5607
5703
|
this.focusRequest = this.draft.groups.length > 0 ? "group-picker-first" : "group-picker-close";
|
|
5608
5704
|
this.render();
|
package/package.json
CHANGED