stathissideris / dali

dali is a Clojure library for representing, exporting and manipulating the SVG graphics format.
291 stars 16 forks source link

Not an issue, but a question #9

Closed ILoveHubGit closed 6 years ago

ILoveHubGit commented 6 years ago

I would like to use Dali for a project of mine. But I can't get it working. :-( I created a new lumnius project and try to get it to work in the standard routes file but I can't see what I'm doing wrong. Can you please help me? Below the code of my file

(ns svgtest.routes.home (:require [svgtest.layout :as layout] [compojure.core :refer [defroutes GET]] [ring.util.http-response :as response] [clojure.java.io :as io] [dali.io :as dio]))

(defn svgfile [] (io/file "Clojure_logo.svg"))

(def svgfile [:dali/page [:circle {:stroke :indigo :stroke-width 4 :fill :darkorange} [30 30] 20]])

(defn home-page [] (layout/render "home.html"))

(defroutes home-routes (GET "/" [] (home-page)) (GET "/docs" [] (-> (response/ok (-> "docs/docs.md" io/resource slurp)) (response/header "Content-Type" "text/plain; charset=utf-8"))) (GET "/img" [] (-> (response/ok (dio/render-svg svgfile "firsttry.svg")) (response/header "Content-Type" "text/html"))))

If I start a REPL and run (dali.io/render-svg svgfile "test.svg"), I get nil as response

stathissideris commented 6 years ago

I think your problem is that response/ok expects a string with the content to return to the browser, but render-svg does not produce a useful string value (as you mentioned it returns nil) because this function's purpose is to write SVG content to files. Unfortunately, dali does not have a function that will give you the string instead of writing it to a file, but if you look at the implementation it's not too hard to figure out how you would do it. I think it would look a bit like that:

(defn render-svg-string [doc]
  (-> doc
      syntax/dali->ixml
      layout/resolve-layout
      syntax/ixml->xml
      xml->svg-document-string))

Mind you, this is untested code that I wrote on the fly via copy-paste, so it may not work perfectly. If it does work, and you test it a bit yourself, you can git clone dali, integrate it into the dali.io namespace and send me a pull request!

ILoveHubGit commented 6 years ago

Thank you for your answer. But I didn't explain very well what I want I guess. I'll try again :-) I've a database with data, say process flows. I want to visualize these process flows on a website. All the process steps are in the db and also their connections. However in a somewhat difficult format. It is easy to retrieve all the process steps and their relations, what is difficult is to show them in a correct way on the website, without crossing connectors. This is where I think dali can help me. I want to retrieve the process steps and their connections from the db and then use dali to organize this in a nice way and show them on my page as an svg image using html templating. I did succeed now by using the following method: <object height="275" data="{{img}}" type="image/svg+xml"></object> I added the above code to my html template and call the template with

(defn home-page []
  (layout/render "home.html" {:img "/img"}))

I created a new routing:

(GET "/img" 
     (-> (response/ok (svgfile id))
           (response/header "Content-Type" "text/html")))

Which get called when the page loads and then the image is loaded. It works but somehow I don't think this is the best solution. Because now I've a call to the server per image to be shown. I would rather have only one call to the server from the client to retrieve the page with all the information.

ILoveHubGit commented 6 years ago

By using previous described message this problem is solved

stathissideris commented 6 years ago

This code...

(GET "/img" 
     (-> (response/ok (svgfile id))
           (response/header "Content-Type" "text/html")))

...looks like you're generating an SVG file on every request and then you serve it via the /img endpoint. It works, but maybe it's not very performant because you need to write to disk and then read again on every request. This won't scale, but maybe it's fine for your application. An alternative is to render directly to string as I've shown you. Also see this pull request.