diff --git a/.github/workflows/documentation-coverage.yaml b/.github/workflows/documentation-coverage.yaml new file mode 100644 index 0000000..b3bac9a --- /dev/null +++ b/.github/workflows/documentation-coverage.yaml @@ -0,0 +1,25 @@ +name: Documentation Coverage + +on: [push, pull_request] + +permissions: + contents: read + +env: + CONSOLE_OUTPUT: XTerm + COVERAGE: PartialSummary + +jobs: + validate: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: "3.3" + bundler-cache: true + + - name: Validate coverage + timeout-minutes: 5 + run: bundle exec bake decode:index:coverage lib diff --git a/.github/workflows/rubocop.yaml b/.github/workflows/rubocop.yaml new file mode 100644 index 0000000..287c06d --- /dev/null +++ b/.github/workflows/rubocop.yaml @@ -0,0 +1,24 @@ +name: RuboCop + +on: [push, pull_request] + +permissions: + contents: read + +env: + CONSOLE_OUTPUT: XTerm + +jobs: + check: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ruby + bundler-cache: true + + - name: Run RuboCop + timeout-minutes: 10 + run: bundle exec rubocop diff --git a/.github/workflows/coverage.yaml b/.github/workflows/test-coverage.yaml similarity index 85% rename from .github/workflows/coverage.yaml rename to .github/workflows/test-coverage.yaml index 68adbf2..50e9293 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/test-coverage.yaml @@ -1,4 +1,4 @@ -name: Coverage +name: Test Coverage on: [push, pull_request] @@ -33,9 +33,11 @@ jobs: - name: Run tests timeout-minutes: 5 run: bundle exec bake test - - - uses: actions/upload-artifact@v3 + + - uses: actions/upload-artifact@v4 with: + include-hidden-files: true + if-no-files-found: error name: coverage-${{matrix.os}}-${{matrix.ruby}} path: .covered.db @@ -50,7 +52,7 @@ jobs: ruby-version: "3.3" bundler-cache: true - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 - name: Validate coverage timeout-minutes: 5 diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..3b8d476 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,53 @@ +AllCops: + DisabledByDefault: true + +Layout/IndentationStyle: + Enabled: true + EnforcedStyle: tabs + +Layout/InitialIndentation: + Enabled: true + +Layout/IndentationWidth: + Enabled: true + Width: 1 + +Layout/IndentationConsistency: + Enabled: true + EnforcedStyle: normal + +Layout/BlockAlignment: + Enabled: true + +Layout/EndAlignment: + Enabled: true + EnforcedStyleAlignWith: start_of_line + +Layout/BeginEndAlignment: + Enabled: true + EnforcedStyleAlignWith: start_of_line + +Layout/ElseAlignment: + Enabled: true + +Layout/DefEndAlignment: + Enabled: true + +Layout/CaseIndentation: + Enabled: true + +Layout/CommentIndentation: + Enabled: true + +Layout/EmptyLinesAroundClassBody: + Enabled: true + +Layout/EmptyLinesAroundModuleBody: + Enabled: true + +Style/FrozenStringLiteralComment: + Enabled: true + +Style/StringLiterals: + Enabled: true + EnforcedStyle: double_quotes diff --git a/gems.rb b/gems.rb index 47b7c12..6f05337 100644 --- a/gems.rb +++ b/gems.rb @@ -3,7 +3,7 @@ # Released under the MIT License. # Copyright, 2021-2024, by Samuel Williams. -source 'https://rubygems.org' +source "https://rubygems.org" gemspec @@ -17,6 +17,8 @@ group :test do gem "sus" gem "covered" + gem "decode" + gem "rubocop" gem "bake-test" gem "bake-test-external" diff --git a/lib/live.rb b/lib/live.rb index f8b0adb..d41e774 100644 --- a/lib/live.rb +++ b/lib/live.rb @@ -5,6 +5,6 @@ require_relative "live/version" -require_relative 'live/page' -require_relative 'live/view' -require_relative 'live/resolver' +require_relative "live/page" +require_relative "live/view" +require_relative "live/resolver" diff --git a/lib/live/element.rb b/lib/live/element.rb index 8345b15..a92f856 100644 --- a/lib/live/element.rb +++ b/lib/live/element.rb @@ -3,8 +3,8 @@ # Released under the MIT License. # Copyright, 2021-2024, by Samuel Williams. -require 'json' -require 'securerandom' +require "json" +require "securerandom" module Live class PageError < RuntimeError diff --git a/lib/live/page.rb b/lib/live/page.rb index 673fa54..e4c13e3 100644 --- a/lib/live/page.rb +++ b/lib/live/page.rb @@ -3,16 +3,16 @@ # Released under the MIT License. # Copyright, 2021-2024, by Samuel Williams. -require_relative 'element' -require_relative 'resolver' +require_relative "element" +require_relative "resolver" -require 'async' -require 'async/queue' +require "async" +require "async/queue" -require 'protocol/websocket' -require 'protocol/websocket/message' +require "protocol/websocket" +require "protocol/websocket/message" -require 'console/event/failure' +require "console/event/failure" module Live # Represents a connected client page with bound dynamic content areas. @@ -87,23 +87,23 @@ def close # Process a single incoming message from the network. def process_message(message) case message[0] - when 'bind' + when "bind" # Bind a client-side element to a server-side element. if element = self.resolve(message[1], message[2]) self.bind(element) else Console.warn(self, "Could not resolve element:", message) - @updates.enqueue(['error', message[1], "Could not resolve element!"]) + @updates.enqueue(["error", message[1], "Could not resolve element!"]) end - when 'unbind' + when "unbind" # Unbind a client-side element from a server-side element. if element = @elements.delete(message[1]) element.close unless @attached.key?(message[1]) else Console.warn(self, "Could not unbind element:", message) - @updates.enqueue(['error', message[1], "Could not unbind element!"]) + @updates.enqueue(["error", message[1], "Could not unbind element!"]) end - when 'event' + when "event" # Handle an event from the client. self.handle(message[1], message[2]) else diff --git a/lib/live/resolver.rb b/lib/live/resolver.rb index 36cf2df..2856b06 100644 --- a/lib/live/resolver.rb +++ b/lib/live/resolver.rb @@ -3,7 +3,7 @@ # Released under the MIT License. # Copyright, 2021-2024, by Samuel Williams. -require_relative 'element' +require_relative "element" module Live # Resolves a client-side tag into a server-side instance. diff --git a/lib/live/version.rb b/lib/live/version.rb index 0142512..d2f7d56 100644 --- a/lib/live/version.rb +++ b/lib/live/version.rb @@ -4,5 +4,5 @@ # Copyright, 2021-2024, by Samuel Williams. module Live - VERSION = "0.13.0" + VERSION = "0.13.0" end diff --git a/lib/live/view.rb b/lib/live/view.rb index 53ff3a8..738b553 100644 --- a/lib/live/view.rb +++ b/lib/live/view.rb @@ -3,8 +3,8 @@ # Released under the MIT License. # Copyright, 2021-2024, by Samuel Williams. -require_relative 'element' -require 'xrb/builder' +require_relative "element" +require "xrb/builder" module Live # Represents a single division of content on the page an provides helpers for rendering the content. @@ -12,7 +12,7 @@ class View < Element # @returns [Object] The generated HTML. def to_html XRB::Builder.fragment do |builder| - builder.inline_tag :div, id: @id, class: 'live', data: @data do + builder.inline_tag :div, id: @id, class: "live", data: @data do render(builder) end end diff --git a/live.gemspec b/live.gemspec index ca70244..6cb0ffb 100644 --- a/live.gemspec +++ b/live.gemspec @@ -10,8 +10,8 @@ Gem::Specification.new do |spec| spec.authors = ["Samuel Williams", "Olle Jonsson", "Tatsuhiro Ujihisa"] spec.license = "MIT" - spec.cert_chain = ['release.cert'] - spec.signing_key = File.expand_path('~/.gem/release.pem') + spec.cert_chain = ["release.cert"] + spec.signing_key = File.expand_path("~/.gem/release.pem") spec.homepage = "https://github.com/socketry/live" @@ -20,7 +20,7 @@ Gem::Specification.new do |spec| "source_code_uri" => "https://github.com/socketry/live.git", } - spec.files = Dir.glob(['{lib}/**/*', '*.md'], File::FNM_DOTMATCH, base: __dir__) + spec.files = Dir.glob(["{lib}/**/*", "*.md"], File::FNM_DOTMATCH, base: __dir__) spec.required_ruby_version = ">= 3.1" diff --git a/test/live/element.rb b/test/live/element.rb index ca669b2..419f1a0 100644 --- a/test/live/element.rb +++ b/test/live/element.rb @@ -3,7 +3,7 @@ # Released under the MIT License. # Copyright, 2024, by Samuel Williams. -require 'live/element' +require "live/element" describe Live::Element do it "can generate a unique id" do diff --git a/test/live/page.rb b/test/live/page.rb index 4ee6914..f18dbf0 100644 --- a/test/live/page.rb +++ b/test/live/page.rb @@ -3,9 +3,9 @@ # Released under the MIT License. # Copyright, 2021-2024, by Samuel Williams. -require 'live/page' -require 'live/view' -require 'live/resolver' +require "live/page" +require "live/view" +require "live/resolver" class MyView < Live::View end @@ -15,19 +15,19 @@ class MyView < Live::View let(:page) {subject.new(resolver)} - with '#resolve' do + with "#resolve" do it "resolves allowed elements" do resolver.allowed[Live::View.name] = Live::View - expect(page.resolve('live-view', {class: 'Live::View'})).to be_a(Live::View) + expect(page.resolve("live-view", {class: "Live::View"})).to be_a(Live::View) end it "ignores non-allowed elements" do - expect(page.resolve('live-view', {class: 'Live::View'})).to be_nil + expect(page.resolve("live-view", {class: "Live::View"})).to be_nil end end - with '#attach' do + with "#attach" do let(:view) {MyView.new} it "can resolve attached elements" do diff --git a/test/live/view.rb b/test/live/view.rb index 108106a..a212d14 100644 --- a/test/live/view.rb +++ b/test/live/view.rb @@ -3,10 +3,10 @@ # Released under the MIT License. # Copyright, 2024, by Samuel Williams. -require 'live/view' +require "live/view" describe Live::View do - let(:view) {subject.new('test-id')} + let(:view) {subject.new("test-id")} with "#to_s" do it "can generate string representation" do diff --git a/test/live/website.rb b/test/live/website.rb index 021eb9b..90e3b5f 100644 --- a/test/live/website.rb +++ b/test/live/website.rb @@ -3,16 +3,16 @@ # Released under the MIT License. # Copyright, 2024, by Samuel Williams. -require 'sus/fixtures/async/http/server_context' -require 'sus/fixtures/async/webdriver/session_context' +require "sus/fixtures/async/http/server_context" +require "sus/fixtures/async/webdriver/session_context" -require 'async/websocket' -require 'async/websocket/adapters/http' +require "async/websocket" +require "async/websocket/adapters/http" -require 'protocol/http' -require 'protocol/http/body/file' +require "protocol/http" +require "protocol/http/body/file" -require 'live' +require "live" class TestResolver < Live::Resolver def initialize(...) @@ -43,7 +43,7 @@ def bind(...) end def render(builder) - builder.tag('p') do + builder.tag("p") do builder.text Time.now.to_s end end @@ -75,13 +75,13 @@ def app local_path = File.join(root, request.path) if File.file?(local_path) - Protocol::HTTP::Response[200, {'content-type' => content_type(local_path)}, ::Protocol::HTTP::Body::File.open(local_path)] + Protocol::HTTP::Response[200, {"content-type" => content_type(local_path)}, ::Protocol::HTTP::Body::File.open(local_path)] elsif request.path == "/live" Async::WebSocket::Adapters::HTTP.open(request) do |connection| Live::Page.new(resolver).run(connection) end else - Protocol::HTTP::Response[404, {'content-type' => 'text/plain'}, ["Not found"]] + Protocol::HTTP::Response[404, {"content-type" => "text/plain"}, ["Not found"]] end end end