Skip to content
This repository was archived by the owner on Apr 2, 2022. It is now read-only.

Commit

Permalink
Initial commit: copied from mnyrop/annotate
Browse files Browse the repository at this point in the history
  • Loading branch information
pbinkley committed Oct 2, 2019
0 parents commit 88dcc3d
Show file tree
Hide file tree
Showing 249 changed files with 80,532 additions and 0 deletions.
5 changes: 5 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
source 'https://rubygems.org'
gem 'jekyll', '~> 3.8'
gem 'jekyll-swiss'
gem 'rake'
gem 'html-proofer'
96 changes: 96 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (5.2.2)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
addressable (2.6.0)
public_suffix (>= 2.0.2, < 4.0)
colorator (1.1.0)
colorize (0.8.1)
concurrent-ruby (1.1.4)
em-websocket (0.5.1)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
ethon (0.12.0)
ffi (>= 1.3.0)
eventmachine (1.2.7)
ffi (1.10.0)
forwardable-extended (2.6.0)
html-proofer (3.10.2)
activesupport (>= 4.2, < 6.0)
addressable (~> 2.3)
colorize (~> 0.8)
mercenary (~> 0.3.2)
nokogiri (~> 1.9)
parallel (~> 1.3)
typhoeus (~> 1.3)
yell (~> 2.0)
http_parser.rb (0.6.0)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
jekyll (3.8.5)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (~> 0.7)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 2.0)
kramdown (~> 1.14)
liquid (~> 4.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (>= 1.7, < 4)
safe_yaml (~> 1.0)
jekyll-sass-converter (1.5.2)
sass (~> 3.4)
jekyll-swiss (1.0.0)
jekyll-watch (2.1.2)
listen (~> 3.0)
kramdown (1.17.0)
liquid (4.0.1)
listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2)
mercenary (0.3.6)
mini_portile2 (2.4.0)
minitest (5.11.3)
nokogiri (1.10.1)
mini_portile2 (~> 2.4.0)
parallel (1.13.0)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (3.0.3)
rake (12.3.2)
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
ffi (~> 1.0)
rouge (3.3.0)
ruby_dep (1.5.0)
safe_yaml (1.0.4)
sass (3.7.3)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
thread_safe (0.3.6)
typhoeus (1.3.1)
ethon (>= 0.9.0)
tzinfo (1.2.5)
thread_safe (~> 0.1)
yell (2.0.7)

PLATFORMS
ruby

DEPENDENCIES
html-proofer
jekyll (~> 3.8)
jekyll-swiss
rake

BUNDLED WITH
1.17.2
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# IIIF-Annotate [![Build Status](https://travis-ci.org/mnyrop/annotate.svg?branch=master)](https://travis-ci.org/mnyrop/annotate) ![Libraries.io for GitHub](https://img.shields.io/librariesio/github/mnyrop/annotate.svg)

Create/store/load static annotations on IIIF manifests via Jekyll

## Getting started

### Requirements
- Ruby >=2.2
- Jekyll >=3.5
- Bundler >=1.12

### Installing
- Clone this repository and navigate into it:<br>
`$ git clone https://github.com/mnyrop/annotate.git && cd annotate`
- Install dependencies:<br>
`$ bundle install`
73 changes: 73 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
require 'fileutils'
require 'json'

task :default => [:store_annotations]

task :store_annotations do
manifests = []
Dir['annotations/*/'].each { | m | manifests << File.basename(m, ".*") }

manifests.each do | manifest |
unstored_canvases = Dir["annotations/" + manifest + "/*.json"].sort!
unstored_canvases.each do |canvas|
name = File.basename(canvas, ".*")
dir = "annotations/" + manifest + "/" + name
sum_annotations = JSON.parse(File.read(canvas))

FileUtils::mkdir_p dir # make dir for canvas annotations

make_anno_list(dir,name,manifest) # write canvas annotation list to file
store_anno_array(dir,name,sum_annotations) # write array of canvas annotations to file

File.delete(canvas) # remove unstored data file
end

unless unstored_canvases.empty?
update_manifest_copy(manifest)
end
end
end



