Initial commit.

master
Florent Revest 2017-06-25 16:39:19 +02:00
commit 7ec86162d5
163 changed files with 15727 additions and 0 deletions

77
.assemblerc.yml Normal file
View File

@ -0,0 +1,77 @@
# =============================================
# ASSEMBLE CONFIG
# =============================================
# Dest config
root: _asteroidos.org
dest: <%= site.root %>
# =============================================
# SOURCE CONFIG
# =============================================
# Assets > fonts, icons, images etc.
assets: assets
images: <%= site.assets %>/images
fonts: <%= site.assets %>/fonts
# Styles
styles: styles
# Scripts
scripts: scripts
# Pages
pages: pages
# =============================================
# TEMPLATES
# =============================================
# Base directory for templates
templates: templates
# Partials
includes: <%= site.templates %>/includes
snippets: <%= site.templates %>/snippets
# Layouts
layouts: <%= site.templates %>/layouts
layoutext: .hbs
layout: content
# =============================================
# EXTENSIONS
# =============================================
helpers: <%= site.templates %>/_helpers
plugins:
# npm
- assemble-contrib-permalinks
# local
- <%= site.templates %>/_plugins/navigation.js
- <%= site.templates %>/_plugins/holder-404-avoid.js
# =============================================
# SITE METADATA
# =============================================
# Site metadata
brand: asteroidos.org
title: AsteroidOS
lead: AsteroidOS - An open-source operating system for smartwatches.
description: >
AsteroidOS is an open-source operating system for smartwatches.
# URLs
homepage: http://asteroidos.org
# =============================================
# SEO/SEM
# =============================================
analytics:
google: false
google_site_id: false

9
.gitattributes vendored Normal file
View File

@ -0,0 +1,9 @@
# Enforce Unix newlines, in case users don't have core.autocrlf set.
*.* text=lf
*.* text eol=lf
*.* eol=lf
*.jpg binary
*.gif binary
*.png binary
*.jpeg binary

15
.gitignore vendored Normal file
View File

@ -0,0 +1,15 @@
# live site
_gh_pages
_asteroidos.org
# node.js
node_modules
npm-debug.log
# local dev
tmp
temp
vendor
TODO.md
*.sublime-*
.idea

14
.jshintrc Normal file
View File

@ -0,0 +1,14 @@
{
"esnext": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"latedef": true,
"newcap": true,
"noarg": true,
"sub": true,
"undef": true,
"boss": true,
"eqnull": true,
"node": true
}

209
Gruntfile.js Normal file
View File

@ -0,0 +1,209 @@
/*
* asteroidos.org
*
* Copyright (c) 2017, Florent Revest, Alexis Sellier, Less Core Team, contributors.
* Licensed under the MIT license.
*/
'use strict';
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
// Project metadata
pkg: grunt.file.readJSON('package.json'),
site: grunt.file.readYAML('.assemblerc.yml'),
jshint: {
options: {
jshintrc: '.jshintrc'
},
all: ['Gruntfile.js', '<%= site.helpers %>/*.js']
},
// Build HTML from templates and data
assemble: {
options: {
flatten: true,
production: false,
assets: '<%= site.dest %>/public',
// Metadata
pkg: '<%= pkg %>', // extend the context with `pkg`
site: '<%= site %>', // extend the context with `site`
// Templates
partials: '<%= site.includes %>/*.hbs',
layoutdir: '<%= site.layouts %>',
layoutext: '<%= site.layoutext %>',
layout: '<%= site.layout %>',
// Extensions
// mixins: ['<%= site.mixins %>/utils.js'],
helpers: ['<%= site.helpers %>/*.js'],
plugins: ['<%= site.plugins %>'],
// `compose` helper options
compose: {cwd: 'pages'},
// markdown options
marked: {
process: true,
// highlight.js options
prefix: 'lang-'
}
},
site: {
options: {
permalinks: {preset: 'pretty'},
partials: ['pages/**/*.md']
},
src: '<%= site.pages %>/*.hbs',
dest: '<%= site.dest %>/'
},
wiki: {
options: {
permalinks: {preset: 'pretty'},
partials: ['pages/**/*.md']
},
src: '<%= site.pages %>/wiki/*.hbs',
dest: '<%= site.dest %>/wiki/'
},
install: {
options: {
permalinks: {preset: 'pretty'},
partials: ['pages/**/*.md']
},
src: '<%= site.pages %>/install/*.hbs',
dest: '<%= site.dest %>/install/'
}
},
prettify: {
site: {
files: [
{
expand: true,
cwd: '<%= site.dest %>',
src: '*.html',
dest: '<%= site.dest %>/',
ext: '.html'
}
]
}
},
connect: {
options: {
port: 9000,
livereload: 35729,
hostname: 'localhost'
},
livereload: {
options: {
open: true,
base: ['<%= site.dest %>']
}
}
},
// Compile Less to CSS
less: {
options: {
paths: ['styles/bootstrap', 'styles/components']
},
site: {
src: ['styles/index.less'],
dest: '<%= assemble.options.assets %>/css/index.css'
}
},
// Copy source assets to _gh_pages
copy: {
assets: {
files: [
{
expand: true,
cwd: '<%= site.assets %>/public',
src: ['**'],
dest: '<%= site.dest %>/public/'
},
{
expand: true,
cwd: '<%= site.assets %>/root',
src: ['*'],
dest: '<%= site.dest %>/',
rename: function (dest, src) {
dest = dest + src.replace(/^_/, '');
return dest;
}
}
]
}
},
watch: {
options: {livereload: true },
styles: {
files: ['<%= site.styles %>/**/*.less'],
tasks: ['less:site']
},
pages: {
files: ['<%= site.pages %>/**/*.hbs'],
tasks: ['assemble:site']
},
wiki: {
files: ['<%= site.pages %>/**/**/*.hbs'],
tasks: ['assemble:wiki']
},
install: {
files: ['<%= site.pages %>/**/**/*.hbs'],
tasks: ['assemble:install']
},
templates: {
files: ['<%= site.templates %>/**/*.hbs'],
tasks: ['assemble:site']
},
assets: {
files: ['<%= site.assets %>/**/*.*'],
tasks: ['copy']
}
}
});
// Load npm plugins to provide necessary tasks.
grunt.loadNpmTasks('assemble');
grunt.loadNpmTasks('assemble-less');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-prettify');
grunt.loadNpmTasks('grunt-repos');
grunt.loadNpmTasks('grunt-sync-pkg');
grunt.loadNpmTasks('grunt-http-download');
grunt.registerTask('design', [
'copy',
'less:site',
'assemble:site',
'assemble:wiki',
'assemble:install',
'connect',
'watch'
]);
// Default tasks to be run.
grunt.registerTask('default', [
'jshint',
'copy',
'less:site',
'assemble:site',
'assemble:wiki',
'assemble:install'
]);
};

319
LICENSE-CC Normal file
View File

