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

Document Level Tags Are Applied In Reverse Order #3756

Open
mcmah309 opened this issue Feb 17, 2025 · 4 comments · May be fixed by #3771
Open

Document Level Tags Are Applied In Reverse Order #3756

mcmah309 opened this issue Feb 17, 2025 · 4 comments · May be fixed by #3771
Labels
bug Something isn't working

Comments

@mcmah309
Copy link

Problem
Document level tags do not respect order. E.g. for

    rsx! {
            document::Script { src: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" }
            document::Script { src: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/rust.min.js" }
            document::Script { {r#"
document.addEventListener("DOMContentLoaded", () => {
    hljs.highlightAll();
});
"#} }
        }
    }

In browser:

<head>
<script>
document.addEventListener("DOMContentLoaded", () => {
    hljs.highlightAll();
});
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/rust.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
</head>

Also worth noting that muli-line str r#" "# breaks dx fmt.

Expected behavior

<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/rust.min.js"></script>
<script>
document.addEventListener("DOMContentLoaded", () => {
    hljs.highlightAll();
});
</script>
</head>

Screenshots

Environment:

  • Dioxus version: 0.6.2
  • Rust version: 1.86.0 nightly
  • OS info: NixOS 25.05
  • App platform: web

Questionnaire

I'm interested in fixing this myself but don't know where to start.

@mcmah309 mcmah309 added the bug Something isn't working label Feb 17, 2025
@ealmloff
Copy link
Member

ealmloff commented Feb 19, 2025

Dioxus mounts nodes in a reverse order here because of the template diffing optimization system. Outside of a single rsx block, I'm not sure there is a clear order for head elements. Head elements could be loaded asynchronously based on the result of a resource. A script that loads immediately will be inserted before a script that loads asynchronously regardless of the depth first order of the script elements in the tree.

You can use imports that don't rely on the order of script tags. es6 imports seem like a much more predictable way to handle dependencies:

use dioxus::prelude::*;

static HIGHLIGHT: Asset = asset!("/assets/highlight/es/highlight.min.js");
static RUST: Asset = asset!("/assets/highlight/es/languages/rust.min.js");

fn app() -> Element {
    rsx! {
        document::Script {
            type: "module",
            r#"import hljs from "{HIGHLIGHT}";
            import rust from "{RUST}";
            hljs.registerLanguage('rust', rust);
            setTimeout(() => {{
                hljs.highlightAll();
            }}, 1000);"#
        }
        pre {
            code {
                class: "language-rust",
                "fn main() {{\nprintln!(\"Hello, world!\");\n}}"
            }
        }
    }
}

fn main() {
    dioxus::launch(app)
}

@mcmah309
Copy link
Author

mcmah309 commented Feb 19, 2025

Thanks for the information and solution! That makes sense. Reverse order in the head is an unfortunate consequence. This should probably be documented somewhere. You're solution of using a module should also probably be documented for such cases.

For completeness, if you decide to use this example, a timeout is not needed since modules are deferred and a style is needed:

use dioxus::prelude::*;

static HIGHLIGHT: Asset = asset!("/assets/highlight/es/highlight.min.js");
static RUST: Asset = asset!("/assets/highlight/es/languages/rust.min.js");
static STYLE: Asset = asset!("/assets/highlight/styles/atom-one-dark.css");

fn app() -> Element {
    rsx! {
        document::Link { rel: "stylesheet", href: STYLE }
        document::Script {
            type: "module",
            r#"import hljs from "{HIGHLIGHT}";
            import rust from "{RUST}";
            hljs.registerLanguage('rust', rust);
            hljs.highlightAll();"#
        }
        pre {
            code {
                class: "language-rust",
                "fn main() {{\nprintln!(\"Hello, world!\");\n}}"
            }
        }
    }
}

fn main() {
    dioxus::launch(app)
}

I can make a pr to add this to the docs if you'd like.

@ealmloff
Copy link
Member

I can make a pr to add this to the docs if you'd like.

That would be great, thanks!

@mcmah309 mcmah309 linked a pull request Feb 20, 2025 that will close this issue
@mcmah309
Copy link
Author

I created a PR #3771

This also lead me to create DioxusLabs/docsite#448

While this issue is fresh in your mind, It may have some relation to #3757

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants