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)
}
}