@ -0,0 +1,319 @@
Creative Commons Legal Code
Attribution 3.0 Unported
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
DAMAGES RESULTING FROM ITS USE.
License
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
CONDITIONS.
1. Definitions
a. "Adaptation" means a work based upon the Work, or upon the Work and
other pre-existing works, such as a translation, adaptation,
derivative work, arrangement of music or other alterations of a
literary or artistic work, or phonogram or performance and includes
cinematographic adaptations or any other form in which the Work may be
recast, transformed, or adapted including in any form recognizably
derived from the original, except that a work that constitutes a
Collection will not be considered an Adaptation for the purpose of
this License. For the avoidance of doubt, where the Work is a musical
work, performance or phonogram, the synchronization of the Work in
timed-relation with a moving image ("synching") will be considered an
Adaptation for the purpose of this License.
b. "Collection" means a collection of literary or artistic works, such as
encyclopedias and anthologies, or performances, phonograms or
broadcasts, or other works or subject matter other than works listed
in Section 1(f) below, which, by reason of the selection and
arrangement of their contents, constitute intellectual creations, in
which the Work is included in its entirety in unmodified form along
with one or more other contributions, each constituting separate and
independent works in themselves, which together are assembled into a
collective whole. A work that constitutes a Collection will not be
considered an Adaptation (as defined above) for the purposes of this
License.
c. "Distribute" means to make available to the public the original and
copies of the Work or Adaptation, as appropriate, through sale or
other transfer of ownership.
d. "Licensor" means the individual, individuals, entity or entities that
offer(s) the Work under the terms of this License.
e. "Original Author" means, in the case of a literary or artistic work,
the individual, individuals, entity or entities who created the Work
or if no individual or entity can be identified, the publisher; and in
addition (i) in the case of a performance the actors, singers,
musicians, dancers, and other persons who act, sing, deliver, declaim,
play in, interpret or otherwise perform literary or artistic works or
expressions of folklore; (ii) in the case of a phonogram the producer
being the person or legal entity who first fixes the sounds of a
performance or other sounds; and, (iii) in the case of broadcasts, the
organization that transmits the broadcast.
f. "Work" means the literary and/or artistic work offered under the terms
of this License including without limitation any production in the
literary, scientific and artistic domain, whatever may be the mode or
form of its expression including digital form, such as a book,
pamphlet and other writing; a lecture, address, sermon or other work
of the same nature; a dramatic or dramatico-musical work; a
choreographic work or entertainment in dumb show; a musical
composition with or without words; a cinematographic work to which are
assimilated works expressed by a process analogous to cinematography;
a work of drawing, painting, architecture, sculpture, engraving or
lithography; a photographic work to which are assimilated works
expressed by a process analogous to photography; a work of applied
art; an illustration, map, plan, sketch or three-dimensional work
relative to geography, topography, architecture or science; a
performance; a broadcast; a phonogram; a compilation of data to the
extent it is protected as a copyrightable work; or a work performed by
a variety or circus performer to the extent it is not otherwise
considered a literary or artistic work.
g. "You" means an individual or entity exercising rights under this
License who has not previously violated the terms of this License with
respect to the Work, or who has received express permission from the
Licensor to exercise rights under this License despite a previous
violation.
h. "Publicly Perform" means to perform public recitations of the Work and
to communicate to the public those public recitations, by any means or
process, including by wire or wireless means or public digital
performances; to make available to the public Works in such a way that
members of the public may access these Works from a place and at a
place individually chosen by them; to perform the Work to the public
by any means or process and the communication to the public of the
performances of the Work, including by public digital performance; to
broadcast and rebroadcast the Work by any means including signs,
sounds or images.
i. "Reproduce" means to make copies of the Work by any means including
without limitation by sound or visual recordings and the right of
fixation and reproducing fixations of the Work, including storage of a
protected performance or phonogram in digital form or other electronic
medium.
2. Fair Dealing Rights. Nothing in this License is intended to reduce,
limit, or restrict any uses free from copyright or rights arising from
limitations or exceptions that are provided for in connection with the
copyright protection under copyright law or other applicable laws.
3. License Grant. Subject to the terms and conditions of this License,
Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
perpetual (for the duration of the applicable copyright) license to
exercise the rights in the Work as stated below:
a. to Reproduce the Work, to incorporate the Work into one or more
Collections, and to Reproduce the Work as incorporated in the
Collections;
b. to create and Reproduce Adaptations provided that any such Adaptation,
including any translation in any medium, takes reasonable steps to
clearly label, demarcate or otherwise identify that changes were made
to the original Work. For example, a translation could be marked "The
original work was translated from English to Spanish," or a
modification could indicate "The original work has been modified.";
c. to Distribute and Publicly Perform the Work including as incorporated
in Collections; and,
d. to Distribute and Publicly Perform Adaptations.
e. For the avoidance of doubt:
i. Non-waivable Compulsory License Schemes. In those jurisdictions in
which the right to collect royalties through any statutory or
compulsory licensing scheme cannot be waived, the Licensor
reserves the exclusive right to collect such royalties for any
exercise by You of the rights granted under this License;
ii. Waivable Compulsory License Schemes. In those jurisdictions in
which the right to collect royalties through any statutory or
compulsory licensing scheme can be waived, the Licensor waives the
exclusive right to collect such royalties for any exercise by You
of the rights granted under this License; and,
iii. Voluntary License Schemes. The Licensor waives the right to
collect royalties, whether individually or, in the event that the
Licensor is a member of a collecting society that administers
voluntary licensing schemes, via that society, from any exercise
by You of the rights granted under this License.
The above rights may be exercised in all media and formats whether now
known or hereafter devised. The above rights include the right to make
such modifications as are technically necessary to exercise the rights in
other media and formats. Subject to Section 8(f), all rights not expressly
granted by Licensor are hereby reserved.
4. Restrictions. The license granted in Section 3 above is expressly made
subject to and limited by the following restrictions:
a. You may Distribute or Publicly Perform the Work only under the terms
of this License. You must include a copy of, or the Uniform Resource
Identifier (URI) for, this License with every copy of the Work You
Distribute or Publicly Perform. You may not offer or impose any terms
on the Work that restrict the terms of this License or the ability of
the recipient of the Work to exercise the rights granted to that
recipient under the terms of the License. You may not sublicense the
Work. You must keep intact all notices that refer to this License and
to the disclaimer of warranties with every copy of the Work You
Distribute or Publicly Perform. When You Distribute or Publicly
Perform the Work, You may not impose any effective technological
measures on the Work that restrict the ability of a recipient of the
Work from You to exercise the rights granted to that recipient under
the terms of the License. This Section 4(a) applies to the Work as
incorporated in a Collection, but this does not require the Collection
apart from the Work itself to be made subject to the terms of this
License. If You create a Collection, upon notice from any Licensor You
must, to the extent practicable, remove from the Collection any credit
as required by Section 4(b), as requested. If You create an
Adaptation, upon notice from any Licensor You must, to the extent
practicable, remove from the Adaptation any credit as required by
Section 4(b), as requested.
b. If You Distribute, or Publicly Perform the Work or any Adaptations or
Collections, You must, unless a request has been made pursuant to
Section 4(a), keep intact all copyright notices for the Work and
provide, reasonable to the medium or means You are utilizing: (i) the
name of the Original Author (or pseudonym, if applicable) if supplied,
and/or if the Original Author and/or Licensor designate another party
or parties (e.g., a sponsor institute, publishing entity, journal) for
attribution ("Attribution Parties") in Licensor's copyright notice,
terms of service or by other reasonable means, the name of such party
or parties; (ii) the title of the Work if supplied; (iii) to the
extent reasonably practicable, the URI, if any, that Licensor
specifies to be associated with the Work, unless such URI does not
refer to the copyright notice or licensing information for the Work;
and (iv) , consistent with Section 3(b), in the case of an Adaptation,
a credit identifying the use of the Work in the Adaptation (e.g.,
"French translation of the Work by Original Author," or "Screenplay
based on original Work by Original Author"). The credit required by
this Section 4 (b) may be implemented in any reasonable manner;
provided, however, that in the case of a Adaptation or Collection, at
a minimum such credit will appear, if a credit for all contributing
authors of the Adaptation or Collection appears, then as part of these
credits and in a manner at least as prominent as the credits for the
other contributing authors. For the avoidance of doubt, You may only
use the credit required by this Section for the purpose of attribution
in the manner set out above and, by exercising Your rights under this
License, You may not implicitly or explicitly assert or imply any
connection with, sponsorship or endorsement by the Original Author,
Licensor and/or Attribution Parties, as appropriate, of You or Your
use of the Work, without the separate, express prior written
permission of the Original Author, Licensor and/or Attribution
Parties.
c. Except as otherwise agreed in writing by the Licensor or as may be
otherwise permitted by applicable law, if You Reproduce, Distribute or
Publicly Perform the Work either by itself or as part of any
Adaptations or Collections, You must not distort, mutilate, modify or
take other derogatory action in relation to the Work which would be
prejudicial to the Original Author's honor or reputation. Licensor
agrees that in those jurisdictions (e.g. Japan), in which any exercise
of the right granted in Section 3(b) of this License (the right to
make Adaptations) would be deemed to be a distortion, mutilation,
modification or other derogatory action prejudicial to the Original
Author's honor and reputation, the Licensor will waive or not assert,
as appropriate, this Section, to the fullest extent permitted by the
applicable national law, to enable You to reasonably exercise Your
right under Section 3(b) of this License (right to make Adaptations)
but not otherwise.
5. Representations, Warranties and Disclaimer
UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION
OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
7. Termination
a. This License and the rights granted hereunder will terminate
automatically upon any breach by You of the terms of this License.
Individuals or entities who have received Adaptations or Collections
from You under this License, however, will not have their licenses
terminated provided such individuals or entities remain in full
compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
survive any termination of this License.
b. Subject to the above terms and conditions, the license granted here is
perpetual (for the duration of the applicable copyright in the Work).
Notwithstanding the above, Licensor reserves the right to release the
Work under different license terms or to stop distributing the Work at
any time; provided, however that any such election will not serve to
withdraw this License (or any other license that has been, or is
required to be, granted under the terms of this License), and this
License will continue in full force and effect unless terminated as
stated above.
8. Miscellaneous
a. Each time You Distribute or Publicly Perform the Work or a Collection,
the Licensor offers to the recipient a license to the Work on the same
terms and conditions as the license granted to You under this License.
b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
offers to the recipient a license to the original Work on the same
terms and conditions as the license granted to You under this License.
c. If any provision of this License is invalid or unenforceable under
applicable law, it shall not affect the validity or enforceability of
the remainder of the terms of this License, and without further action
by the parties to this agreement, such provision shall be reformed to
the minimum extent necessary to make such provision valid and
enforceable.
d. No term or provision of this License shall be deemed waived and no
breach consented to unless such waiver or consent shall be in writing
and signed by the party to be charged with such waiver or consent.
e. This License constitutes the entire agreement between the parties with
respect to the Work licensed here. There are no understandings,
agreements or representations with respect to the Work not specified
here. Licensor shall not be bound by any additional provisions that
may appear in any communication from You. This License may not be
modified without the mutual written agreement of the Licensor and You.
f. The rights granted under, and the subject matter referenced, in this
License were drafted utilizing the terminology of the Berne Convention
for the Protection of Literary and Artistic Works (as amended on
September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996
and the Universal Copyright Convention (as revised on July 24, 1971).
These rights and subject matter take effect in the relevant
jurisdiction in which the License terms are sought to be enforced
according to the corresponding provisions of the implementation of
those treaty provisions in the applicable national law. If the
standard suite of rights granted under applicable copyright law
includes additional rights not granted under this License, such
additional rights are deemed to be included in the License; this
License is not intended to restrict the license of any rights under
applicable law.
Creative Commons Notice
Creative Commons is not a party to this License, and makes no warranty
whatsoever in connection with the Work. Creative Commons will not be
liable to You or any party on any legal theory for any damages
whatsoever, including without limitation any general, special,
incidental or consequential damages arising in connection to this
license. Notwithstanding the foregoing two (2) sentences, if Creative
Commons has expressly identified itself as the Licensor hereunder, it
shall have all rights and obligations of Licensor.
Except for the limited purpose of indicating to the public that the
Work is licensed under the CCPL, Creative Commons does not authorize
the use by either party of the trademark "Creative Commons" or any
related trademark or logo of Creative Commons without the prior
written consent of Creative Commons. Any permitted use will be in
compliance with Creative Commons' then-current trademark usage
guidelines, as may be published on its website or otherwise made
available upon request from time to time. For the avoidance of doubt,
this trademark restriction does not form part of this License.
Creative Commons may be contacted at http://creativecommons.org/.

23
LICENSE-MIT Normal file
View File

@ -0,0 +1,23 @@
Copyright (c) 2017 Florent Revest
Copyright (c) 2013 Alexis Sellier, Less.js, contributors.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

20
README.md Normal file
View File

@ -0,0 +1,20 @@
# asteroidos.org
> Official website and documentation for AsteroidOS
## Quickstart
Assemble and Grunt are used to build the site. To get started:
1. Clone this repository
2. In the root of the repo, run `npm install`
3. Run the `grunt` command to build the site
If all worked properly, you should have your website ready in an '_asteroidos.org' folder
## License
This website is a fork of lesscss.org
Copyright (c) 2017, Florent Revest, Alexis Sellier, Less Core Team, Contributors
Content released under [Creative Commons](./LICENSE-CC).
Source code released under the [MIT License](./LICENSE-MIT).

Binary file not shown.

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 326 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
assets/public/img/bass.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

BIN
assets/public/img/dory.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
assets/public/img/lenok.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
assets/public/img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
assets/public/img/sprat.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
assets/public/img/swift.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
assets/public/img/tetra.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
assets/public/img/watch.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

View File

@ -0,0 +1,103 @@
/*!
* Adapted from Bootstrap docs JavaScript
*/
!function ($) {
$(function () {
// IE10 viewport hack for Surface/desktop Windows 8 bug
//
// See Getting Started docs for more information
if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
var msViewportStyle = document.createElement('style')
msViewportStyle.appendChild(
document.createTextNode(
'@-ms-viewport{width:auto!important}'
)
)
document.querySelector('head').appendChild(msViewportStyle)
}
var $window = $(window)
var $body = $(document.body)
$body.scrollspy({
target: '.sidebar',
offset: 20 // required to select the right thing. if this is smaller then you are at the top of one section
// but the next section is highlighted
});
$window.on('load', function () {
$body.scrollspy('refresh')
});
$('.docs-container [href=#]').click(function (e) {
e.preventDefault()
});
$('.source-link').each(function () {
var id = $(this).data('content');
var content = $('<span>').append($('#' + id)).html();
$(this).attr('data-content', content);
// Keep popovers open when hovered
$(this).popover({
trigger: 'manual',
container: 'body',
placement: 'left',
template: '<div class="popover popover-source"> <div class="arrow"></div> <div class="popover-inner"> <h3 class="popover-title"></h3> <div class="popover-content"> <p></p> </div> </div> </div>',
html: true,
delay: {show: 50, hide: 750}
}).on('mouseenter', function () {
var self = this;
$(this).popover('show');
$(this).addClass('active');
$(this).addClass('popover-source');
$('.popover').on('mouseleave', function () {
$(self).popover('hide');
$(self).removeClass('active');
});
}).on('mouseleave', function () {
var self = this;
setTimeout(function () {
if (!$('.popover:hover').length) {
$(self).popover('hide');
$(self).removeClass('active');
}
}, 100);
});
});
// back to top
setTimeout(function () {
var $sideBar = $('.sidebar')
$sideBar.affix({
offset: {
top: function () {
var offsetTop = $sideBar.offset().top
var sideBarMargin = parseInt($sideBar.children(0).css('margin-top'), 10)
var navOuterHeight = $('.docs-nav').height()
return (this.top = offsetTop - navOuterHeight - sideBarMargin)
},
bottom: function () {
return (this.bottom = $('.footer').outerHeight(true))
}
}
})
}, 100);
setTimeout(function () {
$('.top').affix()
}, 100);
})
}(jQuery)

6
assets/public/js/bootstrap.min.js vendored Normal file

File diff suppressed because one or more lines are too long

8
assets/root/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
node_modules
npm-debug.log
tmp
temp
TODO.md
*.sublime-*

319
assets/root/LICENSE-CC Normal file
View File

@ -0,0 +1,319 @@
Creative Commons Legal Code
Attribution 3.0 Unported
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
DAMAGES RESULTING FROM ITS USE.
License
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
CONDITIONS.
1. Definitions
a. "Adaptation" means a work based upon the Work, or upon the Work and
other pre-existing works, such as a translation, adaptation,
derivative work, arrangement of music or other alterations of a
literary or artistic work, or phonogram or performance and includes
cinematographic adaptations or any other form in which the Work may be
recast, transformed, or adapted including in any form recognizably
derived from the original, except that a work that constitutes a
Collection will not be considered an Adaptation for the purpose of
this License. For the avoidance of doubt, where the Work is a musical
work, performance or phonogram, the synchronization of the Work in
timed-relation with a moving image ("synching") will be considered an
Adaptation for the purpose of this License.
b. "Collection" means a collection of literary or artistic works, such as
encyclopedias and anthologies, or performances, phonograms or
broadcasts, or other works or subject matter other than works listed
in Section 1(f) below, which, by reason of the selection and
arrangement of their contents, constitute intellectual creations, in
which the Work is included in its entirety in unmodified form along
with one or more other contributions, each constituting separate and
independent works in themselves, which together are assembled into a
collective whole. A work that constitutes a Collection will not be
considered an Adaptation (as defined above) for the purposes of this
License.
c. "Distribute" means to make available to the public the original and
copies of the Work or Adaptation, as appropriate, through sale or
other transfer of ownership.
d. "Licensor" means the individual, individuals, entity or entities that
offer(s) the Work under the terms of this License.
e. "Original Author" means, in the case of a literary or artistic work,
the individual, individuals, entity or entities who created the Work
or if no individual or entity can be identified, the publisher; and in
addition (i) in the case of a performance the actors, singers,
musicians, dancers, and other persons who act, sing, deliver, declaim,
play in, interpret or otherwise perform literary or artistic works or
expressions of folklore; (ii) in the case of a phonogram the producer
being the person or legal entity who first fixes the sounds of a
performance or other sounds; and, (iii) in the case of broadcasts, the
organization that transmits the broadcast.
f. "Work" means the literary and/or artistic work offered under the terms
of this License including without limitation any production in the
literary, scientific and artistic domain, whatever may be the mode or
form of its expression including digital form, such as a book,
pamphlet and other writing; a lecture, address, sermon or other work
of the same nature; a dramatic or dramatico-musical work; a
choreographic work or entertainment in dumb show; a musical
composition with or without words; a cinematographic work to which are
assimilated works expressed by a process analogous to cinematography;
a work of drawing, painting, architecture, sculpture, engraving or
lithography; a photographic work to which are assimilated works
expressed by a process analogous to photography; a work of applied
art; an illustration, map, plan, sketch or three-dimensional work
relative to geography, topography, architecture or science; a
performance; a broadcast; a phonogram; a compilation of data to the
extent it is protected as a copyrightable work; or a work performed by
a variety or circus performer to the extent it is not otherwise
considered a literary or artistic work.
g. "You" means an individual or entity exercising rights under this
License who has not previously violated the terms of this License with
respect to the Work, or who has received express permission from the
Licensor to exercise rights under this License despite a previous
violation.
h. "Publicly Perform" means to perform public recitations of the Work and
to communicate to the public those public recitations, by any means or
process, including by wire or wireless means or public digital
performances; to make available to the public Works in such a way that
members of the public may access these Works from a place and at a
place individually chosen by them; to perform the Work to the public
by any means or process and the communication to the public of the
performances of the Work, including by public digital performance; to
broadcast and rebroadcast the Work by any means including signs,
sounds or images.
i. "Reproduce" means to make copies of the Work by any means including
without limitation by sound or visual recordings and the right of
fixation and reproducing fixations of the Work, including storage of a
protected performance or phonogram in digital form or other electronic
medium.
2. Fair Dealing Rights. Nothing in this License is intended to reduce,
limit, or restrict any uses free from copyright or rights arising from
limitations or exceptions that are provided for in connection with the
copyright protection under copyright law or other applicable laws.
3. License Grant. Subject to the terms and conditions of this License,
Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
perpetual (for the duration of the applicable copyright) license to
exercise the rights in the Work as stated below:
a. to Reproduce the Work, to incorporate the Work into one or more
Collections, and to Reproduce the Work as incorporated in the
Collections;
b. to create and Reproduce Adaptations provided that any such Adaptation,
including any translation in any medium, takes reasonable steps to
clearly label, demarcate or otherwise identify that changes were made
to the original Work. For example, a translation could be marked "The
original work was translated from English to Spanish," or a
modification could indicate "The original work has been modified.";
c. to Distribute and Publicly Perform the Work including as incorporated
in Collections; and,
d. to Distribute and Publicly Perform Adaptations.
e. For the avoidance of doubt:
i. Non-waivable Compulsory License Schemes. In those jurisdictions in
which the right to collect royalties through any statutory or
compulsory licensing scheme cannot be waived, the Licensor
reserves the exclusive right to collect such royalties for any
exercise by You of the rights granted under this License;
ii. Waivable Compulsory License Schemes. In those jurisdictions in
which the right to collect royalties through any statutory or
compulsory licensing scheme can be waived, the Licensor waives the
exclusive right to collect such royalties for any exercise by You
of the rights granted under this License; and,
iii. Voluntary License Schemes. The Licensor waives the right to
collect royalties, whether individually or, in the event that the
Licensor is a member of a collecting society that administers
voluntary licensing schemes, via that society, from any exercise
by You of the rights granted under this License.
The above rights may be exercised in all media and formats whether now
known or hereafter devised. The above rights include the right to make
such modifications as are technically necessary to exercise the rights in
other media and formats. Subject to Section 8(f), all rights not expressly
granted by Licensor are hereby reserved.
4. Restrictions. The license granted in Section 3 above is expressly made
subject to and limited by the following restrictions:
a. You may Distribute or Publicly Perform the Work only under the terms
of this License. You must include a copy of, or the Uniform Resource
Identifier (URI) for, this License with every copy of the Work You
Distribute or Publicly Perform. You may not offer or impose any terms
on the Work that restrict the terms of this License or the ability of
the recipient of the Work to exercise the rights granted to that
recipient under the terms of the License. You may not sublicense the
Work. You must keep intact all notices that refer to this License and
to the disclaimer of warranties with every copy of the Work You
Distribute or Publicly Perform. When You Distribute or Publicly
Perform the Work, You may not impose any effective technological
measures on the Work that restrict the ability of a recipient of the
Work from You to exercise the rights granted to that recipient under
the terms of the License. This Section 4(a) applies to the Work as
incorporated in a Collection, but this does not require the Collection
apart from the Work itself to be made subject to the terms of this
License. If You create a Collection, upon notice from any Licensor You
must, to the extent practicable, remove from the Collection any credit
as required by Section 4(b), as requested. If You create an
Adaptation, upon notice from any Licensor You must, to the extent
practicable, remove from the Adaptation any credit as required by
Section 4(b), as requested.
b. If You Distribute, or Publicly Perform the Work or any Adaptations or
Collections, You must, unless a request has been made pursuant to
Section 4(a), keep intact all copyright notices for the Work and
provide, reasonable to the medium or means You are utilizing: (i) the
name of the Original Author (or pseudonym, if applicable) if supplied,
and/or if the Original Author and/or Licensor designate another party
or parties (e.g., a sponsor institute, publishing entity, journal) for
attribution ("Attribution Parties") in Licensor's copyright notice,
terms of service or by other reasonable means, the name of such party
or parties; (ii) the title of the Work if supplied; (iii) to the
extent reasonably practicable, the URI, if any, that Licensor
specifies to be associated with the Work, unless such URI does not
refer to the copyright notice or licensing information for the Work;
and (iv) , consistent with Section 3(b), in the case of an Adaptation,
a credit identifying the use of the Work in the Adaptation (e.g.,
"French translation of the Work by Original Author," or "Screenplay
based on original Work by Original Author"). The credit required by
this Section 4 (b) may be implemented in any reasonable manner;
provided, however, that in the case of a Adaptation or Collection, at
a minimum such credit will appear, if a credit for all contributing
authors of the Adaptation or Collection appears, then as part of these
credits and in a manner at least as prominent as the credits for the
other contributing authors. For the avoidance of doubt, You may only
use the credit required by this Section for the purpose of attribution
in the manner set out above and, by exercising Your rights under this
License, You may not implicitly or explicitly assert or imply any
connection with, sponsorship or endorsement by the Original Author,
Licensor and/or Attribution Parties, as appropriate, of You or Your
use of the Work, without the separate, express prior written
permission of the Original Author, Licensor and/or Attribution
Parties.
c. Except as otherwise agreed in writing by the Licensor or as may be
otherwise permitted by applicable law, if You Reproduce, Distribute or
Publicly Perform the Work either by itself or as part of any
Adaptations or Collections, You must not distort, mutilate, modify or
take other derogatory action in relation to the Work which would be
prejudicial to the Original Author's honor or reputation. Licensor
agrees that in those jurisdictions (e.g. Japan), in which any exercise
of the right granted in Section 3(b) of this License (the right to
make Adaptations) would be deemed to be a distortion, mutilation,
modification or other derogatory action prejudicial to the Original
Author's honor and reputation, the Licensor will waive or not assert,
as appropriate, this Section, to the fullest extent permitted by the
applicable national law, to enable You to reasonably exercise Your
right under Section 3(b) of this License (right to make Adaptations)
but not otherwise.
5. Representations, Warranties and Disclaimer
UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION
OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
7. Termination
a. This License and the rights granted hereunder will terminate
automatically upon any breach by You of the terms of this License.
Individuals or entities who have received Adaptations or Collections
from You under this License, however, will not have their licenses
terminated provided such individuals or entities remain in full
compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
survive any termination of this License.
b. Subject to the above terms and conditions, the license granted here is
perpetual (for the duration of the applicable copyright in the Work).
Notwithstanding the above, Licensor reserves the right to release the
Work under different license terms or to stop distributing the Work at
any time; provided, however that any such election will not serve to
withdraw this License (or any other license that has been, or is
required to be, granted under the terms of this License), and this
License will continue in full force and effect unless terminated as
stated above.
8. Miscellaneous
a. Each time You Distribute or Publicly Perform the Work or a Collection,
the Licensor offers to the recipient a license to the Work on the same
terms and conditions as the license granted to You under this License.
b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
offers to the recipient a license to the original Work on the same
terms and conditions as the license granted to You under this License.
c. If any provision of this License is invalid or unenforceable under
applicable law, it shall not affect the validity or enforceability of
the remainder of the terms of this License, and without further action
by the parties to this agreement, such provision shall be reformed to
the minimum extent necessary to make such provision valid and
enforceable.
d. No term or provision of this License shall be deemed waived and no
breach consented to unless such waiver or consent shall be in writing
and signed by the party to be charged with such waiver or consent.
e. This License constitutes the entire agreement between the parties with
respect to the Work licensed here. There are no understandings,
agreements or representations with respect to the Work not specified
here. Licensor shall not be bound by any additional provisions that
may appear in any communication from You. This License may not be
modified without the mutual written agreement of the Licensor and You.
f. The rights granted under, and the subject matter referenced, in this
License were drafted utilizing the terminology of the Berne Convention
for the Protection of Literary and Artistic Works (as amended on
September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996
and the Universal Copyright Convention (as revised on July 24, 1971).
These rights and subject matter take effect in the relevant
jurisdiction in which the License terms are sought to be enforced
according to the corresponding provisions of the implementation of
those treaty provisions in the applicable national law. If the
standard suite of rights granted under applicable copyright law
includes additional rights not granted under this License, such
additional rights are deemed to be included in the License; this
License is not intended to restrict the license of any rights under
applicable law.
Creative Commons Notice
Creative Commons is not a party to this License, and makes no warranty
whatsoever in connection with the Work. Creative Commons will not be
liable to You or any party on any legal theory for any damages
whatsoever, including without limitation any general, special,
incidental or consequential damages arising in connection to this
license. Notwithstanding the foregoing two (2) sentences, if Creative
Commons has expressly identified itself as the Licensor hereunder, it
shall have all rights and obligations of Licensor.
Except for the limited purpose of indicating to the public that the
Work is licensed under the CCPL, Creative Commons does not authorize
the use by either party of the trademark "Creative Commons" or any
related trademark or logo of Creative Commons without the prior
written consent of Creative Commons. Any permitted use will be in
compliance with Creative Commons' then-current trademark usage
guidelines, as may be published on its website or otherwise made
available upon request from time to time. For the avoidance of doubt,
this trademark restriction does not form part of this License.
Creative Commons may be contacted at http://creativecommons.org/.

23
assets/root/LICENSE-MIT Normal file
View File

@ -0,0 +1,23 @@
Copyright (c) 2017 Florent Revest
Copyright (c) 2013 Alexis Sellier, Less.js, contributors.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

1
assets/root/_CNAME Normal file
View File

@ -0,0 +1 @@
asteroidos.org

64
package.json Normal file
View File

@ -0,0 +1,64 @@
{
"name": "asteroidos.org",
"description": "Official website for AsteroidOS",
"version": "1.0.0",
"homepage": "https://github.com/AsteroidOS/asteroidos.org",
"author": "The AsteroidOS project",
"repository": {
"type": "git",
"url": "https://github.com/AsteroidOS/asteroidos.org.git"
},
"bugs": {
"url": "https://github.com/AsteroidOS/asteroidos.org/issues"
},
"license": "(MIT OR CC-BY-3.0)",
"main": "Gruntfile.js",
"devDependencies": {
"assemble": "^0.4.42",
"assemble-contrib-permalinks": "^0.3.6",
"assemble-less": "^0.7.0",
"chalk": "^0.5.1",
"cheerio": "^0.17.0",
"cwd": "^0.3.7",
"fs-utils": "^0.4.3",
"git-branch": "^0.1.2",
"git-repo-name": "^0.2.0",
"git-username": "^0.2.0",
"github": "^0.2.2",
"github-repo-url": "^0.2.1",
"gray-matter": "^0.5.0",
"grunt": "^0.4.5",
"grunt-contrib-clean": "^0.6.0",
"grunt-contrib-connect": "^0.8.0",
"grunt-contrib-copy": "^0.5.0",
"grunt-contrib-jshint": "^1.0.0",
"grunt-contrib-watch": "^0.6.1",
"grunt-http-download": "^0.1.0",
"grunt-prettify": "^0.3.5",
"grunt-repos": "^0.1.2",
"grunt-sync-pkg": "^0.1.2",
"handlebars": "^2.0.0",
"handlebars-helper-datetime": "^0.1.0",
"handlebars-helper-feed": "^0.1.1",
"handlebars-helper-slugify": "^0.2.0",
"highlight.js": "^9.11.0",
"lodash": "^2.4.1",
"marked": "^0.3.2",
"marked-extras": "^0.2.4",
"relative": "^0.1.6",
"remote-origin-url": "^0.2.1",
"request": "^2.42.0",
"strip-indent": "^1.0.0",
"template": "^0.2.1",
"verbalize": "^0.1.2"
},
"keywords": [
"handlebars-helper-datetime",
"handlebars-helper-feed",
"handlebars-helper-slugify",
"less css",
"less",
"less.js",
"lesscss"
]
}

40
pages/about.hbs Normal file
View File

@ -0,0 +1,40 @@
---
title: About
slug: about
---
<div class="videocontainer">
<iframe src="https://www.youtube-nocookie.com/embed/cVg-vEJlUkU?rel=0&amp;controls=0&amp;showinfo=0" frameborder="0" allowfullscreen class="video"></iframe>
</div>
<div class="about-row">
<div class="about-text">
<h2>Freedom & Privacy</h2>
<p>We believe that when it comes to wearable devices, users should have full control over their machines and data. AsteroidOS has been created from the ground-up with modularity and freedom in mind. For this reason, it is a <a href="https://github.com/AsteroidOS/">free and open-source</a> project.</p>
</div>
<div class="about-img"><img src="{{assets}}/img/about1.jpg" width="300" height="300" /></div>
</div>
<div class="about-row">
<div class="about-img"><img src="{{assets}}/img/about2.jpg" width="300" height="300" /></div>
<div class="about-text">
<h2>Ready for your wrist</h2>
<p>AsteroidOS unleashes the potential of your watch with up to 48 hours of autonomy and a set of apps including everything you need on a smartwatch: an agenda, an alarm clock, a calculator, a music controller, settings, a stopwatch, a timer and a weather forecast app.</p>
</div>
</div>
<div class="about-row">
<div class="about-text">
<h2>Proven building blocks</h2>
<p>AsteroidOS is built upon a rock-solid base system. <a href="http://www.qt.io/">Qt 5.9 and QML</a> are used for fast and easy app development. <a href="http://www.openembedded.org/">OpenEmbedded</a> provides a full GNU/Linux distribution and <a href="https://en.wikipedia.org/wiki/Hybris_(software)">libhybris</a> allows easy porting to most Android and Android Wear watches.</p>
</div>
<div class="about-img"><img src="{{assets}}/img/about3.jpg" width="300" height="300" /></div>
</div>
<div class="about-row">
<div class="about-img"><img src="{{assets}}/img/about4.jpg" width="300" height="300" /></div>
<div class="about-text">
<h2>Community-friendly</h2>
<p>Since its creation in 2015, AsteroidOS has been led by <a href="https://www.linkedin.com/in/florentrevest">Florent Revest</a>, but is open towards external contribution and collaboration. The project is still in active development and if you want to help, make sure to check the <a href="{{rel 'community'}}">Get Involved</a> page.</p>
</div>
</div>

46
pages/community.hbs Normal file
View File

@ -0,0 +1,46 @@
---
title: Get Involved
slug: community
---
<img src="{{assets}}/img/community.jpg" class="community-header-img"/>
<p>AsteroidOS is driven by a vibrant community. If you are interested in making wearable devices more open, here are a couple of ways to join us:</p>
<div class="community-box-ratio"><div class="community-box"><div class="community-centered-text">
<b>Developing:</b><br><br>
Developers can use <a href="http://doc.qt.io/qt-5/qtquick-index.html">QtQuick</a> and <a href="https://github.com/AsteroidOS/qml-asteroid">qml-asteroid</a> to create <a href="{{rel 'wiki/creating-an-asteroid-app'}}">apps</a>, <a href="https://github.com/AsteroidOS/qml-asteroid/tree/master/src/controls/qml">components</a> or <a href="{{rel 'wiki/watchfaces-creation/'}}">watchfaces</a>. C and C++ can also be used for middlewares maintenance.
</div></div></div>
<div class="community-box-ratio"><div class="community-box"><div class="community-centered-text">
<b>Porting:</b><br><br>
Those who are comfortable with Linux systems can <a href="{{rel 'wiki/porting-guide/'}}">port AsteroidOS</a> to new smartwatches and help maintain the <a href="https://github.com/AsteroidOS/meta-asteroid">OpenEmbedded layers</a>.
</div></div></div>
<div class="community-box-ratio"><div class="community-box"><div class="community-centered-text">
<b>Designing:</b><br><br>
Designers can join the UI & UX taskforce to brainstorm on the future of AsteroidOS, conduct usability reports and create mockups or wireframes for developers.
</div></div></div>
<div class="community-box-ratio"><div class="community-box"><div class="community-centered-text">
<b>Translating:</b><br><br>
Internationalization requires contributions from many different persons. Everyone can <a href="{{rel 'wiki/translating-asteroidos/'}}">create, review or maintain AsteroidOS translations</a> on Weblate.
</div></div></div>
<div class="community-box-ratio"><div class="community-box"><div class="community-centered-text">
<b>Testing:</b><br><br>
AsteroidOS is still in development and nightly builds are known to contain bugs. Testers can report and fix bugs or give new ideas on the <a href="https://github.com/AsteroidOS/asteroid/issues">bug tracker</a>.
</div></div></div>
<div class="community-box-ratio"><div class="community-box"><div class="community-centered-text">
<b>Donating:</b><br><br>
Donations are exclusively used to buy unsupported smartwatches or cover basic costs such as the server.
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top"><input name="cmd" type="hidden" value="_s-xclick" />
<input name="hosted_button_id" type="hidden" value="W7VU2KBGJCWE2" />
<input title="PayPal - The safer, easier way to pay online!" alt="Donate" name="submit" src="https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif" type="image" />
<img src="https://www.paypal.com/en_US/i/scr/pixel.gif" alt="" width="1" height="1" border="0" />
</form>
<script id='fbh2aim'>(function(i){var f,s=document.getElementById(i);f=document.createElement('iframe');f.src='//button.flattr.com/view/?fid=o6o0nq&button=compact&url='+encodeURIComponent(document.URL);f.title='Flattr';f.height=20;f.width=110;f.style.borderWidth=0;s.parentNode.insertBefore(f,s);})('fbh2aim');</script>
</div></div></div>
<div class="community-box-ratio"><div class="community-box"><div class="community-centered-text">
<b>Others:</b><br><br>
Enthusiasts can join the community on <a href="/contact/">IRC</a>, <a href="https://twitter.com/AsteroidOS">Twitter</a> and <a href="https://github.com/AsteroidOS/">GitHub</a> or even at various events such as Meetups, QtCon, FOSDEM, workshops and others...
</div></div></div>
<div class="community-box-ratio"><div class="community-box-img">
<img src="{{assets}}/img/iwantyou.jpg" width="100%"/>
</div></div>

17
pages/contact.hbs Normal file
View File

@ -0,0 +1,17 @@
---
title: Contact
slug: contact
---
<h3>Community</h3>
General discussions around AsteroidOS happen on the #asteroid IRC channel on Freenode. Logs are available <a href="https://log.asteroidos.org/">here</a>. If you don't have an IRC client, use the webchat below:
<iframe style="border: 0; width: 100%; height: 600px;" src="https://kiwiirc.com/client/irc.freenode.net/#asteroid"></iframe>
<h3>Media & Press</h3>
If you are a journalist looking for more content or details about AsteroidOS, email: <a href="mailto://media@asteroidos.org">media@asteroidos.org</a>
<h3>Partners</h3>
If you are an OEM or ODM interested in professional services around AsteroidOS, email: <a href="mailto://partners@asteroidos.org">partners@asteroidos.org</a>
<h3>Others</h3>
For other reasons, email: <a href="mailto://partners@asteroidos.org">contact@asteroidos.org</a>

15
pages/index.hbs Normal file
View File

@ -0,0 +1,15 @@
---
title: Hack your wrist
slug: index
lead: "AsteroidOS is an open-source operating system for smartwatches."
layout: content
---
<div class="index-header" id="content">
<div class="container">
<img src="{{assets}}/img/watch.png" height="600"><br>
<h1>{{ title }}</h1>
<p>{{ lead }}</p>
<a class="btn btn-primary" href="{{rel 'about'}}" role="button">Learn more</a>
<a class="btn btn-primary" href="{{rel 'install'}}" role="button">Get AsteroidOS</a>
</div>
</div>

56
pages/install.hbs Normal file
View File

@ -0,0 +1,56 @@
---
title: Install
slug: install
---
<p>AsteroidOS can be installed as an alternative operating system on various smartwatches. Instructions for each model can be found thereafter:</p>
<a href="{{rel 'install/anthias'}}"><div class="install-box">
<img src="{{assets}}/img/anthias.jpg" width="100%"><br>
Asus Zenwatch 1 (anthias)
</div></a>
<a href="{{rel 'install/bass'}}"><div class="install-box">
<img src="{{assets}}/img/bass.jpg" width="100%"><br>
LG G Watch Urbane (bass)
</div></a>
<a href="{{rel '/install/dory'}}"><div class="install-box">
<img src="{{assets}}/img/dory.jpg" width="100%"><br>
LG G Watch (dory)
</div></a>
<a href="{{rel '/install/lenok'}}"><div class="install-box">
<img src="{{assets}}/img/lenok.jpg" width="100%"><br>
LG G Watch R (lenok)
</div></a>
<a href="{{rel '/install/sparrow'}}"><div class="install-box">
<img src="{{assets}}/img/sparrow.jpg" width="100%"><br>
Asus Zenwatch 2 (sparrow & wren)
</div></a>
<a href="{{rel '/install/sprat'}}"><div class="install-box">
<img src="{{assets}}/img/sprat.jpg" width="100%"><br>
Samsung Gear Live (sprat)
</div></a>
<a href="{{rel '/install/swift'}}"><div class="install-box">
<img src="{{assets}}/img/swift.jpg" width="100%"><br>
Asus Zenwatch 3 (swift)
</div></a>
<a href="{{rel '/install/tetra'}}"><div class="install-box">
<img src="{{assets}}/img/tetra.jpg" width="100%"><br>
Sony Smartwatch 3 (tetra)
</div></a>
<div class="page-header">
<h1>FAQ</h1>
</div>
<ol>
<li>Will I be able to go back to the previous operating system after installing AsteroidOS on my watch?</li>
<i>When installing AsteroidOS, you can choose between replacing your previous OS or keeping a "dual-boot". If you decide to replace your previous OS, it is advised to make a backup of your <b>userdata</b> and <b>boot</b> partitions before flashing AsteroidOS, you will then be able to re-flash the previous OS later.</i>
<li>Where can I find a phone synchronization app?</li>
<i>A synchronization client for Android phones named "AsteroidOSSync" is already <a href="https://f-droid.org/repository/browse/?fdfilter=it&fdid=org.asteroidos.sync&fdpage=2&fdstyle=grid">available to download on F-Droid</a>.</i>
<li>What features will and won't be working on my watch with AsteroidOS?</li>
<i>Take a look at the table in the <a href="{{rel 'wiki/porting-status'}}">Porting Status</a> page of the documentation for detailed information on your current model's support.</i>
<li>My watch is not listed on this page, what can I do?</li>
<i>You should refer to the <a href="{{rel 'wiki/porting-status'}}">Porting Status</a> page of the documentation and check if a port of AsteroidOS to your watch is possible or in progress. If you are interested in porting AsteroidOS yourself to a new watch, please take a look at the <a href="{{rel 'wiki/porting-guide'}}">Porting Guide</a> page and get in touch with us via IRC.</i>
<li>I do not want to flash a prebuilt image on my watch, can I compile AsteroidOS myself?</li>
<i>Take a look at the <a href="{{rel 'wiki/building-asteroidos'}}">Building AsteroidOS</a> page of the documentation for detailed instructions on how to compile AsteroidOS yourself.</i>
</ol>

View File

@ -0,0 +1,5 @@
---
title: Asus Zenwatch 1
deviceName: anthias
layout: aw-install
---

6
pages/install/bass.hbs Normal file
View File

@ -0,0 +1,6 @@
---
title: LG G Watch Urbane
deviceName: bass
section: install
layout: aw-install
---

5
pages/install/dory.hbs Normal file
View File

@ -0,0 +1,5 @@
---
title: LG G Watch
deviceName: dory
layout: aw-install
---

5
pages/install/lenok.hbs Normal file
View File

@ -0,0 +1,5 @@
---
title: LG G Watch R
deviceName: lenok
layout: aw-install
---

View File

@ -0,0 +1,5 @@
---
title: Asus Zenwatch 2
deviceName: sparrow
layout: aw-install
---

5
pages/install/sprat.hbs Normal file
View File

@ -0,0 +1,5 @@
---
title: Samsung Gear Live
deviceName: sprat
layout: aw-install
---

5
pages/install/swift.hbs Normal file
View File

@ -0,0 +1,5 @@
---
title: Asus Zenwatch 3
deviceName: swift
layout: aw-install
---

5
pages/install/tetra.hbs Normal file
View File

@ -0,0 +1,5 @@
---
title: Sony Smartwatch 3
deviceName: tetra
layout: aw-install
---

111
pages/wiki/bluetooth.hbs Normal file
View File

@ -0,0 +1,111 @@
---
title: Bluetooth
layout: documentation
---
<p>An app named <a href="https://github.com/AsteroidOS/AsteroidOSSync"><em>AsteroidOSSync</em></a> can be downloaded on Android to synchronize data from a phone to an AsteroidOS watch. Several profiles are already coded: Notifications, Weather, Music and Battery, more could come in the future.</p>
<div class="page-header">
<h1 id="technical-details">Technical details</h1>
</div>
<p>On the phone, AsteroidOSSync uses the <a href="https://github.com/AsteroidOS/AsteroidOSSync/tree/master/app/src/main/lib/sweetblue">SweetBlue</a> library to access the Bluetooth Low Energy capabilities of Bluedroid as a central device. It scans for watches and implements the client part of the&nbsp;<span class="gt-baf-word-clickable">aforementioned</span> profiles.</p>
<p>On the watch, data are received by a BCM20715 BT chip from Broadcom, this chip needs a proprietary firmware which is uploaded by the <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-android/brcm-patchram-plus/brcm-patchram-plus/patchram.service">patchram</a> systemd service.&nbsp;Once the firmware is uploaded an hci0 interface is created and can be set up with hciconfig.</p>
<p>The Linux Kernel can then receive BLE payloads. A newer Bluetooth subsystem (4.1) has been <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-kernel/linux/linux-dory/0001-Backport-mainline-4.1-Bluetooth-subsystem.patch">backported</a> to provide newer MGMT API functionalities needed by the userspace (e.g: DBus advertisement). This MGMT API is only used by the BlueZ5s bluetoothd daemon which exposes various DBus abstraction API. Bluetoothd also had to be <a href="https://github.com/AsteroidOS/meta-asteroid/blob/master/recipes-connectivity/bluez5/bluez5/advertise-name.patch">patched</a> to expose more complete advertisement payloads.</p>
<p>Simple and common interactions with the bluetoothds DBus API like checking for the powered/connected status are implemented in <a href="https://github.com/AsteroidOS/qml-asteroid/blob/master/src/utils/src/bluetoothstatus.cpp">org.asteroid.utils.BluetoothStatus</a> of qml-asteroid. This class is for example used in asteroid-launcher, asteroid-music and <a href="https://github.com/AsteroidOS/asteroid-settings/blob/master/BluetoothPage.qml">asteroid-settings</a>.</p>
<p>More complex interactions with bluetoothd are implemented in <a href="https://github.com/AsteroidOS/asteroid-btsyncd">asteroid-btsyncd</a>, a user-space daemon running as a standard user (ceres) and acting as a DBus multiplexer between BlueZ and the apps. On the BlueZ side it registers BLE Services, Characteristics and Advertisement payloads. On the user side, it exposes specific API for each and every usage needed. For example, it communicates with asteroid-music with to the <a href="https://github.com/AsteroidOS/asteroid-music/blob/master/main.qml#L98">MPRIS API</a>, with asteroid-launcher based on the FreeDesktops notification API or with asteroid-weather thanks to data saved in the dconf “register”.</p>
<div class="page-header">
<h1 id="bt-pan">Bluetooth Personal Area Network</h1>
</div>
<p>In order to use BT PAN on AsteroidOS, you first need to modify the default image. Start by adding the following packages to the <i>IMAGE_INSTALL</i> variable of <i>asteroid/src/meta-asteroid/classes/asteroid-image.bbclass</i>:</p>
<pre><code>adb shell tail -F /var/log/messages</code></pre>
<p>You also need to modify the bluez5s main configuration in <i>asteroid/src/src/meta-asteroid/recipes-connectivity/bluez5/bluez5/main.conf</i> to</p>
<pre><code>[General]
#ControllerMode = le
DiscoverableTimeout = 180</code></pre>
<p>Finally, modify <i>build/conf/bblayers.conf</i> to add the following line to <i>BBLAYERS</i>:</p>
<pre><code>adb shell tail -F /var/log/messages</code></pre>
<p>After above changes, you can rebuild a new asteroid rootfs&nbsp;and push it to the watch with the <a href="{{rel 'wiki/building-asteroidos'}}">usual bitbake asteroid-image and adb push</a>.</p>
<p>In order to watch logs and check on progress, open up first a first terminal and run:</p>
<pre><code>adb shell tail -F /var/log/messages</code></pre>
<p>In a new terminal, download and push the bt-pan helper script: (<a href="http://blog.fraggod.net/2015/03/28/bluetooth-pan-network-setup-with-bluez-5x.html">more info</a>)</p>
<pre><code>adb shell mkdir /tmp/bluetooth
wget https://raw.githubusercontent.com/mk-fg/fgtk/master/bt-pan
chmod +x ./bt-pan
adb push bt-pan /tmp/bluetooth</code></pre>
<p>Now, fix up DNS and make sure localhost is a known thing by modifying (if needed) resolv.conf and hosts</p>
<pre><code>sh-4.3# cat /etc/resolv.conf
nameserver 8.8.8.8
nameserver ::1
sh-4.3# cat /etc/hosts
127.0.0.1 localhost</code></pre>
<p>Make sure you can&nbsp;see bluetooth in connman:</p>
<pre><code>sh-4.3# connmanctl technologies
...
/net/connman/technology/bluetooth
Name = Bluetooth
Type = bluetooth
Powered = True
Connected = False
Tethering = False</code></pre>
<p>You can now use bluetoothctl to establish a connection to your computer (<a href="http://trac.gateworks.com/wiki/wireless/bluetooth#PersonalAreaNetworkDeviceProfilePAN">more info</a>)</p>
<pre><code>sh-4.3# bluetoothctl
[NEW] Controller 20:70:02:A0:1F:AC dory [default]
[NEW] Device 3C:15:C2:C7:DA:95 my-rmbp2
agent on
default-agent
discoverable on
pairable on
scan on
pair 3C:15:C2:C7:DA:95
trust 3C:15:C2:C7:DA:95</code></pre>
<p>Launch bt-pan client which triggers bnep0 creation from connman (you will see it in /var/log/messages)</p>
<pre><code>sh-4.3# /tmp/bluetooth/bt-pan --debug client 3C:15:C2:C7:DA:95
DEBUG:root:Using local device (addr: 20:70:02:A0:1F:AC): /org/bluez/hci0
DEBUG:root:Using remote device (addr: 3C:15:C2:C7:DA:95): /org/bluez/hci0/dev_3C_15_C2_C7_DA_95
DEBUG:root:Connected to network (dev_remote: /org/bluez/hci0/dev_3C_15_C2_C7_DA_95, addr: 3C:15:C2:C7:DA:95) uuid 'nap' with iface: bnep0
DEBUG:root:Finished</code></pre>
<p>At this point your&nbsp;default route should still be rndis0 (USB OTG) instead of bnep0:</p>
<pre><code>sh-4.3# ip route
default via 192.168.2.1 dev rndis0
192.168.2.0/24 dev rndis0 proto kernel scope link src 192.168.2.15</code></pre>
<p>If the ip/bcast/netmask fields are missing on bnep0:</p>
<pre><code>sh-4.3# ifconfig bnep0
bnep0 Link encap:Ethernet HWaddr 20:70:02:A0:1F:AC
inet6 addr: fe80::2270:2ff:fea0:1fac%1202001524/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:39 errors:0 dropped:0 overruns:0 frame:0
TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:10504 (10.2 KiB) TX bytes:148 (148.0 B)</code></pre>
<p>Fix it with ifconfig and verify it worked:</p>
<pre><code>sh-4.3# ifconfig bnep0 192.168.2.2 netmask 255.255.255.0 broadcast 192.168.2.255
sh-4.3# ifconfig bnep0
bnep0 Link encap:Ethernet HWaddr 20:70:02:A0:1F:AC
inet addr:192.168.2.2 Bcast:192.168.2.255 Mask:255.255.255.0
inet6 addr: fe80::2270:2ff:fea0:1fac%1201331708/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:134 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:40369 (39.4 KiB) TX bytes:252 (252.0 B)</code></pre>
<p>Now that both routes are available, data are still going over rndis0 instead of bnep0:</p>
<pre><code>sh-4.3# ip route
default via 192.168.2.1 dev rndis0
192.168.2.0/24 dev rndis0 proto kernel scope link src 192.168.2.15
192.168.2.0/24 dev bnep0 proto kernel scope link src 192.168.2.2</code></pre>
<p>Delete default route and aad a new default one over bnep0</p>
<pre><code>sh-4.3# ip route delete default
sh-4.3# ip route change default via 192.168.2.1 dev bnep0</code></pre>
<p>Verify default is now over bnep0:</p>
<pre><code>sh-4.3# ip route
default via 192.168.2.1 dev bnep0
192.168.2.0/24 dev rndis0 proto kernel scope link src 192.168.2.15
192.168.2.0/24 dev bnep0 proto kernel scope link src 192.168.2.2</code></pre>
<p>You can now test your connection via ping and nslookup</p>
<pre><code>sh-4.3# ping -c 1 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=42 time=80.094 ms
sh-4.3# nslookup www.google.com
Server: 8.8.8.8
Address 1: 8.8.8.8 google-public-dns-a.google.com</code></pre>

View File

@ -0,0 +1,45 @@
---
title: Boot Process
layout: documentation
---
<p>This page describes the basis of the AsteroidOS boot process. Its focused on the LG G Watch but it should be similar on most other Android watches.</p>
<div class="page-header">
<h1 id="general-desc">General description</h1>
</div>
<p>The first component loaded by the LG G Watch is the bootloader, this component is proprietary and cant be modified, by default it is locked and only allows to boot Android, but we can access it by swiping the screen from top left to bottom right when booting up or with the “adb reboot bootloader” from a PC connected to a running Android or AsteroidOS instance.</p>
<p>This bootloader supports the “fastboot” protocol which is also the name of the command used on the computer to communicate with the bootloader. Fastboot allows to unlock the bootloader and then to flash partitions remotely and boot selected kernels. The bootloader can load three kernels, the one flashed on the BOOT partition, the one flashed on the RECOVERY partition and one sent via usb with the “fastboot boot boot.img” command. Kernels are stored in the boot.img format which is a concatenation of a kernel (sometimes with device tree) and an initramdisk. The boot.img format can be packed or unpacked with the mkbootimg and unmkbootimg tools. The AsteroidOSs kernel is a slightly modified Android Kernel with, for example, a backported Bluetooth subsystem. The AsteroidOSs ramdisk mostly load the init program of the rootfs which is systemd by default.</p>
<p>Systemd loads many components like</p>
<ul>
<li>Psplash which is a lightweight splashscreen software.</li>
<li>Androids init which loads the Android log daemon and servicemanager, both needed to run Asteroid-Launcher.</li>
<li>DBus which is needed for inter-process communication.</li>
<li>Adbd which is a daemon implementing the Android Debug Bridge protocol and which is used to get a remote shell and to push/pull files from a connected computer.</li>
<li>MCE which handles the power consumption, inputs and screen…</li>
<li>Patchram which loads a proprietary firmware to the broadcom bluetooth chip.</li>
<li>Bluetoothd which is the BlueZ5 daemon handling bluetooth.</li>
<li>Asteroid-Launcher which is the desktop and wayland compositior.</li>
</ul>
<img src="{{assets}}/img/boot-process.jpg" style="width:100%"/>
<div class="page-header">
<h1 id="troubleshooting">Troubleshooting the boot process</h1>
</div>
<p>The default initramfs has a section to enable adbd on the watch before booting into the rootfs. You can enable it by appending <code>enable_adb</code> to the boot kernels parameters, and when you boot the watch, you will be able to access <code>adb shell</code>.</p>
<p>For example, the bass watch <a href="https://github.com/AsteroidOS/meta-bass-hybris/blob/master/recipes-core%2Finitrdscripts%2Finitramfs-boot-android%2Finit.sh#L50">initscript</a> and <a href="https://github.com/AsteroidOS/meta-bass-hybris/blob/master/recipes-kernel%2Flinux%2Flinux-bass%2Fimg_info#L10">kernel configuration line</a>.</p>
<h3>Troubleshooting systemd</h3>
<p>If you see the AsteroidOS logo (even for a split second), the watch is able to boot into the rootfs and launch systemd.</p>
<p>Logs are normally stored in a tmpfs filesystem which is lost whenever the watch is rebooted. To disable the tmpfs mount, first mount the sdcard card containing the rootfs, and then the rootfs:</p>
<pre><code># . /machine.conf
# mkdir /sdcard /rfs
# mount /dev/$sdcard_partition /sdcard
# mount -o loop /sdcard/media/0/linux/rootfs.ext2 /rfs
</code></pre>
<p>You can then disable the <code>/var/volatile</code> tmpfs mount and enable systemd journal logging (/var/log is a symlink to /var/volatile/log):</p>
<pre><code># sed -i '/volatile/d' /rfs/etc/fstab
# mkdir /rfs/var/log/journal
</code></pre>
<p>Once you reboot into the rootfs partition (itll fail again), you can hop back into the <code>adb shell</code> and read the journal:</p>
<pre><code># chroot /rfs /bin/journalctl
</code></pre>

View File

@ -0,0 +1,36 @@
---
title: Building AsteroidOS
layout: documentation
---
<p>If you decide to compile AsteroidOS from source be aware that its a simple process but the first build might take you a lot of time. Report any problem to the <a href="https://github.com/AsteroidOS/asteroid/issues">issues tracker</a>:</p>
<video class="" id="" width="100%" height="100%" controls="" loop="" autoplay=""><source src="https://asteroidos.org/wp-content/uploads/2016/09/asteroid.mp4" type="video/mp4">
<source src="" type="video/mp4">
<source src="" type="video/mp4"></video>
<div class="page-header">
<h1 id="downloading">Downloading</h1>
</div>
<p>Start by cloning the main repository using the following command:</p>
<pre><code>git clone https://github.com/AsteroidOS/asteroid.git
cd asteroid/
</code></pre>
<p>This repository only contains a shell script that populates <em>src/</em> with OpenEmbedded and the appropriate layers. Then, it setups the environment for a bitbake build. This command will setup a build for <em>dory</em>, the LG G Watch, but you can also build an image for <em>bass</em>, the LG G Watch Urbane, <em>sparrow</em>, the Asus Zenwatch 2 and <em>tetra the Sony Smartwatch 3.</em></p>
<pre><code>. ./prepare-build.sh dory # Be careful that this script must be sourced and not only ran.
</code></pre>
<p>Now that the environment is correctly setup, you should be in the build directory. You can now bake your asteroid system. Make sure you have the following build dependencies:</p>
<pre><code>git build-essential diffstat gawk chrpath texinfo
</code></pre>
<div class="page-header">
<h1 id="building">Building</h1>
</div>
<p>And then you can run:</p>
<pre><code>bitbake asteroid-image
</code></pre>
<div class="page-header">
<h1 id="installing">Installing</h1>
</div>
<p>After a while, the generated image should be available in <em>build/tmp-glibc/deploy/images/dory/</em>.</p> Install AsteroidOS using your usual device's instructions.

View File

@ -0,0 +1,67 @@
---
title: Code of Conduct
layout: documentation
---
<p>We believe that our mission is best served in an environment that is friendly, safe, and accepting; free from intimidation or harassment.</p>
<p>Towards this end, certain behaviors and practices will not be tolerated.</p>
<div class="page-header">
<h1 id="tldr">tl;dr</h1>
</div>
<ul>
<li>Be respectful.</li>
<li>Were here to help:</li>
<li>Abusive behavior is never tolerated.</li>
<li>Violations of this code may result in swift and permanent expulsion from the AsteroidOS&nbsp;community.</li>
<li>“Too long, didnt read” is not a valid excuse for not knowing what is in this document.</li>
</ul>
<div class="page-header">
<h1 id="scope">Scope</h1>
</div>
<p>We expect all members of the AsteroidOS&nbsp;community&nbsp;to abide by this Code of Conduct at all times in all AsteroidOS community&nbsp;venues, online and in person, and in one-on-one communications pertaining to AsteroidOS&nbsp;affairs.</p>
<p>This policy covers the usage of AsteroidOS&nbsp;public infrastructure, including the AsteroidOS IRC channel, as well as other AsteroidOS&nbsp;websites, AsteroidOS&nbsp;related events, and any other services offered by or on behalf of the AsteroidOS&nbsp;community. It also applies to behavior in the context of the AsteroidOS&nbsp;project communities, including but not limited to public GitHub repositories, communication channels, social media, mailing lists, and public events.</p>
<p>This Code of Conduct is in addition to, and does not in any way nullify or invalidate, any other terms or conditions related to use of AsteroidOS&nbsp;services.</p>
<p>The definitions of various subjective terms such as “discriminatory”, “hateful”, or “confusing” will be decided at the sole discretion of the AsteroidOS&nbsp;abuse team.</p>
<div class="page-header">
<h1 id="fhfs">Friendly Harassment-Free Space</h1>
</div>
<p>We are committed to providing a friendly, safe and welcoming environment for all, regardless of gender identity, sexual orientation, disability, ethnicity, religion, age, physical appearance, body size, race, or similar personal characteristics.</p>
<p>We ask that you please respect that people have differences of opinion regarding technical choices, and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a single right answer. A difference of technology preferences is not a license to be rude.</p>
<p>Any spamming, trolling, flaming, baiting, or other attention-stealing behavior is not welcome, and will not be tolerated.</p>
<p>Harassing other users is never tolerated, whether via public or private media.</p>
<p>Avoid using offensive or harassing nicknames, or other identifiers that might detract from a friendly, safe, and welcoming environment for all.</p>
<p>Harassment includes, but is not limited to: harmful or prejudicial verbal or written comments related to gender identity, sexual orientation, disability, ethnicity, religion, age, physical appearance, body size, race, or similar personal characteristics; inappropriate use of nudity, sexual images, and/or sexually explicit language in public spaces; threats of physical or non- physical harm; deliberate intimidation, stalking or following; harassing photography or recording; sustained disruption of talks or other events; inappropriate physical contact; and unwelcome sexual attention.</p>
<div class="page-header">
<h1 id="reporting">Reporting Violations of this Code of Conduct</h1>
</div>
<p>If you believe someone is harassing you or has otherwise violated this Code of Conduct, please contact kido on&nbsp;irc.freenode.net&nbsp;to sen an abuse report. If this is the initial report of a problem, please include as much detail as possible. It is easiest for us to address issues when we have more context.</p>
<div class="page-header">
<h1 id="consequences">Consequences</h1>
</div>
<p>All content published to public AsteroidOS&nbsp;infrastructure is hosted at the sole discretion of&nbsp;AsteroidOS team.</p>
<p>Unacceptable behavior from any community&nbsp;member will not be tolerated.</p>
<p>Anyone asked to stop unacceptable behavior is expected to comply immediately.</p>
<p>If a community&nbsp;member engages in unacceptable behavior, the AsteroidOS team may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community&nbsp;without warning.</p>
<div class="page-header">
<h1 id="addressing">Addressing Grievances</h1>
</div>
<p>If you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should notify the AsteroidOS abuse team. We will do our best to ensure that your grievance is handled appropriately.</p>
<p>In general, we will choose the course of action that we judge as being most in the interest of fostering a safe and friendly community.</p>
<p>On IRC, let one of the ops know if you think that someone has transgressed against the Code of Conduct.</p>
<div class="page-header">
<h1 id="contactinfo">Contact Info</h1>
</div>
<p>Please contact kido on irc.freenode.net&nbsp;if you need to report a problem or address a grievance related to an abuse report.</p>
<p>You are also encouraged to contact us if you are curious about something that might be “on the line” between appropriate and inappropriate content. We are happy to provide guidance to help you be a successful part of this community.</p>
<div class="page-header">
<h1 id="changes">Changes</h1>
</div>
<p>This is a living document and may be updated from time to time.</p>
<div class="page-header">
<h1 id="credit">Credit and License</h1>
</div>
<p>This Code of Conduct is based on <a href="https://github.com/ipfs/community/blob/master/code-of-conduct.md">the IPFS&nbsp;Code of Conduct</a>.</p>
<p>This document may be reused under a <a href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike License</a>.</p>

View File

@ -0,0 +1,65 @@
---
title: Creating an Asteroid app
layout: documentation
---
<p>The app creation process of AsteroidOS needs a Software Development Kit generated by OpenEmbedded. You can either grab a prebuilt SDK <a href="https://www.dropbox.com/s/jio9gojfvflmd2x/oecore-x86_64-armv7ve-neon-toolchain-nodistro.0.sh?dl=1">here</a> (this is a self-contained script) and install it on your system or you can build it yourself as follow.</p>
<div class="page-header">
<h1 id="crosscompiletoolchain">Building the Cross Compilation Toolchain</h1>
</div>
<p>If youve already got an OpenEmbedded build directory via the Building AsteroidOS page, cd to that directory. Else, create one with:</p>
<pre><code>git clone https://github.com/AsteroidOS/asteroid
cd asteroid/
</code></pre>
<p>Then, build the cross compilation toolchain with:</p>
<pre><code>. ./prepare-build.sh dory
bitbake meta-toolchain-qt5
</code></pre>
<div class="page-header">
<h1 id="installsdk">Install the SDK</h1>
</div>
<p>If you downloaded a prebuilt SDK, run the downloaded script. If you followed the previous steps, this will have generated the same installation script in <em>tmp-glibc/deploy/sdk/</em>, you can run it as follow:</p>
<pre><code>./tmp-glibc/deploy/sdk/oecore-x86_64-armv7ve-neon-toolchain-nodistro.0.sh
</code></pre>
<p>This script will install the cross compiler and ARM libraries in <em>/usr/local/oecore-x86_64</em> by default, along with a script that needs to be sourced before every build. If you want to build a simple project via the terminal, this can be done like that:</p>
<pre><code>source /usr/local/oecore-x86_64/environment-setup-armv7ve-neon-oe-linux-gnueabi
qmake
make
</code></pre>
<div class="page-header">
<h1 id="configqtcreator">Configure QtCreator for cross compilation</h1>
</div>
<p>Before running QtCreator you must run the previously mentioned script:</p>
<pre><code>source /usr/local/oecore-x86_64/environment-setup-armv7ve-neon-oe-linux-gnueabi
qtcreator
</code></pre>
<p>This can be done automatically by prepending “source /usr/local/oecore-x86_64/environment-setup-armv7ve-neon-oe-linux-gnueabi” before #!/bin/sh in <em>/usr/bin/qtcreator.sh</em></p>
<p>Now that you are in QtCreator go to <em>Tools-&gt;Options-&gt;Build &amp; Run</em> and</p>
<ul>
<li>In the Compilers tab add the following g++: <em>/usr/local/oecore-x86_64/sysroots/x86_64-oesdk-linux/usr/bin/arm-oe-linux-gnueabi/arm-oe-linux-gnueabi-g++</em></li>
<li>In the Qt Versions tab add the following qmake: <em>/usr/local/oecore-x86_64/sysroots/x86_64-oesdk-linux/usr/bin/qt5/qmake</em></li>
<li>In the Kits tab add a kit with the previously chosen Qt5 version and compiler, set the sysroot to <em>/usr/local/oecore-x86_64/sysroots/armv7a-vfp-neon-oe-linux-gnueabi/</em> and let the other variables empty.</li>
</ul>
<p><strong>TODO:</strong> try to setup <em>Tools-&gt;Options-&gt;Devices</em> for automatic app installation over SSH.</p>
<div class="page-header">
<h1 id="firstapp">First app</h1>
</div>
<p>Asteroid-Stopwatch can act as a cool QML demo app available to make the first step into AsteroidOS development easier. You can clone it, build it, install it and then modify it to follow your needs:</p>
<pre><code>git clone https://github.com/AsteroidOS/asteroid-stopwatch
cd asteroid-stopwatch/
source /usr/local/oecore-x86_64/environment-setup-armv7ve-neon-oe-linux-gnueabi
qmake
make
adb push asteroid-stopwatch /usr/bin/
adb push asteroid-stopwatch.desktop /usr/share/applications/
</code></pre>
<p>If it wasnt already installed, a new icon should have already appeared on asteroid-launcher, try to run it and you should get a QtQuick Controls Calendar component.</p>
<p>You can start by modifying occurrences of “asteroid-calendar” to your apps name. Then you can change the *.desktop file which describes the icon on the apps launcher. Then modify main.qml to describe your UI. To get started with QML development you can read the <a href="http://doc.qt.io/qt-5/qml-tutorial.html">official tutorial</a>.</p>
<div class="page-header">
<h1 id="tipsandtricks">Tips and tricks</h1>
</div>
<p>If you want to start your app from the command line, open a shell with adb shell, connect to the standard user and use invoker:</p>
<pre><code>su ceres
invoker --type=qtcomponents-qt5 /usr/bin/asteroid-stopwatch</code></pre>
<p>If you want to disable screen locking for easier development you can enable the demo mode of mce with:</p>
<pre><code>mcetool -D on</code></pre>

View File

@ -0,0 +1,36 @@
---
title: Documentation
slug: documentation
layout: documentation
---
<div class="page-header">
<h1 id="users">Users</h1>
</div>
<ul>
<li><a href="{{rel 'wiki/translating-asteroidos'}}">Translating AsteroidOS</a></li>
<li><a href="{{rel 'wiki/porting-status'}}">Porting Status</a></li>
<li><a href="{{rel 'wiki/code-of-conduct'}}">Code of Conduct</a></li>
<li><a href="{{rel 'wiki/bluetooth'}}">Bluetooth</a></li>
<li><a href="{{rel 'wiki/ssh'}}">SSH</a></li>
<li><a href="{{rel 'wiki/emulator'}}">Emulator</a></li>
<li><a href="{{rel 'wiki/licenses'}}">Licenses</a></li>
</ul>
<div class="page-header">
<h1 id="developers'}}">Developers</h1>
</div>
<ul>
<li><a href="{{rel 'wiki/creating-an-asteroid-app'}}">Creating an Asteroid app</a></li>
<li><a href="{{rel 'wiki/watchfaces-creation'}}">Watchfaces creation</a></li>
<li><a href="{{rel 'wiki/building-asteroidos'}}">Building AsteroidOS</a></li>
<li><a href="{{rel 'wiki/porting-guide'}}">Porting Guide</a></li>
<li><a href="{{rel 'wiki/boot-process'}}">Boot Process</a></li>
<li><a href="{{rel 'wiki/openembedded'}}">OpenEmbedded</a></li>
<li><a href="{{rel 'wiki/graphic-stack'}}">Graphic Stack</a></li>
</ul>
<div class="page-header">
<h1 id="designers">Designers</h1>
</div>
Work in progress...

15
pages/wiki/emulator.hbs Normal file
View File

@ -0,0 +1,15 @@
---
title: Emulator
layout: documentation
---
<div class="callout callout-warning">
<h4>Support</h4>
<p>The emulator support is a work-in-progress and does not provide any satisfactory experience yet. The graphic stack is known to be buggy and contributions are highly welcome.</p>
</div>
<p>OpenEmbedded can generate images for various emulators. Hence, it is very easy to compile AsteroidOS for the “qemux86” target with:</p>
<pre><code>. ./prepare-build.sh qemux86
bitbake asteroid-image
</code></pre>
<p>The preferred emulator is actually VirtualBox. You can open VBox, create a new virtual machine based on Linux 2.6 (32-bit) with 1024 MB of RAM and use the existing virtual hard disk file generated by OpenEmbedded in build/tmp-glibc/deploy/images/qemux86/asteroid-image-qemux86.vmdk</p>
<p>The usual graphic stack asteroid-launcher works on is based on the hwcomposer QPA which uses libhybriss EGL and Androids code. On VirtualBox, asteroid-launcher runs on the eglfs QPA which uses Mesas software rendering on top of the KMS interface offered by the virtualbox guest drivers.</p>

View File

@ -0,0 +1,12 @@
---
title: Graphic Stack
layout: documentation
---
<p>The AsteroidOSs graphic stack is pretty similar to the one present in SailfishOS or WebOS-Ports. This page is a quick summary of whats involved in showing an app.</p>
<p>User apps, like asteroid-settings, are small software developed using QML and qml-asteroid. Behind the hood, Qt5 uses the QtWayland “QPA” module API for client windows to show up on screen. A communication is established via the “wayland-egl” protocol with the Wayland compositor. This means that user apps dont necessarily have to be developed with Qt as long as the library supports the Wayland protocol.</p>
<p>The Wayland compositor which by default is asteroid-launcher (and could be replaced by GlacierUI for example) is based on Lipstick from the Nemomobile project which allows us to quickly design an interface with QML and qml-asteroid. Behind the hood, two different modules are used: once again QtWayland but this time the compositor API is used which allows us to handle the wayland-egl communication with the client. The QPA module used by asteroid-launcher is qt5-qpa-hwcomposer which uses the libhardware.so glibc binding provided by libhybris in /usr/lib.</p>
<p>This libhardware.so is only a front-end to the androids libhardware.so provided in /system/lib/ and imported from an Android Wear installation. The androids libhardware.so can not be directly used by qt5-qpa-hwcomposer because there is a libc incompatibility, android libraries are linked against bionic instead of glibc so a compatibility layer is needed: thats the job of libhybris. Finally this bionic libhardware.so load some proprietary binary blobs which are able to communicate with the GPU and to show something on-screen.</p>
<p>Libhybris is used to re-use Android drivers from AsteroidOS, SailfishOS, NemoMobile, WebOS-Ports or Ubuntu Touch. Its clearly a hack and not a perfect solution as it relies on some proprietary binary blobs but its often the only way to get reliable hardware acceleration on Android devices and it works really well. Its worth noticing that Ubuntu Touch uses Mir instead of Wayland which is used by all the other projects, including AsteroidOS.</p>
<img src="{{assets}}/img/graphic-stack.jpg" style="width:100%"/>
</div>

8
pages/wiki/licenses.hbs Normal file
View File

@ -0,0 +1,8 @@
---
title: Licenses
layout: documentation
---
<p>An AsteroidOS image is made of plenty of components and its hard to describe the full details of the licenses that are in used in the system. When building the system from sources with OpenEmbedded, one can find the exhaustive set of licenses in the build/tmp-glibc/deploy/licenses directory.</p>
<p>In order to give a very general overview of the licenses that are in used. All the apps are distributed under GPLv3. QML-Asteroid is distributed under LGPL-2.1. asteroid-launcher is distributed under BSD. The wallpapers are covered by the CC BY 2.0 and the logo by CC BY SA 2.0.</p>
<p>Its also worth noticing that on most watches, a few amount of proprietary blobs and firmware need to be used for GPU acceleration and Bluetooth. They are isolated components which can be found in the /vendor/ directory and they are used via <em>libhybris</em>.</p>

View File

@ -0,0 +1,12 @@
---
title: OpenEmbedded
layout: documentation
---
<p><a href="http://www.openembedded.org/wiki/Main_Page">OpenEmbedded</a> is the build system used by AsteroidOS, it allows to easily maintain embedded linux distributions. OE is also used by project such as WebOS-Ports, SHR or Ångström. OpenEmbedded is supported by the <a href="https://www.yoctoproject.org/">Yocto project</a> from the Linux Foundation and provides a rock-solid basis for AsteroidOS.</p>
<p>OpenEmbedded uses the bitbake tool which is developed in python to generate images (like asteroid-image) from packages (like asteroid-launcher-dev) built from recipes (ex: asteroid-launcher_git.bb) provided in layers (ex: meta-asteroid).</p>
<p>Layers are git repositories containing a bunch of related recipes, example of layers include board support packages like <a href="https://github.com/AsteroidOS/meta-dory-hybris">meta-dory-hybris</a> or meta-rockchip which describe a way to support a new machine, but also UI layers like meta-xfce or meta-gnome which describe the building process of graphic components.</p>
<p>A recipe describe how to fetch, patch, configure, compile, install, package (in .rpm, .deb or .ipk) and test a piece of software. Bitbake handles all those operations and dependencies between them and between recipes. In the end it can generate images or SDK for multiple targets.</p>
<p>Contributing to the AsteroidOSs OE architecture mostly consists in maintaining the <a href="https://github.com/AsteroidOS/meta-asteroid">meta-asteroid</a> and meta-*-hybris repositories which contain the recipes related to Asteroid and the watches BSPs.</p>
<p>In depth info can be found in <a href="http://www.yoctoproject.org/docs/2.0/mega-manual/mega-manual.html">the Mega-Manual</a>.</p>
<img src="{{assets}}/img/openembedded.png" style="width:100%"/>

View File

@ -0,0 +1,101 @@
---
title: Porting Guide
layout: documentation
---
<p>An AsteroidOS hardware adaptation layer consists of :</p>
<ul>
<li>OpenEmbedded recipes describing the compilation of the various HW adaptation components.</li>
<li>An appropriate vendor kernel able to boot the watchs SoC and including the required drivers.</li>
<li>A set of Android Wears proprietary binary blobs used through libhybris in order to access some of the Androids HALs.</li>
<li>Some middleware configuration files to use your HW adaptation.</li>
</ul>
<div class="markdown-body">
<div class="page-header">
<h1 id="oebsplayer">Creating an OpenEmbedded BSP layer</h1>
</div>
<p>In order to add the support of&nbsp;your watch to AsteroidOS, youll need to write an OpenEmbedded layer. Start&nbsp;by making sure you are familiar with the core concepts behind OpenEmbedded by reading the two related documentation pages.</p>
<ul>
<li><a href="{{rel 'wiki/openembedded'}}">OpenEmbedded</a></li>
<li><a href="{{rel 'wiki/building-asteroidos'}}">Building AsteroidOS</a></li>
</ul>
<p>The easiest way to create an OpenEmbedded layer for hardware adaptation is to modify one that already exists. If you want to base your port on an Android 5.5.1 base, you should base your layer&nbsp;on <a href="https://github.com/AsteroidOS/meta-dory-hybris">meta-dory-hybris</a>. If you want to base your port on an Android 6 base, you should base your layer on <a href="https://github.com/AsteroidOS/meta-swift-hybris">meta-swift-hybris</a>.</p>
<p>Start by cloning the most appropriate layer into an src/meta-XXX-hybris/ directory in your AsteroidOS build tree. From now on, XXX will be a reference to&nbsp;your watchs codename. Once you have that layer setup, <a href="https://github.com/AsteroidOS/meta-swift-hybris/commit/b665878f80936f21cec1757cdc4d10fa95af1841">roughly&nbsp;replace</a> all references to the previous codename&nbsp;with XXX in the layer and add the path to your layer in your build/conf/bblayers.conf file.</p>
<p>The&nbsp;layer should describe&nbsp;a machine configuration to bitbake in&nbsp;<a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/conf/machine/dory.conf">conf/machine/XXX.conf</a>. The definition of a machine allows to <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/conf/machine/dory.conf#L25">install hardware-specific packages</a>&nbsp;in a generated rootfs and&nbsp;to give very general information about the hardware adaptation like the <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/conf/machine/dory.conf#L18">kernel</a> or <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/conf/machine/dory.conf#L10">egl providers</a>&nbsp;that should be used. Having a new machine also allows to modify other layers&nbsp;recipes based on the builds target. For example a .bbappend file using the _XXX suffix appropriately can&nbsp;<a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-android/brcm-patchram-plus/brcm-patchram-plus_git.bbappend#L1">modify built files</a>, <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-qt/qt5/qt5-qpa-hwcomposer-plugin_git.bbappend#L1">apply&nbsp;patches</a>,&nbsp;<a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-nemomobile/sensorfw/sensorfw_git.bbappend#L1">add build dependencies</a>, <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-multimedia/pulseaudio/pulseaudio_%25.bbappend#L1">add runtime dependencies</a> or&nbsp;<a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-android/brcm-patchram-plus/brcm-patchram-plus_git.bbappend#L3">change compilation flags</a>. bbappends are very powerful but&nbsp;should be used scarcely to&nbsp;avoid conflicts with other layers.</p>
<p>An hardware adaptation layer does not only modify other recipes with bbappend, it also provides a couple of new recipes that are hardware-specific. You can usually find two very important recipes: the <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-kernel/linux/linux-dory_lp-mr1.bb">kernel recipe</a> and the <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-android/android/android_dory-lp.bb">Androids blobs recipe</a>. Those recipes will need extra-care and are the topic&nbsp;of the two following paragraphs.</p>
<div class="page-header">
<h1 id="kernelrecipe">Creating an appropriate Linux kernel recipe</h1>
</div>
<p>The kernel recipe describes how to fetch/patch/configure/compile/install/package the vendor kernel. All of those steps may need to be modified from your base recipe.</p>
<p>First of all, you need to find the <a href="https://android.googlesource.com/kernel/msm/+refs">git repository</a>, branch and commit containing the source code of the watch you want to work on.&nbsp;Adapt <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-kernel/linux/linux-dory_lp-mr1.bb#L11">SRC_URI</a> and <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-kernel/linux/linux-dory_lp-mr1.bb#L16">SRCREV</a> accordingly.</p>
<p>Then, try to find your watchs <a href="https://android.googlesource.com/kernel/msm/+/android-msm-dory-3.10-marshmallow-mr1-wear-release/arch/arm/configs/dory_defconfig">defconfig</a> in the kernels&nbsp;arch/arm/configs/ directory.&nbsp;Copy this base defconfig onto <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-kernel/linux/linux-dory/defconfig">meta-XXX-hybris/recipes-kernel/linux/linux-XXX/defconfig</a>&nbsp;and use the <a href="https://github.com/AsteroidOS/meta-asteroid/blob/master/scripts/check-config">check-config script of meta-asteroid</a> with the -w flag to fix a couple of configuration values.</p>
<p>If you need to patch your kernels tree, add the path to <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-kernel/linux/linux-dory/0001-Backport-mainline-4.1-Bluetooth-subsystem.patch">the patches</a> to <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-kernel/linux/linux-dory_lp-mr1.bb#L14">SRC_URI</a>.</p>
<p>The output of a kernel compilation is a single zImage. In order to be started by your watchs bootloader, this image needs to be packed with an initramfs into a single boot.img file. (for more information cf.&nbsp;<a href="{{rel 'wiki/boot-process'}}">Boot Process</a>) Three different tools can be used to pack the boot.img file: abootimg, mkboot and mkbootimg. Since some watches only work with one of those tools (without any apparent reason), you can <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-kernel/linux/linux-dory_lp-mr1.bb#L36">inherit</a> one of the <a href="https://github.com/AsteroidOS/meta-asteroid/tree/master/classes">provided bbclass</a>&nbsp;and adapt the config accordingly.</p>
<p><strong>Extra-Note</strong>: The Yocto project provides a <a href="http://www.yoctoproject.org/docs/1.6.1/kernel-dev/kernel-dev.html">handy manual</a> on how to work with the Linux kernel with OpenEmbedded.</p>
<div class="page-header">
<h1 id="systemdir">Building the Android's /system/ directory</h1>
</div>
<p>In order to get a full AsteroidOS environment, you will need to install the Android HALs required&nbsp;by the usage of libhybris in various AsteroidOS components.</p>
<p>Actually, only a very limited set of libs from Android is needed. Some of those libs (like bionic) need to be patched and must be recompiled from source. Hence, youll need to start by cloning a <a href="https://github.com/AsteroidOS/android_manifest/blob/master/default.xml">modified and stripped down Android source tree</a> to compile the needed drivers. You can find detailed info on the build process&nbsp;that has been used for dory in <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/README-system-dir">README-system-dir</a>. Youll most likely need to adapt those instructions to your own need, thus you are strongly encouraged to document your steps in your own README-system-dir for reproducibility and in order to help future porters.</p>
<p>Once youll get your first /system/ directory, you can modify meta-XXX-hybris/recipes-android/android/android_XXX-*.bb to use your&nbsp;prebuilt tarball. The next steps in hardware adaptation will most likely require you to iterate various modifications to&nbsp;this system directory so dont get too emotionally attached to this tarball yet.</p>
<div class="page-header">
<h1 id="boot">Boot</h1>
</div>
<p>If you boot your generated boot.img from your watchs bootloader, fastboot should load your kernel which will load the initramfss init script which will eventually load you rootfss init system.&nbsp;(for more information cf.&nbsp;<a href="{{rel 'wiki/boot-process'}}">Boot Process</a>) You can usually know if those steps have successfully been completed when the watch stays up and running and shows the AsteroidOS boot logo for a while (shown by psplash which is ran by systemd on the rootfs). In case your boot stops earlier, you have a boot problem to debug.</p>
<p>You need to proceed by elimination to find what causes your boot to fail. First of all, disable the ramfs -&gt; rootfs switch&nbsp;by adding a bash infinite loop early&nbsp;<a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-core/initrdscripts/initramfs-boot-android/init.sh#L54">in your ramdisks init script</a>. If you notice your watch does not crash anymore, you may have an issue with your rootfs. The Troubleshooting section of the <a href="{{rel 'wiki/boot-process'}}">Boot Process page</a> should help you retrieve your systemd logs and isolate the cause of your boot problem.</p>
<p>If your watch keeps on crashing, you may have a problem with your kernel. Start by making&nbsp;sure you tried the different boot.img packing tools. If the problem persists, youll want to retrieve your kernels message logs. This can usually be retrieved from a /proc/last_kmsg virtual file in Android Wear when enabling the&nbsp;CONFIG_ANDROID_RAM_CONSOLE kernel option. Analyzing the logs should also help narrowing down the issue to a faulty driver or config.</p>
<div class="page-header">
<h1 id="usb">USB</h1>
</div>
<p>If you have your AsteroidOS system running, you will want to get a shell access to it with adb over USB. Try to run adb devices&nbsp;from your computer when your watch has been booted for a few seconds and check if you see your device. If you dont, you may have a problem with your USB setup.</p>
<p>First of all, try to replicate the config of your Android Wears init scripts in <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-core/initrdscripts/initramfs-boot-android/init.sh#L26">your ramdisks init script</a>. Once youre sure the USB config is the same, you should try to run <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-core/initrdscripts/initramfs-boot-android/init.sh#L52">adbd from your ramdisk</a> instead of the rootfs, if it solves the problem you may have an issue with usb_moded not starting adbd properly.</p>
<p>If the problem is the same, you may have a problem with your kernels config or drivers. First of all, make sure CONFIG_USB_G_ANDROID is still enabled in the generated build/tmp-glibc/work/XXX-oe-linux-gnueabi/linux-XXX/*/git/.config as it is quite common to find bitbake removing this option. If the option is still there, your kernel may need special patches.</p>
<div class="page-header">
<h1 id="display">Display</h1>
</div>
<p>As soon as youll get access to a shell on AsteroidOS, you may&nbsp;find yourself without asteroid-launcher running. Checking the system logs with “journalctl no-pager” or “systemctl no-pager” usually shows a segfault from the lipstick process. This is to be expected on your first run and there is nothing to worry about. In order to reproduce the bug, you can start lipstick manually with:</p>
<p>XDG_RUNTIME_DIR=/run/user/1000 EGL_PLATFORM=hwcomposer lipstick platform hwcomposer</p>
<p>asteroid-launcher uses lipstick which uses the hwcomposer QPA which uses libhybris which uses the Android graphic HAL to display things on screen. You may need to adapt&nbsp;the Android graphic HAL to answer the needs of hybris. (usually a matter of starting the right android boot services, having the right files placed in the right directories, having the right system.prop options etc…)</p>
<p>For more information on the Graphic Stack you may want to refer to <a href="{{rel 'wiki/graphic-stack'}}">the associated documentation page</a>. For more information on how to debug an&nbsp;issue, check the Troubleshooting paragraph of this page.</p>
<div class="page-header">
<h1 id="touch">Touch</h1>
</div>
<p>Once youll get asteroid-launcher displaying things on screen, you may have no touch feedback from the UI. If that is the case, youll need to modify the lipsticks start command to use a different evdevtouch file. For example, tetra uses <a href="https://github.com/AsteroidOS/meta-tetra-hybris/tree/master/recipes-asteroid/asteroid-launcher">this bbappend</a> to use /dev/input/event1 instead of the default event0.</p>
<div class="page-header">
<h1 id="audio">Audio</h1>
</div>
<p>Smartwatches usually dont carry&nbsp;speakers but they often have microphones. AsteroidOS does not use those microphones yet but its usually easy to support and should be supported&nbsp;for the future of the project. AsteroidOS uses <a href="https://github.com/AsteroidOS/meta-asteroid/tree/master/recipes-multimedia/pulseaudio">pulseaudio</a> for its audio stack. pulseaudio takes benefits from the pulseaudio-droid-card module to use the Androids Audio HAL.&nbsp;In order to test the microphone, you can install and run parec from the build/tmp-glibc/work/armv7ve-neon-oe-linux-gnueabi/pulseaudio/9.0-r0/packages-split/pulseaudio-misc/ package. If you lack an audio interface, make sure you <a href="https://github.com/AsteroidOS/meta-dory-hybris/commit/0276357cdb266ce28eb37ca958c70f5273d588cd">loaded the audio firmware</a>.</p>
<p>In case a problem persist, enabling <a href="https://wiki.ubuntu.com/PulseAudio/Log">extra debug information</a> from pulseaudio can give you detailed info on the cause of the issue.</p>
<div class="page-header">
<h1 id="bluetooth">Bluetooth</h1>
</div>
<p>Smartwatches make&nbsp;extensive use of Bluetooth for connectivity. The AsteroidOS project comes with a set of Bluetooth Low Energy profiles implemented in the asteroid-btsyncd server daemon and AsteroidOSSync client.&nbsp;(for more information cf.&nbsp;<a href="{{rel 'wiki/bluetooth/'}}">Bluetooth</a>) Bluetooth required a few extra steps to work on your port.</p>
<p>asteroid-btsyncd uses BlueZs DBus API to create a BLE server. Those APIs require a recent Bluetooth subsystem in your kernel. Unfortunately, Android Wear watches usually come with outdated kernels and a newer BT subsystem needs to be backported. The patch used in dory can be found <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-kernel/linux/linux-dory/0001-Backport-mainline-4.1-Bluetooth-subsystem.patch">here</a>&nbsp;and should be adaptable to your kernels tree with very few&nbsp;conflicts.</p>
<p>Most Android Wear smartwatches carry a Broadcom BT chip that requires&nbsp;a proprietary firmware to be applied with a tool named brcm-patchram-plus. This tool is called from a systemd service named patchram.service, your HW adaptation layer should include a <a href="https://github.com/AsteroidOS/meta-dory-hybris/tree/master/recipes-android/brcm-patchram-plus">modified patchram.service</a> file that uses the provided vendors firmware and tty line. Information about the config you should use can be found in the <a href="https://android.googlesource.com/platform/hardware/broadcom/libbt/+/master/include/">Androids libbt-broadcom repository</a>.</p>
<p>With a backported BT subsystem and patched BT firmware, you should already be able to get Bluetooth connectivity on your port but with very limited battery life. Broadcoms bluetooths low power mode&nbsp;is handled by a kernel module named Bluesleep (or more recently Nitrous) that expects custom information to be written in /proc/lpm/. With BlueZ, this proc interface is never used hence the kernel driver must be adapted to receive HCI events from the BT subsystem with <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-kernel/linux/linux-dory/0002-bluesleep-Use-kernel-s-HCI-events-instead-of-proc-bl.patch">a patch</a>. Finally, brcm-patchram-plus must also be <a href="https://github.com/AsteroidOS/meta-dory-hybris/blob/master/recipes-android/brcm-patchram-plus/brcm-patchram-plus_git.bbappend#L3">compiled with a special flag</a> defining the target device and the <a href="https://github.com/AsteroidOS/brcm-patchram-plus/commit/94fb127e614b19a9a95561b8c1a0716e2e1e6293">low power mode options to use</a>.</p>
<div class="page-header">
<h1 id="sensors">Sensors</h1>
</div>
<p>In AsteroidOS, sensors can be used by developers through the QtSensors API that uses the sensorfw backend. Sensorfwd is a sensor daemon that can use libhybris to interface with the Androids Sensors HAL.</p>
<p>In order to use sensors on Asteroid, you need to make sure libhybris recognizes your sensors by running the test_sensors command.&nbsp;For more information on how to debug an&nbsp;issue, check the Troubleshooting paragraph of this page.</p>
<div class="page-header">
<h1 id="haptics">Haptics</h1>
</div>
<p>In AsteroidOS, vibrations&nbsp;can be used by developers through the QtFeedback and ngfd&nbsp;APIs that usually rely on a libhybris backend which uses the Androids vibration HAL.</p>
<p>In order to use vibration&nbsp;on Asteroid with the Android HAL, you need to make sure libhybris recognizes your vibrator by running the test_vibrator command.&nbsp;For more information on how to debug an&nbsp;issue, check the Troubleshooting paragraph of this page.</p>
<p>A much cleaner way to vibrate in AsteroidOS would be to use an ffmemless kernel driver and the sensorfwds ffmemless backend but most watches dont come with such a kernel driver and it would need to be developed.</p>
<div class="page-header">
<h1 id="wlan">WLAN</h1>
</div>
<p>WLAN is not used by AsteroidOSs user-interface yet but it should be supported for the future of the project. Some information about setting up a Wi-Fi interface can be found in the last paragraph of the <a href="{{rel 'wiki/ssh'}}">SSH documentation page</a>.</p>
<div class="page-header">
<h1 id="troubleshooting">Troubleshooting</h1>
</div>
<p>While porting AsteroidOS to your watch, you will most likely meet all kind of problems. In order to debug whats going wrong with your setup you should install debug tools such as strace and gdb and the required debug sybols to your generated rootfs. For example, you can temporarily append the “strace gdb asteroid-launcher-dbg” packages to the <a href="https://github.com/AsteroidOS/meta-asteroid/blob/master/classes/asteroid-image.bbclass#L9">asteroid-image class</a>.</p>
<p>Once you come up with more information about your bug with strace and gdb, your first reflex should be to <a href="https://log.asteroidos.org/search">search&nbsp;the asteroids IRC logs</a> for similar issues. The SailfishOS porters community is another great place to search for information, you may also want to try your chance at <a href="https://www.google.com/search?q=site%3Amerproject.org+irc+QCOM_BSP">searching the merprojects IRC logs</a>.</p>
<p>If you still couldnt find a solution to your problem in the logs, dont hesitate to ask questions on&nbsp;the #asteroid IRC channel. There should be&nbsp;several porters able to help you.</p>
<div class="page-header">
<h1 id="upstreamyourwork">Upstream your work</h1>
</div>
<p>Thats it, you can finally use AsteroidOS on your watch! Sharing your work with the rest community should be the final step to ensure your layer will be maintained through&nbsp;time.&nbsp;Start by requesting on IRC the creation of a new AsteroidOS/meta-XXX-hybris repository and send a pull request to this repository. Your work will be carefully reviewed and commented before being integrated upstream. Youll also need to send a <a href="https://github.com/AsteroidOS/asteroid/pull/8">pull-request to the AsteroidOS/asteroid repository</a>&nbsp;to integrate your machine to prepare-build.sh and join the very privileged circle of AsteroidOS porters! Make sure your work is correctly detailed on the <a href="{{rel 'wiki/porting-status'}}">Porting Status</a> page and share a photo of your watch for public twitter announcement.</p>
</div>

View File

@ -0,0 +1,200 @@
---
title: Porting Status
layout: documentation
---
<p>This page aims at gathering info about the currently supported platforms and porting efforts.</p>
<div class="page-header">
<h1 id="androidwear">Android Wear</h1>
</div>
<p>The Android Wear smartwatches are the most widespread and easy to support. The source code of their kernels is usually easily available and the drivers can be supported with libhybris. Those watches are the current priority of AsteroidOS.</p>
<p><strong>Supported watches:</strong></p>
<table>
<thead>
<tr>
<th>Brand</th>
<th>Model</th>
<th>Codename</th>
<th>Maintainer</th>
<th>Display</th>
<th>Touch</th>
<th>Audio</th>
<th>Bluetooth</th>
<th>Sensors</th>
<th>Haptics</th>
<th>USB</th>
<th>WLAN</th>
<th>Note</th>
</tr>
</thead>
<tbody>
<tr>
<td>Asus</td>
<td>ZenWatch</td>
<td>anthias</td>
<td>locusf</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td></td>
<td>Sluggish UI</td>
</tr>
<tr>
<td>Asus</td>
<td>ZenWatch 2</td>
<td>sparrow/wren</td>
<td>Lrs121/dlandau</td>
<td>X</td>
<td>X</td>
<td></td>
<td>X</td>
<td></td>
<td>X</td>
<td>X</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Asus</td>
<td>ZenWatch 3</td>
<td>swift</td>
<td>anYc</td>
<td>X</td>
<td>X</td>
<td></td>
<td></td>
<td></td>
<td>X</td>
<td>X</td>
<td>X</td>
<td></td>
</tr>
<tr>
<td>LG</td>
<td>G Watch</td>
<td>dory</td>
<td>kido</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td></td>
<td>Best support</td>
</tr>
<tr>
<td>LG</td>
<td>G Watch R</td>
<td>lenok</td>
<td>atx</td>
<td>X</td>
<td>X</td>
<td></td>
<td>X</td>
<td></td>
<td>X</td>
<td>X</td>
<td></td>
<td></td>
</tr>
<tr>
<td>LG</td>
<td>G Watch Urbane</td>
<td>bass</td>
<td>TheAppleMan</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td></td>
<td>X</td>
<td>X</td>
<td>X</td>
<td></td>
</tr>
<tr>
<td>Samsung</td>
<td>Gear Live</td>
<td>sprat</td>
<td>kido/nobody</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td></td>
<td>X</td>
<td>X</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Sony</td>
<td>SmartWatch 3</td>
<td>tetra</td>
<td>kido</td>
<td>X</td>
<td>X</td>
<td></td>
<td></td>
<td></td>
<td>X</td>
<td>X</td>
<td>X</td>
<td></td>
</tr>
<tr>
<td>Huawei</td>
<td>Watch</td>
<td>sturgeon</td>
<td>bencord0</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>Just boots</td>
</tr>
</tbody>
</table>
<p><strong>Possible ports not supported yet:</strong></p>
<ul>
<li>Casio Smart Outdoor Watch</li>
<li>Huawei Watch 2</li>
<li>LG Watch Urbane 2nd Edition</li>
<li>Moto 360 (1st generation)</li>
<li>Nixon Mission</li>
<li>New Balance RunIQ Watch</li>
<li>Samsung Gear S</li>
<li>Tag Heuer Connected</li>
</ul>
<p><strong>Impossible ports because of lack of pinouts:</strong></p>
<ul>
<li>Fossil Q Founder</li>
<li>Fossil Q Marshal</li>
<li>Fossil Q Wander</li>
<li>LG Watch Sport</li>
<li>LG Watch Style</li>
<li>Michael Kors Access</li>
<li>Moto 360 (2nd generation)</li>
<li>Moto 360 Sport</li>
<li>Movado Connect</li>
<li>Polar M600</li>
</ul>
<div class="page-header">
<h1 id="tizensw">Tizen Smartwatches</h1>
</div>
<p>The Samsung Gear S2, S2 Classic and S3 might be supported by AsteroidOS in the future but they will require more work than the other watches. Someone already got interested in the S2 port but gave up because he couldnt find the kernels defconfig.</p>
<div class="page-header">
<h1 id="othersw">Other Smartwatches</h1>
</div>
<p>There are many Android (non-Wear) smartwatches available for a lower price. (e.g: the Omate *, Sony SW, Intex iRist, zWatch etc…) It might be more difficult to get access to the kernels or android tree of those devices but libhybris could also make running AsteroidOS on top of them possible.</p>
<p>Other low-end smartwatches using cheap Mediatek SoCs arent able to run a Linux kernel and cant be supported by AsteroidOS</p>

51
pages/wiki/ssh.hbs Normal file
View File

@ -0,0 +1,51 @@
---
title: SSH
layout: documentation
---
<p>By default, you can get a remote shell on you smartwatch with the Android Debug Bridge tool and the “adb shell” command. However this shell suffers from a many limitations and you might prefer to get a standard SSH connection. To do so you need to setup a TCP connection with your watch. The procedure is different if you want to do it over USB or Wi-Fi (if your watch supports Wi-Fi)</p>
<div class="page-header">
<h1 id="sshoverusb">SSH over USB</h1>
</div>
<p>To use SSH over USBs gadget mode you need to tell Connman to setup a manual IP for your watch. First of all, you need to get your usbs UID thanks to the “get-services” tool which is available in the “connman-tests” package under /usr/lib/connman/test/. The first line of this commands output should contain something like “gadget_<em>UID</em>_usb”, note this UID and replace it when needed in the commands below.</p>
<p>Create a /var/lib/connman/gadget_<em>UID</em>_usb/ directory and in that directory create a “settings” file containing:</p>
<pre><code>[gadget_*UID*_usb]
Favorite=true
IPv4.method=manual
IPv4.netmask_prefixlen=24
IPv4.local_address=192.168.0.133
IPv4.gateway=192.168.0.1
AutoConnect=true
Name=Wired
IPv6.method=off
IPv6.privacy=disabled
</code></pre>
<p>Now from your computer, setup your usb interface with the 192.168.0.1 IP and then youll be able to connect to your watch with:</p>
<pre><code>ssh ceres@192.168.0.133
</code></pre>
<p>/!\ This UID and the gadgets mac address both seem to be re-generated at every boot so this config isnt persistent. We should try to find a solution.</p>
<div class="page-header">
<h1 id="sshoverwifi">SSH over Wi-Fi</h1>
</div>
<p>Dropbear is already running on the watch so we just need an IP address configured to connect.</p>
<p>Ensure wireless drivers are enabled for the watch.</p>
<p>Build your <code>asteroid-image</code> with iproute2 and wpa-supplicant. In <code>meta-{watch}-hybris/conf/machine/{watch}.conf</code> add <code>iproute2</code> and <code>wpa-supplicant</code> to <code>IMAGE_INSTALL</code>:</p>
<pre><code>IMAGE_INSTALL += "android-tools android-system msm-fb-refresher brcm-patchram-plus iproute2 wpa-supplicant"
</code></pre>
<p>Once your image is installed on the watch, open up an <code>adb shell</code>:</p>
<pre><code># mkdir /etc/wpa_supplicant
# cp /etc/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
# systemctl enable --now wpa_supplicant@wlan0
# wpa_cli
&gt; scan
&gt; scan_results
&gt; add_network
&gt; set_network X ssid "MYSSID"
&gt; set_network X psk "MYPSK"
&gt; enable_network X
&gt; select_network X
&gt; save_config
# ip a show dev wlan0
</code></pre>
<p>The watch should automatically get an IPv6 address from your network or you can set a static IPv4. You can disconnect from adb and connect via SSH.</p>
<p>By default, there is no <code>root</code> or <code>ceres</code> password, and no firewall rules.</p>

View File

@ -0,0 +1,14 @@
---
title: Translating AsteroidOS
layout: documentation
---
<p>AsteroidOS translations, aside from the app name, are managed through <a href="https://hosted.weblate.org/projects/asteroidos/">Weblate</a>, a Free/Open Source web translation platform. To be able to use it, you will have to <a href="https://hosted.weblate.org/accounts/register/">register an account</a>, although you can also log in through a few popular third-party services. The rest of this page assumes you have an account.</p>
<div class="page-header">
<h1 id="updatingts">Updating translations for an existing language</h1>
</div>
<p>Updating translations for an existing language is quite simple. Simply go to <a href="https://hosted.weblate.org/projects/asteroidos/">the AsteroidOS Weblate page</a>, choose the project and language you want to translate and start translating. If you want to update the app name, please create a GitHub pull request or issue with the appropriate change to the .desktop file, or <a href="irc://irc.freenode.net/asteroid">join #asteroid on Freenode</a> to tell us about the desired change.</p>
<div class="page-header">
<h1 id="addingts">Adding a new supported language</h1>
</div>
<p>If the language you want to translate to is not supported yet, please <a href="irc://irc.freenode.net/asteroid">join #asteroid on Freenode</a> to tell us which language youd like to see supported and discuss with us what the correct app names would be in that language and well set it up for you.</p>

View File

@ -0,0 +1,38 @@
---
title: Watchfaces Creation
layout: documentation
---
<p>Watchface creation is fairly simple, requiring only QML knowledge. This guide will walk you through the steps.</p>
<div class="page-header">
<h1 id="preparingwfcrea">Preparing watchface creation</h1>
</div>
<div>
<p>First, clone the <a href="https://github.com/AsteroidOS/asteroid-launcher">https://github.com/AsteroidOS/asteroid-launcher</a> repository as it contains all watchfaces. Then, navigate to the <code>watchfaces</code> directory. In here, copy <code>000-default-digital.qml</code> to a new file to use as a base for watchface creation.</p>
</div>
<div class="page-header">
<h1 id="testingwflocal">Testing your watchface locally</h1>
</div>
<div>
<p>To test your watchface locally, I personally open the qml file using qmlscene: <code>qmlscene xxx-my-watchface.qml</code>. Of course, other QML previewing tools should work too.</p>
</div>
<div>
<p>To be able to test properly, replace all references to <code>wallClock.time</code> with <code>new Date()</code>, place an image in the same directory named <code>background.jpg</code> and put the following code just below the first Item statement:</p>
<pre lang=""><code> Image {
source: "background.jpg"
width: 160
height: 160
}</code></pre>
</div>
<div>
<p>The above code allows you to see what the watchface would look like on an actual device, as qmlscene by default uses a pure white background.</p>
</div>
<div class="page-header">
<h1 id="testingwfwatch">Testing on the watch</h1>
</div>
<div>
<p>Make sure to replace all instances of <code>new Date()</code> with <code>wallClock.time</code> and remove the background <code>Image</code> statement. Then, simply push it to the watch: <code>adb push xxx-my-watchface.qml /usr/share/asteroid-launcher/watchfaces/</code>. You can then go to watchfaces in the AsteroidOS settings. If you also pushed an <code>xxx-my-watchface.jpg</code> file, this will be used as preview. Otherwise, you will have to tap a white square to activate it.</p>
</div>
<div>
<p>If you want to update the watchface, you have to push the new version to the device. Do note that AsteroidOS may cache the watchface. The easiest way to fix this is to “restart” the device by running the following command: <code>adb shell systemctl restart user@1000</code>.</p>
</div>

View File

@ -0,0 +1,67 @@
//
// Alerts
// --------------------------------------------------
// Base styles
// -------------------------
.alert {
padding: @alert-padding;
margin-bottom: @line-height-computed;
border: 1px solid transparent;
border-radius: @alert-border-radius;
// Headings for larger alerts
h4 {
margin-top: 0;
// Specified for the h4 to prevent conflicts of changing @headings-color
color: inherit;
}
// Provide class for links that match alerts
.alert-link {
font-weight: @alert-link-font-weight;
}
// Improve alignment and spacing of inner content
> p,
> ul {
margin-bottom: 0;
}
> p + p {
margin-top: 5px;
}
}
// Dismissable alerts
//
// Expand the right padding and account for the close button's positioning.
.alert-dismissable {
padding-right: (@alert-padding + 20);
// Adjust close link position
.close {
position: relative;
top: -2px;
right: -21px;
color: inherit;
}
}
// Alternate styles
//
// Generate contextual modifier classes for colorizing the alert.
.alert-success {
.alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);
}
.alert-info {
.alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);
}
.alert-warning {
.alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);
}
.alert-danger {
.alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);
}

View File

@ -0,0 +1,51 @@
//
// Badges
// --------------------------------------------------
// Base classes
.badge {
display: inline-block;
min-width: 10px;
padding: 3px 7px;
font-size: @font-size-small;
font-weight: @badge-font-weight;
color: @badge-color;
line-height: @badge-line-height;
vertical-align: baseline;
white-space: nowrap;
text-align: center;
background-color: @badge-bg;
border-radius: @badge-border-radius;
// Empty badges collapse automatically (not available in IE8)
&:empty {
display: none;
}
}
// Hover state, but only for links
a.badge {
&:hover,
&:focus {
color: @badge-link-hover-color;
text-decoration: none;
cursor: pointer;
}
}
// Quick fix for labels/badges in buttons
.btn .badge {
position: relative;
top: -1px;
}
// Account for counters in navs
a.list-group-item.active > .badge,
.nav-pills > .active > a > .badge {
color: @badge-active-color;
background-color: @badge-active-bg;
}
.nav-pills > li > a > .badge {
margin-left: 3px;
}

View File

@ -0,0 +1,41 @@
// Reset
@import "normalize.less";
@import "print.less";
// Core CSS
@import "scaffolding.less";
@import "type.less";
@import "code.less";
@import "grid.less";
@import "tables.less";
@import "forms.less";
@import "buttons.less";
// Components
@import "component-animations.less";
@import "ionicons.less";
@import "dropdowns.less";
@import "button-groups.less";
@import "input-groups.less";
@import "navs.less";
@import "navbar.less";
@import "breadcrumbs.less";
@import "pagination.less";
@import "pager.less";
@import "labels.less";
@import "badges.less";
@import "jumbotron.less";
@import "thumbnails.less";
@import "alerts.less";
@import "progress-bars.less";
@import "media.less";
@import "list-group.less";
@import "panels.less";
@import "wells.less";
@import "close.less";
// Components w/ JavaScript
@import "modals.less";
@import "tooltip.less";
@import "popovers.less";
@import "carousel.less";

View File

@ -0,0 +1,23 @@
//
// Breadcrumbs
// --------------------------------------------------
.breadcrumb {
padding: 8px 15px;
margin-bottom: @line-height-computed;
list-style: none;
background-color: @breadcrumb-bg;
border-radius: @border-radius-base;
> li {
display: inline-block;
+ li:before {
content: "@{breadcrumb-separator}\00a0"; // Unicode space added since inline-block means non-collapsing white-space
padding: 0 5px;
color: @breadcrumb-color;
}
}
> .active {
color: @breadcrumb-active-color;
}
}

View File

@ -0,0 +1,248 @@
//
// Button groups
// --------------------------------------------------
// Button carets
//
// Match the button text color to the arrow/caret for indicating dropdown-ness.
.caret {
.btn-default & {
border-top-color: @btn-default-color;
}
.btn-primary &,
.btn-success &,
.btn-warning &,
.btn-danger &,
.btn-info & {
border-top-color: #fff;
}
}
.dropup {
& .btn-default .caret {
border-bottom-color: @btn-default-color;
}
.btn-primary,
.btn-success,
.btn-warning,
.btn-danger,
.btn-info {
.caret {
border-bottom-color: #fff;
}
}
}
// Make the div behave like a button
.btn-group,
.btn-group-vertical {
position: relative;
display: inline-block;
vertical-align: middle; // match .btn alignment given font-size hack above
> .btn {
position: relative;
float: left;
// Bring the "active" button to the front
&:hover,
&:focus,
&:active,
&.active {
z-index: 2;
}
&:focus {
// Remove focus outline when dropdown JS adds it after closing the menu
outline: none;
}
}
}
// Prevent double borders when buttons are next to each other
.btn-group {
.btn + .btn,
.btn + .btn-group,
.btn-group + .btn,
.btn-group + .btn-group {
margin-left: -1px;
}
}
// Optional: Group multiple button groups together for a toolbar
.btn-toolbar {
.clearfix();
.btn-group {
float: left;
}
// Space out series of button groups
> .btn,
> .btn-group {
+ .btn,
+ .btn-group {
margin-left: 5px;
}
}
}
.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
border-radius: 0;
}
// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match
.btn-group > .btn:first-child {
margin-left: 0;
&:not(:last-child):not(.dropdown-toggle) {
.border-right-radius(0);
}
}
// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it
.btn-group > .btn:last-child:not(:first-child),
.btn-group > .dropdown-toggle:not(:first-child) {
.border-left-radius(0);
}
// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)
.btn-group > .btn-group {
float: left;
}
.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
border-radius: 0;
}
.btn-group > .btn-group:first-child {
> .btn:last-child,
> .dropdown-toggle {
.border-right-radius(0);
}
}
.btn-group > .btn-group:last-child > .btn:first-child {
.border-left-radius(0);
}
// On active and open, don't show outline
.btn-group .dropdown-toggle:active,
.btn-group.open .dropdown-toggle {
outline: 0;
}
// Sizing
//
// Remix the default button sizing classes into new ones for easier manipulation.
.btn-group-xs > .btn { .btn-xs(); }
.btn-group-sm > .btn { .btn-sm(); }
.btn-group-lg > .btn { .btn-lg(); }
// Split button dropdowns
// ----------------------
// Give the line between buttons some depth
.btn-group > .btn + .dropdown-toggle {
padding-left: 8px;
padding-right: 8px;
}
.btn-group > .btn-lg + .dropdown-toggle {
padding-left: 12px;
padding-right: 12px;
}
// The clickable button for toggling the menu
// Remove the gradient and set the same inset shadow as the :active state
.btn-group.open .dropdown-toggle {
.box-shadow(inset 0 3px 5px rgba(0,0,0,.125));
}
// Reposition the caret
.btn .caret {
margin-left: 0;
}
// Carets in other button sizes
.btn-lg .caret {
border-width: @caret-width-large @caret-width-large 0;
border-bottom-width: 0;
}
// Upside down carets for .dropup
.dropup .btn-lg .caret {
border-width: 0 @caret-width-large @caret-width-large;
}
// Vertical button groups
// ----------------------
.btn-group-vertical {
> .btn,
> .btn-group {
display: block;
float: none;
width: 100%;
max-width: 100%;
}
// Clear floats so dropdown menus can be properly placed
> .btn-group {
.clearfix();
> .btn {
float: none;
}
}
> .btn + .btn,
> .btn + .btn-group,
> .btn-group + .btn,
> .btn-group + .btn-group {
margin-top: -1px;
margin-left: 0;
}
}
.btn-group-vertical > .btn {
&:not(:first-child):not(:last-child) {
border-radius: 0;
}
&:first-child:not(:last-child) {
border-top-right-radius: @border-radius-base;
.border-bottom-radius(0);
}
&:last-child:not(:first-child) {
border-bottom-left-radius: @border-radius-base;
.border-top-radius(0);
}
}
.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
border-radius: 0;
}
.btn-group-vertical > .btn-group:first-child {
> .btn:last-child,
> .dropdown-toggle {
.border-bottom-radius(0);
}
}
.btn-group-vertical > .btn-group:last-child > .btn:first-child {
.border-top-radius(0);
}
// Justified button groups
// ----------------------
.btn-group-justified {
display: table;
width: 100%;
table-layout: fixed;
border-collapse: separate;
.btn {
float: none;
display: table-cell;
width: 1%;
}
}
// Checkbox and radio options
[data-toggle="buttons"] > .btn > input[type="radio"],
[data-toggle="buttons"] > .btn > input[type="checkbox"] {
display: none;
}

View File

@ -0,0 +1,158 @@
//
// Buttons
// --------------------------------------------------
// Base styles
// --------------------------------------------------
// Core styles
.btn {
display: inline-block;
margin-bottom: 0; // For input.btn
font-weight: @btn-font-weight;
text-align: center;
vertical-align: middle;
cursor: pointer;
background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214
border: 1px solid transparent;
white-space: nowrap;
.button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @border-radius-base);
.user-select(none);
&:focus {
.tab-focus();
}
&:hover,
&:focus {
color: @btn-default-color;
text-decoration: none;
}
&:active,
&.active {
outline: 0;
background-image: none;
.box-shadow(inset 0 3px 5px rgba(0,0,0,.125));
}
&.disabled,
&[disabled],
fieldset[disabled] & {
cursor: not-allowed;
pointer-events: none; // Future-proof disabling of clicks
.opacity(.65);
.box-shadow(none);
}
}
// Alternate buttons
// --------------------------------------------------
.btn-default {
.button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);
}
.btn-primary {
.button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);
}
// Warning appears as orange
.btn-warning {
.button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);
}
// Danger and error appear as red
.btn-danger {
.button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);
}
// Success appears as green
.btn-success {
.button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);
}
// Info appears as blue-green
.btn-info {
.button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);
}
// Link buttons
// -------------------------
// Make a button look and behave like a link
.btn-link {
color: @link-color;
font-weight: normal;
cursor: pointer;
border-radius: 0;
&,
&:active,
&[disabled],
fieldset[disabled] & {
background-color: transparent;
.box-shadow(none);
}
&,
&:hover,
&:focus,
&:active {
border-color: transparent;
}
&:hover,
&:focus {
color: @link-hover-color;
text-decoration: underline;
background-color: transparent;
}
&[disabled],
fieldset[disabled] & {
&:hover,
&:focus {
color: @btn-link-disabled-color;
text-decoration: none;
}
}
}
// Button Sizes
// --------------------------------------------------
.btn-lg {
// line-height: ensure even-numbered height of button next to large input
.button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);
}
.btn-sm,
.btn-xs {
// line-height: ensure proper height of button next to small input
.button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);
}
.btn-xs {
padding: 1px 5px;
}
// Block button
// --------------------------------------------------
.btn-block {
display: block;
width: 100%;
padding-left: 0;
padding-right: 0;
}
// Vertically space out multiple block buttons
.btn-block + .btn-block {
margin-top: 5px;
}
// Specificity overrides
input[type="submit"],
input[type="reset"],
input[type="button"] {
&.btn-block {
width: 100%;
}
}

View File

@ -0,0 +1,220 @@
//
// Carousel
// --------------------------------------------------
// Wrapper for the slide container and indicators
.carousel {
position: relative;
}
.carousel-inner {
position: relative;
overflow: hidden;
width: 100%;
> .item {
display: none;
position: relative;
.transition(.6s ease-in-out left);
// Account for jankitude on images
> img,
> a > img {
.img-responsive();
line-height: 1;
}
}
> .active,
> .next,
> .prev { display: block; }
> .active {
left: 0;
}
> .next,
> .prev {
position: absolute;
top: 0;
width: 100%;
}
> .next {
left: 100%;
}
> .prev {
left: -100%;
}
> .next.left,
> .prev.right {
left: 0;
}
> .active.left {
left: -100%;
}
> .active.right {
left: 100%;
}
}
// Left/right controls for nav
// ---------------------------
.carousel-control {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: @carousel-control-width;
.opacity(@carousel-control-opacity);
font-size: @carousel-control-font-size;
color: @carousel-control-color;
text-align: center;
text-shadow: @carousel-text-shadow;
// We can't have this transition here because webkit cancels the carousel
// animation if you trip this while in the middle of another animation.
// Set gradients for backgrounds
&.left {
#gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001));
}
&.right {
left: auto;
right: 0;
#gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5));
}
// Hover/focus state
&:hover,
&:focus {
color: @carousel-control-color;
text-decoration: none;
.opacity(.9);
}
// Toggles
.icon-prev,
.icon-next,
.glyphicon-chevron-left,
.glyphicon-chevron-right {
position: absolute;
top: 50%;
z-index: 5;
display: inline-block;
}
.icon-prev,
.glyphicon-chevron-left {
left: 50%;
}
.icon-next,
.glyphicon-chevron-right {
right: 50%;
}
.icon-prev,
.icon-next {
width: 20px;
height: 20px;
margin-top: -10px;
margin-left: -10px;
font-family: serif;
}
.icon-prev {
&:before {
content: '\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039)
}
}
.icon-next {
&:before {
content: '\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A)
}
}
}
// Optional indicator pips
//
// Add an unordered list with the following class and add a list item for each
// slide your carousel holds.
.carousel-indicators {
position: absolute;
bottom: 10px;
left: 50%;
z-index: 15;
width: 60%;
margin-left: -30%;
padding-left: 0;
list-style: none;
text-align: center;
li {
display: inline-block;
width: 10px;
height: 10px;
margin: 1px;
text-indent: -999px;
border: 1px solid @carousel-indicator-border-color;
border-radius: 10px;
cursor: pointer;
}
.active {
margin: 0;
width: 12px;
height: 12px;
background-color: @carousel-indicator-active-bg;
}
}
// Optional captions
// -----------------------------
// Hidden by default for smaller viewports
.carousel-caption {
position: absolute;
left: 15%;
right: 15%;
bottom: 20px;
z-index: 10;
padding-top: 20px;
padding-bottom: 20px;
color: @carousel-caption-color;
text-align: center;
text-shadow: @carousel-text-shadow;
& .btn {
text-shadow: none; // No shadow for button elements in carousel-caption
}
}
// Scale up controls for tablets and up
@media screen and (min-width: @screen-sm-min) {
// Scale up the controls a smidge
.carousel-control {
.glyphicons-chevron-left,
.glyphicons-chevron-right,
.icon-prev,
.icon-next {
width: 30px;
height: 30px;
margin-top: -15px;
margin-left: -15px;
font-size: 30px;
}
}
// Show and left align the captions
.carousel-caption {
left: 20%;
right: 20%;
padding-bottom: 30px;
}
// Move up the indicators
.carousel-indicators {
bottom: 20px;
}
}

View File

@ -0,0 +1,33 @@
//
// Close icons
// --------------------------------------------------
.close {
float: right;
font-size: (@font-size-base * 1.5);
font-weight: @close-font-weight;
line-height: 1;
color: @close-color;
text-shadow: @close-text-shadow;
.opacity(.2);
&:hover,
&:focus {
color: @close-color;
text-decoration: none;
cursor: pointer;
.opacity(.5);
}
// Additional properties for button version
// iOS requires the button element instead of an anchor tag.
// If you want the anchor version, it requires `href="#"`.
button& {
padding: 0;
cursor: pointer;
background: transparent;
border: 0;
-webkit-appearance: none;
}
}

View File

@ -0,0 +1,53 @@
//
// Code (inline and blocK)
// --------------------------------------------------
// Inline and block code styles
code,
kbd,
pre,
samp {
font-family: @font-family-monospace;
}
// Inline code
code {
padding: 2px 4px;
font-size: 90%;
color: @code-color;
background-color: @code-bg;
white-space: nowrap;
border-radius: @border-radius-base;
}
// Blocks of code
pre {
display: block;
padding: ((@line-height-computed - 1) / 2);
margin: 0 0 (@line-height-computed / 2);
font-size: (@font-size-base - 1); // 14px to 13px
line-height: @line-height-base;
word-break: break-all;
word-wrap: break-word;
color: @pre-color;
background-color: @pre-bg;
border: 1px solid @pre-border-color;
border-radius: @border-radius-base;
// Account for some code outputs that place code tags in pre tags
code {
padding: 0;
font-size: inherit;
color: inherit;
white-space: pre-wrap;
background-color: transparent;
border-radius: 0;
}
}
// Enable scrollable blocks of code
.pre-scrollable {
max-height: @pre-scrollable-max-height;
overflow-y: scroll;
}

View File

@ -0,0 +1,29 @@
//
// Component animations
// --------------------------------------------------
// Heads up!
//
// We don't use the `.opacity()` mixin here since it causes a bug with text
// fields in IE7-8. Source: https://github.com/twitter/bootstrap/pull/3552.
.fade {
opacity: 0;
.transition(opacity .15s linear);
&.in {
opacity: 1;
}
}
.collapse {
display: none;
&.in {
display: block;
}
}
.collapsing {
position: relative;
height: 0;
overflow: hidden;
.transition(height .35s ease);
}

View File

@ -0,0 +1,192 @@
//
// Dropdown menus
// --------------------------------------------------
// Dropdown arrow/caret
.caret {
display: inline-block;
width: 0;
height: 0;
margin-left: 2px;
vertical-align: middle;
border-top: @caret-width-base solid @dropdown-caret-color;
border-right: @caret-width-base solid transparent;
border-left: @caret-width-base solid transparent;
// Firefox fix for https://github.com/twbs/bootstrap/issues/9538. Once fixed,
// we can just straight up remove this.
border-bottom: 0 dotted;
}
// The dropdown wrapper (div)
.dropdown {
position: relative;
}
// Prevent the focus on the dropdown toggle when closing dropdowns
.dropdown-toggle:focus {
outline: 0;
}
// The dropdown menu (ul)
.dropdown-menu {
position: absolute;
top: 100%;
left: 0;
z-index: @zindex-dropdown;
display: none; // none by default, but block on "open" of the menu
float: left;
min-width: 160px;
padding: 5px 0;
margin: 2px 0 0; // override default ul
list-style: none;
font-size: @font-size-base;
background-color: @dropdown-bg;
border: 1px solid @dropdown-fallback-border; // IE8 fallback
border: 1px solid @dropdown-border;
border-radius: @border-radius-base;
.box-shadow(0 6px 12px rgba(0,0,0,.175));
background-clip: padding-box;
// Aligns the dropdown menu to right
&.pull-right {
right: 0;
left: auto;
}
// Dividers (basically an hr) within the dropdown
.divider {
.nav-divider(@dropdown-divider-bg);
}
// Links within the dropdown menu
> li > a {
display: block;
padding: 3px 20px;
clear: both;
font-weight: normal;
line-height: @line-height-base;
color: @dropdown-link-color;
white-space: nowrap; // prevent links from randomly breaking onto new lines
}
}
// Hover/Focus state
.dropdown-menu > li > a {
&:hover,
&:focus {
text-decoration: none;
color: @dropdown-link-hover-color;
background-color: @dropdown-link-hover-bg;
}
}
// Active state
.dropdown-menu > .active > a {
&,
&:hover,
&:focus {
color: @dropdown-link-active-color;
text-decoration: none;
outline: 0;
background-color: @dropdown-link-active-bg;
}
}
// Disabled state
//
// Gray out text and ensure the hover/focus state remains gray
.dropdown-menu > .disabled > a {
&,
&:hover,
&:focus {
color: @dropdown-link-disabled-color;
}
}
// Nuke hover/focus effects
.dropdown-menu > .disabled > a {
&:hover,
&:focus {
text-decoration: none;
background-color: transparent;
background-image: none; // Remove CSS gradient
.reset-filter();
cursor: not-allowed;
}
}
// Open state for the dropdown
.open {
// Show the menu
> .dropdown-menu {
display: block;
}
// Remove the outline when :focus is triggered
> a {
outline: 0;
}
}
// Dropdown section headers
.dropdown-header {
display: block;
padding: 3px 20px;
font-size: @font-size-small;
line-height: @line-height-base;
color: @dropdown-header-color;
}
// Backdrop to catch body clicks on mobile, etc.
.dropdown-backdrop {
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
z-index: @zindex-dropdown - 10;
}
// Right aligned dropdowns
.pull-right > .dropdown-menu {
right: 0;
left: auto;
}
// Allow for dropdowns to go bottom up (aka, dropup-menu)
//
// Just add .dropup after the standard .dropdown class and you're set, bro.
// TODO: abstract this so that the navbar fixed styles are not placed here?
.dropup,
.navbar-fixed-bottom .dropdown {
// Reverse the caret
.caret {
// Firefox fix for https://github.com/twbs/bootstrap/issues/9538. Once this
// gets fixed, restore `border-top: 0;`.
border-top: 0 dotted;
border-bottom: 4px solid @dropdown-caret-color;
content: "";
}
// Different positioning for bottom up menu
.dropdown-menu {
top: auto;
bottom: 100%;
margin-bottom: 1px;
}
}
// Component alignment
//
// Reiterate per navbar.less and the modified component alignment there.
@media (min-width: @grid-float-breakpoint) {
.navbar-right {
.dropdown-menu {
.pull-right > .dropdown-menu();
}
}
}

366
styles/bootstrap/forms.less Normal file
View File

@ -0,0 +1,366 @@
//
// Forms
// --------------------------------------------------
// Normalize non-controls
//
// Restyle and baseline non-control form elements.
fieldset {
padding: 0;
margin: 0;
border: 0;
}
legend {
display: block;
width: 100%;
padding: 0;
margin-bottom: @line-height-computed;
font-size: (@font-size-base * 1.5);
line-height: inherit;
color: @legend-color;
border: 0;
border-bottom: 1px solid @legend-border-color;
}
label {
display: inline-block;
margin-bottom: 5px;
font-weight: bold;
}
// Normalize form controls
// Override content-box in Normalize (* isn't specific enough)
input[type="search"] {
.box-sizing(border-box);
}
// Position radios and checkboxes better
input[type="radio"],
input[type="checkbox"] {
margin: 4px 0 0;
margin-top: 1px \9; /* IE8-9 */
line-height: normal;
}
// Set the height of select and file controls to match text inputs
input[type="file"] {
display: block;
}
// Make multiple select elements height not fixed
select[multiple],
select[size] {
height: auto;
}
// Fix optgroup Firefox bug per https://github.com/twbs/bootstrap/issues/7611
select optgroup {
font-size: inherit;
font-style: inherit;
font-family: inherit;
}
// Focus for select, file, radio, and checkbox
input[type="file"]:focus,
input[type="radio"]:focus,
input[type="checkbox"]:focus {
.tab-focus();
}
// Fix for Chrome number input
// Setting certain font-sizes causes the `I` bar to appear on hover of the bottom increment button.
// See https://github.com/twbs/bootstrap/issues/8350 for more.
input[type="number"] {
&::-webkit-outer-spin-button,
&::-webkit-inner-spin-button {
height: auto;
}
}
// Adjust output element
output {
display: block;
padding-top: (@padding-base-vertical + 1);
font-size: @font-size-base;
line-height: @line-height-base;
color: @input-color;
vertical-align: middle;
}
// Placeholder
//
// Placeholder text gets special styles because when browsers invalidate entire
// lines if it doesn't understand a selector/
.form-control {
.placeholder();
}
// Common form controls
//
// Shared size and type resets for form controls. Apply `.form-control` to any
// of the following form controls:
//
// select
// textarea
// input[type="text"]
// input[type="password"]
// input[type="datetime"]
// input[type="datetime-local"]
// input[type="date"]
// input[type="month"]
// input[type="time"]
// input[type="week"]
// input[type="number"]
// input[type="email"]
// input[type="url"]
// input[type="search"]
// input[type="tel"]
// input[type="color"]
.form-control {
display: block;
width: 100%;
height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)
padding: @padding-base-vertical @padding-base-horizontal;
font-size: @font-size-base;
line-height: @line-height-base;
color: @input-color;
vertical-align: middle;
background-color: @input-bg;
background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214
border: 1px solid @input-border;
border-radius: @input-border-radius;
.box-shadow(inset 0 1px 1px rgba(0,0,0,.075));
.transition(~"border-color ease-in-out .15s, box-shadow ease-in-out .15s");
// Customize the `:focus` state to imitate native WebKit styles.
.form-control-focus();
// Disabled and read-only inputs
// Note: HTML5 says that controls under a fieldset > legend:first-child won't
// be disabled if the fieldset is disabled. Due to implementation difficulty,
// we don't honor that edge case; we style them as disabled anyway.
&[disabled],
&[readonly],
fieldset[disabled] & {
cursor: not-allowed;
background-color: @input-bg-disabled;
}
// Reset height for `textarea`s
textarea& {
height: auto;
}
}
// Form groups
//
// Designed to help with the organization and spacing of vertical forms. For
// horizontal forms, use the predefined grid classes.
.form-group {
margin-bottom: 15px;
}
// Checkboxes and radios
//
// Indent the labels to position radios/checkboxes as hanging controls.
.radio,
.checkbox {
display: block;
min-height: @line-height-computed; // clear the floating input if there is no label text
margin-top: 10px;
margin-bottom: 10px;
padding-left: 20px;
vertical-align: middle;
label {
display: inline;
margin-bottom: 0;
font-weight: normal;
cursor: pointer;
}
}
.radio input[type="radio"],
.radio-inline input[type="radio"],
.checkbox input[type="checkbox"],
.checkbox-inline input[type="checkbox"] {
float: left;
margin-left: -20px;
}
.radio + .radio,
.checkbox + .checkbox {
margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing
}
// Radios and checkboxes on same line
.radio-inline,
.checkbox-inline {
display: inline-block;
padding-left: 20px;
margin-bottom: 0;
vertical-align: middle;
font-weight: normal;
cursor: pointer;
}
.radio-inline + .radio-inline,
.checkbox-inline + .checkbox-inline {
margin-top: 0;
margin-left: 10px; // space out consecutive inline controls
}
// Apply same disabled cursor tweak as for inputs
//
// Note: Neither radios nor checkboxes can be readonly.
input[type="radio"],
input[type="checkbox"],
.radio,
.radio-inline,
.checkbox,
.checkbox-inline {
&[disabled],
fieldset[disabled] & {
cursor: not-allowed;
}
}
// Form control sizing
.input-sm {
.input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);
}
.input-lg {
.input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);
}
// Form control feedback states
//
// Apply contextual and semantic states to individual form controls.
// Warning
.has-warning {
.form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);
}
// Error
.has-error {
.form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);
}
// Success
.has-success {
.form-control-validation(@state-success-text; @state-success-text; @state-success-bg);
}
// Static form control text
//
// Apply class to a `p` element to make any string of text align with labels in
// a horizontal form layout.
.form-control-static {
margin-bottom: 0; // Remove default margin from `p`
}
// Help text
//
// Apply to any element you wish to create light text for placement immediately
// below a form control. Use for general help, formatting, or instructional text.
.help-block {
display: block; // account for any element using help-block
margin-top: 5px;
margin-bottom: 10px;
color: lighten(@text-color, 25%); // lighten the text some for contrast
}
// Inline forms
//
// Make forms appear inline(-block) by adding the `.form-inline` class. Inline
// forms begin stacked on extra small (mobile) devices and then go inline when
// viewports reach <768px.
//
// Requires wrapping inputs and labels with `.form-group` for proper display of
// default HTML form controls and our custom form controls (e.g., input groups).
//
// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.
.form-inline {
// Kick in the inline
@media (min-width: @screen-sm) {
// Inline-block all the things for "inline"
.form-group {
display: inline-block;
margin-bottom: 0;
vertical-align: middle;
}
// In navbar-form, allow folks to *not* use `.form-group`
.form-control {
display: inline-block;
}
// Remove default margin on radios/checkboxes that were used for stacking, and
// then undo the floating of radios and checkboxes to match (which also avoids
// a bug in WebKit: https://github.com/twbs/bootstrap/issues/1969).
.radio,
.checkbox {
display: inline-block;
margin-top: 0;
margin-bottom: 0;
padding-left: 0;
}
.radio input[type="radio"],
.checkbox input[type="checkbox"] {
float: none;
margin-left: 0;
}
}
}
// Horizontal forms
//
// Horizontal forms are built on grid classes and allow you to create forms with
// labels on the left and inputs on the right.
.form-horizontal {
// Consistent vertical alignment of labels, radios, and checkboxes
.control-label,
.radio,
.checkbox,
.radio-inline,
.checkbox-inline {
margin-top: 0;
margin-bottom: 0;
padding-top: (@padding-base-vertical + 1); // Default padding plus a border
}
// Make form groups behave like rows
.form-group {
.make-row();
}
.form-control-static {
padding-top: (@padding-base-vertical + 1);
}
// Only right align form labels here when the columns stop stacking
@media (min-width: @screen-sm-min) {
.control-label {
text-align: right;
}
}
}

