gitnoted 0.1.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 +7 -0
 - data/Gemfile +2 -0
 - data/Gemfile.lock +40 -0
 - data/README.md +162 -0
 - data/Rakefile +5 -0
 - data/bin/gitnoted +95 -0
 - data/gitnoted.gemspec +25 -0
 - data/lib/git_noted.rb +2 -0
 - data/lib/git_noted/application.rb +163 -0
 - data/lib/git_noted/public/css/gitnoted.css +60 -0
 - data/lib/git_noted/public/index.html +54 -0
 - data/lib/git_noted/public/js/gitnoted.js +46 -0
 - data/lib/git_noted/repository.rb +148 -0
 - metadata +171 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA1:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 514bf87ae44f1a65208940e4a8db87e5a049b27d
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 944db11d0806f73287350138421c35d8b956b38f
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 0ae0007cff3bb75b96d16831d7e779ab2798a80db0dfade08fe3dcb88c9b7b6f470dcb39cb41832c9dc207f14d5a458a6e4a3e98123552ac0b9ce63ee3f2b320
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 32581b4a57bcf3970965cd85f448bbd2955d3cf2b530332b2be49b7edb89a9bbff6234efc5f18abad3385ae152fbe3d5fa8c4647d1d164354ee49b4f764a64ca
         
     | 
    
        data/Gemfile
    ADDED
    
    
    
        data/Gemfile.lock
    ADDED
    
    | 
         @@ -0,0 +1,40 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            PATH
         
     | 
| 
      
 2 
     | 
    
         
            +
              remote: .
         
     | 
| 
      
 3 
     | 
    
         
            +
              specs:
         
     | 
| 
      
 4 
     | 
    
         
            +
                gitnoted (0.1.0)
         
     | 
| 
      
 5 
     | 
    
         
            +
                  concurrent-ruby (>= 1.0.5)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  puma (~> 3.7)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  rack-cors (~> 0.4)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  redcarpet (~> 3.4)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  rugged (~> 0.25)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  sigdump (>= 0.2.4)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  sinatra (~> 1.4)
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            GEM
         
     | 
| 
      
 14 
     | 
    
         
            +
              remote: https://rubygems.org/
         
     | 
| 
      
 15 
     | 
    
         
            +
              specs:
         
     | 
| 
      
 16 
     | 
    
         
            +
                concurrent-ruby (1.0.5)
         
     | 
| 
      
 17 
     | 
    
         
            +
                puma (3.8.1)
         
     | 
| 
      
 18 
     | 
    
         
            +
                rack (1.6.5)
         
     | 
| 
      
 19 
     | 
    
         
            +
                rack-cors (0.4.1)
         
     | 
| 
      
 20 
     | 
    
         
            +
                rack-protection (1.5.3)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  rack
         
     | 
| 
      
 22 
     | 
    
         
            +
                rake (12.0.0)
         
     | 
| 
      
 23 
     | 
    
         
            +
                redcarpet (3.4.0)
         
     | 
| 
      
 24 
     | 
    
         
            +
                rugged (0.25.1.1)
         
     | 
| 
      
 25 
     | 
    
         
            +
                sigdump (0.2.4)
         
     | 
| 
      
 26 
     | 
    
         
            +
                sinatra (1.4.8)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  rack (~> 1.5)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  rack-protection (~> 1.4)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  tilt (>= 1.3, < 3)
         
     | 
| 
      
 30 
     | 
    
         
            +
                tilt (2.0.6)
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            PLATFORMS
         
     | 
| 
      
 33 
     | 
    
         
            +
              ruby
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            DEPENDENCIES
         
     | 
| 
      
 36 
     | 
    
         
            +
              gitnoted!
         
     | 
| 
      
 37 
     | 
    
         
            +
              rake (>= 0.9.2)
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            BUNDLED WITH
         
     | 
