Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reload on css changes + fix css specificity #6738

Merged
merged 7 commits into from Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/fresh-dryers-send.md
@@ -0,0 +1,7 @@
---
"@gradio/app": minor
"@gradio/preview": minor
"gradio": minor
---

feat:reload on css changes + fix css specificity
2 changes: 2 additions & 0 deletions gradio/utils.py
Expand Up @@ -170,6 +170,8 @@ def iter_py_files() -> Iterator[Path]:
for reload_dir in reload_dirs:
for path in list(reload_dir.rglob("*.py")):
yield path.resolve()
for path in list(reload_dir.rglob("*.css")):
yield path.resolve()

module = None
reload_dirs = [Path(dir_) for dir_ in reloader.watch_dirs]
Expand Down
45 changes: 20 additions & 25 deletions js/app/src/Index.svelte
@@ -1,6 +1,6 @@
<script context="module" lang="ts">
import { writable } from "svelte/store";
import { mount_css as default_mount_css } from "./css";
import { mount_css as default_mount_css, prefix_css } from "./css";

import type { ComponentMeta, Dependency, LayoutNode } from "./types";

Expand Down Expand Up @@ -119,14 +119,14 @@
app_id = config.app_id;
}

async function mount_custom_css(
target: HTMLElement,
css_string: string | null
): Promise<void> {
let css_text_stylesheet: HTMLStyleElement | null = null;
async function mount_custom_css(css_string: string | null): Promise<void> {
if (css_string) {
let style = document.createElement("style");
style.innerHTML = css_string;
target.appendChild(style);
css_text_stylesheet = prefix_css(
css_string,
version,
css_text_stylesheet || undefined
);
}
await mount_css(config.root + "/theme.css", document.head);
if (!config.stylesheets) return;
Expand All @@ -135,10 +135,15 @@
config.stylesheets.map((stylesheet) => {
let absolute_link =
stylesheet.startsWith("http:") || stylesheet.startsWith("https:");
return mount_css(
absolute_link ? stylesheet : config.root + "/" + stylesheet,
document.head
);
if (absolute_link) {
return mount_css(stylesheet, document.head);
}

return fetch(config.root + "/" + stylesheet)
.then((response) => response.text())
.then((css_string) => {
prefix_css(css_string, version);
});
})
);
}
Expand Down Expand Up @@ -243,7 +248,7 @@
detail: "RUNNING"
};

await mount_custom_css(wrapper, config.css);
await mount_custom_css(config.css);
await add_custom_html_head(config.head);
css_ready = true;
window.__is_colab__ = config.is_colab;
Expand All @@ -259,22 +264,12 @@
status_callback: handle_status,
normalise_files: false
});

config = app.config;
window.__gradio_space__ = config.space_id;
await mount_custom_css(config.css);
}
};

// websocket = new WebSocket(url);
// websocket.onmessage = async function (event) {
// if (event.data === "CHANGE") {
// app = await client(api_url, {
// status_callback: handle_status,
// normalise_files: false
// });
// config = app.config;
// window.__gradio_space__ = config.space_id;
// }
// };
}, 200);
}
});
Expand Down
39 changes: 39 additions & 0 deletions js/app/src/css.ts
Expand Up @@ -18,3 +18,42 @@ export function mount_css(url: string, target: HTMLElement): Promise<void> {
target.appendChild(link);
});
}

export function prefix_css(
string: string,
version: string,
style_element = document.createElement("style")
): HTMLStyleElement {
style_element.remove();

const stylesheet = new CSSStyleSheet();
stylesheet.replaceSync(string);

const rules = stylesheet.cssRules;

let css_string = "";

for (let i = 0; i < rules.length; i++) {
const rule = rules[i];

if (rule instanceof CSSStyleRule) {
const selector = rule.selectorText;
if (selector) {
const new_selector = selector
.split(",")
.map(
(s) =>
`gradio-app .gradio-container.gradio-container-${version} .contain ${s.trim()}`
)
.join(",");

css_string += rule.cssText;
css_string += rule.cssText.replace(selector, new_selector);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. I don't think repeating a css rule should have any (non-performance-related) downsides so this should be good

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The number of rules should generally be pretty modest, so I think the performance should be ok.

}
pngwn marked this conversation as resolved.
Show resolved Hide resolved
}
}
style_element.textContent = css_string;

document.head.appendChild(style_element);
return style_element;
}
2 changes: 1 addition & 1 deletion js/preview/package.json
Expand Up @@ -21,7 +21,7 @@
"dependencies": {
"@originjs/vite-plugin-commonjs": "^1.0.3",
"@rollup/plugin-sucrase": "^5.0.1",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@sveltejs/vite-plugin-svelte": "^2.5.2",
"@types/which": "^3.0.0",
"coffeescript": "^2.7.0",
"css-tree": "2.3.1",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -41,7 +41,7 @@
"@manypkg/get-packages": "^2.2.0",
"@playwright/experimental-ct-svelte": "^1.39.0",
"@playwright/test": "^1.39.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@sveltejs/vite-plugin-svelte": "^2.5.2",
"@tailwindcss/forms": "^0.5.0",
"@testing-library/dom": "^9.0.0",
"@testing-library/jest-dom": "^6.0.0",
Expand Down