mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-19 18:27:29 -05:00
This MR brings in `$`, `$$`, and `$x` browsers devtools' utilities to our code so we can use these whenever we find it convenient.
This commit is contained in:
committed by
GitHub
parent
3a66be585f
commit
82613d016a
13
pyscriptjs/package-lock.json
generated
13
pyscriptjs/package-lock.json
generated
@@ -7,6 +7,9 @@
|
||||
"": {
|
||||
"name": "pyscript",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"basic-devtools": "^0.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@codemirror/commands": "^6.2.2",
|
||||
"@codemirror/lang-python": "^6.1.2",
|
||||
@@ -2346,6 +2349,11 @@
|
||||
"integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/basic-devtools": {
|
||||
"version": "0.1.6",
|
||||
"resolved": "https://registry.npmjs.org/basic-devtools/-/basic-devtools-0.1.6.tgz",
|
||||
"integrity": "sha512-g9zJ63GmdUesS3/Fwv0B5SYX6nR56TQXmGr+wE5PRTNCnGQMYWhUx/nZB/mMWnQJVLPPAp89oxDNlasdtNkW5Q=="
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
@@ -7743,6 +7751,11 @@
|
||||
"integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==",
|
||||
"dev": true
|
||||
},
|
||||
"basic-devtools": {
|
||||
"version": "0.1.6",
|
||||
"resolved": "https://registry.npmjs.org/basic-devtools/-/basic-devtools-0.1.6.tgz",
|
||||
"integrity": "sha512-g9zJ63GmdUesS3/Fwv0B5SYX6nR56TQXmGr+wE5PRTNCnGQMYWhUx/nZB/mMWnQJVLPPAp89oxDNlasdtNkW5Q=="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
|
||||
@@ -38,5 +38,8 @@
|
||||
"synclink": "0.2.4",
|
||||
"ts-jest": "29.0.3",
|
||||
"typescript": "5.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"basic-devtools": "^0.1.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { $, $$ } from 'basic-devtools';
|
||||
|
||||
import { basicSetup, EditorView } from 'codemirror';
|
||||
import { python } from '@codemirror/lang-python';
|
||||
import { indentUnit } from '@codemirror/language';
|
||||
@@ -78,7 +80,7 @@ export function make_PyRepl(interpreter: InterpreterClient, app: PyScriptApp) {
|
||||
if (!response.ok) {
|
||||
return;
|
||||
}
|
||||
const cmcontentElement = this.querySelector("div[class='cm-content']");
|
||||
const cmcontentElement = $('div[class="cm-content"]', this);
|
||||
const { lastElementChild } = cmcontentElement;
|
||||
cmcontentElement.replaceChildren(lastElementChild);
|
||||
lastElementChild.textContent = await response.text();
|
||||
@@ -191,7 +193,7 @@ export function make_PyRepl(interpreter: InterpreterClient, app: PyScriptApp) {
|
||||
// should be the default.
|
||||
autogenerateMaybe(): void {
|
||||
if (this.hasAttribute('auto-generate')) {
|
||||
const allPyRepls = document.querySelectorAll(`py-repl[root='${this.getAttribute('root')}'][exec-id]`);
|
||||
const allPyRepls = $$(`py-repl[root='${this.getAttribute('root')}'][exec-id]`, document);
|
||||
const lastRepl = allPyRepls[allPyRepls.length - 1];
|
||||
const lastExecId = lastRepl.getAttribute('exec-id');
|
||||
const nextExecId = parseInt(lastExecId) + 1;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { $$, $x } from 'basic-devtools';
|
||||
|
||||
import { ltrim, htmlDecode, ensureUniqueId, createDeprecationWarning } from '../utils';
|
||||
import { getLogger } from '../logger';
|
||||
import { pyExec, displayPyException } from '../pyexec';
|
||||
@@ -113,7 +115,7 @@ export function make_PyScript(interpreter: InterpreterClient, app: PyScriptApp)
|
||||
if ((node as PyScriptElement).matches(pyScriptCSS)) {
|
||||
bootstrap(node as PyScriptElement);
|
||||
}
|
||||
for (const child of (node as PyScriptElement).querySelectorAll(pyScriptCSS)) {
|
||||
for (const child of $$(pyScriptCSS, node as PyScriptElement)) {
|
||||
bootstrap(child as PyScriptElement);
|
||||
}
|
||||
}
|
||||
@@ -139,7 +141,7 @@ export function make_PyScript(interpreter: InterpreterClient, app: PyScriptApp)
|
||||
});
|
||||
|
||||
// bootstrap all already live py <script> tags
|
||||
callback([{ addedNodes: document.querySelectorAll(pyScriptCSS) } as unknown] as MutationRecord[], null);
|
||||
callback([{ addedNodes: $$(pyScriptCSS, document) } as unknown] as MutationRecord[], null);
|
||||
|
||||
// once all tags have been initialized, observe new possible tags added later on
|
||||
// this is to save a few ticks within the callback as each <script> already adds a companion node
|
||||
@@ -149,20 +151,6 @@ export function make_PyScript(interpreter: InterpreterClient, app: PyScriptApp)
|
||||
return PyScript;
|
||||
}
|
||||
|
||||
// Differently from CSS selectors, XPath can crawl attributes by name and select
|
||||
// directly attribute nodes. This allows us to look for literally any `py-*` attribute.
|
||||
// TODO: could we just depend on basic-devtools module?
|
||||
// @see https://github.com/WebReflection/basic-devtools
|
||||
const $x = (path: string, root: Document | HTMLElement = document): (Node | Attr)[] => {
|
||||
const expression = new XPathEvaluator().createExpression(path);
|
||||
const xpath = expression.evaluate(root, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
|
||||
const result = [];
|
||||
for (let i = 0, { snapshotLength } = xpath; i < snapshotLength; i++) {
|
||||
result.push(xpath.snapshotItem(i));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/** A weak relation between an element and current interpreter */
|
||||
const elementInterpreter: WeakMap<Element, InterpreterClient> = new WeakMap();
|
||||
|
||||
@@ -199,7 +187,7 @@ function createElementsWithEventListeners(interpreter: InterpreterClient, el: El
|
||||
|
||||
/** Mount all elements with attribute py-mount into the Python namespace */
|
||||
export async function mountElements(interpreter: InterpreterClient) {
|
||||
const matches: NodeListOf<HTMLElement> = document.querySelectorAll('[py-mount]');
|
||||
const matches = $$('[py-mount]', document);
|
||||
logger.info(`py-mount: found ${matches.length} elements`);
|
||||
|
||||
if (matches.length > 0) {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { $$ } from 'basic-devtools';
|
||||
|
||||
import './styles/pyscript_base.css';
|
||||
|
||||
import { loadConfigFromElement } from './pyconfig';
|
||||
@@ -150,7 +152,7 @@ export class PyScriptApp {
|
||||
// XXX: we should actively complain if there are multiple <py-config>
|
||||
// and show a big error. PRs welcome :)
|
||||
logger.info('searching for <py-config>');
|
||||
const elements = document.getElementsByTagName('py-config');
|
||||
const elements = $$('py-config', document);
|
||||
let el: Element | null = null;
|
||||
if (elements.length > 0) el = elements[0];
|
||||
if (elements.length >= 2) {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { $$ } from 'basic-devtools';
|
||||
|
||||
import { showWarning } from '../utils';
|
||||
import { Plugin } from '../plugin';
|
||||
import { getLogger } from '../logger';
|
||||
@@ -21,7 +23,7 @@ export class ImportmapPlugin extends Plugin {
|
||||
// await the module to be fully registered before executing the code
|
||||
// inside py-script. It's also unclear whether we want to wait or not
|
||||
// (or maybe only wait only if we do an actual 'import'?)
|
||||
for (const node of document.querySelectorAll("script[type='importmap']")) {
|
||||
for (const node of $$("script[type='importmap']", document)) {
|
||||
const importmap: ImportMapType = (() => {
|
||||
try {
|
||||
return JSON.parse(node.textContent) as ImportMapType;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { $ } from 'basic-devtools';
|
||||
|
||||
import type { PyScriptApp } from '../main';
|
||||
import type { AppConfig } from '../pyconfig';
|
||||
import { Plugin, validateConfigParameterFromArray } from '../plugin';
|
||||
@@ -42,7 +44,7 @@ export class PyTerminalPlugin extends Plugin {
|
||||
const { terminal: t, docked: d } = config;
|
||||
const auto = t === true || t === 'auto';
|
||||
const docked = d === true || d === 'docked';
|
||||
if (auto && document.querySelector('py-terminal') === null) {
|
||||
if (auto && $('py-terminal', document) === null) {
|
||||
logger.info('No <py-terminal> found, adding one');
|
||||
const termElem = document.createElement('py-terminal');
|
||||
if (auto) termElem.setAttribute('auto', '');
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { $ } from 'basic-devtools';
|
||||
|
||||
import type { AppConfig } from '../pyconfig';
|
||||
import type { UserError } from '../exceptions';
|
||||
import { showWarning } from '../utils';
|
||||
@@ -92,8 +94,8 @@ export class PySplashscreen extends HTMLElement {
|
||||
</div>
|
||||
</div>`;
|
||||
this.mount_name = this.id.split('-').join('_');
|
||||
this.operation = document.getElementById('pyscript-operation');
|
||||
this.details = document.getElementById('pyscript-operation-details');
|
||||
this.operation = $('#pyscript-operation', document) as HTMLElement;
|
||||
this.details = $('#pyscript-operation-details', document) as HTMLElement;
|
||||
}
|
||||
|
||||
log(msg: string) {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { $ } from 'basic-devtools';
|
||||
|
||||
import { Plugin } from '../plugin';
|
||||
import { TargetedStdio, StdioMultiplexer } from '../stdio';
|
||||
import type { InterpreterClient } from '../interpreter_client';
|
||||
@@ -107,7 +109,7 @@ export class StdioDirector extends Plugin {
|
||||
if (outputId) {
|
||||
// 'output' attribute also used as location to send
|
||||
// result of REPL
|
||||
if (document.getElementById(outputId)) {
|
||||
if ($('#' + outputId, document)) {
|
||||
await pyDisplay(options.interpreter, options.result, { target: outputId });
|
||||
} else {
|
||||
//no matching element on page
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { $ } from 'basic-devtools';
|
||||
|
||||
import { createSingularWarning, escape } from './utils';
|
||||
|
||||
export interface Stdio {
|
||||
@@ -67,7 +69,7 @@ export class TargetedStdio implements Stdio {
|
||||
*/
|
||||
writeline_by_attribute(msg: string) {
|
||||
const target_id = this.source_element.getAttribute(this.source_attribute);
|
||||
const target = document.getElementById(target_id);
|
||||
const target = $('#' + target_id, document);
|
||||
if (target === null) {
|
||||
// No matching ID
|
||||
createSingularWarning(
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { $$ } from 'basic-devtools';
|
||||
|
||||
import { _createAlertBanner } from './exceptions';
|
||||
|
||||
export function addClasses(element: HTMLElement, classes: string[]) {
|
||||
@@ -101,7 +103,7 @@ export function createDeprecationWarning(msg: string, elementName: string): void
|
||||
* If null, the full text of 'msg' is used instead.
|
||||
*/
|
||||
export function createSingularWarning(msg: string, sentinelText: string | null = null): void {
|
||||
const banners = document.getElementsByClassName('alert-banner py-warning');
|
||||
const banners = $$('.alert-banner, .py-warning', document);
|
||||
let bannerCount = 0;
|
||||
for (const banner of banners) {
|
||||
if (banner.innerHTML.includes(sentinelText ? sentinelText : msg)) {
|
||||
|
||||
Reference in New Issue
Block a user