add xanadoc viewer
This commit is contained in:
		
							parent
							
								
									c4bbc45372
								
							
						
					
					
						commit
						09893c4eff
					
				
							
								
								
									
										138
									
								
								sourcing/edl.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								sourcing/edl.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,138 @@
 | 
			
		|||
from .url import get_url, get_text
 | 
			
		||||
from .parse import get_span, parse_span, parse_link, parse_sourcedoc_facet, xanadoc_span_html, span_html, get_urls
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from html import escape
 | 
			
		||||
 | 
			
		||||
import re
 | 
			
		||||
 | 
			
		||||
re_comment = re.compile(r'#.*')
 | 
			
		||||
re_xanalink = re.compile('xanalink: +([^ ]+) *$')
 | 
			
		||||
max_sourcedoc_size = 600000
 | 
			
		||||
 | 
			
		||||
def fulfil_edl(edl):
 | 
			
		||||
    text = {}
 | 
			
		||||
    for url, start, length in parse_edl(edl):
 | 
			
		||||
        if url not in text:
 | 
			
		||||
            text[url] = get_text(url)
 | 
			
		||||
 | 
			
		||||
        yield get_span(text, url, start, length)
 | 
			
		||||
 | 
			
		||||
def parse_edl(edl_text):
 | 
			
		||||
    edl = {
 | 
			
		||||
        'spans': [],
 | 
			
		||||
        'links': [],
 | 
			
		||||
    }
 | 
			
		||||
    for line in edl_text.splitlines():
 | 
			
		||||
        line = re_comment.sub('', line).strip()
 | 
			
		||||
        if not line:
 | 
			
		||||
            continue
 | 
			
		||||
        span_pointer = parse_span(line)
 | 
			
		||||
        if span_pointer:
 | 
			
		||||
            edl['spans'].append(span_pointer)
 | 
			
		||||
            continue
 | 
			
		||||
        m = re_xanalink.match(line)
 | 
			
		||||
        if m:
 | 
			
		||||
            link_url = m.group(1)
 | 
			
		||||
            edl['links'].append({
 | 
			
		||||
                'url': link_url,
 | 
			
		||||
                'text': get_url(link_url),
 | 
			
		||||
            })
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
    return edl
 | 
			
		||||
 | 
			
		||||
def fulfil_edl_with_sources(edl_text):
 | 
			
		||||
    edl = parse_edl(edl_text)
 | 
			
		||||
    spans = edl['spans']
 | 
			
		||||
 | 
			
		||||
    hide_transclusions = set()
 | 
			
		||||
 | 
			
		||||
    two_facet_links = []
 | 
			
		||||
 | 
			
		||||
    link_num = 0
 | 
			
		||||
    for link in edl['links']:
 | 
			
		||||
        link_detail = parse_link(link['text'])
 | 
			
		||||
        if link_detail['type'] == 'HideTransclusions':
 | 
			
		||||
            hide_transclusions.add(parse_sourcedoc_facet(link_detail['facets'][0]))
 | 
			
		||||
        elif len(link_detail['facets']) == 2:
 | 
			
		||||
            two_facet_links.append((link_num, [parse_span(span[0]) for span in link_detail['facets']]))
 | 
			
		||||
            link_num += 1
 | 
			
		||||
 | 
			
		||||
    source = [get_text(url) for url in get_urls(spans)]
 | 
			
		||||
 | 
			
		||||
    source_text = {s['url']: s['text'] for s in source}
 | 
			
		||||
 | 
			
		||||
    source_doc_links = defaultdict(list)
 | 
			
		||||
 | 
			
		||||
    for link_num, facets in two_facet_links:
 | 
			
		||||
        for span in facets:
 | 
			
		||||
            url, start, length = span
 | 
			
		||||
            source_doc_links[url].append((start, length, link_num, 'link'))
 | 
			
		||||
            if url in source_text:
 | 
			
		||||
                continue
 | 
			
		||||
 | 
			
		||||
            s = get_text(url)
 | 
			
		||||
            source.append(s)
 | 
			
		||||
            source_text[s['url']] = s['text']
 | 
			
		||||
 | 
			
		||||
    for s in source_doc_links.values():
 | 
			
		||||
        s.sort()
 | 
			
		||||
 | 
			
		||||
    spans = list(enumerate(spans))
 | 
			
		||||
 | 
			
		||||
    doc_spans = []
 | 
			
		||||
    for num, (url, start, length) in spans:
 | 
			
		||||
        highlight = url not in hide_transclusions
 | 
			
		||||
        span_text = source_text[url]  # [start:start + length]
 | 
			
		||||
        new_text = ''
 | 
			
		||||
        pos = start
 | 
			
		||||
        for link_start, link_len, link_num, span_type in source_doc_links[url]:
 | 
			
		||||
            link_end = link_start + link_len
 | 
			
		||||
            if link_start >= start + length:
 | 
			
		||||
                break
 | 
			
		||||
            if link_end < start:
 | 
			
		||||
                continue
 | 
			
		||||
            open_tag = '<span class="xanadoclink link" id="xanalink{}">'.format(link_num)
 | 
			
		||||
            link_span = (open_tag +
 | 
			
		||||
                         escape(span_text[link_start:link_end]) +
 | 
			
		||||
                         '</span>')
 | 
			
		||||
            new_text += escape(span_text[pos:link_start]) + link_span
 | 
			
		||||
            pos = link_end
 | 
			
		||||
        new_text += escape(span_text[pos:start + length])
 | 
			
		||||
        cur = xanadoc_span_html(num, new_text, url, start, length, highlight=highlight)
 | 
			
		||||
        doc_spans.append(cur)
 | 
			
		||||
 | 
			
		||||
    doc = ''.join(doc_spans)
 | 
			
		||||
 | 
			
		||||
    for s in source:
 | 
			
		||||
        text = s.pop('text')
 | 
			
		||||
        if s['length'] > max_sourcedoc_size:
 | 
			
		||||
            # print('{} > {}'.format(s['length'], max_sourcedoc_size))
 | 
			
		||||
            continue
 | 
			
		||||
        if s['url'] in hide_transclusions:
 | 
			
		||||
            continue
 | 
			
		||||
        source_spans = [(start, length, num, 'transclusion') for num, (url, start, length) in spans if url == s['url']]
 | 
			
		||||
        source_spans += source_doc_links[s['url']]
 | 
			
		||||
        source_spans.sort()
 | 
			
		||||
 | 
			
		||||
        new_text = ''
 | 
			
		||||
        pos = 0
 | 
			
		||||
 | 
			
		||||
        for start, length, num, span_type in source_spans:
 | 
			
		||||
            end = start + length
 | 
			
		||||
            new_text += (escape(text[pos:start]) +
 | 
			
		||||
                         span_html(span_type, num) +
 | 
			
		||||
                         escape(text[start:end]) +
 | 
			
		||||
                         '</span>')
 | 
			
		||||
            pos = end
 | 
			
		||||
        new_text += escape(text[pos:])
 | 
			
		||||
        new_text = new_text.replace('\n', '<br/>\n')
 | 
			
		||||
 | 
			
		||||
        s['text'] = new_text
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        'source': source,
 | 
			
		||||
        'doc': doc.replace('\n', '<br/>\n'),
 | 
			
		||||
        'span_count': len(spans),
 | 
			
		||||
        'link_count': len(two_facet_links),
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1,87 +1,22 @@
 | 
			
		|||