View File

@ -0,0 +1,93 @@
//
// Grid system
// --------------------------------------------------
// Set the container width, and override it for fixed navbars in media queries
.container {
.container-fixed();
}
// mobile first defaults
.row {
.make-row();
}
// Common styles for small and large grid columns
.make-grid-columns();
// Extra small grid
//
// Grid classes for extra small devices like smartphones. No offset, push, or
// pull classes are present here due to the size of the target.
//
// Note that `.col-xs-12` doesn't get floated on purpose--there's no need since
// it's full-width.
.make-grid-columns-float(xs);
.make-grid(@grid-columns, xs, width);
.make-grid(@grid-columns, xs, pull);
.make-grid(@grid-columns, xs, push);
.make-grid(@grid-columns, xs, offset);
// Small grid
//
// Columns, offsets, pushes, and pulls for the small device range, from phones
// to tablets.
//
// Note that `.col-sm-12` doesn't get floated on purpose--there's no need since
// it's full-width.
@media (min-width: @screen-sm-min) {
.container {
width: @container-sm;
}
.make-grid-columns-float(sm);
.make-grid(@grid-columns, sm, width);
.make-grid(@grid-columns, sm, pull);
.make-grid(@grid-columns, sm, push);
.make-grid(@grid-columns, sm, offset);
}
// Medium grid
//
// Columns, offsets, pushes, and pulls for the desktop device range.
//
// Note that `.col-md-12` doesn't get floated on purpose--there's no need since
// it's full-width.
@media (min-width: @screen-md-min) {
.container {
width: @container-md;
}
.make-grid-columns-float(md);
.make-grid(@grid-columns, md, width);
.make-grid(@grid-columns, md, pull);
.make-grid(@grid-columns, md, push);
.make-grid(@grid-columns, md, offset);
}
// Large grid
//
// Columns, offsets, pushes, and pulls for the large desktop device range.
//
// Note that `.col-lg-12` doesn't get floated on purpose--there's no need since
// it's full-width.
@media (min-width: @screen-lg-min) {
.container {
width: @container-lg;
}
.make-grid-columns-float(lg);
.make-grid(@grid-columns, lg, width);
.make-grid(@grid-columns, lg, pull);
.make-grid(@grid-columns, lg, push);
.make-grid(@grid-columns, lg, offset);
}

