From 506183ee16730dfc1e6e3beab047d972e6692272 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Mon, 19 Aug 2024 21:38:04 -0400 Subject: [PATCH] Initial version of multiple source support --- Makefile | 24 +++ README.md | 2 +- app.py | 5 +- build.py | 24 --- copyvios/checker.py | 33 +++- copyvios/highlighter.py | 39 ++-- copyvios/misc.py | 18 ++ scripts/log_analyzer.py | 2 +- static/{ => css}/style.css | 233 ++++++++++++++--------- static/css/tooltip.css | 73 +++++++ static/script.js | 283 +++++++++++++++++++++++----- static/script.min.js | 2 +- static/style.min.css | 2 +- templates/api.mako | 2 +- templates/error.mako | 4 +- templates/{support => includes}/footer.mako | 4 +- templates/includes/form.mako | 44 +++++ templates/{support => includes}/header.mako | 7 +- templates/includes/ooui.mako | 89 +++++++++ templates/includes/result.mako | 191 +++++++++++++++++++ templates/includes/site.mako | 40 ++++ templates/index.mako | 274 +-------------------------- templates/settings.mako | 110 ++++------- 23 files changed, 960 insertions(+), 545 deletions(-) create mode 100644 Makefile delete mode 100755 build.py rename static/{ => css}/style.css (62%) create mode 100644 static/css/tooltip.css rename templates/{support => includes}/footer.mako (95%) create mode 100644 templates/includes/form.mako rename templates/{support => includes}/header.mako (62%) create mode 100644 templates/includes/ooui.mako create mode 100644 templates/includes/result.mako create mode 100644 templates/includes/site.mako diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..93c2fa7 --- /dev/null +++ b/Makefile @@ -0,0 +1,24 @@ +MAKEJS := uglifyjs --compress +MAKECSS := postcss -u cssnano --no-map + +.PHONY: all + +.INTERMEDIATE: static/style.tmp.css + +all: js css + +js: static/script.min.js + +css: static/style.min.css static/api.min.css + +static/script.min.js: static/script.js + $(MAKEJS) -o $@ -- $^ + +static/style.tmp.css: static/css/*.css + cat $^ > $@ + +static/style.min.css: static/style.tmp.css + $(MAKECSS) -o $@ $^ + +static/api.min.css: static/api.css + $(MAKECSS) -o $@ $^ diff --git a/README.md b/README.md index 230bd66..e5f0ed4 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,6 @@ Running If additional arguments are needed by `oursql.connect()`, like usernames or passwords, they should be added to the `_copyviosSQL` section. -- Run `./build.py` to minify JS and CSS files. +- Run `make` to minify JS and CSS files. - Start the web server (on Toolforge, `webservice uwsgi-python start`). diff --git a/app.py b/app.py index ff88f48..e7c3c87 100755 --- a/app.py +++ b/app.py @@ -110,10 +110,7 @@ def index(): def settings(): status = process_settings() if request.method == "POST" else None update_sites() - default = cache.bot.wiki.get_site() - kwargs = {"status": status, "default_lang": default.lang, - "default_project": default.project} - return render_template("settings.mako", **kwargs) + return render_template("settings.mako", status=status) @app.route("/api") @catch_errors diff --git a/build.py b/build.py deleted file mode 100755 index 5519d3f..0000000 --- a/build.py +++ /dev/null @@ -1,24 +0,0 @@ -#! /usr/bin/env python -# -*- coding: utf-8 -*- - -from __future__ import print_function -import os -import subprocess - -def process(*args): - print(*args) - content = subprocess.check_output(args) - -def main(): - root = os.path.join(os.path.dirname(__file__), "static") - for dirpath, dirnames, filenames in os.walk(root): - for filename in filenames: - name = os.path.relpath(os.path.join(dirpath, filename)) - if filename.endswith(".js") and ".min." not in filename: - process("uglifyjs", "--compress", "-o", name.replace(".js", ".min.js"), "--", name) - if filename.endswith(".css") and ".min." not in filename: - process("postcss", "-u", "cssnano", "--no-map", name, "-o", - name.replace(".css", ".min.css")) - -if __name__ == "__main__": - main() diff --git a/copyvios/checker.py b/copyvios/checker.py index c892db3..7098d83 100644 --- a/copyvios/checker.py +++ b/copyvios/checker.py @@ -37,6 +37,21 @@ def do_check(query=None): if query.oldid: query.oldid = query.oldid.strip().lstrip("0") + urls = {} + for key, value in query.query.items(): + if not value: + continue + if key == "url": + urls[0] = value + elif key.startswith("url"): + try: + num = int(key[3:]) + except ValueError: + continue + urls[num] = value + query.urls = [url for _, url in sorted(urls.items())] + query.url = query.urls[0] if query.urls else None + query.submitted = query.project and query.lang and (query.title or query.oldid) if query.submitted: query.site = get_site(query) @@ -69,7 +84,7 @@ def _get_results(query, follow=True): return if not query.action: - query.action = "compare" if query.url else "search" + query.action = "compare" if query.urls else "search" if query.action == "search": use_engine = 0 if query.use_engine in ("0", "false") else 1 use_links = 0 if query.use_links in ("0", "false") else 1 @@ -85,15 +100,17 @@ def _get_results(query, follow=True): # Handle the copyvio check _perform_check(query, page, use_engine, use_links) elif query.action == "compare": - if not query.url: + if not query.urls: query.error = "no URL" return - scheme = urlparse(query.url).scheme - if not scheme and query.url[0] not in ":/": - query.url = "http://" + query.url - elif scheme not in ["http", "https"]: - query.error = "bad URI" - return + for i, url in enumerate(query.urls): + scheme = urlparse(url).scheme + if not scheme and url[0] not in ":/": + query.urls[i] = "http://" + url + elif scheme not in ["http", "https"]: + query.error = "bad URI" + query.bad_uri = url + return degree = 5 if query.degree: try: diff --git a/copyvios/highlighter.py b/copyvios/highlighter.py index a3fb21f..c2e8da3 100644 --- a/copyvios/highlighter.py +++ b/copyvios/highlighter.py @@ -8,20 +8,24 @@ from markupsafe import escape __all__ = ["highlight_delta"] -def highlight_delta(context, chain, delta): +def highlight_delta(context, chain, deltas, index=1): degree = chain.degree - 1 - highlights = [False] * degree + highlights = [None] * degree block = deque([chain.START] * degree) - if not delta: - delta = EMPTY_INTERSECTION + if deltas is None: + deltas = [EMPTY_INTERSECTION] + if not isinstance(deltas, list): + deltas = [deltas] for word in chain.text.split() + ([chain.END] * degree): word = _strip_word(chain, word) block.append(word) - if tuple(block) in delta.chain: - highlights[-1 * degree:] = [True] * degree - highlights.append(True) + for i, delta in enumerate(deltas, index): + if tuple(block) in delta.chain: + highlights[-1 * degree:] = [i] * degree + highlights.append(i) + break else: - highlights.append(False) + highlights.append(None) block.popleft() i = degree @@ -36,7 +40,7 @@ def highlight_delta(context, chain, delta): after = highlights[i + 1] first = i == degree last = i - degree + 1 == numwords - words.append(_highlight_word(word, before, after, first, last)) + words.append(_highlight_word(word, highlights[i], before, after, first, last)) else: words.append(unicode(escape(word))) result.append(u" ".join(words)) @@ -58,24 +62,25 @@ def _get_next(paragraphs): break return body -def _highlight_word(word, before, after, first, last): - if before and after: +def _highlight_word(word, this, before, after, first, last): + open_span = u'' % this + if this == before and this == after: # Word is in the middle of a highlighted block: res = unicode(escape(word)) if first: - res = u'' + res + res = open_span + res if last: res += u'' - elif after: + elif this == after: # Word is the first in a highlighted block: - res = u'' + _fade_word(word, u"in") + res = open_span + _fade_word(word, u"in") if last: res += u"" - elif before: + elif this == before: # Word is the last in a highlighted block: res = _fade_word(word, u"out") + u"" if first: - res = u'' + res + res = open_span + res else: res = unicode(escape(word)) return res @@ -96,4 +101,4 @@ def _fade_word(word, dir): def _strip_word(chain, word): if word == chain.START or word == chain.END: return word - return sub("[^\w\s-]", "", word.lower(), flags=UNICODE) + return sub(r"[^\w\s-]", "", word.lower(), flags=UNICODE) diff --git a/copyvios/misc.py b/copyvios/misc.py index b4cbca2..80cc7a0 100644 --- a/copyvios/misc.py +++ b/copyvios/misc.py @@ -1,8 +1,10 @@ # -*- coding: utf-8 -*- from contextlib import contextmanager +from collections import OrderedDict import datetime from os.path import expanduser, join +import urllib import apsw from flask import g, request @@ -116,3 +118,19 @@ def urlstrip(context, url): if url.endswith("/"): url = url[:-1] return url + +def get_permalink(context, query): + params = OrderedDict() + params["lang"] = query.lang + params["project"] = query.project + params["oldid"] = query.oldid or query.page.lastrevid + params["action"] = query.action + if query.action == "search": + params["use_engine"] = int(query.use_engine not in ("0", "false")) + params["use_links"] = int(query.use_links not in ("0", "false")) + params["turnitin"] = int(query.turnitin in ("1", "true")) + elif query.action == "compare": + params["url"] = query.url + for i, url in enumerate(query.urls[1:], 2): + params["url%d" % i] = url + return "%s/?%s" % (request.script_root, urllib.urlencode(params)) diff --git a/scripts/log_analyzer.py b/scripts/log_analyzer.py index 2c77071..7e28573 100755 --- a/scripts/log_analyzer.py +++ b/scripts/log_analyzer.py @@ -11,7 +11,7 @@ REGEX = re.compile( r'{(?P\d+) vars in (?P\d+) bytes} ' r'\[(?P[0-9A-Za-z: ]+)\] (?P\w+) (?P.*?) => ' r'generated (?P\d+) bytes in (?P\d+) msecs ' - r'\((- http://hasty.ai)?(?P[A-Z0-9/.]+) (?P\d+)\) ' + r'\((- http://hasty.ai ?)?(?P[A-Z0-9/.]+) (?P\d+)\) ' r'(?P\d+) headers in (?P\d+) bytes ' r'\((?P\d+) switches on core (?P\d+)\) ' r'(?P.*?)' diff --git a/static/style.css b/static/css/style.css similarity index 62% rename from static/style.css rename to static/css/style.css index 3c48d55..ed90d17 100644 --- a/static/style.css +++ b/static/css/style.css @@ -46,8 +46,8 @@ body { #content { background-color: #fff; - border: 1px solid #c8ccd1; - filter: drop-shadow(0 0 10px rgba(0, 0, 0, 0.25)); + border: 1px solid #a2a9b1; + filter: drop-shadow(0 0 1em rgba(0, 0, 0, 0.25)); margin: 1.5em 3em; padding: 1em; } @@ -102,22 +102,10 @@ footer { font-size: 0.9em; text-align: center; line-height: 1.5; - border-top: 1px solid #c8ccd1; + border-top: 1px solid #a2a9b1; background: #fff; } -footer ul { - margin: 0; -} - -footer li { - display: inline; -} - -footer li:not(:last-child)::after { - content: ' \00b7'; -} - footer a { white-space: nowrap; } @@ -158,8 +146,7 @@ h2 { #sources-container { padding: 0.5em 1em 1em; margin: 1em 0; - background-color: #eee; - border: 1px solid #bbb; + border: 1px solid #a2a9b1; } #turnitin-title, #sources-title { @@ -183,29 +170,34 @@ h2 { } } -#heading { - width: 100%; -} - #cv-result-sources { width: 100%; border-spacing: 0 0.4em; - table-layout: fixed; } -#cv-result-sources col:nth-child(1) { width: 80%; } -#cv-result-sources col:nth-child(2) { width: 10%; } -#cv-result-sources col:nth-child(3) { width: 10%; } +#cv-result-sources tr:first-child th:nth-child(1) { width: 4em; } +#cv-result-sources tr:first-child th:nth-child(3) { width: 7em; } +#cv-result-sources tr:first-child th:nth-child(4) { width: 10em; } + +@media only screen and (max-width: 1000px) { + #cv-result-sources tr:first-child th:nth-child(1) { width: 3em; } + #cv-result-sources tr:first-child th:nth-child(3) { width: 5em; } + #cv-result-sources tr:first-child th:nth-child(4) { width: 8em; } +} #cv-result-sources th { text-align: left; } #cv-result-sources tr:nth-child(even) { - background-color: #e0e0e0; + background-color: #eaecf0; +} + +#cv-result-sources th:first-child, #cv-result-sources td:first-child { + text-align: center; } -#cv-result-sources td:first-child { +#cv-result-sources td:nth-child(2) { overflow: hidden; word-wrap: break-word; } @@ -247,12 +239,6 @@ h2 { font-size: 0.8em; } -#cv-chain-table { - width: 100%; - border-spacing: 0; - table-layout: fixed; -} - #turnitin-table { table-layout: fixed; width: 100%; @@ -260,12 +246,20 @@ h2 { border-spacing: 0; } -#source-row-selected { - background-color: #cfcfcf !important; +#cv-result-sources tr.source-row-selected { + background-color: #d0d2d5; } -#head-settings { - text-align: right; +.source-row-selected .source-url { + font-weight: bold; +} + +.source-row-selected .source-compare { + display: none; +} + +.source-row:not(.source-row-selected) .source-compare-selected { + display: none; } #cv-result-header { @@ -282,47 +276,37 @@ h2 { font-style: italic; } -#source-selected { - font-weight: bold; +.hlist { + margin: 0; + padding: 0; } -#cv-cached { - position: relative; +.hlist li { + display: inline; } -#cv-cached span { - display: none; - position: absolute; - top: 1.5em; - left: -5em; - width: 30em; - padding: 1em; - z-index: 1; - background: #f3f3f3; - border: 1px solid #aaa; - color: black; - font-style: normal; - text-align: left; +.hlist li:not(:last-child)::after { + content: ' \00b7'; } .green-box { - background-color: #efe; - border: 1px solid #7f7; + background-color: #e0fdf4; + border: 1px solid #54a66d; } .yellow-box { - background-color: #ffd; - border: 1px solid #ee5; + background-color: #fef6e7; + border: 1px solid #fc3; } .red-box { - background-color: #fee; - border: 1px solid #f77; + background-color: #fee7e6; + border: 1px solid #d33; } .gray-box { - background-color: #eee; - border: 1px solid #aaa; + background-color: #eaecf0; + border: 1px solid #a2a9b1; } .indentable { @@ -338,25 +322,30 @@ h2 { font-style: normal; } -.cv-chain-detail { - padding: 0 1em; - background-color: #fff; - border: 1px solid #bbb; +.cv-chain-table { + width: 100%; + border-spacing: 0; + table-layout: fixed; } -.cv-chain-cell { +.cv-chain-table td { vertical-align: top; word-wrap: break-word; } -.cv-chain-cell:first-child { +.cv-chain-table td:first-child { padding-right: 0.5em; } -.cv-chain-cell:last-child { +.cv-chain-table td:not(:first-child) { padding-left: 0.5em; } +.cv-chain-cell > div { + padding: 0 1em; + border: 1px solid #a2a9b1; +} + .turnitin-table-cell { padding: 0.5em 0 0.3em 0; } @@ -366,18 +355,10 @@ h2 { line-height: 1.4; } -.cv-hl { - background: #faa; -} - -.cv-hl-in { - background: #fcc; - background: linear-gradient(to left, #faa, #fff); -} - -.cv-hl-out { - background: #fcc; - background: linear-gradient(to right, #faa, #fff); +.highlight-demo { + display: inline-block; + border: 1px solid #777; + padding: 0.25em 0.5em; } .mono { font-family: monospace; } @@ -414,14 +395,48 @@ header a:active { color: #333; } -#cv-cached:active { color: #040; text-decoration: none; } -#cv-cached:hover { text-decoration: none; } -#cv-cached:hover span { display: block; } +.source-num { + display: inline-block; + min-width: 1.5em; + text-align: center; +} + +.source-num-included { + border: 1px solid #777; +} + +a.source-num-included { + color: #000; +} + +.source-num-included:hover, .source-num-included:active { + text-decoration: none; +} + +.hidden { + display: none; +} + +#source-tooltips { + position: relative; +} + +.source-tooltip-selected a.selector { + display: none; +} + +.source-tooltip:not(.source-tooltip-selected) strong.selector { + display: none; +} + +.source-tooltip .selector, .source-tooltip .domain, .source-tooltip .wordcount { + display: inline-block; +} -.source-url:link { color: #357; } -.source-url:visited { color: #357; } -.source-url:hover { color: #035; } -.source-url:active { color: #404; } +.cv-chain-cell .cv-hl:hover, .cv-selected { + outline: 1px dashed #333; + cursor: pointer; +} .oo-ui-horizontalLayout > .oo-ui-textInputWidget, .oo-ui-horizontalLayout > .oo-ui-dropdownInputWidget { @@ -454,12 +469,46 @@ label.site, label.page { min-width: 4em; } -label.action { - min-width: 10em; -} - @media only screen and (max-width: 720px) { .oo-ui-horizontalLayout > .oo-ui-widget { width: 100%; } } + +/* https://colorbrewer2.org/?type=qualitative&scheme=Pastel1&n=8 */ + +.cv-hl { background: #dddddd; } +.cv-hl .cv-hl-in { background: linear-gradient(to left, #dddddd, #fff); } +.cv-hl .cv-hl-out { background: linear-gradient(to right, #dddddd, #fff); } + +.cv-hl-1 { background: #fed9a6; } +.cv-hl-1 .cv-hl-in { background: linear-gradient(to left, #fed9a6, #fff); } +.cv-hl-1 .cv-hl-out { background: linear-gradient(to right, #fed9a6, #fff); } + +.cv-hl-2 { background: #b3cde3; } +.cv-hl-2 .cv-hl-in { background: linear-gradient(to left, #b3cde3, #fff); } +.cv-hl-2 .cv-hl-out { background: linear-gradient(to right, #b3cde3, #fff); } + +.cv-hl-3 { background: #ccebc5; } +.cv-hl-3 .cv-hl-in { background: linear-gradient(to left, #ccebc5, #fff); } +.cv-hl-3 .cv-hl-out { background: linear-gradient(to right, #ccebc5, #fff); } + +.cv-hl-4 { background: #fbb4ae; } +.cv-hl-4 .cv-hl-in { background: linear-gradient(to left, #fbb4ae, #fff); } +.cv-hl-4 .cv-hl-out { background: linear-gradient(to right, #fbb4ae, #fff); } + +.cv-hl-5 { background: #decbe4; } +.cv-hl-5 .cv-hl-in { background: linear-gradient(to left, #decbe4, #fff); } +.cv-hl-5 .cv-hl-out { background: linear-gradient(to right, #decbe4, #fff); } + +.cv-hl-6 { background: #ffffcc; } +.cv-hl-6 .cv-hl-in { background: linear-gradient(to left, #ffffcc, #fff); } +.cv-hl-6 .cv-hl-out { background: linear-gradient(to right, #ffffcc, #fff); } + +.cv-hl-7 { background: #e5d8bd; } +.cv-hl-7 .cv-hl-in { background: linear-gradient(to left, #e5d8bd, #fff); } +.cv-hl-7 .cv-hl-out { background: linear-gradient(to right, #e5d8bd, #fff); } + +.cv-hl-8 { background: #fddaec; } +.cv-hl-8 .cv-hl-in { background: linear-gradient(to left, #fddaec, #fff); } +.cv-hl-8 .cv-hl-out { background: linear-gradient(to right, #fddaec, #fff); } diff --git a/static/css/tooltip.css b/static/css/tooltip.css new file mode 100644 index 0000000..c4c06a9 --- /dev/null +++ b/static/css/tooltip.css @@ -0,0 +1,73 @@ +.tooltip { + display: block; + position: absolute; + bottom: 100%; + width: 30em; + padding-bottom: 0.5em; + font-style: normal; + text-align: left; + z-index: 1; +} + +.tooltip > span { + display: block; + background-color: white; + border: 1px solid #c8ccd1; + filter: drop-shadow(0 0 0.5em rgba(0, 0, 0, 0.25)); + padding: 0.5em 1em; +} + +.tooltip > span::after { + content: ' '; + position: absolute; + top: 100%; + border: 0.5em solid transparent; + border-top-color: white; +} + +abbr, .tooltip-anchor-inline { + border-width: 0; + text-decoration: underline dotted; +} + +.tooltip-anchor-inline { + position: relative; +} + +.tooltip-anchor-inline > .tooltip { + display: none; +} + +.tooltip-anchor-inline:hover > .tooltip { + display: block; +} + +.tooltip-anchor-fixed { + position: absolute; +} + +.tooltip-align-center { + left: 50%; + margin-left: -15em; +} + +.tooltip-align-center > span::after { + left: 50%; + margin-left: -0.5em; +} + +.tooltip-align-left { + left: -2.5em; +} + +.tooltip-align-left > span::after { + left: 2em; +} + +.tooltip-align-right { + right: -2.5em; +} + +.tooltip-align-right > span::after { + right: 2em; +} diff --git a/static/script.js b/static/script.js index 3bdc77f..bbce644 100644 --- a/static/script.js +++ b/static/script.js @@ -1,16 +1,16 @@ -function update_screen_size() { - var cache = cache_cookie(); +function updateScreenSize() { + var cache = cacheCookie(); var data = { "width": window.screen.availWidth, "height": window.screen.availHeight } if (!cache || cache["width"] != data["width"] || cache["height"] != data["height"]) { - set_cookie("CopyviosScreenCache", JSON.stringify(data), 1095); + setCookie("CopyviosScreenCache", JSON.stringify(data), 1095); } } -function cache_cookie() { - var cookie = get_cookie("CopyviosScreenCache"); +function cacheCookie() { + var cookie = getCookie("CopyviosScreenCache"); if (cookie) { try { data = JSON.parse(cookie); @@ -27,7 +27,7 @@ function cache_cookie() { // Cookie code partially based on http://www.quirksmode.org/js/cookies.html -function get_cookie(name) { +function getCookie(name) { var nameEQ = name + "="; var ca = document.cookie.split(";"); for (var i = 0; i < ca.length; i++) { @@ -45,34 +45,61 @@ function get_cookie(name) { return null; } -function set_cookie_with_date(name, value, date) { +function setCookieWithDate(name, value, date) { value = window.btoa("--cpv2" + value); - var path = window.location.pathname.split("/", 2)[1]; if (date) { - var expires = "; expires=" + date.toUTCString(); + var expires = ";expires=" + date.toUTCString(); } else { var expires = ""; } - document.cookie = name + "=" + value + expires + "; path=/" + path; + document.cookie = name + "=" + value + expires + ";path=/;samesite=lax"; } -function set_cookie(name, value, days) { +function setCookie(name, value, days) { if (days) { var date = new Date(); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); - set_cookie_with_date(name, value, date); + setCookieWithDate(name, value, date); } else { - set_cookie_with_date(name, value); + setCookieWithDate(name, value); } } -function delete_cookie(name) { - set_cookie(name, "", -1); +function selectTab(e) { + var tab = $(e.target); + if (tab.hasClass("oo-ui-optionWidget-selected")) { + return false; + } + var name = tab.data("name"); + var menu = tab.closest(".oo-ui-menuLayout"); + menu.find(".oo-ui-optionWidget-selected") + .removeClass("oo-ui-optionWidget-selected") + .attr("aria-selected", "false"); + tab.addClass("oo-ui-optionWidget-selected") + .attr("aria-selected", "true"); + menu.find(".oo-ui-tabPanelLayout-active") + .removeClass("oo-ui-tabPanelLayout-active") + .addClass("oo-ui-element-hidden") + .attr("aria-hidden", "true"); + menu.find('.oo-ui-tabPanelLayout[data-name="' + name + '"]') + .addClass("oo-ui-tabPanelLayout-active") + .removeClass("oo-ui-element-hidden") + .removeAttr("aria-hidden"); + return false; +} + +function submitForm() { + $("#cv-form button[type='submit']") + .prop("disabled", true) + .css("cursor", "progress") + .parent() + .addClass("oo-ui-widget-disabled") + .removeClass("oo-ui-widget-enabled"); } -function toggle_notice() { +function toggleNotice() { var details = $("#notice-collapse-box"), trigger = $("#notice-collapse-trigger"); if (details.is(":hidden")) { @@ -85,16 +112,16 @@ function toggle_notice() { } } -function install_notice() { +function setNotice() { var details = $("#notice-collapse-box"), trigger = $("#notice-collapse-trigger"); if (details.length >= 0 && trigger.length >= 0) { - trigger.replaceWith($("", { + trigger.replaceWith($("", { id: "notice-collapse-trigger", href: "#", text: "[show]", click: function() { - toggle_notice(); + toggleNotice(); return false; } })); @@ -102,42 +129,173 @@ function install_notice() { } } -$(document).ready(function() { - $("#action-search").change(function() { - $(".cv-search").prop("disabled", false); - $(".cv-compare").prop("disabled", true); - $(".cv-search-oo-ui").addClass("oo-ui-widget-enabled").removeClass("oo-ui-widget-disabled"); - $(".cv-compare-oo-ui").addClass("oo-ui-widget-disabled").removeClass("oo-ui-widget-enabled"); +function addUrl() { + var template = $("#compare-new-url"); + var widget = template[0].content.cloneNode(true); + $(widget).find("input").prop("name", "url" + ($(".compare-url").length + 1)); + $(widget).find(".compare-remove-url").click(removeUrl); + template.before(widget); + return false; +} + +function removeUrl(e) { + $(e.target).closest(".oo-ui-layout").remove(); + $(".compare-url:not(.compare-url-first)").each(function(i, e) { + $(e).find("input").prop("name", "url" + (i + 2)); }); - $("#action-compare").change(function() { - $(".cv-search").prop("disabled", true); - $(".cv-compare").prop("disabled", false); - $(".cv-search-oo-ui").addClass("oo-ui-widget-disabled").removeClass("oo-ui-widget-enabled"); - $(".cv-compare-oo-ui").addClass("oo-ui-widget-enabled").removeClass("oo-ui-widget-disabled"); + return false; +} + +function pasteText() { + // TODO + return false; +} + +function uploadFile() { + // TODO + return false; +} + +function selectResult(n) { + var select = $(".cv-chain-source-" + n); + if (select.length === 0) { + return; + } + $(".cv-chain-source").addClass("hidden"); + select.removeClass("hidden"); + $(".source-row-selected").removeClass("source-row-selected"); + $($(".source-row")[n - 1]).addClass("source-row-selected"); + $(".source-tooltip > .tooltip-align-right").remove(); + $(".source-tooltip-selected").removeClass("source-tooltip-selected"); + $(".source-tooltip").filter(function(i, elem) { + return elem.dataset.id === n.toString(); + }).addClass("source-tooltip-selected"); +} + +function setResultSelectionHandlers() { + $(".source-compare").click(function(e) { + selectResult($(e.target).data("id")); + return false; }); - if ($("#action-search" ).is(":checked")) $("#action-search" ).change(); - if ($("#action-compare").is(":checked")) $("#action-compare").change(); - - $("#cv-form").submit(function() { - if ($("#action-search").is(":checked")) { - var hidden = [ - ["engine", "use_engine"], ["links", "use_links"], - ["turnitin", "turnitin"]]; - $.each(hidden, function(i, val) { - if ($("#cv-cb-" + val[0]).is(":checked")) - $("#cv-form input[type='hidden'][name='" + val[1] + "']") - .prop("disabled", true); - }); + $("#cv-result-sources tr:not(:first-child)").click(function(e) { + if (e.target.tagName === "TD") { + selectResult($(e.target).parent().data("id")); + return false; } - $("#cv-form button[type='submit']") - .prop("disabled", true) - .css("cursor", "progress") - .parent() - .addClass("oo-ui-widget-disabled") - .removeClass("oo-ui-widget-enabled"); }); +} + +function toggleSource(e) { + var el = $(e.target), + id = el.data("id"); + if (el.hasClass("cv-hl")) { + $(".cv-hl-" + id) + .addClass("cv-hl-disabled-" + id) + .removeClass(["cv-hl-" + id, "cv-hl"]); + } else { + $(".cv-hl-disabled-" + id) + .addClass(["cv-hl-" + id, "cv-hl"]) + .removeClass("cv-hl-disabled-" + id); + } + return false; +} + +function unselectRegions() { + if ($(".source-tooltip, .cv-selected").length > 0) { + $(".source-tooltip").remove(); + $(".cv-selected").removeClass("cv-selected"); + return false; + } +} + +function selectRegion(e) { + unselectRegions(); + var target = $(e.target).closest(".cv-hl"); + if (target.length === 0) { + return; + } + var hls = [].slice.apply(target[0].classList).filter(function(c) { + return c.startsWith("cv-hl-"); + }); + if (hls.length === 0) { + return; + } + var num = parseInt(hls[0].substr(6)); + var url = null, selected = true; + if ($("#cv-result-sources").length > 0) { + url = $(".source-url-" + num); + if (url.length === 0) { + return; + } + selected = $(".source-row-selected").data("id") === num; + } + var wordcount = target.text().split(/\s+/).filter(function(s) { return s != '' }).length; + var width; + + var contents = $(""); + if (url !== null) { + var domain = url.data("domain") || url.text(); + contents.append( + $("", { + class: "selector", + href: "#", + title: "Select source", + }) + .text("Source " + num) + .click(function() { + selectResult(num); + return false; + }) + ).append( + $("", {class: "selector"}) + .text("Source " + num) + ).append(" ") + .append( + $("", {class: "domain"}) + .text("(" + domain + "):") + ).append(" "); + width = Math.min(15 + domain.length / 2, 30); + } else { + width = 8; + } + contents + .append( + $("", {class: "wordcount"}) + .text(wordcount.toString() + " words") + ).click(function() { + if ($(".source-row-selected").data("id") === num) { + unselectRegions(); + } else { + selectResult(num); + } + return false; + }); + + var container = $("#source-tooltips"); + var containerOffset = container.offset(); + var chain = target.closest(".cv-chain-cell"); + var tooltipDirection = chain.hasClass("cv-chain-source") ? "right" : "left"; + var tooltip = $("
", {class: "source-tooltip tooltip-anchor-fixed"}) + .css({ + top: (e.pageY - containerOffset.top) + "px", + left: (e.pageX - containerOffset.left) + "px", + }) + .append( + $("", {class: "tooltip tooltip-align-" + tooltipDirection}) + .css({ + width: width + "em", + }).append(contents) + ).appendTo(container) + .attr("data-id", num.toString()); + if (selected) { + tooltip.addClass("source-tooltip-selected"); + } + target.addClass("cv-selected"); + return false; +} +function hideAdditionalSources() { if ($("#cv-additional").length >= 0) { $("#cv-additional").css("display", "block"); $(".source-default-hidden").css("display", "none"); @@ -147,6 +305,31 @@ $(document).ready(function() { return false; }); } +} + +$(document).ready(function() { + $(".oo-ui-optionWidget").click(selectTab); + $("#compare-add-url").click(addUrl); + $("#compare-paste").click(pasteText); + $("#compare-upload").click(uploadFile); + $(".compare-remove-url").click(removeUrl); + + setResultSelectionHandlers(); + + $(".source-num-included").click(toggleSource); + + $(".cv-chain-cell .cv-hl").click(selectRegion); + $("body").click(unselectRegions); + + $(document).keyup(function(e) { + if (e.key === "Escape") { + return unselectRegions(); + } + }); + + $("#cv-form").submit(submitForm); + + hideAdditionalSources(); - install_notice(); + setNotice(); }); diff --git a/static/script.min.js b/static/script.min.js index e415611..56c2e47 100644 --- a/static/script.min.js +++ b/static/script.min.js @@ -1 +1 @@ -function update_screen_size(){var cache=cache_cookie(),data={width:window.screen.availWidth,height:window.screen.availHeight};cache&&cache.width==data.width&&cache.height==data.height||set_cookie("CopyviosScreenCache",JSON.stringify(data),1095)}function cache_cookie(){var cookie=get_cookie("CopyviosScreenCache");if(cookie)try{data=JSON.parse(cookie);var width=data.width,height=data.height;if(width&&height)return{width:width,height:height}}catch(SyntaxError){}return!1}function get_cookie(name){for(var nameEQ=name+"=",ca=document.cookie.split(";"),i=0;i",{id:"notice-collapse-trigger",href:"#",text:"[show]",click:function(){return toggle_notice(),!1}})),details.hide())}$(document).ready(function(){$("#action-search").change(function(){$(".cv-search").prop("disabled",!1),$(".cv-compare").prop("disabled",!0),$(".cv-search-oo-ui").addClass("oo-ui-widget-enabled").removeClass("oo-ui-widget-disabled"),$(".cv-compare-oo-ui").addClass("oo-ui-widget-disabled").removeClass("oo-ui-widget-enabled")}),$("#action-compare").change(function(){$(".cv-search").prop("disabled",!0),$(".cv-compare").prop("disabled",!1),$(".cv-search-oo-ui").addClass("oo-ui-widget-disabled").removeClass("oo-ui-widget-enabled"),$(".cv-compare-oo-ui").addClass("oo-ui-widget-enabled").removeClass("oo-ui-widget-disabled")}),$("#action-search").is(":checked")&&$("#action-search").change(),$("#action-compare").is(":checked")&&$("#action-compare").change(),$("#cv-form").submit(function(){$("#action-search").is(":checked")&&$.each([["engine","use_engine"],["links","use_links"],["turnitin","turnitin"]],function(i,val){$("#cv-cb-"+val[0]).is(":checked")&&$("#cv-form input[type='hidden'][name='"+val[1]+"']").prop("disabled",!0)}),$("#cv-form button[type='submit']").prop("disabled",!0).css("cursor","progress").parent().addClass("oo-ui-widget-disabled").removeClass("oo-ui-widget-enabled")}),0<=$("#cv-additional").length&&($("#cv-additional").css("display","block"),$(".source-default-hidden").css("display","none"),$("#show-additional-sources").click(function(){return $(".source-default-hidden").css("display",""),$("#cv-additional").css("display","none"),!1})),install_notice()}); \ No newline at end of file +function updateScreenSize(){var cache=cacheCookie(),data={width:window.screen.availWidth,height:window.screen.availHeight};cache&&cache.width==data.width&&cache.height==data.height||setCookie("CopyviosScreenCache",JSON.stringify(data),1095)}function cacheCookie(){var cookie=getCookie("CopyviosScreenCache");if(cookie)try{data=JSON.parse(cookie);var width=data.width,height=data.height;if(width&&height)return{width:width,height:height}}catch(SyntaxError){}return!1}function getCookie(name){for(var nameEQ=name+"=",ca=document.cookie.split(";"),i=0;i",{id:"notice-collapse-trigger",href:"#",text:"[show]",click:function(){return toggleNotice(),!1}})),details.hide())}function addUrl(){var template=$("#compare-new-url"),widget=template[0].content.cloneNode(!0);return $(widget).find("input").prop("name","url"+($(".compare-url").length+1)),$(widget).find(".compare-remove-url").click(removeUrl),template.before(widget),!1}function removeUrl(e){return $(e.target).closest(".oo-ui-layout").remove(),$(".compare-url:not(.compare-url-first)").each(function(i,e){$(e).find("input").prop("name","url"+(i+2))}),!1}function pasteText(){return!1}function uploadFile(){return!1}function selectResult(n){var select=$(".cv-chain-source-"+n);0!==select.length&&($(".cv-chain-source").addClass("hidden"),select.removeClass("hidden"),$(".source-row-selected").removeClass("source-row-selected"),$($(".source-row")[n-1]).addClass("source-row-selected"),$(".source-tooltip > .tooltip-align-right").remove(),$(".source-tooltip-selected").removeClass("source-tooltip-selected"),$(".source-tooltip").filter(function(i,elem){return elem.dataset.id===n.toString()}).addClass("source-tooltip-selected"))}function setResultSelectionHandlers(){$(".source-compare").click(function(e){return selectResult($(e.target).data("id")),!1}),$("#cv-result-sources tr:not(:first-child)").click(function(e){if("TD"===e.target.tagName)return selectResult($(e.target).parent().data("id")),!1})}function toggleSource(id){var el=$(id.target),id=el.data("id");return el.hasClass("cv-hl")?$(".cv-hl-"+id).addClass("cv-hl-disabled-"+id).removeClass(["cv-hl-"+id,"cv-hl"]):$(".cv-hl-disabled-"+id).addClass(["cv-hl-"+id,"cv-hl"]).removeClass("cv-hl-disabled-"+id),!1}function unselectRegions(){if(0<$(".source-tooltip, .cv-selected").length)return $(".source-tooltip").remove(),$(".cv-selected").removeClass("cv-selected"),!1}function selectRegion(e){unselectRegions();var target=$(e.target).closest(".cv-hl");if(0!==target.length){var width=[].slice.apply(target[0].classList).filter(function(c){return c.startsWith("cv-hl-")});if(0!==width.length){var num=parseInt(width[0].substr(6)),tooltip=null,selected=!0;if(0<$("#cv-result-sources").length){if(0===(tooltip=$(".source-url-"+num)).length)return;selected=$(".source-row-selected").data("id")===num}var tooltipDirection=target.text().split(/\s+/).filter(function(s){return""!=s}).length,contents=$(""),width=null!==tooltip?(containerOffset=tooltip.data("domain")||tooltip.text(),contents.append($("",{class:"selector",href:"#",title:"Select source"}).text("Source "+num).click(function(){return selectResult(num),!1})).append($("",{class:"selector"}).text("Source "+num)).append(" ").append($("",{class:"domain"}).text("("+containerOffset+"):")).append(" "),Math.min(15+containerOffset.length/2,30)):8;contents.append($("",{class:"wordcount"}).text(tooltipDirection.toString()+" words")).click(function(){return $(".source-row-selected").data("id")===num?unselectRegions():selectResult(num),!1});var tooltip=$("#source-tooltips"),containerOffset=tooltip.offset(),tooltipDirection=target.closest(".cv-chain-cell").hasClass("cv-chain-source")?"right":"left",tooltip=$("
",{class:"source-tooltip tooltip-anchor-fixed"}).css({top:e.pageY-containerOffset.top+"px",left:e.pageX-containerOffset.left+"px"}).append($("",{class:"tooltip tooltip-align-"+tooltipDirection}).css({width:width+"em"}).append(contents)).appendTo(tooltip).attr("data-id",num.toString());return selected&&tooltip.addClass("source-tooltip-selected"),target.addClass("cv-selected"),!1}}}function hideAdditionalSources(){0<=$("#cv-additional").length&&($("#cv-additional").css("display","block"),$(".source-default-hidden").css("display","none"),$("#show-additional-sources").click(function(){return $(".source-default-hidden").css("display",""),$("#cv-additional").css("display","none"),!1}))}$(document).ready(function(){$(".oo-ui-optionWidget").click(selectTab),$("#compare-add-url").click(addUrl),$("#compare-paste").click(pasteText),$("#compare-upload").click(uploadFile),$(".compare-remove-url").click(removeUrl),setResultSelectionHandlers(),$(".source-num-included").click(toggleSource),$(".cv-chain-cell .cv-hl").click(selectRegion),$("body").click(unselectRegions),$(document).keyup(function(e){if("Escape"===e.key)return unselectRegions()}),$("#cv-form").submit(submitForm),hideAdditionalSources(),setNotice()}); \ No newline at end of file diff --git a/static/style.min.css b/static/style.min.css index 56e876f..ad4cc99 100644 --- a/static/style.min.css +++ b/static/style.min.css @@ -1 +1 @@ -body,html{height:100%;margin:0}body{display:flex;flex-direction:column;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;font-size:14px;color:#000;background-color:#eaecf0;background-attachment:fixed;background-position:50%;background-size:cover}#container{flex:auto;line-height:1.25;margin:0 auto}#container.splash{display:flex;flex-direction:column;justify-content:center}@media only screen and (min-width:1200px){#container.splash{min-width:1200px;max-width:1600px}}@media only screen and (max-width:1200px){#container.splash{width:100%}}#container.splash>.padding{height:25%}#content{background-color:#fff;border:1px solid #c8ccd1;filter:drop-shadow(0 0 10px rgba(0,0,0,.25));margin:1.5em 3em;padding:1em}@media only screen and (max-width:1000px){#content{margin:1em}}@media only screen and (max-width:400px){#content{margin:0}}header{background-color:#eaecf0;padding:.2em 1em}header>*{vertical-align:middle;display:inline-block}header h1{font-size:2.25em;font-weight:400;margin:0 1em 0 0}@media only screen and (max-width:500px){header h1{font-size:1.5em}}#settings-link:before{content:" ";font-size:.85em;color:#000;opacity:.6;padding-left:1.67em;background-image:linear-gradient(transparent,transparent),url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='20' height='20'%3E%3Cg transform='translate(10 10)'%3E%3Cpath id='a' d='M1.5-10h-3l-1 6.5h5m0 7h-5l1 6.5h3'/%3E%3Cuse transform='rotate(45)' xlink:href='%23a'/%3E%3Cuse transform='rotate(90)' xlink:href='%23a'/%3E%3Cuse transform='rotate(135)' xlink:href='%23a'/%3E%3C/g%3E%3Cpath d='M10 2.5a7.5 7.5 0 000 15 7.5 7.5 0 000-15v4a3.5 3.5 0 010 7 3.5 3.5 0 010-7'/%3E%3C/svg%3E");background-repeat:no-repeat;background-size:contain}footer{padding:1em;font-size:.9em;text-align:center;line-height:1.5;border-top:1px solid #c8ccd1;background:#fff}footer ul{margin:0}footer li{display:inline}footer li:not(:last-child):after{content:" \00b7"}footer a{white-space:nowrap}ol,ul{line-height:1.5}h2{margin-bottom:.2em}#info-box,#notice-box{padding:0 1em;margin:1em 0}#notice-box ul{padding-left:1.5em;margin:0}#cv-result{padding:.5em;margin:1em 0}#attribution-warning{padding:1em;margin:1em 0}#sources-container,#turnitin-container{padding:.5em 1em 1em;margin:1em 0}#sources-container{background-color:#eee;border:1px solid #bbb}#sources-title,#turnitin-title{margin-bottom:-.5em;text-align:center;font-weight:700}#cv-additional{display:none}#generation-time{text-align:right;font-style:italic}@media only screen and (min-width:600px){#generation-time{margin-top:-1em}}#heading{width:100%}#cv-result-sources{width:100%;border-spacing:0 .4em;table-layout:fixed}#cv-result-sources col:first-child{width:80%}#cv-result-sources col:nth-child(2),#cv-result-sources col:nth-child(3){width:10%}#cv-result-sources th{text-align:left}#cv-result-sources tr:nth-child(2n){background-color:#e0e0e0}#cv-result-sources td:first-child{overflow:hidden;word-wrap:break-word}#cv-result-head-table{width:100%;text-align:center;table-layout:fixed;border-spacing:0}#cv-result-head-table col:nth-child(odd){width:42.5%}#cv-result-head-table col:nth-child(2){width:15%}#cv-result-head-table td:nth-child(odd){font-size:1.25em;font-weight:700;overflow:hidden;word-wrap:break-word}#cv-result-head-table td:nth-child(2) div:first-child{font-weight:700;white-space:nowrap}#cv-result-head-table td:nth-child(2) div:nth-child(2){font-size:2.5em;font-weight:700;line-height:1}#cv-result-head-table td:nth-child(2) div:nth-child(3){font-size:.8em}#cv-chain-table,#turnitin-table{width:100%;border-spacing:0;table-layout:fixed}#turnitin-table{word-wrap:break-word}#source-row-selected{background-color:#cfcfcf!important}#head-settings{text-align:right}#cv-result-header{margin:0}#redirected-from{font-size:.75em;font-weight:400}#redirected-from,#result-head-no-sources{font-style:italic}#source-selected{font-weight:700}#cv-cached{position:relative}#cv-cached span{display:none;position:absolute;top:1.5em;left:-5em;width:30em;padding:1em;z-index:1;background:#f3f3f3;border:1px solid #aaa;color:#000;font-style:normal;text-align:left}.green-box{background-color:#efe;border:1px solid #7f7}.yellow-box{background-color:#ffd;border:1px solid #ee5}.red-box{background-color:#fee;border:1px solid #f77}.gray-box{background-color:#eee;border:1px solid #aaa}.indentable{white-space:pre-wrap}.cv-source-footer{padding-bottom:.5em;font-style:italic}.cv-source-footer a{font-style:normal}.cv-chain-detail{padding:0 1em;background-color:#fff;border:1px solid #bbb}.cv-chain-cell{vertical-align:top;word-wrap:break-word}.cv-chain-cell:first-child{padding-right:.5em}.cv-chain-cell:last-child{padding-left:.5em}.turnitin-table-cell{padding:.5em 0 .3em}.turnitin-table-cell ul{margin:.2em 0 0;line-height:1.4}.cv-hl{background:#faa}.cv-hl-in{background:#fcc;background:linear-gradient(270deg,#faa,#fff)}.cv-hl-out{background:#fcc;background:linear-gradient(90deg,#faa,#fff)}.mono{font-family:monospace}.light{color:#ccc}.medium{color:#aaa}.source-similarity{font-weight:700}.source-suspect{color:#900}.source-possible{color:#990}.source-novio{color:#090}.source-excluded,.source-skipped{font-style:italic}a:link,a:visited{color:#002bb8;text-decoration:none}a:hover{color:#002bb8}a:active,a:hover{text-decoration:underline}a:active{color:#404}header a:hover,header a:link,header a:visited{color:#54595d}header a:active{color:#333}#cv-cached:active{color:#040}#cv-cached:active,#cv-cached:hover{text-decoration:none}#cv-cached:hover span{display:block}.source-url:link,.source-url:visited{color:#357}.source-url:hover{color:#035}.source-url:active{color:#404}.oo-ui-horizontalLayout>.oo-ui-dropdownInputWidget,.oo-ui-horizontalLayout>.oo-ui-textInputWidget{width:auto}.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline{hyphens:manual}.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-left>.oo-ui-fieldLayout-body>.oo-ui-fieldLayout-header,.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-right>.oo-ui-fieldLayout-body>.oo-ui-fieldLayout-header{width:10%}.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-left>.oo-ui-fieldLayout-body>.oo-ui-fieldLayout-field,.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-right>.oo-ui-fieldLayout-body>.oo-ui-fieldLayout-field{width:90%}.compare-url.oo-ui-textInputWidget,.page-title.oo-ui-textInputWidget{width:60%}.page-oldid.oo-ui-textInputWidget{width:10em}label.page,label.site{min-width:4em}label.action{min-width:10em}@media only screen and (max-width:720px){.oo-ui-horizontalLayout>.oo-ui-widget{width:100%}} \ No newline at end of file +body,html{height:100%;margin:0}body{display:flex;flex-direction:column;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;font-size:14px;color:#000;background-color:#eaecf0;background-attachment:fixed;background-position:50%;background-size:cover}#container{flex:auto;line-height:1.25;margin:0 auto}#container.splash{display:flex;flex-direction:column;justify-content:center}@media only screen and (min-width:1200px){#container.splash{min-width:1200px;max-width:1600px}}@media only screen and (max-width:1200px){#container.splash{width:100%}}#container.splash>.padding{height:25%}#content{background-color:#fff;border:1px solid #a2a9b1;filter:drop-shadow(0 0 1em rgba(0,0,0,.25));margin:1.5em 3em;padding:1em}@media only screen and (max-width:1000px){#content{margin:1em}}@media only screen and (max-width:400px){#content{margin:0}}header{background-color:#eaecf0;padding:.2em 1em}header>*{vertical-align:middle;display:inline-block}header h1{font-size:2.25em;font-weight:400;margin:0 1em 0 0}@media only screen and (max-width:500px){header h1{font-size:1.5em}}#settings-link:before{content:" ";font-size:.85em;color:#000;opacity:.6;padding-left:1.67em;background-image:linear-gradient(transparent,transparent),url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='20' height='20'%3E%3Cg transform='translate(10 10)'%3E%3Cpath id='a' d='M1.5-10h-3l-1 6.5h5m0 7h-5l1 6.5h3'/%3E%3Cuse transform='rotate(45)' xlink:href='%23a'/%3E%3Cuse transform='rotate(90)' xlink:href='%23a'/%3E%3Cuse transform='rotate(135)' xlink:href='%23a'/%3E%3C/g%3E%3Cpath d='M10 2.5a7.5 7.5 0 000 15 7.5 7.5 0 000-15v4a3.5 3.5 0 010 7 3.5 3.5 0 010-7'/%3E%3C/svg%3E");background-repeat:no-repeat;background-size:contain}footer{padding:1em;font-size:.9em;text-align:center;line-height:1.5;border-top:1px solid #a2a9b1;background:#fff}footer a{white-space:nowrap}ol,ul{line-height:1.5}h2{margin-bottom:.2em}#info-box,#notice-box{padding:0 1em;margin:1em 0}#notice-box ul{padding-left:1.5em;margin:0}#cv-result{padding:.5em;margin:1em 0}#attribution-warning{padding:1em;margin:1em 0}#sources-container,#turnitin-container{padding:.5em 1em 1em;margin:1em 0}#sources-container{border:1px solid #a2a9b1}#sources-title,#turnitin-title{margin-bottom:-.5em;text-align:center;font-weight:700}#cv-additional{display:none}#generation-time{text-align:right;font-style:italic}@media only screen and (min-width:600px){#generation-time{margin-top:-1em}}#cv-result-sources{width:100%;border-spacing:0 .4em}#cv-result-sources tr:first-child th:first-child{width:4em}#cv-result-sources tr:first-child th:nth-child(3){width:7em}#cv-result-sources tr:first-child th:nth-child(4){width:10em}@media only screen and (max-width:1000px){#cv-result-sources tr:first-child th:first-child{width:3em}#cv-result-sources tr:first-child th:nth-child(3){width:5em}#cv-result-sources tr:first-child th:nth-child(4){width:8em}}#cv-result-sources th{text-align:left}#cv-result-sources tr:nth-child(2n){background-color:#eaecf0}#cv-result-sources td:first-child,#cv-result-sources th:first-child{text-align:center}#cv-result-sources td:nth-child(2){overflow:hidden;word-wrap:break-word}#cv-result-head-table{width:100%;text-align:center;table-layout:fixed;border-spacing:0}#cv-result-head-table col:nth-child(odd){width:42.5%}#cv-result-head-table col:nth-child(2){width:15%}#cv-result-head-table td:nth-child(odd){font-size:1.25em;font-weight:700;overflow:hidden;word-wrap:break-word}#cv-result-head-table td:nth-child(2) div:first-child{font-weight:700;white-space:nowrap}#cv-result-head-table td:nth-child(2) div:nth-child(2){font-size:2.5em;font-weight:700;line-height:1}#cv-result-head-table td:nth-child(2) div:nth-child(3){font-size:.8em}#turnitin-table{table-layout:fixed;width:100%;word-wrap:break-word;border-spacing:0}#cv-result-sources tr.source-row-selected{background-color:#d0d2d5}.source-row-selected .source-url{font-weight:700}.source-row-selected .source-compare,.source-row:not(.source-row-selected) .source-compare-selected{display:none}#cv-result-header{margin:0}#redirected-from{font-size:.75em;font-weight:400}#redirected-from,#result-head-no-sources{font-style:italic}.hlist{margin:0;padding:0}.hlist li{display:inline}.hlist li:not(:last-child):after{content:" \00b7"}.green-box{background-color:#e0fdf4;border:1px solid #54a66d}.yellow-box{background-color:#fef6e7;border:1px solid #fc3}.red-box{background-color:#fee7e6;border:1px solid #d33}.gray-box{background-color:#eaecf0;border:1px solid #a2a9b1}.indentable{white-space:pre-wrap}.cv-source-footer{padding-bottom:.5em;font-style:italic}.cv-source-footer a{font-style:normal}.cv-chain-table{width:100%;border-spacing:0;table-layout:fixed}.cv-chain-table td{vertical-align:top;word-wrap:break-word}.cv-chain-table td:first-child{padding-right:.5em}.cv-chain-table td:not(:first-child){padding-left:.5em}.cv-chain-cell>div{padding:0 1em;border:1px solid #a2a9b1}.turnitin-table-cell{padding:.5em 0 .3em}.turnitin-table-cell ul{margin:.2em 0 0;line-height:1.4}.highlight-demo{display:inline-block;border:1px solid #777;padding:.25em .5em}.mono{font-family:monospace}.light{color:#ccc}.medium{color:#aaa}.source-similarity{font-weight:700}.source-suspect{color:#900}.source-possible{color:#990}.source-novio{color:#090}.source-excluded,.source-skipped{font-style:italic}a:link,a:visited{color:#002bb8;text-decoration:none}a:hover{color:#002bb8}a:active,a:hover{text-decoration:underline}a:active{color:#404}header a:hover,header a:link,header a:visited{color:#54595d}header a:active{color:#333}.source-num{display:inline-block;min-width:1.5em;text-align:center}.source-num-included{border:1px solid #777}a.source-num-included{color:#000}.source-num-included:active,.source-num-included:hover{text-decoration:none}.hidden{display:none}#source-tooltips{position:relative}.source-tooltip-selected a.selector,.source-tooltip:not(.source-tooltip-selected) strong.selector{display:none}.source-tooltip .domain,.source-tooltip .selector,.source-tooltip .wordcount{display:inline-block}.cv-chain-cell .cv-hl:hover,.cv-selected{outline:1px dashed #333;cursor:pointer}.oo-ui-horizontalLayout>.oo-ui-dropdownInputWidget,.oo-ui-horizontalLayout>.oo-ui-textInputWidget{width:auto}.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline{hyphens:manual}.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-left>.oo-ui-fieldLayout-body>.oo-ui-fieldLayout-header,.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-right>.oo-ui-fieldLayout-body>.oo-ui-fieldLayout-header{width:10%}.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-left>.oo-ui-fieldLayout-body>.oo-ui-fieldLayout-field,.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-right>.oo-ui-fieldLayout-body>.oo-ui-fieldLayout-field{width:90%}.compare-url.oo-ui-textInputWidget,.page-title.oo-ui-textInputWidget{width:60%}.page-oldid.oo-ui-textInputWidget{width:10em}label.page,label.site{min-width:4em}@media only screen and (max-width:720px){.oo-ui-horizontalLayout>.oo-ui-widget{width:100%}}.cv-hl{background:#ddd}.cv-hl .cv-hl-in{background:linear-gradient(270deg,#ddd,#fff)}.cv-hl .cv-hl-out{background:linear-gradient(90deg,#ddd,#fff)}.cv-hl-1{background:#fed9a6}.cv-hl-1 .cv-hl-in{background:linear-gradient(270deg,#fed9a6,#fff)}.cv-hl-1 .cv-hl-out{background:linear-gradient(90deg,#fed9a6,#fff)}.cv-hl-2{background:#b3cde3}.cv-hl-2 .cv-hl-in{background:linear-gradient(270deg,#b3cde3,#fff)}.cv-hl-2 .cv-hl-out{background:linear-gradient(90deg,#b3cde3,#fff)}.cv-hl-3{background:#ccebc5}.cv-hl-3 .cv-hl-in{background:linear-gradient(270deg,#ccebc5,#fff)}.cv-hl-3 .cv-hl-out{background:linear-gradient(90deg,#ccebc5,#fff)}.cv-hl-4{background:#fbb4ae}.cv-hl-4 .cv-hl-in{background:linear-gradient(270deg,#fbb4ae,#fff)}.cv-hl-4 .cv-hl-out{background:linear-gradient(90deg,#fbb4ae,#fff)}.cv-hl-5{background:#decbe4}.cv-hl-5 .cv-hl-in{background:linear-gradient(270deg,#decbe4,#fff)}.cv-hl-5 .cv-hl-out{background:linear-gradient(90deg,#decbe4,#fff)}.cv-hl-6{background:#ffc}.cv-hl-6 .cv-hl-in{background:linear-gradient(270deg,#ffc,#fff)}.cv-hl-6 .cv-hl-out{background:linear-gradient(90deg,#ffc,#fff)}.cv-hl-7{background:#e5d8bd}.cv-hl-7 .cv-hl-in{background:linear-gradient(270deg,#e5d8bd,#fff)}.cv-hl-7 .cv-hl-out{background:linear-gradient(90deg,#e5d8bd,#fff)}.cv-hl-8{background:#fddaec}.cv-hl-8 .cv-hl-in{background:linear-gradient(270deg,#fddaec,#fff)}.cv-hl-8 .cv-hl-out{background:linear-gradient(90deg,#fddaec,#fff)}.tooltip{display:block;position:absolute;bottom:100%;width:30em;padding-bottom:.5em;font-style:normal;text-align:left;z-index:1}.tooltip>span{display:block;background-color:#fff;border:1px solid #c8ccd1;filter:drop-shadow(0 0 .5em rgba(0,0,0,.25));padding:.5em 1em}.tooltip>span:after{content:" ";position:absolute;top:100%;border:.5em solid transparent;border-top-color:#fff}.tooltip-anchor-inline,abbr{border-width:0;text-decoration:underline dotted}.tooltip-anchor-inline{position:relative}.tooltip-anchor-inline>.tooltip{display:none}.tooltip-anchor-inline:hover>.tooltip{display:block}.tooltip-anchor-fixed{position:absolute}.tooltip-align-center{left:50%;margin-left:-15em}.tooltip-align-center>span:after{left:50%;margin-left:-.5em}.tooltip-align-left{left:-2.5em}.tooltip-align-left>span:after{left:2em}.tooltip-align-right{right:-2.5em}.tooltip-align-right>span:after{right:2em} \ No newline at end of file diff --git a/templates/api.mako b/templates/api.mako index a507137..2b7e9fa 100644 --- a/templates/api.mako +++ b/templates/api.mako @@ -33,7 +33,7 @@ - API | Earwig's Copyvio Detector + API - Earwig's Copyvio Detector diff --git a/templates/error.mako b/templates/error.mako index f26aea1..a650437 100644 --- a/templates/error.mako +++ b/templates/error.mako @@ -1,7 +1,7 @@ -<%include file="/support/header.mako" args="title='Error! | Earwig\'s Copyvio Detector'"/> +<%include file="/includes/header.mako" args="title='Error! - Earwig\'s Copyvio Detector'"/>

Error!

An error occurred. If it hasn't been reported (try to check), please file an issue or email me. Include the following information:

${traceback | trim,h}
-<%include file="/support/footer.mako"/> +<%include file="/includes/footer.mako"/> diff --git a/templates/support/footer.mako b/templates/includes/footer.mako similarity index 95% rename from templates/support/footer.mako rename to templates/includes/footer.mako index 153f07c..4f841c6 100644 --- a/templates/support/footer.mako +++ b/templates/includes/footer.mako @@ -1,13 +1,13 @@ <%! from datetime import datetime from flask import g, request -%>\ +%>