def make_anno_list(dir,name,manifest)
listpath = dir + "/" + "list.json"
if !File.exist?(listpath) # make annotation list if necessary
puts "creating " + listpath + ".\n"
File.open(listpath, 'w') do |f|
f.write("---\nlayout: null\ncanvas: '" + name + "'\n---\n" + '{% assign anno_name = page.canvas | append: "-resources" %}{% assign annotations = site.pages | where: "label", anno_name | first %}{"@context": "http://iiif.io/api/presentation/2/context.json","@id": "{{ site.url }}{{ site.baseurl }}/annotations/' + manifest + '/' + name + '/list.json","@type": "sc:AnnotationList","resources": {{ annotations.content }} }')
end
end
end

def store_anno_array(dir,name,sum_annotations)
annopath = dir + "/" + name + ".json"
if !File.exist?(annopath) # if no preexisting annotation file
puts "creating " + annopath + ".\n"
else # if preexisting annotation file
puts "appending new annotations to " + annopath + ".\n"
old_annotations = JSON.parse(File.read(annopath).gsub(/\A---(.|\n)*?---/, ""))
sum_annotations = sum_annotations.concat old_annotations # add annotation JSON to array
end
File.open(annopath, 'w') { |f| f.write("---\nlayout: null\nlabel: " + name + "-resources\n---\n" + sum_annotations.to_json) }
end

def update_manifest_copy(manifest)
stored_canvases = []
Dir['annotations/' + manifest + "/*/"].each { | c | stored_canvases << File.basename(c, ".*") }

puts "adding annotation references for canvases " + stored_canvases.to_s + " to manifest copy."

manifest_json = JSON.parse(File.read("iiif/" + manifest + "/clean-manifest.json").gsub(/\A---(.|\n)*?---/, "").to_s)
canvases = manifest_json["sequences"][0]["canvases"].select {|c| stored_canvases.include? c["@id"].split('/')[-1] }

canvases.each do | canvas |
annotation_hash = Hash.new { |hash, key| hash[key] = {} }
this_id = canvas["@id"].split('/')[-1]
annotation_hash["@id"] = "{{ site.url }}{{ site.baseurl }}/annotations/" + manifest + "/" + this_id + "/list.json"
annotation_hash["@type"] = "sc:AnnotationList"
canvas["otherContent"] = Array.new << annotation_hash
end

File.open("iiif/" + manifest + "/manifest.json", 'w+') { |f| f.write("---\nlayout: null\n---\n"+manifest_json.to_json) }
end
19 changes: 19 additions & 0 deletions _config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
title: IIIF Annotation Demo
description: ""
baseurl: "/annotate"
url: "http://marii.info"

markdown: kramdown
permalink: pretty

github_username: mnyrop
social_username: mariinyrop

theme: jekyll-swiss

exclude: [Rakefile, Gemfile*, vendor]
include: [feed.xml]

webrick:
headers:
"Access-Control-Allow-Origin": "*"
65 changes: 65 additions & 0 deletions _includes/annotation_to_json.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<style>
.anno{max-width:800;overflow:scroll;padding:10px;margin-top:10px;}
</style>
<br>
<button type="button" id="anno_button">View cached annotation JSON</button>
<div id="anno_results"></div>
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script type="text/jscript">
var canvas_regex = /.+canvas\/([^.]+)/;