View File

@ -0,0 +1,136 @@
//
// Input groups
// --------------------------------------------------
// Base styles
// -------------------------
.input-group {
position: relative; // For dropdowns
display: table;
border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table
// Undo padding and float of grid classes
&.col {
float: none;
padding-left: 0;
padding-right: 0;
}
.form-control {
width: 100%;
margin-bottom: 0;
}
}
// Sizing options
//
// Remix the default form control sizing classes into new ones for easier
// manipulation.
.input-group-lg > .form-control,
.input-group-lg > .input-group-addon,
.input-group-lg > .input-group-btn > .btn { .input-lg(); }
.input-group-sm > .form-control,
.input-group-sm > .input-group-addon,
.input-group-sm > .input-group-btn > .btn { .input-sm(); }
// Display as table-cell
// -------------------------
.input-group-addon,
.input-group-btn,
.input-group .form-control {
display: table-cell;
&:not(:first-child):not(:last-child) {
border-radius: 0;
}
}
// Addon and addon wrapper for buttons
.input-group-addon,
.input-group-btn {
width: 1%;
white-space: nowrap;
vertical-align: middle; // Match the inputs
}
// Text input groups
// -------------------------
.input-group-addon {
padding: @padding-base-vertical @padding-base-horizontal;
font-size: @font-size-base;
font-weight: normal;
line-height: 1;
color: @input-color;
text-align: center;
background-color: @input-group-addon-bg;
border: 1px solid @input-group-addon-border-color;
border-radius: @border-radius-base;
// Sizing
&.input-sm {
padding: @padding-small-vertical @padding-small-horizontal;
font-size: @font-size-small;
border-radius: @border-radius-small;
}
&.input-lg {
padding: @padding-large-vertical @padding-large-horizontal;
font-size: @font-size-large;
border-radius: @border-radius-large;
}
// Nuke default margins from checkboxes and radios to vertically center within.
input[type="radio"],
input[type="checkbox"] {
margin-top: 0;
}
}
// Reset rounded corners
.input-group .form-control:first-child,
.input-group-addon:first-child,
.input-group-btn:first-child > .btn,
.input-group-btn:first-child > .dropdown-toggle,
.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) {
.border-right-radius(0);
}
.input-group-addon:first-child {
border-right: 0;
}
.input-group .form-control:last-child,
.input-group-addon:last-child,
.input-group-btn:last-child > .btn,
.input-group-btn:last-child > .dropdown-toggle,
.input-group-btn:first-child > .btn:not(:first-child) {
.border-left-radius(0);
}
.input-group-addon:last-child {
border-left: 0;
}
// Button input groups
// -------------------------
.input-group-btn {
position: relative;
white-space: nowrap;
// Negative margin to only have a 1px border between the two
&:first-child > .btn {
margin-right: -1px;
}
&:last-child > .btn {
margin-left: -1px;
}
}
.input-group-btn > .btn {
position: relative;
// Jankily prevent input button groups from wrapping
+ .btn {
margin-left: -4px;
}
// Bring the "active" button to the front
&:hover,
&:active {
z-index: 2;
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,40 @@
//
// Jumbotron
// --------------------------------------------------
.jumbotron {
padding: @jumbotron-padding;
margin-bottom: @jumbotron-padding;
font-size: @jumbotron-font-size;
font-weight: 200;
line-height: (@line-height-base * 1.5);
color: @jumbotron-color;
background-color: @jumbotron-bg;
h1 {
line-height: 1;
color: @jumbotron-heading-color;
}
p {
line-height: 1.4;
}
.container & {
border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container
}
@media screen and (min-width: @screen-sm-min) {
padding-top: (@jumbotron-padding * 1.6);
padding-bottom: (@jumbotron-padding * 1.6);
.container & {
padding-left: (@jumbotron-padding * 2);
padding-right: (@jumbotron-padding * 2);
}
h1 {
font-size: (@font-size-base * 4.5);
}
}
}

View File

@ -0,0 +1,58 @@
//
// Labels
// --------------------------------------------------
.label {
display: inline;
padding: .2em .6em .3em;
font-size: 75%;
font-weight: bold;
line-height: 1;
color: @label-color;
text-align: center;
white-space: nowrap;
vertical-align: baseline;
border-radius: .25em;
// Add hover effects, but only for links
&[href] {
&:hover,
&:focus {
color: @label-link-hover-color;
text-decoration: none;
cursor: pointer;
}
}
// Empty labels collapse automatically (not available in IE8)
&:empty {
display: none;
}
}
// Colors
// Contextual variations (linked labels get darker on :hover)
.label-default {
.label-variant(@label-default-bg);
}
.label-primary {
.label-variant(@label-primary-bg);
}
.label-success {
.label-variant(@label-success-bg);
}
.label-info {
.label-variant(@label-info-bg);
}
.label-warning {
.label-variant(@label-warning-bg);
}
.label-danger {
.label-variant(@label-danger-bg);
}

View File

@ -0,0 +1,88 @@
//
// List groups
// --------------------------------------------------
// Base class
//
// Easily usable on <ul>, <ol>, or <div>.
.list-group {
// No need to set list-style: none; since .list-group-item is block level
margin-bottom: 20px;
padding-left: 0; // reset padding because ul and ol
}
// Individual list items
// -------------------------
.list-group-item {
position: relative;
display: block;
padding: 10px 15px;
// Place the border on the list items and negative margin up for better styling
margin-bottom: -1px;
background-color: @list-group-bg;
border: 1px solid @list-group-border;
// Round the first and last items
&:first-child {
.border-top-radius(@list-group-border-radius);
}
&:last-child {
margin-bottom: 0;
.border-bottom-radius(@list-group-border-radius);
}
// Align badges within list items
> .badge {
float: right;
}
> .badge + .badge {
margin-right: 5px;
}
}
// Linked list items
a.list-group-item {
color: @list-group-link-color;
.list-group-item-heading {
color: @list-group-link-heading-color;
}
// Hover state
&:hover,
&:focus {
text-decoration: none;
background-color: @list-group-hover-bg;
}
// Active class on item itself, not parent
&.active,
&.active:hover,
&.active:focus {
z-index: 2; // Place active items above their siblings for proper border styling
color: @list-group-active-color;
background-color: @list-group-active-bg;
border-color: @list-group-active-border;
// Force color to inherit for custom content
.list-group-item-heading {
color: inherit;
}
.list-group-item-text {
color: lighten(@list-group-active-bg, 40%);
}
}
}
// Custom content options
// -------------------------
.list-group-item-heading {
margin-top: 0;
margin-bottom: 5px;
}
.list-group-item-text {
margin-bottom: 0;
line-height: 1.3;
}

View File

@ -0,0 +1,56 @@
// Media objects
// Source: http://stubbornella.org/content/?p=497
// --------------------------------------------------
// Common styles
// -------------------------
// Clear the floats
.media,
.media-body {
overflow: hidden;
zoom: 1;
}
// Proper spacing between instances of .media
.media,
.media .media {
margin-top: 15px;
}
.media:first-child {
margin-top: 0;
}
// For images and videos, set to block
.media-object {
display: block;
}
// Reset margins on headings for tighter default spacing
.media-heading {
margin: 0 0 5px;
}
// Media image alignment
// -------------------------
.media {
> .pull-left {
margin-right: 10px;
}
> .pull-right {
margin-left: 10px;
}
}
// Media list variation
// -------------------------
// Undo default ul/ol styles
.media-list {
padding-left: 0;
list-style: none;
}

View File

@ -0,0 +1,846 @@
//
// Mixins
// --------------------------------------------------
// Utilities
// -------------------------
// Clearfix
// Source: http://nicolasgallagher.com/micro-clearfix-hack/
//
// For modern browsers
// 1. The space content is one way to avoid an Opera bug when the
// contenteditable attribute is included anywhere else in the document.
// Otherwise it causes space to appear at the top and bottom of elements
// that are clearfixed.
// 2. The use of `table` rather than `block` is only necessary if using
// `:before` to contain the top-margins of child elements.
.clearfix() {
&:before,
&:after {
content: " "; /* 1 */
display: table; /* 2 */
}
&:after {
clear: both;
}
}
// Webkit-style focus
.tab-focus() {
// Default
outline: thin dotted #333;
// Webkit
outline: 5px auto -webkit-focus-ring-color;
outline-offset: -2px;
}
// Center-align a block level element
.center-block() {
display: block;
margin-left: auto;
margin-right: auto;
}
// Sizing shortcuts
.size(@width; @height) {
width: @width;
height: @height;
}
.square(@size) {
.size(@size; @size);
}
// Placeholder text
.placeholder(@color: @input-color-placeholder) {
&:-moz-placeholder { color: @color; } // Firefox 4-18
&::-moz-placeholder { color: @color; } // Firefox 19+
&:-ms-input-placeholder { color: @color; } // Internet Explorer 10+
&::-webkit-input-placeholder { color: @color; } // Safari and Chrome
}
// Text overflow
// Requires inline-block or block for proper styling
.text-overflow() {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
// CSS image replacement
//
// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for
// mixins being reused as classes with the same name, this doesn't hold up. As
// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`. Note
// that we cannot chain the mixins together in Less, so they are repeated.
//
// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757
// Deprecated as of v3.0.1 (will be removed in v4)
.hide-text() {
font: ~"0/0" a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}
// New mixin to use as of v3.0.1
.text-hide() {
font: ~"0/0" a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}
// CSS3 PROPERTIES
// --------------------------------------------------
// Single side border-radius
.border-top-radius(@radius) {
border-top-right-radius: @radius;
border-top-left-radius: @radius;
}
.border-right-radius(@radius) {
border-bottom-right-radius: @radius;
border-top-right-radius: @radius;
}
.border-bottom-radius(@radius) {
border-bottom-right-radius: @radius;
border-bottom-left-radius: @radius;
}
.border-left-radius(@radius) {
border-bottom-left-radius: @radius;
border-top-left-radius: @radius;
}
// Drop shadows
.box-shadow(@shadow) {
-webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1
box-shadow: @shadow;
}
// Transitions
.transition(@transition) {
-webkit-transition: @transition;
transition: @transition;
}
.transition-property(@transition-property) {
-webkit-transition-property: @transition-property;
transition-property: @transition-property;
}
.transition-delay(@transition-delay) {
-webkit-transition-delay: @transition-delay;
transition-delay: @transition-delay;
}
.transition-duration(@transition-duration) {
-webkit-transition-duration: @transition-duration;
transition-duration: @transition-duration;
}
.transition-transform(@transition) {
-webkit-transition: -webkit-transform @transition;
-moz-transition: -moz-transform @transition;
-o-transition: -o-transform @transition;
transition: transform @transition;
}
// Transformations
.rotate(@degrees) {
-webkit-transform: rotate(@degrees);
-ms-transform: rotate(@degrees); // IE9+
transform: rotate(@degrees);
}
.scale(@ratio) {
-webkit-transform: scale(@ratio);
-ms-transform: scale(@ratio); // IE9+
transform: scale(@ratio);
}
.translate(@x; @y) {
-webkit-transform: translate(@x, @y);
-ms-transform: translate(@x, @y); // IE9+
transform: translate(@x, @y);
}
.skew(@x; @y) {
-webkit-transform: skew(@x, @y);
-ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+
transform: skew(@x, @y);
}
.translate3d(@x; @y; @z) {
-webkit-transform: translate3d(@x, @y, @z);
transform: translate3d(@x, @y, @z);
}
.rotateX(@degrees) {
-webkit-transform: rotateX(@degrees);
-ms-transform: rotateX(@degrees); // IE9+
transform: rotateX(@degrees);
}
.rotateY(@degrees) {
-webkit-transform: rotateY(@degrees);
-ms-transform: rotateY(@degrees); // IE9+
transform: rotateY(@degrees);
}
.perspective(@perspective) {
-webkit-perspective: @perspective;
-moz-perspective: @perspective;
perspective: @perspective;
}
.perspective-origin(@perspective) {
-webkit-perspective-origin: @perspective;
-moz-perspective-origin: @perspective;
perspective-origin: @perspective;
}
.transform-origin(@origin){
-webkit-transform-origin: @origin;
-moz-transform-origin: @origin;
transform-origin: @origin;
}
// Backface visibility
// Prevent browsers from flickering when using CSS 3D transforms.
// Default value is `visible`, but can be changed to `hidden`
// See git pull https://github.com/dannykeane/bootstrap.git backface-visibility for examples
.backface-visibility(@visibility){
-webkit-backface-visibility: @visibility;
-moz-backface-visibility: @visibility;
backface-visibility: @visibility;
}
// Box sizing
.box-sizing(@boxmodel) {
-webkit-box-sizing: @boxmodel;
-moz-box-sizing: @boxmodel;
box-sizing: @boxmodel;
}
// User select
// For selecting text on the page
.user-select(@select) {
-webkit-user-select: @select;
-moz-user-select: @select;
-ms-user-select: @select; // IE10+
-o-user-select: @select;
user-select: @select;
}
// Resize anything
.resizable(@direction) {
resize: @direction; // Options: horizontal, vertical, both
overflow: auto; // Safari fix
}
// CSS3 Content Columns
.content-columns(@column-count; @column-gap: @grid-gutter-width) {
-webkit-column-count: @column-count;
-moz-column-count: @column-count;
column-count: @column-count;
-webkit-column-gap: @column-gap;
-moz-column-gap: @column-gap;
column-gap: @column-gap;
}
// Optional hyphenation
.hyphens(@mode: auto) {
word-wrap: break-word;
-webkit-hyphens: @mode;
-moz-hyphens: @mode;
-ms-hyphens: @mode; // IE10+
-o-hyphens: @mode;
hyphens: @mode;
}
// Opacity
.opacity(@opacity) {
opacity: @opacity;
// IE8 filter
@opacity-ie: (@opacity * 100);
filter: ~"alpha(opacity=@{opacity-ie})";
}
// GRADIENTS
// --------------------------------------------------
#gradient {
// Horizontal gradient, from left to right
//
// Creates two color stops, start and end, by specifying a color and position for each color stop.
// Color stops are not available in IE9 and below.
.horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {
background-image: -webkit-gradient(linear, @start-percent top, @end-percent top, from(@start-color), to(@end-color)); // Safari 4+, Chrome 2+
background-image: -webkit-linear-gradient(left, color-stop(@start-color @start-percent), color-stop(@end-color @end-percent)); // Safari 5.1+, Chrome 10+
background-image: -moz-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // FF 3.6+
background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10
background-repeat: repeat-x;
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)",argb(@start-color),argb(@end-color))); // IE9 and down
}
// Vertical gradient, from top to bottom
//
// Creates two color stops, start and end, by specifying a color and position for each color stop.
// Color stops are not available in IE9 and below.
.vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {
background-image: -webkit-gradient(linear, left @start-percent, left @end-percent, from(@start-color), to(@end-color)); // Safari 4+, Chrome 2+
background-image: -webkit-linear-gradient(top, @start-color, @start-percent, @end-color, @end-percent); // Safari 5.1+, Chrome 10+
background-image: -moz-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // FF 3.6+
background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10
background-repeat: repeat-x;
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",argb(@start-color),argb(@end-color))); // IE9 and down
}
.directional(@start-color: #555; @end-color: #333; @deg: 45deg) {
background-repeat: repeat-x;
background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1+, Chrome 10+
background-image: -moz-linear-gradient(@deg, @start-color, @end-color); // FF 3.6+
background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10
}
.horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {
background-image: -webkit-gradient(left, linear, 0 0, 0 100%, from(@start-color), color-stop(@color-stop, @mid-color), to(@end-color));
background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);
background-image: -moz-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);
background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);
background-repeat: no-repeat;
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback
}
.vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(@start-color), color-stop(@color-stop, @mid-color), to(@end-color));
background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);
background-image: -moz-linear-gradient(top, @start-color, @mid-color @color-stop, @end-color);
background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);
background-repeat: no-repeat;
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback
}
.radial(@inner-color: #555; @outer-color: #333) {
background-image: -webkit-gradient(radial, center center, 0, center center, 460, from(@inner-color), to(@outer-color));
background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);
background-image: -moz-radial-gradient(circle, @inner-color, @outer-color);
background-image: radial-gradient(circle, @inner-color, @outer-color);
background-repeat: no-repeat;
}
.striped(@color: rgba(255,255,255,.15); @angle: 45deg) {
background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, @color), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, @color), color-stop(.75, @color), color-stop(.75, transparent), to(transparent));
background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);
background-image: -moz-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);
background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);
}
}
// Reset filters for IE
//
// When you need to remove a gradient background, do not forget to use this to reset
// the IE filter for IE9 and below.
.reset-filter() {
filter: e(%("progid:DXImageTransform.Microsoft.gradient(enabled = false)"));
}
// Retina images
//
// Short retina mixin for setting background-image and -size
.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {
background-image: url("@{file-1x}");
@media
only screen and (-webkit-min-device-pixel-ratio: 2),
only screen and ( min--moz-device-pixel-ratio: 2),
only screen and ( -o-min-device-pixel-ratio: 2/1),
only screen and ( min-device-pixel-ratio: 2),
only screen and ( min-resolution: 192dpi),
only screen and ( min-resolution: 2dppx) {
background-image: url("@{file-2x}");
background-size: @width-1x @height-1x;
}
}
// Responsive image
//
// Keep images from scaling beyond the width of their parents.
.img-responsive(@display: block;) {
display: @display;
max-width: 100%; // Part 1: Set a maximum relative to the parent
height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching
}
// COMPONENT MIXINS
// --------------------------------------------------
// Horizontal dividers
// -------------------------
// Dividers (basically an hr) within dropdowns and nav lists
.nav-divider(@color: #e5e5e5) {
height: 1px;
margin: ((@line-height-computed / 2) - 1) 0;
overflow: hidden;
background-color: @color;
}
// Panels
// -------------------------
.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border;) {
border-color: @border;
& > .panel-heading {
color: @heading-text-color;
background-color: @heading-bg-color;
border-color: @heading-border;
+ .panel-collapse .panel-body {
border-top-color: @border;
}
}
& > .panel-footer {
+ .panel-collapse .panel-body {
border-bottom-color: @border;
}
}
}
// Alerts
// -------------------------
.alert-variant(@background; @border; @text-color) {
background-color: @background;
border-color: @border;
color: @text-color;
hr {
border-top-color: darken(@border, 5%);
}
.alert-link {
color: darken(@text-color, 10%);
}
}
// Tables
// -------------------------
.table-row-variant(@state; @background; @border) {
// Exact selectors below required to override `.table-striped` and prevent
// inheritance to nested tables.
.table > thead > tr,
.table > tbody > tr,
.table > tfoot > tr {
> td.@{state},
> th.@{state},
&.@{state} > td,
&.@{state} > th {
background-color: @background;
border-color: @border;
}
}
// Hover states for `.table-hover`
// Note: this is not available for cells or rows within `thead` or `tfoot`.
.table-hover > tbody > tr {
> td.@{state}:hover,
> th.@{state}:hover,
&.@{state}:hover > td,
&.@{state}:hover > th {
background-color: darken(@background, 5%);
border-color: darken(@border, 5%);
}
}
}
// Button variants
// -------------------------
// Easily pump out default styles, as well as :hover, :focus, :active,
// and disabled options for all buttons
.button-variant(@color; @background; @border) {
color: @color;
background-color: @background;
border-color: @border;
&:hover,
&:focus,
&:active,
&.active,
.open .dropdown-toggle& {
color: @color;
background-color: darken(@background, 8%);
border-color: darken(@border, 12%);
}
&:active,
&.active,
.open .dropdown-toggle& {
background-image: none;
}
&.disabled,
&[disabled],
fieldset[disabled] & {
&,
&:hover,
&:focus,
&:active,
&.active {
background-color: @background;
border-color: @border;
}
}
}
// Button sizes
// -------------------------
.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {
padding: @padding-vertical @padding-horizontal;
font-size: @font-size;
line-height: @line-height;
border-radius: @border-radius;
}
// Pagination
// -------------------------
.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @border-radius) {
> li {
> a,
> span {
padding: @padding-vertical @padding-horizontal;
font-size: @font-size;
}
&:first-child {
> a,
> span {
.border-left-radius(@border-radius);
}
}
&:last-child {
> a,
> span {
.border-right-radius(@border-radius);
}
}
}
}
// Labels
// -------------------------
.label-variant(@color) {
background-color: @color;
&[href] {
&:hover,
&:focus {
background-color: darken(@color, 10%);
}
}
}
// Navbar vertical align
// -------------------------
// Vertically center elements in the navbar.
// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.
.navbar-vertical-align(@element-height) {
margin-top: ((@navbar-height - @element-height) / 2);
margin-bottom: ((@navbar-height - @element-height) / 2);
}
// Progress bars
// -------------------------
.progress-bar-variant(@color) {
background-color: @color;
.progress-striped & {
#gradient > .striped();
}
}
// Responsive utilities
// -------------------------
// More easily include all the states for responsive-utilities.less.
.responsive-visibility() {
display: block !important;
tr& { display: table-row !important; }
th&,
td& { display: table-cell !important; }
}
.responsive-invisibility() {
&,
tr&,
th&,
td& { display: none !important; }
}
// Grid System
// -----------
// Centered container element
.container-fixed() {
margin-right: auto;
margin-left: auto;
padding-left: (@grid-gutter-width / 2);
padding-right: (@grid-gutter-width / 2);
.clearfix();
}
// Creates a wrapper for a series of columns
.make-row(@gutter: @grid-gutter-width) {
margin-left: (@gutter / -2);
margin-right: (@gutter / -2);
.clearfix();
}
// Generate the extra small columns
.make-xs-column(@columns; @gutter: @grid-gutter-width) {
position: relative;
float: left;
width: percentage((@columns / @grid-columns));
// Prevent columns from collapsing when empty
min-height: 1px;
// Inner gutter via padding
padding-left: (@gutter / 2);
padding-right: (@gutter / 2);
}
// Generate the small columns
.make-sm-column(@columns; @gutter: @grid-gutter-width) {
position: relative;
// Prevent columns from collapsing when empty
min-height: 1px;
// Inner gutter via padding
padding-left: (@gutter / 2);
padding-right: (@gutter / 2);
// Calculate width based on number of columns available
@media (min-width: @screen-sm-min) {
float: left;
width: percentage((@columns / @grid-columns));
}
}
// Generate the small column offsets
.make-sm-column-offset(@columns) {
@media (min-width: @screen-sm-min) {
margin-left: percentage((@columns / @grid-columns));
}
}
.make-sm-column-push(@columns) {
@media (min-width: @screen-sm-min) {
left: percentage((@columns / @grid-columns));
}
}
.make-sm-column-pull(@columns) {
@media (min-width: @screen-sm-min) {
right: percentage((@columns / @grid-columns));
}
}
// Generate the medium columns
.make-md-column(@columns; @gutter: @grid-gutter-width) {
position: relative;
// Prevent columns from collapsing when empty
min-height: 1px;
// Inner gutter via padding
padding-left: (@gutter / 2);
padding-right: (@gutter / 2);
// Calculate width based on number of columns available
@media (min-width: @screen-md-min) {
float: left;
width: percentage((@columns / @grid-columns));
}
}
// Generate the medium column offsets
.make-md-column-offset(@columns) {
@media (min-width: @screen-md-min) {
margin-left: percentage((@columns / @grid-columns));
}
}
.make-md-column-push(@columns) {
@media (min-width: @screen-md) {
left: percentage((@columns / @grid-columns));
}
}
.make-md-column-pull(@columns) {
@media (min-width: @screen-md-min) {
right: percentage((@columns / @grid-columns));
}
}
// Generate the large columns
.make-lg-column(@columns; @gutter: @grid-gutter-width) {
position: relative;
// Prevent columns from collapsing when empty
min-height: 1px;
// Inner gutter via padding
padding-left: (@gutter / 2);
padding-right: (@gutter / 2);
// Calculate width based on number of columns available
@media (min-width: @screen-lg-min) {
float: left;
width: percentage((@columns / @grid-columns));
}
}
// Generate the large column offsets
.make-lg-column-offset(@columns) {
@media (min-width: @screen-lg-min) {
margin-left: percentage((@columns / @grid-columns));
}
}
.make-lg-column-push(@columns) {
@media (min-width: @screen-lg-min) {
left: percentage((@columns / @grid-columns));
}
}
.make-lg-column-pull(@columns) {
@media (min-width: @screen-lg-min) {
right: percentage((@columns / @grid-columns));
}
}
// Framework grid generation
//
// Used only by Bootstrap to generate the correct number of grid classes given
// any value of `@grid-columns`.
.make-grid-columns() {
// Common styles for all sizes of grid columns, widths 1-12
.col(@index) when (@index = 1) { // initial
@item: ~".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}";
.col(@index + 1, @item);
}
.col(@index, @list) when (@index =< @grid-columns) { // general; "=<" isn't a typo
@item: ~".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}";
.col(@index + 1, ~"@{list}, @{item}");
}
.col(@index, @list) when (@index > @grid-columns) { // terminal
@{list} {
position: relative;
// Prevent columns from collapsing when empty
min-height: 1px;
// Inner gutter via padding
padding-left: (@grid-gutter-width / 2);
padding-right: (@grid-gutter-width / 2);
}
}
.col(1); // kickstart it
}
.make-grid-columns-float(@class) {
.col(@index) when (@index = 1) { // initial
@item: ~".col-@{class}-@{index}";
.col(@index + 1, @item);
}
.col(@index, @list) when (@index < @grid-columns) { // general
@item: ~".col-@{class}-@{index}";
.col(@index + 1, ~"@{list}, @{item}");
}
.col(@index, @list) when (@index = @grid-columns) { // terminal
@{list} {
float: left;
}
}
.col(1); // kickstart it
}
.calc-grid(@index, @class, @type) when (@type = width) {
.col-@{class}-@{index} {
width: percentage((@index / @grid-columns));
}
}
.calc-grid(@index, @class, @type) when (@type = push) {
.col-@{class}-push-@{index} {
left: percentage((@index / @grid-columns));
}
}
.calc-grid(@index, @class, @type) when (@type = pull) {
.col-@{class}-pull-@{index} {
right: percentage((@index / @grid-columns));
}
}
.calc-grid(@index, @class, @type) when (@type = offset) {
.col-@{class}-offset-@{index} {
margin-left: percentage((@index / @grid-columns));
}
}
// Basic looping in LESS
.make-grid(@index, @class, @type) when (@index > 0) {
.calc-grid(@index, @class, @type);
// next iteration
.make-grid(@index - 1, @class, @type);
}
// Form validation states
//
// Used in forms.less to generate the form validation CSS for warnings, errors,
// and successes.
.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) {
// Color the label and help text
.help-block,
.control-label {
color: @text-color;
}
// Set the border and box shadow on specific inputs to match
.form-control {
border-color: @border-color;
.box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work
&:focus {
border-color: darken(@border-color, 10%);
@shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%);
.box-shadow(@shadow);
}
}
// Set validation states also for addons
.input-group-addon {
color: @text-color;
border-color: @border-color;
background-color: @background-color;
}
}
// Form control focus state
//
// Generate a customized focus state and for any input with the specified color,
// which defaults to the `@input-focus-border` variable.
//
// We highly encourage you to not customize the default value, but instead use
// this to tweak colors on an as-needed basis. This aesthetic change is based on
// WebKit's default styles, but applicable to a wider range of browsers. Its
// usability and accessibility should be taken into account with any change.
//
// Example usage: change the default blue border and shadow to white for better
// contrast against a dark gray background.
.form-control-focus(@color: @input-border-focus) {
@color-rgba: rgba(red(@color), green(@color), blue(@color), .6);
&:focus {
border-color: @color;
outline: 0;
.box-shadow(~"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}");
}
}
// Form control sizing
//
// Relative text size, padding, and border-radii changes for form controls. For
// horizontal sizing, wrap controls in the predefined grid classes. `<select>`
// element gets special love because it's special, and that's a fact!
.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {
height: @input-height;
padding: @padding-vertical @padding-horizontal;
font-size: @font-size;
line-height: @line-height;
border-radius: @border-radius;
select& {
height: @input-height;
line-height: @input-height;
}
textarea& {
height: auto;
}
}

