Conditional import possible?

You are basically doing a conditional import already, but you’re now facing the problem that this import is limited in scope: your imports are only visible inside the { ... } block where it happens.

Since target() requires context and you can’t ever get anything out of a context expression (see here), this is a dead end. The inputs approach could be made to work, though (maybe at the cost of good autocomplete, because we’re doing a dynamic import):

#let defaults-module-name = if sys.inputs.at("type", default: "paged") == "paged" {
    "paged-defaults.typ"
} else {
    "html-defaults.typ"
}
#import defaults-module-name: *

Or less direct, but imo also a bit less cursed:

#let defaults-module = if sys.inputs.at("type", default: "paged") == "paged" {
    import "paged-defaults.typ"
    paged-defaults
} else {
    import "html-defaults.typ"
    html-defaults
}
#import defaults-module: *

Instead of using a dynamic string and importing from that, this imports the module, and then does a wildcard import from that module.


However, even though that’s the answer to the literal question you asked, I don’t think that’s what you want or need. You don’t show it in full, but your template probably started out like this:

#show: doc => context {
    if target() == "paged" {
        set page(...)
        // few other setup blocks for pdf output
        doc
    } else {
        html.elem("div", attrs: (class: "my-container"))[
            // few other setup blocks for html output
        ]
        doc
    }
}

Your problem is that the if and else got too large, and you’re already halfway there by creating separate modules:

#show: doc => context {
    if target() == "paged" {
        import "paged-defaults.typ": *
        show: _paged_defaults()
        doc
    } else {
        import "html-defaults.typ": *
        show: _paged_defaults()
        doc
    }
}

Similar things could be done for other parts of your template. If you have a foo function with two separate implementations, you could write

#let foo(..args) = context {
    if target() == "paged" {
        import "paged-defaults.typ": *
        foo(..args)
    } else {
        import "html-defaults.typ": *
        foo(..args)
    }
}