From 264fcb72e08f7b9530227c997d6dbfb2b0c6efcb Mon Sep 17 00:00:00 2001 From: Abigail Watson Date: Thu, 2 Oct 2014 14:31:19 -0400 Subject: [PATCH] initial comimt --- .gitignore | 3 + LICENSE.md | 20 + README.md | 5 + keymaps/meteor-api.cson | 11 + lib/grammar.cson | 547 +++++++++++++++++++++ lib/meteor-api-view.coffee | 24 + lib/meteor-api.coffee | 13 + lib/snippets.cson | 816 +++++++++++++++++++++++++++++++ lib/stylesheet.less | 63 +++ menus/meteor-api.cson | 16 + package.json | 14 + spec/meteor-api-spec.coffee | 29 ++ spec/meteor-api-view-spec.coffee | 6 + stylesheets/meteor-api.less | 8 + 14 files changed, 1575 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 keymaps/meteor-api.cson create mode 100644 lib/grammar.cson create mode 100644 lib/meteor-api-view.coffee create mode 100644 lib/meteor-api.coffee create mode 100644 lib/snippets.cson create mode 100644 lib/stylesheet.less create mode 100644 menus/meteor-api.cson create mode 100644 package.json create mode 100644 spec/meteor-api-spec.coffee create mode 100644 spec/meteor-api-view-spec.coffee create mode 100644 stylesheets/meteor-api.less diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ade14b9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +npm-debug.log +node_modules diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..7ce8c08 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,20 @@ +Copyright (c) 2014 + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a594ab5 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# meteor-api package + +A short description of your package. + +![A screenshot of your spankin' package](https://f.cloud.github.com/assets/69169/2290250/c35d867a-a017-11e3-86be-cd7c5bf3ff9b.gif) diff --git a/keymaps/meteor-api.cson b/keymaps/meteor-api.cson new file mode 100644 index 0000000..eeaa538 --- /dev/null +++ b/keymaps/meteor-api.cson @@ -0,0 +1,11 @@ +# Keybindings require three things to be fully defined: A selector that is +# matched against the focused element, the keystroke and the command to +# execute. +# +# Below is a basic keybinding which registers on all platforms by applying to +# the root workspace element. + +# For more detailed documentation see +# https://atom.io/docs/latest/advanced/keymaps +'.workspace': + 'ctrl-alt-o': 'meteor-api:toggle' diff --git a/lib/grammar.cson b/lib/grammar.cson new file mode 100644 index 0000000..63d6fb3 --- /dev/null +++ b/lib/grammar.cson @@ -0,0 +1,547 @@ + +'scopeName': 'source.js' +'fileTypes': [ + 'js' + 'htc' + '_js' + 'es6' +] +'firstLineMatch': '^#!.*\\bnode' +'name': 'JavaScript (Meteor)' +'patterns': [ + { + 'match': 'Meteor' + 'name': 'api.meteor' + } + { + 'match': '(isClient|isServer|startup|absolute)' + 'name': 'api.meteor.core' + } + { + 'match': '(?)' + 'name': 'comment.block.html.js' + } + # { + # 'match': '(?=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?|\\:|\\*=|(? + @div class: 'meteor-api overlay from-top', => + @div "The MeteorApi package is Alive! It's ALIVE!", class: "message" + + initialize: (serializeState) -> + atom.workspaceView.command "meteor-api:toggle", => @toggle() + + # Returns an object that can be retrieved when package is activated + serialize: -> + + # Tear down any state and detach + destroy: -> + @detach() + + toggle: -> + console.log "MeteorApiView was toggled!" + if @hasParent() + @detach() + else + atom.workspaceView.append(this) diff --git a/lib/meteor-api.coffee b/lib/meteor-api.coffee new file mode 100644 index 0000000..18cc8f1 --- /dev/null +++ b/lib/meteor-api.coffee @@ -0,0 +1,13 @@ +MeteorApiView = require './meteor-api-view' + +module.exports = + meteorApiView: null + + activate: (state) -> + @meteorApiView = new MeteorApiView(state.meteorApiViewState) + + deactivate: -> + @meteorApiView.destroy() + + serialize: -> + meteorApiViewState: @meteorApiView.serialize() diff --git a/lib/snippets.cson b/lib/snippets.cson new file mode 100644 index 0000000..d498de5 --- /dev/null +++ b/lib/snippets.cson @@ -0,0 +1,816 @@ +# Your snippets +# +# Atom snippets allow you to enter a simple prefix in the editor and hit tab to +# expand the prefix into a larger code block with templated values. +# +# You can create a new snippet in this file by typing "snip" and then hitting +# tab. +# +# An example CoffeeScript snippet to expand log to console.log: +# +# '.source.coffee': +# 'Console log': +# 'prefix': 'log' +# 'body': 'console.log $1' +# + + + +#=================================================== +# HTML / Document Object Model Snippets + +'.html': + 'Blaze Template': + 'prefix': 'template' + 'body': '', + 'Blaze #each': + 'prefix': '#each' + 'body': ' + {{#each ${1:collections}}}\n\t${2}\n{{/each}} + ', + 'Blaze #if': + 'prefix': '#if' + 'body': ' + {{#if ${1:statement}}}\n\t${2}\n{{/if}} + ', + 'Blaze #if else': + 'prefix': '#ife' + 'body': '{{#if ${1:statement}}}\n\t${2}\n{{else}}\n\t${3}\n{{/if}} + ' + +#=================================================== +# Javascript Lanaguage Snippets + +'.js': + + 'if, else if, else': + 'prefix': 'ieie' + 'body': ' + if (${1:true}) { + $2 + } else if (${3:false}) { + $4 + } else { + $5 + } + ', + + 'console.log': + 'prefix': 'log' + 'body': 'console.log("${1:message}");\n${2:}', + + 'function()': + 'prefix': 'f' + 'body': 'function(${1:argument}){\n\t${2:}\n},', + + +#=================================================== +# Meteor Core API + + 'Meteor.isClient': + 'prefix': 'isClient' + 'body': 'if(Meteor.isClient){\n\t${1:}\n}', + + 'Meteor.isServer': + 'prefix': 'isServer' + 'body': 'if(Meteor.isServer){\n\t${1:}\n}', + + 'Meteor.isCordova': + 'prefix': 'isCordova' + 'body': 'if(Meteor.isCordova){\n\t${1:}\n}', + + 'Meteor.startup': + 'prefix': 'startup' + 'body': 'Meteor.startup(function(){\n\t${1:}\n});', + + 'Meteor.absoluteUrl': + 'prefix': 'absolute' + 'body': 'Meteor.absoluteUrl("${1:}");', + + +#=================================================== +# Publish & Subscribe + + 'Meteor Publish': + 'prefix': 'publish' + 'body': 'Meteor.publish("${1:name}", function(${2:argument}){\n\t${3:}\n});', + + 'Meteor Subscribe': + 'prefix': 'subscribe' + 'body': 'Meteor.subscribe("${1:name}", ${2:argument});', + + +#=================================================== +# Methods + + 'Meteor Methods': + 'prefix': 'methods' + 'body': 'Meteor.methods({ + \n\t${1:methodName}:function(){ + \n\t\t${2:} + \n\t} + \n});', + + 'Meteor.Error': + 'prefix': 'error' + 'body': 'Meteor.Error(${1:Number}, "${2:description}");', + + + 'Meteor.call': + 'prefix': 'call' + 'body': 'Meteor.call("${1:meteorMethod}", ${2:dataObject}, function(error, result){ + \n\tif(error){ + \n\t\tconsole.log("error", error); + \n\t} + \n\tif(result){ + \n\t\t${3:} + \n\t} + \n});', + + +#=================================================== +# Connections + + 'Meteor.status': + 'prefix': 'status' + 'body': 'Meteor.status()', + + + 'Meteor.reconnect': + 'prefix': 'reconnect' + 'body': 'Meteor.reconnect()', + + + 'Meteor.disconnect': + 'prefix': 'disconnect' + 'body': 'Meteor.disconnect()', + + + 'Meteor.onConnection': + 'prefix': 'onConnection' + 'body': 'Meteor.onConnection(function(){ + \n\t${1:} + \n});', + + +#=================================================== +# Collections + + 'Meteor.Collection.ObjectID': + 'prefix': 'object' + 'body': 'new Meteor.Collection.ObjectID("${1:id}")', + + 'Collection.find': + 'prefix': 'find' + 'body': '${1:Collection}.find({"${2:field}":${3:value}});\n${4:}', + + 'Collection.findOne': + 'prefix': 'findOne' + 'body': '${1:Collection}.findOne({_id:"${2:recordId}"${3:}});\n${4:}', + + 'Collection.insert': + 'prefix': 'insert' + 'body': '${1:Collection}.insert(${2:newRecord});\n${3:}', + + + 'Collection.Update': + 'prefix': 'update' + 'body': '${1:Collection}.update({_id:${2:idSelector}}, {$set:{\n\t${3:}\n}});\n${4:}', + + 'Collection.Upsert': + 'prefix': 'upsert' + 'body': '${1:Collection}.upsert({_id:${2:idSelector}}, {$set:{\n\t${3:}\n}});\n${4:}', + + 'Collection.remove': + 'prefix': 'remove' + 'body': '${1:Collection}.remove({_id:"${2:recordId}"${3:}});\n${4:}', + + 'Collection.allow': + 'prefix': 'allow' + 'body': '${1:Collection}.allow({ + \n\tinsert: function(){ + \n\t\treturn ${2:true}; + \n\t}, + \n\tupdate: function(){ + \n\t\treturn ${3:true}; + \n\t}, + \n\tremove: function(){ + \n\t\treturn ${4:true}; + \n\t} + \n});\n${5:}', + + 'Collection.deny': + 'prefix': 'deny' + 'body': '${1:Collection}.deny({ + \n\tinsert: function(){ + \n\t\treturn ${2:false}; + \n\t}, + \n\tupdate: function(){ + \n\t\treturn ${3:false}; + \n\t}, + \n\tremove: function(){ + \n\t\treturn ${4:false}; + \n\t} + \n});\n${5:}', + + + 'Collection': + 'prefix': 'Collection' + 'body': '${1:CollectionName} = new Meteor.Collection("${2:name}"); + \n${3:CollectionName}.allow({ + \n\tinsert: function(){ + \n\t\treturn ${4:true}; + \n\t}, + \n\tupdate: function(){ + \n\t\treturn ${5:true}; + \n\t}, + \n\tremove: function(){ + \n\t\treturn ${6:true}; + \n\t} + \n});\n${7:}', + + +#=================================================== +# Session Snippets + + 'Session.set': + 'prefix': 'set' + 'body': 'Session.set("${1:variableName}", ${2:value});\n${3:}', + + 'Session.get': + 'prefix': 'get' + 'body': 'Session.get("${1:variableName}");\n${2:}', + + 'Session.equals': + 'prefix': 'equals' + 'body': 'Session.equals("${1:variableName}", ${2:value});\n${3:}', + + 'Session.setDefault': + 'prefix': 'setDefault' + 'body': 'Session.setDefault("${1:variableName}", ${2:value});\n${3:}', + +#=================================================== +# Accounts Snippets + + + 'Meteor.user': + 'prefix': 'user' + 'body': 'Meteor.user()', + 'Meteor.user': + 'prefix': 'varuser' + 'body': 'var user = Meteor.user();', + 'Meteor.userId': + 'prefix': 'userId' + 'body': 'Meteor.userId()', + 'Meteor.users': + 'prefix': 'users' + 'body': 'Meteor.users', + 'Meteor.loggingIn': + 'prefix': 'loggingIn' + 'body': 'Meteor.loggingIn()', + 'Meteor.logout': + 'prefix': 'logout' + 'body': 'Meteor.logout(function(){ + \n\t${1:} + \n});', + 'Meteor.logoutOtherClients': + 'prefix': 'logoutOtherClients' + 'body': 'Meteor.logoutOtherClients(function(){ + \n\t${1:} + \n});', + 'Meteor.loginWithPassword': + 'prefix': 'logoutOtherClients' + 'body': 'Meteor.logoutOtherClients(${1:user}, ${2:password}, function(){ + \n\t${3:} + \n});', + + + 'Accounts': + 'prefix': 'Accounts' + 'body': ' + Accounts.config({ + \n\tsendVerificationEmail: ${1:true}, + \n\tforbidClientAccountCreation: ${2:true}, + \n\trestrictCreationByEmailDomain: "${3:school.edu}", + \n\tloginExpirationDays: ${4:30}, + \n\toauthSecretKey: "${5:wgporjigrpqgdfg}", + \n}); + \nAccounts.ui.config({ + \n\trequestPermissions: ${1:{}}, + \n\trequestOfflineToken: ${1:{}}, + \n\tpasswordSignupFields: "${3:USERNAME_AND_OPTIONAL_EMAIL}", + \n}); + \n${12:} + ', + + 'Accounts.validateNewUser': + 'prefix': 'validateNewUser' + 'body': 'Meteor.validateNewUser(function(){ + \n\t${1:} + \n});', + + 'Accounts.onCreateUser': + 'prefix': 'onCreateUser' + 'body': 'Meteor.onCreateUser(function(options, user){ + \n\t${1:} + \n\treturn ${1:user} + \n});', + 'Accounts.onLogin': + 'prefix': 'onLogin' + 'body': 'Meteor.onLogin(function(){ + \n\t${1:} + \n});', + 'Accounts.onLoginFailure': + 'prefix': 'onLoginFailure' + 'body': 'Meteor.onLoginFailure(function(){ + \n\t${1:} + \n});', + + +#=================================================== +# Passwords Snippets + + + 'Accounts.createUser': + 'prefix': 'createUser' + 'body': ' + var userObject = { + \n\tusername: "${1:username}", + \n\tmail: "${1:email}", + \n\tpassword: "${1:password}" + \n}; + \n + \nAccounts.createUser(${1:userObject}, function(){ + \n\t${1:} + \n});', + 'Accounts.changePassword': + 'prefix': 'changePassword' + 'body': 'Accounts.changePassword(${1:oldPassword}, ${2:newPassword}, function(){ + \n\t${1:} + \n});', + 'Accounts.forgotPassword': + 'prefix': 'forgotPassword' + 'body': 'Accounts.forgotPassword({email: "${1:address}"}, function(){ + \n\t${2:} + \n});', + 'Accounts.resetPassword': + 'prefix': 'resetPassword' + 'body': 'Accounts.resetPassword(${1:token}, ${2:newPassword}, function(){ + \n\t${3:} + \n});', + 'Accounts.setPassword': + 'prefix': 'setPassword' + 'body': 'Accounts.setPassword(${1:userId}, ${2:newPassword});', + 'Accounts.verifyEmail': + 'prefix': 'verifyEmail' + 'body': 'Accounts.verifyEmail(${1:token}, function(){ + \n\t${1:} + \n});', + 'Accounts.sendResetPasswordEmail': + 'prefix': 'sendResetPasswordEmail' + 'body': 'Accounts.sendResetPasswordEmail(${1:userId});', + + 'Accounts.sendEnrollmentEmail': + 'prefix': 'sendEnrollmentEmail' + 'body': 'Accounts.sendEnrollmentEmail(${1:userId});', + + 'Accounts.sendVerificationEmail': + 'prefix': 'sendVerificationEmail' + 'body': 'Accounts.sendVerificationEmail(${1:userId});', + + + + +#=================================================== +# Match Snippets + + 'Match.check': + 'prefix': 'check' + 'body': 'check(${1:variable}, ${2:String});\n${3:}', + + 'Match.test': + 'prefix': 'test' + 'body': 'Match.test(${1:variable}, ${2:String});\n${3:}', + +#=================================================== +# Timers Snippets + + 'Meteor.setTimeout': + 'prefix': 'setTimeout' + 'body': 'Match.setTimeout(function(){ + \n\t${2:} + \n}, ${1:milliseconds});', + + 'Meteor.setInterval': + 'prefix': 'setInterval' + 'body': 'Match.setTimeout(function(){ + \n\t${2:} + \n}, ${1:milliseconds});', + + 'Meteor.clearTimeout': + 'prefix': 'clearTimeout' + 'body': 'Meteor.clearTimeout(${1:id})', + + 'Meteor.clearInterval': + 'prefix': 'clearInterval' + 'body': 'Meteor.clearInterval(${1:id})', + + +#=================================================== +# Tracker + + 'Tracker.autorun': + 'prefix': 'autorun' + 'body': 'Tracker.autorun(function(){ + \n\t${2:} + \n});', + + 'Tracker.flush': + 'prefix': 'flush' + 'body': 'Tracker.flush();', + + 'Tracker.nonreactive': + 'prefix': 'nonreactive' + 'body': 'Tracker.nonreactive(function(){ + \n\t${2:} + \n});', + + 'Tracker.onInvalidate': + 'prefix': 'onInvalidate' + 'body': 'Tracker.onInvalidate(function(){ + \n\t${2:} + \n});', + + 'Tracker.afterFlush': + 'prefix': 'afterFlush' + 'body': 'Tracker.afterFlush(function(){ + \n\t${2:} + \n});', + + 'Tracker.active': + 'prefix': 'active' + 'body': 'Tracker.active;', + + 'Tracker.currentComputation': + 'prefix': 'currentComputation' + 'body': 'Tracker.currentComputation;', + + +#=================================================== +# Templates Snippets + + 'Template Rendered': + 'prefix': 'rendered' + 'body': 'Template.${1:name}.rendered = function(){\n\t${2}\n}', + 'Template Events': + 'prefix': 'events' + 'body': ' + Template.${1:name}.events({ + \n\t"click ${2:#event}": function(event, template){ + \n\t\t${3:} + \n\t} + \n}); + ', + 'Template Created': + 'prefix': 'created' + 'body': ' + Template.${1:name}.created = function(){ + \n\t${2:} + \n}; + ', + + 'Template Destroyed': + 'prefix': 'destroyed' + 'body': ' + Template.${1:name}.destroyed = function(){ + \n\t${2:} + \n}; + ', + + 'Template': + 'prefix': 'Template' + 'body': ' + \nTemplate.${1:name}.helpers({ + \n\tcreate: function(){ + \n\t\t${2:} + \n\t}, + \n\trendered: function(){ + \n\t\t${3:} + \n\t}, + \n\tdestroyed: function(){ + \n\t\t${4:} + \n\t}, + \n}); + \n\nTemplate.${9:name}.events({ + \n\t"${5:click #foo}": function(event, template){ + \n\t\t${6:} + \n\t} + \n}); + \n${7:} + ', + + 'Template Helpers': + 'prefix': 'helpers' + 'body': 'Template.${1:name}.helpers({\n\trendered: function(){\n\t\t${2}\n\t}\n});', + + 'Template.registerHelper': + 'prefix': 'registerHelper' + 'body': 'Template.registerHelper("${1:helperName}", function(${2:argument}){\n\t${3}\n});', + + +#=================================================== +# Blaze Snippets + + 'Blaze.render': + 'prefix': 'render' + 'body': 'Blaze.render(${1:templateOrView}, ${2:parentNode});', + 'Blaze.renderWithData': + 'prefix': 'renderWithData' + 'body': 'Blaze.renderWithData(${1:templateOrView}, ${2:data}, ${3:parentNode});', + 'Blaze.remove': + 'prefix': 'bremove' + 'body': 'Blaze.remove(${1:renderedView});', + 'Blaze.getData': + 'prefix': 'getData' + 'body': 'Blaze.getData(${1:elementOrView});', + 'Blaze.toHTML': + 'prefix': 'toHTML' + 'body': 'Blaze.toHTML(${1:templateOrView});', + 'Blaze.toHTMLWithData': + 'prefix': 'toHTMLWithData' + 'body': 'Blaze.toHTMLWithData(${1:templateOrView}, ${2:data});', + 'Blaze.toHTMLWithData': + 'prefix': 'toHTMLWithData' + 'body': 'Blaze.toHTMLWithData(${1:templateOrView}, ${2:data});', + 'Blaze.isTemplate': + 'prefix': 'isTemplate' + 'body': 'Blaze.isTemplate(${1:value});', + + +#=================================================== +# EJSON Snippets + + 'EJSON.parse': + 'prefix': 'parse' + 'body': 'EJSON.parse(${1:string});', + 'EJSON.stringify': + 'prefix': 'stringify' + 'body': 'EJSON.stringify(${1:string}, {indent: true});', + 'EJSON.clone': + 'prefix': 'clone' + 'body': 'EJSON.clone(${1:object});', + 'EJSON.equals': + 'prefix': 'deeequals' + 'body': 'EJSON.equals(${1:objectA}, ${2:objectB});', + 'EJSON.toJSONValue': + 'prefix': 'toJSON' + 'body': 'EJSON.toJSONValue(${1:value});', + 'EJSON.fromJSONValue': + 'prefix': 'fromJSON' + 'body': 'EJSON.fromJSONValue(${1:value});', + 'EJSON.isBinary': + 'prefix': 'isBinary' + 'body': 'EJSON.isBinary(${1:value});', + +#=================================================== +# HTTP Snippets + + 'HTTP Call': + 'prefix': 'httpcall' + 'body': 'HTTP.call("${1:meteorMethod}", function(error, result){ + \n\tif(error){ + \n\t\tconsole.log("error", error); + \n\t} + \n\tif(result){ + \n\t\t${2:} + \n\t} + \n});', + 'HTTP Get': + 'prefix': 'httpget' + 'body': 'HTTP.get("${1:meteorMethod}", function(error, result){ + \n\tif(error){ + \n\t\tconsole.log("error", error); + \n\t} + \n\tif(result){ + \n\t\t${2:} + \n\t} + \n});', + 'HTTP.post': + 'prefix': 'httppost' + 'body': 'HTTP.post("${1:meteorMethod}", ${2:dataObject}, function(error, result){ + \n\tif(error){ + \n\t\tconsole.log("error", error); + \n\t} + \n\tif(result){ + \n\t\t${3:} + \n\t} + \n});', + 'HTTP.put': + 'prefix': 'http.put' + 'body': 'HTTP.put("${1:meteorMethod}", ${2:dataObject}, function(error, result){ + \n\tif(error){ + \n\t\tconsole.log("error", error); + \n\t} + \n\tif(result){ + \n\t\t${3:} + \n\t} + \n});', + 'HTTP.del': + 'prefix': 'httpdel' + 'body': 'HTTP.del("${1:meteorMethod}", function(error, result){ + \n\tif(error){ + \n\t\tconsole.log("error", error); + \n\t} + \n\tif(result){ + \n\t\t${2:} + \n\t} + \n});', + + + + +#=================================================== +# Email Snippets + + 'Email.send': + 'prefix': 'Email' + 'body': 'Email.send({ + \n\tfrom: "${1:sender@somewhere.net}", + \n\tto: "${2:receiver@elsewhere.io}", + \n\tcc: "${3:carboncopy@elsewhere.io}", + \n\tbcc: "${4:lurker@somewhere.io}", + \n\treplyTo: "${5:public@somewhere.net}", + \n\tsubject: "${6:Hello Email}", + \n\ttext: "${7:lorem ispum...}", + \n\thtml: "${8:}", + \n\theaders: "${9:}", + \n});', + + +#=================================================== +# Assets Snippets + + + 'Assets.getText': + 'prefix': 'getText' + 'body': 'Assets.getText("${1:assetPath}", function(error, result){ + \n\tif(error){ + \n\t\tconsole.log("error", error); + \n\t} + \n\tif(result){ + \n\t\t${2:} + \n\t} + \n});', + 'Assets.getBinary': + 'prefix': 'getBinary' + 'body': 'Assets.getBinary("${1:assetPath}", function(error, result){\n\tif(error){ + \n\t\tconsole.log("error", error); + \n\t} + \n\tif(result){ + \n\t\t${2:} + \n\t} + \n});', + + +#=================================================== +# Router Snippets + + 'Router': + 'prefix': 'Router' + 'body': ' + Router.map(function(){ + \n\tthis.route("${1:routeName}"{ + \n\t\t${2} + \n\t}); + \n}); + ', + 'route': + 'prefix': 'route' + 'body': ' + this.route("${1:routeName}"{ + \n\tpath:"${2}", + \n\ttemplate:"${3}", + \n\twaitOn:function(){ + \n\t\t${4} + \n\t}, + \n\tdata:function(){ + \n\t\t${5} + \n\t}, + \n\tonBeforeAction:function(){ + \n\t\tsetPageTitle("${6}"); + \n\t}, + \n\tonAfterAction:function(){ + \n\t\t${7} + \n\t}, + \n}); + ', + 'Upsert Route': + 'prefix': 'UpsertRoute' + 'body': ' + Router.map(function(){ + \n\tthis.route("${1:routeName}"{ + \n\t\tpath:"/${2:route}/add", + \n\t\ttemplate:"${3:routeTemplate}", + \n\t\twaitOn:function(){ + \n\t\t\t${4} + \n\t\t}, + \n\t\tdata:function(){ + \n\t\t\treturn {}; + \n\t\t}, + \n\t\tonBeforeAction:function(){ + \n\t\t\tsetPageTitle("${5}"); + \n\t\t}, + \n\t\tonAfterAction:function(){ + \n\t\t\t${6} + \n\t\t}, + \n\t}); + + \n\tthis.route("${7:routeName}"{ + \n\t\tpath:"/${8}/edit/${9:paramId}", + \n\t\ttemplate:"${10: routeTemplate}", + \n\t\twaitOn:function(){ + \n\t\t\treturn Meteor.subscribe("${11: subscription}"); + \n\t\t}, + \n\t\tdata:function(){ + \n\t\t\treturn ${12: Collection}.findOne(this.params.${13: paramId}); + \n\t\t}, + \n\t\tonBeforeAction:function(){ + \n\t\t\tsetPageTitle("${14}"); + \n\t\t}, + \n\t\tonAfterAction:function(){ + \n\t\t\t${15} + \n\t\t}, + \n\t}); + \n}); + ', + + +#=================================================== +# Template + Router + + 'Page': + 'prefix': 'page' + 'body': ' + Router.map(function(){ + \n\tthis.route("${1:routeName}", { + \n\t\tpath: "/${2:route}", + \n\t\ttemplate: "${3:pageTemplate}", + \n\t\tonBeforeAction: function () { + \n\t\t\tsetPageTitle("${4:Page Title}"); + \n\t\t} + \n\t}); + \n}); + \n + \nTemplate.${5:pageTemplate}.helpers({ + \n\trendered: function(){ + \n\t\t${6:} + \n\t} + \n}); + \n\nTemplate.${7:pageTemplate}.events({ + \n\t"${8:click #foo}": function(event, template){ + \n\t\t${9:} + \n\t} + \n}); + ', + +#=================================================== +# Nightwatch + + 'verify.elementPresent': + 'prefix': 'vep' + 'body': '.verify.elementPresent("#${1}")${2}', + + 'verify.elementNotPresent': + 'prefix': 'venp' + 'body': '.verify.elementNotPresent("#${1}")${2}', + + 'waitForElementVisible': + 'prefix': 'wfev' + 'body': '.waitForElementVisible("#${1}", ${2})${3}', + + 'containsText': + 'prefix': 'vct' + 'body': '.verify.containsText("#${1}", "${2}")${3}', + + 'click': + 'prefix': 'click' + 'body': '.click("#${1}").pause(${2})${3}', + + 'attributeEquals': + 'prefix': 'ae' + 'body': '.verify.attributeEquals("#${1}", "value", "${2}")${3}', + + + + +#=================================================== +# Stylesheet / View Snippets + + + + + +'.less': + 'Responsive Stylesheets': + "prefix": "mobile" + "body": 'media' diff --git a/lib/stylesheet.less b/lib/stylesheet.less new file mode 100644 index 0000000..0263e58 --- /dev/null +++ b/lib/stylesheet.less @@ -0,0 +1,63 @@ +/* + * Your Stylesheet + * + * This stylesheet is loaded when Atom starts up and is reloaded automatically + * when it is changed. + * + * If you are unfamiliar with LESS, you can read more about it here: + * http://www.lesscss.org + */ + +.tree-view { + +} + +.editor { + //background-color: #222222; + .api.meteor{ + color: #ffffff; + } + .api.meteor.core{ + color: #E8C6B8; + } + .api.meteor.ddp{ + color: #FFA581; + } + .api.meteor.ddp.functions{ + color: #E87E75; + } + .api.meteor.http{ + color: #FF514F; + } + .api.meteor.template{ + color: #FFF443; + } + .api.meteor.template.api{ + color: #FFF56D; + } + .api.meteor.template.functions{ + color: #B3ABF5; + } + .api.meteor.blaze{ + color: #F51B15; + } + .api.meteor.blaze.functions{ + color: #F53B27; + } + .api.meteor.router{ + color: #52F3F5; + } + .api.meteor.router.functions{ + color: #83F5ED; + } + .api.meteor.collection{ + color: #E8D361; + } + .api.meteor.collection.functions{ + color: #F5EA66; + } +} + +.editor .cursor { + +} diff --git a/menus/meteor-api.cson b/menus/meteor-api.cson new file mode 100644 index 0000000..8329344 --- /dev/null +++ b/menus/meteor-api.cson @@ -0,0 +1,16 @@ +# See https://atom.io/docs/latest/creating-a-package#menus for more details +'context-menu': + '.overlayer': + 'Enable meteor-api': 'meteor-api:toggle' + +'menu': [ + { + 'label': 'Packages' + 'submenu': [ + 'label': 'meteor-api' + 'submenu': [ + { 'label': 'Toggle', 'command': 'meteor-api:toggle' } + ] + ] + } +] diff --git a/package.json b/package.json new file mode 100644 index 0000000..bb2992b --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "meteor-api", + "main": "./lib/meteor-api", + "version": "0.0.0", + "description": "Meteor API with tab completion and syntax highlighting.", + "activationEvents": ["meteor-api:toggle"], + "repository": "https://github.com/awatson1978/meteor-api", + "license": "MIT", + "engines": { + "atom": ">0.50.0" + }, + "dependencies": { + } +} diff --git a/spec/meteor-api-spec.coffee b/spec/meteor-api-spec.coffee new file mode 100644 index 0000000..51c443f --- /dev/null +++ b/spec/meteor-api-spec.coffee @@ -0,0 +1,29 @@ +MeteorApi = require '../lib/meteor-api' + +# Use the command `window:run-package-specs` (cmd-alt-ctrl-p) to run specs. +# +# To run a specific `it` or `describe` block add an `f` to the front (e.g. `fit` +# or `fdescribe`). Remove the `f` to unfocus the block. + +describe "MeteorApi", -> + activationPromise = null + + beforeEach -> + atom.workspaceView = new WorkspaceView + activationPromise = atom.packages.activatePackage('meteorApi') + + describe "when the meteor-api:toggle event is triggered", -> + it "attaches and then detaches the view", -> + expect(atom.workspaceView.find('.meteor-api')).not.toExist() + + # This is an activation event, triggering it will cause the package to be + # activated. + atom.workspaceView.trigger 'meteor-api:toggle' + + waitsForPromise -> + activationPromise + + runs -> + expect(atom.workspaceView.find('.meteor-api')).toExist() + atom.workspaceView.trigger 'meteor-api:toggle' + expect(atom.workspaceView.find('.meteor-api')).not.toExist() diff --git a/spec/meteor-api-view-spec.coffee b/spec/meteor-api-view-spec.coffee new file mode 100644 index 0000000..400a140 --- /dev/null +++ b/spec/meteor-api-view-spec.coffee @@ -0,0 +1,6 @@ +MeteorApiView = require '../lib/meteor-api-view' +{WorkspaceView} = require 'atom' + +describe "MeteorApiView", -> + it "has one valid test", -> + expect("life").toBe "easy" diff --git a/stylesheets/meteor-api.less b/stylesheets/meteor-api.less new file mode 100644 index 0000000..72549f2 --- /dev/null +++ b/stylesheets/meteor-api.less @@ -0,0 +1,8 @@ +// The ui-variables file is provided by base themes provided by Atom. +// +// See https://github.com/atom/atom-dark-ui/blob/master/stylesheets/ui-variables.less +// for a full listing of what's available. +@import "ui-variables"; + +.meteor-api { +}