annotot 0.2.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/README.md +71 -1
- data/app/assets/javascripts/annotot/annotot_endpoint.js +10 -8
- data/app/controllers/annotot/annotations_controller.rb +13 -3
- data/app/controllers/annotot/application_controller.rb +1 -1
- data/app/models/annotot/annotation.rb +12 -0
- data/app/views/annotot/annotations/pages.json.jbuilder +4 -0
- data/app/views/annotot/annotations/show.json.erb +1 -0
- data/config/routes.rb +2 -1
- data/lib/annotot/version.rb +1 -1
- data/lib/generators/annotot/install_generator.rb +5 -0
- data/lib/tasks/annotot_tasks.rake +59 -4
- metadata +7 -6
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 | 
            -
             | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 2 | 
            +
            SHA256:
         | 
| 3 | 
            +
              metadata.gz: f30142a82474f3723a5d0e041a7b26bce696b1aa975d6b4dc3da81b7cc89ad43
         | 
| 4 | 
            +
              data.tar.gz: 1f3d9a4ebb62364cb8ca4a2eea465abc6e4a461b397a61949afe4380c0c2f200
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: bfbefc765005d29ab2ec2810941692a93a2d02111701c86648ba9e08efd4b21ee6f639ebf6ea209a185777e7b8020d013b1244c34dedbaff4a3b48ee5dd39421
         | 
| 7 | 
            +
              data.tar.gz: 0a93107a49bf745413b4f515e6ceb072d62159f9c5d47919bf615b7b22eef27e4e1af984cf10ea647a0664491552f5f58dbcd666562a0bd3dccf784bf7442059
         | 
    
        data/README.md
    CHANGED
    
    | @@ -3,7 +3,7 @@ | |
| 3 3 |  | 
| 4 4 | 
             
            Need to persist annotations quick and easily? Annotot, the original mini annotation API is for you. Don't annotate, annotot instead.
         | 
| 5 5 |  | 
| 6 | 
            -
            h/t @ | 
