jsduck 3.8.2 → 3.8.3

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.
data/Rakefile CHANGED
@@ -17,12 +17,12 @@ def load_sdk_vars
17
17
  else
18
18
  puts "Error: sdk-vars.rb not found."
19
19
  puts
20
- puts "Please create file sdk-vars.rb and define constants SDK_DIR and OUT_DIR in it."
21
- puts
22
- puts "For example:"
20
+ puts "Please create file sdk-vars.rb and define in it:"
23
21
  puts
24
22
  puts " # path to Ext JS 4 build"
25
- puts " EXT_DIR='/path/to/ext-4.0.7'"
23
+ puts " EXT_BUILD='/path/to/ext-4.0.7'"
24
+ puts " # path to Touch 2 build"
25
+ puts " TOUCH_BUILD='/path/to/touch-2.0.0'"
26
26
  puts " # where to output the docs"
27
27
  puts " OUT_DIR='/path/to/ouput/dir'"
28
28
  puts " # path to SDK (for developers at Sencha)"
@@ -132,7 +132,7 @@ def compress
132
132
  system "mkdir #{dir}/extjs"
133
133
  system "cp template/extjs/ext-all.js #{dir}/extjs"
134
134
  system "mkdir -p #{dir}/extjs/resources/themes/images"
135
- system "cp -r #{EXT_DIR}/resources/themes/images/default #{dir}/extjs/resources/themes/images"
135
+ system "cp -r #{EXT_BUILD}/resources/themes/images/default #{dir}/extjs/resources/themes/images"
136
136
  end
137
137
 
138
138
 
@@ -140,10 +140,6 @@ class JsDuckRunner
140
140
  def initialize
141
141
  @options = []
142
142
  load_sdk_vars
143
- @sdk_dir = SDK_DIR
144
- @out_dir = OUT_DIR
145
- @ext_dir = EXT_DIR
146
- @animator_dir = ANIMATOR_DIR
147
143
  end
148
144
 
149
145
  def add_options(options)
@@ -168,14 +164,14 @@ class JsDuckRunner
168
164
 
169
165
  # For export of ExtJS, reference extjs from the parent dir
170
166
  def make_extjs_path_relative
171
- ["#{@out_dir}/index.html"].each do |file|
167
+ ["#{OUT_DIR}/index.html"].each do |file|
172
168
  out = []
173
169
  IO.read(file).each_line do |line|
174
170
  out << line.sub(/(src|href)="extjs\//, '\1="../')
175
171
  end
176
172
  File.open(file, 'w') {|f| f.write(out) }
177
173
  end
178
- system "rm -rf #{@out_dir}/extjs"
174
+ system "rm -rf #{OUT_DIR}/extjs"
179
175
  end
180
176
 
181
177
  def add_ext4
@@ -184,10 +180,10 @@ class JsDuckRunner
184
180
  "--footer", "Ext JS 4.0 Docs - Generated with <a href='https://github.com/senchalabs/jsduck'>JSDuck</a> VERSION. <a href='http://www.sencha.com/legal/terms-of-use/'>Terms of Use</a>",
185
181
  "--ignore-global",
186
182
  "--no-warnings",
187
- "--images", "#{@ext_dir}/docs/doc-resources",
183
+ "--images", "#{EXT_BUILD}/docs/doc-resources",
188
184
  "--local-storage-db", "ext-4",
189
- "--output", "#{@out_dir}",
190
- "#{@ext_dir}/src",
185
+ "--output", "#{OUT_DIR}",
186
+ "#{EXT_BUILD}/src",
191
187
  ]
192
188
  end
193
189
 
@@ -274,6 +270,10 @@ class JsDuckRunner
274
270
  text: 'Ext JS 3',
275
271
  href: 'http://docs.sencha.com/ext-js/3-4'
276
272
  },
273
+ {
274
+ text: 'Ext JS 2',
275
+ href: 'http://docs.sencha.com/ext-js/2-3'
276
+ },
277
277
  {
278
278
  text: 'Sencha Touch 2',
279
279
  href: 'http://docs.sencha.com/touch/2-0'
@@ -302,12 +302,12 @@ class JsDuckRunner
302
302
  end
303
303
 
304
304
  def copy_extjs_build
305
- system "cp -r #{@ext_dir} #{@out_dir}/extjs-build"
305
+ system "cp -r #{EXT_BUILD} #{OUT_DIR}/extjs-build"
306
306
  end
307
307
 
308
308
  # Copy over Sencha Touch
309
309
  def copy_touch2_build
310
- system "cp -r #{@sdk_dir}/touch/build #{@out_dir}/touch"
310
+ system "cp -r #{TOUCH_BUILD} #{OUT_DIR}/touch"
311
311
  end
312
312
 
313
313
  def run
@@ -397,6 +397,23 @@ task :ext3, [:mode] => :sass do |t, args|
397
397
  runner.run
398
398
  end
399
399
 
400
+ desc "Run JSDuck on official Ext JS 2.3 build\n" +
401
+ "ext2 - creates debug/development version\n" +
402
+ "ext2[export] - creates export/deployable version\n"
403
+ "ext2[live] - creates live version for deployment\n"
404
+ task :ext2, [:mode] => :sass do |t, args|
405
+ mode = args[:mode] || "debug"
406
+ throw "Unknown mode #{mode}" unless ["debug", "export", "live"].include?(mode)
407
+ compress if mode == "export"
408
+
409
+ runner = JsDuckRunner.new
410
+ runner.add_options ["--output", OUT_DIR, "--config", "#{SDK_DIR}/../ext-2-source/doc-config.json"]
411
+ runner.add_debug if mode == "debug"
412
+ runner.add_seo if mode == "live"
413
+ runner.add_google_analytics if mode == "live"
414
+ runner.run
415
+ end
416
+
400
417
  desc "Run JSDuck on Sencha Touch (for internal use at Sencha)\n" +
401
418
  "touch - creates debug/development version\n" +
402
419
  "touch[live] - create live version for deployment\n"
@@ -475,7 +492,7 @@ task :senchaio, [:mode] => :sass do |t, args|
475
492
  compress if mode == "live"
476
493
 
477
494
  runner = JsDuckRunner.new
478
- runner.add_options ["--output", OUT_DIR, "--config", "#{SDK_DIR}/../sync/docs/config.json"]
495
+ runner.add_options ["--output", OUT_DIR, "--config", "#{SDK_DIR}/../client-framework/docs/config.json"]
479
496
  runner.add_debug if mode == "debug"
480
497
  runner.add_seo if mode == "debug" || mode == "live"
481
498
  runner.add_google_analytics if mode == "live"
@@ -2,8 +2,8 @@ Gem::Specification.new do |s|
2
2
  s.required_rubygems_version = ">= 1.3.5"
3
3
 
4
4
  s.name = 'jsduck'
5
- s.version = '3.8.2'
6
- s.date = '2012-03-29'
5
+ s.version = '3.8.3'
6
+ s.date = '2012-04-05'
7
7
  s.summary = "Simple JavaScript Duckumentation generator"
8
8
  s.description = "Documentation generator for Sencha JS frameworks"
9
9
  s.homepage = "https://github.com/senchalabs/jsduck"
@@ -13,7 +13,7 @@ module JsDuck
13
13
 
14
14
  # Don't crash if old syntax is used.
15
15
  if @categories.is_a?(Hash) && @categories["categories"]
16
- Logger.instance.warn(:old_cat_format, 'Update categories file to contain just the array inside {"categories": [...]}')
16
+ Logger.instance.warn(nil, 'Update categories file to contain just the array inside {"categories": [...]}')
17
17
  @categories = @categories["categories"]
18
18
  end
19
19
 
@@ -34,7 +34,12 @@ module JsDuck
34
34
 
35
35
  # Reads and parses JSON from file
36
36
  def self.read(filename)
37
- self.parse(JsDuck::IO.read(filename))
37
+ begin
38
+ self.parse(JsDuck::IO.read(filename))
39
+ rescue
40
+ puts "Oh noes! #{filename} is not a valid JSON file."
41
+ exit(1)
42
+ end
38
43
  end
39
44
 
40
45
  # Parses JSON string
@@ -1,7 +1,7 @@
1
1
  require 'optparse'
2
2
  require 'jsduck/meta_tag_registry'
3
3
  require 'jsduck/logger'
4
- require 'jsduck/io'
4
+ require 'jsduck/json_duck'
5
5
 
6
6
  module JsDuck
7
7
 
@@ -73,7 +73,7 @@ module JsDuck
73
73
  ]
74
74
  @meta_tag_paths = []
75
75
 
76
- @version = "3.8.2"
76
+ @version = "3.8.3"
77
77
 
78
78
  # Customizing output
79
79
  @title = "Sencha Docs - Ext JS"
@@ -349,7 +349,12 @@ module JsDuck
349
349
  opts.on('--config=PATH',
350
350
  "Loads config options from JSON file.", " ") do |path|
351
351
  path = canonical(path)
352
- config = read_json_config(path)
352
+ if File.exists?(path)
353
+ config = read_json_config(path)
354
+ else
355
+ puts "Oh noes! The config file #{path} doesn't exist."
356
+ exit(1)
357
+ end
353
358
  # treat paths inside JSON config relative to the location of
354
359
  # config file. When done, switch back to current working dir.
355
360
  @working_dir = File.dirname(path)
@@ -447,7 +452,7 @@ module JsDuck
447
452
 
448
453
  # Extracts files of first build in jsb file
449
454
  def extract_jsb_files(jsb_file)
450
- json = JSON.parse(JsDuck::IO.read(jsb_file))
455
+ json = JsonDuck::read(jsb_file)
451
456
  basedir = File.dirname(jsb_file)
452
457
 
453
458
  return json["builds"][0]["packages"].map do |package_id|
@@ -19,10 +19,8 @@
19
19
  *
20
20
  */
21
21
 
22
- config = require('./config');
23
- mongoose = require('mongoose');
22
+ var config = require('./config');
24
23
  require('./database');
25
- require('express-namespace');
26
24
 
27
25
  var mysql = require('mysql'),
28
26
  client = mysql.createClient({
@@ -32,328 +30,334 @@ var mysql = require('mysql'),
32
30
  database: config.db.dbName
33
31
  }),
34
32
  express = require('express'),
35
- connect = require('connect'),
36
- MongoStore = require('connect-session-mongo'),
33
+ MongoStore = require('connect-mongo'),
37
34
  _ = require('underscore'),
38
35
  ForumUser = require('./ForumUser').ForumUser,
39
36
  forumUser = new ForumUser(client),
40
37
  util = require('./util'),
41
- crypto = require('crypto');
38
+ crypto = require('crypto'),
39
+ mongoose = require('mongoose');
42
40
 
41
+ var app = express();
43
42
 