| 
      
 40 
     | 
    
         
            +
               1.14.6
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,162 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # GitNoted
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            GitNoted is a simple document server that works with [Github Wiki](https://help.github.com/articles/about-github-wikis/) or [Gollum](https://github.com/gollum/gollum) to serve foot notes for external web sites just by adding a small script tag.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            * [JavaScript tag](#javascript-tag)
         
     | 
| 
      
 6 
     | 
    
         
            +
            * [Writing notes](#writing-notes)
         
     | 
| 
      
 7 
     | 
    
         
            +
            * [Running server with Github Wiki](#running-server-with-github-wiki)
         
     | 
| 
      
 8 
     | 
    
         
            +
            * [Running server with other git repositories](#running-server-with-other-git-repositories)
         
     | 
| 
      
 9 
     | 
    
         
            +
            * [Deploying to Heroku](#deploying-to-heroku)
         
     | 
| 
      
 10 
     | 
    
         
            +
            * [Server usage](#server-usage)
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            ## JavaScript tag
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            You can find the JavaScript code on [lib/git_noted/public/js/gitnoted.js](lib/git_noted/public/js/gitnoted.js). This file will be served as `/js/gitnoted.js` from the GitNoted server. You can import it using `<script>` tag as following.
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            ```
         
     | 
| 
      
 17 
     | 
    
         
            +
            <!-- GitNoted depends on jQuery -->
         
     | 
| 
      
 18 
     | 
    
         
            +
            <script src="https://code.jquery.com/jquery-3.1.1.min.js"
         
     | 
| 
      
 19 
     | 
    
         
            +
                integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
         
     | 
| 
      
 20 
     | 
    
         
            +
                crossorigin="anonymous"></script>
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            <!-- GitNoted -->
         
     | 
| 
      
 23 
     | 
    
         
            +
            <link rel="stylesheet" type="text/css" href="http://localhost:4567/css/gitnoted.css" />
         
     | 
| 
      
 24 
     | 
    
         
            +
            <script type="text/javascript" src="http://localhost:4567/js/gitnoted.js"></script>
         
     | 
| 
      
 25 
     | 
    
         
            +
            ```
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            Please replace `http://localhost:4567` to point your GitNoted server (see bellow).
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            Once the JavaScript tag is set up, you can add following `<div class="gitnoted" data-labels="label,label,...">` tags your HTML to embed notes. Here is an example:
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            ```
         
     | 
| 
      
 32 
     | 
    
         
            +
            <div class="gitnoted" data-labels="purpose:test,message:hello"></div>
         
     | 
| 
      
 33 
     | 
    
         
            +
            ```
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            `data-labels` is used to search notes by labels. Notes that include all of them match.
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            ## Writing notes
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            Edit mode must be Markdown. Other formats are not supported.
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            In the body of a page, you need to include `:label: label,label,label,...` line at the beginning or at the end. Example:
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            ```
         
     | 
| 
      
 45 
     | 
    
         
            +
            # My first wiki page
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            Hello!
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            ---
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            :label: purpose:test,message:hello
         
     | 
| 
      
 52 
     | 
    
         
            +
            ```
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            ## Running server with Github Wiki
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            Prepare following information first:
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
            * Domain names (and ports) of your website that embeds notes. You can have multiple web sites. Here uses `example.com` and `localhost:8080` as an example.
         
     | 
| 
      
 59 
     | 
    
         
            +
            * Repository URL of a Github Wiki. Format of the URL is `https://github.com/<user>/<repo>.wiki.git` where "<user> and <repo> are your repository's username and repository name.
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
            This command starts a server on http://localhost:4567:
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
            ```
         
     | 
| 
      
 64 
     | 
    
         
            +
            $ gem install gitnoted
         
     | 
| 
      
 65 
     | 
    
         
            +
            $ gitnoted "https://github.com/frsyuki/gitnoted.wiki.git" \
         
     | 
| 
      
 66 
     | 
    
         
            +
                       ./repo \
         
     | 
| 
      
 67 
     | 
    
         
            +
                       -a example.com -a localhost:8080 \
         
     | 
| 
      
 68 
     | 
    
         
            +
                       -h localhost -p 4567
         
     | 
| 
      
 69 
     | 
    
         
            +
            ```
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            If your repository is private, you also need to set `GITHUB_ACCESS_TOKEN` environment variable. You can create a token on [your account configuration page](https://github.com/settings/tokens). Example:
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            ```
         
     | 
| 
      
 74 
     | 
    
         
            +
            $ gem install gitnoted
         
     | 
| 
      
 75 
     | 
    
         
            +
            $ export GITHUB_ACCESS_TOKEN=abcdef0123456789abcdef0123456789abcdef01
         
     | 
| 
      
 76 
     | 
    
         
            +
            $ gitnoted \
         
     | 
| 
      
 77 
     | 
    
         
            +
                       "https://github.com/frsyuki/my_secret_repository.wiki.git" \
         
     | 
| 
      
 78 
     | 
    
         
            +
                       ./repo \
         
     | 
| 
      
 79 
     | 
    
         
            +
                       -a example.com -a localhost:8080 \
         
     | 
| 
      
 80 
     | 
    
         
            +
                       -h localhost -p 4567
         
     | 
| 
      
 81 
     | 
    
         
            +
            ```
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
            ## Running server with other git repositories
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
            Instead of using Github Wiki, you can use any git repositories that contain files named `<name>.md`. You can use your text editor or tools such as [Gollum](https://github.com/gollum/gollum) to push `.md` files.
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
            To start GitNoted for those git repositories, prepare following information:
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
            * Domain names (and ports) of your website that embeds notes. You can have multiple web sites. Here uses `example.com` and `localhost:8080` as an example.
         
     | 
| 
      
 90 
     | 
    
         
            +
            * Repository URL of the git repository. It should provide http access (ssh is not supported at this moment).
         
     | 
| 
      
 91 
     | 
    
         
            +
            * Username and password of the git repository. You need to set them to GIT_USERNAME and GIT_PASSWORD environment variables.
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
            This command starts a server on http://localhost:4567:
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
            ```
         
     | 
| 
      
 96 
     | 
    
         
            +
            $ gem install gitnoted
         
     | 
| 
      
 97 
     | 
    
         
            +
            $ export GIT_USERNAME=myname
         
     | 
| 
      
 98 
     | 
    
         
            +
            $ export GIT_PASSWORD=topsecret
         
     | 
| 
      
 99 
     | 
    
         
            +
            $ gitnoted \
         
     | 
| 
      
 100 
     | 
    
         
            +
                       "https://github.com/frsyuki/my_secret_repository.wiki.git" \
         
     | 
| 
      
 101 
     | 
    
         
            +
                       ./repo \
         
     | 
| 
      
 102 
     | 
    
         
            +
                       -a example.com -a localhost:8080 \
         
     | 
| 
      
 103 
     | 
    
         
            +
                       -h localhost -p 4567
         
     | 
| 
      
 104 
     | 
    
         
            +
            ```
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
            ## Deploying to Heroku
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
            You need to create 4 files in a new git repository.
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
            ### Procfile
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
            Put a gitnoted command in your `Procfile` with `$PORT` variable as the port number. Here is an example:
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
            ```
         
     | 
| 
      
 115 
     | 
    
         
            +
            web: bundle exec gitnoted "https://github.com/frsyuki/gitnoted.wiki.git ./repo -a example.com -h 0.0.0.0 -p $PORT
         
     | 
| 
      
 116 
     | 
    
         
            +
            ```
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
            ### Gemfile
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
            ```
         
     | 
| 
      
 121 
     | 
    
         
            +
            source "https://rubygems.org"
         
     | 
| 
      
 122 
     | 
    
         
            +
            ruby "2.4.0"
         
     | 
| 
      
 123 
     | 
    
         
            +
            gem "gitnoted"
         
     | 
| 
      
 124 
     | 
    
         
            +
            ```
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
            ### .buildpacks
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
            ```
         
     | 
| 
      
 129 
     | 
    
         
            +
            https://github.com/ddollar/heroku-buildpack-apts
         
     | 
| 
      
 130 
     | 
    
         
            +
            https://github.com/heroku/heroku-buildpack-ruby
         
     | 
| 
      
 131 
     | 
    
         
            +
            ```
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
            ### Aptfile
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
            ```
         
     | 
| 
      
 136 
     | 
    
         
            +
            cmake
         
     | 
| 
      
 137 
     | 
    
         
            +
            pkg-config
         
     | 
| 
      
 138 
     | 
    
         
            +
            ```
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
            ## Server usage
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
            ```
         
     | 
| 
      
 143 
     | 
    
         
            +
            $ gitnoted [options] <git url> <local path to store>
         
     | 
| 
      
 144 
     | 
    
         
            +
              options:
         
     | 
| 
      
 145 
     | 
    
         
            +
                -a, --allow-origin DOMAIN[:PORT] Allow cross-origin resource sharing (CORS) from this domain (can be set multiple times)
         
     | 
| 
      
 146 
     | 
    
         
            +
                -h, --host ADDRESS               Bind address (default: 'localhost')
         
     | 
| 
      
 147 
     | 
    
         
            +
                -p, --port PORT                  Port (default: 4567)
         
     | 
| 
      
 148 
     | 
    
         
            +
                -e, --extra-app PATH.rb          Add an extra Sinatra application
         
     | 
| 
      
 149 
     | 
    
         
            +
                -i, --interval SECONDS           Interval to update the git repository
         
     | 
| 
      
 150 
     | 
    
         
            +
                    --threads MIN:MAX            Number of HTTP worker threads
         
     | 
| 
      
 151 
     | 
    
         
            +
              environment variables:
         
     | 
| 
      
 152 
     | 
    
         
            +
                GIT_USERNAME                 Git username
         
     | 
| 
      
 153 
     | 
    
         
            +
                GIT_PASSWORD                 Git password
         
     | 
| 
      
 154 
     | 
    
         
            +
                GITHUB_ACCESS_TOKEN          Github personal API token
         
     | 
| 
      
 155 
     | 
    
         
            +
            ```
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
            ----
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                GitNoted
         
     | 
| 
      
 160 
     | 
    
         
            +
                Author: Sadayuki Furuhashi
         
     | 
| 
      
 161 
     | 
    
         
            +
                License: MIT
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
    
        data/Rakefile
    ADDED
    
    
    
        data/bin/gitnoted
    ADDED
    
    | 
         @@ -0,0 +1,95 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'optparse'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'logger'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            extra_app_paths = []
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            scheduler_options = {
         
     | 
| 
      
 9 
     | 
    
         
            +
              interval: 60
         
     | 
| 
      
 10 
     | 
    
         
            +
            }
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            app_options = {
         
     | 
| 
      
 13 
     | 
    
         
            +
              allow_origins: [],
         
     | 
| 
      
 14 
     | 
    
         
            +
            }
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            repo_options = {
         
     | 
| 
      
 17 
     | 
    
         
            +
              logger: Logger.new(STDOUT),
         
     | 
| 
      
 18 
     | 
    
         
            +
            }
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            server_options = {
         
     | 
| 
      
 21 
     | 
    
         
            +
              server: 'puma',
         
     | 
| 
      
 22 
     | 
    
         
            +
              Host: 'localhost',
         
     | 
| 
      
 23 
     | 
    
         
            +
              Port: 4567,
         
     | 
| 
      
 24 
     | 
    
         
            +
              Threads: nil,
         
     | 
| 
      
 25 
     | 
    
         
            +
            }
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            op = OptionParser.new
         
     | 
| 
      
 28 
     | 
    
         
            +
            op.banner = "#{$0} [options] <git url> <local path to store>"
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            op.separator "  options:"
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            op.on('-a', '--allow-origin DOMAIN[:PORT]', "Allow cross-origin resource sharing (CORS) from this domain (can be set multiple times)") do |v|
         
     | 
| 
      
 33 
     | 
    
         
            +
              app_options[:allow_origins] << v
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            op.on('-h', '--host ADDRESS', "Bind address (default: 'localhost')") do |v|
         
     | 
| 
      
 37 
     | 
    
         
            +
              server_options[:Host] = v
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            op.on('-p', '--port PORT', Integer, "Port (default: 4567)") do |v|
         
     | 
| 
      
 41 
     | 
    
         
            +
              server_options[:Port] = v
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            op.on('-e', '--extra-app PATH.rb', "Add an extra Sinatra application") do |v|
         
     | 
| 
      
 45 
     | 
    
         
            +
              extra_app_paths << v
         
     | 
| 
      
 46 
     | 
    
         
            +
            end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            op.on('-i', '--interval SECONDS', Integer, "Interval to update the git repository") do |v|
         
     | 
| 
      
 49 
     | 
    
         
            +
              scheduler_options[:interval] = v
         
     | 
| 
      
 50 
     | 
    
         
            +
            end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            op.on('--threads MIN:MAX', "Number of HTTP worker threads") do |v|
         
     | 
| 
      
 53 
     | 
    
         
            +
              server_options[:Threads] = v
         
     | 
| 
      
 54 
     | 
    
         
            +
            end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            op.separator <<EOF
         
     | 
| 
      
 57 
     | 
    
         
            +
              environment variables:
         
     | 
| 
      
 58 
     | 
    
         
            +
                GIT_USERNAME                 Git username
         
     | 
| 
      
 59 
     | 
    
         
            +
                GIT_PASSWORD                 Git password
         
     | 
| 
      
 60 
     | 
    
         
            +
                GITHUB_ACCESS_TOKEN          Github personal API token
         
     | 
| 
      
 61 
     | 
    
         
            +
            EOF
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            op.parse!(ARGV)
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
            if ARGV.length != 2
         
     | 
| 
      
 67 
     | 
    
         
            +
              puts op.to_s
         
     | 
| 
      
 68 
     | 
    
         
            +
              exit 1
         
     | 
| 
      
 69 
     | 
    
         
            +
            end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            remote_url, local_path = *ARGV
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            require 'git_noted'
         
     | 
| 
      
 74 
     | 
    
         
            +
            require 'sigdump/setup'
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
            ENV['RACK_ENV'] ||= 'production'
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
            if ENV['GIT_USERNAME']
         
     | 
| 
      
 79 
     | 
    
         
            +
              repo_options[:username] = ENV['GIT_USERNAME']
         
     | 
| 
      
 80 
     | 
    
         
            +
              repo_options[:password] = ENV['GIT_PASSWORD']
         
     | 
| 
      
 81 
     | 
    
         
            +
            elsif ENV['GITHUB_ACCESS_TOKEN']
         
     | 
| 
      
 82 
     | 
    
         
            +
              repo_options[:username] = ENV['GITHUB_ACCESS_TOKEN']
         
     | 
| 
      
 83 
     | 
    
         
            +
              repo_options[:password] = 'x-oauth-basic'
         
     | 
| 
      
 84 
     | 
    
         
            +
            end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
            repository = GitNoted::Repository.new(remote_url, local_path, **repo_options)
         
     | 
| 
      
 87 
     | 
    
         
            +
            app = GitNoted::Application.with(repository: repository, **app_options)
         
     | 
| 
      
 88 
     | 
    
         
            +
            repository.schedule_update! scheduler_options[:interval]
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
            extra_app_paths.each do |path|
         
     | 
| 
      
 91 
     | 
    
         
            +
              app.instance_eval(File.read(path), path)
         
     | 
| 
      
 92 
     | 
    
         
            +
            end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
            app.run!(server_options)
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
    
        data/gitnoted.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            Gem::Specification.new do |gem|
         
     | 
| 
      
 3 
     | 
    
         
            +
              gem.name        = "gitnoted"
         
     | 
| 
      
 4 
     | 
    
         
            +
              gem.description = "Simple document server that works with Github Wiki or Gollum to serve foot notes for external websites just by adding a small script tag"
         
     | 
| 
      
 5 
     | 
    
         
            +
              gem.homepage    = "https://github.com/frsyuki/gitnoted"
         
     | 
| 
      
 6 
     | 
    
         
            +
              gem.summary     = gem.description
         
     | 
| 
      
 7 
     | 
    
         
            +
              gem.version     = "0.1.0"
         
     | 
| 
      
 8 
     | 
    
         
            +
              gem.authors     = ["Sadayuki Furuhashi"]
         
     | 
| 
      
 9 
     | 
    
         
            +
              gem.email       = ["frsyuki@gmail.com"]
         
     | 
| 
      
 10 
     | 
    
         
            +
              gem.license     = "MIT"
         
     | 
| 
      
 11 
     | 
    
         
            +
              gem.has_rdoc    = false
         
     | 
| 
      
 12 
     | 
    
         
            +
              gem.files       = `git ls-files`.split("\n")
         
     | 
| 
      
 13 
     | 
    
         
            +
              gem.test_files  = `git ls-files -- {test,spec,features}/*`.split("\n")
         
     | 
| 
      
 14 
     | 
    
         
            +
              gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
         
     | 
| 
      
 15 
     | 
    
         
            +
              gem.require_paths = ['lib']
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              gem.add_dependency 'sinatra', '~> 1.4'
         
     | 
| 
      
 18 
     | 
    
         
            +
              gem.add_dependency 'puma', '~> 3.7'
         
     | 
| 
      
 19 
     | 
    
         
            +
              gem.add_dependency 'rack-cors', '~> 0.4'
         
     | 
| 
      
 20 
     | 
    
         
            +
              gem.add_dependency 'redcarpet', '~> 3.4'
         
     | 
| 
      
 21 
     | 
    
         
            +
              gem.add_dependency 'rugged', '~>  0.25'
         
     | 
| 
      
 22 
     | 
    
         
            +
              gem.add_dependency 'concurrent-ruby', '>= 1.0.5'
         
     | 
| 
      
 23 
     | 
    
         
            +
              gem.add_dependency 'sigdump', '>= 0.2.4'
         
     | 
| 
      
 24 
     | 
    
         
            +
              gem.add_development_dependency "rake", ">= 0.9.2"
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/git_noted.rb
    ADDED
    
    
| 
         @@ -0,0 +1,163 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'sinatra/base'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'rack/cors'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'rack/static'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'redcarpet'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'erb'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'json'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'git_noted/repository'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            module GitNoted
         
     | 
| 
      
 10 
     | 
    
         
            +
              class Application < Sinatra::Base
         
     | 
| 
      
 11 
     | 
    
         
            +
                def self.default_renderer
         
     | 
| 
      
 12 
     | 
    
         
            +
                  renderer = Redcarpet::Render::HTML.new({
         
     | 
| 
      
 13 
     | 
    
         
            +
                    escape_html: true,
         
     | 
| 
      
 14 
     | 
    
         
            +
                    safe_links_only: true,
         
     | 
| 
      
 15 
     | 
    
         
            +
                  })
         
     | 
| 
      
 16 
     | 
    
         
            +
                  redcarpet = Redcarpet::Markdown.new(renderer, {
         
     | 
| 
      
 17 
     | 
    
         
            +
                    tables: true,
         
     | 
| 
      
 18 
     | 
    
         
            +
                    no_intra_emphasis: true
         
     | 
| 
      
 19 
     | 
    
         
            +
                  })
         
     | 
| 
      
 20 
     | 
    
         
            +
                  redcarpet.method(:render)
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def self.with(allow_origins: [], **options)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  Class.new(self) do
         
     | 
| 
      
 25 
     | 
    
         
            +
                    alias_method :initialize_saved, :initialize
         
     | 
| 
      
 26 
     | 
    
         
            +
                    define_method(:initialize) do
         
     | 
| 
      
 27 
     | 
    
         
            +
                      initialize_saved(**options)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    use Rack::Cors do
         
     | 
| 
      
 31 
     | 
    
         
            +
                      allow do
         
     | 
| 
      
 32 
     | 
    
         
            +
                        origins *allow_origins unless allow_origins.empty?
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                        resource '/api/*', {
         
     | 
| 
      
 35 
     | 
    
         
            +
                            methods: [:get, :options, :head],
         
     | 
| 
      
 36 
     | 
    
         
            +
                            headers: :any,
         
     | 
| 
      
 37 
     | 
    
         
            +
                            expose:  [],
         
     | 
| 
      
 38 
     | 
    
         
            +
                            credentials: true,
         
     | 
| 
      
 39 
     | 
    
         
            +
                            max_age: 600,
         
     | 
| 
      
 40 
     | 
    
         
            +
                        }
         
     | 
| 
      
 41 
     | 
    
         
            +
                      end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                      allow do
         
     | 
| 
      
 44 
     | 
    
         
            +
                        origins '*'
         
     | 
| 
      
 45 
     | 
    
         
            +
                        resource '/public/*', :headers => :any, :methods => :get
         
     | 
| 
      
 46 
     | 
    
         
            +
                      end
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                def initialize(repository:, renderer: Application.default_renderer)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  super()
         
     | 
| 
      
 53 
     | 
    
         
            +
                  @repository = repository
         
     | 
| 
      
 54 
     | 
    
         
            +
                  @renderer = renderer
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                attr_accessor :repository
         
     | 
| 
      
 58 
     | 
    
         
            +
                attr_accessor :renderer
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                use Rack::Static, urls: ["/js", "/css"], root: File.expand_path("../public", __FILE__)
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                include ERB::Util
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                TRANSPARENT_1PX_PNG = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=".unpack('m').first
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                get '/' do
         
     | 
| 
      
 67 
     | 
    
         
            +
                  redirect "/index.html"
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                # GET /api/notes
         
     | 
| 
      
 71 
     | 
    
         
            +
                #     ?labels=k1:v1,k2:v2,...
         
     | 
| 
      
 72 
     | 
    
         
            +
                #     ?exclude_labels=k1:v1,k2:v2,...
         
     | 
| 
      
 73 
     | 
    
         
            +
                get '/api/notes' do
         
     | 
| 
      
 74 
     | 
    
         
            +
                  notes = load_notes(params).map do |note|
         
     | 
| 
      
 75 
     | 
    
         
            +
                    {
         
     | 
| 
      
 76 
     | 
    
         
            +
                      labels: note.labels,
         
     | 
| 
      
 77 
     | 
    
         
            +
                      body: read_note(note)
         
     | 
| 
      
 78 
     | 
    
         
            +
                    }
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  response = {
         
     | 
| 
      
 82 
     | 
    
         
            +
                    notes: notes
         
     | 
| 
      
 83 
     | 
    
         
            +
                  }
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  content_type "application/json"
         
     | 
| 
      
 86 
     | 
    
         
            +
                  return response.to_json
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                # GET /api/notes.html
         
     | 
| 
      
 90 
     | 
    
         
            +
                #     ?labels=k1:v1,k2:v2,...
         
     | 
| 
      
 91 
     | 
    
         
            +
                #     ?exclude_labels=k1:v1,k2:v2,...
         
     | 
| 
      
 92 
     | 
    
         
            +
                get '/api/notes.html' do
         
     | 
| 
      
 93 
     | 
    
         
            +
                  notes = load_notes(params)
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                  html = %[<ul class="gitnoted">]
         
     | 
| 
      
 96 
     | 
    
         
            +
                  notes.each do |note|
         
     | 
| 
      
 97 
     | 
    
         
            +
                    body = render_note(note)
         
     | 
| 
      
 98 
     | 
    
         
            +
                    html << %[<li class="gitnoted-note">]
         
     | 
| 
      
 99 
     | 
    
         
            +
                      html << %[<div class="gitnoted-body">#{body}</div>]
         
     | 
| 
      
 100 
     | 
    
         
            +
                      html << %[<ul class="gitnoted-labels">]
         
     | 
| 
      
 101 
     | 
    
         
            +
                        note.labels.each do |label|
         
     | 
| 
      
 102 
     | 
    
         
            +
                          html << %[<li class="gitnoted-label">#{html_escape(label)}</li>]
         
     | 
| 
      
 103 
     | 
    
         
            +
                        end
         
     | 
| 
      
 104 
     | 
    
         
            +
                      html << %[</ul>]
         
     | 
| 
      
 105 
     | 
    
         
            +
                    html << %[</li>]
         
     | 
| 
      
 106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
                  html << %[</ul>]
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                  content_type "text/html"
         
     | 
| 
      
 110 
     | 
    
         
            +
                  return html
         
     | 
| 
      
 111 
     | 
    
         
            +
                end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                # GET /api/labels
         
     | 
| 
      
 114 
     | 
    
         
            +
                #     ?prefix=k1:
         
     | 
| 
      
 115 
     | 
    
         
            +
                #     ?used_with=k1:v1
         
     | 
| 
      
 116 
     | 
    
         
            +
                get '/api/labels' do
         
     | 
| 
      
 117 
     | 
    
         
            +
                  labels = load_labels(params)
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                  response = {
         
     | 
| 
      
 120 
     | 
    
         
            +
                    labels: labels
         
     | 
| 
      
 121 
     | 
    
         
            +
                  }
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                  content_type "application/json"
         
     | 
| 
      
 124 
     | 
    
         
            +
                  return response.to_json
         
     | 
| 
      
 125 
     | 
    
         
            +
                end
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
                # force update
         
     | 
| 
      
 128 
     | 
    
         
            +
                get '/api/github_hook' do
         
     | 
| 
      
 129 
     | 
    
         
            +
                  @repository.update!
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                  response = { }
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                  content_type "application/json"
         
     | 
| 
      
 134 
     | 
    
         
            +
                  return response.to_json
         
     | 
| 
      
 135 
     | 
    
         
            +
                end
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                get '/favicon.ico' do
         
     | 
| 
      
 138 
     | 
    
         
            +
                  content_type "image/png"
         
     | 
| 
      
 139 
     | 
    
         
            +
                  return TRANSPARENT_1PX_PNG
         
     | 
| 
      
 140 
     | 
    
         
            +
                end
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                def read_note(note)
         
     | 
| 
      
 143 
     | 
    
         
            +
                  @repository.read(note)
         
     | 
| 
      
 144 
     | 
    
         
            +
                end
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                def render_note(note)
         
     | 
| 
      
 147 
     | 
    
         
            +
                  @renderer.call(read_note(note))
         
     | 
| 
      
 148 
     | 
    
         
            +
                end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                def load_notes(params)
         
     | 
| 
      
 151 
     | 
    
         
            +
                  label_names = (params[:labels] || '').split(",")
         
     | 
| 
      
 152 
     | 
    
         
            +
                  exclude_label_names = (params[:exclude_labels] || '').split(",")
         
     | 
| 
      
 153 
     | 
    
         
            +
                  @repository.search_notes(labels: label_names, exclude_labels: exclude_label_names)
         
     | 
| 
      
 154 
     | 
    
         
            +
                end
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
                def load_labels(params)
         
     | 
| 
      
 157 
     | 
    
         
            +
                  used_with_label_names = (params[:used_with] || '').split(',')
         
     | 
| 
      
 158 
     | 
    
         
            +
                  prefix = params[:prefix]
         
     | 
| 
      
 159 
     | 
    
         
            +
                  prefix = nil if prefix == ''
         
     | 
| 
      
 160 
     | 
    
         
            +
                  @repository.search_labels(prefix: prefix, used_with: used_with_label_names)
         
     | 
| 
      
 161 
     | 
    
         
            +
                end
         
     | 
| 
      
 162 
     | 
    
         
            +
              end
         
     | 
| 
      
 163 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,60 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ul.gitnoted {
         
     | 
| 
      
 2 
     | 
    
         
            +
              list-style-type: none;
         
     | 
| 
      
 3 
     | 
    
         
            +
              list-style-position: outside;
         
     | 
| 
      
 4 
     | 
    
         
            +
              margin: 0;
         
     | 
| 
      
 5 
     | 
    
         
            +
              padding: 0;
         
     | 
| 
      
 6 
     | 
    
         
            +
            }
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            ul.gitnoted > li.gitnoted-note {
         
     | 
| 
      
 9 
     | 
    
         
            +
              display: block;
         
     | 
| 
      
 10 
     | 
    
         
            +
              margin: 2em 0;
         
     | 
| 
      
 11 
     | 
    
         
            +
              padding: 0.8em 1em 0.5em 1em;
         
     | 
| 
      
 12 
     | 
    
         
            +
              border: 1px solid #ddd;
         
     | 
| 
      
 13 
     | 
    
         
            +
              background-color: #fff;
         
     | 
| 
      
 14 
     | 
    
         
            +
            }
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            ul.gitnoted > li.gitnoted-note > div.gitnoted-body
         
     | 
| 
      
 17 
     | 
    
         
            +
            h1 {
         
     | 
| 
      
 18 
     | 
    
         
            +
              font-size: 120%;
         
     | 
| 
      
 19 
     | 
    
         
            +
            }
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            ul.gitnoted > li.gitnoted-note > div.gitnoted-body
         
     | 
| 
      
 22 
     | 
    
         
            +
            h2 {
         
     | 
| 
      
 23 
     | 
    
         
            +
              font-size: 120%;
         
     | 
| 
      
 24 
     | 
    
         
            +
            }
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            ul.gitnoted > li.gitnoted-note > div.gitnoted-body
         
     | 
| 
      
 27 
     | 
    
         
            +
            h3 {
         
     | 
| 
      
 28 
     | 
    
         
            +
              font-size: 100%;
         
     | 
| 
      
 29 
     | 
    
         
            +
            }
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            ul.gitnoted > li.gitnoted-note > div.gitnoted-body
         
     | 
| 
      
 32 
     | 
    
         
            +
            h4 {
         
     | 
| 
      
 33 
     | 
    
         
            +
              font-size: 100%;
         
     | 
| 
      
 34 
     | 
    
         
            +
            }
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            ul.gitnoted > li.gitnoted-note > ul.gitnoted-labels {
         
     | 
| 
      
 37 
     | 
    
         
            +
              list-style-type: none;
         
     | 
| 
      
 38 
     | 
    
         
            +
              list-style-position: outside;
         
     | 
| 
      
 39 
     | 
    
         
            +
              text-align: right;
         
     | 
| 
      
 40 
     | 
    
         
            +
              font-size: 70%;
         
     | 
| 
      
 41 
     | 
    
         
            +
            }
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            ul.gitnoted > li.gitnoted-note > ul.gitnoted-labels > li.gitnoted-label {
         
     | 
| 
      
 44 
     | 
    
         
            +
              display: inline-block;
         
     | 
| 
      
 45 
     | 
    
         
            +
              margin-left: 1.3em;
         
     | 
| 
      
 46 
     | 
    
         
            +
              margin-right: -1em;
         
     | 
| 
      
 47 
     | 
    
         
            +
              padding: 0 0.5em;
         
     | 
| 
      
 48 
     | 
    
         
            +
              color: #fff;
         
     | 
| 
      
 49 
     | 
    
         
            +
              background-color: #bbb;
         
     | 
| 
      
 50 
     | 
    
         
            +
              border-radius: 0.8em;
         
     | 
| 
      
 51 
     | 
    
         
            +
            }
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            ul.gitnoted > li.gitnoted-note > ul.gitnoted-labels .gitnoted-label-button:hover {
         
     | 
| 
      
 54 
     | 
    
         
            +
              background-color: #888;
         
     | 
| 
      
 55 
     | 
    
         
            +
            }
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
            ul.gitnoted > li.gitnoted-note code {
         
     | 
| 
      
 58 
     | 
    
         
            +
              white-space: pre;
         
     | 
| 
      
 59 
     | 
    
         
            +
            }
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,54 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            <!DOCTYPE html>
         
     | 
| 
      
 2 
     | 
    
         
            +
            <html lang="en">
         
     | 
| 
      
 3 
     | 
    
         
            +
            <head>
         
     | 
| 
      
 4 
     | 
    
         
            +
              <title>GitNotes setup completed</title>
         
     | 
| 
      
 5 
     | 
    
         
            +
            </head>
         
     | 
| 
      
 6 
     | 
    
         
            +
            <body>
         
     | 
| 
      
 7 
     | 
    
         
            +
              <h1>GitNotes setup completed</h1>
         
     | 
| 
      
 8 
     | 
    
         
            +
              <section id="api_notes_html">
         
     | 
| 
      
 9 
     | 
    
         
            +
                <form action="/api/notes.html":>
         
     | 
| 
      
 10 
     | 
    
         
            +
                  <h2>GET /api/notes.html</h2>
         
     | 
| 
      
 11 
     | 
    
         
            +
                  <p>Search and render notes.</p>
         
     | 
| 
      
 12 
     | 
    
         
            +
                  <div>
         
     | 
| 
      
 13 
     | 
    
         
            +
                    <label for="labels">Labels (separated by comma ","):</label><br />
         
     | 
| 
      
 14 
     | 
    
         
            +
                    <input type="text" name="labels" id="labels" />
         
     | 
| 
      
 15 
     | 
    
         
            +
                  </div>
         
     | 
| 
      
 16 
     | 
    
         
            +
                  <div>
         
     | 
| 
      
 17 
     | 
    
         
            +
                    <label for="exclude_labels">Exclude labels (separated by comma ","):</label><br />
         
     | 
| 
      
 18 
     | 
    
         
            +
                    <input type="text" name="exclude_labels" id="exclude_labels" />
         
     | 
| 
      
 19 
     | 
    
         
            +
                  </div>
         
     | 
| 
      
 20 
     | 
    
         
            +
                  <input type="submit" value="Go">
         
     | 
| 
      
 21 
     | 
    
         
            +
                </form>
         
     | 
| 
      
 22 
     | 
    
         
            +
              </section>
         
     | 
| 
      
 23 
     | 
    
         
            +
              <section id="api_notes">
         
     | 
| 
      
 24 
     | 
    
         
            +
                <form action="/api/notes":>
         
     | 
| 
      
 25 
     | 
    
         
            +
                  <h2>GET /api/notes</h2>
         
     | 
| 
      
 26 
     | 
    
         
            +
                  <p>Search notes.</p>
         
     | 
| 
      
 27 
     | 
    
         
            +
                  <div>
         
     | 
| 
      
 28 
     | 
    
         
            +
                    <label for="labels">Labels (separated by comma ","):</label><br />
         
     | 
| 
      
 29 
     | 
    
         
            +
                    <input type="text" name="labels" id="labels" />
         
     | 
| 
      
 30 
     | 
    
         
            +
                  </div>
         
     | 
| 
      
 31 
     | 
    
         
            +
                  <div>
         
     | 
| 
      
 32 
     | 
    
         
            +
                    <label for="exclude_labels">Exclude labels (separated by comma ","):</label><br />
         
     | 
| 
      
 33 
     | 
    
         
            +
                    <input type="text" name="exclude_labels" id="exclude_labels" />
         
     | 
| 
      
 34 
     | 
    
         
            +
                  </div>
         
     | 
| 
      
 35 
     | 
    
         
            +
                  <input type="submit" value="Go">
         
     | 
| 
      
 36 
     | 
    
         
            +
                </form>
         
     | 
| 
      
 37 
     | 
    
         
            +
              </section>
         
     | 
| 
      
 38 
     | 
    
         
            +
              <section id="api_labels">
         
     | 
| 
      
 39 
     | 
    
         
            +
                <form action="/api/labels":>
         
     | 
| 
      
 40 
     | 
    
         
            +
                  <h2>GET /api/labels</h2>
         
     | 
| 
      
 41 
     | 
    
         
            +
                  <p>Search labels.</p>
         
     | 
| 
      
 42 
     | 
    
         
            +
                  <div>
         
     | 
| 
      
 43 
     | 
    
         
            +
                    <label for="prefix">Label name prefix:</label><br />
         
     | 
| 
      
 44 
     | 
    
         
            +
                    <input type="text" name="prefix" id="prefix" />
         
     | 
| 
      
 45 
     | 
    
         
            +
                  </div>
         
     | 
| 
      
 46 
     | 
    
         
            +
                  <div>
         
     | 
| 
      
 47 
     | 
    
         
            +
                    <label for="used_with">Used with labels (separated by comma ","):</label><br />
         
     | 
| 
      
 48 
     | 
    
         
            +
                    <input type="text" name="used_with" id="used_with" />
         
     | 
| 
      
 49 
     | 
    
         
            +
                  </div>
         
     | 
| 
      
 50 
     | 
    
         
            +
                  <input type="submit" value="Go">
         
     | 
| 
      
 51 
     | 
    
         
            +
                </form>
         
     | 
| 
      
 52 
     | 
    
         
            +
              </section>
         
     | 
| 
      
 53 
     | 
    
         
            +
            </body>
         
     | 
| 
      
 54 
     | 
    
         
            +
            </html>
         
     | 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            var gitNotesUrl = new URL(document.currentScript.src)
         
     | 
| 
      
 2 
     | 
    
         
            +
            gitNotesUrl.pathname = "/api/notes.html"
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            $(document).ready(function() {
         
     | 
| 
      
 5 
     | 
    
         
            +
              function injectExpandScript(e, parentLabels) {
         
     | 
| 
      
 6 
     | 
    
         
            +
                e.querySelectorAll('.gitnoted-label').forEach(function (e) {
         
     | 
| 
      
 7 
     | 
    
         
            +
                  var url = new URL(gitNotesUrl)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  url.searchParams.set('labels', e.innerText)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  url.searchParams.set('exclude_labels', parentLabels)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  var nextParentLabels = `${parentLabels},${e.innerText}`
         
     | 
| 
      
 11 
     | 
    
         
            +
                  e.classList.add('gitnoted-label-button')
         
     | 
| 
      
 12 
     | 
    
         
            +
                  e.onclick = function() {
         
     | 
| 
      
 13 
     | 
    
         
            +
                    console.log(`exclude_labels: ${nextParentLabels}`)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    fetch(url, {mode: 'cors'}).then(function (r) {
         
     | 
| 
      
 15 
     | 
    
         
            +
                      return r.text()
         
     | 
| 
      
 16 
     | 
    
         
            +
                    }).then(function (t) {
         
     | 
| 
      
 17 
     | 
    
         
            +
                      var template = document.createElement('template')
         
     | 
| 
      
 18 
     | 
    
         
            +
                      template.innerHTML = t
         
     | 
| 
      
 19 
     | 
    
         
            +
                      var note = template.content.firstChild
         
     | 
| 
      
 20 
     | 
    
         
            +
                      injectExpandScript(note, nextParentLabels)
         
     | 
| 
      
 21 
     | 
    
         
            +
                      e.parentNode.parentNode.appendChild(note, e)
         
     | 
| 
      
 22 
     | 
    
         
            +
                      e.classList.remove('gitnoted-label-button')
         
     | 
| 
      
 23 
     | 
    
         
            +
                      e.onclick = null
         
     | 
| 
      
 24 
     | 
    
         
            +
                    })
         
     | 
| 
      
 25 
     | 
    
         
            +
                  }
         
     | 
| 
      
 26 
     | 
    
         
            +
                })
         
     | 
| 
      
 27 
     | 
    
         
            +
              }
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              document.querySelectorAll('div.gitnoted').forEach(function (e) {
         
     | 
| 
      
 30 
     | 
    
         
            +
                var url = new URL(gitNotesUrl)
         
     | 
| 
      
 31 
     | 
    
         
            +
                if (e.dataset.labels) {
         
     | 
| 
      
 32 
     | 
    
         
            +
                  url.searchParams.set('labels', e.dataset.labels)
         
     | 
| 
      
 33 
     | 
    
         
            +
                }
         
     | 
| 
      
 34 
     | 
    
         
            +
                fetch(url, {mode: 'cors'}).then(function (r) {
         
     | 
| 
      
 35 
     | 
    
         
            +
                  return r.text()
         
     | 
| 
      
 36 
     | 
    
         
            +
                }).then(function (t) {
         
     | 
| 
      
 37 
     | 
    
         
            +
                  var template = document.createElement('template')
         
     | 
| 
      
 38 
     | 
    
         
            +
                  template.innerHTML = t
         
     | 
| 
      
 39 
     | 
    
         
            +
                  var note = template.content.firstChild
         
     | 
| 
      
 40 
     | 
    
         
            +
                  if (e.dataset.labels) {
         
     | 
| 
      
 41 
     | 
    
         
            +
                    injectExpandScript(note, e.dataset.labels)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  }
         
     | 
| 
      
 43 
     | 
    
         
            +
                  e.parentNode.replaceChild(note, e)
         
     | 
| 
      
 44 
     | 
    
         
            +
                })
         
     | 
| 
      
 45 
     | 
    
         
            +
              })
         
     | 
| 
      
 46 
     | 
    
         
            +
            })
         
     | 
| 
         @@ -0,0 +1,148 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rugged'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'concurrent'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'pathname'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module GitNoted
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Repository
         
     | 
| 
      
 7 
     | 
    
         
            +
                class Note
         
     | 
| 
      
 8 
     | 
    
         
            +
                  def initialize(name, path, labels)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @name = name
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @path = path
         
     | 
| 
      
 11 
     | 
    
         
            +
                    @labels = labels
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  attr_reader :name, :path, :labels
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def initialize(remote_url, local_path, username: nil, password: nil, logger: Logger.new(STDERR))
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @local_path = Pathname.new(local_path).cleanpath
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @remote_url = remote_url
         
     | 
| 
      
 20 
     | 
    
         
            +
                  if username
         
     | 
| 
      
 21 
     | 
    
         
            +
                    @credentials = Rugged::Credentials::UserPassword.new(username: username, password: password)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  else
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @credentials = nil
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @logger = logger
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  # initial update
         
     | 
| 
      
 28 
     | 
    
         
            +
                  update! || index!
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                def update!
         
     | 
| 
      
 32 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 33 
     | 
    
         
            +
                    @repo ||= Rugged::Repository.init_at(@local_path.to_s)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    updated = fetch(@repo)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    return false unless updated
         
     | 
| 
      
 36 
     | 
    
         
            +
                  rescue => e
         
     | 
| 
      
 37 
     | 
    
         
            +
                    # fall back to clone.
         
     | 
| 
      
 38 
     | 
    
         
            +
                    @logger.warn "Failed to update repository incrementally. Falling back to clone: #{e}"
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
                  @repo = clone
         
     | 
| 
      
 41 
     | 
    
         
            +
                  index!
         
     | 
| 
      
 42 
     | 
    
         
            +
                  return true
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                def read(note)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  File.read(note.path).sub(/^:label:(.*)$\n/, '')
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def schedule_update!(interval)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  Concurrent::ScheduledTask.execute(interval) do
         
     | 
| 
      
 51 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 52 
     | 
    
         
            +
                      update!
         
     | 
| 
      
 53 
     | 
    
         
            +
                    rescue => e
         
     | 
| 
      
 54 
     | 
    
         
            +
                      @logger.error "Failed to update repository: #{e}"
         
     | 
| 
      
 55 
     | 
    
         
            +
                      e.backtrace.each do |bt|
         
     | 
| 
      
 56 
     | 
    
         
            +
                        @logger.error "  #{bt}"
         
     | 
| 
      
 57 
     | 
    
         
            +
                      end
         
     | 
| 
      
 58 
     | 
    
         
            +
                    ensure
         
     | 
| 
      
 59 
     | 
    
         
            +
                      schedule_update!(interval)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    end
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                def search_notes(labels: nil, exclude_labels: nil)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  labels ||= []
         
     | 
| 
      
 66 
     | 
    
         
            +
                  exclude_labels ||= []
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                  @notes.select do |note|
         
     | 
| 
      
 69 
     | 
    
         
            +
                    labels.all? {|t| note.labels.include?(t) } &&
         
     | 
| 
      
 70 
     | 
    
         
            +
                      !exclude_labels.any? {|t| note.labels.include?(t) }
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                def search_labels(prefix: nil, used_with: nil)
         
     | 
| 
      
 75 
     | 
    
         
            +
                  match = {}
         
     | 
| 
      
 76 
     | 
    
         
            +
                  @notes.each do |note|
         
     | 
| 
      
 77 
     | 
    
         
            +
                    if used_with.nil? || used_with.all? {|t| note.labels.include?(t) }
         
     | 
| 
      
 78 
     | 
    
         
            +
                      if prefix.nil?
         
     | 
| 
      
 79 
     | 
    
         
            +
                        matching = note.labels
         
     | 
| 
      
 80 
     | 
    
         
            +
                      else
         
     | 
| 
      
 81 
     | 
    
         
            +
                        matching = note.labels.select {|label| label.start_with?(prefix) }
         
     | 
| 
      
 82 
     | 
    
         
            +
                      end
         
     | 
| 
      
 83 
     | 
    
         
            +
                      matching.each {|label| match[label] = true }
         
     | 
| 
      
 84 
     | 
    
         
            +
                    end
         
     | 
| 
      
 85 
     | 
    
         
            +
                  end
         
     | 
| 
      
 86 
     | 
    
         
            +
                  match.keys.sort
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                private
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                def clone
         
     | 
| 
      
 92 
     | 
    
         
            +
                  logger_timer "Cloning remote repository." do
         
     | 
| 
      
 93 
     | 
    
         
            +
                    tmp_path = "#{@local_path}.tmp"
         
     | 
| 
      
 94 
     | 
    
         
            +
                    FileUtils.rm_rf tmp_path
         
     | 
| 
      
 95 
     | 
    
         
            +
                    Rugged::Repository.clone_at(@remote_url, tmp_path, credentials: @credentials)
         
     | 
| 
      
 96 
     | 
    
         
            +
                    FileUtils.rm_rf @local_path
         
     | 
| 
      
 97 
     | 
    
         
            +
                    FileUtils.mv tmp_path, @local_path
         
     | 
| 
      
 98 
     | 
    
         
            +
                    Rugged::Repository.init_at(@local_path.to_s)
         
     | 
| 
      
 99 
     | 
    
         
            +
                  end
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                def fetch(repo)
         
     | 
| 
      
 103 
     | 
    
         
            +
                  logger_timer "Fetching remote repository." do
         
     | 
| 
      
 104 
     | 
    
         
            +
                    remote = repo.remotes["origin"]
         
     | 
| 
      
 105 
     | 
    
         
            +
                    unless remote
         
     | 
| 
      
 106 
     | 
    
         
            +
                      raise "Remote repository is not fetched yet."
         
     | 
| 
      
 107 
     | 
    
         
            +
                    end
         
     | 
| 
      
 108 
     | 
    
         
            +
                    fetched = remote.fetch
         
     | 
| 
      
 109 
     | 
    
         
            +
                    return fetched[:total_objects] > 0
         
     | 
| 
      
 110 
     | 
    
         
            +
                  end
         
     | 
| 
      
 111 
     | 
    
         
            +
                end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                def index!
         
     | 
| 
      
 114 
     | 
    
         
            +
                  logger_timer "Updating label index." do
         
     | 
| 
      
 115 
     | 
    
         
            +
                    files = Dir["#{@local_path}/**/*.md"]
         
     | 
| 
      
 116 
     | 
    
         
            +
                    @notes = files.map do |path|
         
     | 
| 
      
 117 
     | 
    
         
            +
                      name = Pathname.new(path).relative_path_from(Pathname.new(@local_path)).sub(/\.md$/, '')
         
     | 
| 
      
 118 
     | 
    
         
            +
                      parse_note(name, path, File.read(path))
         
     | 
| 
      
 119 
     | 
    
         
            +
                    end
         
     | 
| 
      
 120 
     | 
    
         
            +
                  end
         
     | 
| 
      
 121 
     | 
    
         
            +
                end
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                LABEL_KEY_CHARSET = /[a-zA-Z0-9_\-\.\/]/
         
     | 
| 
      
 124 
     | 
    
         
            +
                LABEL_VALUE_CHARSET = /[a-zA-Z0-9_\-\.\/]/
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                def parse_note(name, path, text)
         
     | 
| 
      
 127 
     | 
    
         
            +
                  m = /^:label:(.*)$/.match(text)
         
     | 
| 
      
 128 
     | 
    
         
            +
                  if m
         
     | 
| 
      
 129 
     | 
    
         
            +
                    labels = m[1].scan(/[a-zA-Z0-9_\-\.\/]+:[a-zA-Z0-9_\-\.\/]+/)
         
     | 
| 
      
 130 
     | 
    
         
            +
                  else
         
     | 
| 
      
 131 
     | 
    
         
            +
                    labels = []
         
     | 
| 
      
 132 
     | 
    
         
            +
                  end
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                  Note.new(name, path, labels)
         
     | 
| 
      
 135 
     | 
    
         
            +
                end
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                def logger_timer(start_message, end_message = "%.2f seconds.")
         
     | 
| 
      
 138 
     | 
    
         
            +
                  @logger.info start_message
         
     | 
| 
      
 139 
     | 
    
         
            +
                  start_time = Time.now
         
     | 
| 
      
 140 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 141 
     | 
    
         
            +
                    return yield
         
     | 
| 
      
 142 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 143 
     | 
    
         
            +
                    finish_time = Time.now
         
     | 
| 
      
 144 
     | 
    
         
            +
                    @logger.info end_message % (finish_time - start_time)
         
     | 
| 
      
 145 
     | 
    
         
            +
                  end
         
     | 
| 
      
 146 
     | 
    
         
            +
                end
         
     | 
| 
      
 147 
     | 
    
         
            +
              end
         
     | 
| 
      
 148 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,171 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: gitnoted
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.1.0
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Sadayuki Furuhashi
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2017-03-13 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              name: sinatra
         
     | 
| 
      
 15 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 16 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 17 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 18 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 19 
     | 
    
         
            +
                    version: '1.4'
         
     | 
| 
      
 20 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 21 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 22 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 23 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 24 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 25 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 26 
     | 
    
         
            +
                    version: '1.4'
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 28 
     | 
    
         
            +
              name: puma
         
     | 
| 
      
 29 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 30 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 31 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: '3.7'
         
     | 
| 
      
 34 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 35 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 36 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 37 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 38 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 39 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 40 
     | 
    
         
            +
                    version: '3.7'
         
     | 
| 
      
 41 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 42 
     | 
    
         
            +
              name: rack-cors
         
     | 
| 
      
 43 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 44 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 45 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 46 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 47 
     | 
    
         
            +
                    version: '0.4'
         
     | 
| 
      
 48 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 49 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 50 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 51 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 52 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 53 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 54 
     | 
    
         
            +
                    version: '0.4'
         
     | 
| 
      
 55 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 56 
     | 
    
         
            +
              name: redcarpet
         
     | 
| 
      
 57 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 58 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 59 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 60 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 61 
     | 
    
         
            +
                    version: '3.4'
         
     | 
| 
      
 62 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 63 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 64 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 65 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 66 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 67 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 68 
     | 
    
         
            +
                    version: '3.4'
         
     | 
| 
      
 69 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 70 
     | 
    
         
            +
              name: rugged
         
     | 
| 
      
 71 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 72 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 73 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 74 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 75 
     | 
    
         
            +
                    version: '0.25'
         
     | 
| 
      
 76 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 77 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 78 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 79 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 80 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 81 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 82 
     | 
    
         
            +
                    version: '0.25'
         
     | 
| 
      
 83 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 84 
     | 
    
         
            +
              name: concurrent-ruby
         
     | 
| 
      
 85 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 86 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 87 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 88 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 89 
     | 
    
         
            +
                    version: 1.0.5
         
     | 
| 
      
 90 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 91 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 92 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 93 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 94 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 95 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 96 
     | 
    
         
            +
                    version: 1.0.5
         
     | 
| 
      
 97 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 98 
     | 
    
         
            +
              name: sigdump
         
     | 
| 
      
 99 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 100 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 101 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 102 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 103 
     | 
    
         
            +
                    version: 0.2.4
         
     | 
| 
      
 104 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 105 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 106 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 107 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 108 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 109 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 110 
     | 
    
         
            +
                    version: 0.2.4
         
     | 
| 
      
 111 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 112 
     | 
    
         
            +
              name: rake
         
     | 
| 
      
 113 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 114 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 115 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 116 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 117 
     | 
    
         
            +
                    version: 0.9.2
         
     | 
| 
      
 118 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 119 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 120 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 121 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 122 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 123 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 124 
     | 
    
         
            +
                    version: 0.9.2
         
     | 
| 
      
 125 
     | 
    
         
            +
            description: Simple document server that works with Github Wiki or Gollum to serve
         
     | 
| 
      
 126 
     | 
    
         
            +
              foot notes for external websites just by adding a small script tag
         
     | 
| 
      
 127 
     | 
    
         
            +
            email:
         
     | 
| 
      
 128 
     | 
    
         
            +
            - frsyuki@gmail.com
         
     | 
| 
      
 129 
     | 
    
         
            +
            executables:
         
     | 
| 
      
 130 
     | 
    
         
            +
            - gitnoted
         
     | 
| 
      
 131 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 132 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 133 
     | 
    
         
            +
            files:
         
     | 
| 
      
 134 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 135 
     | 
    
         
            +
            - Gemfile.lock
         
     | 
| 
      
 136 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 137 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 138 
     | 
    
         
            +
            - bin/gitnoted
         
     | 
| 
      
 139 
     | 
    
         
            +
            - gitnoted.gemspec
         
     | 
| 
      
 140 
     | 
    
         
            +
            - lib/git_noted.rb
         
     | 
| 
      
 141 
     | 
    
         
            +
            - lib/git_noted/application.rb
         
     | 
| 
      
 142 
     | 
    
         
            +
            - lib/git_noted/public/css/gitnoted.css
         
     | 
| 
      
 143 
     | 
    
         
            +
            - lib/git_noted/public/index.html
         
     | 
| 
      
 144 
     | 
    
         
            +
            - lib/git_noted/public/js/gitnoted.js
         
     | 
| 
      
 145 
     | 
    
         
            +
            - lib/git_noted/repository.rb
         
     | 
| 
      
 146 
     | 
    
         
            +
            homepage: https://github.com/frsyuki/gitnoted
         
     | 
| 
      
 147 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 148 
     | 
    
         
            +
            - MIT
         
     | 
| 
      
 149 
     | 
    
         
            +
            metadata: {}
         
     | 
| 
      
 150 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 151 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 152 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 153 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 154 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 155 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 156 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 157 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 158 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 159 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 160 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 161 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 162 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 163 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 164 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 165 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 166 
     | 
    
         
            +
            rubygems_version: 2.6.8
         
     | 
| 
      
 167 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 168 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 169 
     | 
    
         
            +
            summary: Simple document server that works with Github Wiki or Gollum to serve foot
         
     | 
| 
      
 170 
     | 
    
         
            +
              notes for external websites just by adding a small script tag
         
     | 
| 
      
 171 
     | 
    
         
            +
            test_files: []
         
     |