diff --git a/README.md b/README.md index a93a6a9..bb8eb1b 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,50 @@ 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. + +* 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 * nginx configuration to run Isso on `/isso`: diff --git a/isso/js/app/api.js b/isso/js/app/api.js index 4aacf04..ca6569f 100644 --- a/isso/js/app/api.js +++ b/isso/js/app/api.js @@ -17,20 +17,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) { 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)