| 6 | 
            +
            h/t [@eefahy](https://github.com/eefahy) for the inspiration and name
         | 
| 7 7 |  | 
| 8 8 | 
             
            
         | 
| 9 9 |  | 
| @@ -30,6 +30,76 @@ annotationEndpoint: { | |
| 30 30 |  | 
| 31 31 | 
             
            If you want to configure Annotot to receive annotations from external sources make sure that you enable CORs in the Rails application. This can be done using [rack-cors](https://github.com/cyu/rack-cors).
         | 
| 32 32 |  | 
| 33 | 
            +
            ## API
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            Annotot by default mounts itself at `/`. Though [this can be changed](http://guides.rubyonrails.org/engines.html#mounting-the-engine). All API endpoints are relative to its mount location.
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            | Path / Url | HTTP Verb | Path | Controller#Action |
         | 
| 38 | 
            +
            | --- | --- | --- | --- |
         | 
| 39 | 
            +
            | [annotations_path](#annotationspath) | GET | /annotations(.:format) | annotot/annotations#index {:format=>:json} |
         | 
| 40 | 
            +
            | | POST | /annotations(.:format) | annotot/annotations#create {:format=>:json} |
         | 
| 41 | 
            +
            | [lists_annotations_path](#listsannotationspath) | GET | /annotations/lists(.:format) | annotot/annotations#lists {:format=>:json} |
         | 
| 42 | 
            +
            | [annotation_path](#annotationpath) | PATCH | /annotations/:id(.:format) | annotot/annotations#update {:format=>:json} |
         | 
| 43 | 
            +
            | | PUT | /annotations/:id(.:format) |  annotot/annotations#update {:format=>:json}
         | 
| 44 | 
            +
            | | DELETE | /annotations/:id(.:format) |  annotot/annotations#destroy {:format=>:json}
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            ---
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            ### annotations_path
         | 
| 49 | 
            +
            `GET` - Return annotations for a given canvas
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            Parameters:
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            | Name | Required? | Description |
         | 
| 54 | 
            +
            | --- | --- | --- |
         | 
| 55 | 
            +
            | uri | yes | Canvas uri for which to return annotations
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            `POST` -  Create a new annotation
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            Parameters:
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            | Name | Required? | Description |
         | 
| 62 | 
            +
            | --- | --- | --- |
         | 
| 63 | 
            +
            | annotation | yes | object containing creation parameters
         | 
| 64 | 
            +
            | annotation.uuid | no | uuid for annotation
         | 
| 65 | 
            +
            | annotation.data | no | annotation body data as string
         | 
| 66 | 
            +
            | annotation.canvas | no | canvas to place the annotation on
         | 
| 67 | 
            +
             | 
| 68 | 
            +
            ---
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            ### lists_annotations_path
         | 
| 71 | 
            +
            `GET` - Return an AnnotationList of annotations for a given canvas
         | 
| 72 | 
            +
             | 
| 73 | 
            +
            Parameters:
         | 
| 74 | 
            +
             | 
| 75 | 
            +
            | Name | Required? | Description |
         | 
| 76 | 
            +
            | --- | --- | --- |
         | 
| 77 | 
            +
            | uri | yes | Canvas uri for which to return annotations
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            ---
         | 
| 80 | 
            +
             | 
| 81 | 
            +
            ### annotation_path
         | 
| 82 | 
            +
            `PATCH`, `PUT` - Update an annotation
         | 
| 83 | 
            +
             | 
| 84 | 
            +
            Parameters:
         | 
| 85 | 
            +
             | 
| 86 | 
            +
            | Name | Required? | Description |
         | 
| 87 | 
            +
            | --- | --- | --- |
         | 
| 88 | 
            +
            | id | yes | Canvas uri or Rails ActiveRecord id for annotation to update
         | 
| 89 | 
            +
            | annotation | yes | object containing creation parameters
         | 
| 90 | 
            +
            | annotation.uuid | no | uuid for annotation
         | 
| 91 | 
            +
            | annotation.data | no | annotation body data as string
         | 
| 92 | 
            +
            | annotation.canvas | no | canvas to place the annotation on
         | 
| 93 | 
            +
             | 
| 94 | 
            +
            `DELETE` - Delete an annotation
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            Parameters:
         | 
| 97 | 
            +
             | 
| 98 | 
            +
            | Name | Required? | Description |
         | 
| 99 | 
            +
            | --- | --- | --- |
         | 
| 100 | 
            +
            | id | yes | Canvas uri or Rails ActiveRecord id for annotation to delete
         | 
| 101 | 
            +
             | 
| 102 | 
            +
             | 
| 33 103 | 
             
            ## Installation
         | 
| 34 104 | 
             
            Add this line to your application's Gemfile:
         | 
| 35 105 |  | 
| @@ -31,7 +31,7 @@ | |
| 31 31 | 
             
                search: function(options, successCallback, errorCallback) {
         | 
| 32 32 | 
             
                  var _this = this;
         | 
| 33 33 | 
             
                  _this.annotationsList = [];
         | 
| 34 | 
            -
                  options.format = 'json'
         | 
| 34 | 
            +
                  options.format = 'json';
         | 
| 35 35 |  | 
| 36 36 | 
             
                  jQuery.ajax({
         | 
| 37 37 | 
             
                    url: _this.endpoint,
         | 
| @@ -65,7 +65,7 @@ | |
| 65 65 | 
             
                deleteAnnotation: function(annotationID, successCallback, errorCallback) {
         | 
| 66 66 | 
             
                  var _this = this;
         | 
| 67 67 | 
             
                  jQuery.ajax({
         | 
| 68 | 
            -
                    url: _this.endpoint + '/' + annotationID,
         | 
| 68 | 
            +
                    url: _this.endpoint + '/' + encodeURIComponent(annotationID),
         | 
| 69 69 | 
             
                    type: 'DELETE',
         | 
| 70 70 | 
             
                    dataType: 'json',
         | 
| 71 71 | 
             
                    headers: {
         | 
| @@ -89,11 +89,11 @@ | |
| 89 89 | 
             
                update: function(oaAnnotation, successCallback, errorCallback) {
         | 
| 90 90 | 
             
                  var _this = this;
         | 
| 91 91 | 
             
                  var annotation = _this.getAnnotationInEndpoint(oaAnnotation);
         | 
| 92 | 
            -
             | 
| 93 | 
            -
                  var annotationID = annotation.annotation | 
| 92 | 
            +
             | 
| 93 | 
            +
                  var annotationID = annotation.annotation.uuid;
         | 
| 94 94 |  | 
| 95 95 | 
             
                  jQuery.ajax({
         | 
| 96 | 
            -
                    url: _this.endpoint + '/' + annotationID,
         | 
| 96 | 
            +
                    url: _this.endpoint + '/' + encodeURIComponent(annotationID),
         | 
| 97 97 | 
             
                    type: 'PATCH',
         | 
| 98 98 | 
             
                    dataType: 'json',
         | 
| 99 99 | 
             
                    headers: {
         | 
| @@ -158,13 +158,15 @@ | |
| 158 158 | 
             
                // Converts OA Annotation to endpoint format
         | 
| 159 159 | 
             
                getAnnotationInEndpoint: function(oaAnnotation) {
         | 
| 160 160 | 
             
                  // Generate a new uuid if one is not present
         | 
| 161 | 
            -
                   | 
| 161 | 
            +
                  // condition needs to be set to check for "falsy" values
         | 
| 162 | 
            +
                  // !oaAnnotation['@id'] should match null and undefined
         | 
| 163 | 
            +
                  if (!oaAnnotation['@id']) {
         | 
| 162 164 | 
             
                    oaAnnotation["@id"] = Mirador.genUUID();
         | 
| 163 165 | 
             
                  }
         | 
| 164 | 
            -
             | 
| 166 | 
            +
             | 
| 165 167 | 
             
                  canvas = oaAnnotation.on[0].full;
         | 
| 166 168 | 
             
                  var newAnno = jQuery.extend({}, oaAnnotation);
         | 
| 167 | 
            -
                  delete newAnno.endpoint
         | 
| 169 | 
            +
                  delete newAnno.endpoint;
         | 
| 168 170 | 
             
                  return {
         | 
| 169 171 | 
             
                    annotation: {
         | 
| 170 172 | 
             
                      uuid: oaAnnotation["@id"],
         | 
| @@ -2,18 +2,26 @@ require_dependency "annotot/application_controller" | |
| 2 2 |  | 
| 3 3 | 
             
            module Annotot
         | 
| 4 4 | 
             
              class AnnotationsController < ApplicationController
         | 
| 5 | 
            -
                before_action :set_annotation, only: %i[update destroy]
         | 
| 5 | 
            +
                before_action :set_annotation, only: %i[update destroy show]
         | 
| 6 6 |  | 
| 7 7 | 
             
                # GET /annotations
         | 
| 8 8 | 
             
                def index
         | 
| 9 9 | 
             
                  @annotations = Annotation.where(canvas: annotation_search_params)
         | 
| 10 10 | 
             
                end
         | 
| 11 11 |  | 
| 12 | 
            +
                # GET /annotations
         | 
| 13 | 
            +
                def show; end
         | 
| 14 | 
            +
             | 
| 12 15 | 
             
                # Get /annotations/lists
         | 
| 13 16 | 
             
                def lists
         | 
| 14 17 | 
             
                  @annotations = Annotation.where(canvas: annotation_search_params)
         | 
| 15 18 | 
             
                end
         | 
| 16 19 |  | 
| 20 | 
            +
                # Get /annotations/pages
         | 
| 21 | 
            +
                def pages
         | 
| 22 | 
            +
                  @annotations = Annotation.where(canvas: annotation_search_params)
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 17 25 | 
             
                # POST /annotations
         | 
| 18 26 | 
             
                def create
         | 
| 19 27 | 
             
                  @annotation = Annotation.new(annotation_params)
         | 
| @@ -50,7 +58,9 @@ module Annotot | |
| 50 58 | 
             
                private
         | 
| 51 59 |  | 
| 52 60 | 
             
                def set_annotation
         | 
| 53 | 
            -
                  @annotation = Annotation. | 
| 61 | 
            +
                  @annotation = Annotot::Annotation.retrieve_by_id_or_uuid(
         | 
| 62 | 
            +
                    CGI.unescape(params[:id])
         | 
| 63 | 
            +
                  )
         | 
| 54 64 | 
             
                  raise ActiveRecord::RecordNotFound unless @annotation.present?
         | 
| 55 65 | 
             
                end
         | 
| 56 66 |  | 
| @@ -59,7 +69,7 @@ module Annotot | |
| 59 69 | 
             
                end
         | 
| 60 70 |  | 
| 61 71 | 
             
                def annotation_search_params
         | 
| 62 | 
            -
                  params.require(:uri)
         | 
| 72 | 
            +
                  CGI.unescape(params.require(:uri))
         | 
| 63 73 | 
             
                end
         | 
| 64 74 | 
             
              end
         | 
| 65 75 | 
             
            end
         | 
| @@ -4,5 +4,17 @@ module Annotot | |
| 4 4 | 
             
                validates :canvas, presence: true
         | 
| 5 5 |  | 
| 6 6 | 
             
                serialize :data, JSON
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                ##
         | 
| 9 | 
            +
                # Used to differentiate between a numeric id and a uuid. Rails will trim a
         | 
| 10 | 
            +
                # uuid with leading numbers eg '123a'.to_i => 123
         | 
| 11 | 
            +
                # @param [String] identifier
         | 
| 12 | 
            +
                def self.retrieve_by_id_or_uuid(identifier)
         | 
| 13 | 
            +
                  if identifier =~ /\A\d+\z/
         | 
| 14 | 
            +
                    find_by(id: identifier)
         | 
| 15 | 
            +
                  else
         | 
| 16 | 
            +
                    find_by(uuid: identifier)
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                end
         | 
| 7 19 | 
             
              end
         | 
| 8 20 | 
             
            end
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            <%= JSON.parse(@annotation.data).to_json.html_safe %>
         | 
    
        data/config/routes.rb
    CHANGED
    
    | @@ -1,7 +1,8 @@ | |
| 1 1 | 
             
            Annotot::Engine.routes.draw do
         | 
| 2 | 
            -
              resources :annotations, except: %i[new edit | 
| 2 | 
            +
              resources :annotations, path: '/', except: %i[new edit], defaults: { format: :json } do
         | 
| 3 3 | 
             
                collection do
         | 
| 4 4 | 
             
                  get 'lists'
         | 
| 5 | 
            +
                  get 'pages'
         | 
| 5 6 | 
             
                end
         | 
| 6 7 | 
             
              end
         | 
| 7 8 | 
             
            end
         | 
    
        data/lib/annotot/version.rb
    CHANGED
    
    
| @@ -1,4 +1,59 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
             | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 1 | 
            +
            require 'json'
         | 
| 2 | 
            +
            require 'pathname'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            namespace :annotot do
         | 
| 5 | 
            +
              desc 'Import annotation list from path'
         | 
| 6 | 
            +
              task :import_file, [:url_path] => :environment do |_t, args|
         | 
| 7 | 
            +
                path = Pathname.new(args.url_path)
         | 
| 8 | 
            +
                puts "Importing annotations from #{path}"
         | 
| 9 | 
            +
                anno_list = JSON.parse(File.read(path))
         | 
| 10 | 
            +
                puts "#{anno_list['resources'].length} resources found"
         | 
| 11 | 
            +
                touch_count = 0
         | 
| 12 | 
            +
                anno_list['resources'].map do |resource|
         | 
| 13 | 
            +
                  uuid = resource['@id']
         | 
| 14 | 
            +
                  selector = resource['on'].first['selector']
         | 
| 15 | 
            +
                  canvas = resource['on'].first['full']
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  ##
         | 
| 18 | 
            +
                  # Annotation appears to be Mirador 2.6.0 compatible
         | 
| 19 | 
            +
                  if resource['on'].first['@type'] == 'oa:SpecificResource' && selector['@type'] == 'oa:Choice'
         | 
| 20 | 
            +
                    if selector['default']['@type'] == 'oa:FragmentSelector' && selector['item']['@type'] == 'oa:SvgSelector'
         | 
| 21 | 
            +
                      touch_count += 1
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  ##
         | 
| 26 | 
            +
                  # Annotation needs to be updated to a single fragment selector
         | 
| 27 | 
            +
                  if resource['on'].first['@type'] == 'oa:SpecificResource' && selector['@type'] == 'oa:FragmentSelector'
         | 
| 28 | 
            +
                    new_on = "#{canvas}##{selector['value']}"
         | 
| 29 | 
            +
                    resource['on'] = new_on
         | 
| 30 | 
            +
                    touch_count += 1
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  ##
         | 
| 34 | 
            +
                  # Annotation only has an SvgSelector and in an non-compliant format
         | 
| 35 | 
            +
                  if selector['@type'] == 'oa:SvgSelector'
         | 
| 36 | 
            +
                    item = selector.deep_dup
         | 
| 37 | 
            +
                    # Fix missing quotes in SVG
         | 
| 38 | 
            +
                    item['value'] = item['value'].gsub('xmlns=http://www.w3.org/2000/svg', 'xmlns="http://www.w3.org/2000/svg"')
         | 
| 39 | 
            +
                    selector['@type'] = 'oa:Choice'
         | 
| 40 | 
            +
                    selector['default'] = {
         | 
| 41 | 
            +
                      '@type' => 'oa:FragmentSelector',
         | 
| 42 | 
            +
                      'value' => 'xywh=0,0,0,0'
         | 
| 43 | 
            +
                    }
         | 
| 44 | 
            +
                    selector.delete('value')
         | 
| 45 | 
            +
                    selector['item'] = item
         | 
| 46 | 
            +
                    resource['on'].first['selector'] = selector.deep_dup
         | 
| 47 | 
            +
                    touch_count += 1
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                  anno_json = resource.to_json
         | 
| 51 | 
            +
                  anno = Annotot::Annotation.find_or_create_by(uuid: uuid)
         | 
| 52 | 
            +
                  anno.update!(
         | 
| 53 | 
            +
                    canvas: canvas,
         | 
| 54 | 
            +
                    data: anno_json
         | 
| 55 | 
            +
                  )
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
                puts "Updated #{touch_count} annotations"
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: annotot
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.7.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Jack Reed
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2020-07-28 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: rails
         | 
| @@ -16,14 +16,14 @@ dependencies: | |
| 16 16 | 
             
                requirements:
         | 
| 17 17 | 
             
                - - "~>"
         | 
| 18 18 | 
             
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            -
                    version: 5.1 | 
| 19 | 
            +
                    version: '5.1'
         | 
| 20 20 | 
             
              type: :runtime
         | 
| 21 21 | 
             
              prerelease: false
         | 
| 22 22 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 23 | 
             
                requirements:
         | 
| 24 24 | 
             
                - - "~>"
         | 
| 25 25 | 
             
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            -
                    version: 5.1 | 
| 26 | 
            +
                    version: '5.1'
         | 
| 27 27 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 28 28 | 
             
              name: engine_cart
         | 
| 29 29 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -117,6 +117,8 @@ files: | |
| 117 117 | 
             
            - app/models/annotot/application_record.rb
         | 
| 118 118 | 
             
            - app/views/annotot/annotations/index.json.erb
         | 
| 119 119 | 
             
            - app/views/annotot/annotations/lists.json.jbuilder
         | 
| 120 | 
            +
            - app/views/annotot/annotations/pages.json.jbuilder
         | 
| 121 | 
            +
            - app/views/annotot/annotations/show.json.erb
         | 
| 120 122 | 
             
            - app/views/layouts/annotot/application.html.erb
         | 
| 121 123 | 
             
            - config/routes.rb
         | 
| 122 124 | 
             
            - db/migrate/20180215183225_create_annotot_annotations.rb
         | 
| @@ -144,8 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 144 146 | 
             
                - !ruby/object:Gem::Version
         | 
| 145 147 | 
             
                  version: '0'
         | 
| 146 148 | 
             
            requirements: []
         | 
| 147 | 
            -
             | 
| 148 | 
            -
            rubygems_version: 2.6.11
         | 
| 149 | 
            +
            rubygems_version: 3.1.2
         | 
| 149 150 | 
             
            signing_key: 
         | 
| 150 151 | 
             
            specification_version: 4
         | 
| 151 152 | 
             
            summary: Annotot. Open annotations in Rails.
         |