View File

@ -0,0 +1,131 @@
//
// Modals
// --------------------------------------------------
// .modal-open - body class for killing the scroll
// .modal - container to scroll within
// .modal-dialog - positioning shell for the actual modal
// .modal-content - actual modal w/ bg and corners and shit
// Kill the scroll on the body
.modal-open {
overflow: hidden;
}
// Container that the modal scrolls within
.modal {
display: none;
overflow: auto;
overflow-y: scroll;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: @zindex-modal-background;
// When fading in the modal, animate it to slide down
&.fade .modal-dialog {
.translate(0, -25%);
.transition-transform(~"0.3s ease-out");
}
&.in .modal-dialog { .translate(0, 0)}
}
// Shell div to position the modal with bottom padding
.modal-dialog {
margin-left: auto;
margin-right: auto;
width: auto;
padding: 10px;
z-index: (@zindex-modal-background + 10);
}
// Actual modal
.modal-content {
position: relative;
background-color: @modal-content-bg;
border: 1px solid @modal-content-fallback-border-color; //old browsers fallback (ie8 etc)
border: 1px solid @modal-content-border-color;
border-radius: @border-radius-large;
.box-shadow(0 3px 9px rgba(0,0,0,.5));
background-clip: padding-box;
// Remove focus outline from opened modal
outline: none;
}
// Modal background
.modal-backdrop {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: (@zindex-modal-background - 10);
background-color: @modal-backdrop-bg;
// Fade for backdrop
&.fade { .opacity(0); }
&.in { .opacity(.5); }
}
// Modal header
// Top section of the modal w/ title and dismiss
.modal-header {
padding: @modal-title-padding;
border-bottom: 1px solid @modal-header-border-color;
min-height: (@modal-title-padding + @modal-title-line-height);
}
// Close icon
.modal-header .close {
margin-top: -2px;
}
// Title text within header
.modal-title {
margin: 0;
line-height: @modal-title-line-height;
}
// Modal body
// Where all modal content resides (sibling of .modal-header and .modal-footer)
.modal-body {
position: relative;
padding: @modal-inner-padding;
}
// Footer (for actions)
.modal-footer {
margin-top: 15px;
padding: (@modal-inner-padding - 1) @modal-inner-padding @modal-inner-padding;
text-align: right; // right align buttons
border-top: 1px solid @modal-footer-border-color;
.clearfix(); // clear it in case folks use .pull-* classes on buttons
// Properly space out buttons
.btn + .btn {
margin-left: 5px;
margin-bottom: 0; // account for input[type="submit"] which gets the bottom margin like all other inputs
}
// but override that for button groups
.btn-group .btn + .btn {
margin-left: -1px;
}
// and override it for block buttons as well
.btn-block + .btn-block {
margin-left: 0;
}
}
// Scale up the modal
@media screen and (min-width: @screen-sm-min) {
.modal-dialog {
width: 600px;
padding-top: 30px;
padding-bottom: 30px;
}
.modal-content {
.box-shadow(0 5px 15px rgba(0,0,0,.5));
}
}

