newport 1.0.1 → 1.0.6
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 +4 -4
- data/README.md +16 -7
- data/exe/newport +0 -18
- data/lib/newport.rb +35 -0
- data/lib/newport/build.rb +87 -0
- data/lib/newport/help.rb +13 -0
- data/lib/newport/logger.rb +8 -0
- data/lib/newport/new.rb +69 -0
- data/lib/newport/version.rb +5 -0
- data/lib/site_template/config.yml +7 -0
- data/lib/site_template/javascript/js.cookie.min.js +2 -0
- data/lib/site_template/layouts/footer.html +10 -0
- data/lib/site_template/layouts/head.html +9 -0
- data/lib/site_template/layouts/main.html +16 -0
- data/lib/site_template/layouts/nav.html +5 -0
- data/lib/site_template/layouts/style.css +101 -0
- data/lib/site_template/plugins/darkmode.js +35 -0
- data/lib/site_template/plugins/expander.js +29 -0
- data/lib/site_template/plugins/pagination.js +30 -0
- data/lib/site_template/plugins/permalink.js +42 -0
- data/lib/site_template/posts/202107211703_digital-ocean-static-site-hosting.md +14 -0
- metadata +20 -22
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: e111cd4c09644217b541f2a4a54ff5be9b20f2fad5ce8819a821a0cb77f2a657
         | 
| 4 | 
            +
              data.tar.gz: '0862e9f1354dc4ac499c2a00f548fbe60f507a4cf25f5fd265e05f333fac8a52'
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: f6f8f1d31101f91d3bc1c25f7b82d243fabe4b2ff761df354333d283db88f7c439e1f9b8ec1c16e30385c80b6c1c92fa779a13703934e69b096b51b8f0626a34
         | 