import re
 | 
			
		||||
import requests
 | 
			
		||||
import os.path
 | 
			
		||||
import random
 | 
			
		||||
from html import escape
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
 | 
			
		||||
re_comment = re.compile(r'#.*')
 | 
			
		||||
re_span_pointer = re.compile(r'span: (.*),start=(\d+),length=(\d+)')
 | 
			
		||||
re_xanalink = re.compile('xanalink: +([^ ]+) *$')
 | 
			
		||||
re_facet = re.compile('^facet\d* *=\s*(.*)\s*$')
 | 
			
		||||
 | 
			
		||||
re_colon_slash = re.compile('[/:]+')
 | 
			
		||||
re_comment = re.compile(r'#.*')
 | 
			
		||||
 | 
			
		||||
project_dir = os.path.dirname(os.path.dirname(__file__))
 | 
			
		||||
cache_location = os.path.join(project_dir, 'cache')
 | 
			
		||||
 | 
			
		||||
max_sourcedoc_size = 600000
 | 
			
		||||
 | 
			
		||||
xnb_per_char = 150000
 | 
			
		||||
 | 
			
		||||
censor_urls = {'http://hyperland.com/xuCambDemo/J.Ineffable.txt',
 | 
			
		||||
               'http://royalty.pub/Ineffable/17/32/Trovato'}
 | 
			
		||||
 | 
			
		||||
def censor_text(text):
 | 
			
		||||
    return ''.join(chr(random.randint(9728, 9983)) if c.isalnum() else c
 | 
			
		||||
                   for c in text)
 | 
			
		||||
 | 
			
		||||
def get_url(url):
 | 
			
		||||
    filename = os.path.join(cache_location, url_filename(url))
 | 
			
		||||
 | 
			
		||||
    if os.path.exists(filename):
 | 
			
		||||
        content = open(filename, 'rb').read()
 | 
			
		||||
    else:
 | 
			
		||||
        content = requests.get(url).content
 | 
			
		||||
        open(filename, 'wb').write(content)
 | 
			
		||||
 | 
			
		||||
    return content.decode(errors='replace')
 | 
			
		||||
 | 
			
		||||
