From 0d07515c189fc20f829a8efd2d6fe53f3cebc3d3 Mon Sep 17 00:00:00 2001 From: Martin Zimmermann Date: Sat, 2 Nov 2013 15:07:42 +0100 Subject: [PATCH 1/2] override HTML title parsing with a `data-title="...` attribute If you don't use a

to markup your post's title (but h2), it is no longer possible to reliable detect the site's title. E.g. you have a single page with only one

and that's the *real* title of that page. But on the other hand, it is also possible, that the

tag is just your website's name and the actual post title is marked up in

. --- README.md | 35 +++++++++++++++++++++++++++++++++++ isso/utils/parse.py | 19 ++++++++++++++++--- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a93a6a9..186d73e 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,41 @@ current comment count. This functionality is already included when you embed `embed.min.js`, do *not* mix `embed.min.js` and `count.min.js` in a single document. +### Client Configuration + +You can configure the client (the JS part) via `data-` attributes: + +* data-title + + When you start a new thread (= first comment on a page), Isso sends + a GET request that page to see if it a) exists and b) parse the site's + heading (currently used as subject in emails). + + Isso assumes that the title is inside an `h1` tag near the isso thread: + + ```html + + +

Website Title

+
+
+

Post Title

+
+ ... + ``` + + In this example, the detected title is `Post Title` as expected, but some + older sites may only use a single `h1` as their website's maintitle, and + a `h2` for the post title. Unfortunately this is unambiguous and you have + to tell Isso what's the actual post title: + + ```html +
+ ``` + + Make sure to escape the attribute value. + + ### Webserver configuration * nginx configuration to run Isso on `/isso`: diff --git a/isso/utils/parse.py b/isso/utils/parse.py index 8decd38..a03ba7b 100644 --- a/isso/utils/parse.py +++ b/isso/utils/parse.py @@ -7,9 +7,10 @@ import datetime from itertools import chain try: + from urllib import unquote from urlparse import urlparse except ImportError: - from urllib.parse import urlparse + from urllib.parse import urlparse, unquote import html5lib @@ -81,7 +82,7 @@ def title(data, default=u"Untitled."): which is the nearest H1 node in context to an element with the `isso-thread` id. >>> title("asdf") # doctest: +IGNORE_UNICODE - u'Untitled.' + 'Untitled.' >>> title(''' ... ... @@ -101,7 +102,14 @@ def title(data, default=u"Untitled."): ...
... ... ''') # doctest: +IGNORE_UNICODE - u'Can you find me?' + 'Can you find me?' + >>> title(''' + ... + ... + ...

I'm the real title!1 + ...
+ ... ''') # doctest: +IGNORE_UNICODE + 'No way!' """ html = html5lib.parse(data, treebuilder="dom") @@ -137,6 +145,11 @@ def title(data, default=u"Untitled."): for item in gettext(child): yield item + try: + return unquote(el.attributes["data-title"].value) + except (KeyError, AttributeError): + pass + while el is not None: # el.parentNode is None in the very end visited.append(el) From 8da9d0b13bb72a5e3a57711af001c9397048e12e Mon Sep 17 00:00:00 2001 From: Martin Zimmermann Date: Sat, 2 Nov 2013 18:26:33 +0100 Subject: [PATCH 2/2] override API location with `data-prefix="..."` --- README.md | 9 +++++++++ isso/js/app/api.js | 47 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 186d73e..bb8eb1b 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,15 @@ You can configure the client (the JS part) via `data-` attributes: Make sure to escape the attribute value. +* data-prefix + + Isso usually detects the REST API automatically, but when you serve the JS + script on a different location, this may fail. Use `data-prefix` to + override the API location: + + ```html + + ``` ### Webserver configuration diff --git a/isso/js/app/api.js b/isso/js/app/api.js index 33cab7c..5bbd1c4 100644 --- a/isso/js/app/api.js +++ b/isso/js/app/api.js @@ -22,20 +22,51 @@ define(["q"], function(Q) { "/count": [200] }; - // guess Isso API location + /* + * Detect Isso API endpoint. There are typically two use cases: + * + * 1. use minified, single-file JavaScript. The browser interprets + * scripts sequentially, thus we can safely use the last script + * tag. Then, we chop off some characters -- /js/embed.min.s -- + * and we're done. + * + * If the script is not served by Isso directly, a custom data + * attribute can be used to override the default detection + * mechanism: + * + * .. code-block:: html + * + * + * + * 2. use require.js (during development). When using require.js, we + * assume that the path to the scripts ends with `/js/`. + * + */ + + var script, uri; + var port = window.location.port ? ":" + window.location.port : "", + host = window.location.protocol + "//" + window.location.hostname + port; + var js = document.getElementsByTagName("script"); for (var i = 0; i < js.length; i++) { - if (js[i].src.match("/js/components/requirejs/require\\.js$")) { - endpoint = js[i].src.substring(0, js[i].src.length - 35); - break; - } else if (js[i].src.match("/js/(embed|count)\\.(min|dev)\\.js$")) { - endpoint = js[i].src.substring(0, js[i].src.length - 16); - break; + if (js[i].src.match("require\\.js$") && js[i].dataset.main.match("/js/embed$")) { + uri = js[i].dataset.main; + endpoint = uri.substr(0, uri.length - "/js/main".length); } } if (! endpoint) { - throw "no Isso API location found"; + script = js[js.length - 1]; + + if (script.dataset.prefix) { + endpoint = script.dataset.prefix; + if (endpoint[endpoint.length - 1] === "/") { + endpoint = endpoint.substring(0, endpoint.length - 1); + } + } else { + uri = script.src.substring(host.length); + endpoint = uri.substring(0, uri.length - "/js/embed.min.js".length); + } } var curl = function(method, url, data) {