convert from markdown to html using Clojure or ClojureScript, including tables - clojure

markdown-clj seems to work well but does not convert markdown tables. I do understand that tables are not an official part of the markdown specification.
So I am now using Showdown via CLJSJS, for which there's a convenient example, repeated here:
(defn convert-to-html [markdown]
(let [converter (js/Showdown.converter.)]
(.makeHtml converter markdown)))
From the Showdown documentation what you need to do to have tables converted as well is to turn on the option tables. How would I do this in the ClojureScript code above?
EDIT
Note that the above syntax was correct at the time this question was asked. However you now need to:
(js/showdown.Converter.)
Note that both showdown and Converter have changed their capitalisation.

Read up on JavaScript interop.
Looking at the Showdown docs you got a few ways to enable table parsing.
Globally:
showdown.setOption('optionKey', 'value');
(.setOption js/showdown "tables" true)
Locally:
var converter = new showdown.Converter({optionKey: 'value'});
(let [converter (js/showdown.Converter. #js {:tables true})]
..)
Note the #js, a short hand for clj->js, which takes care of converting ClojureScript values to JavaScript.
var converter = new showdown.Converter();
converter.setOption('optionKey', 'value');
(let [converter (js/showdown.Converter.)
_ (.setOption converter "tables" true)]
..)

Related

Text and String search in clojure ogre to query Janusgraph - Not able to find any function or method

I'm using Clojure Ogre to query Janusgraph database from my clojure application. Everything went well until I got a requirement for text search. In gremlin shell I can able to search via regular expression using below syntax,
g.V().has('name', textContainsRegex('.*shr.*'))
I'm looking for equivalent function/method for "textContainsRegex" in clojure Ogre so that I can able to query from my application. Can you please help in this regard. For now I'm using the below syntax to search from my application,
(og/traverse g og/V (og/has :name qu) (og/value-map) (og/into-list!))
Thanks a lot for your time. Looking forward for the solution.
textContainsRegex is a JanusGraph class and therefore isn't something exposed by Ogre. You would need to import that class org.janusgraph.core.attribute.Text and then:
(og/traverse g og/V
(og/has :name (Text/textContainsRegex ".*shr.*")
(og/value-map)
(og/into-list!))

Client-side cookies in Racket

I'm trying to re-write some Common Lisp web-scraping code in Racket.
In Common Lisp, I'm POSTing a login request, and storing the cookie-jar for subsequent GETs:
(defun login (username password)
"Logs in to www.example.com. Returns a cookie-jar containing authentication details."
(let ((cookie-jar (make-instance 'drakma:cookie-jar)))
(drakma:http-request "http://www.example.com/login"
:method :post
:parameters `(("username" . ,username) ("password" . ,password))
:cookie-jar cookie-jar)
cookie-jar))
; snip
(defun get-page (page-num cookie-jar)
"Downloads a potentially invalid HTML page containing data to scrape. Returns a string containing the HTML."
(let ((url (concatenate 'string "http://www.example.com/data/" (write-to-string page-num))))
(let ((body (drakma:http-request url :cookie-jar cookie-jar)))
(if (search "No data found." body)
nil
body))))
However, I can't find an equivalent in Racket. The latest HTTP library makes no mention of cookies at all, and AFAICT the cookie library seems more about correctly serializing and deserializing them.
Can anyone suggest a way of re-writing the above CL in Racket without having to implement a bunch of header-parsing stuff?
There is no such functionality in the Racket libraries (at the time of writing, 30 Jan 2014).
There has been some discussion on the Racket users list about this, and there is a third-party library called client-cookies that addresses the issue. At the time of writing that library is not yet production-ready, but is under active development.

Assignments and Usage of global Variables in Clojure

I've got the following problem:
I do understand that the concept of functional programming languages do not allow immutable variables, so classic variable assignment and usage like
var foo = bar();
after that in another function...
var baz = funnything(foo);
is not possible (correct me if it is, I'm still trying to get the whole idea and concepts behind functional programming).
I'm trying to play around a bit with Clojure and come to a point where I stuck:
I want to get a webpage and save the DOM into a variable for later usage.
The program starts, a prompt is spawning and the user can enter a URL which he want to fetch.
After the DOM of the website is fetched he can navigate through the DOM by for example getting the title, or all links or whatever.
The Problem:
Because I can't use a construct like
; More or less pseudo-code
(def page nil)
(get-url [url]
(page (browser/get url)))
(get-title
(println (html/select page [:title])))
I have to use the following construct:
(get-title [url]
(println (html/select (browser/get url) [:title])))
Due to this construct everytime I want to access an element of the site via get-title, get-links or whatever I have to download the whole webpage whenever the user is entering one of those methods on the command prompt.
Do I miss something here? Are there classical assigments in Clojure? Am I doing the complete thing wrong and should study a whole lot more functional programming concepts before getting hands-on and learning-by-doing?
You are misunderstanding assignment in clojure.
(page (browser/get url))
is not equivalent to: page = browser/get(url), it is equivalent to page(browser/get(url)).
I think you don't really need a global variable, just composable functions. Your example could look something like this:
(defn get-title [url]
(let [page (browser/get url)]
(println (html/select page [:title]))))
That and using memoize, like Joost mentioned, if you want to cache the return values of broser/get.
You can easily cache the value of (browser/get url) so you don't have to refetch the page every time you want to examine a property of it. See clojure.core/memoize. But that will only solve part of the problem.
In your particular case, your program requires some sort of global (or session scoped), mutable, concept of "the current page" or at least, "the current url", since that is what you're expecting your user to enter and modify. Clojure provides multiple constructs for managing mutable state.
Since you're only dealing with one page at a time, this is probably best modeled by using atoms. See http://clojure.org/atoms and http://clojuredocs.org/clojure_core/clojure.core/swap!

extend Babel date format tags in Django

I'm using BabelDjango to format dates and times in templates. Babel comes with some predefined formats called "short", "long", and "full". I know you can also just pass in your custom format like "DDD mmm" etc, but I would like to create a few more named formats. This would be much easier to spread a few different standard formats throughout my app.
is this possible? can I add more to Babel, or is it best to create my own tag filters in django?
Thanks!
Unfortunately defining custom aliases for date formats is not possible (yet) in Babel. The existing format names are taken from the CLDR database so they are pretty static at the moment.
I suggest you write you a wrapper function which translates your alias to a Babel date pattern.
Btw: Which date formats do you need?
Btw2: The Babel users mailing list is a good place to ask such questions (and likely you'll get faster answers).

What are the namespace gotchas for clojurescript when coming from clojure?

I'm trying to understand the namespacing model in clojurescript. I understand that javascript doesn't come built in with namespace support, so its been an add on via the google closure library. However, I don't understand how clojurescript deals with these differences. Can someone please explain?
Lets say for example I want to use the google charts api and whenever possible would like to use advanced compilation. What do I use in the closure/build call, how would the ns form look like and what's the best way to refer to the api from the code? I've looked at https://github.com/sritchie/contour but that example doesn't use advanced compilation, and I don't see the options referring to the google api in the project.clj file.
The namespace declaration is the same regardless of whether you are using simple or advanced mode compilation. The difference is that libraries that don't participate in google dependency management via goog.require('') and goog.provide('') need to be explictly referenced via an externs.js file. This file, which you pass to the cljs compiler, provides stubs of all the vars and associated methods. A typical externs.js would look something like:
// contents of externs.js
var externalLibrary = {}
var externalLibrary.method = function() {}
So to reference a google closure aware library your namespace declaration looks like this:
(ns my.namespace
(:require [goog.events.KeyCodes :as key-codes])
And that emits the following javascript:
goog.provide("my.namespace");
goog.require("goog.events.keycodes");
Note that if you want to call your closurescript from another javascript file then you need to tag the method as exported so that the optimizing compiler knows to preserve the name. (e.g. you might have a script tag on a page from where you want to call a javascript function that has been generated from clojurescript)
That looks like this:
(defn ^:export externallyCalled [])
The other thing to be aware of is that you have to treat macros differently in clojurescript, this is because the ability to process them 'on the fly' in the reader is not present in the same way as it is in clojure.
you do that as follows (note that you are obliged to bind the macros with :as in this case)
(ns my.namespace
(:require-macros [my.macros :as my]))
If you are calling code that didn't participate in google's dependency management you access it via the js namespace and the javascript interop...
(. js/nonGoogle (method args)) ; a method access
(. js/nonGoogle -p) ; a property access
all the usual . variants work too..