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)