erb_lint_daemon 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0d496463d30131bb2ad398b705fedb62d3f94e3b2ff0919013d783d3cd6a5107
4
+ data.tar.gz: ca1bff36a62dba95bfe16e63843b2da448441a3d1c9c159876c8fc657e18edc8
5
+ SHA512:
6
+ metadata.gz: 437c395f96ad32260a35c7cf68ea75db4671275135585cc6fce76214222f641f0252ff59fbc403bb4c4b70efad390d843a3ce024fd7d492615497d51fe003c4a
7
+ data.tar.gz: 0ebd647e7f9ced9d4def4696cf3c0be128ba9184dfc1d5feed6c86568471b7abc7e7efb42748a38c9722d1ab0d42bc70c91d0d8c4bd41b225999af5fabd78f74
data/.erb_lint.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ linters:
3
+ SpaceAroundErbTag:
4
+ enabled: true
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ *.gem
2
+ pkg/
3
+ bin/erb_lint_client_bin
4
+ erb_lint_client
5
+ ext/Makefile
6
+ ext/mkmf.log
7
+ ext/*.o
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,133 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ erb_lint_daemon (0.1.0)
5
+ erb_lint
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ actionview (8.1.1)
11
+ activesupport (= 8.1.1)
12
+ builder (~> 3.1)
13
+ erubi (~> 1.11)
14
+ rails-dom-testing (~> 2.2)
15
+ rails-html-sanitizer (~> 1.6)
16
+ activesupport (8.1.1)
17
+ base64
18
+ bigdecimal
19
+ concurrent-ruby (~> 1.0, >= 1.3.1)
20
+ connection_pool (>= 2.2.5)
21
+ drb
22
+ i18n (>= 1.6, < 2)
23
+ json
24
+ logger (>= 1.4.2)
25
+ minitest (>= 5.1)
26
+ securerandom (>= 0.3)
27
+ tzinfo (~> 2.0, >= 2.0.5)
28
+ uri (>= 0.13.1)
29
+ ast (2.4.3)
30
+ base64 (0.3.0)
31
+ better_html (2.2.0)
32
+ actionview (>= 7.0)
33
+ activesupport (>= 7.0)
34
+ ast (~> 2.0)
35
+ erubi (~> 1.4)
36
+ parser (>= 2.4)
37
+ smart_properties
38
+ bigdecimal (3.3.1)
39
+ builder (3.3.0)
40
+ concurrent-ruby (1.3.5)
41
+ connection_pool (2.5.5)
42
+ crass (1.0.6)
43
+ drb (2.2.3)
44
+ erb_lint (0.9.0)
45
+ activesupport
46
+ better_html (>= 2.0.1)
47
+ parser (>= 2.7.1.4)
48
+ rainbow
49
+ rubocop (>= 1)
50
+ smart_properties
51
+ erubi (1.13.1)
52
+ i18n (1.14.7)
53
+ concurrent-ruby (~> 1.0)
54
+ json (2.16.0)
55
+ language_server-protocol (3.17.0.5)
56
+ lint_roller (1.1.0)
57
+ logger (1.7.0)
58
+ loofah (2.24.1)
59
+ crass (~> 1.0.2)
60
+ nokogiri (>= 1.12.0)
61
+ minitest (5.26.2)
62
+ nokogiri (1.18.10-aarch64-linux-gnu)
63
+ racc (~> 1.4)
64
+ nokogiri (1.18.10-aarch64-linux-musl)
65
+ racc (~> 1.4)
66
+ nokogiri (1.18.10-arm-linux-gnu)
67
+ racc (~> 1.4)
68
+ nokogiri (1.18.10-arm-linux-musl)
69
+ racc (~> 1.4)
70
+ nokogiri (1.18.10-arm64-darwin)
71
+ racc (~> 1.4)
72
+ nokogiri (1.18.10-x86_64-darwin)
73
+ racc (~> 1.4)
74
+ nokogiri (1.18.10-x86_64-linux-gnu)
75
+ racc (~> 1.4)
76
+ nokogiri (1.18.10-x86_64-linux-musl)
77
+ racc (~> 1.4)
78
+ parallel (1.27.0)
79
+ parser (3.3.10.0)
80
+ ast (~> 2.4.1)
81
+ racc
82
+ prism (1.6.0)
83
+ racc (1.8.1)
84
+ rails-dom-testing (2.3.0)
85
+ activesupport (>= 5.0.0)
86
+ minitest
87
+ nokogiri (>= 1.6)
88
+ rails-html-sanitizer (1.6.2)
89
+ loofah (~> 2.21)
90
+ nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
91
+ rainbow (3.1.1)
92
+ rake (13.3.1)
93
+ regexp_parser (2.11.3)
94
+ rubocop (1.81.7)
95
+ json (~> 2.3)
96
+ language_server-protocol (~> 3.17.0.2)
97
+ lint_roller (~> 1.1.0)
98
+ parallel (~> 1.10)
99
+ parser (>= 3.3.0.2)
100
+ rainbow (>= 2.2.2, < 4.0)
101
+ regexp_parser (>= 2.9.3, < 3.0)
102
+ rubocop-ast (>= 1.47.1, < 2.0)
103
+ ruby-progressbar (~> 1.7)
104
+ unicode-display_width (>= 2.4.0, < 4.0)
105
+ rubocop-ast (1.48.0)
106
+ parser (>= 3.3.7.2)
107
+ prism (~> 1.4)
108
+ ruby-progressbar (1.13.0)
109
+ securerandom (0.4.1)
110
+ smart_properties (1.17.0)
111
+ tzinfo (2.0.6)
112
+ concurrent-ruby (~> 1.0)
113
+ unicode-display_width (3.2.0)
114
+ unicode-emoji (~> 4.1)
115
+ unicode-emoji (4.1.0)
116
+ uri (1.1.1)
117
+
118
+ PLATFORMS
119
+ aarch64-linux-gnu
120
+ aarch64-linux-musl
121
+ arm-linux-gnu
122
+ arm-linux-musl
123
+ arm64-darwin
124
+ x86_64-darwin
125
+ x86_64-linux-gnu
126
+ x86_64-linux-musl
127
+
128
+ DEPENDENCIES
129
+ erb_lint_daemon!
130
+ rake
131
+
132
+ BUNDLED WITH
133
+ 2.7.2
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # ErbLintDaemon
2
+
3
+ A fast daemon wrapper for `erb_lint` to amortize startup costs. It uses a persistent Ruby server and a lightweight Go client to achieve near-instant linting feedback (~20ms).
4
+
5
+ ## Installation
6
+
7
+ **Prerequisites:**
8
+ - Go (golang) installed on your system.
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'erb_lint_daemon'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle install
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install erb_lint_daemon
23
+
24
+ The gem will automatically compile the Go client during installation.
25
+
26
+ ## Usage
27
+
28
+ Start the daemon (in a separate terminal or background):
29
+
30
+ ```bash
31
+ # Starts the server
32
+ ruby -r erb_lint_daemon/server -e 'ErbLintDaemon::Server.new.start'
33
+ ```
34
+
35
+ Run the linter using the client:
36
+
37
+ ```bash
38
+ # Lints the specified file
39
+ erb_lint_daemon app/views/users/index.html.erb
40
+ ```
41
+
42
+ ### Options
43
+
44
+ The client accepts the same arguments as `erb_lint`.
45
+
46
+ ## Development
47
+
48
+ To modify the Go client:
49
+ 1. Edit `ext/client.go`.
50
+ 2. Run `rake build` to recompile locally.
51
+
52
+ ## Publishing
53
+
54
+ To publish a new version:
55
+ 1. Update the version number in `version.rb`.
56
+ 2. Commit changes.
57
+ 3. Run `bundle exec rake release`.
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require 'rake'
2
+ require 'bundler/gem_tasks'
3
+
4
+ desc "Build the Go client"
5
+ task :build do
6
+ puts "Building Go client..."
7
+ system("go build -o bin/erb_lint_client_bin ext/client.go")
8
+ if $?.success?
9
+ puts "Successfully built bin/erb_lint_client_bin"
10
+ else
11
+ abort "Failed to build Go client. Make sure Go is installed."
12
+ end
13
+ end
14
+
15
+ desc "Clean build artifacts"
16
+ task :clean do
17
+ rm_f "bin/erb_lint_client_bin"
18
+ rm_f "erb_lint_client"
19
+ end
20
+
21
+ task :default => :build
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+ # Wrapper to execute the compiled Go client
3
+ exec "$(dirname "$0")/erb_lint_client_bin" "$@"
@@ -0,0 +1,30 @@
1
+ require_relative 'lib/erb_lint_daemon/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "erb_lint_daemon"
5
+ spec.version = ErbLintDaemon::VERSION
6
+ spec.authors = ["Owais Khan"]
7
+ spec.email = ["owais@example.com"]
8
+
9
+ spec.summary = "A daemon wrapper for erb_lint to improve performance."
10
+ spec.description = "Amortizes the startup cost of erb_lint by keeping a process alive."
11
+ spec.homepage = "https://github.com/example/erb_lint_daemon"
12
+ spec.license = "MIT"
13
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
14
+
15
+ spec.metadata["homepage_uri"] = spec.homepage
16
+ spec.metadata["source_code_uri"] = "https://github.com/example/erb_lint_daemon"
17
+
18
+ # Specify which files should be added to the gem when it is released.
19
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
20
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
21
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
22
+ end
23
+ spec.bindir = "bin"
24
+ spec.executables = ["erb_lint_daemon"]
25
+ spec.require_paths = ["lib"]
26
+ spec.extensions = ["ext/extconf.rb"]
27
+
28
+ spec.add_dependency "erb_lint"
29
+ spec.add_development_dependency "rake"
30
+ end
data/ext/client.go ADDED
@@ -0,0 +1,74 @@
1
+ package main
2
+
3
+ import (
4
+ "encoding/json"
5
+ "fmt"
6
+ "io"
7
+ "net"
8
+ "os"
9
+ )
10
+
11
+ const socketPath = "/tmp/erb_lint_daemon.sock"
12
+
13
+ type Request struct {
14
+ Args []string `json:"args"`
15
+ Cwd string `json:"cwd"`
16
+ }
17
+
18
+ type Response struct {
19
+ Output string `json:"output"`
20
+ Status int `json:"status"`
21
+ }
22
+
23
+ func main() {
24
+ cwd, err := os.Getwd()
25
+ if err != nil {
26
+ fmt.Fprintf(os.Stderr, "Error getting CWD: %v\n", err)
27
+ os.Exit(1)
28
+ }
29
+
30
+ req := Request{
31
+ Args: os.Args[1:],
32
+ Cwd: cwd,
33
+ }
34
+
35
+ conn, err := net.Dial("unix", socketPath)
36
+ if err != nil {
37
+ // If daemon is not running, we could fallback or error.
38
+ // For now, let's error.
39
+ fmt.Fprintf(os.Stderr, "Error connecting to daemon: %v\n", err)
40
+ os.Exit(1)
41
+ }
42
+ defer conn.Close()
43
+
44
+ reqData, err := json.Marshal(req)
45
+ if err != nil {
46
+ fmt.Fprintf(os.Stderr, "Error marshaling request: %v\n", err)
47
+ os.Exit(1)
48
+ }
49
+
50
+ if _, err := conn.Write(reqData); err != nil {
51
+ fmt.Fprintf(os.Stderr, "Error writing to socket: %v\n", err)
52
+ os.Exit(1)
53
+ }
54
+
55
+ // Close write end to signal EOF to server
56
+ if c, ok := conn.(*net.UnixConn); ok {
57
+ c.CloseWrite()
58
+ }
59
+
60
+ respData, err := io.ReadAll(conn)
61
+ if err != nil {
62
+ fmt.Fprintf(os.Stderr, "Error reading response: %v\n", err)
63
+ os.Exit(1)
64
+ }
65
+
66
+ var resp Response
67
+ if err := json.Unmarshal(respData, &resp); err != nil {
68
+ fmt.Fprintf(os.Stderr, "Error unmarshaling response: %v\n", err)
69
+ os.Exit(1)
70
+ }
71
+
72
+ fmt.Print(resp.Output)
73
+ os.Exit(resp.Status)
74
+ }
data/ext/extconf.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'mkmf'
2
+
3
+ # Find the go compiler
4
+ find_executable('go')
5
+
6
+ # Create a dummy Makefile to satisfy Gem::Installer
7
+ create_makefile('erb_lint_daemon/erb_lint_daemon')
8
+
9
+ # We append a rule to the Makefile to build the Go binary
10
+ File.open('Makefile', 'a') do |f|
11
+ f.write <<~MAKE
12
+
13
+ all:
14
+ \tgo build -o ../../bin/erb_lint_client_bin client.go
15
+
16
+ install: all
17
+ MAKE
18
+ end
data/go.mod ADDED
@@ -0,0 +1,3 @@
1
+ module erb_lint_daemon
2
+
3
+ go 1.16
@@ -0,0 +1,83 @@
1
+ require 'socket'
2
+ require 'erb_lint'
3
+ require 'erb_lint/cli'
4
+ require 'json'
5
+
6
+ module ErbLintDaemon
7
+ class Server
8
+ SOCKET_PATH = '/tmp/erb_lint_daemon.sock'
9
+
10
+ def start
11
+ File.unlink(SOCKET_PATH) if File.exist?(SOCKET_PATH)
12
+ server = UNIXServer.new(SOCKET_PATH)
13
+ puts "ERB Lint Daemon started on #{SOCKET_PATH}"
14
+
15
+ # Preload ERB Lint to warm up
16
+ # We might want to load the config here too if it's static,
17
+ # but for now let's just ensure the library is loaded.
18
+
19
+ loop do
20
+ client = server.accept
21
+ handle_client(client)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def handle_client(client)
28
+ begin
29
+ # Read all data from client until EOF
30
+ request_data = client.read
31
+ payload = JSON.parse(request_data)
32
+ args = payload['args']
33
+ cwd = payload['cwd']
34
+
35
+ # Capture stdout/stderr
36
+ original_stdout = $stdout
37
+ original_stderr = $stderr
38
+ output = StringIO.new
39
+ $stdout = output
40
+ $stderr = output
41
+
42
+ # Run ERB Lint
43
+ # We need to instantiate a new CLI for each run to avoid state pollution
44
+ # but the classes are already loaded.
45
+ @cli ||= ERBLint::CLI.new
46
+ @default_options ||= @cli.instance_variable_get(:@options).dup
47
+
48
+ @cli.instance_variable_set(:@stats, ERBLint::Stats.new)
49
+ @cli.instance_variable_set(:@options, @default_options.dup)
50
+ @cli.instance_variable_set(:@files, nil)
51
+ @cli.instance_variable_set(:@lint_files, nil)
52
+
53
+ cli = @cli
54
+
55
+ success = false
56
+ Dir.chdir(cwd) do
57
+ success = cli.run(args)
58
+ end
59
+
60
+ result = {
61
+ output: output.string,
62
+ status: success ? 0 : 1
63
+ }
64
+
65
+ client.write(JSON.generate(result))
66
+ rescue => e
67
+ error_result = {
68
+ output: "Daemon Error: #{e.message}\n#{e.backtrace.join("\n")}",
69
+ status: 1
70
+ }
71
+ client.write(JSON.generate(error_result))
72
+ ensure
73
+ $stdout = original_stdout
74
+ $stderr = original_stderr
75
+ client.close
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ if __FILE__ == $0
82
+ ErbLintDaemon::Server.new.start
83
+ end
@@ -0,0 +1,3 @@
1
+ module ErbLintDaemon
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,6 @@
1
+ require "erb_lint_daemon/version"
2
+ require "erb_lint_daemon/server"
3
+
4
+ module ErbLintDaemon
5
+ # Your code goes here...
6
+ end
@@ -0,0 +1,4 @@
1
+ ---
2
+ linters:
3
+ SpaceAroundErbTag:
4
+ enabled: false
@@ -0,0 +1 @@
1
+ <%foo%>
@@ -0,0 +1 @@
1
+ <div>No newline</div>
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: erb_lint_daemon
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Owais Khan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-12-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: erb_lint
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Amortizes the startup cost of erb_lint by keeping a process alive.
42
+ email:
43
+ - owais@example.com
44
+ executables:
45
+ - erb_lint_daemon
46
+ extensions:
47
+ - ext/extconf.rb
48
+ extra_rdoc_files: []
49
+ files:
50
+ - ".erb_lint.yml"
51
+ - ".gitignore"
52
+ - Gemfile
53
+ - Gemfile.lock
54
+ - README.md
55
+ - Rakefile
56
+ - bin/erb_lint_daemon
57
+ - erb_lint_daemon.gemspec
58
+ - ext/client.go
59
+ - ext/extconf.rb
60
+ - go.mod
61
+ - lib/erb_lint_daemon.rb
62
+ - lib/erb_lint_daemon/server.rb
63
+ - lib/erb_lint_daemon/version.rb
64
+ - subdir/.erb_lint.yml
65
+ - subdir/bad_spacing.html.erb
66
+ - subdir/no_newline.html.erb
67
+ homepage: https://github.com/example/erb_lint_daemon
68
+ licenses:
69
+ - MIT
70
+ metadata:
71
+ homepage_uri: https://github.com/example/erb_lint_daemon
72
+ source_code_uri: https://github.com/example/erb_lint_daemon
73
+ post_install_message:
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: 2.6.0
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubygems_version: 3.5.9
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: A daemon wrapper for erb_lint to improve performance.
92
+ test_files: []