View File

@ -0,0 +1,621 @@
//
// Navbars
// --------------------------------------------------
// Wrapper and base class
//
// Provide a static navbar from which we expand to create full-width, fixed, and
// other navbar variations.
.navbar {
position: relative;
z-index: @zindex-navbar;
min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)
margin-bottom: @navbar-margin-bottom;
border: 1px solid transparent;
// Prevent floats from breaking the navbar
.clearfix();
@media (min-width: @grid-float-breakpoint) {
border-radius: @navbar-border-radius;
}
}
// Navbar heading
//
// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy
// styling of responsive aspects.
.navbar-header {
.clearfix();
@media (min-width: @grid-float-breakpoint) {
float: left;
}
}
// Navbar collapse (body)
//
// Group your navbar content into this for easy collapsing and expanding across
// various device sizes. By default, this content is collapsed when <768px, but
// will expand past that for a horizontal display.
//
// To start (on mobile devices) the navbar links, forms, and buttons are stacked
// vertically and include a `max-height` to overflow in case you have too much
// content for the user's viewport.
.navbar-collapse {
max-height: 340px;
overflow-x: visible;
padding-right: @navbar-padding-horizontal;
padding-left: @navbar-padding-horizontal;
border-top: 1px solid transparent;
box-shadow: inset 0 1px 0 rgba(255,255,255,.1);
.clearfix();
-webkit-overflow-scrolling: touch;
&.in {
overflow-y: auto;
}
@media (min-width: @grid-float-breakpoint) {
width: auto;
border-top: 0;
box-shadow: none;
&.collapse {
display: block !important;
height: auto !important;
padding-bottom: 0; // Override default setting
overflow: visible !important;
}
&.in {
overflow-y: visible;
}
// Account for first and last children spacing
.navbar-nav.navbar-left:first-child {
margin-left: -@navbar-padding-horizontal;
}
.navbar-nav.navbar-right:last-child {
margin-right: -@navbar-padding-horizontal;
}
.navbar-text:last-child {
margin-right: 0;
}
}
}
// Both navbar header and collapse
//
// When a container is present, change the behavior of the header and collapse.
.container > .navbar-header,
.container > .navbar-collapse {
margin-right: -@navbar-padding-horizontal;
margin-left: -@navbar-padding-horizontal;
@media (min-width: @grid-float-breakpoint) {
margin-right: 0;
margin-left: 0;
}
}
//
// Navbar alignment options
//
// Display the navbar across the entirity of the page or fixed it to the top or
// bottom of the page.
// Static top (unfixed, but 100% wide) navbar
.navbar-static-top {
border-width: 0 0 1px;
@media (min-width: @grid-float-breakpoint) {
border-radius: 0;
}
}
// Fix the top/bottom navbars when screen real estate supports it
.navbar-fixed-top,
.navbar-fixed-bottom {
position: fixed;
right: 0;
left: 0;
border-width: 0 0 1px;
// Undo the rounded corners
@media (min-width: @grid-float-breakpoint) {
border-radius: 0;
}
}
.navbar-fixed-top {
z-index: @zindex-navbar-fixed;
top: 0;
}
.navbar-fixed-bottom {
bottom: 0;
margin-bottom: 0; // override .navbar defaults
}
// Brand/project name
.navbar-brand {
float: left;
padding: @navbar-padding-vertical @navbar-padding-horizontal;
font-size: @font-size-large;
line-height: @line-height-computed;
&:hover,
&:focus {
text-decoration: none;
}
@media (min-width: @grid-float-breakpoint) {
.navbar > .container & {
margin-left: -@navbar-padding-horizontal;
}
}
}
// Navbar toggle
//
// Custom button for toggling the `.navbar-collapse`, powered by the collapse
// JavaScript plugin.
.navbar-toggle {
position: relative;
float: right;
margin-right: @navbar-padding-horizontal;
padding: 9px 10px;
.navbar-vertical-align(34px);
background-color: transparent;
border: 1px solid transparent;
border-radius: @border-radius-base;
// Bars
.icon-bar {
display: block;
width: 22px;
height: 2px;
border-radius: 1px;
}
.icon-bar + .icon-bar {
margin-top: 4px;
}
@media (min-width: @grid-float-breakpoint) {
display: none;
}
}
// Navbar nav links
//
// Builds on top of the `.nav` components with it's own modifier class to make
// the nav the full height of the horizontal nav (above 768px).
.navbar-nav {
margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;
> li > a {
padding-top: 10px;
padding-bottom: 10px;
line-height: @line-height-computed;
}
@media (max-width: @screen-xs-max) {
// Dropdowns get custom display when collapsed
.open .dropdown-menu {
position: static;
float: none;
width: auto;
margin-top: 0;
background-color: transparent;
border: 0;
box-shadow: none;
> li > a,
.dropdown-header {
padding: 5px 15px 5px 25px;
}
> li > a {
line-height: @line-height-computed;
&:hover,
&:focus {
background-image: none;
}
}
}
}
// Uncollapse the nav
@media (min-width: @grid-float-breakpoint) {
float: left;
margin: 0;
> li {
float: left;
> a {
padding-top: ((@navbar-height - @line-height-computed) / 2);
padding-bottom: ((@navbar-height - @line-height-computed) / 2);
}
}
}
}
// Component alignment
//
// Repurpose the pull utilities as their own navbar utilities to avoid specifity
// issues with parents and chaining. Only do this when the navbar is uncollapsed
// though so that navbar contents properly stack and align in mobile.
@media (min-width: @grid-float-breakpoint) {
.navbar-left { .pull-left(); }
.navbar-right { .pull-right(); }
}
// Navbar form
//
// Extension of the `.form-inline` with some extra flavor for optimum display in
// our navbars.
.navbar-form {
margin-left: -@navbar-padding-horizontal;
margin-right: -@navbar-padding-horizontal;
padding: 10px @navbar-padding-horizontal;
border-top: 1px solid transparent;
border-bottom: 1px solid transparent;
@shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);
.box-shadow(@shadow);
// Mixin behavior for optimum display
.form-inline();
.form-group {
@media (max-width: @screen-xs-max) {
margin-bottom: 5px;
}
}
// Vertically center in expanded, horizontal navbar
.navbar-vertical-align(@input-height-base);
// Undo 100% width for pull classes
@media (min-width: @grid-float-breakpoint) {
width: auto;
border: 0;
margin-left: 0;
margin-right: 0;
padding-top: 0;
padding-bottom: 0;
.box-shadow(none);
}
}
// Dropdown menus
// Menu position and menu carets
.navbar-nav > li > .dropdown-menu {
margin-top: 0;
.border-top-radius(0);
}
// Menu position and menu caret support for dropups via extra dropup class
.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {
.border-bottom-radius(0);
}
// Right aligned menus need alt position
.navbar-nav.pull-right > li > .dropdown-menu,
.navbar-nav > li > .dropdown-menu.pull-right {
left: auto;
right: 0;
}
// Buttons in navbars
//
// Vertically center a button within a navbar (when *not* in a form).
.navbar-btn {
.navbar-vertical-align(@input-height-base);
}
// Text in navbars
//
// Add a class to make any element properly align itself vertically within the navbars.
.navbar-text {
float: left;
.navbar-vertical-align(@line-height-computed);
@media (min-width: @grid-float-breakpoint) {
margin-left: @navbar-padding-horizontal;
margin-right: @navbar-padding-horizontal;
}
}
// Alternate navbars
// --------------------------------------------------
// Default navbar
.navbar-default {
background-color: @navbar-default-bg;
border-color: @navbar-default-border;
.navbar-brand {
color: @navbar-default-brand-color;
&:hover,
&:focus {
color: @navbar-default-brand-hover-color;
background-color: @navbar-default-brand-hover-bg;
}
}
.navbar-text {
color: @navbar-default-color;
}
.navbar-nav {
> li > a {
color: @navbar-default-link-color;
&:hover,
&:focus {
color: @navbar-default-link-hover-color;
background-color: @navbar-default-link-hover-bg;
}
}
> .active > a {
&,
&:hover,
&:focus {
color: @navbar-default-link-active-color;
background-color: @navbar-default-link-active-bg;
}
}
> .disabled > a {
&,
&:hover,
&:focus {
color: @navbar-default-link-disabled-color;
background-color: @navbar-default-link-disabled-bg;
}
}
}
.navbar-toggle {
border-color: @navbar-default-toggle-border-color;
&:hover,
&:focus {
background-color: @navbar-default-toggle-hover-bg;
}
.icon-bar {
background-color: @navbar-default-toggle-icon-bar-bg;
}
}
.navbar-collapse,
.navbar-form {
border-color: @navbar-default-border;
}
// Dropdown menu items and carets
.navbar-nav {
// Caret should match text color on hover
> .dropdown > a:hover .caret,
> .dropdown > a:focus .caret {
border-top-color: @navbar-default-link-hover-color;
border-bottom-color: @navbar-default-link-hover-color;
}
// Remove background color from open dropdown
> .open > a {
&,
&:hover,
&:focus {
background-color: @navbar-default-link-active-bg;
color: @navbar-default-link-active-color;
.caret {
border-top-color: @navbar-default-link-active-color;
border-bottom-color: @navbar-default-link-active-color;
}
}
}
> .dropdown > a .caret {
border-top-color: @navbar-default-link-color;
border-bottom-color: @navbar-default-link-color;
}
@media (max-width: @screen-xs-max) {
// Dropdowns get custom display when collapsed
.open .dropdown-menu {
> li > a {
color: @navbar-default-link-color;
&:hover,
&:focus {
color: @navbar-default-link-hover-color;
background-color: @navbar-default-link-hover-bg;
}
}
> .active > a {
&,
&:hover,
&:focus {
color: @navbar-default-link-active-color;
background-color: @navbar-default-link-active-bg;
}
}
> .disabled > a {
&,
&:hover,
&:focus {
color: @navbar-default-link-disabled-color;
background-color: @navbar-default-link-disabled-bg;
}
}
}
}
}
// Links in navbars
//
// Add a class to ensure links outside the navbar nav are colored correctly.
.navbar-link {
color: @navbar-default-link-color;
&:hover {
color: @navbar-default-link-hover-color;
}
}
}
// Inverse navbar
.navbar-inverse {
background-color: @navbar-inverse-bg;
border-color: @navbar-inverse-border;
.navbar-brand {
color: @navbar-inverse-brand-color;
&:hover,
&:focus {
color: @navbar-inverse-brand-hover-color;
background-color: @navbar-inverse-brand-hover-bg;
}
}
.navbar-text {
color: @navbar-inverse-color;
}
.navbar-nav {
> li > a {
color: @navbar-inverse-link-color;
&:hover,
&:focus {
color: @navbar-inverse-link-hover-color;
background-color: @navbar-inverse-link-hover-bg;
}
}
> .active > a {
&,
&:hover,
&:focus {
color: @navbar-inverse-link-active-color;
background-color: @navbar-inverse-link-active-bg;
}
}
> .disabled > a {
&,
&:hover,
&:focus {
color: @navbar-inverse-link-disabled-color;
background-color: @navbar-inverse-link-disabled-bg;
}
}
}
// Darken the responsive nav toggle
.navbar-toggle {
border-color: @navbar-inverse-toggle-border-color;
&:hover,
&:focus {
background-color: @navbar-inverse-toggle-hover-bg;
}
.icon-bar {
background-color: @navbar-inverse-toggle-icon-bar-bg;
}
}
.navbar-collapse,
.navbar-form {
border-color: darken(@navbar-inverse-bg, 7%);
}
// Dropdowns
.navbar-nav {
> .open > a {
&,
&:hover,
&:focus {
background-color: @navbar-inverse-link-active-bg;
color: @navbar-inverse-link-active-color;
}
}
> .dropdown > a:hover .caret {
border-top-color: @navbar-inverse-link-hover-color;
border-bottom-color: @navbar-inverse-link-hover-color;
}
> .dropdown > a .caret {
border-top-color: @navbar-inverse-link-color;
border-bottom-color: @navbar-inverse-link-color;
}
> .open > a {
&,
&:hover,
&:focus {
.caret {
border-top-color: @navbar-inverse-link-active-color;
border-bottom-color: @navbar-inverse-link-active-color;
}
}
}
@media (max-width: @screen-xs-max) {
// Dropdowns get custom display
.open .dropdown-menu {
> .dropdown-header {
border-color: @navbar-inverse-border;
}
> li > a {
color: @navbar-inverse-link-color;
&:hover,
&:focus {
color: @navbar-inverse-link-hover-color;
background-color: @navbar-inverse-link-hover-bg;
}
}
> .active > a {
&,
&:hover,
&:focus {
color: @navbar-inverse-link-active-color;
background-color: @navbar-inverse-link-active-bg;
}
}
> .disabled > a {
&,
&:hover,
&:focus {
color: @navbar-inverse-link-disabled-color;
background-color: @navbar-inverse-link-disabled-bg;
}
}
}
}
}
.navbar-link {
color: @navbar-inverse-link-color;
&:hover {
color: @navbar-inverse-link-hover-color;
}
}
}

257
styles/bootstrap/navs.less Normal file
View File

@ -0,0 +1,257 @@
//
// Navs
// --------------------------------------------------
// Base class
// --------------------------------------------------
.nav {
margin-bottom: 0;
padding-left: 0; // Override default ul/ol
list-style: none;
.clearfix();
> li {
position: relative;
display: block;
> a {
position: relative;
display: block;
padding: @nav-link-padding;
&:hover,
&:focus {
text-decoration: none;
background-color: @nav-link-hover-bg;
}
}
// Disabled state sets text to gray and nukes hover/tab effects
&.disabled > a {
color: @nav-disabled-link-color;
&:hover,
&:focus {
color: @nav-disabled-link-hover-color;
text-decoration: none;
background-color: transparent;
cursor: not-allowed;
}
}
}
// Open dropdowns
.open > a {
&,
&:hover,
&:focus {
background-color: @nav-link-hover-bg;
border-color: @link-color;
.caret {
border-top-color: @link-hover-color;
border-bottom-color: @link-hover-color;
}
}
}
// Nav dividers (deprecated with v3.0.1)
//
// This should have been removed in v3 with the dropping of `.nav-list`, but
// we missed it. We don't currently support this anywhere, but in the interest
// of maintaining backward compatibility in case you use it, it's deprecated.
.nav-divider {
.nav-divider();
}
// Prevent IE8 from misplacing imgs
//
// See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989
> li > a > img {
max-width: none;
}
}
// Tabs
// -------------------------
// Give the tabs something to sit on
.nav-tabs {
border-bottom: 1px solid @nav-tabs-border-color;
> li {
float: left;
// Make the list-items overlay the bottom border
margin-bottom: -1px;
// Actual tabs (as links)
> a {
margin-right: 2px;
line-height: @line-height-base;
border: 1px solid transparent;
border-radius: @border-radius-base @border-radius-base 0 0;
&:hover {
border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;
}
}
// Active state, and it's :hover to override normal :hover
&.active > a {
&,
&:hover,
&:focus {
color: @nav-tabs-active-link-hover-color;
background-color: @nav-tabs-active-link-hover-bg;
border: 1px solid @nav-tabs-active-link-hover-border-color;
border-bottom-color: transparent;
cursor: default;
}
}
}
// pulling this in mainly for less shorthand
&.nav-justified {
.nav-justified();
.nav-tabs-justified();
}
}
// Pills
// -------------------------
.nav-pills {
> li {
float: left;
// Links rendered as pills
> a {
border-radius: @nav-pills-border-radius;
}
+ li {
margin-left: 2px;
}
// Active state
&.active > a {
&,
&:hover,
&:focus {
color: @nav-pills-active-link-hover-color;
background-color: @nav-pills-active-link-hover-bg;
.caret {
border-top-color: @nav-pills-active-link-hover-color;
border-bottom-color: @nav-pills-active-link-hover-color;
}
}
}
}
}
// Stacked pills
.nav-stacked {
> li {
float: none;
+ li {
margin-top: 2px;
margin-left: 0; // no need for this gap between nav items
}
}
}
// Nav variations
// --------------------------------------------------
// Justified nav links
// -------------------------
.nav-justified {
width: 100%;
> li {
float: none;
> a {
text-align: center;
margin-bottom: 5px;
}
}
@media (min-width: @screen-sm-min) {
> li {
display: table-cell;
width: 1%;
> a {
margin-bottom: 0;
}
}
}
}
// Move borders to anchors instead of bottom of list
//
// Mixin for adding on top the shared `.nav-justified` styles for our tabs
.nav-tabs-justified {
border-bottom: 0;
> li > a {
// Override margin from .nav-tabs
margin-right: 0;
border-radius: @border-radius-base;
}
> .active > a,
> .active > a:hover,
> .active > a:focus {
border: 1px solid @nav-tabs-justified-link-border-color;
}
@media (min-width: @screen-sm-min) {
> li > a {
border-bottom: 1px solid @nav-tabs-justified-link-border-color;
border-radius: @border-radius-base @border-radius-base 0 0;
}
> .active > a,
> .active > a:hover,
> .active > a:focus {
border-bottom-color: @nav-tabs-justified-active-link-border-color;
}
}
}
// Tabbable tabs
// -------------------------
// Hide tabbable panes to start, show them when `.active`
.tab-content {
> .tab-pane {
display: none;
}
> .active {
display: block;
}
}
// Dropdowns
// -------------------------
// Make dropdown carets use link color in navs
.nav .caret {
border-top-color: @link-color;
border-bottom-color: @link-color;
}
.nav a:hover .caret {
border-top-color: @link-hover-color;
border-bottom-color: @link-hover-color;
}
// Specific dropdowns
.nav-tabs .dropdown-menu {
// make dropdown border overlap tab border
margin-top: -1px;
// Remove the top rounded corners here since there is a hard edge above the menu
.border-top-radius(0);
}

406
styles/bootstrap/normalize.less vendored Normal file
View File

@ -0,0 +1,406 @@
/*! normalize.css v2.1.3 | MIT License | git.io/normalize */
// ==========================================================================
// HTML5 display definitions
// ==========================================================================
//
// Correct `block` display not defined in IE 8/9.
//
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
nav,
section,
summary {
display: block;
}
//
// Correct `inline-block` display not defined in IE 8/9.
//
audio,
canvas,
video {
display: inline-block;
}
//
// Prevent modern browsers from displaying `audio` without controls.
// Remove excess height in iOS 5 devices.
//
audio:not([controls]) {
display: none;
height: 0;
}
//
// Address `[hidden]` styling not present in IE 8/9.
// Hide the `template` element in IE, Safari, and Firefox < 22.
//
[hidden],
template {
display: none;
}
// ==========================================================================
// Base
// ==========================================================================
//
// 1. Set default font family to sans-serif.
// 2. Prevent iOS text size adjust after orientation change, without disabling
// user zoom.
//
html {
font-family: sans-serif; // 1
-ms-text-size-adjust: 100%; // 2
-webkit-text-size-adjust: 100%; // 2
}
//
// Remove default margin.
//
body {
margin: 0;
}
// ==========================================================================
// Links
// ==========================================================================
//
// Remove the gray background color from active links in IE 10.
//
a {
background: transparent;
}
//
// Address `outline` inconsistency between Chrome and other browsers.
//
a:focus {
outline: thin dotted;
}
//
// Improve readability when focused and also mouse hovered in all browsers.
//
a:active,
a:hover {
outline: 0;
}
// ==========================================================================
// Typography
// ==========================================================================
//
// Address variable `h1` font-size and margin within `section` and `article`
// contexts in Firefox 4+, Safari 5, and Chrome.
//
h1 {
font-size: 2em;
margin: 0.67em 0;
}
//
// Address styling not present in IE 8/9, Safari 5, and Chrome.
//
abbr[title] {
border-bottom: 1px dotted;
}
//
// Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
//
b,
strong {
font-weight: bold;
}
//
// Address styling not present in Safari 5 and Chrome.
//
dfn {
font-style: italic;
}
//
// Address differences between Firefox and other browsers.
//
hr {
-moz-box-sizing: content-box;
box-sizing: content-box;
height: 0;
}
//
// Address styling not present in IE 8/9.
//
mark {
background: #ff0;
color: #000;
}
//
// Correct font family set oddly in Safari 5 and Chrome.
//
code,
kbd,
pre,
samp {
font-family: monospace, serif;
font-size: 1em;
}
//
// Improve readability of pre-formatted text in all browsers.
//
pre {
white-space: pre-wrap;
}
//
// Set consistent quote types.
//
q {
quotes: "\201C" "\201D" "\2018" "\2019";
}
//
// Address inconsistent and variable font size in all browsers.
//
small {
font-size: 80%;
}
//
// Prevent `sub` and `sup` affecting `line-height` in all browsers.
//
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
// ==========================================================================
// Embedded content
// ==========================================================================
//
// Remove border when inside `a` element in IE 8/9.
//
img {
border: 0;
}
//
// Correct overflow displayed oddly in IE 9.
//
svg:not(:root) {
overflow: hidden;
}
// ==========================================================================
// Figures
// ==========================================================================
//
// Address margin not present in IE 8/9 and Safari 5.
//
figure {
margin: 0;
}
// ==========================================================================
// Forms
// ==========================================================================
//
// Define consistent border, margin, and padding.
//
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
//
// 1. Correct `color` not being inherited in IE 8/9.
// 2. Remove padding so people aren't caught out if they zero out fieldsets.
//
legend {
border: 0; // 1
padding: 0; // 2
}
//
// 1. Correct font family not being inherited in all browsers.
// 2. Correct font size not being inherited in all browsers.
// 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
//
button,
input,
select,
textarea {
font-family: inherit; // 1
font-size: 100%; // 2
margin: 0; // 3
}
//
// Address Firefox 4+ setting `line-height` on `input` using `!important` in
// the UA stylesheet.
//
button,
input {
line-height: normal;
}
//
// Address inconsistent `text-transform` inheritance for `button` and `select`.
// All other form control elements do not inherit `text-transform` values.
// Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.
// Correct `select` style inheritance in Firefox 4+ and Opera.
//
button,
select {
text-transform: none;
}
//
// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
// and `video` controls.
// 2. Correct inability to style clickable `input` types in iOS.
// 3. Improve usability and consistency of cursor style between image-type
// `input` and others.
//
button,
html input[type="button"], // 1
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; // 2
cursor: pointer; // 3
}
//
// Re-set default cursor for disabled elements.
//
button[disabled],
html input[disabled] {
cursor: default;
}
//
// 1. Address box sizing set to `content-box` in IE 8/9/10.
// 2. Remove excess padding in IE 8/9/10.
//
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; // 1
padding: 0; // 2
}
//
// 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
// 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
// (include `-moz` to future-proof).
//
input[type="search"] {
-webkit-appearance: textfield; // 1
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; // 2
box-sizing: content-box;
}
//
// Remove inner padding and search cancel button in Safari 5 and Chrome
// on OS X.
//
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
//
// Remove inner padding and border in Firefox 4+.
//
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
//
// 1. Remove default vertical scrollbar in IE 8/9.
// 2. Improve readability and alignment in all browsers.
//
textarea {
overflow: auto; // 1
vertical-align: top; // 2
}
// ==========================================================================
// Tables
// ==========================================================================
//
// Remove most spacing between table cells.
//
table {
border-collapse: collapse;
border-spacing: 0;
}

View File

@ -0,0 +1,55 @@
//
// Pager pagination
// --------------------------------------------------
.pager {
padding-left: 0;
margin: @line-height-computed 0;
list-style: none;
text-align: center;
.clearfix();
li {
display: inline;
> a,
> span {
display: inline-block;
padding: 5px 14px;
background-color: @pagination-bg;
border: 1px solid @pagination-border;
border-radius: @pager-border-radius;
}
> a:hover,
> a:focus {
text-decoration: none;
background-color: @pagination-hover-bg;
}
}
.next {
> a,
> span {
float: right;
}
}
.previous {
> a,
> span {
float: left;
}
}
.disabled {
> a,
> a:hover,
> a:focus,
> span {
color: @pager-disabled-color;
background-color: @pagination-bg;
cursor: not-allowed;
}
}
}

View File

@ -0,0 +1,85 @@
//
// Pagination (multiple pages)
// --------------------------------------------------
.pagination {
display: inline-block;
padding-left: 0;
margin: @line-height-computed 0;
border-radius: @border-radius-base;
> li {
display: inline; // Remove list-style and block-level defaults
> a,
> span {
position: relative;
float: left; // Collapse white-space
padding: @padding-base-vertical @padding-base-horizontal;
line-height: @line-height-base;
text-decoration: none;
background-color: @pagination-bg;
border: 1px solid @pagination-border;
margin-left: -1px;
}
&:first-child {
> a,
> span {
margin-left: 0;
.border-left-radius(@border-radius-base);
}
}
&:last-child {
> a,
> span {
.border-right-radius(@border-radius-base);
}
}
}
> li > a,
> li > span {
&:hover,
&:focus {
background-color: @pagination-hover-bg;
}
}
> .active > a,
> .active > span {
&,
&:hover,
&:focus {
z-index: 2;
color: @pagination-active-color;
background-color: @pagination-active-bg;
border-color: @pagination-active-bg;
cursor: default;
}
}
> .disabled {
> span,
> span:hover,
> span:focus,
> a,
> a:hover,
> a:focus {
color: @pagination-disabled-color;
background-color: @pagination-bg;
border-color: @pagination-border;
cursor: not-allowed;
}
}
}
// Sizing
// --------------------------------------------------
// Large
.pagination-lg {
.pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @border-radius-large);
}
// Small
.pagination-sm {
.pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @border-radius-small);
}

View File

@ -0,0 +1,168 @@
//
// Panels
// --------------------------------------------------
// Base class
.panel {
margin-bottom: @line-height-computed;
background-color: @panel-bg;
border: 1px solid transparent;
border-radius: @panel-border-radius;
.box-shadow(0 1px 1px rgba(0,0,0,.05));
}
// Panel contents
.panel-body {
padding: 15px;
.clearfix();
}
// List groups in panels
//
// By default, space out list group content from panel headings to account for
// any kind of custom content between the two.
.panel {
> .list-group {
margin-bottom: 0;
.list-group-item {
border-width: 1px 0;
// Remove border radius for top one
&:first-child {
.border-top-radius(0);
}
// But keep it for the last one
&:last-child {
border-bottom: 0;
}
}
}
}
// Collapse space between when there's no additional content.
.panel-heading + .list-group {
.list-group-item:first-child {
border-top-width: 0;
}
}
// Tables in panels
//
// Place a non-bordered `.table` within a panel (not within a `.panel-body`) and
// watch it go full width.
.panel {
> .table,
> .table-responsive {
margin-bottom: 0;
}
> .panel-body + .table,
> .panel-body + .table-responsive {
border-top: 1px solid @table-border-color;
}
> .table-bordered,
> .table-responsive > .table-bordered {
border: 0;
> thead,
> tbody,
> tfoot {
> tr {
> th:first-child,
> td:first-child {
border-left: 0;
}
> th:last-child,
> td:last-child {
border-right: 0;
}
&:last-child > th,
&:last-child > td {
border-bottom: 0;
}
}
}
}
}
// Optional heading
.panel-heading {
padding: 10px 15px;
border-bottom: 1px solid transparent;
.border-top-radius(@panel-border-radius - 1);
}
// Within heading, strip any `h*` tag of it's default margins for spacing.
.panel-title {
margin-top: 0;
margin-bottom: 0;
font-size: ceil((@font-size-base * 1.125));
> a {
color: inherit;
}
}
// Optional footer (stays gray in every modifier class)
.panel-footer {
padding: 10px 15px;
background-color: @panel-footer-bg;
border-top: 1px solid @panel-inner-border;
.border-bottom-radius(@panel-border-radius - 1);
}
// Collapsable panels (aka, accordion)
//
// Wrap a series of panels in `.panel-group` to turn them into an accordion with
// the help of our collapse JavaScript plugin.
.panel-group {
// Tighten up margin so it's only between panels
.panel {
margin-bottom: 0;
border-radius: @panel-border-radius;
overflow: hidden; // crop contents when collapsed
+ .panel {
margin-top: 5px;
}
}
.panel-heading {
border-bottom: 0;
+ .panel-collapse .panel-body {
border-top: 1px solid @panel-inner-border;
}
}
.panel-footer {
border-top: 0;
+ .panel-collapse .panel-body {
border-bottom: 1px solid @panel-inner-border;
}
}
}
// Contextual variations
.panel-default {
.panel-variant(@panel-default-border; @panel-default-text; @panel-default-heading-bg; @panel-default-border);
}
.panel-primary {
.panel-variant(@panel-primary-border; @panel-primary-text; @panel-primary-heading-bg; @panel-primary-border);
}
.panel-success {
.panel-variant(@panel-success-border; @panel-success-text; @panel-success-heading-bg; @panel-success-border);
}
.panel-warning {
.panel-variant(@panel-warning-border; @panel-warning-text; @panel-warning-heading-bg; @panel-warning-border);
}
.panel-danger {
.panel-variant(@panel-danger-border; @panel-danger-text; @panel-danger-heading-bg; @panel-danger-border);
}
.panel-info {
.panel-variant(@panel-info-border; @panel-info-text; @panel-info-heading-bg; @panel-info-border);
}

View File

@ -0,0 +1,132 @@
//
// Popovers
// --------------------------------------------------
.popover {
position: absolute;
top: 0;
left: 0;
z-index: @zindex-popover;
display: none;
padding: 1px;
text-align: left; // Reset given new insertion method
background-color: @popover-bg;
background-clip: padding-box;
border: 1px solid @popover-fallback-border-color;
border: 1px solid @popover-border-color;
border-radius: @border-radius-large;
.box-shadow(0 5px 10px rgba(0,0,0,.2));
// Overrides for proper insertion
white-space: normal;
// Offset the popover to account for the popover arrow
&.top { margin-top: -10px; }
&.right { margin-left: 10px; }
&.bottom { margin-top: 10px; }
&.left { margin-left: -10px; }
}
.popover-title {
margin: 0; // reset heading margin
padding: 8px 14px;
font-size: @font-size-base;
font-weight: normal;
line-height: 18px;
background-color: @popover-title-bg;
border-bottom: 1px solid darken(@popover-title-bg, 5%);
border-radius: 5px 5px 0 0;
}
.popover-content {
padding: 9px 14px;
}
// Arrows
//
// .arrow is outer, .arrow:after is inner
.popover .arrow {
&,
&:after {
position: absolute;
display: block;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
}
}
.popover .arrow {
border-width: @popover-arrow-outer-width;
}
.popover .arrow:after {
border-width: @popover-arrow-width;
content: "";
}
.popover {
&.top .arrow {
left: 50%;
margin-left: -@popover-arrow-outer-width;
border-bottom-width: 0;
border-top-color: @popover-arrow-outer-fallback-color; // IE8 fallback
border-top-color: @popover-arrow-outer-color;
bottom: -@popover-arrow-outer-width;
&:after {
content: " ";
bottom: 1px;
margin-left: -@popover-arrow-width;
border-bottom-width: 0;
border-top-color: @popover-arrow-color;
}
}
&.right .arrow {
top: 50%;
left: -@popover-arrow-outer-width;
margin-top: -@popover-arrow-outer-width;
border-left-width: 0;
border-right-color: @popover-arrow-outer-fallback-color; // IE8 fallback
border-right-color: @popover-arrow-outer-color;
&:after {
content: " ";
left: 1px;
bottom: -@popover-arrow-width;
border-left-width: 0;
border-right-color: @popover-arrow-color;
}
}
&.bottom .arrow {
left: 50%;
margin-left: -@popover-arrow-outer-width;
border-top-width: 0;
border-bottom-color: @popover-arrow-outer-fallback-color; // IE8 fallback
border-bottom-color: @popover-arrow-outer-color;
top: -@popover-arrow-outer-width;
&:after {
content: " ";
top: 1px;
margin-left: -@popover-arrow-width;
border-top-width: 0;
border-bottom-color: @popover-arrow-color;
}
}
&.left .arrow {
top: 50%;
right: -@popover-arrow-outer-width;
margin-top: -@popover-arrow-outer-width;
border-right-width: 0;
border-left-color: @popover-arrow-outer-fallback-color; // IE8 fallback
border-left-color: @popover-arrow-outer-color;
&:after {
content: " ";
right: 1px;
border-right-width: 0;
border-left-color: @popover-arrow-color;
bottom: -@popover-arrow-width;
}
}
}

100
styles/bootstrap/print.less Normal file
View File

@ -0,0 +1,100 @@
//
// Basic print styles
// --------------------------------------------------
// Source: https://github.com/h5bp/html5-boilerplate/blob/master/css/main.css
@media print {
* {
text-shadow: none !important;
color: #000 !important; // Black prints faster: h5bp.com/s
background: transparent !important;
box-shadow: none !important;
}
a,
a:visited {
text-decoration: underline;
}
a[href]:after {
content: " (" attr(href) ")";
}
abbr[title]:after {
content: " (" attr(title) ")";
}
// Don't show links for images, or javascript/internal links
.ir a:after,
a[href^="javascript:"]:after,
a[href^="#"]:after {
content: "";
}
pre,
blockquote {
border: 1px solid #999;
page-break-inside: avoid;
}
thead {
display: table-header-group; // h5bp.com/t
}
tr,
img {
page-break-inside: avoid;
}
img {
max-width: 100% !important;
}
@page {
margin: 2cm .5cm;
}
p,
h2,
h3 {
orphans: 3;
widows: 3;
}
h2,
h3 {
page-break-after: avoid;
}
// Bootstrap components
.navbar {
display: none;
}
.table {
td,
th {
background-color: #fff !important;
}
}
.btn,
.dropup > .btn {
> .caret {
border-top-color: #000 !important;
}
}
.label {
border: 1px solid #000;
}
.table {
border-collapse: collapse !important;
}
.table-bordered {
th,
td {
border: 1px solid #ddd !important;
}
}
}

View File

@ -0,0 +1,96 @@
//
// Progress bars
// --------------------------------------------------
// Bar animations
// -------------------------
// Webkit
@-webkit-keyframes progress-bar-stripes {
from { background-position: 40px 0; }
to { background-position: 0 0; }
}
// Firefox
@-moz-keyframes progress-bar-stripes {
from { background-position: 40px 0; }
to { background-position: 0 0; }
}
// Opera
@-o-keyframes progress-bar-stripes {
from { background-position: 0 0; }
to { background-position: 40px 0; }
}
// Spec and IE10+
@keyframes progress-bar-stripes {
from { background-position: 40px 0; }
to { background-position: 0 0; }
}
// Bar itself
// -------------------------
// Outer container
.progress {
overflow: hidden;
height: @line-height-computed;
margin-bottom: @line-height-computed;
background-color: @progress-bg;
border-radius: @border-radius-base;
.box-shadow(inset 0 1px 2px rgba(0,0,0,.1));
}
// Bar of progress
.progress-bar {
float: left;
width: 0%;
height: 100%;
font-size: @font-size-small;
line-height: @line-height-computed;
color: @progress-bar-color;
text-align: center;
background-color: @progress-bar-bg;
.box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));
.transition(width .6s ease);
}
// Striped bars
.progress-striped .progress-bar {
#gradient > .striped();
background-size: 40px 40px;
}
// Call animation for the active one
.progress.active .progress-bar {
-webkit-animation: progress-bar-stripes 2s linear infinite;
-moz-animation: progress-bar-stripes 2s linear infinite;
-ms-animation: progress-bar-stripes 2s linear infinite;
-o-animation: progress-bar-stripes 2s linear infinite;
animation: progress-bar-stripes 2s linear infinite;
}
// Variations
// -------------------------
.progress-bar-success {
.progress-bar-variant(@progress-bar-success-bg);
}
.progress-bar-info {
.progress-bar-variant(@progress-bar-info-bg);
}
.progress-bar-warning {
.progress-bar-variant(@progress-bar-warning-bg);
}
.progress-bar-danger {
.progress-bar-variant(@progress-bar-danger-bg);
}

View File

@ -0,0 +1,209 @@
//
// Responsive: Utility classes
// --------------------------------------------------
// IE10 in Windows (Phone) 8
//
// Support for responsive views via media queries is kind of borked in IE10, for
// Surface/desktop in split view and for Windows Phone 8. This particular fix
// must be accompanied by a snippet of JavaScript to sniff the user agent and
// apply some conditional CSS to *only* the Surface/desktop Windows 8. Look at
// our Getting Started page for more information on this bug.
//
// For more information, see the following:
//
// Issue: https://github.com/twbs/bootstrap/issues/10497
// Docs: http://getbootstrap.com/getting-started/#browsers
// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/
@-ms-viewport {
width: device-width;
}
// Visibility utilities
.visible-xs {
.responsive-invisibility();
@media (max-width: @screen-xs-max) {
.responsive-visibility();
}
&.visible-sm {
@media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {
.responsive-visibility();
}
}
&.visible-md {
@media (min-width: @screen-md-min) and (max-width: @screen-md-max) {
.responsive-visibility();
}
}
&.visible-lg {
@media (min-width: @screen-lg-min) {
.responsive-visibility();
}
}
}
.visible-sm {
.responsive-invisibility();
&.visible-xs {
@media (max-width: @screen-xs-max) {
.responsive-visibility();
}
}
@media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {
.responsive-visibility();
}
&.visible-md {
@media (min-width: @screen-md-min) and (max-width: @screen-md-max) {
.responsive-visibility();
}
}
&.visible-lg {
@media (min-width: @screen-lg-min) {
.responsive-visibility();
}
}
}
.visible-md {
.responsive-invisibility();
&.visible-xs {
@media (max-width: @screen-xs-max) {
.responsive-visibility();
}
}
&.visible-sm {
@media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {
.responsive-visibility();
}
}
@media (min-width: @screen-md-min) and (max-width: @screen-md-max) {
.responsive-visibility();
}
&.visible-lg {
@media (min-width: @screen-lg-min) {
.responsive-visibility();
}
}
}
.visible-lg {
.responsive-invisibility();
&.visible-xs {
@media (max-width: @screen-xs-max) {
.responsive-visibility();
}
}
&.visible-sm {
@media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {
.responsive-visibility();
}
}
&.visible-md {
@media (min-width: @screen-md-min) and (max-width: @screen-md-max) {
.responsive-visibility();
}
}
@media (min-width: @screen-lg-min) {
.responsive-visibility();
}
}
.hidden-xs {
.responsive-visibility();
@media (max-width: @screen-xs-max) {
.responsive-invisibility();
}
&.hidden-sm {
@media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {
.responsive-invisibility();
}
}
&.hidden-md {
@media (min-width: @screen-md-min) and (max-width: @screen-md-max) {
.responsive-invisibility();
}
}
&.hidden-lg {
@media (min-width: @screen-lg-min) {
.responsive-invisibility();
}
}
}
.hidden-sm {
.responsive-visibility();
&.hidden-xs {
@media (max-width: @screen-xs-max) {
.responsive-invisibility();
}
}
@media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {
.responsive-invisibility();
}
&.hidden-md {
@media (min-width: @screen-md-min) and (max-width: @screen-md-max) {
.responsive-invisibility();
}
}
&.hidden-lg {
@media (min-width: @screen-lg-min) {
.responsive-invisibility();
}
}
}
.hidden-md {
.responsive-visibility();
&.hidden-xs {
@media (max-width: @screen-xs-max) {
.responsive-invisibility();
}
}
&.hidden-sm {
@media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {
.responsive-invisibility();
}
}
@media (min-width: @screen-md-min) and (max-width: @screen-md-max) {
.responsive-invisibility();
}
&.hidden-lg {
@media (min-width: @screen-lg-min) {
.responsive-invisibility();
}
}
}
.hidden-lg {
.responsive-visibility();
&.hidden-xs {
@media (max-width: @screen-xs-max) {
.responsive-invisibility();
}
}
&.hidden-sm {
@media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {
.responsive-invisibility();
}
}
&.hidden-md {
@media (min-width: @screen-md-min) and (max-width: @screen-md-max) {
.responsive-invisibility();
}
}
@media (min-width: @screen-lg-min) {
.responsive-invisibility();
}
}
// Print utilities
.visible-print {
.responsive-invisibility();
}
@media print {
.visible-print {
.responsive-visibility();
}
.hidden-print {
.responsive-invisibility();
}
}

Some files were not shown because too many files have changed in this diff Show More