├── .bowerrc ├── .editorconfig ├── .ember-cli ├── .env.sample ├── .eslintrc ├── .eslintrc.js ├── .gitignore ├── .jshintrc ├── .travis.yml ├── .watchmanconfig ├── README.md ├── app.json ├── app ├── adapters │ └── application.js ├── app.js ├── components │ ├── em-header.js │ ├── em-icon-clipboard.js │ ├── em-list.js │ ├── em-page.js │ ├── em-pagination.js │ ├── em-pkg.js │ └── observer-score.js ├── controllers │ └── packages │ │ └── list.js ├── helpers │ └── split-prefix.js ├── index.html ├── models │ └── package.js ├── resolver.js ├── router.js ├── routes │ └── packages │ │ └── list.js ├── serializers │ └── package.js ├── snippets │ ├── google-analytics.js │ └── perf-utils.js ├── styles │ └── app.css ├── templates │ ├── -footer.hbs │ ├── -placeholder-row.hbs │ ├── -table-header.hbs │ ├── application.hbs │ ├── components │ │ ├── em-header.hbs │ │ ├── em-icon-clipboard.hbs │ │ ├── em-list.hbs │ │ ├── em-page.hbs │ │ ├── em-pagination.hbs │ │ ├── em-pkg.hbs │ │ └── observer-score.hbs │ └── packages │ │ ├── list.hbs │ │ └── loading.hbs └── transitions.js ├── config ├── deploy.js ├── deprecation-workflow.js ├── environment.js ├── parse-flag.js └── targets.js ├── ember-cli-build.js ├── package.json ├── public ├── assets │ ├── favicon.png │ └── github-logo.svg ├── crossdomain.xml ├── osdd_file.xml └── robots.txt ├── testem.js ├── tests ├── .eslintrc.js ├── .jshintrc ├── helpers │ ├── destroy-app.js │ ├── module-for-acceptance.js │ ├── resolver.js │ └── start-app.js ├── index.html ├── test-helper.js └── unit │ ├── .gitkeep │ ├── components │ ├── em-header-test.js │ ├── em-icon-clipboard-test.js │ ├── em-pagination-test.js │ ├── em-pkg-test.js │ └── observer-score-test.js │ ├── controllers │ └── packages │ │ └── list-test.js │ ├── helpers │ └── split-prefix-test.js │ └── routes │ └── packages │ └── list-test.js ├── vendor ├── .gitkeep └── airplane-mode │ ├── addons.json │ └── gravatar.jpg └── yarn.lock /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bower_components", 3 | "analytics": false 4 | } 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | indent_style = space 14 | indent_size = 2 15 | 16 | [*.hbs] 17 | insert_final_newline = false 18 | 19 | [*.{diff,md}] 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /.ember-cli: -------------------------------------------------------------------------------- 1 | { 2 | /** 3 | Ember CLI sends analytics information by default. The data is completely 4 | anonymous, but there are times when you might want to disable this behavior. 5 | 6 | Setting `disableAnalytics` to true will prevent any data from being sent. 7 | */ 8 | "disableAnalytics": false 9 | } 10 | -------------------------------------------------------------------------------- /.env.sample: -------------------------------------------------------------------------------- 1 | DISTRIBUTION="" 2 | AWS_REGION="" 3 | AWS_BUCKET="" 4 | AWS_PROFILE="" 5 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["blimp"], 3 | "rules": { 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parserOptions: { 4 | ecmaVersion: 2017, 5 | sourceType: 'module' 6 | }, 7 | extends: 'eslint:recommended', 8 | env: { 9 | browser: true 10 | }, 11 | rules: { 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | 7 | # dependencies 8 | /node_modules 9 | /bower_components 10 | 11 | # misc 12 | /.sass-cache 13 | /connect.lock 14 | /coverage/* 15 | /libpeerconnection.log 16 | npm-debug.log* 17 | yarn-error.log 18 | testem.log 19 | 20 | # ember-try 21 | .node_modules.ember-try/ 22 | bower.json.ember-try 23 | package.json.ember-try 24 | 25 | .env 26 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "predef": [ 3 | "document", 4 | "window", 5 | "-Promise" 6 | ], 7 | "browser": true, 8 | "boss": true, 9 | "curly": true, 10 | "debug": false, 11 | "devel": true, 12 | "eqeqeq": true, 13 | "evil": true, 14 | "forin": false, 15 | "immed": false, 16 | "laxbreak": false, 17 | "newcap": true, 18 | "noarg": true, 19 | "noempty": false, 20 | "nonew": false, 21 | "nomen": false, 22 | "onevar": false, 23 | "plusplus": false, 24 | "regexp": false, 25 | "undef": true, 26 | "sub": true, 27 | "strict": false, 28 | "white": false, 29 | "eqnull": true, 30 | "esversion": 6, 31 | "unused": true 32 | } 33 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | language: node_js 3 | node_js: 4 | - "6" 5 | 6 | sudo: false 7 | dist: trusty 8 | 9 | addons: 10 | chrome: stable 11 | 12 | cache: 13 | yarn: true 14 | 15 | env: 16 | global: 17 | # See https://git.io/vdao3 for details. 18 | - JOBS=1 19 | 20 | before_install: 21 | - curl -o- -L https://yarnpkg.com/install.sh | bash 22 | - export PATH=$HOME/.yarn/bin:$PATH 23 | 24 | install: 25 | - yarn install --non-interactive 26 | 27 | script: 28 | - yarn test 29 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | { 2 | "ignore_dirs": ["tmp", "dist"] 3 | } 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ember-cli-addon-search 2 | 3 | This README outlines the details of collaborating on this Ember application. 4 | A short introduction of this app could easily go here. 5 | 6 | ## Deprecated 7 | 8 | This project has been deprecated, please visit [Ember Observer](https://emberobserver.com). 9 | 10 | ## Prerequisites 11 | 12 | You will need the following things properly installed on your computer. 13 | 14 | * [Git](https://git-scm.com/) 15 | * [Node.js](https://nodejs.org/) (with NPM) 16 | * [Bower](https://bower.io/) 17 | * [Ember CLI](https://ember-cli.com/) 18 | * [PhantomJS](http://phantomjs.org/) 19 | 20 | ## Installation 21 | 22 | * `git clone ` this repository 23 | * `cd ember-cli-addon-search` 24 | * `npm install` 25 | * `bower install` 26 | 27 | ## Running / Development 28 | 29 | * `ember serve` 30 | * Visit your app at [http://localhost:4200](http://localhost:4200). 31 | 32 | ### Code Generators 33 | 34 | Make use of the many generators for code, try `ember help generate` for more details 35 | 36 | ### Running Tests 37 | 38 | * `ember test` 39 | * `ember test --server` 40 | 41 | ### Building 42 | 43 | * `ember build` (development) 44 | * `ember build --environment production` (production) 45 | 46 | ### Deploying 47 | 48 | * `ember deploy prodcution` 49 | 50 | ## Further Reading / Useful Links 51 | 52 | * [ember.js](http://emberjs.com/) 53 | * [ember-cli](https://ember-cli.com/) 54 | * Development Browser Extensions 55 | * [ember inspector for chrome](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi) 56 | * [ember inspector for firefox](https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/) 57 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Ember Addons", 3 | "description": "Listing hundreds of modules that extend ember-cli.", 4 | "website": "http://www.emberaddons.com/", 5 | "repository": "https://github.com/gcollazo/ember-cli-addon-search/", 6 | "logo": "http://emberjs.com/images/logos/ember-logo.png", 7 | "keywords": ["ember", "ember.js", "ember-cli"], 8 | "env": { 9 | "BUILDPACK_URL": "https://github.com/tonycoco/heroku-buildpack-ember-cli.git", 10 | "NGINX_WORKERS": "4" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/adapters/application.js: -------------------------------------------------------------------------------- 1 | import DS from 'ember-data'; 2 | import config from 'ember-addons-website/config/environment'; 3 | 4 | export default DS.RESTAdapter.extend({ 5 | host: config.host, 6 | 7 | buildURL(/* type, id */) { 8 | return this.get('host') + '/addons.json'; 9 | } 10 | }); 11 | -------------------------------------------------------------------------------- /app/app.js: -------------------------------------------------------------------------------- 1 | import Application from '@ember/application'; 2 | import Resolver from './resolver'; 3 | import loadInitializers from 'ember-load-initializers'; 4 | import config from './config/environment'; 5 | 6 | const App = Application.extend({ 7 | modulePrefix: config.modulePrefix, 8 | podModulePrefix: config.podModulePrefix, 9 | Resolver 10 | }); 11 | 12 | loadInitializers(App, config.modulePrefix); 13 | 14 | export default App; 15 | -------------------------------------------------------------------------------- /app/components/em-header.js: -------------------------------------------------------------------------------- 1 | import Component from '@ember/component'; 2 | import { computed } from '@ember/object'; 3 | 4 | export default Component.extend({ 5 | tagName: 'header', 6 | 7 | placeholder: computed('packageCount', function() { 8 | return `Search ${this.get('packageCount')} addons`; 9 | }), 10 | 11 | actions: { 12 | resetPageCount() { 13 | this.sendAction('reset-page'); 14 | } 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /app/components/em-icon-clipboard.js: -------------------------------------------------------------------------------- 1 | import Component from '@ember/component'; 2 | 3 | export default Component.extend({ 4 | tagName: 'div', 5 | classNames: ['clipboard'], 6 | 7 | mouseEnter() { 8 | this._showToolip('Copy Install Command'); 9 | }, 10 | 11 | actions: { 12 | success() { 13 | this._showToolip('Copied!'); 14 | }, 15 | 16 | error() { 17 | this._showToolip('Error :('); 18 | } 19 | }, 20 | 21 | _showToolip(text) { 22 | this.$('[data-toggle="tooltip"]') 23 | .attr('data-original-title', text).tooltip('show'); 24 | } 25 | }); 26 | -------------------------------------------------------------------------------- /app/components/em-list.js: -------------------------------------------------------------------------------- 1 | import Component from '@ember/component'; 2 | import { computed, get } from '@ember/object'; 3 | import { equal } from '@ember/object/computed'; 4 | import { task, timeout } from 'ember-concurrency'; 5 | import filterByQuery from 'ember-cli-filter-by-query/util/filter'; 6 | 7 | // when sorting the list of 3500 addons every little bit coints, rather then 8 | // constantly parsing and resplitting the paths (like time.modified), we 9 | // pre-split them once per sort. 10 | function prebuildGet(path) { 11 | const split = path.split('.'); 12 | 13 | return function(obj) { 14 | for (let i = 0; i < split.length; i++) { 15 | const key = split[i]; 16 | if (typeof obj !== 'object' && obj !== null) { 17 | return; 18 | } 19 | obj = get(obj, key); 20 | } 21 | 22 | return obj; 23 | }; 24 | } 25 | 26 | const QUERY_DEBOUNCE = 300; 27 | 28 | export default Component.extend({ 29 | tagName: 'table', 30 | classNames: 'table table-packages', 31 | 32 | init() { 33 | this._super(...arguments); 34 | this._filterList(this.get('meta.query')); 35 | }, 36 | 37 | didUpdateAttrs() { 38 | this._super(...arguments); 39 | this.get('taskFilterList').perform(this.get('meta.query')); 40 | }, 41 | 42 | filteredList: [], 43 | taskFilterList: task(function* (query) { 44 | yield timeout(query ? QUERY_DEBOUNCE : 0); 45 | this._filterList(query); 46 | }).restartable(), 47 | 48 | _filterList(query) { 49 | const filteredList = filterByQuery( 50 | this.get('list'), 51 | ['name', '_npmUser.name', 'description'], 52 | query, 53 | { conjunction: 'and' } 54 | ); 55 | this.set('filteredList', filteredList); 56 | }, 57 | 58 | sortAscending: true, 59 | sortProperty: 'time.modified', 60 | 61 | sortedPackages: computed( 62 | 'filteredList', 63 | 'sortProperty', 64 | 'sortAscending', 65 | function() { 66 | const prop = this.get('sortProperty'); 67 | const get = prebuildGet(prop); // get function tuned for this sortProperty 68 | 69 | const sorted = this.get('filteredList').toArray().sort(function(x, y) { 70 | const x1 = get(x); 71 | const y1 = get(y); 72 | return x1 < y1 ? -1 : x1 > y1 ? 1 : 0; 73 | }); 74 | 75 | if (this.get('sortAscending')) { 76 | sorted.reverse(); 77 | } 78 | return sorted; 79 | }).readOnly(), 80 | 81 | currentPageContent: computed( 82 | 'sortedPackages.[]', 'meta.{page,limit}', 83 | function() { 84 | const { page, limit } = this.get('meta'); 85 | return this.get('sortedPackages').slice((page - 1) * limit, page * limit); 86 | } 87 | ).readOnly(), 88 | 89 | nothingFound: equal('sortedPackages.length', 0), 90 | 91 | actions: { 92 | sortBy(propertyKey) { 93 | if (propertyKey === this.get('sortProperty')) { 94 | this.toggleProperty('sortAscending'); 95 | } 96 | this.set('sortProperty', propertyKey); 97 | } 98 | } 99 | }); 100 | -------------------------------------------------------------------------------- /app/components/em-page.js: -------------------------------------------------------------------------------- 1 | import Component from '@ember/component'; 2 | 3 | export default Component.extend({ 4 | tagName: 'table', 5 | classNames: 'table table-packages', 6 | 7 | actions: { 8 | sortBy(...args) { 9 | this.sortBy(...args); 10 | } 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /app/components/em-pagination.js: -------------------------------------------------------------------------------- 1 | import $ from 'jquery'; 2 | import Component from '@ember/component'; 3 | import { computed } from '@ember/object'; 4 | 5 | export default Component.extend({ 6 | tagName: 'div', 7 | classNames: ['pagination-row'], 8 | 9 | page: 1, 10 | limit: 12, 11 | list: [], 12 | 13 | didInsertElement() { 14 | this._super(...arguments); 15 | $(document).on('keyup', (event) => { 16 | this.onGlobalKeyUp(event); 17 | }); 18 | }, 19 | 20 | willDestroyElement() { 21 | this._super(...arguments); 22 | $(document).off('keyup'); 23 | }, 24 | 25 | onGlobalKeyUp(event) { 26 | const key = event.keyCode; 27 | const tag = event.target.tagName.toLowerCase(); 28 | 29 | if (tag === 'input') { 30 | return; 31 | } 32 | 33 | switch (key) { 34 | case 37: 35 | this.send('previousPage'); 36 | break; 37 | case 39: 38 | this.send('nextPage'); 39 | break; 40 | } 41 | }, 42 | 43 | hasPreviousPage: computed('page', function() { 44 | return this.get('page') !== 1; 45 | }).readOnly(), 46 | 47 | hasNextPage: computed('page', 'limit', 'list.length', function() { 48 | const page = this.get('page'); 49 | const limit = this.get('limit'); 50 | const length = this.get('list.length'); 51 | 52 | return page * limit < length; 53 | }).readOnly(), 54 | 55 | actions: { 56 | nextPage() { 57 | if (this.get('hasNextPage')) { 58 | this.sendAction('next'); 59 | } 60 | }, 61 | 62 | previousPage() { 63 | if (this.get('hasPreviousPage')) { 64 | this.sendAction('previous'); 65 | } 66 | } 67 | } 68 | }); 69 | -------------------------------------------------------------------------------- /app/components/em-pkg.js: -------------------------------------------------------------------------------- 1 | import { readOnly } from '@ember/object/computed'; 2 | import Component from '@ember/component'; 3 | import { computed } from '@ember/object'; 4 | import moment from 'moment'; 5 | 6 | export default Component.extend({ 7 | tagName: 'tr', 8 | classNames: ['package'], 9 | 10 | downloads: readOnly('pkg.downloads.downloads'), 11 | user: readOnly('pkg._npmUser'), 12 | hideInstallCommand: true, 13 | 14 | installCommand: computed('pkg.name', function() { 15 | return `ember install ${this.get('pkg.name')}`; 16 | }), 17 | 18 | isNew: computed('pkg.time.created', function() { 19 | return moment().diff(this.get('pkg.time.created'), 'days') <= 7; 20 | }).readOnly(), 21 | 22 | hasDescription: computed('pkg.description', function() { 23 | const defaultString = 'The default blueprint for ember-cli addons.'; 24 | return this.get('pkg.description') !== defaultString; 25 | }).readOnly() 26 | }); 27 | -------------------------------------------------------------------------------- /app/components/observer-score.js: -------------------------------------------------------------------------------- 1 | import Component from '@ember/component'; 2 | import { computed } from '@ember/object'; 3 | 4 | export default Component.extend({ 5 | computedScore: computed('score', function() { 6 | const score = this.get('score'); 7 | if (score === -2) { 8 | return '-'; 9 | } else if (score === -1) { 10 | return 'WIP'; 11 | } else { 12 | return score; 13 | } 14 | }) 15 | }); 16 | -------------------------------------------------------------------------------- /app/controllers/packages/list.js: -------------------------------------------------------------------------------- 1 | import Controller from '@ember/controller'; 2 | import { readOnly } from '@ember/object/computed'; 3 | 4 | export default Controller.extend({ 5 | queryParams: ['query', 'page'], 6 | 7 | query: '', 8 | page: 1, 9 | limit: 12, 10 | packageCount: readOnly('model.length'), 11 | 12 | actions: { 13 | resetPage() { 14 | this.set('page', 1); 15 | }, 16 | nextPage() { 17 | this.incrementProperty('page'); 18 | }, 19 | 20 | previousPage() { 21 | this.decrementProperty('page'); 22 | } 23 | } 24 | }); 25 | -------------------------------------------------------------------------------- /app/helpers/split-prefix.js: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | import { htmlSafe } from '@ember/string'; 3 | import Ember from 'ember'; 4 | 5 | const { 6 | Handlebars: { Utils: { escapeExpression } } 7 | } = Ember; 8 | 9 | const NAME_REGEX = /^(ember\-cli\-|ember\-)(.+)/; 10 | 11 | export function splitPrefix(value) { 12 | if ((typeof value[0]) !== 'string') { 13 | return null; 14 | } 15 | 16 | const parts = value[0].match(NAME_REGEX); 17 | 18 | if (!parts) { 19 | return value[0]; 20 | } 21 | 22 | const prefix = parts[1]; 23 | const name = escapeExpression(parts[2]); 24 | 25 | return htmlSafe( 26 | `${prefix}` + 27 | `${name}` 28 | ); 29 | } 30 | 31 | export default helper(splitPrefix); 32 | -------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Ember Addons 7 | 8 | 9 | 10 | 11 | 12 | {{content-for "head"}} 13 | 14 | 15 | 16 | 17 | 18 | {{content-for "snippets/perf-utils"}} 19 | 20 | {{content-for "head-footer"}} 21 | 22 | 23 | {{content-for "body"}} 24 | 25 |
26 |
27 |
28 |
29 |
30 |

Ember Addons

31 |
32 |
33 |
34 | 35 |
36 |
37 | 56 |
57 |
58 |
59 |
60 |
61 |
62 |

Loading...

63 |
64 |
65 |
66 |
67 | 68 | {{content-for "snippets/google-analytics"}} 69 | 70 | 71 | 72 | 73 | 78 | 79 | 80 | 81 | {{content-for "body-footer"}} 82 | 83 | 84 | -------------------------------------------------------------------------------- /app/models/package.js: -------------------------------------------------------------------------------- 1 | import DS from 'ember-data'; 2 | const { attr } = DS; 3 | 4 | export default DS.Model.extend({ 5 | _npmUser: attr(), 6 | author: attr(), 7 | demoURL: attr(), 8 | description: attr(), 9 | downloads: attr(), 10 | emberObserver: attr(), 11 | github: attr(), 12 | name: attr(), 13 | time: attr() 14 | }); 15 | -------------------------------------------------------------------------------- /app/resolver.js: -------------------------------------------------------------------------------- 1 | import Resolver from 'ember-resolver'; 2 | 3 | export default Resolver; 4 | -------------------------------------------------------------------------------- /app/router.js: -------------------------------------------------------------------------------- 1 | import EmberRouter from '@ember/routing/router'; 2 | import config from './config/environment'; 3 | 4 | const Router = EmberRouter.extend({ 5 | location: config.locationType, 6 | 7 | willTransition() { 8 | this._super(...arguments); 9 | performance.mark('willTransition'); 10 | }, 11 | 12 | didTransition() { 13 | this._super(...arguments); 14 | performance.mark('didTransition'); 15 | }, 16 | 17 | rootURL: config.rootURL 18 | }); 19 | 20 | export default Router.map(function() { 21 | this.route('packages', { resetNamespace: true, path: '/' }, function() { 22 | this.route('list', { path: '/' }); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /app/routes/packages/list.js: -------------------------------------------------------------------------------- 1 | import { schedule } from '@ember/runloop'; 2 | import Route from '@ember/routing/route'; 3 | 4 | export default Route.extend({ 5 | queryParams: { 6 | query: { 7 | replace: true 8 | } 9 | }, 10 | 11 | model() { 12 | return this.store.findAll('package'); 13 | }, 14 | 15 | afterModel() { 16 | performance.mark('dataLoaded'); 17 | schedule('afterRender', renderEnd); 18 | } 19 | }); 20 | 21 | /* 22 | * This provides two additional benchmarking modes `?perf.profile` and 23 | * `?perf.tracing`. The former wraps the initial render in a CPU profile. The 24 | * latter is intended to be used with `chrome-tracing` where it redirects to 25 | * `about:blank` after the initial render as the termination signal. 26 | */ 27 | function renderEnd() { 28 | requestAnimationFrame(() => { 29 | performance.mark('beforePaint'); 30 | 31 | requestAnimationFrame(() => { 32 | performance.mark('afterPaint'); 33 | 34 | performance.measure('assets', 'domLoading', 'beforeVendor'); 35 | 36 | performance.measure('evalVendor', 'beforeVendor', 'beforeApp'); 37 | performance.measure('evalApp', 'beforeApp', 'afterApp'); 38 | 39 | performance.measure('boot', 'beforeVendor', 'willTransition'); 40 | performance.measure('routing', 'willTransition', 'didTransition'); 41 | performance.measure('render', 'didTransition', 'beforePaint'); 42 | performance.measure('paint', 'beforePaint', 'afterPaint'); 43 | 44 | performance.measure('data', 'willTransition', 'dataLoaded'); 45 | performance.measure('afterData', 'dataLoaded', 'beforePaint'); 46 | 47 | if (location.search === '?perf.tracing') { 48 | document.location.href = 'about:blank'; 49 | } else if (location.search === '?perf.profile') { 50 | console.profileEnd('initialRender'); 51 | } 52 | }); 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /app/serializers/package.js: -------------------------------------------------------------------------------- 1 | import DS from 'ember-data'; 2 | 3 | let id = 0; 4 | export default DS.JSONSerializer.extend({ 5 | normalizeResponse(store, type, payload) { 6 | return { 7 | data: payload.map(attributes => { 8 | return { 9 | id: id++, 10 | type: 'package', 11 | attributes 12 | }; 13 | }) 14 | }; 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /app/snippets/google-analytics.js: -------------------------------------------------------------------------------- 1 | /* jshint ignore:start */ 2 | (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ 3 | (i[r].q=i[r].q||[]).push(arguments);},i[r].l=1*new Date(),a=s.createElement(o), 4 | m=s.getElementsByTagName(o)[0],a.async=1,a.src=g,m.parentNode.insertBefore(a,m); 5 | })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); 6 | 7 | window.ga('create', 'UA-25728534-11', 'auto'); 8 | window.ga('send', 'pageview'); 9 | /* jshint ignore:end */ 10 | -------------------------------------------------------------------------------- /app/snippets/perf-utils.js: -------------------------------------------------------------------------------- 1 | window.performance = window.performance || {}; 2 | 3 | if (!performance.mark) { 4 | performance.mark = function() {}; 5 | performance.measure = function() {}; 6 | } 7 | 8 | // WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=137407 9 | window._performance = window.performance; 10 | 11 | if (!console.profile) { 12 | console.profile = function() {}; 13 | console.profileEnd = function() {}; 14 | } 15 | -------------------------------------------------------------------------------- /app/styles/app.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body { 6 | font-size: 16px; 7 | } 8 | 9 | header { 10 | background-color: #ea3723; 11 | padding: 20px 0 12 | } 13 | 14 | a, a:hover, a:active, a:visited { 15 | color: #ea3723; 16 | } 17 | 18 | a span.name-prefix { 19 | opacity: 0.33; 20 | } 21 | 22 | .search-wrapper { 23 | background-color: #ea3723; 24 | } 25 | 26 | .container-loading { 27 | text-align: center; 28 | padding: 50px 0; 29 | } 30 | 31 | .loading { 32 | color:#7f7f7f; 33 | } 34 | 35 | .container-footer { 36 | text-align: center; 37 | padding: 50px 0; 38 | font-size: 13px; 39 | color: #7f7f7f; 40 | border-top: 1px solid #d5d5d5; 41 | } 42 | 43 | .branding { 44 | position: relative; 45 | z-index: 1; 46 | color: white; 47 | font-weight: 100; 48 | margin:0; 49 | font-size: 40px; 50 | padding-top: 4px; 51 | } 52 | 53 | .branding a { 54 | color: white; 55 | } 56 | 57 | .branding a:hover, 58 | .branding a:active, 59 | .branding a:focus { 60 | text-decoration: none; 61 | } 62 | 63 | .top-menu-wrapper { 64 | font-size: 22px; 65 | padding-top: 10px; 66 | overflow: hidden; 67 | } 68 | 69 | a.top-menu-link, 70 | a.top-menu-link:hover { 71 | color: white; 72 | } 73 | 74 | .search-field { 75 | border-radius: 4px; 76 | border: 2px solid #A94442; 77 | font-size: 18px; 78 | height: 50px; 79 | } 80 | 81 | .form-control:focus { 82 | border-color: #A94442; 83 | box-shadow: none !important; 84 | } 85 | 86 | .search-field[disabled=disabled] { 87 | background-color: rgba(255, 255, 255, 0.6); 88 | } 89 | 90 | input[type="search"]::-webkit-search-cancel-button { 91 | -webkit-appearance: searchfield-cancel-button; 92 | } 93 | 94 | .table th { 95 | font-size: 12px; 96 | } 97 | 98 | .cell-name, 99 | .cell-gravatar, 100 | .cell-downloads, 101 | .cell-updated, 102 | .cell-travis { 103 | vertical-align: middle !important; 104 | color: #7f7f7f; 105 | } 106 | 107 | .cell-name { 108 | padding: 8px 8px 15px 8px !important; 109 | } 110 | 111 | .cell-gravatar { 112 | width: 190px; 113 | } 114 | 115 | .cell-downloads, 116 | .cell-updated { 117 | width: 130px; 118 | } 119 | 120 | .cell-travis { 121 | padding: 0; 122 | width: 100px; 123 | } 124 | 125 | .cell-clipboard, .cell-github { 126 | width: 42px; 127 | vertical-align: middle !important; 128 | } 129 | 130 | .clipboard, .github-logo { 131 | display:none; 132 | } 133 | 134 | .clipboard { 135 | padding-top: 5px; 136 | padding-left: 10px; 137 | cursor: pointer; 138 | } 139 | 140 | .github-logo { 141 | padding-right: 10px; 142 | } 143 | 144 | tr.package:hover .clipboard, 145 | tr.package:hover .github-logo { 146 | display: inline-block; 147 | } 148 | 149 | a.sort-button { 150 | color: black; 151 | } 152 | 153 | .table-packages { 154 | margin-top: 20px; 155 | } 156 | 157 | .gravatar { 158 | border-radius: 50%; 159 | margin-right: 5px; 160 | } 161 | 162 | .package-link { 163 | font-size: 24px; 164 | } 165 | 166 | .new-package { 167 | display:inline-block; 168 | background-color: #ea3723; 169 | font-size: 11px; 170 | color:white; 171 | padding:1px 4px; 172 | position: relative; 173 | top: -4px; 174 | } 175 | 176 | .demo-link { 177 | display:inline-block; 178 | color: #ea3723; 179 | border: 1px solid #ea3723; 180 | font-size: 11px; 181 | padding:1px 4px; 182 | } 183 | 184 | .demo-link:hover { 185 | text-decoration: none; 186 | background-color: #ea3723; 187 | color: white; 188 | } 189 | 190 | .demo-link:focus { 191 | text-decoration: none; 192 | } 193 | 194 | .list-package-details { 195 | font-size: 11px; 196 | } 197 | 198 | .list-package-details > li { 199 | background-color: #e6e6e6; 200 | margin-bottom: 3px; 201 | } 202 | 203 | .not-found { 204 | text-align: center; 205 | font-size: 20px; 206 | padding: 50px 0; 207 | color: #7f7f7f; 208 | font-weight: bold; 209 | } 210 | 211 | .twitter-badge-list-item { 212 | position: relative; 213 | top: 3px; 214 | } 215 | 216 | 217 | .pagination-row { 218 | text-align: center; 219 | margin-bottom: 30px; 220 | } 221 | 222 | .pagination-link, 223 | .pagination-link:visited { 224 | display: inline-block; 225 | margin-top: 20px; 226 | padding: 15px 20px; 227 | width: 200px; 228 | border-radius: 3px; 229 | border: 2px solid #d5d5d5; 230 | background-color: #FFF; 231 | color: #7f7f7f; 232 | outline:none; 233 | } 234 | 235 | .pagination-link:active { 236 | background-color: #bfbfbf !important; 237 | } 238 | 239 | .pagination-link.enabled:hover { 240 | color: #FFF; 241 | background-color: #d6d6d6; 242 | } 243 | 244 | .pagination-link.disabled { 245 | color: #d9d9d9; 246 | border: 2px solid #d9d9d9; 247 | } 248 | 249 | .score { 250 | display: inline-block; 251 | color: white; 252 | height: 40px; 253 | width: 40px; 254 | line-height: 40px; 255 | text-align: center; 256 | border-radius: 3px; 257 | } 258 | 259 | .score--s-, 260 | .score--sWIP { 261 | background-color: #ACACAC; 262 | } 263 | 264 | .score--s1 { 265 | background-color: #E12728; 266 | } 267 | 268 | .score--s2 { 269 | background-color: #E12728; 270 | } 271 | 272 | .score--s3 { 273 | background-color: #EE9428; 274 | } 275 | 276 | .score--s4 { 277 | background-color: #EE9428; 278 | } 279 | 280 | .score--s5 { 281 | background-color: #F7C428; 282 | } 283 | 284 | .score--s6 { 285 | background-color: #F7C428; 286 | } 287 | 288 | .score--s7 { 289 | background-color: #A1D916; 290 | } 291 | 292 | .score--s8 { 293 | background-color: #A1D916; 294 | } 295 | 296 | .score--s9 { 297 | background-color: #66DD1D; 298 | } 299 | 300 | .score--s10 { 301 | background-color: #3C820A; 302 | } 303 | 304 | /* Placeholder styles */ 305 | .placeholder__pakcage-name { 306 | background-color: #F5F5F5; 307 | width: 280px; 308 | height: 24px; 309 | margin-top: 7px; 310 | } 311 | 312 | .placeholder__description-line { 313 | margin-top: 3px; 314 | background-color: #F5F5F5; 315 | width: 280px; 316 | height: 14px; 317 | } 318 | 319 | .placeholder__demo-button { 320 | margin-top: 3px; 321 | background-color: #F5F5F5; 322 | height:20px; 323 | width: 45px; 324 | } 325 | 326 | .placeholder__gravatar { 327 | background-color: #F5F5F5; 328 | width: 30px; 329 | height: 30px; 330 | display: inline-block; 331 | vertical-align: middle; 332 | } 333 | 334 | .placeholder__username { 335 | display: inline-block; 336 | background-color: #F5F5F5; 337 | height: 16px; 338 | width: 70px; 339 | display: inline-block; 340 | vertical-align: middle; 341 | } 342 | 343 | .placeholder__score { 344 | background-color: #F5F5F5; 345 | } 346 | 347 | .placeholder__updated { 348 | background-color: #F5F5F5; 349 | height: 16px; 350 | width: 80px; 351 | } 352 | 353 | /* xs */ 354 | @media (min-width: 0px) and (max-width: 767px) { 355 | .branding { 356 | font-size: 26px; 357 | margin-bottom: 8px; 358 | text-align: center; 359 | } 360 | 361 | .description { 362 | word-wrap: break-word; 363 | width: 270px; 364 | } 365 | } 366 | 367 | /* sm */ 368 | @media (min-width: 768px) and (max-width: 991px) { 369 | .branding { 370 | font-size: 26px; 371 | padding-top: 12px; 372 | } 373 | 374 | .description { 375 | width: 220px; 376 | } 377 | } 378 | 379 | /* md */ 380 | @media (min-width: 992px) and (max-width: 1199px) { 381 | .branding { 382 | font-size: 32px; 383 | padding-top: 8px; 384 | } 385 | } 386 | 387 | /* lg */ 388 | @media (min-width: 1200px) {} 389 | -------------------------------------------------------------------------------- /app/templates/-footer.hbs: -------------------------------------------------------------------------------- 1 |
2 |
3 | 11 |
12 |
13 | -------------------------------------------------------------------------------- /app/templates/-placeholder-row.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /app/templates/-table-header.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | NAME 5 | 6 | 7 | 8 | 9 | 10 | 11 | OWNER 12 | 13 | 14 | 15 | 16 | SCORE 17 | 18 | 19 | 20 | 21 | UPDATED 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/templates/application.hbs: -------------------------------------------------------------------------------- 1 | {{ember-load-remover}} 2 | {{outlet}} 3 | {{partial 'footer'}} 4 | -------------------------------------------------------------------------------- /app/templates/components/em-header.hbs: -------------------------------------------------------------------------------- 1 | {{yield}} 2 |
3 |
4 |
5 |

{{#link-to 'packages.list' (query-params page=1 query="")}} 6 | Ember Addons{{/link-to}} 7 |

8 |
9 |
10 | {{#if packageCount}} 11 | {{input type="search" 12 | value=query 13 | placeholder=placeholder 14 | class="form-control search-field" 15 | autofocus="autofocus" 16 | key-press="resetPageCount"}} 17 | {{else}} 18 |
19 | 20 |
21 | {{/if}} 22 |
23 | 37 |
38 |
39 | -------------------------------------------------------------------------------- /app/templates/components/em-icon-clipboard.hbs: -------------------------------------------------------------------------------- 1 | {{!-- {{#clip-board text=attrs.command tagName='span'}} 2 | 3 | 4 | 5 | {{/clip-board}} --}} 6 | 7 | 8 | {{#copy-button 9 | tagName='span' 10 | clipboardText=attrs.command 11 | success=(action 'success') 12 | error=(action 'error') 13 | }} 14 | 15 | 16 | 17 | {{/copy-button}} 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/templates/components/em-list.hbs: -------------------------------------------------------------------------------- 1 | {{#liquid-bind 2 | (hash 3 | list=currentPageContent 4 | meta=meta 5 | ) 6 | class="lf-slider" as |currentState|}} 7 | {{em-page 8 | list=currentState.list 9 | query=currentState.meta.query 10 | 11 | sortBy=(action 'sortBy') 12 | }} 13 | {{/liquid-bind}} 14 | 15 | {{em-pagination 16 | list=sortedPackages 17 | page=meta.page 18 | limit=meta.limit 19 | previous=previous 20 | next=next 21 | }} 22 | -------------------------------------------------------------------------------- /app/templates/components/em-page.hbs: -------------------------------------------------------------------------------- 1 | 2 | {{partial "-table-header"}} 3 | 4 | 5 | 6 | {{#each list key="id" as |pkg|}} 7 | {{em-pkg pkg=pkg}} 8 | {{else}} 9 | 10 |

Nothing found for "{{query}}"

11 | 12 | {{/each}} 13 | 14 | -------------------------------------------------------------------------------- /app/templates/components/em-pagination.hbs: -------------------------------------------------------------------------------- 1 | Previous 2 | Next 3 | -------------------------------------------------------------------------------- /app/templates/components/em-pkg.hbs: -------------------------------------------------------------------------------- 1 | 2 | {{split-prefix pkg.name}} 5 | {{#if isNew}} 6 |
NEW
7 | {{/if}} 8 | {{#if hasDescription}} 9 |
10 | {{pkg.description}} 11 |
12 | {{/if}} 13 | {{#if pkg.demoURL}} 14 |
15 | DEMO 16 |
17 | {{/if}} 18 | 19 | 20 | {{em-icon-clipboard 21 | command=installCommand 22 | color=(if hideInstallCommand '#7f7f7f' '#ea3723') 23 | }} 24 | 25 | 26 | {{#if pkg.github}} 27 | 28 | 31 | 32 | {{/if}} 33 | 34 | 35 | 36 | 37 | {{user.name}} 38 | 39 | 40 | 41 | {{observer-score 42 | score=pkg.emberObserver.score 43 | name=pkg.name}} 44 | 45 | 46 | {{moment-from-now pkg.time.modified}} 47 | 48 | -------------------------------------------------------------------------------- /app/templates/components/observer-score.hbs: -------------------------------------------------------------------------------- 1 | 2 |
3 | {{computedScore}} 4 |
5 |
6 | -------------------------------------------------------------------------------- /app/templates/packages/list.hbs: -------------------------------------------------------------------------------- 1 | {{em-header 2 | packageCount=packageCount 3 | query=query 4 | reset-page=(action 'resetPage') 5 | }} 6 | 7 |
8 |
9 |
10 | 11 | {{em-list 12 | list=model 13 | 14 | meta=(hash 15 | query=query 16 | page=page 17 | limit=limit 18 | packageCount=packageCount 19 | ) 20 | 21 | previous=(action 'previousPage') 22 | next=(action 'nextPage') 23 | }} 24 | 25 |
26 |
27 |
28 | -------------------------------------------------------------------------------- /app/templates/packages/loading.hbs: -------------------------------------------------------------------------------- 1 | {{em-header}} 2 | 3 |
4 |
5 |
6 | 7 | 8 | {{partial "-table-header"}} 9 | 10 | 11 | {{partial "-placeholder-row"}} 12 | {{partial "-placeholder-row"}} 13 | {{partial "-placeholder-row"}} 14 | {{partial "-placeholder-row"}} 15 | {{partial "-placeholder-row"}} 16 | {{partial "-placeholder-row"}} 17 | {{partial "-placeholder-row"}} 18 | {{partial "-placeholder-row"}} 19 | {{partial "-placeholder-row"}} 20 | {{partial "-placeholder-row"}} 21 | {{partial "-placeholder-row"}} 22 | {{partial "-placeholder-row"}} 23 | 24 |
25 |
26 |
27 |
28 | -------------------------------------------------------------------------------- /app/transitions.js: -------------------------------------------------------------------------------- 1 | const opts = { duration: 300, delay: 100, easing: 'easeInOutQuart' }; 2 | 3 | // Only animate between page results if the distance between the pages is one. 4 | // This avoids animations occuring when the distance between pages is possibly more 5 | // that one (i.e. clicking the logo). 6 | 7 | export default function(){ 8 | this.transition( 9 | this.hasClass('lf-slider'), 10 | this.toValue(function(newPage, oldPage){ 11 | return newPage.meta.page - 1 === oldPage.meta.page; 12 | }), 13 | this.use('toLeft', opts) 14 | ); 15 | 16 | this.transition( 17 | this.hasClass('lf-slider'), 18 | this.toValue(function(newPage, oldPage){ 19 | return newPage.meta.page + 1 === oldPage.meta.page; 20 | }), 21 | this.use('toRight', opts) 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /config/deploy.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | module.exports = function(deployTarget) { 3 | var ENV = { 4 | build: {}, 5 | pipeline: { 6 | activateOnDeploy: true 7 | }, 8 | s3: { 9 | profile: process.env.AWS_PROFILE, 10 | filePattern: '*' 11 | }, 12 | cloudfront: { 13 | profile: process.env.AWS_PROFILE 14 | } 15 | }; 16 | 17 | if (deployTarget === 'production') { 18 | ENV.build.environment = 'production'; 19 | ENV.s3.bucket = process.env.AWS_BUCKET; 20 | ENV.s3.region = process.env.AWS_REGION; 21 | ENV.cloudfront.distribution = process.env.DISTRIBUTION; 22 | } 23 | 24 | // Note: if you need to build some configuration asynchronously, you can return 25 | // a promise that resolves with the ENV object instead of returning the 26 | // ENV object synchronously. 27 | return ENV; 28 | }; 29 | -------------------------------------------------------------------------------- /config/deprecation-workflow.js: -------------------------------------------------------------------------------- 1 | window.deprecationWorkflow = window.deprecationWorkflow || {}; 2 | window.deprecationWorkflow.config = { 3 | workflow: [ 4 | { handler: "throw", matchMessage: "Using the injected `container` is deprecated. Please use the `getOwner` helper instead to access the owner of this object." } 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /config/environment.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 'use strict'; 3 | 4 | let parseFlag = require('./parse-flag'); 5 | let AIRPLANE_MODE = parseFlag('AIRPLANE_MODE', false); 6 | 7 | module.exports = function(environment) { 8 | let ENV = { 9 | host: AIRPLANE_MODE ? '/assets' : 'https://io-builtwithember-addons-data.s3.amazonaws.com', 10 | modulePrefix: 'ember-addons-website', 11 | environment, 12 | rootURL: '/', 13 | locationType: 'auto', 14 | EmberENV: { 15 | FEATURES: { 16 | // Here you can enable experimental features on an ember canary build 17 | // e.g. 'with-controller': true 18 | }, 19 | EXTEND_PROTOTYPES: { 20 | // Prevent Ember Data from overriding Date.parse. 21 | Date: false 22 | } 23 | }, 24 | 25 | APP: { 26 | // Here you can pass flags/options to your application instance 27 | // when it is created 28 | } 29 | }; 30 | 31 | if (environment === 'development') { 32 | // ENV.APP.LOG_RESOLVER = true; 33 | // ENV.APP.LOG_ACTIVE_GENERATION = true; 34 | // ENV.APP.LOG_TRANSITIONS = true; 35 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; 36 | // ENV.APP.LOG_VIEW_LOOKUPS = true; 37 | } 38 | 39 | if (environment === 'test') { 40 | // Testem prefers this... 41 | ENV.locationType = 'none'; 42 | 43 | // keep test console output quieter 44 | ENV.APP.LOG_ACTIVE_GENERATION = false; 45 | ENV.APP.LOG_VIEW_LOOKUPS = false; 46 | 47 | ENV.APP.rootElement = '#ember-testing'; 48 | } 49 | 50 | if (environment === 'production') { 51 | // here you can enable a production-specific feature 52 | } 53 | 54 | return ENV; 55 | }; 56 | -------------------------------------------------------------------------------- /config/parse-flag.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | 3 | module.exports = function parseFlag(flagName, fallback) { 4 | var flag = process.env[flagName]; 5 | 6 | if (flag === 'true') { 7 | return true; 8 | } else if (flag === 'false') { 9 | return false; 10 | } else { 11 | return fallback; 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /config/targets.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | module.exports = { 3 | browsers: [ 4 | 'ie 9', 5 | 'last 1 Chrome versions', 6 | 'last 1 Firefox versions', 7 | 'last 1 Safari versions' 8 | ] 9 | }; 10 | -------------------------------------------------------------------------------- /ember-cli-build.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 'use strict'; 3 | const EmberApp = require('ember-cli/lib/broccoli/ember-app'); 4 | const parseFlag = require('./config/parse-flag'); 5 | const env = EmberApp.env(); 6 | 7 | const AIRPLANE_MODE = parseFlag('AIRPLANE_MODE', false); 8 | const GOOGLE_ANALYTICS = !AIRPLANE_MODE && parseFlag('GOOGLE_ANALYTICS', env === 'production'); 9 | 10 | module.exports = function(defaults) { 11 | var options = { 12 | inlineContent: {}, 13 | minifyJS: {}, 14 | minifyCSS: {}, 15 | sourcemaps: { 16 | extensions: ['js'] 17 | }, 18 | fingerprint: { 19 | enabled: parseFlag('FINGERPRINT', env === 'production'), 20 | exclude: ['gravatar.jpg'] 21 | } 22 | }; 23 | 24 | options.inlineContent['snippets/perf-utils'] = 'app/snippets/perf-utils.js'; 25 | 26 | if (GOOGLE_ANALYTICS) { 27 | options.inlineContent['snippets/google-analytics'] = 'app/snippets/google-analytics.js'; 28 | } 29 | 30 | options.minifyJS.enabled = parseFlag('MINIFY_JS', env === 'production'); 31 | 32 | options.minifyCSS.enabled = parseFlag('MINIFY_CSS', env === 'production'); 33 | 34 | options.sourcemaps.enabled = parseFlag('SOURCEMAPS', env !== 'production'); 35 | 36 | let app = new EmberApp(defaults, options); 37 | 38 | // Use `app.import` to add additional libraries to the generated 39 | // output files. 40 | // 41 | // If you need to use different assets in different 42 | // environments, specify an object as the first parameter. That 43 | // object's keys should be the environment name and the values 44 | // should be the asset to use in that environment. 45 | // 46 | // If the library that you are including contains AMD or ES6 47 | // modules that you would like to import into your application 48 | // please specify an object with the list of modules as keys 49 | // along with the exports of each module as its value. 50 | app.import('node_modules/bootstrap/dist/css/bootstrap.min.css'); 51 | app.import('node_modules/bootstrap/dist/js/bootstrap.min.js'); 52 | 53 | if (AIRPLANE_MODE) { 54 | app.import('vendor/airplane-mode/addons.json', { destDir: 'assets' }); 55 | app.import('vendor/airplane-mode/gravatar.jpg', { destDir: 'assets' }); 56 | } 57 | 58 | return app.toTree(); 59 | }; 60 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ember-addons-website", 3 | "version": "1.1.0", 4 | "description": "Search hundreds of modules that extend ember-cli.", 5 | "private": false, 6 | "author": "", 7 | "license": "MIT", 8 | "directories": { 9 | "doc": "doc", 10 | "test": "tests" 11 | }, 12 | "repository": "https://github.com/gcollazo/ember-cli-addon-search", 13 | "scripts": { 14 | "start": "ember server", 15 | "build": "ember build", 16 | "test": "ember test", 17 | "deploy": "ember deploy production" 18 | }, 19 | "engines": { 20 | "node": ">= 0.10.0" 21 | }, 22 | "devDependencies": { 23 | "bootstrap": "^3.3.7", 24 | "broccoli-asset-rev": "^2.4.5", 25 | "ember-ajax": "^3.0.0", 26 | "ember-cli": "^2.16.2", 27 | "ember-cli-app-version": "^3.1.0", 28 | "ember-cli-babel": "^6.8.2", 29 | "ember-cli-clipboard": "^0.8.0", 30 | "ember-cli-dependency-checker": "^2.1.0", 31 | "ember-cli-deploy": "^1.0.0", 32 | "ember-cli-deploy-aws-pack": "^1.0.1", 33 | "ember-cli-deploy-build": "^1.1.1", 34 | "ember-cli-deploy-cloudfront": "^1.2.0", 35 | "ember-cli-deploy-gzip": "^1.0.1", 36 | "ember-cli-deploy-manifest": "^1.1.0", 37 | "ember-cli-deploy-s3": "^1.2.0", 38 | "ember-cli-deprecation-workflow": "^0.2.3", 39 | "ember-cli-filter-by-query": "^1.3.0", 40 | "ember-cli-htmlbars": "^2.0.3", 41 | "ember-cli-htmlbars-inline-precompile": "^1.0.2", 42 | "ember-cli-inject-live-reload": "^1.4.1", 43 | "ember-cli-inline-content": "^0.4.0", 44 | "ember-cli-moment-shim": "^3.5.0", 45 | "ember-cli-qunit": "^4.3.2", 46 | "ember-cli-release": "^1.0.0-beta.2", 47 | "ember-cli-shims": "^1.2.0", 48 | "ember-cli-sri": "^2.1.0", 49 | "ember-cli-test-loader": "^2.2.0", 50 | "ember-cli-uglify": "^2.1.0", 51 | "ember-concurrency": "^0.8.17", 52 | "ember-data": "3.1.1", 53 | "ember-export-application-global": "^2.0.0", 54 | "ember-font-awesome": "^4.0.0-rc.2", 55 | "ember-load": "0.0.12", 56 | "ember-load-initializers": "^1.0.0", 57 | "ember-moment": "^7.6.0", 58 | "ember-resolver": "^4.5.5", 59 | "ember-source": "^3.0.0", 60 | "eslint-config-blimp": "^7.0.0", 61 | "liquid-fire": "^0.29.2", 62 | "loader.js": "^4.0.10" 63 | }, 64 | "dependencies": {} 65 | } 66 | -------------------------------------------------------------------------------- /public/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gcollazo/ember-cli-addon-search/1586def9fedb432cc2df29eb08769239a5962c96/public/assets/favicon.png -------------------------------------------------------------------------------- /public/assets/github-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/crossdomain.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /public/osdd_file.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Search Ember Addons 4 | Search Ember Addons 5 | UTF-8 6 | 7 | http://www.emberaddons.com/assets/favicon-f2d07120d2bb7f0d4a63810011903d75.png 8 | http://www.emberaddons.com/ 9 | 10 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # http://www.robotstxt.org 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /testem.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | module.exports = { 3 | test_page: 'tests/index.html?hidepassed', 4 | disable_watching: true, 5 | launch_in_ci: [ 6 | 'Chrome' 7 | ], 8 | launch_in_dev: [ 9 | 'Chrome' 10 | ], 11 | browser_args: { 12 | Chrome: { 13 | mode: 'ci', 14 | args: [ 15 | '--no-sandbox', 16 | '--disable-gpu', 17 | '--headless', 18 | '--remote-debugging-port=0', 19 | '--window-size=1440,900' 20 | ] 21 | }, 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /tests/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | embertest: true 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /tests/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "predef": [ 3 | "document", 4 | "window", 5 | "location", 6 | "setTimeout", 7 | "$", 8 | "-Promise", 9 | "define", 10 | "console", 11 | "visit", 12 | "exists", 13 | "fillIn", 14 | "click", 15 | "keyEvent", 16 | "triggerEvent", 17 | "find", 18 | "findWithAssert", 19 | "wait", 20 | "DS", 21 | "andThen", 22 | "currentURL", 23 | "currentPath", 24 | "currentRouteName" 25 | ], 26 | "node": false, 27 | "browser": false, 28 | "boss": true, 29 | "curly": true, 30 | "debug": false, 31 | "devel": false, 32 | "eqeqeq": true, 33 | "evil": true, 34 | "forin": false, 35 | "immed": false, 36 | "laxbreak": false, 37 | "newcap": true, 38 | "noarg": true, 39 | "noempty": false, 40 | "nonew": false, 41 | "nomen": false, 42 | "onevar": false, 43 | "plusplus": false, 44 | "regexp": false, 45 | "undef": true, 46 | "sub": true, 47 | "strict": false, 48 | "white": false, 49 | "eqnull": true, 50 | "esversion": 6, 51 | "unused": true 52 | } 53 | -------------------------------------------------------------------------------- /tests/helpers/destroy-app.js: -------------------------------------------------------------------------------- 1 | import { run } from '@ember/runloop'; 2 | 3 | export default function destroyApp(application) { 4 | run(application, 'destroy'); 5 | } 6 | -------------------------------------------------------------------------------- /tests/helpers/module-for-acceptance.js: -------------------------------------------------------------------------------- 1 | import { module } from 'qunit'; 2 | import { resolve } from 'rsvp'; 3 | import startApp from '../helpers/start-app'; 4 | import destroyApp from '../helpers/destroy-app'; 5 | 6 | export default function(name, options = {}) { 7 | module(name, { 8 | beforeEach() { 9 | this.application = startApp(); 10 | 11 | if (options.beforeEach) { 12 | return options.beforeEach.apply(this, arguments); 13 | } 14 | }, 15 | 16 | afterEach() { 17 | let afterEach = options.afterEach && options.afterEach.apply(this, arguments); 18 | return resolve(afterEach).then(() => destroyApp(this.application)); 19 | } 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /tests/helpers/resolver.js: -------------------------------------------------------------------------------- 1 | import Resolver from '../../resolver'; 2 | import config from '../../config/environment'; 3 | 4 | const resolver = Resolver.create(); 5 | 6 | resolver.namespace = { 7 | modulePrefix: config.modulePrefix, 8 | podModulePrefix: config.podModulePrefix 9 | }; 10 | 11 | export default resolver; 12 | -------------------------------------------------------------------------------- /tests/helpers/start-app.js: -------------------------------------------------------------------------------- 1 | import Application from '../../app'; 2 | import config from '../../config/environment'; 3 | import { merge } from '@ember/polyfills'; 4 | import { run } from '@ember/runloop'; 5 | 6 | export default function startApp(attrs) { 7 | let attributes = merge({}, config.APP); 8 | attributes = merge(attributes, attrs); // use defaults, but you can override; 9 | 10 | return run(() => { 11 | let application = Application.create(attributes); 12 | application.setupForTesting(); 13 | application.injectTestHelpers(); 14 | return application; 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EmberAddonsWebsite Tests 7 | 8 | 9 | 10 | {{content-for "head"}} 11 | {{content-for "test-head"}} 12 | 13 | 14 | 15 | 16 | 17 | {{content-for "snippets/perf-utils"}} 18 | 19 | {{content-for "head-footer"}} 20 | {{content-for "test-head-footer"}} 21 | 22 | 23 | {{content-for "body"}} 24 | {{content-for "test-body"}} 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | {{content-for "body-footer"}} 34 | {{content-for "test-body-footer"}} 35 | 36 | 37 | -------------------------------------------------------------------------------- /tests/test-helper.js: -------------------------------------------------------------------------------- 1 | import resolver from './helpers/resolver'; 2 | import { 3 | setResolver 4 | } from 'ember-qunit'; 5 | import { start } from 'ember-cli-qunit'; 6 | 7 | setResolver(resolver); 8 | start(); 9 | -------------------------------------------------------------------------------- /tests/unit/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gcollazo/ember-cli-addon-search/1586def9fedb432cc2df29eb08769239a5962c96/tests/unit/.gitkeep -------------------------------------------------------------------------------- /tests/unit/components/em-header-test.js: -------------------------------------------------------------------------------- 1 | import { module, test } from 'qunit'; 2 | import { setupRenderingTest } from 'ember-qunit'; 3 | import { render } from '@ember/test-helpers'; 4 | import hbs from 'htmlbars-inline-precompile'; 5 | 6 | module('Unit | Component | em header', function(hooks) { 7 | setupRenderingTest(hooks); 8 | 9 | test('it renders', async function(assert) { 10 | assert.expect(0); 11 | 12 | // Renders the component to the page 13 | await render(hbs`{{em-header}}`); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /tests/unit/components/em-icon-clipboard-test.js: -------------------------------------------------------------------------------- 1 | import { module, test } from 'qunit'; 2 | import { setupRenderingTest } from 'ember-qunit'; 3 | import { render } from '@ember/test-helpers'; 4 | import hbs from 'htmlbars-inline-precompile'; 5 | 6 | module('Unit | Component | em icon clipboard', function(hooks) { 7 | setupRenderingTest(hooks); 8 | 9 | test('it renders', async function(assert) { 10 | assert.expect(0); 11 | 12 | // Renders the component to the page 13 | await render(hbs`{{em-icon-clipboard}}`); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /tests/unit/components/em-pagination-test.js: -------------------------------------------------------------------------------- 1 | import { module, test } from 'qunit'; 2 | import { setupRenderingTest } from 'ember-qunit'; 3 | import { render } from '@ember/test-helpers'; 4 | import hbs from 'htmlbars-inline-precompile'; 5 | 6 | module('Unit | Component | em pagination', function(hooks) { 7 | setupRenderingTest(hooks); 8 | 9 | test('it renders', async function(assert) { 10 | assert.expect(0); 11 | 12 | // Renders the component to the page 13 | await render(hbs`{{em-pagination}}`); 14 | 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /tests/unit/components/em-pkg-test.js: -------------------------------------------------------------------------------- 1 | import { module, test } from 'qunit'; 2 | import { setupRenderingTest } from 'ember-qunit'; 3 | import { render } from '@ember/test-helpers'; 4 | import hbs from 'htmlbars-inline-precompile'; 5 | 6 | module('Unit | Component | em pkg', function(hooks) { 7 | setupRenderingTest(hooks); 8 | 9 | test('it renders', async function(assert) { 10 | assert.expect(0); 11 | 12 | // Renders the component to the page 13 | await render(hbs`{{em-pkg}}`); 14 | 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /tests/unit/components/observer-score-test.js: -------------------------------------------------------------------------------- 1 | import { module, test } from 'qunit'; 2 | import { setupRenderingTest } from 'ember-qunit'; 3 | import { render } from '@ember/test-helpers'; 4 | import hbs from 'htmlbars-inline-precompile'; 5 | 6 | module('Unit | Component | observer score', function(hooks) { 7 | setupRenderingTest(hooks); 8 | 9 | test('it renders', async function(assert) { 10 | assert.expect(0); 11 | 12 | // Renders the component to the page 13 | await render(hbs`{{observer-score}}`); 14 | 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /tests/unit/controllers/packages/list-test.js: -------------------------------------------------------------------------------- 1 | import { module, test } from 'qunit'; 2 | import { setupTest } from 'ember-qunit'; 3 | 4 | module('controller:packages/list', function(hooks) { 5 | setupTest(hooks); 6 | 7 | // Replace this with your real tests. 8 | test('it exists', function(assert) { 9 | var controller = this.owner.lookup('controller:packages/list'); 10 | assert.ok(controller); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /tests/unit/helpers/split-prefix-test.js: -------------------------------------------------------------------------------- 1 | import { splitPrefix } from '../../../helpers/split-prefix'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | split prefix', function() { 5 | test('it works', function(assert) { 6 | var result = splitPrefix(['ember-cli-testing']); 7 | 8 | assert.equal(result.toString(), 'ember-cli-testing'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /tests/unit/routes/packages/list-test.js: -------------------------------------------------------------------------------- 1 | import { module, test } from 'qunit'; 2 | import { setupTest } from 'ember-qunit'; 3 | 4 | module('Unit | Route | packages/list', function(hooks) { 5 | setupTest(hooks); 6 | 7 | test('it exists', function(assert) { 8 | var route = this.owner.lookup('route:packages/list'); 9 | assert.ok(route); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /vendor/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gcollazo/ember-cli-addon-search/1586def9fedb432cc2df29eb08769239a5962c96/vendor/.gitkeep -------------------------------------------------------------------------------- /vendor/airplane-mode/gravatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gcollazo/ember-cli-addon-search/1586def9fedb432cc2df29eb08769239a5962c96/vendor/airplane-mode/gravatar.jpg --------------------------------------------------------------------------------