Last active
March 31, 2025 06:16
-
-
Save gnaggnoyil/abb9e9ce5e076aabae3bcd97b3ba8653 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: AGPL-3.0-only | |
// Tested under VS Code 1.98.2 | |
'use strict'; | |
window.onload = (event) => { | |
const _has_class = (node_element, class_name) => { | |
if(node_element.nodeType !== Node.ELEMENT_NODE){ | |
return false; | |
} | |
return node_element.classList.contains(class_name); | |
}; | |
class _async_gen_queue{ | |
#m_pending_values; | |
#m_pending_continuations; | |
constructor(initial_values){ | |
this.#m_pending_values = [...initial_values]; | |
this.#m_pending_continuations = []; | |
} | |
_push_value(value){ | |
if(this.#m_pending_continuations.length === 0){ | |
this.#m_pending_values.push(value); | |
return ; | |
} | |
let first_continuation = this.#m_pending_continuations.shift(); | |
first_continuation({ done: false, value: value }); | |
return ; | |
} | |
#_push_continuation(continuation){ | |
if(this.#m_pending_values.length === 0){ | |
this.#m_pending_continuations.push(continuation); | |
return ; | |
} | |
let first_value = this.#m_pending_values.shift(); | |
continuation({ done: false, value: first_value }); | |
return ; | |
} | |
next(){ | |
return new Promise((resolve, reject) => { | |
this.#_push_continuation(resolve); | |
return ; | |
}); | |
} | |
}; // class _async_gen_queue | |
class _children_of{ | |
// We don't store m_target and m_target_ob so that they can just be | |
// GC-ed without the disruption of our `children_of` object. | |
// Actually if ECMAScript supports `protected` members we could have put | |
// `_async_gen_queue` as base class instead of class members since this | |
// will allow `_children_of` to add other optionally needed member | |
// functions of iterator protocol to `_async_gen_queue` more easily. | |
#m_iterator_queue; | |
constructor(target){ | |
this.#m_iterator_queue = new _async_gen_queue(target.childNodes); | |
let target_ob = new MutationObserver((mutations, observer) => { | |
for(const mutation of mutations){ | |
if(mutation.addedNodes.length === 0){ | |
continue; | |
} | |
for(const child of mutation.addedNodes){ | |
this.#m_iterator_queue._push_value(child); | |
} | |
} | |
}); | |
target_ob.observe(target, { childList: true }); | |
} | |
[Symbol.asyncIterator](){ | |
return this.#m_iterator_queue; | |
} | |
}; // class _children_of | |
class _descendants_of{ | |
#m_iterator_queue; | |
async #start_awaiting_impl(current_target, class_selectors, current_depth){ | |
if(current_depth === class_selectors.length){ | |
// Should happen only if `class_selectors.length === 0`; | |
return ; | |
} | |
const current_class_selector = class_selectors[current_depth]; | |
for await(let child of new _children_of(current_target)){ | |
if(!_has_class(child, current_class_selector)){ | |
continue; | |
} | |
if((current_depth + 1) === class_selectors.length){ | |
this.#m_iterator_queue._push_value(child); | |
continue; | |
} | |
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for#lexical_declarations_in_the_initialization_block | |
setTimeout(async () => { await this.#start_awaiting_impl(child, class_selectors, current_depth + 1); }); | |
} | |
} | |
constructor(target, class_selectors){ | |
this.#m_iterator_queue = new _async_gen_queue([]); | |
setTimeout(async () => { await this.#start_awaiting_impl(target, class_selectors, 0); }); | |
} | |
[Symbol.asyncIterator](){ | |
return this.#m_iterator_queue; | |
} | |
}; // class _descendants_of | |
const CSS_PATCH_TEXT = ` | |
:host-context(.windows:lang(zh-Hans)), :host-context(.windows:lang(en)) { font-family: "Sarasa Fixed SC", monospace !important; } | |
:host-context(.windows:lang(zh-Hant)) { font-family: "Sarasa Fixed TC", monospace !important; } | |
:host-context(.windows:lang(ja)) { font-family: "Sarasa Fixed J", monospace !important; } | |
:host-context(.windows:lang(ko)) { font-family: "Sarasa Fixed K", monospace !important; } | |
:host-context(.linux:lang(zh-Hans)), :host-context(.linux:lang(en)) { font-family: "Sarasa Fixed SC", monospace !important; } | |
:host-context(.linux:lang(zh-Hant)) { font-family: "Sarasa Fixed TC", monospace !important; } | |
:host-context(.linux:lang(ja)) { font-family: "Sarasa Fixed J", monospace !important; } | |
:host-context(.linux:lang(ko)) { font-family: "Sarasa Fixed K", monospace !important; } | |
:host-context(.mac:lang(zh-Hans)), :host-context(.mac:lang(en)) { font-family: "Sarasa Fixed SC", monospace !important; } | |
:host-context(.mac:lang(zh-Hant)) { font-family: "Sarasa Fixed TC", monospace !important; } | |
:host-context(.mac:lang(ja)) { font-family: "Sarasa Fixed J", monospace !important; } | |
:host-context(.mac:lang(ko)) { font-family: "Sarasa Fixed K", monospace !important; } | |
`; | |
const _handle_shadow_root_host = async (shadow_root_host) => { | |
// It seems that by the time a `.shadow-root-host` is created, its | |
// shadow root element is already present. | |
//let css_patch = new CSSStyleSheet(); | |
//await css_patch.replace(CSS_PATCH_TEXT); | |
//let shadow_root = shadow_root_host.shadowRoot; | |
//shadow_root.adoptedStyleSheets.push(css_patch); | |
let shadow_root = shadow_root_host.shadowRoot; | |
let set_of_style = shadow_root.querySelectorAll("style"); | |
let set_of_style_of_no_attribute = []; | |
for(let style of set_of_style){ | |
if(style.attributes.length === 0){ | |
set_of_style_of_no_attribute.push(style); | |
} | |
} | |
if(set_of_style_of_no_attribute.length !== 1){ | |
console.log(`error: set_of_style_of_no_attribute.length ${set_of_style_of_no_attribute.length}`); | |
return ; | |
} | |
let style = set_of_style_of_no_attribute[0]; | |
let new_css_text = `${CSS_PATCH_TEXT}\n${style.textContent}`; | |
style.textContent = new_css_text; | |
return ; | |
}; | |
const dom_visited = (element) => { | |
if(element.hasAttribute("_custom_css_and_js_custom_fonts_visited")){ | |
return true; | |
} | |
element.setAttribute("_custom_css_and_js_custom_fonts_visited", ""); | |
return false; | |
}; | |
const _handle_editor_group_container = async (editor_group_container) => { | |
let gen_of_shadow_root_host = new _descendants_of( | |
editor_group_container, | |
[ | |
"editor-container", | |
"editor-instance", | |
"monaco-editor", | |
"shadow-root-host" | |
] | |
); | |
for await(let shadow_root_host of gen_of_shadow_root_host){ | |
// It is possible the same `.shadow-root-host` is counted for | |
// multiple times, due to either being added then removed and then | |
// added, or anything else. We need to mark and check the "visited" | |
// flag first. | |
if(dom_visited(shadow_root_host)){ | |
continue; | |
} | |
setTimeout(async () => { await _handle_shadow_root_host(shadow_root_host); }); | |
} | |
}; | |
// Handle every | |
// `.monaco-grid-branch-node:has(> .monaco-split-view2 > .monaco-scrollable-element > .split-view-container > .split-view-view)` | |
// which is the descendant or itself of `monaco_grid_branch_node` that | |
// either: | |
// 1. it has a direct child of `.editor-group-container` (thus is the | |
// direct level of parent wrapper of the `.monaco-editor` we are looking | |
// at), or | |
// 2. it is (potentially) one of the parent wrappers of the | |
// `.monaco-grid-branch-node:has(> .monaco-split-view2 > .monaco-scrollable-element > .split-view-container > .split-view-view)`s | |
// mentioned in point 1 above. | |
const _handle_monaco_grid_branch_node = async (monaco_grid_branch_node) => { | |
let gen_of_split_view_view = new _descendants_of( | |
monaco_grid_branch_node, | |
[ | |
"monaco-split-view2", | |
"monaco-scrollable-element", | |
"split-view-container", | |
"split-view-view" | |
] | |
); | |
for await(let split_view_view of gen_of_split_view_view){ | |
setTimeout(async () => { | |
for await(let child of new _children_of(split_view_view)){ | |
if(_has_class(child, "monaco-grid-branch-node")){ | |
setTimeout(async () => { await _handle_monaco_grid_branch_node(child); }); | |
continue; | |
} | |
if(_has_class(child, "editor-group-container")){ | |
setTimeout(async () => { await _handle_editor_group_container(child); }); | |
continue; | |
} | |
continue; | |
} | |
}); | |
} | |
}; | |
// Handle `.shadow-root-host` appeared in title bar after "Command Center" | |
// is activated and made appeared by user. | |
const _handle_command_center = async (command_center) => { | |
let gen_of_shadow_root_host = new _descendants_of( | |
command_center, | |
[ | |
"monaco-toolbar", | |
"monaco-action-bar", | |
"actions-container", // actually this is a `ul` | |
// Actually this is also an `.action-item`, and the | |
// `.shadow-host-root` in it seems to be going to be refreshed | |
// each time the "arrow left" or "arrow right" button in | |
// other `.action-item`s are pressed and triggered. | |
"monaco-dropdown-with-primary", | |
"dropdown-action-container", | |
"monaco-dropdown", | |
"shadow-root-host" | |
] | |
); | |
for await(let shadow_root_host of gen_of_shadow_root_host){ | |
if(dom_visited(shadow_root_host)){ | |
continue; | |
} | |
setTimeout(async () => { await _handle_shadow_root_host(shadow_root_host); }); | |
} | |
}; | |
const main_async = async () => { | |
let set_of_body = [...document.getElementsByTagName("body")]; | |
for(let body of set_of_body){ | |
// It seems that when `window.onload`, `body` is just empty. | |
let gen_of_monaco_workbench = new _descendants_of(body, ["monaco-workbench"]); | |
for await(let monaco_workbench of gen_of_monaco_workbench){ | |
// It seems that | |
// `.editor > .content > .grid-view-container > .monaco-grid-view` | |
// is already present as long as dom is added to `body` and will | |
// not be re-added. And this element is the deepest element that | |
// will not be replaced by any of its copies since its | |
// appearance. | |
// Note: There are many `.monaco-grid-view`s in the ancestors of | |
// the final `.monaco-editor` we want to locate. But by using | |
// this specific CSS selector we select the `.monaco-grid-view` | |
// we need, so that we don't receive multiple | |
// `.monaco-grid-view`s for a single `.monaco-editor`. | |
let set_of_monaco_grid_view_in_editor = monaco_workbench.querySelectorAll( | |
".editor > .content > .grid-view-container > .monaco-grid-view" | |
); | |
setTimeout(async () => { | |
for(let monaco_grid_view_in_editor of set_of_monaco_grid_view_in_editor){ | |
for await(let monaco_grid_branch_node of new _descendants_of(monaco_grid_view_in_editor, ["monaco-grid-branch-node"])){ | |
setTimeout(async () => { await _handle_monaco_grid_branch_node(monaco_grid_branch_node); }); | |
} | |
} | |
}); | |
// It seems that | |
// `.titlebar > .titlebar-container > .titlebar-center > .window-title` | |
// is already present as long as dom is added to `body` and will | |
// not be re-added. And this element is the deepest element that | |
// will not be replaced by any of its copies since its | |
// appearance. | |
let set_of_window_title_in_titlebar = monaco_workbench.querySelectorAll( | |
".titlebar > .titlebar-container > .titlebar-center > .window-title" | |
); | |
setTimeout(async () => { | |
for(let window_title_in_titlebar of set_of_window_title_in_titlebar){ | |
for await(let command_center of new _descendants_of(window_title_in_titlebar, ["command-center"])){ | |
setTimeout(async () => { await _handle_command_center(command_center); }) | |
} | |
} | |
}); | |
} | |
} | |
}; | |
main_async(); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment