indexer 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/.index +8 -4
  2. data/Gemfile.lock +29 -0
  3. data/HISTORY.md +18 -1
  4. data/README.md +5 -2
  5. data/data/indexer/{r2013/index.kwalify → index.kwalify} +0 -0
  6. data/data/indexer/{r2013/index.yes → index.yes} +0 -0
  7. data/data/indexer/{r2013/index.yesi → index.yesi} +0 -0
  8. data/data/indexer/{r2013/ruby.txt → ruby.txt} +0 -0
  9. data/data/indexer/{r2013/yaml.txt → yaml.txt} +0 -0
  10. data/lib/indexer/attributes.rb +7 -3
  11. data/lib/indexer/command.rb +18 -13
  12. data/lib/indexer/components.rb +1 -0
  13. data/lib/indexer/components/conflict.rb +7 -0
  14. data/lib/indexer/components/engine.rb +87 -0
  15. data/lib/indexer/components/requirement.rb +17 -15
  16. data/lib/indexer/conversion/gemspec.rb +9 -9
  17. data/lib/indexer/conversion/gemspec_exporter.rb +2 -1
  18. data/lib/indexer/core_ext/hash/rekey.rb +89 -0
  19. data/lib/indexer/core_ext/hash/to_h.rb +4 -0
  20. data/lib/indexer/core_ext/kernel/cli.rb +54 -0
  21. data/lib/indexer/importer/html.rb +5 -0
  22. data/lib/indexer/importer/markdown.rb +22 -4
  23. data/lib/indexer/metadata.rb +27 -10
  24. data/lib/indexer/validator.rb +7 -6
  25. data/lib/indexer/webui.rb +167 -0
  26. data/lib/indexer/webui/assets/dotruby_binding.js +41 -0
  27. data/lib/indexer/webui/assets/dotruby_model.js +203 -0
  28. data/lib/indexer/webui/assets/jquery-1.4.2.min.js +154 -0
  29. data/lib/indexer/webui/assets/json2.js +482 -0
  30. data/lib/indexer/webui/assets/knockout-2.0.0.js +97 -0
  31. data/lib/indexer/webui/assets/testdata.json +23 -0
  32. data/lib/indexer/webui/assets/underscore-min.js +31 -0
  33. data/lib/indexer/webui/index-old.html +92 -0
  34. data/lib/indexer/webui/index.html +286 -0
  35. metadata +53 -19
@@ -0,0 +1,4 @@
1
+ class Hash
2
+ def to_h; self; end unless method_defined?(:to_h)
3
+ end
4
+
@@ -0,0 +1,54 @@
1
+ module Kernel
2
+ private
3
+ #
4
+ # CLI is based on Clap library
5
+ # Copyright (c) 2010 Michel Martens
6
+ #
7
+ def cli(*args)
8
+ opts = args.pop
9
+ argv = (args.first || ARGV).dup
10
+ args = []
11
+
12
+ # Split option aliases.
13
+ opts = opts.inject({}) do |h,(k,v)|
14
+ k.to_s.split(/\s+/).each{|o| h[o]=v}; h
15
+ end
16
+
17
+ # Convert single dash flags into multiple flags.
18
+ argv = argv.inject([]) do |a, v|
19
+ if v[0,1] == '-' && v[1,1] != '-'
20
+ a.concat(v[1..-1].chars.map{|c| "-#{c}"})
21
+ else
22
+ a << v
23
+ end
24
+ a
25
+ end
26
+
27
+ while argv.any?
28
+ item = argv.shift
29
+ flag = opts[item]
30
+
31
+ if flag
32
+ # Work around lambda semantics in 1.8.7.
33
+ arity = [flag.arity, 0].max
34
+
35
+ # Raise if there are not enough parameters
36
+ # available for the flag.
37
+ if argv.size < arity
38
+ raise ArgumentError
39
+ end
40
+
41
+ # Call the lambda with N items from argv,
42
+ # where N is the lambda's arity.
43
+ flag.call(*argv.shift(arity))
44
+ else
45
+
46
+ # Collect the items that don't correspond to
47
+ # flags.
48
+ args << item
49
+ end
50
+ end
51
+
52
+ args
53
+ end
54
+ end
@@ -153,6 +153,11 @@ module Indexer
153
153
  entry['version'] = n.content.strip
154
154
  end
155
155
 
156
+ # TODO: better approach to optional field?
157
+ if n = node.at_css('.optional')
158
+ entry['optional'] = true #n.content.strip != "false"
159
+ end
160
+
156
161
  if n = (node.at_css('.groups') || node.at_css('.group'))
157
162
  text = n.content.strip
158
163
  text = text.sub(/^[(]/, '').sub(/[)]$/, '').strip
@@ -25,14 +25,32 @@ module Indexer
25
25
  #
26
26
  def load_markdown(file)
27
27
  require 'nokogiri'
28
- require 'redcarpet'
29
28
 
29
+ text = File.read(file)
30
+
31
+ begin
32
+ require 'redcarpet'
33
+ html = render_with_redcarpet(text)
34
+ rescue LoadError
35
+ require 'kramdown'
36
+ html = render_with_kramdown(text)
37
+ end
38
+
39
+ doc = Nokogiri::HTML(html)
40
+
41
+ load_html(doc)
42
+ end
43
+
44
+ #
45
+ def render_with_redcarpet(text)
30
46
  renderer = Redcarpet::Render::HTML.new()
31
47
  markdown = Redcarpet::Markdown.new(renderer, :autolink=>true, :tables=>true, :space_after_headers=>true)
32
- html = markdown.render(File.read(file))
33
- doc = Nokogiri::HTML(html)
48
+ markdown.render(text)
49
+ end
34
50
 
35
- load_html(doc)
51
+ #
52
+ def render_with_kramdown(text)
53
+ Kramdown::Document.new(text).to_html
36
54
  end
37
55
 
38
56
  end
@@ -51,7 +51,7 @@ module Indexer
51
51
  end
52
52
 
53
53
  #
54
- # Create a new Meta::Spec given a Gem::Specification or .gemspec file.
54
+ # Create a new Metadata instance given a Gem::Specification or .gemspec file.
55
55
  #
56
56
  # @param [Gem::Specification,String] gemspec
57
57
  # RubyGems Gem::Specification object or path to .gemspec file.
@@ -319,17 +319,20 @@ module Indexer
319
319
 
320
320
  # TODO: should we warn if directory does not exist?
321
321
 
322
- # Sets the require paths of the project.
322
+ # Sets the named paths of the project.
323
323
  #
324
- # @param [Array<String>, String] paths
325
- # The require-paths or a glob-pattern.
324
+ # @param [Hash[String]=Array<String>] path_map
325
+ # Mappaing of names to list of paths.
326
326
  #
327
- def load_path=(paths)
328
- @data[:load_path] = \
329
- Array(paths).map do |path|
330
- Valid.path!(path)
331
- path
327
+ def paths=(path_map)
328
+ @data[:paths] = \
329
+ map = {}
330
+ path_map = path_map.to_hash if path_map.respond_to?(:to_hash)
331
+ Valid.hash!(path_map)
332
+ path_map.each do |name, paths|
333
+ map[name.to_s] = Array(paths).map{ |path| Valid.path!(path) }
332
334
  end
335
+ map
333
336
  end
334
337
 
335
338
  # List of language engine/version family supported.
@@ -534,6 +537,20 @@ module Indexer
534
537
 
535
538
  # -- Utility Methods ----------------------------------------------------
536
539
 
540
+ #
541
+ # Legacy method to common Ruby path via `paths['load']`.
542
+ #
543
+ def load_path
544
+ paths['load']
545
+ end
546
+
547
+ #
548
+ # Legacy method to set `paths['load']`.
549
+ #
550
+ def load_path=(path)
551
+ paths['load'] = Array(path).map{ |path| Valid.path!(path) }
552
+ end
553
+
537
554
  #
538
555
  # Adds a new requirement.
539
556
  #
@@ -599,7 +616,7 @@ module Indexer
599
616
  true
600
617
  end
601
618
 
602
- # TODO: What was used for again, load_path ?
619
+ # TODO: What was used for again, load path ?
603
620
  =begin
604
621
  #
605
622
  # Iterates over the paths.
@@ -101,11 +101,12 @@ module Indexer
101
101
  super(value)
102
102
  end
103
103
 
104
- # Loadpath must be an Array of valid pathnames or a String of pathnames
105
- # separated by colons or semi-colons.
106
- def load_path=(value)
107
- Valid.array!(value, :load_path)
108
- value.each_with_index{ |path, i| Valid.path!(path, "load_path #{i}") }
104
+ # Paths must be a Hash of names mapped to an Array of valid pathnames.
105
+ def paths=(value)
106
+ Valid.hash!(value, :paths)
107
+ value.each do |name, paths|
108
+ paths.each_with_index{ |path, i| Valid.path!(path, "paths[#{name}] ##{i}") }
109
+ end
109
110
  super(value)
110
111
  end
111
112
 
@@ -294,7 +295,7 @@ module Indexer
294
295
  :resources => [],
295
296
  :repositories => [],
296
297
  :categories => [],