def get_text(url):
 | 
			
		||||
    # assume UTF-8
 | 
			
		||||
 | 
			
		||||
    text = get_url(url)
 | 
			
		||||
    if url in censor_urls:
 | 
			
		||||
        text = censor_text(text)
 | 
			
		||||
 | 
			
		||||
    heading = url.rsplit('/', 1)[-1]
 | 
			
		||||
    return {
 | 
			
		||||
        'url': url,
 | 
			
		||||
        'text': text,
 | 
			
		||||
        'heading': heading,
 | 
			
		||||
        'length': len(text),
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
def parse_span(line):
 | 
			
		||||
    m = re_span_pointer.match(line)
 | 
			
		||||
    if not m:
 | 
			
		||||
        return None
 | 
			
		||||
    return (m.group(1), int(m.group(2)), int(m.group(3)))
 | 
			
		||||
 | 
			
		||||
def parse_edl(edl_text):
 | 
			
		||||
    edl = {
 | 
			
		||||
        'spans': [],
 | 
			
		||||
        'links': [],
 | 
			
		||||
    }
 | 
			
		||||
    for line in edl_text.splitlines():
 | 
			
		||||
        line = re_comment.sub('', line).strip()
 | 
			
		||||
        if not line:
 | 
			
		||||
            continue
 | 
			
		||||
        span_pointer = parse_span(line)
 | 
			
		||||
        if span_pointer:
 | 
			
		||||
            edl['spans'].append(span_pointer)
 | 
			
		||||
            continue
 | 
			
		||||
        m = re_xanalink.match(line)
 | 
			
		||||
        if m:
 | 
			
		||||
            link_url = m.group(1)
 | 
			
		||||
            edl['links'].append({
 | 
			
		||||
                'url': link_url,
 | 
			
		||||
                'text': get_url(link_url),
 | 
			
		||||
            })
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
    return edl
 | 
			
		||||
 | 
			
		||||
def get_span(text, url, start, length):
 | 
			
		||||
    return {
 | 
			
		||||
        'url': url,
 | 
			
		||||
| 
						 | 
				
			
			@ -90,20 +25,9 @@ def get_span(text, url, start, length):
 | 
			
		|||
        'text': text[url][start:start + length]
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
def fulfil_edl(edl):
 | 
			
		||||
    text = {}
 | 
			
		||||
    for url, start, length in parse_edl(edl):
 | 
			
		||||
        if url not in text:
 | 
			
		||||
            text[url] = get_text(url)
 | 
			
		||||
 | 
			
		||||
        yield get_span(text, url, start, length)
 | 
			
		||||
 | 
			
		||||
def get_urls(spans):
 | 
			
		||||
    return {i[0] for i in spans}
 | 
			
		||||
 | 
			
		||||
def url_filename(url):
 | 
			
		||||
    return re_colon_slash.sub('_', url)
 | 
			
		||||
 | 
			
		||||
def find_min_max(spans, source):
 | 
			
		||||
    text_min, text_max = {}, {}
 | 
			
		||||
    for url, start, length in spans:
 | 
			
		||||
| 
						 | 
				
			
			@ -175,99 +99,4 @@ def parse_link(link_text):
 | 
			
		|||
            legs.append(line.strip())
 | 
			
		||||
    return {'type': link_type, 'facets': facets}
 | 
			
		||||
 | 
			
		||||
def fulfil_edl_with_sources(edl_text):
 | 
			
		||||
    edl = parse_edl(edl_text)
 | 
			
		||||
    spans = edl['spans']
 | 
			
		||||
 | 
			
		||||
    hide_transclusions = set()
 | 
			
		||||
 | 
			
		||||
    two_facet_links = []
 | 
			
		||||
 | 
			
		||||
    link_num = 0
 | 
			
		||||
    for link in edl['links']:
 | 
			
		||||
        link_detail = parse_link(link['text'])
 | 
			
		||||
        if link_detail['type'] == 'HideTransclusions':
 | 
			
		||||
            hide_transclusions.add(parse_sourcedoc_facet(link_detail['facets'][0]))
 | 
			
		||||
        elif len(link_detail['facets']) == 2:
 | 
			
		||||
            two_facet_links.append((link_num, [parse_span(span[0]) for span in link_detail['facets']]))
 | 
			
		||||
            link_num += 1
 | 
			
		||||
 | 
			
		||||
    source = [get_text(url) for url in get_urls(spans)]
 | 
			
		||||
 | 
			
		||||
    source_text = {s['url']: s['text'] for s in source}
 | 
			
		||||
 | 
			
		||||
    source_doc_links = defaultdict(list)
 | 
			
		||||
 | 
			
		||||
    for link_num, facets in two_facet_links:
 | 
			
		||||
        for span in facets:
 | 
			
		||||
            url, start, length = span
 | 
			
		||||
            source_doc_links[url].append((start, length, link_num, 'link'))
 | 
			
		||||
            if url in source_text:
 | 
			
		||||
                continue
 | 
			
		||||
 | 
			
		||||
            s = get_text(url)
 | 
			
		||||
            source.append(s)
 | 
			
		||||
            source_text[s['url']] = s['text']
 | 
			
		||||
 | 
			
		||||
    for s in source_doc_links.values():
 | 
			
		||||
        s.sort()
 | 
			
		||||
 | 
			
		||||
    spans = list(enumerate(spans))
 | 
			
		||||
 | 
			
		||||
    doc_spans = []
 | 
			
		||||
    for num, (url, start, length) in spans:
 | 
			
		||||
        highlight = url not in hide_transclusions
 | 
			
		||||
        span_text = source_text[url]  # [start:start + length]
 | 
			
		||||
        censor = url in censor_urls
 | 
			
		||||
        new_text = ''
 | 
			
		||||
        pos = start
 | 
			
		||||
        for link_start, link_len, link_num, span_type in source_doc_links[url]:
 | 
			
		||||
            link_end = link_start + link_len
 | 
			
		||||
            if link_start >= start + length:
 | 
			
		||||
                break
 | 
			
		||||
            if link_end < start:
 | 
			
		||||
                continue
 | 
			
		||||
            open_tag = '<span class="xanadoclink link" id="xanalink{}">'.format(link_num)
 | 
			
		||||
            link_span = (open_tag +
 | 
			
		||||
                         escape(span_text[link_start:link_end]) +
 | 
			
		||||
                         '</span>')
 | 
			
		||||
            new_text += escape(span_text[pos:link_start]) + link_span
 | 
			
		||||
            pos = link_end
 | 
			
		||||
        new_text += escape(span_text[pos:start + length])
 | 
			
		||||
        cur = xanadoc_span_html(num, new_text, url, start, length, highlight=highlight, censor=censor)
 | 
			
		||||
        doc_spans.append(cur)
 | 
			
		||||
 | 
			
		||||
    doc = ''.join(doc_spans)
 | 
			
		||||
 | 
			
		||||
    for s in source:
 | 
			
		||||
        text = s.pop('text')
 | 
			
		||||
        if s['length'] > max_sourcedoc_size:
 | 
			
		||||
            # print('{} > {}'.format(s['length'], max_sourcedoc_size))
 | 
			
		||||
            continue
 | 
			
		||||
        if s['url'] in hide_transclusions:
 | 
			
		||||
            continue
 | 
			
		||||
        source_spans = [(start, length, num, 'transclusion') for num, (url, start, length) in spans if url == s['url']]
 | 
			
		||||
        source_spans += source_doc_links[s['url']]
 | 
			
		||||
        source_spans.sort()
 | 
			
		||||
 | 
			
		||||
        new_text = ''
 | 
			
		||||
        pos = 0
 | 
			
		||||
 | 
			
		||||
        for start, length, num, span_type in source_spans:
 | 
			
		||||
            end = start + length
 | 
			
		||||
            new_text += (escape(text[pos:start]) +
 | 
			
		||||
                         span_html(span_type, num) +
 | 
			
		||||
                         escape(text[start:end]) +
 | 
			
		||||
                         '</span>')
 | 
			
		||||
            pos = end
 | 
			
		||||
        new_text += escape(text[pos:])
 | 
			
		||||
        new_text = new_text.replace('\n', '<br/>\n')
 | 
			
		||||
 | 
			
		||||
        s['text'] = new_text
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        'source': source,
 | 
			
		||||
        'doc': doc.replace('\n', '<br/>\n'),
 | 
			
		||||
        'span_count': len(spans),
 | 
			
		||||
        'link_count': len(two_facet_links),
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										106
									
								
								sourcing/static/css/xanadoc.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								sourcing/static/css/xanadoc.css
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,106 @@
 | 
			
		|||
.document {
 | 
			
		||||
    padding: 5px;
 | 
			
		||||
	margin: 10px;
 | 
			
		||||
    background-color: #eee;
 | 
			
		||||
    width: 400px;
 | 
			
		||||
    height: 400px;
 | 
			
		||||
    border: 1px black solid;
 | 
			
		||||
    position: fixed;
 | 
			
		||||
/*     transform: scale(2); */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.sourcedoc {
 | 
			
		||||
    background-color: #ffe;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.xanadoc {
 | 
			
		||||
    background-color: #eef;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.scale {
 | 
			
		||||
    transform: scale(2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#edlform {
 | 
			
		||||
    padding: 5px;
 | 
			
		||||
	margin: 10px;
 | 
			
		||||
    width: 400px;
 | 
			
		||||
    background-color: #eee;
 | 
			
		||||
    border: 1px black solid;
 | 
			
		||||
    position: fixed;
 | 
			
		||||
    left: 20px;
 | 
			
		||||
    top: 20px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.heading {
 | 
			
		||||
    background-color: #888;
 | 
			
		||||
    color: white;
 | 
			
		||||
    margin-left: -5px;
 | 
			
		||||
    margin-right: -5px;
 | 
			
		||||
    margin-top: -5px;
 | 
			
		||||
    padding: 5px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.wrapper {
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 30px;
 | 
			
		||||
    bottom: 0px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.body {
 | 
			
		||||
    text-align: justify;
 | 
			
		||||
    overflow-y: auto;
 | 
			
		||||
    box-sizing: border-box;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.transclusion {
 | 
			
		||||
    border: solid #FF901A 3px;
 | 
			
		||||
    padding: 1px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.link {
 | 
			
		||||
    border: solid #33BDFF 3px;
 | 
			
		||||
    padding: 1px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hovertransclusion {
 | 
			
		||||
    background-color: #FF901A;
 | 
			
		||||
    padding: 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hoverlink {
 | 
			
		||||
    background-color: #33BDFF;
 | 
			
		||||
    padding: 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
polygon {
 | 
			
		||||
    fill:white;
 | 
			
		||||
    fill-opacity: 0;
 | 
			
		||||
    pointer-events: auto;
 | 
			
		||||
    stroke-width: 3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
polygon.bridge { stroke:#FF901A; }
 | 
			
		||||
polygon.linkbridge { stroke:#33BDFF; }
 | 
			
		||||
polygon.hoverbridge {
 | 
			
		||||
    fill:#FF901A;
 | 
			
		||||
    fill-opacity: 0.75;
 | 
			
		||||
}
 | 
			
		||||
polygon.hoverlinkbridge {
 | 
			
		||||
    fill:#33BDFF;
 | 
			
		||||
    fill-opacity: 0.75;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
html, body { margin:0; padding:0; overflow:hidden; }
 | 
			
		||||
svg {
 | 
			
		||||
    position:fixed; top:0; bottom:0; left:0; right:0;
 | 
			
		||||
    z-index: 100000;
 | 
			
		||||
    pointer-events: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.paylink {
 | 
			
		||||
    background-color: #33BDFF;
 | 
			
		||||
    color: black;
 | 
			
		||||
    padding: 2px;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5976
									
								
								sourcing/static/js/interact.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5976
									
								
								sourcing/static/js/interact.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										397
									
								
								sourcing/static/js/viewer.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										397
									
								
								sourcing/static/js/viewer.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,397 @@
 | 
			
		|||
'use strict';
 | 
			
		||||
 | 
			
		||||
var doc1 = document.getElementById('doc1');
 | 
			
		||||
var edlform = document.getElementById('edlform');
 | 
			
		||||
var max_zindex = 0;
 | 
			
		||||
var bridge_count = 0;
 | 
			
		||||
var link_bridge_count = 0;
 | 
			
		||||
var payment_params = {};
 | 
			
		||||
var payment_content;
 | 
			
		||||
var xnb_per_char = 150000;
 | 
			
		||||
 | 
			
		||||
function listener (event) {
 | 
			
		||||
    console.log(event.type, event.pageX, event.pageY);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function hl_location(hl) {
 | 
			
		||||
    var rects = hl.getClientRects();
 | 
			
		||||
    var top = rects[0].top;
 | 
			
		||||
    var right = rects[0].right;
 | 
			
		||||
    var bottom = rects[rects.length-1].bottom
 | 
			
		||||
    var left = rects[rects.length-1].left;
 | 
			
		||||
    console.log(top, right, bottom, left);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function dragMoveListener (event) {
 | 
			
		||||
    var target = event.target,
 | 
			
		||||
        // keep the dragged position in the data-x/data-y attributes
 | 
			
		||||
        x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
 | 
			
		||||
        y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
 | 
			
		||||
 | 
			
		||||
    update_location(target, x, y);
 | 
			
		||||
 | 
			
		||||
    update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function update() {
 | 
			
		||||
    for(var i = 0; i < bridge_count; i++) {
 | 
			
		||||
        update_bridge('bridge' + i, 'span' + i, 'transclusion' + i);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for(var i = 0; i < link_bridge_count; i++) {
 | 
			
		||||
        update_bridge('linkbridge' + i, 'xanalink' + i, 'link' + i);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function update_bridge(bridge, name_h1, name_h2) {
 | 
			
		||||
    var points = []
 | 
			
		||||
 | 
			
		||||
    var h1 = document.getElementById(name_h1);
 | 
			
		||||
    var h2 = document.getElementById(name_h2);
 | 
			
		||||
 | 
			
		||||
    if (!h1) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (!h2) {
 | 
			
		||||
        return;  // because we skipped the large document
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    var rect1 = h1.getBoundingClientRect();
 | 
			
		||||
    var rect2 = h2.getBoundingClientRect();
 | 
			
		||||
 | 
			
		||||
    var h1_x_center = rect1.right - rect1.width / 2;
 | 
			
		||||
    var h2_x_center = rect2.right - rect2.width / 2;
 | 
			
		||||
 | 
			
		||||
    var bridge_element = document.getElementById(bridge);
 | 
			
		||||
 | 
			
		||||
    var h_l, h_r, rect_l, rect_r;
 | 
			
		||||
    if (h1_x_center < h2_x_center) {
 | 
			
		||||
        h_l = h1;
 | 
			
		||||
        h_r = h2;
 | 
			
		||||
        rect_l = rect1;
 | 
			
		||||
        rect_r = rect2;
 | 
			
		||||
    } else {
 | 
			
		||||
        h_l = h2;
 | 
			
		||||
        h_r = h1;
 | 
			
		||||
        rect_l = rect2;
 | 
			
		||||
        rect_r = rect1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var body_l = $(h_l).closest(".body").get(0).getBoundingClientRect();
 | 
			
		||||
    var body_r = $(h_r).closest(".body").get(0).getBoundingClientRect();
 | 
			
		||||
 | 
			
		||||
    var left_bottom = rect_l.bottom;
 | 
			
		||||
    if(left_bottom < body_l.top) {
 | 
			
		||||
        left_bottom = body_l.top;
 | 
			
		||||
    } else if (left_bottom > body_l.bottom) {
 | 
			
		||||
        left_bottom = body_l.bottom;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var left_top = rect_l.top;
 | 
			
		||||
    if(left_top < body_l.top) {
 | 
			
		||||
        left_top = body_l.top;
 | 
			
		||||
    } else if (left_top > body_l.bottom) {
 | 
			
		||||
        left_top = body_l.bottom;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var right_bottom = rect_r.bottom;
 | 
			
		||||
    if(right_bottom < body_r.top) {
 | 
			
		||||
        right_bottom = body_r.top;
 | 
			
		||||
    } else if (right_bottom > body_r.bottom) {
 | 
			
		||||
        right_bottom = body_r.bottom;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var right_top = rect_r.top;
 | 
			
		||||
    if(right_top < body_r.top) {
 | 
			
		||||
        right_top = body_r.top;
 | 
			
		||||
    } else if (right_top > body_r.bottom) {
 | 
			
		||||
        right_top = body_r.bottom;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    points.push(rect_l.right + ',' + left_top);
 | 
			
		||||
    points.push(rect_l.right  + ',' + left_bottom);
 | 
			
		||||
 | 
			
		||||
    points.push(rect_r.left  + ',' + right_bottom);
 | 
			
		||||
    points.push(rect_r.left + ',' + right_top);
 | 
			
		||||
 | 
			
		||||
    var poly = document.getElementById(bridge);
 | 
			
		||||
    poly.setAttribute('points', points.join(' '));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function update_location(target, x, y) {
 | 
			
		||||
    // target.style.transform = 'scale(0.75) translate(' + x + 'px, ' + y + 'px)';
 | 
			
		||||
    target.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
 | 
			
		||||
 | 
			
		||||
    target.setAttribute('data-x', x);
 | 
			
		||||
    target.setAttribute('data-y', y);
 | 
			
		||||
 | 
			
		||||
    max_zindex += 1;
 | 
			
		||||
    target.style.zIndex = max_zindex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function resizemove(event) {
 | 
			
		||||
    var target = event.target,
 | 
			
		||||
            x = (parseFloat(target.getAttribute('data-x')) || 0),
 | 
			
		||||
            y = (parseFloat(target.getAttribute('data-y')) || 0);
 | 
			
		||||
 | 
			
		||||
    // update the element's style
 | 
			
		||||
    target.style.width  = event.rect.width + 'px';
 | 
			
		||||
    target.style.height = event.rect.height + 'px';
 | 
			
		||||
 | 
			
		||||
    // translate when resizing from top or left edges
 | 
			
		||||
    x += event.deltaRect.left;
 | 
			
		||||
    y += event.deltaRect.top;
 | 
			
		||||
 | 
			
		||||
    update_location(target, x, y);
 | 
			
		||||
 | 
			
		||||
    update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interact('.document')
 | 
			
		||||
    .draggable({
 | 
			
		||||
        onmove: dragMoveListener,
 | 
			
		||||
    })
 | 
			
		||||
    .resizable({
 | 
			
		||||
        // preserveAspectRatio: false,
 | 
			
		||||
        edges: { left: true, right: true, bottom: true, top: true },
 | 
			
		||||
    })
 | 
			
		||||
    .on('resizemove', resizemove)
 | 
			
		||||
    .actionChecker(function (pointer, event, action, interactable, element, interaction) {
 | 
			
		||||
        if (!interact.matchesSelector(event.target, '.heading') && action.name == 'drag') {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        return action;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
interact('#edlform')
 | 
			
		||||
    .draggable({
 | 
			
		||||
        onmove: dragMoveListener,
 | 
			
		||||
    })
 | 
			
		||||
    .on('resizemove', resizemove)
 | 
			
		||||
    .actionChecker(function (pointer, event, action, interactable, element, interaction) {
 | 
			
		||||
        if (!interact.matchesSelector(event.target, '.heading') && action.name == 'drag') {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        return action;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
// doc1.style.height = '400px';
 | 
			
		||||
// update_location(doc1, 200, 50);
 | 
			
		||||
 | 
			
		||||
var docid = 0;
 | 
			
		||||
 | 
			
		||||
function new_document(doc) {
 | 
			
		||||
    var source   = $("#document-template").html();
 | 
			
		||||
    var template = Handlebars.compile(source);
 | 
			
		||||
    docid++;
 | 
			
		||||
    var context  = {
 | 
			
		||||
        docid: docid,
 | 
			
		||||
        heading: doc.heading,
 | 
			
		||||
        doctype: doc.doctype,
 | 
			
		||||
        text: doc.text
 | 
			
		||||
    };
 | 
			
		||||
    var element = $(template(context));
 | 
			
		||||
    var w = document.documentElement.clientWidth;
 | 
			
		||||
    var h = document.documentElement.clientHeight;
 | 
			
		||||
 | 
			
		||||
    if (doc.doctype == 'xanadoc') {
 | 
			
		||||
      var x = (w / 2) - 400;
 | 
			
		||||
      var y = (h / 2) - 400;
 | 
			
		||||
    } else {
 | 
			
		||||
      var x = Math.random() * (w - 400);
 | 
			
		||||
      var y = Math.random() * (h - 400);
 | 
			
		||||
    }
 | 
			
		||||
    update_location(element.get(0), x, y);
 | 
			
		||||
 | 
			
		||||
    $("#top").append(element);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function reset() {
 | 
			
		||||
    $(".document").remove();
 | 
			
		||||
 | 
			
		||||
    var svg = document.getElementById('svg');
 | 
			
		||||
    while (svg.firstChild) {
 | 
			
		||||
        svg.removeChild(svg.firstChild);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bridge_count = 0;
 | 
			
		||||
    link_bridge_count = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$("button#clear").click(function(event) {
 | 
			
		||||
    $("#edl").val("");
 | 
			
		||||
    reset();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function get_end_number(str) {
 | 
			
		||||
    var len = str.length;
 | 
			
		||||
    var num;
 | 
			
		||||
    for(var i = 0; i < len; i++) {
 | 
			
		||||
        if(!isNaN(num = parseInt(str.substr(i))))
 | 
			
		||||
            return num;
 | 
			
		||||
    }
 | 
			
		||||
    throw "no number found";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function hover_bridge(element, hover) {
 | 
			
		||||
    var num = get_end_number(element.id);
 | 
			
		||||
    var bridge = document.getElementById('bridge' + num);
 | 
			
		||||
 | 
			
		||||
    bridge.setAttribute("class", hover ? 'hoverbridge' : 'bridge');
 | 
			
		||||
 | 
			
		||||
    var cls = 'hovertransclusion';
 | 
			
		||||
 | 
			
		||||
    if (hover) {
 | 
			
		||||
        $('#transclusion' + num).addClass(cls);
 | 
			
		||||
        $('#span' + num).addClass(cls);
 | 
			
		||||
    } else {
 | 
			
		||||
        $('#transclusion' + num).removeClass(cls);
 | 
			
		||||
        $('#span' + num).removeClass(cls);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function hover_link_bridge(element, hover) {
 | 
			
		||||
    var num = get_end_number(element.id);
 | 
			
		||||
    var bridge = document.getElementById('linkbridge' + num);
 | 
			
		||||
 | 
			
		||||
    bridge.setAttribute("class", hover ? 'hoverlinkbridge' : 'linkbridge');
 | 
			
		||||
 | 
			
		||||
    var cls = 'hoverlink';
 | 
			
		||||
 | 
			
		||||
    if (hover) {
 | 
			
		||||
        $('#xanalink' + num).addClass(cls);
 | 
			
		||||
        $('#link' + num).addClass(cls);
 | 
			
		||||
    } else {
 | 
			
		||||
        $('#xanalink' + num).removeClass(cls);
 | 
			
		||||
        $('#link' + num).removeClass(cls);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function fulfil() {
 | 
			
		||||
    reset();  // clear all documents and bridges
 | 
			
		||||
 | 
			
		||||
    bridge_count = doc.span_count;
 | 
			
		||||
    link_bridge_count = doc.link_count;
 | 
			
		||||
    var svg_element = document.getElementById('svg');
 | 
			
		||||
 | 
			
		||||
    for(var i = 0; i < doc.span_count; i++) {
 | 
			
		||||
        var p = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
 | 
			
		||||
        p.setAttribute('id', 'bridge' + i);
 | 
			
		||||
        p.setAttribute('class', 'bridge');
 | 
			
		||||
        p.setAttribute('visibility', 'hidden');
 | 
			
		||||
 | 
			
		||||
        p.addEventListener('mouseover', function(e) {
 | 
			
		||||
            hover_bridge(this, true);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        p.addEventListener('mouseout', function(e) {
 | 
			
		||||
            hover_bridge(this, false);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        svg_element.appendChild(p);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for(var i = 0; i < doc.link_count; i++) {
 | 
			
		||||
        var p = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
 | 
			
		||||
        p.setAttribute('id', 'linkbridge' + i);
 | 
			
		||||
        p.setAttribute('class', 'linkbridge');
 | 
			
		||||
        p.setAttribute('visibility', 'hidden');
 | 
			
		||||
 | 
			
		||||
        p.addEventListener('mouseover', function(e) {
 | 
			
		||||
            hover_link_bridge(this, true);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        p.addEventListener('mouseout', function(e) {
 | 
			
		||||
            hover_link_bridge(this, false);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        svg_element.appendChild(p);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $.each(doc.source, function(key, doc) {
 | 
			
		||||
        if (doc.text) {
 | 
			
		||||
            doc.heading += " (source document)";
 | 
			
		||||
            doc.doctype = 'sourcedoc';
 | 
			
		||||
            new_document(doc);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    new_document({'heading': 'xanadoc',
 | 
			
		||||
                  'text': doc.doc,
 | 
			
		||||
                  'doctype': 'xanadoc'});
 | 
			
		||||
 | 
			
		||||
    update();
 | 
			
		||||
 | 
			
		||||
    $('.transclusion').bind('mouseover', function(e) {
 | 
			
		||||
        hover_bridge(this, true);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $('.transclusion').bind('mouseout', function(e) {
 | 
			
		||||
        hover_bridge(this, false);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $('.link').bind('mouseover', function(e) {
 | 
			
		||||
        hover_link_bridge(this, true);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $('.link').bind('mouseout', function(e) {
 | 
			
		||||
        hover_link_bridge(this, false);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $('.xanadoclink').click(function(e) {
 | 
			
		||||
        var num = get_end_number(this.id);
 | 
			
		||||
        var source = $('#link' + num).closest( ".sourcedoc" );
 | 
			
		||||
 | 
			
		||||
        var bridge1 = document.getElementById('linkbridge' + num);
 | 
			
		||||
        var cur_state = bridge1.getAttribute('visibility');
 | 
			
		||||
        var new_state = cur_state == 'hidden' ? 'visible' : 'hidden';
 | 
			
		||||
 | 
			
		||||
        source.find('.sourcedoclink').each(function(index, value) {
 | 
			
		||||
            var bridge_num = get_end_number(value.id);
 | 
			
		||||
            var bridge = document.getElementById('linkbridge' + bridge_num);
 | 
			
		||||
            bridge.setAttribute('visibility', new_state);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        source.toggle();
 | 
			
		||||
 | 
			
		||||
        update();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $('.xanadoctransclusion').click(function(e) {
 | 
			
		||||
        var num = get_end_number(this.id);
 | 
			
		||||
        var source = $('#transclusion' + num).closest( ".sourcedoc" );
 | 
			
		||||
 | 
			
		||||
        var bridge1 = document.getElementById('bridge' + num);
 | 
			
		||||
        var cur_state = bridge1.getAttribute('visibility');
 | 
			
		||||
        var new_state = cur_state == 'hidden' ? 'visible' : 'hidden';
 | 
			
		||||
 | 
			
		||||
        source.find('.sourcedoctransclusion').each(function(index, value) {
 | 
			
		||||
            var bridge_num = get_end_number(value.id);
 | 
			
		||||
            var bridge = document.getElementById('bridge' + bridge_num);
 | 
			
		||||
            bridge.setAttribute('visibility', new_state);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        source.toggle();
 | 
			
		||||
 | 
			
		||||
        update();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $('.body').bind('scroll', function(event) {
 | 
			
		||||
        update();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $('.sourcedoc').hide();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function size_svg() {
 | 
			
		||||
    var w = document.documentElement.clientWidth - 10;
 | 
			
		||||
    var h = document.documentElement.clientHeight - 10;
 | 
			
		||||
    $('svg').width(w);
 | 
			
		||||
    $('svg').height(h);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$(function() {
 | 
			
		||||
    size_svg();
 | 
			
		||||
    $(window).resize(size_svg);
 | 
			
		||||
    fulfil();
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -7,6 +7,7 @@
 | 
			
		|||
<title>{{ title | default("Xanadu") }}</title>
 | 
			
		||||
 | 
			
		||||
<link rel="stylesheet" href="{{ url_for('static', filename='bootstrap/css/bootstrap.css') }}">
 | 
			
		||||
{{ style | safe }}
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,9 @@ div#text { font-family: Courier; }
 | 
			
		|||
      {% if doc.user == current_user %}
 | 
			
		||||
      <a href="{{ doc.edit_url }}" class="btn btn-default">edit</a>
 | 
			
		||||
      {% endif %}
 | 
			
		||||
      {% if doc.type == 'xanadoc' %}
 | 
			
		||||
      <a href="{{ doc.url }}" class="btn btn-default">fulfil</a>
 | 
			
		||||
      {% endif %}
 | 
			
		||||
    </h1>
 | 
			
		||||
    <p><a href="{{ url_for('.home') }}">back to index</a></p>
 | 
			
		||||
    <div class="well" id="text">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										53
									
								
								sourcing/templates/view/xanadoc.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								sourcing/templates/view/xanadoc.html
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,53 @@
 | 
			
		|||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<head>
 | 
			
		||||
<meta charset="utf-8">
 | 
			
		||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
 | 
			
		||||
<meta name="viewport" content="width=device-width, initial-scale=1">
 | 
			
		||||
<title>{{ title | default("Xanadu") }}</title>
 | 
			
		||||
 | 
			
		||||
<link rel="stylesheet" href="{{ url_for('static', filename='bootstrap/css/bootstrap.css') }}">
 | 
			
		||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/xanadoc.css') }}">
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
{% include "navbar.html" %}
 | 
			
		||||
<div class="container-fluid">
 | 
			
		||||
{% include "flash_msg.html" %}
 | 
			
		||||
 | 
			
		||||
{% raw %}
 | 
			
		||||
<script id="document-template" type="text/x-handlebars-template">
 | 
			
		||||
    <div class="document {{ doctype }}" id="doc{{ docid }}">
 | 
			
		||||
        <div class="heading" id="head{{ docid }}">{{ heading }}</div>
 | 
			
		||||
        <div class="wrapper">
 | 
			
		||||
            <div class="body" id="body{{ docid }}">
 | 
			
		||||
                {{{ text }}}
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</script>
 | 
			
		||||
{% endraw %}
 | 
			
		||||
 | 
			
		||||
<svg id="svg" version="1.2" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
</svg>
 | 
			
		||||
 | 
			
		||||
<div id="top">
 | 
			
		||||
 | 
			
		||||
<a href="{{ item.url + '/edl' }}" class="btn btn-default">view EDL</a>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<script src="{{ url_for('static', filename='jquery/jquery.js') }}"></script>
 | 
			
		||||
<script src="{{ url_for('static', filename='bootstrap/js/bootstrap.js') }}"></script>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
var get_span_path = "{{ url_for('.get_span') }}";
 | 
			
		||||
var doc = {{ doc | tojson }};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<script src="{{ url_for('static', filename='js/interact.js') }}"></script>
 | 
			
		||||
<script src="{{ url_for('static', filename='js/viewer.js') }}"></script>
 | 
			
		||||
<script src="{{ url_for('static', filename='handlebars/handlebars.js') }}"></script>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										45
									
								
								sourcing/url.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								sourcing/url.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,45 @@
 | 
			
		|||
import requests
 | 
			
		||||
from .model import Item
 | 
			
		||||
import os.path
 | 
			
		||||
import re
 | 
			
		||||
 | 
			
		||||
project_dir = os.path.dirname(os.path.dirname(__file__))
 | 
			
		||||
cache_location = os.path.join(project_dir, 'cache')
 | 
			
		||||
 | 
			
		||||
re_colon_slash = re.compile('[/:]+')
 | 
			
		||||
 | 
			
		||||
def url_filename(url):
 | 
			
		||||
    return re_colon_slash.sub('_', url)
 | 
			
		||||
 | 
			
		||||
def get_text(url):
 | 
			
		||||
    # assume UTF-8
 | 
			
		||||
 | 
			
		||||
    text = get_url(url)
 | 
			
		||||
 | 
			
		||||
    heading = url.rsplit('/', 1)[-1]
 | 
			
		||||
    return {
 | 
			
		||||
        'url': url,
 | 
			
		||||
        'text': text,
 | 
			
		||||
        'heading': heading,
 | 
			
		||||
        'length': len(text),
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
def get_url(url):
 | 
			
		||||
    print('get_url:', url)
 | 
			
		||||
    item = Item.from_external(url)
 | 
			
		||||
    if item:
 | 
			
		||||
        return item.text
 | 
			
		||||
    content = requests.get(url).content
 | 
			
		||||
    return content.decode(errors='replace')
 | 
			
		||||
 | 
			
		||||
    filename = os.path.join(cache_location, url_filename(url))
 | 
			
		||||
 | 
			
		||||
    if os.path.exists(filename):
 | 
			
		||||
        content = open(filename, 'rb').read()
 | 
			
		||||
    else:
 | 
			
		||||
        content = requests.get(url).content
 | 
			
		||||
        open(filename, 'wb').write(content)
 | 
			
		||||
 | 
			
		||||
    return content.decode(errors='replace')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -5,6 +5,8 @@ from flask_login import (login_user, current_user, logout_user,
 | 
			
		|||
from .forms import (LoginForm, SignupForm, AccountSettingsForm,
 | 
			
		||||
                    UploadSourceDocForm, SourceDocForm, ItemForm)
 | 
			
		||||
from .model import User, SourceDoc, Item, XanaDoc, XanaLink
 | 
			
		||||
from .url import get_url
 | 
			
		||||
from .edl import fulfil_edl_with_sources
 | 
			
		||||
from .database import session
 | 
			
		||||
from .text import iter_lines
 | 
			
		||||
from werkzeug.debug.tbtools import get_current_traceback
 | 
			
		||||
| 
						 | 
				
			
			@ -122,10 +124,27 @@ def get_item(username, hashid):
 | 
			
		|||
        doc = None
 | 
			
		||||
    return doc if doc else abort(404)
 | 
			
		||||
 | 
			
		||||
def view_xanadoc(item):
 | 
			
		||||
    return render_template('view/xanadoc.html',
 | 
			
		||||
                           item=item,
 | 
			
		||||
                           doc=fulfil_edl_with_sources(item.text))
 | 
			
		||||
 | 
			
		||||
@bp.route('/<username>/<hashid>/edl')
 | 
			
		||||
def view_edl(username, hashid):
 | 
			
		||||
    item = get_item(username, hashid)
 | 
			
		||||
    if item.type != 'xanadoc':
 | 
			
		||||
        return abort(404)
 | 
			
		||||
 | 
			
		||||
    return render_template('view.html', doc=item, iter_lines=iter_lines)
 | 
			
		||||
 | 
			
		||||
@bp.route('/<username>/<hashid>')
 | 
			
		||||
def view_item(username, hashid):
 | 
			
		||||
    item = get_item(username, hashid)
 | 
			
		||||
    if item.type == 'xanadoc':
 | 
			
		||||
        return view_xanadoc(item)
 | 
			
		||||
 | 
			
		||||
    return render_template('view.html',
 | 
			
		||||
                           doc=get_item(username, hashid),
 | 
			
		||||
                           doc=item,
 | 
			
		||||
                           iter_lines=iter_lines)
 | 
			
		||||
 | 
			
		||||
@bp.route('/<username>/<hashid>/edit', methods=['GET', 'POST'])
 | 
			
		||||
| 
						 | 
				
			
			@ -224,9 +243,11 @@ def api_get_document(username, filename):
 | 
			
		|||
    }
 | 
			
		||||
    return jsonify(ret)
 | 
			
		||||
 | 
			
		||||
@bp.route('/all_titles')
 | 
			
		||||
def get_all_titles():
 | 
			
		||||
    titles = XanaLink.get_all_titles()
 | 
			
		||||
    for k, v in titles.items():
 | 
			
		||||
        print(from_external(k), v)
 | 
			
		||||
    return ''
 | 
			
		||||
@bp.route('/get_span.json')
 | 
			
		||||
def get_span():
 | 
			
		||||
    url = request.args['url']
 | 
			
		||||
    start = int(request.args['start'])
 | 
			
		||||
    length = int(request.args['length'])
 | 
			
		||||
    spanid = request.args['spanid']
 | 
			
		||||
    text = get_url(url)
 | 
			
		||||
    return jsonify(text=text[start:start + length], spanid=spanid)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue