├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── gulpfile.js ├── package.json ├── projects.json └── src ├── css ├── fontello.css └── webdev.css ├── font ├── fontello.eot ├── fontello.svg ├── fontello.ttf └── fontello.woff ├── img ├── mozilla.png └── wordmark.png ├── index.html ├── js ├── lib │ └── jquery.simplePagination.js └── webdev.js └── macros.lib.html /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | .env 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - stable 4 | before_script: 5 | - git config --global user.email "travis@travis-ci.org" 6 | - git config --global user.name "TravisCI Automated Build" 7 | - git remote set-url origin "https://${GITHUB_PASSWORD}@github.com/mozilla/webdev.git" 8 | - npm install -g gulp 9 | - gulp clean 10 | script: gulp deploy --force 11 | env: 12 | global: 13 | - secure: Nrk9anKoHUEs+SChvZ7GFoBl/6db97/NrkOAR9FDUwyfzrNXrc5NFC7ajfODg+US3jGpaMVhu7ZdxdrbiRvD+mwWzJETqNGCS73aY8Y5qbbzaO9EJi6fPJ39xKiIyh8D34wL6hRrtxLAivYVTEPCGJB2YdpVbMIfC5AoA/f7xio= 14 | - secure: IdJ+W6RaraYD85qeJPDXl3FHKCPm6PmJUaDyOePpZXdmksvP5w/wrxn4Vzd4xCVmbj8+AJCz6fyfQ6EXTYO+BWoRzE0w+JDgItnR9QoiGpwhqTmwiYehss/R9HokSFmZJAl9OLxNPIre6rFw/dbtLxIcp7EHo96D4+vH0C965d8= 15 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Community Participation Guidelines 2 | 3 | This repository is governed by Mozilla's code of conduct and etiquette guidelines. 4 | For more details, please read the 5 | [Mozilla Community Participation Guidelines](https://www.mozilla.org/about/governance/policies/participation/). 6 | 7 | ## How to Report 8 | For more information on how to report violations of the Community Participation Guidelines, please read our '[How to Report](https://www.mozilla.org/about/governance/policies/participation/reporting/)' page. 9 | 10 | 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2016 Mozilla Corporation 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mozilla Webdev Tools and Pages 2 | 3 | This repo serves several purposes: 4 | 5 | 1. Contains code for building and deploying the gh-pages branch behind 6 | https://mozilla.github.io/webdev/. 7 | 2. Contains small tools that are useful for the [Mozilla Webdev][] group. 8 | 9 | [Mozilla Webdev]: https://mozweb.readthedocs.org/en/latest/guide/webdev.html 10 | 11 | ## Developer Setup 12 | 13 | These steps assume you have [Node.js][] installed. 14 | 15 | 1. Clone this repo: 16 | 17 | ```sh 18 | $ git clone https://github.com/mozilla/webdev.git 19 | ``` 20 | 21 | 2. Install dependencies: 22 | 23 | ```sh 24 | $ npm install -g gulp 25 | $ npm install 26 | ``` 27 | 28 | 3. (Optional) Add your Github credentials to a `.env` file 29 | in the repo's root. These are used by the `build` command when downloading 30 | metadata from Github. For security, you should probably use a 31 | [Personal Access Token][] for the password and limit it to `public_repo` 32 | permissions only. For example: 33 | 34 | ``` 35 | GITHUB_USERNAME=Osmose 36 | GITHUB_PASSWORD=some_personal_access_token 37 | ``` 38 | 39 | [Node.js]: https://nodejs.org/ 40 | [Personal Access Token]: https://github.com/settings/applications 41 | 42 | ## projects.json 43 | 44 | `projects.json` contains a categorized list of projects the Webdev group is 45 | responsible for. It's intended to be manually kept up-to-date and is useful for 46 | running scripts across all Webdev projects. 47 | 48 | ## Available Gulp Commands 49 | 50 | ### `gulp serve` 51 | 52 | Run a development server for the Github pages site on port 8000. Auto-builds the 53 | site when anything is changed in the `src` directory. 54 | 55 | ### `gulp build` 56 | 57 | Builds the site in the `build` directory. Runs all the HTML files through 58 | [Nunjucks][] with the following context: 59 | 60 | - `projects`: Object containing the parsed contents of `build/projects.json`. 61 | 62 | The metadata added to the projects list is downloaded from the Github API and 63 | is cached for 24 hours. The `--force` flag will force a re-download of this 64 | data. 65 | 66 | Note that it's very easy to hit API limits if you haven't 67 | [added your credentials to a .env file](#user-content-dotenv). 68 | 69 | [Nunjucks]: https://mozilla.github.io/nunjucks/ 70 | 71 | ### `gulp deploy` 72 | 73 | Build the site and commit the changes to the `gh-pages` branch, pushing them to 74 | `origin`. 75 | 76 | ### `gulp validate_contribute_json` 77 | 78 | Fetch [contribute.json][] files for all of the projects in `projects.json` and 79 | validate them. Currently only supports repos hosted on Github. 80 | 81 | [contribute.json]: https://contribute.paas.allizom.org/ 82 | 83 | ## License 84 | 85 | Licensed under the Apache 2.0 License. For details, see the [`LICENSE`](./LICENSE) file. 86 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var argv = require('yargs').argv; 2 | var async = require('async'); 3 | var babel = require('gulp-babel'); 4 | var del = require('del'); 5 | var deploy = require('gulp-gh-pages'); 6 | var dotenv = require('dotenv'); 7 | var fs = require('fs'); 8 | var GitHubApi = require("github"); 9 | var gitRev = require('git-rev'); 10 | var gulp = require('gulp'); 11 | var gutil = require('gulp-util'); 12 | var jsonschema = require('jsonschema'); 13 | var myth = require('gulp-myth'); 14 | var nunjucksRender = require('gulp-nunjucks-render'); 15 | var plumber = require('gulp-plumber'); 16 | var ProgressBar = require('progress'); 17 | var request = require('request'); 18 | var serve = require('gulp-serve'); 19 | var util = require('util'); 20 | 21 | 22 | var CONTRIBUTE_JSON_URL = 'https://raw.githubusercontent.com/%s/%s/master/contribute.json'; 23 | var CONTRIBUTE_JSON_SCHEMA = 'https://raw.githubusercontent.com/mozilla/contribute.json/master/schema.json'; 24 | 25 | 26 | // Set up Github API connection if necessary. 27 | dotenv.load(); 28 | var github = new GitHubApi({ 29 | version: '3.0.0', 30 | }); 31 | if (process.env.GITHUB_USERNAME && process.env.GITHUB_PASSWORD) { 32 | github.authenticate({ 33 | type: 'basic', 34 | username: process.env.GITHUB_USERNAME, 35 | password: process.env.GITHUB_PASSWORD, 36 | }); 37 | } 38 | 39 | 40 | /** 41 | * Run a local development server. The site is re-generated 42 | * automatically when changes are made. 43 | */ 44 | gulp.task('serve', ['build'], function() { 45 | var watcher = gulp.watch('./src/**/*', ['build']); 46 | watcher.on('change', function(event) { 47 | gutil.log(gutil.colors.cyan('Change detected, rebuilding.')); 48 | }); 49 | 50 | // Wish I had a better way of doing this. 51 | return serve({ 52 | root: 'build', 53 | port: 8000, 54 | })(); 55 | }); 56 | 57 | /** 58 | * Build a projects.json file annotated with data pulled from Github and other 59 | * sources. 60 | */ 61 | gulp.task('build.projectdata', function(callback) { 62 | // Ensure the build directory exists. 63 | try { 64 | fs.mkdirSync('build'); 65 | } catch (err) {} 66 | 67 | // If the list has been updated in the past 24 hours, don't bother updating. 68 | // Unless we're being forced to, that is. 69 | if (!argv.force) { 70 | try { 71 | var oldProjects = JSON.parse(fs.readFileSync('build/projects.json')); 72 | var lastUpdated = new Date(oldProjects.lastUpdated); 73 | if (lastUpdated - Date.now() < (24 * 60 * 60 * 1000)) { 74 | gutil.log(gutil.colors.yellow('Projects are up-to-date, skipping re-generation.')); 75 | return callback(); 76 | } 77 | } catch (err) { 78 | // Any failure in checking the old projects means we need to 79 | // regenerate anyway. 80 | } 81 | } 82 | 83 | var projects = loadProjects(); 84 | projects.lastUpdated = Date.now(); 85 | 86 | // Annnotate the projects with extra data and s 87 | async.each(allProjects(projects), annotateProject, function(err) { 88 | if (err) { 89 | console.error('Error annotating projects.'); 90 | console.error(err); 91 | callback(err); 92 | } else { 93 | fs.writeFileSync('build/projects.json', JSON.stringify(projects)); 94 | callback(); 95 | } 96 | }); 97 | }); 98 | 99 | /** 100 | * Build HTML files by running them through nunjucks. 101 | */ 102 | gulp.task('build.templates', ['build.projectdata'], function() { 103 | nunjucksRender.nunjucks.configure(['src']); 104 | 105 | var projects = JSON.parse(fs.readFileSync('build/projects.json')); 106 | var githubProjects = allProjects(projects, function(p) {return p.github;}); 107 | githubProjects.sort(function(a, b) { 108 | return b.github.stars - a.github.stars; 109 | }); 110 | 111 | var ctx = { 112 | projects: githubProjects, 113 | thisYear: new Date().getFullYear(), 114 | now: new Date(), 115 | }; 116 | return gulp.src('./src/index.html') 117 | .pipe(plumber()) 118 | .pipe(nunjucksRender(ctx)) 119 | .pipe(gulp.dest('./build')); 120 | }); 121 | 122 | /** 123 | * Copy other files over to the build directory. 124 | */ 125 | gulp.task('build.static', function() { 126 | return gulp.src(['./src/font/**/*', 127 | './src/img/**/*', 128 | './src/js/lib/**/*'], 129 | {base: './src'}) 130 | .pipe(gulp.dest('./build')); 131 | }); 132 | 133 | /** 134 | * Build CSS files by running them through myth. 135 | */ 136 | gulp.task('build.css', function() { 137 | return gulp.src('./src/css/*.css') 138 | .pipe(plumber()) 139 | .pipe(myth()) 140 | .pipe(gulp.dest('./build/css')); 141 | }); 142 | 143 | /** 144 | * Build JS files by running them through Babel. 145 | */ 146 | gulp.task('build.js', function() { 147 | return gulp.src('./src/js/*.js') 148 | .pipe(plumber()) 149 | .pipe(babel()) 150 | .pipe(gulp.dest('./build/js')); 151 | }); 152 | 153 | /** 154 | * Full build of the static site. 155 | */ 156 | gulp.task('build', ['build.templates', 'build.css', 'build.js', 'build.static']); 157 | 158 | gulp.task('clean', function(cb) { 159 | del('build/**/*', cb); 160 | }); 161 | 162 | /** 163 | * Build the site, commit it to the gh-pages branch, and push to origin. 164 | */ 165 | gulp.task('deploy', ['build'], function(cb) { 166 | gitRev.long(function(rev) { 167 | gulp.src('./build/**/*') 168 | .pipe(deploy({ 169 | message: 'Building from commit ' + rev, 170 | })) 171 | .on('end', cb); 172 | }); 173 | }); 174 | 175 | /** 176 | * Download and validate contribute.json files for all the projects in 177 | * projects.json. 178 | */ 179 | gulp.task('validate_contribute_json', function(gulpCallback) { 180 | var projects = allProjects(loadProjects()); 181 | var bar = new ProgressBar(':bar', {total: projects.length}); 182 | var passed = []; 183 | var failed = []; 184 | var skipped = []; 185 | 186 | // Sort projects by name. 187 | projects.sort(function(a, b) { 188 | return a.name.toLowerCase().localeCompare(b.name.toLowerCase()); 189 | }); 190 | 191 | async.each(projects, function(project, eachCallback) { 192 | if (!project.github) { 193 | skipped.push({project: project, reason: 'No Github repo.'}); 194 | bar.tick(); 195 | return eachCallback(); 196 | } 197 | 198 | getContributeJSON(project, function(contributeJSON, error) { 199 | if (error) { 200 | failed.push({ 201 | project: project, 202 | reason: error 203 | }); 204 | bar.tick(); 205 | eachCallback(); 206 | } else { 207 | validateContributeJSON(contributeJSON, function(result) { 208 | if (result.errors.length > 0) { 209 | failed.push({ 210 | project: project, 211 | reason: 'Failed validation.', 212 | validationResult: result, 213 | }); 214 | bar.tick(); 215 | eachCallback(); 216 | } else { 217 | passed.push(project); 218 | bar.tick(); 219 | eachCallback(); 220 | } 221 | }); 222 | } 223 | }); 224 | }, function() { 225 | gutil.log(gutil.colors.green('== Passed ==')); 226 | passed.forEach(function(project) { 227 | gutil.log(' ' + gutil.colors.underline(project.name)); 228 | }); 229 | 230 | gutil.log(gutil.colors.red('== Failed ==')); 231 | failed.forEach(function(result) { 232 | gutil.log(' ' + gutil.colors.underline(result.project.name)); 233 | gutil.log(' ' + result.reason); 234 | if (result.validationResult) { 235 | gutil.log(result.validationResult.errors); 236 | } 237 | }); 238 | 239 | gutil.log(gutil.colors.yellow('== Skipped ==')); 240 | skipped.forEach(function(result) { 241 | gutil.log(' ' + gutil.colors.underline(result.project.name)); 242 | gutil.log(' ' + result.reason); 243 | }); 244 | }); 245 | }); 246 | 247 | function getContributeJSON(project, callback) { 248 | if (!project.github) { 249 | callback(null, 'No Github repo.'); 250 | } 251 | 252 | var url = util.format(CONTRIBUTE_JSON_URL, project.github.user, 253 | project.github.repository); 254 | request(url, function(error, response, body) { 255 | if (error) { 256 | callback(null, 'Error downloading contribute.json: ' + error); 257 | } else if (response.statusCode != 200) { 258 | callback(null, 'Bad response code: ' + response.statusCode); 259 | } else { 260 | try { 261 | var contributeJSON = JSON.parse(body); 262 | callback(contributeJSON, null); 263 | } catch (error) { 264 | callback(null, 'Error parsing contribute.json: ' + error); 265 | } 266 | } 267 | }); 268 | } 269 | 270 | var _contributeSchema = null; 271 | function getContributeSchema(callback) { 272 | if (!_contributeSchema) { 273 | request(CONTRIBUTE_JSON_SCHEMA, function(error, response, body) { 274 | // TODO: Handle errors fetching this. 275 | _contributeSchema = JSON.parse(body); 276 | callback(_contributeSchema); 277 | }); 278 | } else { 279 | callback(_contributeSchema); 280 | } 281 | } 282 | 283 | function validateContributeJSON(contributeJSON, callback) { 284 | getContributeSchema(function(contributeSchema) { 285 | callback(jsonschema.validate(contributeJSON, contributeSchema)); 286 | }); 287 | } 288 | 289 | /** 290 | * Return a list of every individual project from the categorized lists in 291 | * projects.json. 292 | */ 293 | function allProjects(projects, filter) { 294 | var _allProjects = []; 295 | ['websites', 'libraries', 'apps', 'other'].forEach(function(category) { 296 | projects[category].forEach(function(project) { 297 | if (filter && !filter(project)) return; 298 | _allProjects.push(project); 299 | }); 300 | }); 301 | 302 | return _allProjects; 303 | } 304 | 305 | /** 306 | * Load projects.json. 307 | */ 308 | function loadProjects() { 309 | return JSON.parse(fs.readFileSync('projects.json')); 310 | } 311 | 312 | /** 313 | * Annotate a project with extra metadata, such as repo info pulled from the 314 | * Github API. 315 | */ 316 | function annotateProject(project, callback) { 317 | project.searchData = [project.name]; 318 | if (project.repos) { 319 | project.link = project.repos[0]; 320 | } else if (project.see_also) { 321 | project.link = project.see_also[0]; 322 | } 323 | 324 | // If we have info about the Github repo, we can get the Github metadata as 325 | // well as the contribute.json file. 326 | if (project.github) { 327 | async.series([ 328 | annotateProjectGithub.bind(null, project), 329 | annotateProjectContributeJSON.bind(null, project), 330 | ], function() { 331 | if (project.description) { 332 | project.searchData.push(project.description); 333 | } 334 | project.searchData = project.searchData.join(',').toLowerCase(); 335 | 336 | callback(); 337 | }); 338 | } else { 339 | callback(); 340 | } 341 | } 342 | 343 | /** 344 | * Annotate a project with info from the Github API. 345 | */ 346 | function annotateProjectGithub(project, callback) { 347 | github.repos.get({ 348 | user: project.github.user, 349 | repo: project.github.repository, 350 | }, function(err, result) { 351 | if (err) { 352 | callback(err, project); 353 | } else { 354 | project.github.description = result.description; 355 | project.description = result.description; 356 | project.github.stars = result.stargazers_count; 357 | project.github.forks = result.forks_count; 358 | callback(null, project); 359 | } 360 | }); 361 | } 362 | 363 | /** 364 | * Annotate a project with info from its contribute.json file. 365 | */ 366 | function annotateProjectContributeJSON(project, callback) { 367 | getContributeJSON(project, function(contributeJSON, error) { 368 | if (error) { 369 | callback(error, project); 370 | } else { 371 | project.contributeJSON = contributeJSON; 372 | project.description = contributeJSON.description || project.description; 373 | if (contributeJSON.keywords) { 374 | project.searchData = project.searchData.concat(contributeJSON.keywords); 375 | } 376 | 377 | callback(null, project); 378 | } 379 | }); 380 | } 381 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mozilla-webdev", 3 | "version": "0.0.1", 4 | "description": "Mozilla Webdev tools and pages", 5 | "private": true, 6 | "author": "Mozilla Project", 7 | "license": "Apache 2.0", 8 | "scripts": {}, 9 | "dependencies": {}, 10 | "devDependencies": { 11 | "async": "^0.9.0", 12 | "del": "^1.1.1", 13 | "dotenv": "^0.5.1", 14 | "git-rev": "^0.2.1", 15 | "github": "^0.2.3", 16 | "gulp": "^3.8.11", 17 | "gulp-babel": "^4.0.0", 18 | "gulp-gh-pages": "^0.4.0", 19 | "gulp-myth": "^1.0.2", 20 | "gulp-nunjucks-render": "^0.1.3", 21 | "gulp-plumber": "^1.0.0", 22 | "gulp-serve": "^0.3.0", 23 | "gulp-util": "^3.0.3", 24 | "jsonschema": "^1.0.0", 25 | "nunjucks": "^1.2.0", 26 | "progress": "^1.1.8", 27 | "request": "^2.53.0", 28 | "yargs": "^3.0.4" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /projects.json: -------------------------------------------------------------------------------- 1 | { 2 | "websites": [ 3 | { 4 | "name": "www.mozilla.org", 5 | "repos": [ 6 | "https://github.com/mozilla/bedrock" 7 | ], 8 | "github": { 9 | "user": "mozilla", 10 | "repository": "bedrock" 11 | } 12 | }, 13 | { 14 | "name": "affiliates.mozilla.org", 15 | "repos": [ 16 | "https://github.com/mozilla/affiliates" 17 | ], 18 | "github": { 19 | "user": "mozilla", 20 | "repository": "affiliates" 21 | } 22 | }, 23 | { 24 | "name": "errormill.mozilla.org", 25 | "see_also": [ 26 | "https://getsentry.com/welcome/" 27 | ] 28 | }, 29 | { 30 | "name": "support.mozilla.org", 31 | "repos": [ 32 | "https://github.com/mozilla/kitsune/" 33 | ], 34 | "github": { 35 | "user": "mozilla", 36 | "repository": "kitsune" 37 | } 38 | }, 39 | { 40 | "name": "firefoxflicks.mozilla.org", 41 | "repos": [ 42 | "https://github.com/mozilla/firefox-flicks" 43 | ], 44 | "github": { 45 | "user": "mozilla", 46 | "repository": "firefox-flicks" 47 | } 48 | }, 49 | { 50 | "name": "snippets.mozilla.com", 51 | "repos": [ 52 | "https://github.com/mozilla/snippets-service" 53 | ], 54 | "github": { 55 | "user": "mozilla", 56 | "repository": "snippets-service" 57 | } 58 | }, 59 | { 60 | "name": "reps.mozilla.org", 61 | "repos": [ 62 | "https://github.com/mozilla/remo/" 63 | ], 64 | "github": { 65 | "user": "mozilla", 66 | "repository": "remo" 67 | } 68 | }, 69 | { 70 | "name": "mozillians.org", 71 | "repos": [ 72 | "https://github.com/mozilla/mozillians/" 73 | ], 74 | "github": { 75 | "user": "mozilla", 76 | "repository": "mozillians" 77 | } 78 | }, 79 | { 80 | "name": "addons.mozilla.org", 81 | "repos": [ 82 | "https://github.com/mozilla/olympia/" 83 | ], 84 | "github": { 85 | "user": "mozilla", 86 | "repository": "olympia" 87 | } 88 | }, 89 | { 90 | "name": "marketplace.firefox.com", 91 | "repos": [ 92 | "https://github.com/mozilla/zamboni", 93 | "https://github.com/mozilla/fireplace" 94 | ], 95 | "github": { 96 | "user": "mozilla", 97 | "repository": "zamboni" 98 | } 99 | }, 100 | { 101 | "name": "crash-stats.mozilla.org", 102 | "repos": [ 103 | "https://github.com/mozilla/socorro/" 104 | ], 105 | "github": { 106 | "user": "mozilla", 107 | "repository": "socorro" 108 | } 109 | }, 110 | { 111 | "name": "developer.mozilla.org", 112 | "repos": [ 113 | "https://github.com/mozilla/kuma" 114 | ], 115 | "github": { 116 | "user": "mozilla", 117 | "repository": "kuma" 118 | } 119 | }, 120 | { 121 | "name": "dxr.mozilla.org", 122 | "repos": [ 123 | "https://github.com/mozilla/dxr" 124 | ], 125 | "github": { 126 | "user": "mozilla", 127 | "repository": "dxr" 128 | } 129 | }, 130 | { 131 | "name": "air.mozilla.org", 132 | "repos": [ 133 | "https://github.com/mozilla/airmozilla/" 134 | ], 135 | "github": { 136 | "user": "mozilla", 137 | "repository": "airmozilla" 138 | } 139 | }, 140 | { 141 | "name": "input.mozilla.org", 142 | "repos": [ 143 | "https://github.com/mozilla/fjord" 144 | ], 145 | "github": { 146 | "user": "mozilla", 147 | "repository": "fjord" 148 | } 149 | }, 150 | { 151 | "name": "webmaker.org", 152 | "repos": [ 153 | "https://github.com/mozilla/webmaker.org/" 154 | ], 155 | "github": { 156 | "user": "mozilla", 157 | "repository": "webmaker.org" 158 | } 159 | }, 160 | { 161 | "name": "oneanddone.mozilla.org", 162 | "repos": [ 163 | "https://github.com/mozilla/oneanddone" 164 | ], 165 | "github": { 166 | "user": "mozilla", 167 | "repository": "oneanddone" 168 | } 169 | }, 170 | { 171 | "name": "wiki.mozilla.org", 172 | "repos": [ 173 | "https://github.com/mozilla/wiki.mozilla.org" 174 | ], 175 | "github": { 176 | "user": "mozilla", 177 | "repository": "wiki.mozilla.org" 178 | } 179 | }, 180 | { 181 | "name": "blog.mozilla.org", 182 | "see_also": [ 183 | "https://wordpress.org/" 184 | ] 185 | }, 186 | { 187 | "name": "basket.mozilla.org", 188 | "repos": [ 189 | "https://github.com/mozilla/basket", 190 | "https://github.com/mozilla/basket-client/" 191 | ], 192 | "github": { 193 | "user": "mozilla", 194 | "repository": "basket" 195 | } 196 | }, 197 | { 198 | "name": "www.contributejson.org", 199 | "repos": [ 200 | "https://github.com/mozilla/contribute.json" 201 | ], 202 | "github": { 203 | "user": "mozilla", 204 | "repository": "contribute.json" 205 | } 206 | }, 207 | { 208 | "name": "webwewant.mozilla.org", 209 | "repos": [ 210 | "https://github.com/mozilla/mrburns" 211 | ], 212 | "github": { 213 | "user": "mozilla", 214 | "repository": "mrburns" 215 | } 216 | }, 217 | { 218 | "name": "nightly.mozilla.org", 219 | "repos": [ 220 | "https://github.com/mozilla/nocturnal" 221 | ], 222 | "github": { 223 | "user": "mozilla", 224 | "repository": "nocturnal" 225 | } 226 | }, 227 | { 228 | "name": "location.services.mozilla.com", 229 | "repos": [ 230 | "https://github.com/mozilla/ichnaea" 231 | ], 232 | "github": { 233 | "user": "mozilla", 234 | "repository": "ichnaea" 235 | } 236 | }, 237 | { 238 | "name": "mobilepartners.mozilla.org", 239 | "repos": [ 240 | "https://github.com/mozilla/fxoss" 241 | ], 242 | "github": { 243 | "user": "mozilla", 244 | "repository": "fxoss" 245 | } 246 | }, 247 | { 248 | "name": "openstandard.mozilla.org", 249 | "repos": [ 250 | "https://github.com/mozilla/theopenstandard" 251 | ], 252 | "github": { 253 | "user": "mozilla", 254 | "repository": "theopenstandard" 255 | } 256 | }, 257 | { 258 | "name": "careers.mozilla.org", 259 | "repos": [ 260 | "https://github.com/mozilla/lumbergh" 261 | ], 262 | "github": { 263 | "user": "mozilla", 264 | "repository": "lumbergh" 265 | } 266 | }, 267 | { 268 | "name": "peekaboo.mozilla.org", 269 | "repos": [ 270 | "https://github.com/mozilla/peekaboo" 271 | ], 272 | "github": { 273 | "user": "mozilla", 274 | "repository": "peekaboo" 275 | } 276 | }, 277 | { 278 | "name": "www.standu.ps", 279 | "repos": [ 280 | "https://github.com/mozilla/standup", 281 | "https://github.com/mozilla/standup-irc" 282 | ], 283 | "github": { 284 | "user": "mozilla", 285 | "repository": "standup" 286 | } 287 | } 288 | ], 289 | "libraries": [ 290 | { 291 | "name": "django-browserid", 292 | "repos": [ 293 | "https://github.com/mozilla/django-browserid" 294 | ], 295 | "github": { 296 | "user": "mozilla", 297 | "repository": "django-browserid" 298 | } 299 | }, 300 | { 301 | "name": "jingo", 302 | "repos": [ 303 | "https://github.com/jbalogh/jingo" 304 | ], 305 | "github": { 306 | "user": "jbalogh", 307 | "repository": "jingo" 308 | } 309 | }, 310 | { 311 | "name": "jingo-minify", 312 | "repos": [ 313 | "https://github.com/jsocol/jingo-minify" 314 | ], 315 | "github": { 316 | "user": "jsocol", 317 | "repository": "jingo-minify" 318 | } 319 | }, 320 | { 321 | "name": "playdoh", 322 | "repos": [ 323 | "https://github.com/mozilla/playdoh", 324 | "https://github.com/mozilla/playdoh-lib", 325 | "https://github.com/mozilla/funfactory" 326 | ], 327 | "github": { 328 | "user": "mozilla", 329 | "repository": "playdoh" 330 | } 331 | }, 332 | { 333 | "name": "brick", 334 | "repos": [ 335 | "https://github.com/mozbrick/brick/" 336 | ], 337 | "github": { 338 | "user": "mozbrick", 339 | "repository": "brick" 340 | } 341 | }, 342 | { 343 | "name": "nunjucks", 344 | "repos": [ 345 | "https://github.com/mozilla/nunjucks" 346 | ], 347 | "github": { 348 | "user": "mozilla", 349 | "repository": "nunjucks" 350 | } 351 | }, 352 | { 353 | "name": "sugardough", 354 | "repos": [ 355 | "https://github.com/mozilla/sugardough" 356 | ], 357 | "github": { 358 | "user": "mozilla", 359 | "repository": "sugardough" 360 | } 361 | }, 362 | { 363 | "name": "commonware", 364 | "repos": [ 365 | "https://github.com/jsocol/commonware" 366 | ], 367 | "github": { 368 | "user": "jsocol", 369 | "repository": "commonware" 370 | } 371 | }, 372 | { 373 | "name": "configman", 374 | "repos": [ 375 | "https://github.com/mozilla/configman" 376 | ], 377 | "github": { 378 | "user": "mozilla", 379 | "repository": "configman" 380 | } 381 | }, 382 | { 383 | "name": "crontabber", 384 | "repos": [ 385 | "https://github.com/mozilla/crontabber" 386 | ], 387 | "github": { 388 | "user": "mozilla", 389 | "repository": "crontabber" 390 | } 391 | }, 392 | { 393 | "name": "django-badger", 394 | "repos": [ 395 | "https://github.com/mozilla/django-badger" 396 | ], 397 | "github": { 398 | "user": "mozilla", 399 | "repository": "django-badger" 400 | } 401 | }, 402 | { 403 | "name": "django-nose", 404 | "repos": [ 405 | "https://github.com/django-nose/django-nose" 406 | ], 407 | "github": { 408 | "user": "django-nose", 409 | "repository": "django-nose" 410 | } 411 | }, 412 | { 413 | "name": "tower", 414 | "repos": [ 415 | "https://github.com/clouserw/tower" 416 | ], 417 | "github": { 418 | "user": "clouserw", 419 | "repository": "tower" 420 | } 421 | }, 422 | { 423 | "name": "django-session-csrf", 424 | "repos": [ 425 | "https://github.com/mozilla/django-session-csrf" 426 | ], 427 | "github": { 428 | "user": "mozilla", 429 | "repository": "django-session-csrf" 430 | } 431 | }, 432 | { 433 | "name": "localForage", 434 | "repos": [ 435 | "https://github.com/localForage/localForage" 436 | ], 437 | "github": { 438 | "user": "localForage", 439 | "repository": "localforage" 440 | } 441 | }, 442 | { 443 | "name": "django-session-csrf", 444 | "repos": [ 445 | "https://github.com/mozilla/django-session-csrf" 446 | ], 447 | "github": { 448 | "user": "mozilla", 449 | "repository": "django-session-csrf" 450 | } 451 | }, 452 | { 453 | "name": "cliquet", 454 | "repos": [ 455 | "https://github.com/mozilla-services/cliquet" 456 | ], 457 | "github": { 458 | "user": "mozilla-services", 459 | "repository": "cliquet" 460 | } 461 | }, 462 | { 463 | "name": "cornice", 464 | "repos": [ 465 | "https://github.com/mozilla-services/cornice" 466 | ], 467 | "github": { 468 | "user": "mozilla-services", 469 | "repository": "cornice" 470 | } 471 | }, 472 | { 473 | "name": "requests-hawk", 474 | "repos": [ 475 | "https://github.com/mozilla-services/requests-hawk" 476 | ], 477 | "github": { 478 | "user": "mozilla-services", 479 | "repository": "requests-hawk" 480 | } 481 | }, 482 | { 483 | "name": "konfig", 484 | "repos": [ 485 | "https://github.com/mozilla-services/konfig" 486 | ], 487 | "github": { 488 | "user": "mozilla-services", 489 | "repository": "konfig" 490 | } 491 | }, 492 | { 493 | "name": "pyramid-hawkauth", 494 | "repos": [ 495 | "https://github.com/mozilla-services/pyramid-hawkauth" 496 | ], 497 | "github": { 498 | "user": "mozilla-services", 499 | "repository": "pyramid-hawkauth" 500 | } 501 | }, 502 | { 503 | "name": "tokenlib", 504 | "repos": [ 505 | "https://github.com/mozilla-services/tokenlib" 506 | ], 507 | "github": { 508 | "user": "mozilla-services", 509 | "repository": "tokenlib" 510 | } 511 | }, 512 | { 513 | "name": "pyramid_multiauth", 514 | "repos": [ 515 | "https://github.com/mozilla-services/pyramid_multiauth" 516 | ], 517 | "github": { 518 | "user": "mozilla-services", 519 | "repository": "pyramid_multiauth" 520 | } 521 | }, 522 | { 523 | "name": "hawkauthlib", 524 | "repos": [ 525 | "https://github.com/mozilla-services/hawkauthlib" 526 | ], 527 | "github": { 528 | "user": "mozilla-services", 529 | "repository": "hawkauthlib" 530 | } 531 | }, 532 | { 533 | "name": "metrics-graphics", 534 | "repos": [ 535 | "https://github.com/mozilla/metrics-graphics" 536 | ], 537 | "github": { 538 | "user": "mozilla", 539 | "repository": "metrics-graphics" 540 | } 541 | } 542 | ], 543 | "apps": [ 544 | { 545 | "name": "Buddyup", 546 | "repos": [ 547 | "https://github.com/mozilla/buddyup" 548 | ], 549 | "github": { 550 | "user": "mozilla", 551 | "repository": "buddyup" 552 | } 553 | }, 554 | { 555 | "name": "readinglist-client", 556 | "repos": [ 557 | "https://github.com/mozilla-services/readinglist-client" 558 | ], 559 | "github": { 560 | "user": "mozilla-services", 561 | "repository": "readinglist-client" 562 | } 563 | }, 564 | { 565 | "name": "pontoon", 566 | "repos": [ 567 | "https://github.com/mozilla/pontoon" 568 | ], 569 | "github": { 570 | "user": "mozilla", 571 | "repository": "pontoon" 572 | } 573 | } 574 | ], 575 | "other": [ 576 | { 577 | "name": "corsica", 578 | "repos": [ 579 | "https://github.com/mozilla/corsica" 580 | ], 581 | "github": { 582 | "user": "mozilla", 583 | "repository": "corsica" 584 | } 585 | }, 586 | { 587 | "name": "peep", 588 | "repos": [ 589 | "https://github.com/erikrose/peep" 590 | ], 591 | "github": { 592 | "user": "erikrose", 593 | "repository": "peep" 594 | } 595 | }, 596 | { 597 | "name": "The Mozilla Foundation Client-Side Prototype", 598 | "repos": [ 599 | "https://github.com/MozillaFoundation/mofo-example-app" 600 | ], 601 | "github": { 602 | "user": "MozillaFoundation", 603 | "repository": "mofo-example-app" 604 | } 605 | }, 606 | { 607 | "name": "heka", 608 | "repos": [ 609 | "https://github.com/mozilla-services/heka" 610 | ], 611 | "github": { 612 | "user": "mozilla-services", 613 | "repository": "heka" 614 | } 615 | }, 616 | { 617 | "name": "autopush", 618 | "repos": [ 619 | "https://github.com/mozilla-services/autopush" 620 | ], 621 | "github": { 622 | "user": "mozilla-services", 623 | "repository": "autopush" 624 | } 625 | }, 626 | { 627 | "name": "loop-server", 628 | "repos": [ 629 | "https://github.com/mozilla-services/loop-server" 630 | ], 631 | "github": { 632 | "user": "mozilla-services", 633 | "repository": "loop-server" 634 | } 635 | }, 636 | { 637 | "name": "readinglist", 638 | "repos": [ 639 | "https://github.com/mozilla-services/readinglist" 640 | ], 641 | "github": { 642 | "user": "mozilla-services", 643 | "repository": "readinglist" 644 | } 645 | }, 646 | { 647 | "name": "Kinto - A database for the Web", 648 | "repos": [ 649 | "https://github.com/kinto/kinto" 650 | ], 651 | "github": { 652 | "user": "kinto", 653 | "repository": "kinto" 654 | } 655 | }, 656 | { 657 | "name": "tokenserver", 658 | "repos": [ 659 | "https://github.com/mozilla-services/tokenserver" 660 | ], 661 | "github": { 662 | "user": "mozilla-services", 663 | "repository": "tokenserver" 664 | } 665 | }, 666 | { 667 | "name": "loads", 668 | "repos": [ 669 | "https://github.com/mozilla-services/loads" 670 | ], 671 | "github": { 672 | "user": "mozilla-services", 673 | "repository": "loads" 674 | } 675 | }, 676 | { 677 | "name": "syncserver", 678 | "repos": [ 679 | "https://github.com/mozilla-services/syncserver" 680 | ], 681 | "github": { 682 | "user": "mozilla-services", 683 | "repository": "syncserver" 684 | } 685 | }, 686 | { 687 | "name": "msisdn-gateway", 688 | "repos": [ 689 | "https://github.com/mozilla-services/msisdn-gateway" 690 | ], 691 | "github": { 692 | "user": "mozilla-services", 693 | "repository": "msisdn-gateway" 694 | } 695 | }, 696 | { 697 | "name": "vaurien", 698 | "repos": [ 699 | "https://github.com/mozilla-services/vaurien" 700 | ], 701 | "github": { 702 | "user": "mozilla-services", 703 | "repository": "vaurien" 704 | } 705 | }, 706 | { 707 | "name": "ship-it", 708 | "repos": [ 709 | "https://github.com/mozilla/ship-it" 710 | ], 711 | "github": { 712 | "user": "mozilla", 713 | "repository": "ship-it" 714 | } 715 | }, 716 | { 717 | "name": "relengapi", 718 | "repos": [ 719 | "https://github.com/mozilla/build-relengapi" 720 | ], 721 | "github": { 722 | "user": "mozilla", 723 | "repository": "build-relengapi" 724 | } 725 | } 726 | ] 727 | } 728 | -------------------------------------------------------------------------------- /src/css/fontello.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'fontello'; 3 | src: url('../font/fontello.eot?13999958'); 4 | src: url('../font/fontello.eot?13999958#iefix') format('embedded-opentype'), 5 | url('../font/fontello.woff?13999958') format('woff'), 6 | url('../font/fontello.ttf?13999958') format('truetype'), 7 | url('../font/fontello.svg?13999958#fontello') format('svg'); 8 | font-weight: normal; 9 | font-style: normal; 10 | } 11 | /* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */ 12 | /* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */ 13 | /* 14 | @media screen and (-webkit-min-device-pixel-ratio:0) { 15 | @font-face { 16 | font-family: 'fontello'; 17 | src: url('../font/fontello.svg?13999958#fontello') format('svg'); 18 | } 19 | } 20 | */ 21 | 22 | [class^="icon-"]:before, [class*=" icon-"]:before { 23 | font-family: "fontello"; 24 | font-style: normal; 25 | font-weight: normal; 26 | speak: none; 27 | 28 | display: inline-block; 29 | text-decoration: inherit; 30 | width: 1em; 31 | margin-right: .2em; 32 | text-align: center; 33 | /* opacity: .8; */ 34 | 35 | /* For safety - reset parent styles, that can break glyph codes*/ 36 | font-variant: normal; 37 | text-transform: none; 38 | 39 | /* fix buttons height, for twitter bootstrap */ 40 | line-height: 1em; 41 | 42 | /* Animation center compensation - margins should be symmetric */ 43 | /* remove if not needed */ 44 | margin-left: .2em; 45 | 46 | /* you can be more comfortable with increased icons size */ 47 | /* font-size: 120%; */ 48 | 49 | /* Uncomment for 3D effect */ 50 | /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ 51 | } 52 | 53 | .icon-star:before { content: '\e800'; } /* '' */ 54 | .icon-star-empty:before { content: '\e801'; } /* '' */ 55 | .icon-fork:before { content: '\e802'; } /* '' */ -------------------------------------------------------------------------------- /src/css/webdev.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --text-color: #FFF; 3 | --link-color: #0095DD; 4 | --background: radial-gradient(ellipse farthest-side at left top, 5 | #00549E 0px, transparent 100%) 6 | #1E1E21; 7 | 8 | --filter-background: #FFF; 9 | --filter-text-color: #000; 10 | --filter-border: 2px solid #CCC; 11 | 12 | --project-background: linear-gradient(#EAEFF2, #D4DDE4); 13 | --project-text-color: #424F5A; 14 | --project-tag-background: #ADBFCC; 15 | 16 | --want-to-help-background: #14C329; 17 | --want-to-help-text-color: #FFF; 18 | 19 | --pagination-background: linear-gradient(#EAEFF2, #D4DDE4); 20 | --pagination-text-color: #424F5A; 21 | --pagination-link-color: #0095DD; 22 | 23 | --footer-background: #FFF; 24 | --footer-text-color: #424F5A; 25 | } 26 | 27 | * { 28 | box-sizing: border-box; 29 | } 30 | 31 | body { 32 | background: var(--background) no-repeat; 33 | background-size: auto 640px; 34 | color: var(--text-color); 35 | font: 14px 'Fira Sans', sans-serif; 36 | } 37 | 38 | a { 39 | color: var(--link-color); 40 | text-decoration: none; 41 | } 42 | 43 | a:hover { 44 | text-decoration: underline; 45 | } 46 | 47 | #tabzilla-border { 48 | border-top: 2px solid #FFF; 49 | } 50 | 51 | #wrapper { 52 | margin: 0 auto; 53 | max-width: 960px; 54 | } 55 | 56 | #masthead { 57 | padding: 20px 0; 58 | } 59 | 60 | #masthead h1 { 61 | margin: 0; 62 | } 63 | 64 | .wordmark { 65 | /* Set dimensions to half-size for hi-DPI screens. */ 66 | height: calc(168px / 2); 67 | width: calc(311px / 2); 68 | } 69 | 70 | #intro { 71 | margin-bottom: 50px; 72 | text-align: center; 73 | } 74 | 75 | #intro h2 { 76 | font-size: 42px; 77 | font-weight: 400; 78 | margin: 0; 79 | } 80 | 81 | #intro p { 82 | font-size: 24px; 83 | font-weight: 200; 84 | margin: 0 auto; 85 | max-width: 640px; 86 | } 87 | 88 | #intro a { 89 | font-weight: 300; 90 | } 91 | 92 | #projects h2 { 93 | font-size: 28px; 94 | font-weight: 400; 95 | margin: 0 0 20px; 96 | text-align: center; 97 | } 98 | 99 | #search { 100 | display: block; 101 | margin: 10px; 102 | } 103 | 104 | #search span { 105 | position: absolute; 106 | top: -999999em; 107 | left: auto; 108 | width: 1px; 109 | height: 1px; 110 | overflow: hidden; 111 | } 112 | 113 | #search input { 114 | background: var(--filter-background); 115 | border: var(--filter-border); 116 | color: var(--filter-text-color); 117 | padding: 15px 15px 10px; 118 | width: 100%; 119 | } 120 | 121 | .search-message { 122 | font-size: 24px; 123 | font-weight: 400; 124 | margin: 20px auto; 125 | max-width: 480px; 126 | } 127 | 128 | .columns { 129 | display: flex; 130 | flex-flow: row wrap; 131 | } 132 | 133 | .column { 134 | flex: 1; 135 | } 136 | 137 | .column.left { 138 | margin-right: 20px; 139 | } 140 | 141 | .project { 142 | background: var(--project-background); 143 | color: var(--project-text-color); 144 | display: flex; 145 | margin-bottom: 20px; 146 | padding: 10px; 147 | flex-direction: column; 148 | flex-grow: 2; 149 | margin: 10px; 150 | width: 460px; 151 | } 152 | 153 | .project .stars, 154 | .project .forks { 155 | float: right; 156 | margin-left: 5px; 157 | } 158 | 159 | .project h3 { 160 | margin: 0; 161 | padding: 0 0 10px; 162 | } 163 | 164 | .project p { 165 | margin: 0; 166 | padding: 0 0 15px; 167 | } 168 | 169 | .project .description { 170 | flex: 2; 171 | } 172 | 173 | .project .topBar { 174 | display: flex; 175 | } 176 | 177 | .project .topBar .right { 178 | margin-left: auto; 179 | } 180 | 181 | .want-to-help { 182 | background: var(--want-to-help-background); 183 | color: var(--want-to-help-text-color); 184 | font-size: 16px; 185 | font-weight: 400; 186 | padding: 8px 14px 6px; 187 | } 188 | 189 | .project .keywords { 190 | list-style-type: none; 191 | margin: 0 0 -8px; 192 | padding: 0; 193 | } 194 | 195 | .project .keywords li { 196 | background: var(--project-tag-background); 197 | cursor: pointer; 198 | display: inline-block; 199 | font-size: 12px; 200 | font-weight: 600; 201 | margin: 0 5px 8px 0; 202 | padding: 2px 4px; 203 | } 204 | 205 | .project .keywords li:hover { 206 | text-decoration: underline; 207 | } 208 | 209 | .project .keywords .show-all { 210 | background: none; 211 | } 212 | 213 | .simple-pagination ul { 214 | list-style-type: none; 215 | padding: 0; 216 | margin: 10px; 217 | } 218 | 219 | .simple-pagination li { 220 | background: var(--pagination-background); 221 | color: var(--pagination-text-color); 222 | display: inline-block; 223 | padding: 0; 224 | margin-right: 5px; 225 | } 226 | 227 | .simple-pagination li span, 228 | .simple-pagination li a { 229 | padding: 10px; 230 | line-height: 26px; 231 | } 232 | 233 | .simple-pagination li a { 234 | color: var(--pagination-link-color); 235 | } 236 | 237 | #colophon { 238 | background: var(--footer-background); 239 | color: var(--footer-text-color); 240 | min-height: 150px; 241 | margin-top: 20px; 242 | text-align: center; 243 | } 244 | 245 | #colophon p { 246 | margin: 0; 247 | padding: 10px 0 5px; 248 | } 249 | 250 | .footer-logo { 251 | /* Set dimensions to half-size for hi-DPI screens. */ 252 | height: calc(83px / 2); 253 | width: calc(260px / 2); 254 | } 255 | 256 | /* Recognized keyword colors */ 257 | 258 | .project .keywords li[data-keyword="python"] { 259 | background: #3771A3; 260 | color: #FFF; 261 | } 262 | 263 | .project .keywords li[data-keyword="less-css"] { 264 | background: #1D365D; 265 | color: #FFF; 266 | } 267 | 268 | .project .keywords li[data-keyword="django"] { 269 | background: #103E2E; 270 | color: #FFF; 271 | } 272 | 273 | .project .keywords li[data-keyword="html"], 274 | .project .keywords li[data-keyword="html5"] { 275 | background: #F06529; 276 | color: #FFF; 277 | } 278 | 279 | .project .keywords li[data-keyword="javascript"] { 280 | background: #F0DB4F; 281 | color: #323330; 282 | } 283 | 284 | .project .keywords li[data-keyword="node"], 285 | .project .keywords li[data-keyword="nodejs"] { 286 | background: #333333; 287 | color: #7FBD42; 288 | } 289 | 290 | .project .keywords li[data-keyword="css"] { 291 | background: #33A9DC; 292 | color: #FFF; 293 | } 294 | -------------------------------------------------------------------------------- /src/font/fontello.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla/webdev/ffbed700b5590fdcdda185f6df994956d97ee11a/src/font/fontello.eot -------------------------------------------------------------------------------- /src/font/fontello.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/font/fontello.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla/webdev/ffbed700b5590fdcdda185f6df994956d97ee11a/src/font/fontello.ttf -------------------------------------------------------------------------------- /src/font/fontello.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla/webdev/ffbed700b5590fdcdda185f6df994956d97ee11a/src/font/fontello.woff -------------------------------------------------------------------------------- /src/img/mozilla.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla/webdev/ffbed700b5590fdcdda185f6df994956d97ee11a/src/img/mozilla.png -------------------------------------------------------------------------------- /src/img/wordmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla/webdev/ffbed700b5590fdcdda185f6df994956d97ee11a/src/img/wordmark.png -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | {% from 'macros.lib.html' import project_box %} 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 |Webdev is an informal group of Mozillians who develop websites and web services to further our mission.
27 |{{ project.description }}
17 | {% endif %} 18 | 19 | {% if project.contributeJSON.participate.home %} 20 |21 | 22 | I want to help this project » 23 | 24 |
25 | {% endif %} 26 | 27 | {% if project.contributeJSON.keywords %} 28 |