44
- var app = express.createServer(
43
+ app.configure(function() {
45
44
 
46
45
  // Headers for Cross Origin Resource Sharing (CORS)
47
- function (req, res, next) {
46
+ app.use(function (req, res, next) {
48
47
  res.setHeader('Access-Control-Allow-Origin', '*');
49
48
  res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS');
50
49
  res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
51
50
  next();
52
- },
51
+ });
53
52
 
54
- express.cookieParser(),
53
+ app.use(express.cookieParser(config.sessionSecret));
55
54
 
56
55
  // Hack to set session cookie if session ID is set as a URL param.
57
56
  // This is because not all browsers support sending cookies via CORS
58
- function(req, res, next) {
59
- if (req.query.sid) {
57
+ app.use(function(req, res, next) {
58
+ if (req.query.sid && req.query.sid != 'null') {
60
59
  var sid = req.query.sid.replace(/ /g, '+');
61
- req.cookies = req.cookies || {};
62
- req.cookies['sencha_docs'] = sid;
60
+ req.sessionID = sid;
61
+ req.signedCookies = req.signedCookies || {};
62
+ req.signedCookies['sencha_docs'] = sid;
63
63
  }
64
64
  next();
65
- },
65
+ });
66
66
 
67
67
  // Use MongoDB for session storage
68
- connect.session({ store: new MongoStore, secret: config.sessionSecret, key: 'sencha_docs' }),
69
-
70
- function(req, res, next) {
68
+ app.use(express.session({
69
+ secret: config.sessionSecret,
70
+ key: 'sencha_docs',
71
+ store: new MongoStore({
72
+ url: exports.mongoDb + "/sessions"
73
+ })
74
+ }));
75
+
76
+ app.use(function(req, res, next) {
71
77
  // IE doesn't get content-type, so default to form encoded.
72
78
  if (!req.headers['content-type']) {
73
79
  req.headers['content-type'] = 'application/x-www-form-urlencoded';
74
80
  }
75
81
  next();
76
- },
77
- express.bodyParser(),
78
- express.methodOverride()
79
- );
82
+ });
80
83
 
81
- app.enable('jsonp callback');
84
+ app.use(express.bodyParser());
85
+ app.use(express.methodOverride());
82
86
 
83
- // All URLs start with /auth
84
- app.namespace('/auth', function(){
87
+ app.enable('jsonp callback');
88
+ });
85
89
 
86
- /**
87
- * Authentication
88
- */
90
+ app.configure('development', function(){
91
+ app.use(express.logger('dev'));
92
+ app.use(express.errorHandler());
93
+ });
89
94
 
90
- app.get('/session', function(req, res) {
91
- var result = req.session && req.session.user && forumUser.clientUser(req.session.user);
92
- res.json(result || false);
93
- });
95
+ /**
96
+ * Authentication
97
+ */
94
98
 
95
- app.post('/login', function(req, res){
99
+ app.get('/auth/session', function(req, res) {
100
+ var result = req.session && req.session.user && forumUser.clientUser(req.session.user);
101
+ res.json(result || false);
102
+ });
96
103
 
97
- forumUser.login(req.body.username, req.body.password, function(err, result) {
104
+ app.post('/auth/login', function(req, res){
98
105
 
99
- if (err) {
100
- res.json({ success: false, reason: err });
101
- return;
102
- }
106
+ forumUser.login(req.body.username, req.body.password, function(err, result) {
103
107
 
104
- req.session = req.session || {};
105
- req.session.user = result;
108
+ if (err) {
109
+ res.json({ success: false, reason: err });
110
+ return;
111
+ }
106
112
 
107
- var response = _.extend(forumUser.clientUser(result), {
108
- sessionID: req.sessionID,
109
- success: true
110
- });
113
+ req.session = req.session || {};
114
+ req.session.user = result;
111
115
 
112
- res.json(response);
116
+ var response = _.extend(forumUser.clientUser(result), {
117
+ sessionID: req.sessionID,
118
+ success: true
113
119
  });
114
- });
115
-
116
- // Remove session
117
- app.post('/logout', function(req, res){
118
- req.session.user = null;
119
- res.json({ success: true });
120
- });
121
120
 
122
- /**
123
- * Handles comment unsubscription requests.
124
- */
125
- app.get('/unsubscribe/:subscriptionId', function(req, res) {
126
-
127
- Subscription.findOne({ _id: req.params.subscriptionId }, function(err, subscription) {
128
- if (err) throw(err);
129
-
130
- if (subscription) {
131
- if (req.query.all == 'true') {
132
- Subscription.remove({ userId: subscription.userId }, function(err) {
133
- res.send("You have been unsubscribed from all threads.");
134
- });
135
- } else {
136
- Subscription.remove({ _id: req.params.subscriptionId }, function(err) {
137
- res.send("You have been unsubscribed from that thread.");
138
- });
139
- }
140
- } else {
141
- res.send("You are already unsubscribed.");
142
- }
143
- });
121
+ res.json(response);
144
122
  });
145
-
146
123
  });
147
124
 
125
+ // Remove session
126
+ app.post('/auth/logout', function(req, res){
127
+ req.session.user = null;
128
+ res.json({ success: true });
129
+ });
148
130
 
149
131
  /**
150
- * Commenting
132
+ * Handles comment unsubscription requests.
151
133
  */
152
- app.namespace('/auth/:sdk/:version', function(){
134
+ app.get('/auth/unsubscribe/:subscriptionId', function(req, res) {
153
135
 
154
- /**
155
- * Returns a list of comments for a particular target (eg class, guide, video)
156
- */
157
- app.get('/comments', util.getCommentReads, function(req, res) {
136
+ Subscription.findOne({ _id: req.params.subscriptionId }, function(err, subscription) {
137
+ if (err) throw(err);
158
138
 
159
- if (!req.query.startkey) {
160
- res.json({error: 'Invalid request'});
161
- return;
139
+ if (subscription) {
140
+ if (req.query.all == 'true') {
141
+ Subscription.remove({ userId: subscription.userId }, function(err) {
142
+ res.send("You have been unsubscribed from all threads.");
143
+ });
144
+ } else {
145
+ Subscription.remove({ _id: req.params.subscriptionId }, function(err) {
146
+ res.send("You have been unsubscribed from that thread.");
147
+ });
148
+ }
149
+ } else {
150
+ res.send("You are already unsubscribed.");
162
151
  }
163
-
164
- Comment.find({
165
- target: JSON.parse(req.query.startkey),
166
- deleted: { '$ne': true },
167
- sdk: req.params.sdk,
168
- version: req.params.version
169
- }).sort('createdAt', 1).run(function(err, comments){
170
- res.json(util.scoreComments(comments, req));
171
- });
172
152
  });
153
+ });
173
154
 
174
- /**
175
- * Returns n most recent comments.
176
- * Takes two parameters: offset and limit.
177
- *
178
- * The last comment object returned will contain `total_rows`,
179
- * `offset` and `limit` fields. I'd say it's a hack, but at least
180
- * it works for now.
181
- */
182
- app.get('/comments_recent', util.getCommentReads, function(req, res) {
183
- var offset = parseInt(req.query.offset, 10) || 0;
184
- var limit = parseInt(req.query.limit, 10) || 100;
185
- var filter = {
186
- deleted: { '$ne': true },
187
- sdk: req.params.sdk,
188
- version: req.params.version
189
- };
190
-
191
- if (req.query.hideRead && req.commentMeta.reads.length > 0) {
192
- filter._id = { $nin: req.commentMeta.reads };
193
- }
194
155
 
195
- Comment.find(filter).sort('createdAt', -1).skip(offset).limit(limit).run(function(err, comments) {
196
- comments = util.scoreComments(comments, req);
197
- // Count all comments, store count to last comment
198
- Comment.count(filter).run(function(err, count) {
199
- var last = comments[comments.length-1];
200
- last.total_rows = count;
201
- last.offset = offset;
202
- last.limit = limit;
203
- res.json(comments);
204
- });
205
- });
206
- });
156
+ /**
157
+ * Commenting
158
+ */
207
159
 
208
- /**
209
- * Returns number of comments for each class/member,
210
- * and a list of classes/members into which the user has subscribed.
211
- */
212
- app.get('/comments_meta', util.getCommentCounts, util.getCommentSubscriptions, function(req, res) {
213
- res.send({ comments: req.commentCounts, subscriptions: req.commentSubscriptions || [] });
160
+ /**
161
+ * Returns a list of comments for a particular target (eg class, guide, video)
162
+ */
163
+ app.get('/auth/:sdk/:version/comments', util.getCommentReads, function(req, res) {
164
+
165
+ if (!req.query.startkey) {
166
+ res.json({error: 'Invalid request'});
167
+ return;
168
+ }
169
+
170
+ Comment.find({
171
+ target: JSON.parse(req.query.startkey),
172
+ deleted: { '$ne': true },
173
+ sdk: req.params.sdk,
174
+ version: req.params.version
175
+ }).sort('createdAt', 1).run(function(err, comments){
176
+ res.json(util.scoreComments(comments, req));
214
177
  });
178
+ });
215
179
 
216
- /**
217
- * Returns an individual comment (used when editing a comment)
218
- */
219
- app.get('/comments/:commentId', util.findComment, function(req, res) {
220
- res.json({ success: true, content: req.comment.content });
180
+ /**
181
+ * Returns n most recent comments.
182
+ * Takes two parameters: offset and limit.
183
+ *
184
+ * The last comment object returned will contain `total_rows`,
185
+ * `offset` and `limit` fields. I'd say it's a hack, but at least
186
+ * it works for now.
187
+ */
188
+ app.get('/auth/:sdk/:version/comments_recent', util.getCommentReads, function(req, res) {
189
+ var offset = parseInt(req.query.offset, 10) || 0;
190
+ var limit = parseInt(req.query.limit, 10) || 100;
191
+ var filter = {
192
+ deleted: { '$ne': true },
193
+ sdk: req.params.sdk,
194
+ version: req.params.version
195
+ };
196
+
197
+ if (req.query.hideRead && req.commentMeta.reads.length > 0) {
198
+ filter._id = { $nin: req.commentMeta.reads };
199
+ }
200
+
201
+ Comment.find(filter).sort('createdAt', -1).skip(offset).limit(limit).run(function(err, comments) {
202
+ comments = util.scoreComments(comments, req);
203
+ // Count all comments, store count to last comment
204
+ Comment.count(filter).run(function(err, count) {
205
+ var last = comments[comments.length-1];
206
+ last.total_rows = count;
207
+ last.offset = offset;
208
+ last.limit = limit;
209
+ res.json(comments);
210
+ });
221
211
  });
212
+ });
222
213
 
223
- /**
224
- * Creates a new comment
225
- */
226
- app.post('/comments', util.requireLoggedInUser, function(req, res) {
227
-
228
- var target = JSON.parse(req.body.target);
229
-
230
- if (target.length === 2) {
231
- target.push('');
232
- }
233
-
234
- var comment = new Comment({
235
- author: req.session.user.username,
236
- userId: req.session.user.userid,
237
- content: req.body.comment,
238
- action: req.body.action,
239
- rating: Number(req.body.rating),
240
- contentHtml: util.markdown(req.body.comment),
241
- downVotes: [],
242
- upVotes: [],
243
- createdAt: new Date,
244
- target: target,
245
- emaiHash: crypto.createHash('md5').update(req.session.user.email).digest("hex"),
246
- sdk: req.params.sdk,
247
- version: req.params.version,
248
- moderator: req.session.user.moderator,
249
- title: req.body.title,
250
- url: req.body.url
251
- });
214
+ /**
215
+ * Returns number of comments for each class/member,
216
+ * and a list of classes/members into which the user has subscribed.
217
+ */
218
+ app.get('/auth/:sdk/:version/comments_meta', util.getCommentCounts, util.getCommentSubscriptions, function(req, res) {
219
+ res.send({ comments: req.commentCounts, subscriptions: req.commentSubscriptions || [] });
220
+ });
252
221
 
253
- comment.save(function(err, response) {
254
- res.json({ success: true, id: response._id, action: req.body.action });
222
+ /**
223
+ * Returns an individual comment (used when editing a comment)
224
+ */
225
+ app.get('/auth/:sdk/:version/comments/:commentId', util.findComment, function(req, res) {
226
+ res.json({ success: true, content: req.comment.content });
227
+ });
255
228
 
256
- util.sendEmailUpdates(comment);
257
- });
229
+ /**
230
+ * Creates a new comment
231
+ */
232
+ app.post('/auth/:sdk/:version/comments', util.requireLoggedInUser, function(req, res) {
233
+
234
+ var target = JSON.parse(req.body.target);
235
+
236
+ if (target.length === 2) {
237
+ target.push('');
238
+ }
239
+
240
+ var comment = new Comment({
241
+ author: req.session.user.username,
242
+ userId: req.session.user.userid,
243
+ content: req.body.comment,
244
+ action: req.body.action,
245
+ rating: Number(req.body.rating),
246
+ contentHtml: util.markdown(req.body.comment),
247
+ downVotes: [],
248
+ upVotes: [],
249
+ createdAt: new Date,
250
+ target: target,
251
+ emaiHash: crypto.createHash('md5').update(req.session.user.email).digest("hex"),
252
+ sdk: req.params.sdk,
253
+ version: req.params.version,
254
+ moderator: req.session.user.moderator,
255
+ title: req.body.title,
256
+ url: req.body.url
258
257
  });
259
258
 
260
- /**
261
- * Updates an existing comment (for voting or updating contents)
262
- */
263
- app.post('/comments/:commentId', util.requireLoggedInUser, util.findComment, function(req, res) {
264
-
265
- var voteDirection,
266
- comment = req.comment;
259
+ comment.save(function(err, response) {
260
+ res.json({ success: true, id: response._id, action: req.body.action });
267
261
 
268
- if (req.body.vote) {
269
- util.vote(req, res, comment);
270
- } else {
271
- util.requireOwner(req, res, function() {
272
- comment.content = req.body.content;
273
- comment.contentHtml = util.markdown(req.body.content);
274
-
275
- comment.updates = comment.updates || [];
276
- comment.updates.push({
277
- updatedAt: String(new Date()),
278
- author: req.session.user.username
279
- });
262
+ util.sendEmailUpdates(comment);
263
+ });
264
+ });
280
265
 
281
- comment.save(function(err, response) {
282
- res.json({ success: true, content: comment.contentHtml });
283
- });
266
+ /**
267
+ * Updates an existing comment (for voting or updating contents)
268
+ */
269
+ app.post('/auth/:sdk/:version/comments/:commentId', util.requireLoggedInUser, util.findComment, function(req, res) {
270
+
271
+ var voteDirection,
272
+ comment = req.comment;
273
+
274
+ if (req.body.vote) {
275
+ util.vote(req, res, comment);
276
+ } else {
277
+ util.requireOwner(req, res, function() {
278
+ comment.content = req.body.content;
279
+ comment.contentHtml = util.markdown(req.body.content);
280
+
281
+ comment.updates = comment.updates || [];
282
+ comment.updates.push({
283
+ updatedAt: String(new Date()),
284
+ author: req.session.user.username
284
285
  });
285
- }
286
- });
287
286
 
288
- /**
289
- * Deletes a comment
290
- */
291
- app.post('/comments/:commentId/delete', util.requireLoggedInUser, util.findComment, util.requireOwner, function(req, res) {
292
- req.comment.deleted = true;
293
- req.comment.save(function(err, response) {
294
- res.send({ success: true });
287
+ comment.save(function(err, response) {
288
+ res.json({ success: true, content: comment.contentHtml });
289
+ });
295
290
  });
296
- });
291
+ }
292
+ });
297
293
 
298
- /**
299
- * Restores deleted comment
300
- */
301
- app.post('/comments/:commentId/undo_delete', util.requireLoggedInUser, util.findComment, util.requireOwner, util.getCommentReads, function(req, res) {
302
- req.comment.deleted = false;
303
- req.comment.save(function(err, response) {
304
- res.send({ success: true, comment: util.scoreComments([req.comment], req)[0] });
305
- });
294
+ /**
295
+ * Deletes a comment
296
+ */
297
+ app.post('/auth/:sdk/:version/comments/:commentId/delete', util.requireLoggedInUser, util.findComment, util.requireOwner, function(req, res) {
298
+ req.comment.deleted = true;
299
+ req.comment.save(function(err, response) {
300
+ res.send({ success: true });
306
301
  });
302
+ });
307
303
 
308
- /**
309
- * Marks a comment 'read'
310
- */
311
- app.post('/comments/:commentId/read', util.requireLoggedInUser, util.findCommentMeta, function(req, res) {
312
- req.commentMeta.metaType = 'read';
313
- req.commentMeta.save(function(err, response) {
314
- res.send({ success: true });
315
- });
304
+ /**
305
+ * Restores deleted comment
306
+ */
307
+ app.post('/auth/:sdk/:version/comments/:commentId/undo_delete', util.requireLoggedInUser, util.findComment, util.requireOwner, util.getCommentReads, function(req, res) {
308
+ req.comment.deleted = false;
309
+ req.comment.save(function(err, response) {
310
+ res.send({ success: true, comment: util.scoreComments([req.comment], req)[0] });
316
311
  });
312
+ });
317
313
 
318
- /**
319
- * Get email subscriptions
320
- */
321
- app.get('/subscriptions', util.getCommentSubscriptions, function(req, res) {
322
- res.json({ subscriptions: req.commentMeta.subscriptions });
314
+ /**
315
+ * Marks a comment 'read'
316
+ */
317
+ app.post('/auth/:sdk/:version/comments/:commentId/read', util.requireLoggedInUser, util.findCommentMeta, function(req, res) {
318
+ req.commentMeta.metaType = 'read';
319
+ req.commentMeta.save(function(err, response) {
320
+ res.send({ success: true });
323
321
  });
322
+ });
323
+
324
+ /**
325
+ * Get email subscriptions
326
+ */
327
+ app.get('/auth/:sdk/:version/subscriptions', util.getCommentSubscriptions, function(req, res) {
328
+ res.json({ subscriptions: req.commentMeta.subscriptions });
329
+ });
324
330
 
325
- /**
326
- * Subscibe / unsubscribe to a comment thread
327
- */
328
- app.post('/subscribe', util.requireLoggedInUser, function(req, res) {
331
+ /**
332
+ * Subscibe / unsubscribe to a comment thread
333
+ */
334
+ app.post('/auth/:sdk/:version/subscribe', util.requireLoggedInUser, function(req, res) {
329
335
 
330
- var subscriptionBody = {
331
- sdk: req.params.sdk,
332
- version: req.params.version,
333
- target: JSON.parse(req.body.target),
334
- userId: req.session.user.userid
335
- };
336
+ var subscriptionBody = {
337
+ sdk: req.params.sdk,
338
+ version: req.params.version,
339
+ target: JSON.parse(req.body.target),
340
+ userId: req.session.user.userid
341
+ };
336
342
 
337
- Subscription.findOne(subscriptionBody, function(err, subscription) {
343
+ Subscription.findOne(subscriptionBody, function(err, subscription) {
338
344
 
339
- if (subscription && req.body.subscribed == 'false') {
345
+ if (subscription && req.body.subscribed == 'false') {
340
346
 
341
- subscription.remove(function(err, ok) {
342
- res.send({ success: true });
343
- });
347
+ subscription.remove(function(err, ok) {
348
+ res.send({ success: true });
349
+ });
344
350
 
345
- } else if (!subscription && req.body.subscribed == 'true') {
351
+ } else if (!subscription && req.body.subscribed == 'true') {
346
352
 
347
- subscription = new Subscription(subscriptionBody);
348
- subscription.email = req.session.user.email;
353
+ subscription = new Subscription(subscriptionBody);
354
+ subscription.email = req.session.user.email;
349
355
 
350
- subscription.save(function(err, ok) {
351
- res.send({ success: true });
352
- });
353
- }
354
- });
356
+ subscription.save(function(err, ok) {
357
+ res.send({ success: true });
358
+ });
359
+ }
355
360
  });
356
-
357
361
  });
358
362
 
359
363
  var port = 3000;
@@ -1,6 +1,11 @@
1
+
1
2
  /**
2
3
  * Defines comment schema and connects to database
3
4
  */
5
+
6
+ var mongoose = require('mongoose'),
7
+ config = require('./config');
8
+
4
9
  Comment = mongoose.model('Comment', new mongoose.Schema({
5
10
  sdk: String,
6
11
  version: String,
@@ -43,4 +48,6 @@ Meta = mongoose.model('Meta', new mongoose.Schema({
43
48
  metaType: String
44
49
  }));
45
50
 
46
- mongoose.connect(config.mongoDb);
51
+ mongoose.connect(config.mongoDb, function(err, ok) {
52
+ console.log("Connected to DB")
53
+ });
@@ -4,10 +4,10 @@
4
4
  "description": "Commenting backend for JSDuck Documentation",
5
5
  "author": "Nick Poudlen <nick@sencha.com>",
6
6
  "dependencies": {
7
+ "express": "git://github.com/visionmedia/express.git",
8
+ "express-namespace": "",
7
9
  "connect": "",
8
10
  "connect-mongo": "",
9
- "express": "",
10
- "express-namespace": "",
11
11
  "marked": "",
12
12
  "mongoose": "",
13
13
  "mysql": "",
@@ -17,4 +17,3 @@
17
17
  "nodemailer": ""
18
18
  }
19
19
  }
20
-
@@ -2,7 +2,8 @@
2
2
  var marked = require('marked'),
3
3
  _ = require('underscore'),
4
4
  sanitizer = require('sanitizer'),
5
- nodemailer = require("nodemailer");
5
+ nodemailer = require("nodemailer"),
6
+ mongoose = require('mongoose');
6
7
 
7
8
  /**
8
9
  * Converts Markdown-formatted comment text into HTML.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsduck
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.8.2
4
+ version: 3.8.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-03-29 00:00:00.000000000 Z
13
+ date: 2012-04-05 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rdiscount
17
- requirement: &9961600 !ruby/object:Gem::Requirement
17
+ requirement: &9318620 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *9961600
25
+ version_requirements: *9318620
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: json
28
- requirement: &9961020 !ruby/object:Gem::Requirement
28
+ requirement: &9318020 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *9961020
36
+ version_requirements: *9318020
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: parallel
39
- requirement: &9960340 !ruby/object:Gem::Requirement
39
+ requirement: &9317460 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,7 +44,7 @@ dependencies:
44
44
  version: '0'
45
45
  type: :runtime
46
46
  prerelease: false
47
- version_requirements: *9960340
47
+ version_requirements: *9317460
48
48
  description: Documentation generator for Sencha JS frameworks
49
49
  email: rene.saarsoo@sencha.com
50
50
  executables:
@@ -464,20 +464,12 @@ files:
464
464
  - template-min/extjs/resources/themes/images/default/form/text-bg.gif
465
465
  - template-min/extjs/resources/themes/images/default/window-header/window-header-default-bottom-corners.gif
466
466
  - template-min/extjs/resources/themes/images/default/window-header/window-header-default-right-sides.gif
467
- - template-min/extjs/resources/themes/images/default/window-header/window-header-default-collapsed-bottom-corners.gif
468
- - template-min/extjs/resources/themes/images/default/window-header/window-header-default-collapsed-right-sides.gif
469
467
  - template-min/extjs/resources/themes/images/default/window-header/window-header-default-top-sides.gif
470
- - template-min/extjs/resources/themes/images/default/window-header/window-header-default-collapsed-left-sides.gif
471
468
  - template-min/extjs/resources/themes/images/default/window-header/window-header-default-top-corners.gif
472
469
  - template-min/extjs/resources/themes/images/default/window-header/window-header-default-left-corners.gif
473
- - template-min/extjs/resources/themes/images/default/window-header/window-header-default-collapsed-right-corners.gif
474
- - template-min/extjs/resources/themes/images/default/window-header/window-header-default-collapsed-top-corners.gif
475
470
  - template-min/extjs/resources/themes/images/default/window-header/window-header-default-left-sides.gif
476
- - template-min/extjs/resources/themes/images/default/window-header/window-header-default-collapsed-bottom-sides.gif
477
- - template-min/extjs/resources/themes/images/default/window-header/window-header-default-collapsed-left-corners.gif
478
471
  - template-min/extjs/resources/themes/images/default/window-header/window-header-default-right-corners.gif
479
472
  - template-min/extjs/resources/themes/images/default/window-header/window-header-default-bottom-sides.gif
480
- - template-min/extjs/resources/themes/images/default/window-header/window-header-default-collapsed-top-sides.gif
481
473
  - template-min/extjs/resources/themes/images/default/tab-bar/scroll-left.gif
482
474
  - template-min/extjs/resources/themes/images/default/tab-bar/tab-bar-default-bg.gif
483
475
  - template-min/extjs/resources/themes/images/default/tab-bar/scroll-right.gif