297
- :load_path => ['lib'],
298
+ :paths => {'load' => ['lib']},
298
299
  :copyrights => []
299
300
  }
300
301
  end
@@ -0,0 +1,167 @@
1
+ #require 'fileutils'
2
+ #require 'tmpdir'
3
+ require 'optparse'
4
+ require 'json'
5
+
6
+ require 'rack'
7
+ require 'rack/server'
8
+ require 'rack/handler'
9
+ require 'rack/builder'
10
+ require 'rack/directory'
11
+ require 'rack/file'
12
+
13
+ module Indexer
14
+
15
+ module WebUI
16
+
17
+ # Server is a Rack-based server that simply serves up the editing page.
18
+ #
19
+ class Server
20
+
21
+ ROOT = File.join(File.dirname(__FILE__), 'webui')
22
+
23
+ # Rack configuration file.
24
+ #RACK_FILE = 'brite.ru'
25
+
26
+ #
27
+ #
28
+ #
29
+ def self.start(argv)
30
+ new(argv).start
31
+ end
32
+
33
+ #
34
+ # Server options, parsed from command line.
35
+ #
36
+ attr :options
37
+
38
+ #
39
+ # Setup new instance of Brite::Server.
40
+ #
41
+ def initialize(argv)
42
+ @options = ::Rack::Server::Options.new.parse!(argv)
43
+
44
+ @root = argv.first || Dir.pwd
45
+
46
+ @options[:app] = app
47
+ #@options[:pid] = "#{tmp_dir}/pids/server.pid"
48
+
49
+ @options[:Port] ||= '4444'
50
+ end
51
+
52
+ # THINK: Should we be using a local tmp directory instead?
53
+ # Then again, why do we need them at all, really?
54
+
55
+ #
56
+ # Temporary directory used by the rack server.
57
+ #
58
+ def tmp_dir
59
+ @tmp_dir ||= File.join(Dir.tmpdir, 'indexer', root)
60
+ end
61
+
62
+ #
63
+ # Start the server.
64
+ #
65
+ def start
66
+ # ensure_site
67
+
68
+ # create required tmp directories if not found
69
+ # %w(cache pids sessions sockets).each do |dir_to_make|
70
+ # FileUtils.mkdir_p(File.join(tmp_dir, dir_to_make))
71
+ # end
72
+
73
+ ::Rack::Server.start(options)
74
+ end
75
+
76
+ # # Ensure root is a Brite Site.
77
+ # def ensure_site
78
+ # return true if File.exist?(rack_file)
79
+ # #return true if config.file
80
+ # abort "Where's the site?"
81
+ # end
82
+
83
+ # # Load Brite configuration.
84
+ # def config
85
+ # @config ||= Brite::Config.new(root)
86
+ # end
87
+
88
+ #
89
+ # Site root directory.
90
+ #
91
+ def root
92
+ ROOT
93
+ end
94
+
95
+ # Configuration file for server.
96
+ #def rack_file
97
+ # RACK_FILE
98
+ #end
99
+
100
+ #
101
+ # If the site has a `brite.ru` file, that will be used to start the server,
102
+ # otherwise a standard Rack::Directory server ise used.
103
+ #
104
+ def app
105
+ @app ||= (
106
+ #if ::File.exist?(rack_file)
107
+ # app, options = Rack::Builder.parse_file(rack_file, opt_parser)
108
+ # @options.merge!(options)
109
+ # app
110
+ #else
111
+ root = self.root
112
+ json = index_json
113
+
114
+ Rack::Builder.new do
115
+ use IndexHTML, root
116
+ map '/index' do
117
+ run Proc.new{ |env| [200, {"Content-Type" => "text/json"}, [json]] }
118
+ end
119
+ run Rack::Directory.new("#{root}")
120
+ end
121
+ #end
122
+ )
123
+ end
124
+
125
+ #
126
+ #
127
+ #
128
+ def index_json
129
+ YAML.load_file('.index').to_json
130
+ end
131
+
132
+ # Rack middleware to serve `index.html` file by default.
133
+ #
134
+ class IndexHTML
135
+ def initialize(app, root)
136
+ @app = app
137
+ @root = root || Dir.pwd
138
+ end
139
+
140
+ def call(env)
141
+ path = Rack::Utils.unescape(env['PATH_INFO'])
142
+ index_file = File.join(@root, path, 'index.html')
143
+ if File.exists?(index_file)
144
+ [200, {'Content-Type' => 'text/html'}, File.new(index_file)]
145
+ else
146
+ @app.call(env) #Rack::Directory.new(@root).call(env)
147
+ end
148
+ end
149
+ end
150
+
151
+ #
152
+ #def log_path
153
+ # "_brite.log"
154
+ #end
155
+
156
+ #
157
+ #def middleware
158
+ # middlewares = []
159
+ # #middlewares << [Rails::Rack::LogTailer, log_path] unless options[:daemonize]
160
+ # #middlewares << [Rails::Rack::Debugger] if options[:debugger]
161
+ # Hash.new(middlewares)
162
+ #end
163
+ end
164
+
165
+ end
166
+
167
+ end
@@ -0,0 +1,41 @@
1
+
2
+ // Remove list items.
3
+ $('body').delegate(".remove", "click", function() {
4
+ var list = $(this).attr('list');
5
+
6
+ //retrieve the context
7
+ var context = ko.contextFor(this);
8
+ var parentArray = context.$parent[list];
9
+
10
+ //remove the data (context.$data) from the appropriate array on its parent (context.$parent)
11
+ parentArray.remove(context.$data);
12
+
13
+ return false;
14
+ });
15
+
16
+ // Add list items.
17
+ $('body').delegate(".insert", "click", function() {
18
+ var list = $(this).attr('list');
19
+
20
+ //retrieve the context
21
+ var context = ko.contextFor(this);
22
+
23
+ var newItem = prompt("Enter new entry for " + list + ': ');
24
+
25
+ if (newItem != '' && newItem != null) {
26
+ context.$data[list].push(newItem);
27
+ };
28
+
29
+ return false;
30
+ });
31
+
32
+ //function save() {
33
+ // $(). ko.toJSON(DotRubyViewModel);
34
+ //}
35
+
36
+ function save() {
37
+ //var json = ko.toJSON(dotrubyInstance);
38
+ var json = JSON.stringify( ko.toJS(dotrubyInstance), null, 2 );
39
+ $('#lastSavedJson').val(json);
40
+ };
41
+
@@ -0,0 +1,203 @@
1
+ DotRuby = {
2
+
3
+ viewModel: function(data) {
4
+ var self = this;
5
+ var data = DotRuby.prepareData(data);
6
+
7
+ self.name = ko.observable(data.name);
8
+ self.title = ko.observable(data.title);
9
+ self.version = ko.observable(data.version);
10
+ self.codename = ko.observable(data.codename);
11
+ self.summary = ko.observable(data.summary);
12
+ self.description = ko.observable(data.description);
13
+ self.created = ko.observable(data.created);
14
+ self.date = ko.observable(data.date);
15
+ self.organization = ko.observable(data.organization);
16
+ self.suite = ko.observable(data.suite);
17
+ self.install_message = ko.observable(data.install_message);
18
+
19
+ self.authors = ko.observableArray(data.authors);
20
+ self.repositories = ko.observableArray(data.repositories);
21
+ self.requirements = ko.observableArray(data.requirements);
22
+ self.dependencies = ko.observableArray(data.dependencies);
23
+ self.conflicts = ko.observableArray(data.conflicts);
24
+ self.alternatives = ko.observableArray(data.alternatives);
25
+ self.resources = ko.observableArray(data.resources);
26
+ self.copyrights = ko.observableArray(data.copyrights);
27
+ self.load_path = ko.observableArray(data.load_path);
28
+
29
+ self.addResource = function(){
30
+ this.resources.push(new DotRuby.resourceModel( {label: '', uri: ''} ));
31
+ };
32
+
33
+ self.addRepository = function(){
34
+ this.repositories.push(new DotRuby.repositoryModel( {label: '', uri: '', scm: ''} ));
35
+ };
36
+
37
+ self.addRequirement = function(){
38
+ this.requirements.push(new DotRuby.requirementModel( {name: '', version: '', development: false, groups: [], engines: [], platforms: []} ));
39
+ };
40
+
41
+ self.addDependency = function(){
42
+ this.dependencies.push(new DotRuby.dependencyModel( {name: '', version: '', development: false, groups: [], engines: [], platforms: []} ));
43
+ };
44
+
45
+ self.addCopyright = function(){
46
+ this.copyrights.push(new DotRuby.copyrightModel( {holder: '', year: '', license: ''} ));
47
+ };
48
+
49
+ self.addAuthor = function(){
50
+ this.authors.push(new DotRuby.authorModel( {name: '', email: '', website: ''} ));
51
+ };
52
+
53
+ self.addAlternative = function(){
54
+ this.alternatives.push('');
55
+ };
56
+
57
+ self.addConflict = function(){
58
+ this.conflicts.push('');
59
+ };
60
+
61
+ self.addLoadpath = function(){
62
+ this.load_path.push('');
63
+ };
64
+
65
+ self.json = function(){
66
+ // @todo Convert resources back to mapping
67
+ ko.toJSON(this)
68
+ };
69
+ },
70
+
71
+ authorModel: function(data) {
72
+ var self = this;
73
+ self.name = ko.observable(data.name);
74
+ self.email = ko.observable(data.email);
75
+ self.website = ko.observable(data.website);
76
+ self.roles = ko.observableArray(data.roles);
77
+ },
78
+
79
+ repositoryModel: function(data) {
80
+ var self = this;
81
+ self.label = ko.observable(data.label);
82
+ self.uri = ko.observable(data.uri);
83
+ self.scm = ko.observable(data.scm);
84
+ },
85
+
86
+ requirementModel: function(data) {
87
+ var self = this;
88
+ self.name = ko.observable(data.name);
89
+ self.version = ko.observable(data.version);
90
+ self.groups = ko.observableArray(makeArray(data.groups));
91
+ self.platforms = ko.observableArray(makeArray(data.platforms));
92
+ self.engines = ko.observableArray(makeArray(data.engines));
93
+ self.development = ko.observable(data.development);
94
+ self.repository = ko.observable(data.repository);
95
+ },
96
+
97
+ dependencyModel: function(data) {
98
+ var self = this;
99
+ self.name = ko.observable(data.name);
100
+ self.version = ko.observable(data.version);
101
+ self.groups = ko.observableArray(makeArray(data.groups));
102
+ self.engines = ko.observableArray(makeArray(data.engines));
103
+ self.platforms = ko.observableArray(makeArray(data.platforms));
104
+ self.development = ko.observable(data.development);
105
+ self.repository = ko.observable(data.repository);
106
+ },
107
+
108
+ resourceModel: function(data) {
109
+ var self = this;
110
+ self.label = ko.observable(data.label);
111
+ self.uri = ko.observable(data.uri);
112
+ },
113
+
114
+ copyrightModel: function(data) {
115
+ var self = this;
116
+ self.holder = ko.observable(data.holder);
117
+ self.year = ko.observable(data.year);
118
+ self.license = ko.observable(data.license);
119
+ },
120
+
121
+ // take raw hash and convert elements to models
122
+ // also ensure all fields are accounted for
123
+ prepareData: function(data) {
124
+ newData = {
125
+ name: '',
126
+ version: '0.0.0',
127
+ date: '',
128
+ title: '',
129
+ organization: '',
130
+ summary: '',
131
+ description: '',
132
+ requirements: [],
133
+ dependencies: [],
134
+ alternatives: [],
135
+ repositories: [],
136
+ resources: [],
137
+ authors: [],
138
+ copyrights: []
139
+ };
140
+
141
+ _.each(data, function(val, key){
142
+ newData[key] = val;
143
+ });
144
+
145
+ newData.resources = _.map(data.resources, function(v,k){
146
+ return(new DotRuby.resourceModel({'label': k, 'uri': v}));
147
+ });
148
+
149
+ newData.requirements = _.map(data.requirements, function(a){
150
+ return(new DotRuby.requirementModel(a));
151
+ });
152
+
153
+ newData.dependencies = _.map(data.dependencies, function(a){
154
+ return(new DotRuby.dependencyModel(a));
155
+ });
156
+
157
+ newData.repositories = _.map(data.repositories, function(x){
158
+ return(new DotRuby.repositoryModel(x));
159
+ });
160
+
161
+ newData.authors = _.map(data.authors, function(x){
162
+ return(new DotRuby.authorModel(x));
163
+ });
164
+
165
+ newData.copyrights = _.map(data.copyrights, function(x){
166
+ return(new DotRuby.copyrightModel(x));
167
+ });
168
+
169
+ //newData.conflicts = _.map(data.conflicts, function(x){
170
+ // return(new DotRuby.confictModel(x));
171
+ //});
172
+
173
+ //newData.alternatives = _.map(data.alternatives, function(x){
174
+ // return(new DotRuby.copyrightModel(x));
175
+ //});
176
+
177
+ return newData;
178
+ },
179
+
180
+ };
181
+
182
+ //DotRuby.resourceModel.create = function(){
183
+ // return( new DotRuby.resourceModel({label: '', uri: ''}) );
184
+ //};
185
+
186
+ // support functions
187
+
188
+ function makeArray(value){
189
+ if (typeof(value) == Array) {
190
+ return value;
191
+ } else {
192
+ return _.compact([value]);
193
+ }
194
+ };
195
+
196
+ function makeString(value){
197
+ if (typeof(value) == String) {
198
+ return value;
199
+ } else {
200
+ return '' + value;
201
+ }
202
+ };
203
+