# Can I call extend or export functions inside a custom Leaf tag?

**URL:** <https://forums.swift.org/t/can-i-call-extend-or-export-functions-inside-a-custom-leaf-tag/68086>\
**Category:** Vapor\
**Tags:** leaf\
**Created:** [October 26, 2023, 1:22pm UTC](https://forums.swift.org/t/can-i-call-extend-or-export-functions-inside-a-custom-leaf-tag/68086 "2023-10-26T13:22:17Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![RussBaz](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/russbaz/32/30841_2.png) [@RussBaz](https://forums.swift.org/u/RussBaz)\
**Post date:** [October 26, 2023, 1:22pm UTC](https://forums.swift.org/t/can-i-call-extend-or-export-functions-inside-a-custom-leaf-tag/68086/1 "2023-10-26T13:22:17Z")

</div>

Hi. Can I call `#extend` or `#export` inbuilt tags inside my own custom Leaf tag? Or is it possible to load a leaf template from a string instead of a file?

What I am trying to achieve is to be able to load outer (layout) HTML conditionally without creating additional files. So that my route handler can either return a fragment of the page or the whole page depending on a certain condition without a need for an extra template. Basically, I am experimenting with `htmx` and creating some helpers for it. 🙂

Thanks and sorry for a messy post.

---

<div class="post-metadata">

**Author:** ![0xTim](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/0xtim/32/27968_2.png) [@0xTim](https://forums.swift.org/u/0xTim)\
**Post date:** [October 27, 2023, 10:59pm UTC](https://forums.swift.org/t/can-i-call-extend-or-export-functions-inside-a-custom-leaf-tag/68086/2 "2023-10-27T22:59:13Z")

</div>

I don't _think_ you can, those tags are treated as special cases in Leaf so I don't think the behaviour is exposed to tags. Worth playing around though!

You should be able to load templates as a string, there are some examples in the tests.

As for doing conditional stuff like that, generally it doesn't play well with Leaf as it's designed to be a daily basic templating language. You would probably be better off having a function to work out the template name and pass in the correct template you want for that use case

---

<div class="post-metadata">

**Author:** ![RussBaz](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/russbaz/32/30841_2.png) [@RussBaz](https://forums.swift.org/u/RussBaz)\
**Post date:** [October 31, 2023, 4:56pm UTC](https://forums.swift.org/t/can-i-call-extend-or-export-functions-inside-a-custom-leaf-tag/68086/3 "2023-10-31T16:56:11Z")

</div>

Thanks for a suggestion. In the end, conditionally returning dynamically generated templates worked well. Meta templating for template files. 🙂

For future references for those who are interested – I managed to implement a custom `LeafSource` `struct` such as:

```swift
struct HtmxPageLeafSource: LeafSource { // implementation ... }

```

and then registered it in `configure.swift`:

```swift
// Copying the default init for sources
app.leaf.sources = .singleSource(NIOLeafFiles(fileio: app.fileio, limits: .default, sandboxDirectory: app.leaf.configuration.rootDirectory, viewDirectory: app.leaf.configuration.rootDirectory))
// Adding a custom source
try app.leaf.sources.register(source: "htmx", using: HtmxPageLeafSource(), searchable: true)

```

Now, the `file` method of the `LeafSource` protocol would check for a special pattern in the `template` name and interpolate it to generate a custom template. However, such a template must not exist in the filesystem because this custom `LeafSource` is the last one in the search path as defined in the `LeafSources`.

So, as an example, my `file` method checks if the template name starts with `"--page/"` and if it does, it treats the remainder of the template name as a parameter and returns something like this (as a buffer, of course):

```swift
let result =
            """
            #extend("index-base"): #export("body"): #extend("\(String(remainder))") #endexport #endextend
            """

```

Where the `remainder` is the non-zero length remainder after dropping `"--page/"` part of the template name.

In all other case it will return an error which will make the leaf work as it always does.
