chrome-devtools-frontend 1.0.1702515 → 1.0.1703574
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/front_end/core/common/ParsedURL.ts +5 -1
- package/front_end/core/text_utils/Markdown.ts +73 -0
- package/front_end/core/text_utils/text_utils.ts +2 -0
- package/front_end/generated/InspectorBackendCommands.ts +3 -1
- package/front_end/generated/protocol-mapping.d.ts +8 -0
- package/front_end/generated/protocol-proxy-api.d.ts +6 -0
- package/front_end/generated/protocol.ts +22 -0
- package/front_end/models/comment_manager/CD4ABridge.ts +5 -0
- package/front_end/models/issues_manager/MarkdownIssueDescription.ts +4 -47
- package/front_end/models/persistence/AutomaticFileSystemWorkspaceBinding.ts +1 -1
- package/front_end/panels/common/CommentsStatusBarPill.ts +40 -7
- package/front_end/panels/common/commentsStatusBarPill.css +13 -0
- package/front_end/panels/issues/IssueView.ts +5 -1
- package/front_end/panels/sources/SourcesView.ts +127 -147
- package/front_end/panels/sources/TabbedEditorContainer.ts +266 -207
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/markdown_view/MarkdownPlaceholderLitRenderer.ts +7 -65
- package/front_end/ui/legacy/TabbedPane.ts +51 -40
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +342 -373
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- package/package.json +2 -1
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
import * as Platform from '../../../core/platform/platform.js';
|
|
6
|
-
import * as
|
|
6
|
+
import * as TextUtils from '../../../core/text_utils/text_utils.js';
|
|
7
|
+
import type * as Marked from '../../../third_party/marked/marked.js';
|
|
7
8
|
import * as Lit from '../../lit/lit.js';
|
|
8
9
|
|
|
9
10
|
import {getMarkdownLink} from './MarkdownLinksMap.js';
|
|
@@ -11,69 +12,9 @@ import {MarkdownLitRenderer} from './MarkdownView.js';
|
|
|
11
12
|
|
|
12
13
|
const {html} = Lit;
|
|
13
14
|
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
key: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const validPlaceholderMatchPattern = /\{(PLACEHOLDER_[a-zA-Z][a-zA-Z0-9_]*)\}/g;
|
|
21
|
-
const validPlaceholderNamePattern = /^PLACEHOLDER_[a-zA-Z][a-zA-Z0-9_]*$/;
|
|
22
|
-
|
|
23
|
-
const placeholderExtension: Marked.Marked.TokenizerExtension = {
|
|
24
|
-
name: 'placeholder',
|
|
25
|
-
level: 'inline',
|
|
26
|
-
start(src: string): number |
|
|
27
|
-
undefined {
|
|
28
|
-
return src.match(/\{PLACEHOLDER_[a-zA-Z][a-zA-Z0-9_]*\}/)?.index;
|
|
29
|
-
},
|
|
30
|
-
tokenizer(src: string): PlaceholderToken |
|
|
31
|
-
undefined {
|
|
32
|
-
const match = /^\{(PLACEHOLDER_[a-zA-Z][a-zA-Z0-9_]*)\}/.exec(src);
|
|
33
|
-
if (match) {
|
|
34
|
-
return {
|
|
35
|
-
type: 'placeholder',
|
|
36
|
-
raw: match[0],
|
|
37
|
-
key: match[1],
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
return undefined;
|
|
41
|
-
},
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
function validateSubstitutions(rawMarkdown: string, substitutions?: Map<string, string>): void {
|
|
45
|
-
if (!substitutions) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
const unusedPlaceholders = new Set(substitutions.keys());
|
|
49
|
-
for (const key of unusedPlaceholders) {
|
|
50
|
-
if (!validPlaceholderNamePattern.test(key)) {
|
|
51
|
-
throw new Error(`Invalid placeholder '${key}' provided in the substitutions map.`);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
for (const [, placeholder] of rawMarkdown.matchAll(validPlaceholderMatchPattern)) {
|
|
55
|
-
if (!substitutions.has(placeholder)) {
|
|
56
|
-
throw new Error(`No replacement provided for placeholder '${placeholder}'.`);
|
|
57
|
-
}
|
|
58
|
-
unusedPlaceholders.delete(placeholder);
|
|
59
|
-
}
|
|
60
|
-
if (unusedPlaceholders.size > 0) {
|
|
61
|
-
throw new Error(`Unused replacements provided: ${[...unusedPlaceholders]}`);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function tokenizeWithPlaceholders(markdown: string|Marked.Marked.Token[],
|
|
66
|
-
substitutions?: Map<string, string>): Marked.Marked.Token[] {
|
|
67
|
-
const rawMarkdown = typeof markdown === 'string' ? markdown : markdown.map(token => token.raw).join('');
|
|
68
|
-
validateSubstitutions(rawMarkdown, substitutions);
|
|
69
|
-
if (typeof markdown !== 'string' && !rawMarkdown.includes('{PLACEHOLDER_')) {
|
|
70
|
-
return markdown;
|
|
71
|
-
}
|
|
72
|
-
const markedInstance = new Marked.Marked.Marked({
|
|
73
|
-
extensions: [placeholderExtension],
|
|
74
|
-
});
|
|
75
|
-
return markedInstance.lexer(rawMarkdown);
|
|
76
|
-
}
|
|
15
|
+
export type PlaceholderToken = TextUtils.Markdown.PlaceholderToken;
|
|
16
|
+
export const tokenizeWithPlaceholders: (markdown: string|Marked.Marked.Token[], substitutions?: Map<string, string>) =>
|
|
17
|
+
Marked.Marked.Token[] = TextUtils.Markdown.tokenizeWithPlaceholders;
|
|
77
18
|
|
|
78
19
|
export class MarkdownPlaceholderLitRenderer extends MarkdownLitRenderer {
|
|
79
20
|
readonly #substitutions?: Map<string, string>;
|
|
@@ -89,7 +30,8 @@ export class MarkdownPlaceholderLitRenderer extends MarkdownLitRenderer {
|
|
|
89
30
|
}
|
|
90
31
|
|
|
91
32
|
override unescape(text: string): string {
|
|
92
|
-
return super.unescape(text).replace(
|
|
33
|
+
return super.unescape(text).replace(TextUtils.Markdown.VALID_PLACEHOLDER_MATCH_PATTERN,
|
|
34
|
+
(raw, key) => this.#resolvePlaceholder(key, raw));
|
|
93
35
|
}
|
|
94
36
|
|
|
95
37
|
override templateForToken(token: Marked.Marked.MarkedToken): Lit.LitTemplate|null {
|
|
@@ -8,7 +8,7 @@ import * as Common from '../../core/common/common.js';
|
|
|
8
8
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
9
9
|
import * as Platform from '../../core/platform/platform.js';
|
|
10
10
|
import * as Buttons from '../../ui/components/buttons/buttons.js';
|
|
11
|
-
import {type LitTemplate, render} from '../../ui/lit/lit.js';
|
|
11
|
+
import {type LitTemplate, nothing, render} from '../../ui/lit/lit.js';
|
|
12
12
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
13
13
|
import * as Geometry from '../geometry/geometry.js';
|
|
14
14
|
import {createIcon, Icon} from '../kit/kit.js';
|
|
@@ -105,7 +105,7 @@ export class TabbedPane extends TabbedPaneBase {
|
|
|
105
105
|
private delegate?: TabbedPaneTabDelegate;
|
|
106
106
|
private currentTab?: TabbedPaneTab;
|
|
107
107
|
private sliderEnabled?: boolean;
|
|
108
|
-
private placeholderElement?: Element;
|
|
108
|
+
private placeholderElement?: Element|LitTemplate;
|
|
109
109
|
private focusedPlaceholderElement?: Element;
|
|
110
110
|
private placeholderContainerElement?: HTMLElement;
|
|
111
111
|
private lastSelectedOverflowTab?: TabbedPaneTab;
|
|
@@ -184,7 +184,6 @@ export class TabbedPane extends TabbedPaneBase {
|
|
|
184
184
|
this.currentDevicePixelRatio = window.devicePixelRatio;
|
|
185
185
|
ZoomManager.instance().addEventListener(ZoomManagerEvents.ZOOM_CHANGED, this.zoomChanged, this);
|
|
186
186
|
this.makeTabSlider();
|
|
187
|
-
|
|
188
187
|
}
|
|
189
188
|
|
|
190
189
|
setAccessibleName(name: string): void {
|
|
@@ -271,9 +270,8 @@ export class TabbedPane extends TabbedPaneBase {
|
|
|
271
270
|
this.delegate = delegate;
|
|
272
271
|
}
|
|
273
272
|
|
|
274
|
-
appendTab(
|
|
275
|
-
|
|
276
|
-
isPreviewFeature?: boolean, index?: number, jslogContext?: string): void {
|
|
273
|
+
appendTab(id: string, tabTitle: string, view: AnyWidget, tabTooltip?: string, userGesture?: boolean,
|
|
274
|
+
isCloseable?: boolean, isPreviewFeature?: boolean, index?: number, jslogContext?: string): void {
|
|
277
275
|
const closeable = typeof isCloseable === 'boolean' ? isCloseable : Boolean(this.closeableTabs);
|
|
278
276
|
const tab =
|
|
279
277
|
new TabbedPaneTab(this, id, tabTitle, closeable, Boolean(isPreviewFeature), view, tabTooltip, jslogContext);
|
|
@@ -620,14 +618,19 @@ export class TabbedPane extends TabbedPaneBase {
|
|
|
620
618
|
return constraints;
|
|
621
619
|
}
|
|
622
620
|
|
|
623
|
-
setPlaceholderElement(element: Element, focusedElement?: Element): void {
|
|
621
|
+
setPlaceholderElement(element: Element|LitTemplate, focusedElement?: Element): void {
|
|
624
622
|
this.placeholderElement = element;
|
|
625
623
|
if (focusedElement) {
|
|
626
624
|
this.focusedPlaceholderElement = focusedElement;
|
|
627
625
|
}
|
|
628
626
|
if (this.placeholderContainerElement) {
|
|
629
|
-
|
|
630
|
-
|
|
627
|
+
if (element instanceof Element) {
|
|
628
|
+
render(nothing, this.placeholderContainerElement);
|
|
629
|
+
this.placeholderContainerElement.removeChildren();
|
|
630
|
+
this.placeholderContainerElement.appendChild(element);
|
|
631
|
+
} else {
|
|
632
|
+
render(element, this.placeholderContainerElement);
|
|
633
|
+
}
|
|
631
634
|
}
|
|
632
635
|
}
|
|
633
636
|
|
|
@@ -644,7 +647,11 @@ export class TabbedPane extends TabbedPaneBase {
|
|
|
644
647
|
this.#contentElement.classList.add('has-no-tabs');
|
|
645
648
|
if (this.placeholderElement && !this.placeholderContainerElement) {
|
|
646
649
|
this.placeholderContainerElement = this.#contentElement.createChild('div', 'tabbed-pane-placeholder fill');
|
|
647
|
-
|
|
650
|
+
if (this.placeholderElement instanceof Element) {
|
|
651
|
+
this.placeholderContainerElement.appendChild(this.placeholderElement);
|
|
652
|
+
} else {
|
|
653
|
+
render(this.placeholderElement, this.placeholderContainerElement);
|
|
654
|
+
}
|
|
648
655
|
if (this.focusedPlaceholderElement) {
|
|
649
656
|
this.setDefaultFocusedElement(this.focusedPlaceholderElement);
|
|
650
657
|
}
|
|
@@ -675,10 +682,9 @@ export class TabbedPane extends TabbedPaneBase {
|
|
|
675
682
|
if (!this.#rightToolbar.hasCompactLayout() &&
|
|
676
683
|
totalWidth - rightToolbarWidth - leftToolbarWidth < this.measuredDropDownButtonWidth + 10) {
|
|
677
684
|
this.#rightToolbar.setCompactLayout(true);
|
|
678
|
-
} else if (
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
totalWidth - 2 * rightToolbarWidth - leftToolbarWidth > this.measuredDropDownButtonWidth + 10) {
|
|
685
|
+
} else if (this.#rightToolbar.hasCompactLayout() &&
|
|
686
|
+
// Estimate the right toolbar size in non-compact mode as 2 times its compact size.
|
|
687
|
+
totalWidth - 2 * rightToolbarWidth - leftToolbarWidth > this.measuredDropDownButtonWidth + 10) {
|
|
682
688
|
this.#rightToolbar.setCompactLayout(false);
|
|
683
689
|
}
|
|
684
690
|
}
|
|
@@ -732,11 +738,11 @@ export class TabbedPane extends TabbedPaneBase {
|
|
|
732
738
|
continue;
|
|
733
739
|
}
|
|
734
740
|
if (this.numberOfTabsShown() === 0 && this.tabsHistory[0] === tab) {
|
|
735
|
-
menu.defaultSection().appendCheckboxItem(
|
|
736
|
-
|
|
741
|
+
menu.defaultSection().appendCheckboxItem(tab.title, this.dropDownMenuItemSelected.bind(this, tab),
|
|
742
|
+
{checked: true, jslogContext: tab.jslogContext});
|
|
737
743
|
} else {
|
|
738
|
-
menu.defaultSection().appendItem(
|
|
739
|
-
|
|
744
|
+
menu.defaultSection().appendItem(tab.title, this.dropDownMenuItemSelected.bind(this, tab),
|
|
745
|
+
{jslogContext: tab.jslogContext});
|
|
740
746
|
}
|
|
741
747
|
}
|
|
742
748
|
void menu.show().then(() => ARIAUtils.setExpanded(this.dropDownButton, menu.isHostedMenuOpen()));
|
|
@@ -996,9 +1002,8 @@ export class TabbedPane extends TabbedPaneBase {
|
|
|
996
1002
|
return totalWidth / measuredWidths.length;
|
|
997
1003
|
}
|
|
998
1004
|
|
|
999
|
-
private tabsToShowIndexes(
|
|
1000
|
-
|
|
1001
|
-
measuredDropDownButtonWidth: number): number[] {
|
|
1005
|
+
private tabsToShowIndexes(tabsOrdered: TabbedPaneTab[], tabsHistory: TabbedPaneTab[], totalWidth: number,
|
|
1006
|
+
measuredDropDownButtonWidth: number): number[] {
|
|
1002
1007
|
const tabsToShowIndexes = [];
|
|
1003
1008
|
|
|
1004
1009
|
let totalTabsWidth = 0;
|
|
@@ -1222,9 +1227,8 @@ export class TabbedPaneTab {
|
|
|
1222
1227
|
private titleElement?: HTMLElement;
|
|
1223
1228
|
private dragStartX?: number;
|
|
1224
1229
|
#jslogContext?: string;
|
|
1225
|
-
constructor(
|
|
1226
|
-
|
|
1227
|
-
tooltip?: string, jslogContext?: string) {
|
|
1230
|
+
constructor(tabbedPane: TabbedPane, id: string, title: string, closeable: boolean, previewFeature: boolean,
|
|
1231
|
+
view: AnyWidget, tooltip?: string, jslogContext?: string) {
|
|
1228
1232
|
this.closeable = closeable;
|
|
1229
1233
|
this.previewFeature = previewFeature;
|
|
1230
1234
|
this.tabbedPane = tabbedPane;
|
|
@@ -1427,9 +1431,8 @@ export class TabbedPaneTab {
|
|
|
1427
1431
|
|
|
1428
1432
|
tabElement.addEventListener('contextmenu', this.tabContextMenu.bind(this), false);
|
|
1429
1433
|
if (this.tabbedPane.allowTabReorder) {
|
|
1430
|
-
installDragHandle(
|
|
1431
|
-
|
|
1432
|
-
null, null, 200);
|
|
1434
|
+
installDragHandle(tabElement, this.startTabDragging.bind(this), this.tabDragging.bind(this),
|
|
1435
|
+
this.endTabDragging.bind(this), null, null, 200);
|
|
1433
1436
|
}
|
|
1434
1437
|
}
|
|
1435
1438
|
|
|
@@ -1542,25 +1545,24 @@ export class TabbedPaneTab {
|
|
|
1542
1545
|
const contextMenu = new ContextMenu(event);
|
|
1543
1546
|
if (this.closeable) {
|
|
1544
1547
|
contextMenu.defaultSection().appendItem(i18nString(UIStrings.close), close.bind(this), {jslogContext: 'close'});
|
|
1545
|
-
contextMenu.defaultSection().appendItem(
|
|
1546
|
-
|
|
1547
|
-
contextMenu.defaultSection().appendItem(
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
i18nString(UIStrings.closeAll), closeAll.bind(this), {jslogContext: 'close-all'});
|
|
1548
|
+
contextMenu.defaultSection().appendItem(i18nString(UIStrings.closeOthers), closeOthers.bind(this),
|
|
1549
|
+
{jslogContext: 'close-others'});
|
|
1550
|
+
contextMenu.defaultSection().appendItem(i18nString(UIStrings.closeTabsToTheRight), closeToTheRight.bind(this),
|
|
1551
|
+
{jslogContext: 'close-tabs-to-the-right'});
|
|
1552
|
+
contextMenu.defaultSection().appendItem(i18nString(UIStrings.closeAll), closeAll.bind(this),
|
|
1553
|
+
{jslogContext: 'close-all'});
|
|
1552
1554
|
}
|
|
1553
1555
|
if (this.delegate) {
|
|
1554
1556
|
this.delegate.onContextMenu(this.id, contextMenu);
|
|
1555
1557
|
}
|
|
1556
1558
|
const tabIndex = this.tabbedPane.getTabIndex(this.id);
|
|
1557
1559
|
if (tabIndex > 0) {
|
|
1558
|
-
contextMenu.defaultSection().appendItem(
|
|
1559
|
-
|
|
1560
|
+
contextMenu.defaultSection().appendItem(i18nString(UIStrings.moveTabLeft), moveTabBackward.bind(this, tabIndex),
|
|
1561
|
+
{jslogContext: 'move-tab-backward'});
|
|
1560
1562
|
}
|
|
1561
1563
|
if (tabIndex < this.tabbedPane.tabsElement.childNodes.length - 1) {
|
|
1562
|
-
contextMenu.defaultSection().appendItem(
|
|
1563
|
-
|
|
1564
|
+
contextMenu.defaultSection().appendItem(i18nString(UIStrings.moveTabRight), moveTabForward.bind(this, tabIndex),
|
|
1565
|
+
{jslogContext: 'move-tab-forward'});
|
|
1564
1566
|
}
|
|
1565
1567
|
void contextMenu.show();
|
|
1566
1568
|
}
|
|
@@ -1673,13 +1675,19 @@ export class TabbedPaneElement extends WidgetElement<TabbedPane> {
|
|
|
1673
1675
|
this.getWidget()?.setTabDelegate(delegate);
|
|
1674
1676
|
}
|
|
1675
1677
|
|
|
1676
|
-
#placeholderElement?: Element;
|
|
1678
|
+
#placeholderElement?: Element|LitTemplate;
|
|
1679
|
+
#headerJslog?: string;
|
|
1677
1680
|
#managedTabIds = new Set<string>();
|
|
1678
|
-
set placeholder(element: Element) {
|
|
1681
|
+
set placeholder(element: Element|LitTemplate) {
|
|
1679
1682
|
this.#placeholderElement = element;
|
|
1680
1683
|
this.getWidget()?.setPlaceholderElement(element);
|
|
1681
1684
|
}
|
|
1682
1685
|
|
|
1686
|
+
set headerJslog(jslog: string) {
|
|
1687
|
+
this.#headerJslog = jslog;
|
|
1688
|
+
this.getWidget()?.headerElement().setAttribute('jslog', jslog);
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1683
1691
|
readonly #tabObserver = new MutationObserver(() => this.#updateTabs());
|
|
1684
1692
|
|
|
1685
1693
|
constructor() {
|
|
@@ -1693,6 +1701,9 @@ export class TabbedPaneElement extends WidgetElement<TabbedPane> {
|
|
|
1693
1701
|
if (this.#delegate) {
|
|
1694
1702
|
widget.setTabDelegate(this.#delegate);
|
|
1695
1703
|
}
|
|
1704
|
+
if (this.#headerJslog) {
|
|
1705
|
+
widget.headerElement().setAttribute('jslog', this.#headerJslog);
|
|
1706
|
+
}
|
|
1696
1707
|
const slot = widget.contentElement.querySelector('slot:not([name])');
|
|
1697
1708
|
if (slot) {
|
|
1698
1709
|
slot.addEventListener('slotchange', () => this.#syncTabs());
|