function download(filename, text) {
var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
var safetext = function(text){
var table = {
'<': 'lt',
'>': 'gt',
'"': 'quot',
'\'': 'apos',
'&': 'amp',
'\r': '#10',
'\n': '#13'
};

return text.toString().replace(/[<>"'\r\n&]/g, function(chr){
return '&' + table[chr] + ';';
});
};

$(document).ready(function(){
$( "#anno_button" ).click(function() {
$( "#anno_results" ).empty()
for(var i =0; i < localStorage.length; i++){
var key = localStorage.key(i);
var matches = canvas_regex.exec(key);
if(matches != null) {
var canvas = matches[1];
var fileName = canvas + '.json';
var fileContent = localStorage.getItem(key);
if (fileContent.length > 2) {
$("#anno_results").append("<div class='anno'></div>" )
.append("<h1 class='file'>" + canvas + "</h1>")
.append("<textarea rows='30' cols='100' id='" + canvas + "-content'>"+ safetext(fileContent))
.append("<br><button type='button' id='" + canvas +"' class='download-button'>Download " + fileName + "</button>");
}
}
}
$(".download-button").click(function(){
var content_id = this.id + "-content";
var text = document.getElementById(content_id).value;
var file = this.id + ".json"
download(file, text);
});
});
});
</script>
16 changes: 16 additions & 0 deletions _includes/head.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<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>{% if page.title %}{{ page.title | escape }}{% else %}{{ site.title | escape }}{% endif %}</title>
<meta name="description" content="{% if page.excerpt %}{{ page.excerpt | strip_html | strip_newlines | truncate: 160 }}{% else %}{{ site.description }}{% endif %}">

{% assign user_url = site.url | append: site.baseurl %}
{% assign full_base_url = user_url | default: site.github.url %}
<link rel="stylesheet" href="{{ "/assets/style.css" | prepend: full_base_url }}">

<link rel="canonical" href="{{ page.url | replace:'index.html','' | prepend: site.baseurl | prepend: site.url }}">

<script async defer src="https://buttons.github.io/buttons.js"></script>
</head>
26 changes: 26 additions & 0 deletions _includes/header.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<header class="border-bottom-thick px-2 clearfix" style="position: fixed;top:0;width: 100%;background-color:#fff;">
<div class="left sm-width-full py-1 mt-1 mt-lg-0">
<a class="align-middle link-primary text-accent" href="{{ site.baseurl }}/">
{{ site.title }}
</a>
</div>
<div class="right sm-width-full">
<ul class="list-reset mt-lg-1 mb-2 mb-lg-1">
<li class="inline-block">
<a class="align-middle link-primary mr-2 mr-lg-0 ml-lg-2" href="#1">
1. Select a Manifest
</a>
</li>
<li class="inline-block">
<a class="align-middle link-primary mr-2 mr-lg-0 ml-lg-2" href="#2">
2. Add Annotations
</a>
</li>
<li class="inline-block">
<a class="align-middle link-primary mr-2 mr-lg-0 ml-lg-2" href="#3">
3. Store Annotations
</a>
</li>
</ul>
</div>
</header>
26 changes: 26 additions & 0 deletions _includes/iiif_presentation.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{% capture data %}
{% for m in page.manifests %}
{ manifestUri: '{{ site.url }}{{ site.baseurl }}/iiif/{{ m }}/manifest.json' }{% unless forloop.last %}, {% endunless %}
{% endfor %}
{% endcapture %}

<iframe title='Mirador' class="iiif_presentation" allowtransparency="true" src='iiif_mirador.html' allowfullscreen='true' webkitallowfullscreen='true' mozallowfullscreen='true' style='width: 100%; height: 600px;margin:40px 0px 20px 0px;' srcdoc="<link rel='stylesheet' type='text/css' href='{{ site.baseurl }}/build/mirador/css/mirador-combined.css'>
<style>#viewer {width: 100%;}</style>
<div id='viewer'></div>
<script src='{{ site.baseurl }}/build/mirador/mirador.js'></script>
<script type='text/javascript'>
$(function() {
myMiradorInstance = Mirador({
id: 'viewer',
data: [{{ data }}],
windowObjects: [{
loadedManifest: '{{ site.url }}{{ site.baseurl }}/iiif/{{ page.loaded_manifest }}/manifest.json',
canvasID: '{{ page.canvas_id }}',
bottomPanelVisible: {{ page.bottom_panel | default: 'true' }}
}],
annotationEndpoint: { 'name':'Local Storage', 'module': 'LocalStorageEndpoint' }
});
});
</script>">
</iframe>
5 changes: 5 additions & 0 deletions annotations/bnf640/f10/f10.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
layout: null
label: f10-resources
---
[{"@context":"http://iiif.io/api/presentation/2/context.json","@type":"oa:Annotation","motivation":["oa:commenting"],"resource":[{"@type":"dctypes:Text","format":"text/html","chars":"<p>5</p>"}],"on":[{"@type":"oa:SpecificResource","full":"http://gallica.bnf.fr/iiif/ark:/12148/btv1b10500001g/canvas/f10","selector":{"@type":"oa:Choice","default":{"@type":"oa:FragmentSelector","value":"xywh=1220,698,1243,17"},"item":{"@type":"oa:SvgSelector","value":"<svg xmlns='http://www.w3.org/2000/svg'><path xmlns=\"http://www.w3.org/2000/svg\" d=\"M1219.72996,697.54631l1242.61505,17.41984l0,0\" data-paper-data=\"{&quot;defaultStrokeValue&quot;:1,&quot;editStrokeValue&quot;:5,&quot;currentStrokeValue&quot;:5,&quot;annotation&quot;:null,&quot;editable&quot;:true}\" id=\"rough_path_6b925223-487d-492a-864d-1c26c345856f\" fill=\"none\" fill-rule=\"nonzero\" stroke=\"#00bfff\" stroke-width=\"19.35537\" stroke-linecap=\"butt\" stroke-linejoin=\"miter\" stroke-miterlimit=\"10\" stroke-dasharray=\"\" stroke-dashoffset=\"0\" font-family=\"none\" font-weight=\"none\" font-size=\"none\" text-anchor=\"none\" style=\"mix-blend-mode: normal\"/></svg>"}},"within":{"@id":"http://gallica.bnf.fr/iiif/ark:/12148/btv1b10500001g/manifest.json","@type":"sc:Manifest"}}],"@id":"0028ebc0-9097-449e-9daa-50ae7c6e95c9"}]
5 changes: 5 additions & 0 deletions annotations/bnf640/f10/list.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
layout: null
canvas: f10
---
{% assign anno_name = page.canvas | append: "-resources" %}{% assign annotations = site.pages | where: "label", anno_name | first %}{"@context": "http://iiif.io/api/presentation/2/context.json","@id": "{{ site.url }}{{ site.baseurl }}/annotations/bnf640/f10/list.json","@type": "sc:AnnotationList","resources": {{ annotations.content }} }
5 changes: 5 additions & 0 deletions annotations/bnf640/f11/f11.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
layout: null
label: f11-resources
---
[{"@context":"http://iiif.io/api/presentation/2/context.json","@type":"oa:Annotation","motivation":["oa:commenting"],"resource":[{"@type":"dctypes:Text","format":"text/html","chars":"<p>6</p>"}],"on":[{"@type":"oa:SpecificResource","full":"http://gallica.bnf.fr/iiif/ark:/12148/btv1b10500001g/canvas/f11","selector":{"@type":"oa:Choice","default":{"@type":"oa:FragmentSelector","value":"xywh=1331,537,50,75"},"item":{"@type":"oa:SvgSelector","value":"<svg xmlns='http://www.w3.org/2000/svg'><path xmlns=\"http://www.w3.org/2000/svg\" d=\"M1356.21336,611.96834c0,-16.71379 8.35689,-33.42757 25.07068,-50.14136c0,-13.84615 -11.22453,-25.07068 -25.07068,-25.07068c-13.84615,0 -25.07068,11.22453 -25.07068,25.07068c16.71379,16.71379 25.07068,33.42757 25.07068,50.14136z\" data-paper-data=\"{&quot;defaultStrokeValue&quot;:1,&quot;editStrokeValue&quot;:5,&quot;currentStrokeValue&quot;:1,&quot;fixedSize&quot;:true,&quot;editable&quot;:true,&quot;deleteIcon&quot;:null,&quot;annotation&quot;:null}\" id=\"pin_f06b387d-01ed-446f-8a5b-ae509faed686\" fill-opacity=\"0\" fill=\"#00bfff\" fill-rule=\"nonzero\" stroke=\"#00bfff\" stroke-width=\"5.01414\" stroke-linecap=\"butt\" stroke-linejoin=\"miter\" stroke-miterlimit=\"10\" stroke-dasharray=\"\" stroke-dashoffset=\"0\" font-family=\"none\" font-weight=\"none\" font-size=\"none\" text-anchor=\"none\" style=\"mix-blend-mode: normal\"/></svg>"}},"within":{"@id":"http://gallica.bnf.fr/iiif/ark:/12148/btv1b10500001g/manifest.json","@type":"sc:Manifest"}}],"@id":"6a988caa-d35d-4482-8cee-3c12454c4d32"},{"@context":"http://iiif.io/api/presentation/2/context.json","@type":"oa:Annotation","motivation":["oa:commenting"],"resource":[{"@type":"dctypes:Text","format":"text/html","chars":"<p>7</p>"}],"on":[{"@type":"oa:SpecificResource","full":"http://gallica.bnf.fr/iiif/ark:/12148/btv1b10500001g/canvas/f11","selector":{"@type":"oa:Choice","default":{"@type":"oa:FragmentSelector","value":"xywh=1440,1810,104,156"},"item":{"@type":"oa:SvgSelector","value":"<svg xmlns='http://www.w3.org/2000/svg'><path xmlns=\"http://www.w3.org/2000/svg\" d=\"M1492.43853,1965.59751c0,-34.65771 17.32885,-69.31542 51.98656,-103.97313c0,-28.71139 -23.27518,-51.98656 -51.98656,-51.98656c-28.71139,0 -51.98656,23.27518 -51.98656,51.98656c34.65771,34.65771 51.98656,69.31542 51.98656,103.97313z\" data-paper-data=\"{&quot;defaultStrokeValue&quot;:1,&quot;editStrokeValue&quot;:5,&quot;currentStrokeValue&quot;:1,&quot;fixedSize&quot;:true,&quot;editable&quot;:true,&quot;deleteIcon&quot;:null,&quot;annotation&quot;:null}\" id=\"pin_26e0e405-617b-4001-88c9-91ce1b725a3d\" fill-opacity=\"0\" fill=\"#00bfff\" fill-rule=\"nonzero\" stroke=\"#00bfff\" stroke-width=\"10.39731\" stroke-linecap=\"butt\" stroke-linejoin=\"miter\" stroke-miterlimit=\"10\" stroke-dasharray=\"\" stroke-dashoffset=\"0\" font-family=\"none\" font-weight=\"none\" font-size=\"none\" text-anchor=\"none\" style=\"mix-blend-mode: normal\"/></svg>"}},"within":{"@id":"http://gallica.bnf.fr/iiif/ark:/12148/btv1b10500001g/manifest.json","@type":"sc:Manifest"}}],"@id":"a0818a1e-ebed-4215-9438-f06e7d9173f4"},{"@context":"http://iiif.io/api/presentation/2/context.json","@type":"oa:Annotation","motivation":["oa:commenting"],"resource":[{"@type":"dctypes:Text","format":"text/html","chars":"<p>8</p>"}],"on":[{"@type":"oa:SpecificResource","full":"http://gallica.bnf.fr/iiif/ark:/12148/btv1b10500001g/canvas/f11","selector":{"@type":"oa:Choice","default":{"@type":"oa:FragmentSelector","value":"xywh=1451,3463,104,156"},"item":{"@type":"oa:SvgSelector","value":"<svg xmlns='http://www.w3.org/2000/svg'><path xmlns=\"http://www.w3.org/2000/svg\" d=\"M1502.83584,3618.77026c0,-34.65771 17.32885,-69.31542 51.98656,-103.97313c0,-28.71139 -23.27518,-51.98656 -51.98656,-51.98656c-28.71139,0 -51.98656,23.27518 -51.98656,51.98656c34.65771,34.65771 51.98656,69.31542 51.98656,103.97313z\" data-paper-data=\"{&quot;defaultStrokeValue&quot;:1,&quot;editStrokeValue&quot;:5,&quot;currentStrokeValue&quot;:1,&quot;fixedSize&quot;:true,&quot;editable&quot;:true,&quot;deleteIcon&quot;:null,&quot;annotation&quot;:null}\" id=\"pin_15c9cfff-d7d6-464a-b524-95b23949bcbe\" fill-opacity=\"0\" fill=\"#00bfff\" fill-rule=\"nonzero\" stroke=\"#00bfff\" stroke-width=\"10.39731\" stroke-linecap=\"butt\" stroke-linejoin=\"miter\" stroke-miterlimit=\"10\" stroke-dasharray=\"\" stroke-dashoffset=\"0\" font-family=\"none\" font-weight=\"none\" font-size=\"none\" text-anchor=\"none\" style=\"mix-blend-mode: normal\"/></svg>"}},"within":{"@id":"http://gallica.bnf.fr/iiif/ark:/12148/btv1b10500001g/manifest.json","@type":"sc:Manifest"}}],"@id":"7fba6a72-3520-43e1-a05a-f40f653c1246"}]
5 changes: 5 additions & 0 deletions annotations/bnf640/f11/list.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
layout: null
canvas: f11
---
{% assign anno_name = page.canvas | append: "-resources" %}{% assign annotations = site.pages | where: "label", anno_name | first %}{"@context": "http://iiif.io/api/presentation/2/context.json","@id": "{{ site.url }}{{ site.baseurl }}/annotations/bnf640/f11/list.json","@type": "sc:AnnotationList","resources": {{ annotations.content }} }
Loading

0 comments on commit 88dcc3d

Please sign in to comment.