moonshard 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: 93fffd8c4d7bb102f655c8062412d7ac5bfd816a5adfd87d2299551ee030db39
4
+ data.tar.gz: 4e6e7961be6fc2b9379bdd3b054d3b9b013b0998c857eb1ac203d8ce471c351f
5
+ SHA512:
6
+ metadata.gz: 54cc25eb6933812d809e0b27948bf3eb9db825f37b947c4320aa0887dde5ac792aee8dacf6f8d6e0b45822581073258b041e14d22e8cf0a3a19d8b7bdef7623f
7
+ data.tar.gz: 74c2cf709fc228d89684d97bdfb4ef69848859374f52e9900e9f57279a07f5dcead3aa07d58fa26cd9c1a84bb00ba397db50657ef8955b72dea3203e50d2db56
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/bin/moonshard ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "moonshard"
4
+
5
+ Moonshard.run(ARGV)
data/lib/moonshard.rb ADDED
@@ -0,0 +1,113 @@
1
+ require "json"
2
+
3
+ module Moonshard
4
+ DEFAULT_BACKUP_FILE = "original_files.json"
5
+
6
+ class Error < StandardError
7
+ end
8
+
9
+ def self.run(args)
10
+ if args[0] == "-r"
11
+ restore(args[1] || DEFAULT_BACKUP_FILE)
12
+ else
13
+ replace(args[0] || ".")
14
+ end
15
+ end
16
+
17
+ def self.restore(backup_file)
18
+ unless File.file?(backup_file)
19
+ warn "Error: backup file not found: #{backup_file}"
20
+ return false
21
+ end
22
+
23
+ begin
24
+ original_files = JSON.parse(File.read(backup_file))
25
+ rescue JSON::ParserError => e
26
+ warn "Error: invalid JSON file: #{e.message}"
27
+ return false
28
+ end
29
+
30
+ original_files.each do |file, content|
31
+ begin
32
+ File.write(file, content)
33
+ puts "Restored: #{file}"
34
+ rescue => e
35
+ warn "Warning: cannot restore #{file}: #{e.message}"
36
+ end
37
+ end
38
+
39
+ puts "Restore completed."
40
+
41
+ true
42
+ end
43
+
44
+ def self.replace(root_dir)
45
+ root_dir = File.expand_path(root_dir)
46
+ backup_file = File.expand_path(DEFAULT_BACKUP_FILE)
47
+
48
+ original_files = {}
49
+
50
+ Dir.glob(File.join(root_dir, "**", "*")).each do |file|
51
+ next unless File.file?(file)
52
+
53
+ # Don't process the backup JSON itself
54
+ next if File.expand_path(file) == backup_file
55
+
56
+ begin
57
+ content = File.read(file)
58
+ rescue => e
59
+ warn "Warning: cannot read #{file}: #{e.message}"
60
+ next
61
+ end
62
+
63
+ # Only process files containing ##{...}
64
+ next unless content.match?(/##\{[^}]+\}/)
65
+
66
+ # Save original content before replacement
67
+ original_files[file] = content
68
+
69
+ file_dir = File.dirname(file)
70
+
71
+ replaced = content.gsub(/^([ \t]*)##\{([^}]+)\}[ \t]*$/) do
72
+ indentation = Regexp.last_match(1)
73
+ referenced_file = Regexp.last_match(2)
74
+
75
+ referenced_path = File.expand_path(
76
+ referenced_file,
77
+ file_dir
78
+ )
79
+
80
+ unless File.file?(referenced_path)
81
+ warn "Warning: file not found: #{referenced_path} (referenced from #{file})"
82
+ next Regexp.last_match(0)
83
+ end
84
+
85
+ inserted_content = File.read(referenced_path).chomp
86
+
87
+ # Apply the indentation of ##{...}
88
+ # to every non-empty line.
89
+ inserted_content.lines.map do |line|
90
+ if line.strip.empty?
91
+ line
92
+ else
93
+ indentation + line
94
+ end
95
+ end.join
96
+ end
97
+
98
+ next if replaced == content
99
+
100
+ File.write(file, replaced)
101
+ puts "Updated: #{file}"
102
+ end
103
+
104
+ File.write(
105
+ backup_file,
106
+ JSON.pretty_generate(original_files)
107
+ )
108
+
109
+ puts "Backup saved to: #{backup_file}"
110
+
111
+ true
112
+ end
113
+ end
data/moonshard.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = "moonshard"
3
+ spec.version = "0.1.0"
4
+ spec.authors = ["Tommy Jeff"]
5
+ spec.email = ["threcius@gmail.com"]
6
+
7
+ spec.summary = "Replace ##{file} references with file contents"
8
+ spec.description = "Recursively replaces ##{file} references with the contents of referenced files."
9
+ spec.homepage = "https://github.com/orklann/moonshard"
10
+ spec.license = "MIT"
11
+
12
+ spec.required_ruby_version = ">= 3.0"
13
+
14
+ spec.files = Dir[
15
+ "README.md",
16
+ "Gemfile",
17
+ "moonshard.gemspec",
18
+ "bin/**/*",
19
+ "lib/**/*"
20
+ ]
21
+
22
+ spec.bindir = "bin"
23
+ spec.executables = ["moonshard"]
24
+ spec.require_paths = ["lib"]
25
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: moonshard
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tommy Jeff
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-08-30 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: 'Recursively replaces #moonshard.gemspec references with the contents
14
+ of referenced files.'
15
+ email:
16
+ - threcius@gmail.com
17
+ executables:
18
+ - moonshard
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - Gemfile
23
+ - bin/moonshard
24
+ - lib/moonshard.rb
25
+ - moonshard.gemspec
26
+ homepage: https://github.com/orklann/moonshard
27
+ licenses:
28
+ - MIT
29
+ metadata: {}
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '3.0'
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ requirements: []
45
+ rubygems_version: 3.5.11
46
+ signing_key:
47
+ specification_version: 4
48
+ summary: 'Replace #moonshard.gemspec references with file contents'
49
+ test_files: []