Vai al contenuto

Tag Personalizzati

Puoi creare tag Leaf personalizzati usando il protocollo LeafTag.

Per mostrare come funziona, diamo un'occhiata alla creazione di un tag personalizzato #now che stampa l'attuale marca temporale. Il tag supporterà anche un singolo parametro opzionale per specificare il formato della data.

Tip

Se il tuo tag personalizzato renderizza HTML dovresti conformare il tuo tag personalizzato a UnsafeUnescapedLeafTag così che l'HTML non sia "escaped". Ricorda di controllare o ripulire ogni input dell'utente.

LeafTag

Prima creiamo una classe chiamata NowTag e conformiamola a LeafTag.

struct NowTag: LeafTag {
    func render(_ ctx: LeafContext) throws -> LeafData {
        ...
    }
}

Adesso implementiamo il metodo render(_:). Il contesto LeafContext passato a questo metodo ha tutto quello che ci dovrebbe servire.

enum NowTagError: Error {
    case invalidFormatParameter
    case tooManyParameters
}

struct NowTag: LeafTag {
    func render(_ ctx: LeafContext) throws -> LeafData {
        let formatter = DateFormatter()
        switch ctx.parameters.count {
        case 0: formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        case 1:
            guard let string = ctx.parameters[0].string else {
                throw NowTagError.invalidFormatParameter
            }

            formatter.dateFormat = string
        default:
            throw NowTagError.tooManyParameters
        }

        let dateAsString = formatter.string(from: Date())
        return LeafData.string(dateAsString)
    }
}

Configura il Tag

Adesso che abbiamo implementato NowTag, dobbiamo solo dirlo a Leaf. Puoi aggiungere qualsiasi tag così - anche se vengono da un pacchetto separato. Di solito si fa in configure.swift:

app.leaf.tags["now"] = NowTag()

Fatto! Ora possiamo usare la nostra tag personalizzata in Leaf.

The time is #now()

Proprietà del Contesto

Il LeafContext contiene due proprietà importanti: parameters e data, che hanno tutto quello che ci dovrebbe servire.

  • parameters: Un array che contiene i parametri del tag;
  • data: Un dizionario che contiene i dati della view passata a render(_:_:) come contesto.

Tag Hello di Esempio

Per vedere come usarlo, implementiamo un semplice tag di saluto usando entrambe le proprietà.

Usando i Parametri

Possiamo accedere al primo parametro che dovrebbe contenere il nome.

enum HelloTagError: Error {
    case missingNameParameter
}

struct HelloTag: UnsafeUnescapedLeafTag {
    func render(_ ctx: LeafContext) throws -> LeafData {
        guard let name = ctx.parameters[0].string else {
            throw HelloTagError.missingNameParameter
        }

        return LeafData.string("<p>Hello \(name)</p>")
    }
}
#hello("John")

Usando i Dati

Possiamo accedere al valore del nome usando la chiave "name" dentro la proprietà dei dati.

enum HelloTagError: Error {
    case nameNotFound
}

struct HelloTag: UnsafeUnescapedLeafTag {
    func render(_ ctx: LeafContext) throws -> LeafData {
        guard let name = ctx.data["name"]?.string else {
            throw HelloTagError.nameNotFound
        }

        return LeafData.string("<p>Hello \(name)</p>")
    }
}
#hello()

Controller:

return try await req.view.render("home", ["name": "John"])