| 7 | 
            +
              data.tar.gz: 531cee4fbafa6b18c405d520fc658b4530e5024473545725250226de4f8be966180e971aeb32a6788b59a8f5548c8f85cb9daa645b4c14ba79c30db414b4502b
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,16 +1,25 @@ | |
| 1 | 
            +
            [https://richard.fisher.cymru](https://richard.fisher.cymru)
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            # Newport
         | 
| 2 | 
            -
            Newport is a  | 
| 4 | 
            +
            Newport is a Ruby Gem for building a single file blog/static site.
         | 
| 3 5 |  | 
| 4 6 | 
             
            ## Getting Started
         | 
| 5 | 
            -
            -  | 
| 6 | 
            -
            -  | 
| 7 | 
            -
            -  | 
| 8 | 
            -
            -  | 
| 9 | 
            -
            - Modify the layouts and add some posts
         | 
| 10 | 
            -
            - Run `bundle exec ruby build.rb`
         | 
| 7 | 
            +
            - `gem install newport`
         | 
| 8 | 
            +
            - `newport new <path>`
         | 
| 9 | 
            +
            - `cd <path>`
         | 
| 10 | 
            +
            - `newport build`
         | 
| 11 11 |  | 
| 12 12 | 
             
            ## Plugins
         | 
| 13 13 | 
             
            Plugins are available in the plugins directory and are pure javascript. Plugins are run after the page loads and can modify the contents.  
         | 
| 14 14 |  | 
| 15 15 | 
             
            ### Expander
         | 
| 16 16 | 
             
            For example the expander plugin will loop through your posts and show n number of paragraphs for each one and hide the rest, adding a down arrow to click to expand and show the full post.
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            ### Pagination
         | 
| 19 | 
            +
            Set the variable show in pagination.js to the number of posts you want to display per page.  The plugin will automatically add an arrow to click to show more.
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            ### Permalinks
         | 
| 22 | 
            +
            Add a hash to the end of each post that links to the permanent location for that post.
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            ### Dark Mode
         | 
| 25 | 
            +
            Shows a light/dark toggle to toggle between light mode and dark mode.  It uses cookies to remember your selection.  There are some css variables that you can change for light/dark mode in style.css
         | 
    
        data/exe/newport
    CHANGED
    
    | @@ -17,21 +17,3 @@ when 'build' | |
| 17 17 | 
             
            else
         | 
| 18 18 | 
             
              Newport.logger.abort_with "fatal: 'newport #{ARGV.first}' could not be found.".red
         | 
| 19 19 | 
             
            end
         | 
| 20 | 
            -
             | 
| 21 | 
            -
            # Mercenary.program(:newport) do |p|
         | 
| 22 | 
            -
            #   p.version Newport::VERSION
         | 
| 23 | 
            -
            #   p.description 'Newport is a static site blog generator written in Ruby'
         | 
| 24 | 
            -
            #   p.syntax 'newport <command>'
         | 
| 25 | 
            -
             | 
| 26 | 
            -
            #   Newport::Command.subclasses.each { |c| c.init_with_program(p) }
         | 
| 27 | 
            -
             | 
| 28 | 
            -
            #   p.action do |args, _|
         | 
| 29 | 
            -
            #     if args.empty?
         | 
| 30 | 
            -
            #       Newport.logger.error 'A subcommand is required.'
         | 
| 31 | 
            -
            #       abort
         | 
| 32 | 
            -
            #     else
         | 
| 33 | 
            -
            #       subcommand = args.first
         | 
| 34 | 
            -
            #       Newport.logger.abort_with "fatal: 'newport #{args.first}' could not be found." unless p.has_command? subcommand
         | 
| 35 | 
            -
            #     end
         | 
| 36 | 
            -
            #   end
         | 
| 37 | 
            -
            # end
         | 
    
        data/lib/newport.rb
    ADDED
    
    | @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            $LOAD_PATH.unshift __dir__ # For use/testing when no gem is installed
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            def require_all(path)
         | 
| 6 | 
            +
              glob = File.join(__dir__, path, '*.rb')
         | 
| 7 | 
            +
              Dir[glob].each do |f|
         | 
| 8 | 
            +
                require f
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
            end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            require 'rubygems'
         | 
| 13 | 
            +
            require 'fileutils'
         | 
| 14 | 
            +
            require 'time'
         | 
| 15 | 
            +
            require 'logger'
         | 
| 16 | 
            +
            require 'colorator'
         | 
| 17 | 
            +
            require 'kramdown'
         | 
| 18 | 
            +
            require 'rss'
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            module Newport
         | 
| 21 | 
            +
              autoload :VERSION, 'newport/version'
         | 
| 22 | 
            +
              autoload :Help,    'newport/help'
         | 
| 23 | 
            +
              autoload :New,     'newport/new'
         | 
| 24 | 
            +
              autoload :Build,   'newport/build'
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              require 'newport/logger'
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              class << self
         | 
| 29 | 
            +
                def logger
         | 
| 30 | 
            +
                  @logger ||= Logger.new($stdout)
         | 
| 31 | 
            +
                  @logger.formatter = proc { |_severity, _datetime, _progname, msg| "#{msg}\n" }
         | 
| 32 | 
            +
                  @logger
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
            end
         | 
| @@ -0,0 +1,87 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Newport
         | 
| 4 | 
            +
              class Build
         | 
| 5 | 
            +
                class << self
         | 
| 6 | 
            +
                  def process(args)
         | 
| 7 | 
            +
                    show_help if args[1] == 'help'
         | 
| 8 | 
            +
                    build_blog
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  private
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  def show_help
         | 
| 14 | 
            +
                    Newport.logger.info "Newport #{Newport::VERSION}"
         | 
| 15 | 
            +
                    Newport.logger.info 'usage: newport build'
         | 
| 16 | 
            +
                    abort
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  def build_blog
         | 
| 20 | 
            +
                    html = content_from_layouts
         | 
| 21 | 
            +
                    html = add_javascript html
         | 
| 22 | 
            +
                    html = add_plugins html
         | 
| 23 | 
            +
                    html = add_posts(html, build_posts)
         | 
| 24 | 
            +
                    html = replcae_tags html
         | 
| 25 | 
            +
                    write_html html
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def config
         | 
| 29 | 
            +
                    @config ||= YAML.load_file('config.yml')
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  def content_from_layouts
         | 
| 33 | 
            +
                    head       = File.read('layouts/head.html')
         | 
| 34 | 
            +
                    style      = File.read('layouts/style.css')
         | 
| 35 | 
            +
                    head       = head.gsub('<!-- style -->', "<style>#{style}</style>")
         | 
| 36 | 
            +
                    nav        = File.read('layouts/nav.html')
         | 
| 37 | 
            +
                    main       = File.read('layouts/main.html')
         | 
| 38 | 
            +
                    footer     = File.read('layouts/footer.html')
         | 
| 39 | 
            +
                    main.gsub('<!-- head -->', head).gsub('<!-- nav -->', nav).gsub('<!-- footer -->', footer)
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  def add_javascript(html)
         | 
| 43 | 
            +
                    jss = []
         | 
| 44 | 
            +
                    Dir.glob('javascript/*.js') { |filename| jss << File.open(filename).read }
         | 
| 45 | 
            +
                    html.gsub('<!-- javascript -->', "<script>#{jss.join}</script>")
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  def add_plugins(html)
         | 
| 49 | 
            +
                    plugins = []
         | 
| 50 | 
            +
                    config['plugins'].each do |p|
         | 
| 51 | 
            +
                      plugin = File.open("plugins/#{p}.js").read
         | 
| 52 | 
            +
                      plugins << plugin
         | 
| 53 | 
            +
                    end
         | 
| 54 | 
            +
                    html.gsub('<!-- plugins -->', "<script>#{plugins.join}</script>")
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  def build_posts
         | 
| 58 | 
            +
                    files = []
         | 
| 59 | 
            +
                    posts = []
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    Dir.glob('posts/*.md') { |filename| files << filename.split('/').last }
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                    files.reverse.each do |filename|
         | 
| 64 | 
            +
                      post = '<article>' + Kramdown::Document.new(File.open("posts/#{filename}").read).to_html + '</article>'
         | 
| 65 | 
            +
                      posts << post
         | 
| 66 | 
            +
                    end
         | 
| 67 | 
            +
                    posts
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                  def add_posts(html, posts)
         | 
| 71 | 
            +
                    html.gsub('<!-- posts -->', posts.join)
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                  def replcae_tags(html)
         | 
| 75 | 
            +
                    html = html.gsub('<!-- email -->', config['email'])
         | 
| 76 | 
            +
                    html.gsub('<!-- title -->', config['title'])
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                  def write_html(html)
         | 
| 80 | 
            +
                    FileUtils.mkdir_p 'production/images'
         | 
| 81 | 
            +
                    File.open('production/index.html', 'w') do |f|
         | 
| 82 | 
            +
                      f.write html
         | 
| 83 | 
            +
                    end
         | 
| 84 | 
            +
                  end
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
              end
         | 
| 87 | 
            +
            end
         | 
    
        data/lib/newport/help.rb
    ADDED
    
    | @@ -0,0 +1,13 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Newport
         | 
| 4 | 
            +
              class Help
         | 
| 5 | 
            +
                class << self
         | 
| 6 | 
            +
                  def show
         | 
| 7 | 
            +
                    Newport.logger.info "Newport #{Newport::VERSION}"
         | 
| 8 | 
            +
                    Newport.logger.info 'usage: newport [command] [options]'
         | 
| 9 | 
            +
                    Newport.logger.info 'commands: new, build, help'
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
            end
         | 
    
        data/lib/newport/new.rb
    ADDED
    
    | @@ -0,0 +1,69 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Newport
         | 
| 4 | 
            +
              class New
         | 
| 5 | 
            +
                class << self
         | 
| 6 | 
            +
                  def process(args)
         | 
| 7 | 
            +
                    Newport.logger.abort_with 'fatal: please specify path.'.red unless args[1]
         | 
| 8 | 
            +
                    show_help if args[1] == 'help'
         | 
| 9 | 
            +
                    create_blog args[1]
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  private
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  def show_help
         | 
| 15 | 
            +
                    Newport.logger.info "Newport #{Newport::VERSION}"
         | 
| 16 | 
            +
                    Newport.logger.info 'usage: newport new [path]'
         | 
| 17 | 
            +
                    abort
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  def create_blog(path)
         | 
| 21 | 
            +
                    blog_path = File.expand_path(path, Dir.pwd)
         | 
| 22 | 
            +
                    FileUtils.mkdir_p blog_path
         | 
| 23 | 
            +
                    FileUtils.cp_r "#{template}/.", path
         | 
| 24 | 
            +
                    FileUtils.chmod_R 'u+w', path
         | 
| 25 | 
            +
                    File.open(File.expand_path('Gemfile', path), 'w') do |f|
         | 
| 26 | 
            +
                      f.write(gemfile_contents)
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                    after_install path
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  def template
         | 
| 32 | 
            +
                    File.expand_path('../site_template', __dir__)
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  def gemfile_contents
         | 
| 36 | 
            +
                    <<~RUBY
         | 
| 37 | 
            +
                      source "https://rubygems.org"
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                      gem "newport", "~> #{Newport::VERSION}"
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                      # Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
         | 
| 42 | 
            +
                      # and associated library.
         | 
| 43 | 
            +
                      platforms :mingw, :x64_mingw, :mswin, :jruby do
         | 
| 44 | 
            +
                        gem "tzinfo", "~> 1.2"
         | 
| 45 | 
            +
                        gem "tzinfo-data"
         | 
| 46 | 
            +
                      end
         | 
| 47 | 
            +
                    RUBY
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                  def after_install(path)
         | 
| 51 | 
            +
                    begin
         | 
| 52 | 
            +
                      require 'bundler'
         | 
| 53 | 
            +
                      bundle_install path
         | 
| 54 | 
            +
                    rescue LoadError
         | 
| 55 | 
            +
                      Newport.logger.info 'Could not load Bundler. Bundle install skipped.'
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                    Newport.logger.info "New Newport site installed in #{path.cyan}."
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  def bundle_install(path)
         | 
| 62 | 
            +
                    Newport.logger.info "Running bundle install in #{path.cyan}..."
         | 
| 63 | 
            +
                    Dir.chdir(path) do
         | 
| 64 | 
            +
                      system('bundle')
         | 
| 65 | 
            +
                    end
         | 
| 66 | 
            +
                  end
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
              end
         | 
| 69 | 
            +
            end
         | 
| @@ -0,0 +1,2 @@ | |
| 1 | 
            +
            /*! js-cookie v3.0.0-rc.1 | MIT */
         | 
| 2 | 
            +
            !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self,function(){var n=e.Cookies,r=e.Cookies=t();r.noConflict=function(){return e.Cookies=n,r}}())}(this,function(){"use strict";function e(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)e[r]=n[r]}return e}var t={read:function(e){return e.replace(/(%[\dA-F]{2})+/gi,decodeURIComponent)},write:function(e){return encodeURIComponent(e).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,decodeURIComponent)}};return function n(r,o){function i(t,n,i){if("undefined"!=typeof document){"number"==typeof(i=e({},o,i)).expires&&(i.expires=new Date(Date.now()+864e5*i.expires)),i.expires&&(i.expires=i.expires.toUTCString()),t=encodeURIComponent(t).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape),n=r.write(n,t);var c="";for(var u in i)i[u]&&(c+="; "+u,!0!==i[u]&&(c+="="+i[u].split(";")[0]));return document.cookie=t+"="+n+c}}return Object.create({set:i,get:function(e){if("undefined"!=typeof document&&(!arguments.length||e)){for(var n=document.cookie?document.cookie.split("; "):[],o={},i=0;i<n.length;i++){var c=n[i].split("="),u=c.slice(1).join("=");'"'===u[0]&&(u=u.slice(1,-1));try{var f=t.read(c[0]);if(o[f]=r.read(u,f),e===f)break}catch(e){}}return e?o[e]:o}},remove:function(t,n){i(t,"",e({},n,{expires:-1}))},withAttributes:function(t){return n(this.converter,e({},this.attributes,t))},withConverter:function(t){return n(e({},this.converter,t),this.attributes)}},{attributes:{value:Object.freeze(o)},converter:{value:Object.freeze(r)}})}(t,{path:"/"})});
         | 
