قالب وردپرس درنا توس
Home / Apple / Kitura Stencil Tutorial: How to create websites with Swift

Kitura Stencil Tutorial: How to create websites with Swift



It's very fun to build a back-end API in Swift with Kitura and test it with OpenAPI Explorer or maybe you've gone the distance to build an iOS app to consume Your API. It is quite understandable to want to show this work to your friends.

But what if they are trying to log in as "Leia Organa" through API Explorer on your computer when you distribute to localhost, and they get annoyed at you for constantly asking them to come over? Worse yet … what if they don't have iPhones ?!

In this tutorial on building websites with a Swift templating library named Stencil use a pre-determined Kitura app to save emoji information called EmojiJournal to: [1

9659005] Discover how a web-based front end is structured.
  • Learn how Stencil templating works.
  • Configure your basic / client route to access the front end of the web.
  • At the end of this tutorial you have a working web client who still needs some work but is ready to leave the box!

    You must also have the following available to you to be able to follow:

    • MacOS 10.14 or later
    • Xcode 10.1 or later
    • Homebrew
    • PostgreSQL
    • Basic Knowledge of Terminal As You Want use the command line quite

    Getting Started [19659015] To start, download the startup project material using Download the materials button at the top or bottom of this page.

    This tutorial will contain some work in the following languages:

    • HTML (HyperText Markup Language)
    • JS (JungleScribble … kidding, JavaScript)

    Whatever your experience working on any of these, I humbly ask you not to be alarmed! I might not go into the deepest depths to explain everything we write in other languages, but I want to include a nugget or two knowledge of everything you add to your project.

    Open the startup project in Finder and navigate to EmojiJournalServer / public directory. Open the folder and look at the structure. It should look like this:

     The web directory structure

    This project does not require you to change these files in any way, so you can largely leave them alone, but at least you should know what is in each directory:

    • css : This is an acronym for Cascading Style Sheets . Using CSS is how the various HTML components you will create will order and position themselves by reference. You have CSS files for both the emoji picker component and the main page you want to format.
    • img : These are short for pictures . This is nothing more than a static image share folder that will go to your web client. I am by no means a web designer, so if you look to make changes, you have to go!
    • js : The scripts that allow your web client to run as smoothly as you like. If you edit these, to quote npm (Node Package Manager): I hope you know what you're doing.

    It is good and common to load these into a folder called public on your front page. Usually, you can also add .html files into their own directory here as well. However, you should work with Stencil, a powerful templating library written for Swift, and mostly maintained by Kyle Fuller.

    Wait … Templering?

    When I say templating, I mean the ability to reproduce multiple variables and components in a repeatable way that you have the ability to format.

    Take this for example: Let's say you wanted to write a website that always tells you the current month. A naive approach to such a task can look like this in HTML:

    
    
      
          The current month is December! 
      
    
    

    Depending on when you read this tutorial, this result may be appropriate, but it is only about an 8.5% chance of it.

    It's barely sustainable; I don't want to be the web developer responsible for maintaining this! Thanks to Stencil, you now have the opportunity to pass in a variable, and Stencil will render your template file to spit out the correct date! Your .stencil file will look like this:

    
    
      
          The current month is {{currentMonth}}! 
      
    
    

    The main difference here is the inclusion of {{currentMonth}} ] but notice the curly bands around each end of the variable. These are the delimitations that Stencil will search for when looking for a place to insert information. Stencil mainly operates on this workflow:

    1. Prepare data from your API.
    2. Configure a context: a dictionary of key / value pairs.
    3. Populate your context with the values ​​you want to display.
    4. Give a template in your answer, using a context.

    If you didn't lift an eyebrow halfway through this list, go back and look at # 2. Hopefully you think, "Wait a minute … that's all this focus in Swift on the Codable protocol, and now I have to create a key value pair dictionary? What gives, David?! "You should know that I would never go over on you like that – by course you can use Codable!

    On the cool side of things you have to prepare an object that is either Codable or a number of homogeneous Codable objects. You will cover the entire power from the front to the back, but if you want to reduce the example above to a short code bit, it may look like this:

      struct CurrentMonth: Codable {
    Every month: String
    }
    
    try response.render ("home.stencil",
    with: CurrentMonth (month: "December"), forKey: "currentMonth")
    

    And then, in the file home.stencil you would handle this variable as such:

    
    
      
        
     Current month is {{currentMonth.month}}!
    
      
    
    

    Notice the slight change in the example above. This is because the object Codable has a property on the month title . Since Codable handles the serialization of JSON for you, Stencil gives you an easy way to read stored properties on the .stencil file.

    Note : As in most of Kitura's functionality, you can load a raw dictionary of values ​​and keys. Version 1.x APIs still work.

    Loops and other operations in Stencil

    Like the control flow in most modern programming languages, Stencil has a way to handle looping through a variety of objects you might want to use. Use our previous example, saying that you make a matrix in your answer like this:

      leave birthdays = [CurrentMonth(month: "September"), 
                     CurrentMonth(month: "January"),
                     CurrentMonth(month: "March")]
    
    try response.render ("home.stencil", with: birthdays,
    forKey: "birthdays")
    

    This means you now have a collection of items available to you in Stencil, instead of just a single object.

    Now you must use one of Stencil's built-in template labels with a loop. Your HTML may look like this:

    
      
        {% for birthdays%}
    
  • Month: {{birthday.month}}
  • {% endfor%}

    Note the difference between {% and {{ delimiters. As you have already learned, everything within {{}} will represent a string in your rendered HTML document. But if something is in the {%%} delimit, then this applies to a tag that Stencil recognizes. Many Stencil codes require a delimited code such as for which "quits" the previous command.

    The Loop for is certainly an example of it, but you can also do the same with a if statement in the Stencil as:

      {% if birthday.month%}
    
  • Month: {{birthday.month}}
  • {% else%}
  • No month listed.
  • {% end of%}

    Here is a partial list of some of the embedded codes that Stencil has available for you to use:

    • for
    • if
    • ifnot
    • now
    • filter
    • include
    • extending
    • block

    To check the documentation on how to use any of these tags in your own website template, visit Kyle's documentation page at https://stencil.fuller.li/en/latest/builtins.html. [19659002] Note : With the tags you can use, is tagged of particular interest, since you can submit a connection to another . stencil file in the original file by typing {% includes "secondTemplate.stencil"%} . You will not use it in this project, but some sites may be a bit tricky if you do not share them - this could be useful!

    With this theory behind you, it's finally time to start updating your startup project!

    Configuring PostgreSQL

    To build the trial project, you must have PostgreSQL installed on your development system, which you can do using Homebrew.

    Run the following command in Terminal to install PostgreSQL if it is not already installed:

      brew install postgres
    

    Then start the database server and create a database for the EmojiJournal app using these commands:

      pg_ctl -D / usr / local / var / postgres start
    initdb / usr / local / var / postgres
    sudo -u postgres -i
    createdb emojijournal
    

    Note : You can also have some luck by running PostgreSQL in a Docker container.

    Adding Stencil for Your Project

    Open up EmojiJournalServer / Package.swift in a text editor.

    First, add the Stencil addiction at the bottom of the dependency list:

      .package (url:
    "Https://github.com/IBM-Swift/Kitura-StencilTemplateEngine.git"
    .upToNextMinor (from: "1.11.0")),
    

    Make sure the previous line has a at the end, or Package.swift will not compile.

    Next, scroll down to the program target, and in the list of addictions this goal has, add KituraStencil to the end of the array. It should look like this:

      .target (name: "Application", dependencies: [ "Kitura", "CloudEnvironment", "SwiftMetrics", "Health", "KituraOpenAPI", "SwiftKueryPostgreSQL", "SwiftKueryORM", "CredentialsHTTP", "KituraStencil"]),
    

    Save the file and navigate to the root directory of your project in Terminal .

    This is a good time to remind you that the Quick Pack Generate-xcodeproj command will solve the dependency graph for you and then generate an Xcode project for you. And remember that the Swift Package Manager runs quick package update and swift build under the cap for you!

    Run the Quick Pack Generate-xcode Proj command from EmojiJournalServer folder and when finished, open EmojiJournalServer.xcodeproj . Build your project in Xcode and make sure everything goes well.

    Web Cluster Route

    The startup project includes a router for JournalEntry objects and for UserAuth administration. You need to add another route to manage connection to your web client.

    In Xcode, navigate to the folder Sources / Program / Routes . Create a new file, and then WebClientRoutes.swift .

    At the top of this file, you import the following libraries:

      import fund
    import loggerAPI
    importer KituraStencil
    import Kitura
    import SwiftKueryORM
    

    Now add a function to help you register a route in the main menu Router to handle the web client:

      func initializeWebClientRoutes (app: App) {
    
    // 1
    app.router.setDefault (templateEngine: StencilTemplateEngine ())
    
    // 2
    app.router.all (middleware: StaticFileServer (path: "./public"))
    
    // 3
    app.router.get ("/ client", acting: showClient)
    
    // 4
    Log info ("Web client routes created")
    }
    

    Look at each line of this feature you just added:

    1. Since you have added the Stencil dependency to your project, you must tell Kitura that Stencil should be the format for templating the HTML. Yes - you have choices for other templating engines, but our team has chosen Stencil!
    2. Here you have to tell Kitura that when searching for static files to operate (pictures etc.) which directory should be viewed, and this tells Kitura to look in your appropriate name public directory.
    3. Here you register the route / client on your router and you will handle this route with Stencil and Kitura soon.
    4. Log, log, log your work!

    Under this feature, add the following feature signature:

      func showClient (request: RouterRequest,
    answer: RouterResponse, next: @escaping () -> Void) {
    
    }
    

    This way, the project can compile, and you now have a function to handle your route. From now on, write a bunch of Swift code that will serve what you will eventually form in a Stencil file.

    Begin by declaring the following object above the initializeWebClientRoutes function: [19659041] struct JournalEntryWeb: Codable {
    Where id: String?
    was emoji: String
    Date: Date
    was displayDate: String
    was displayTime: String
    var backgroundColorCode: String
    was using: String
    }

    This can be seen superfluous first; Technically it is. However, remember our previous note on how Stencil can only operate stored properties? Stencil cannot handle calculated properties for some objects. Note that this object complies with Codable !

    Now you can think: "Wait ... my JournalEntry object has no calculated properties!" Take a deep breath; It doesn't. However, you should extend it so that it does it for your convenience.

    Scroll up to the top of this file, but only during your import, and add the following three calculated properties to a fileprivate extension of your object:

      fileprivate extension UserJournalEntry {
    was displayDate: String {
    get {
    la formatter = DateFormatter ()
    formats.dateStyle = .long
    return formats.string (from: self.date)
    }
    }
    
    var displayTime: String {
    get {
    la formatter = DateFormatter ()
    formatter.timeStyle = .long
    return formats.string (from: self.date)
    }
    }
    
    var backgroundColorCode: String {
    get {
    guard let substring = id? .suffix (6). busy () other {
    return "000000"
    }
    return substring
    }
    }
    }
    

    A few points about what you just added:

    • You want to make sure you expand UserJournalEntry that includes the user in each object you pass through to the Stencil context.

      displayDate and displayTime are purely for convenience. You can certainly create these variables from the date you submit to your HTML page, but this allows you to do so with Swift and make HTML easier!

    • backgroundColorCode is a design decision in lock test with your iOS app, based on the ID of a journal entry object. Hey, it works!

    Ok, now you have the object you are going to pass into the context.

    Add the following code to your showClient route manager:

      UserJournalEntry.findAll: Database.default) {
    entries, errors in
    
    guard let entries = entries other {
    response.status (.service unavailable) .send (json: ["Message": 
          "Service unavailable:" +
          "(String(describing: error?.localizedDescription))"])
    return
    }
    
    la sortedEntries = entries.sorted (by: {
    $ 0.date.timeIntervalSince1970>
    $ 1.date.timeIntervalSince1970
    })
    }
    

    Note that you use the ORM function on UserJournalEntry instead of just JournalEntry . This is to override user authentication on the server side - of course! Later, you need to handle approval properly. By protecting against a potential problem with the database, make sure you protect your web client from unexpected issues.

    When you get a handle on your selection of entries sort them so that they are date-descending.

    Then make the final selection of items you send to . stencil file. Within the UserJournalEntry.findAll feature but at the bottom, add the following code:

      // 1
    was webEntries = [JournalEntryWeb] ()
    
    for entry in sortedEntries {
    
    // 2
    webEntries.append (JournalEntryWeb (id: entry.id,
    emoji: entry.emoji, date: entry.date,
    displayDate: entry.displayDate,
    displayTime: entry.displayTime,
    backgroundColorCode: entry.backgroundColorCode,
    user: entry.user))
    }
    
    // 3
    do {
    try response.render ("home.stencil", with: webEntries,
    forKey: "listings")
    } grab bugs {
    response.status (.internalServerError)
    .send (error.localizedDescription)
    }
    

    With this code, do:

    1. Create a buffer group of JournalEntryWeb objects to send over.
    2. Popular it using a combination of the calculated properties of the extension in this file and the stored properties this object already carries.
    3. Stuff your response.render command in a catch block and you are free!

    Finally, in Xcode, open Sources / Application / Application.swift and go to postInit . Right below what you call initializeUserRoutes add the following function:

      initializeWebClientRoutes (app: self)
    

    Nice! Now everything is ready to go. Return to WebClientRoutes.swift seen a breakpoint in showClient .

    Build and run your server in Xcode.

    Open a web browser and visit http: / / localhost: 8080 / client. Your break point should trigger; go through the built-in functionality and see your contextual building! After you've turned your breakpoint and let the router manager complete, check your browser and ...

     Initial Web Client

    To test your web interface, add a few journal entries if You have nothing already. You can use OpenAPI Spec with the Kitura app to do so by visiting http: // localhost: 8080 / openapi / ui . For instructions on using OpenAPI, see OpenAPI Spec and Kitura: Getting Started. You must create a user and then use the / entries POST command to add an entry to the database.

    Adding Stencil Code

    From here, edit the file home.stencil and check the output to see what happens.

    In Xcode, go to the catalog Views and open home.stencil . Three things to note about this file as you continue.

    1. This counts technically as a static file. This means you can edit this file, save it, and don't have to run the server again to notice the changes! This also means that you will build and run your server and not worry about restarting it for the rest of this tutorial.
    2. Xcode is ... less than desirable as a text editor that is not Swift / Objective-C. To make it marginally better, go to the top menu bar and select Editor ▸ Syntax Coloring ▸ HTML. I won't blame you if you kick the tires on Visual Studio Code or Sublime Text.
    3. Take a moment to read through the rest of the code and look at the accompanying style of index.css if you want. The web client will use something that looks like a UICollectionView with cards to sort all the entries.

    Ready to edit the template file?

    Scroll to line 27, which should read as

    and after this line add the following snippet:

      {% for entry in listings%}
    

    {{entry.displayDate}}
    {{entry.displayTime}}

    {{entry.emoji}}

    {% endfor%}

    Here's what you've just done:

    • You create an HTML item called an article, which lets you classify an item with subsections called divs. One of the nice things about HTML is that you can override your CSS file with specific style instructions inline; you do it here with the hex code from backgroundColorCode passed through your context from Stencil!
    • Furthermore, you make fine and immediate use of the two calculated properties of date and time.
    • You have set up a recording element in the top right corner to delete an entry (Mac vs. Windows holy war participants, not @ me), but you may notice that you have "I have not yet written the feature to handle this yet - it's OK!
    • The main course is obviously the special emoji that you show on the card!
    • And all this packed into a for loop over listings !

    Think about this for a second; You just wrote a way to display many EmojiJournal entries with a block of HTML and you did everything with Swift and some sugar from the Stencil!

    Update your browser. No matter which user you submitted below, if you added a few journal entries to your database, your site should display them:

     Completed template

    Nice work! Have you ever wanted to turn your Ray Bans on, cross your arms and tell Twitter you're a web developer? Spin Up Your Internet Machine - You Can Now!

    Where to go from here?

    You can download the finished project for this tutorial using the Download Materials button at the top or bottom of this page.

    Congratulations! You have a working web client now!

    The web version of EmojiJournal is not quite a complete app since you have not implemented add functionality in the web interface. But you are well on your way with Stencil with Kitura. See our book Server Side Swift with Kitura for more information on completing the web version of EmojiJournal.

    Stencil is a very powerful framework for templating, and you should give it a shot on its own. You can check out the GitHub repo for it at https://github.com/stencilproject/Stencil.

    If you have questions or comments on this tutorial, please add them to the comments


    Source link