| @@ -0,0 +1,101 @@ | |
| 1 | 
            +
            html{height:100%}
         | 
| 2 | 
            +
            body{margin:0;padding:0 0.5em;background-color: var(--background-color);color: var(--text-color);height:100%}
         | 
| 3 | 
            +
            .container{max-width:768px;margin:auto;padding-left:5px;padding-right:5px}
         | 
| 4 | 
            +
            body{font-family:monospace;font-size:1.1rem;line-height:1.2rem;}
         | 
| 5 | 
            +
            a,a:active,a:visited{color:#1FC5FF;text-decoration:none}
         | 
| 6 | 
            +
            article h1 {margin-bottom:3px;color:var(--h1-color)}
         | 
| 7 | 
            +
            article h2 {margin-top:-1em;color:#EA4D89;font-weight:normal;font-size:0.85rem;margin: 0}
         | 
| 8 | 
            +
            pre{white-space: pre-wrap}
         | 
| 9 | 
            +
            article{margin-bottom:3em}
         | 
| 10 | 
            +
            nav{text-align:right;padding-top:0.5rem}
         | 
| 11 | 
            +
            article img{margin: auto;display: block}
         | 
| 12 | 
            +
            article blockquote{margin-left:25px;border-left:10px #ddd solid;padding-left:15px;white-space: pre-wrap}
         | 
| 13 | 
            +
            img{max-width: 100%;}
         | 
| 14 | 
            +
            h1 a,h1 a:active,h1 a:visited{color:var(--h1-color)}
         | 
| 15 | 
            +
            .title{float:left;padding-top:0.5rem}
         | 
| 16 | 
            +
            section{margin-top:2rem}
         | 
| 17 | 
            +
            #darkmode{display:inline}
         | 
| 18 | 
            +
            .expander-arrow, .more-arrow, .more-arrow:active, .more-arrow:visited { color: var(--text-color); fill: var(--text-color) }
         | 
| 19 | 
            +
            footer {border-top: 1px var(--footer-border-color) solid;min-height: 80px;padding-top: 10px;padding-bottom:15px}
         | 
| 20 | 
            +
            .main {min-height: calc(100% - 40px)}
         | 
| 21 | 
            +
            code{background:var(--code-background-color);padding-left:2px;padding-right:2px}
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            :root {
         | 
| 24 | 
            +
                --background-color: #fafafa;
         | 
| 25 | 
            +
                --text-color: #111;
         | 
| 26 | 
            +
                --code-background-color: #ccc;
         | 
| 27 | 
            +
                --footer-border-color: #ccc;
         | 
| 28 | 
            +
                --h1-color: #111;
         | 
| 29 | 
            +
            }
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            [data-theme="dark"] {
         | 
| 32 | 
            +
                --background-color: #0D1117;
         | 
| 33 | 
            +
                --text-color: #8B949E;
         | 
| 34 | 
            +
                --code-background-color: #888;
         | 
| 35 | 
            +
                --footer-border-color: #555;
         | 
| 36 | 
            +
                --h1-color: #ddd;
         | 
| 37 | 
            +
            }
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            /* The switch - the box around the slider */
         | 
| 40 | 
            +
            .switch {
         | 
| 41 | 
            +
            position: relative;
         | 
| 42 | 
            +
            display: inline-block;
         | 
| 43 | 
            +
            width: 30px;
         | 
| 44 | 
            +
            height: 17px;
         | 
| 45 | 
            +
            }
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            /* Hide default HTML checkbox */
         | 
| 48 | 
            +
            .switch input {
         | 
| 49 | 
            +
            opacity: 0;
         | 
| 50 | 
            +
            width: 0;
         | 
| 51 | 
            +
            height: 0;
         | 
| 52 | 
            +
            }
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            /* The slider */
         | 
| 55 | 
            +
            .slider {
         | 
| 56 | 
            +
            position: absolute;
         | 
| 57 | 
            +
            cursor: pointer;
         | 
| 58 | 
            +
            top: 0;
         | 
| 59 | 
            +
            left: 0;
         | 
| 60 | 
            +
            right: 0;
         | 
| 61 | 
            +
            bottom: 0;
         | 
| 62 | 
            +
            background-color: #ccc;
         | 
| 63 | 
            +
            -webkit-transition: .4s;
         | 
| 64 | 
            +
            transition: .4s;
         | 
| 65 | 
            +
            }
         | 
| 66 | 
            +
             | 
| 67 | 
            +
            .slider:before {
         | 
| 68 | 
            +
            position: absolute;
         | 
| 69 | 
            +
            content: "";
         | 
| 70 | 
            +
            height: 13px;
         | 
| 71 | 
            +
            width: 13px;
         | 
| 72 | 
            +
            left: 2px;
         | 
| 73 | 
            +
            bottom: 2px;
         | 
| 74 | 
            +
            background-color: white;
         | 
| 75 | 
            +
            -webkit-transition: .4s;
         | 
| 76 | 
            +
            transition: .4s;
         | 
| 77 | 
            +
            color: #000;
         | 
| 78 | 
            +
            }
         | 
| 79 | 
            +
             | 
| 80 | 
            +
            input:checked + .slider {
         | 
| 81 | 
            +
            background-color: #333;
         | 
| 82 | 
            +
            }
         | 
| 83 | 
            +
             | 
| 84 | 
            +
            input:focus + .slider {
         | 
| 85 | 
            +
            box-shadow: 0 0 1px #333;
         | 
| 86 | 
            +
            }
         | 
| 87 | 
            +
             | 
| 88 | 
            +
            input:checked + .slider:before {
         | 
| 89 | 
            +
            -webkit-transform: translateX(13px);
         | 
| 90 | 
            +
            -ms-transform: translateX(13px);
         | 
| 91 | 
            +
            transform: translateX(13px);
         | 
| 92 | 
            +
            }
         | 
| 93 | 
            +
             | 
| 94 | 
            +
            /* Rounded sliders */
         | 
| 95 | 
            +
            .slider.round {
         | 
| 96 | 
            +
            border-radius: 17px;
         | 
| 97 | 
            +
            }
         | 
| 98 | 
            +
             | 
| 99 | 
            +
            .slider.round:before {
         | 
| 100 | 
            +
            border-radius: 50%;
         | 
| 101 | 
            +
            }
         | 
| @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            // Place an empty div with the id darkmode where you want to toggle to appear in your html
         | 
| 2 | 
            +
            // ie. <div id="darkmode"></div>
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            (function() {
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              function showDark() {
         | 
| 7 | 
            +
                document.documentElement.setAttribute("data-theme", "dark");
         | 
| 8 | 
            +
                Cookies.set('appearance', 'dark');
         | 
| 9 | 
            +
              }
         | 
| 10 | 
            +
              
         | 
| 11 | 
            +
              function showLight() {
         | 
| 12 | 
            +
                document.documentElement.setAttribute("data-theme", "light");
         | 
| 13 | 
            +
                Cookies.set('appearance', 'light');
         | 
| 14 | 
            +
              }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              var appearance = Cookies.get('appearance')
         | 
| 17 | 
            +
              document.getElementById("darkmode").innerHTML = '<span style="color: orangered">☼</span>/<span style="color: #888">☽</span><label class="switch"><input type="checkbox" name="darkmode" id="darkmode-checkbox"/><span class="slider round"></span></label>';
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              if (appearance == 'dark') {
         | 
| 20 | 
            +
                document.getElementById('darkmode-checkbox').checked = true;
         | 
| 21 | 
            +
                showDark();
         | 
| 22 | 
            +
              } else if (appearance == 'light') {
         | 
| 23 | 
            +
                document.getElementById('darkmode-checkbox').checked = false;
         | 
| 24 | 
            +
                showLight();
         | 
| 25 | 
            +
              }
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              document.getElementById("darkmode-checkbox").onchange = function(){
         | 
| 28 | 
            +
                if (document.getElementById('darkmode-checkbox').checked) {
         | 
| 29 | 
            +
                  showDark();
         | 
| 30 | 
            +
                } else {
         | 
| 31 | 
            +
                  showLight();
         | 
| 32 | 
            +
                }
         | 
| 33 | 
            +
              };
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            })();
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            (function() {
         | 
| 2 | 
            +
                const show = 1; // The number of paragraphs to show for each article/post
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                var articles = document.getElementsByTagName("article");
         | 
| 5 | 
            +
                for(var i = 0; i < articles.length; i++){
         | 
| 6 | 
            +
                    var paras = articles[i].getElementsByTagName("p");
         | 
| 7 | 
            +
                    if (paras.length > show) {
         | 
| 8 | 
            +
                        // We have more paragraphs than we want to show
         | 
| 9 | 
            +
                        var r = Math.random().toString(36).substring(7);
         | 
| 10 | 
            +
                        // Now loop through the paragraphs
         | 
| 11 | 
            +
                        for(var j = 0; j < paras.length; j++){
         | 
| 12 | 
            +
                            if (j >= show) {
         | 
| 13 | 
            +
                                paras[j].setAttribute("style", 'display:none');
         | 
| 14 | 
            +
                                paras[j].setAttribute("class", r);
         | 
| 15 | 
            +
                            }
         | 
| 16 | 
            +
                        }
         | 
| 17 | 
            +
                        let expander = document.createElement('a');
         | 
| 18 | 
            +
                        expander.innerHTML = '<svg style="height: 10px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/></svg>';
         | 
| 19 | 
            +
                        var expand_function = 'var elms = document.getElementsByClassName("'+r+'"); for(var k = 0; k < elms.length; k++) { elms[k].setAttribute("style", "display:block") } document.getElementById("link_'+r+'").setAttribute("style", "display:none"); return false;';
         | 
| 20 | 
            +
                        expander.setAttribute('onclick', expand_function);
         | 
| 21 | 
            +
                        expander.setAttribute('href', "#");
         | 
| 22 | 
            +
                        expander.setAttribute("id", 'link_'+r);
         | 
| 23 | 
            +
                        expander.setAttribute("style", 'color: #000');
         | 
| 24 | 
            +
                        expander.setAttribute("class", 'expander-arrow');
         | 
| 25 | 
            +
                        expander.setAttribute("title", 'Click to expand text');
         | 
| 26 | 
            +
                        paras[show].parentNode.insertBefore(expander, paras[show]);
         | 
| 27 | 
            +
                    }
         | 
| 28 | 
            +
                }
         | 
| 29 | 
            +
            })();
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
             | 
| 2 | 
            +
            const show = 10; // The number of posts to show per page
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            function showPage(offset) {
         | 
| 5 | 
            +
                // Avoid conflicts with permalink plugin
         | 
| 6 | 
            +
                const link = window.location.href.split('#')[1];
         | 
| 7 | 
            +
                if (link !== undefined) {
         | 
| 8 | 
            +
                    return;
         | 
| 9 | 
            +
                }
         | 
| 10 | 
            +
                let articles = document.getElementsByTagName("article");
         | 
| 11 | 
            +
                for(let i = 0; i < articles.length; i++){
         | 
| 12 | 
            +
                    if (i < show+offset) {
         | 
| 13 | 
            +
                        articles[i].setAttribute("style", 'display:block');
         | 
| 14 | 
            +
                    } else {
         | 
| 15 | 
            +
                        articles[i].setAttribute("style", 'display:none');
         | 
| 16 | 
            +
                    }
         | 
| 17 | 
            +
                }
         | 
| 18 | 
            +
                if (articles.length > show+offset) {
         | 
| 19 | 
            +
                    let more = document.createElement('a');
         | 
| 20 | 
            +
                    more.innerHTML = 'more <svg style="width: 10px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z"/></svg>';
         | 
| 21 | 
            +
                    let more_function = 'var elms = document.getElementsByClassName("more-arrow"); for(var k = 0; k < elms.length; k++) { elms[k].remove() }; showPage('+(offset+show)+'); return false;';
         | 
| 22 | 
            +
                    more.setAttribute('onclick', more_function);
         | 
| 23 | 
            +
                    more.setAttribute('href', "#");
         | 
| 24 | 
            +
                    more.setAttribute("class", 'more-arrow');
         | 
| 25 | 
            +
                    more.setAttribute("title", 'Click to show more posts');
         | 
| 26 | 
            +
                    articles[show+offset-1].parentNode.insertBefore(more, articles[show+offset-1].nextSibling);
         | 
| 27 | 
            +
                }
         | 
| 28 | 
            +
            }
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            showPage(0);
         | 
| @@ -0,0 +1,42 @@ | |
| 1 | 
            +
            (function () {
         | 
| 2 | 
            +
                window.addEventListener('hashchange', function () {
         | 
| 3 | 
            +
                    window.location.reload(true);
         | 
| 4 | 
            +
                }, false);
         | 
| 5 | 
            +
                // Add id and permailink to every article
         | 
| 6 | 
            +
                var articles = document.getElementsByTagName("article");
         | 
| 7 | 
            +
                for (var i = 0; i < articles.length; i++) {
         | 
| 8 | 
            +
                    let id = articles[i].getElementsByTagName("h1")[0].id;
         | 
| 9 | 
            +
                    articles[i].id = id;
         | 
| 10 | 
            +
                    var paras = articles[i].getElementsByTagName("p");
         | 
| 11 | 
            +
                    var pos = paras.length - 1;
         | 
| 12 | 
            +
                    paras[pos].innerHTML = paras[pos].innerHTML + '  <a href="#' + id + '" title="Permanent link to post" onclick="window.location.reload(true);">#</a>';
         | 
| 13 | 
            +
                }
         | 
| 14 | 
            +
                // Check if url contains link to article
         | 
| 15 | 
            +
                const link = window.location.href.split('#')[1];
         | 
| 16 | 
            +
                if (link !== undefined) {
         | 
| 17 | 
            +
                    var articles = document.getElementsByTagName("article");
         | 
| 18 | 
            +
                    var found = false;
         | 
| 19 | 
            +
                    for (var i = 0; i < articles.length; i++) {
         | 
| 20 | 
            +
                        var id = articles[i].id;
         | 
| 21 | 
            +
                        if (link == id) {
         | 
| 22 | 
            +
                            found = true;
         | 
| 23 | 
            +
                            articles[i].setAttribute("style", 'display:block');
         | 
| 24 | 
            +
                            var paras = articles[i].getElementsByTagName("p");
         | 
| 25 | 
            +
                            for (var j = 0; j < paras.length; j++) {
         | 
| 26 | 
            +
                                paras[j].setAttribute("style", 'display:block');
         | 
| 27 | 
            +
                            }
         | 
| 28 | 
            +
                            var arrows = articles[i].getElementsByClassName("expander-arrow");
         | 
| 29 | 
            +
                            for (var k = 0; k < arrows.length; k++) {
         | 
| 30 | 
            +
                                arrows[k].setAttribute("style", 'display:none');
         | 
| 31 | 
            +
                            }
         | 
| 32 | 
            +
                        } else {
         | 
| 33 | 
            +
                            articles[i].setAttribute("style", 'display:none');
         | 
| 34 | 
            +
                        }
         | 
| 35 | 
            +
                    }
         | 
| 36 | 
            +
                    if (found == false) {
         | 
| 37 | 
            +
                        let p = document.createElement('p');
         | 
| 38 | 
            +
                        p.innerHTML = 'Post ' + link + ' not found :(';
         | 
| 39 | 
            +
                        document.getElementsByTagName("section")[0].appendChild(p);
         | 
| 40 | 
            +
                    }
         | 
| 41 | 
            +
                }
         | 
| 42 | 
            +
            })();
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            # Welcome to Newport
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            ## 21 Jul, 2021
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Welcome to your new blog powered by Newport.  Start writing your blog posts in this directory, using markdown, and then run `newport build`.  Your static blog will be written to a folder called production and you just need to upload the contents of that folder somewhere that is capable of hosting a static site for you.  Some free options are:
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            1. [GitHub Pages](https://pages.github.com)
         | 
| 8 | 
            +
            2. [DigitalOcean App Platform](https://www.digitalocean.com/products/app-platform/)
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            Don't forget to update your email address and site title in the config.yml
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            You'll find plugins in the javascript directory.  If you develop any useful plugins for your own use please consider submitting a pull request to the [Newport GitHub](https://github.com/richard-fisher/newport)
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            Happy blogging!
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: newport
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1.0. | 
| 4 | 
            +
              version: 1.0.6
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Richard Fisher
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2021-07- | 
| 11 | 
            +
            date: 2021-07-26 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: colorator
         | 
| @@ -44,26 +44,6 @@ dependencies: | |
| 44 44 | 
             
                - - ">="
         | 
| 45 45 | 
             
                  - !ruby/object:Gem::Version
         | 
| 46 46 | 
             
                    version: 2.3.1
         | 
| 47 | 
            -
            - !ruby/object:Gem::Dependency
         | 
| 48 | 
            -
              name: mercenary
         | 
| 49 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 50 | 
            -
                requirements:
         | 
| 51 | 
            -
                - - ">="
         | 
| 52 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 53 | 
            -
                    version: 0.3.6
         | 
| 54 | 
            -
                - - "<"
         | 
| 55 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 56 | 
            -
                    version: '0.5'
         | 
| 57 | 
            -
              type: :runtime
         | 
| 58 | 
            -
              prerelease: false
         | 
| 59 | 
            -
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 60 | 
            -
                requirements:
         | 
| 61 | 
            -
                - - ">="
         | 
| 62 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 63 | 
            -
                    version: 0.3.6
         | 
| 64 | 
            -
                - - "<"
         | 
| 65 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 66 | 
            -
                    version: '0.5'
         | 
| 67 47 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 68 48 | 
             
              name: rss
         | 
| 69 49 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -97,6 +77,24 @@ files: | |
| 97 77 | 
             
            - LICENSE
         | 
| 98 78 | 
             
            - README.md
         | 
| 99 79 | 
             
            - exe/newport
         | 
| 80 | 
            +
            - lib/newport.rb
         | 
| 81 | 
            +
            - lib/newport/build.rb
         | 
| 82 | 
            +
            - lib/newport/help.rb
         | 
| 83 | 
            +
            - lib/newport/logger.rb
         | 
| 84 | 
            +
            - lib/newport/new.rb
         | 
| 85 | 
            +
            - lib/newport/version.rb
         | 
| 86 | 
            +
            - lib/site_template/config.yml
         | 
| 87 | 
            +
            - lib/site_template/javascript/js.cookie.min.js
         | 
| 88 | 
            +
            - lib/site_template/layouts/footer.html
         | 
| 89 | 
            +
            - lib/site_template/layouts/head.html
         | 
| 90 | 
            +
            - lib/site_template/layouts/main.html
         | 
| 91 | 
            +
            - lib/site_template/layouts/nav.html
         | 
| 92 | 
            +
            - lib/site_template/layouts/style.css
         | 
| 93 | 
            +
            - lib/site_template/plugins/darkmode.js
         | 
| 94 | 
            +
            - lib/site_template/plugins/expander.js
         | 
| 95 | 
            +
            - lib/site_template/plugins/pagination.js
         | 
| 96 | 
            +
            - lib/site_template/plugins/permalink.js
         | 
| 97 | 
            +
            - lib/site_template/posts/202107211703_digital-ocean-static-site-hosting.md
         | 
| 100 98 | 
             
            homepage: https://github.com/richard-fisher/newport
         | 
| 101 99 | 
             
            licenses:
         | 
| 102 100 | 
             
            - MIT
         |