diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..64ac0f5f7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +FROM ruby:2.6.1-alpine3.9 + +RUN apk add --update \ + bash \ + bash-completion \ + build-base \ + libxml2-dev \ + libxslt-dev \ + git \ + rsync \ + nginx \ + nodejs \ + npm \ + && npm config set unsafe-perm true \ + && rm -rf /var/cache/apk/* \ + && npm config set cache /var --global \ + && npm install -g grunt \ + && npm install -g gulp \ + && npm install -g typescript \ + && npm install -g gulp-typedoc typedoc\ + && mkdir /run/nginx + +COPY docs-watcher/start.sh / + +RUN chmod +x /start.sh + +ENTRYPOINT [ "/start.sh" ] + +EXPOSE 9192 diff --git a/Gemfile b/Gemfile new file mode 100644 index 000000000..abe2cda5d --- /dev/null +++ b/Gemfile @@ -0,0 +1,10 @@ +source 'https://rubygems.org' + +gem 'uglifier' +gem 'json', '1.8.6' +gem 'jekyll', '3.0.1' +gem 'jekyll-sitemap' +gem 'jekyll-assets' +gem 'github-markdown' +gem 'html-pipeline' +gem 'jekyll-unsanitize', '0.4' diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 000000000..0c1ce14e9 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,97 @@ +GEM + remote: https://rubygems.org/ + specs: + activesupport (4.2.5) + i18n (~> 0.7) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + addressable (2.3.8) + colorator (0.1) + execjs (2.6.0) + fastimage (1.8.0) + addressable (~> 2.3, >= 2.3.5) + ffi (1.9.24) + github-markdown (0.6.9) + hike (1.2.3) + html-pipeline (2.2.2) + activesupport (>= 2, < 5) + nokogiri (>= 1.4) + i18n (0.7.0) + jekyll (3.0.1) + colorator (~> 0.1) + jekyll-sass-converter (~> 1.0) + jekyll-watch (~> 1.1) + kramdown (~> 1.3) + liquid (~> 3.0) + mercenary (~> 0.3.3) + rouge (~> 1.7) + safe_yaml (~> 1.0) + jekyll-assets (1.0.0) + fastimage (~> 1.6) + jekyll (>= 2) + mini_magick (~> 4.1) + sass (~> 3.2) + sprockets (~> 2.10) + sprockets-helpers + sprockets-sass + jekyll-sass-converter (1.4.0) + sass (~> 3.4) + jekyll-sitemap (0.9.0) + jekyll-unsanitize (0.4) + jekyll-watch (1.4.0) + listen (~> 3.0, < 3.1) + json (1.8.6) + kramdown (1.11.1) + liquid (3.0.6) + listen (3.0.8) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + mercenary (0.3.6) + mini_magick (4.3.6) + mini_portile2 (2.4.0) + minitest (5.8.2) + multi_json (1.11.2) + nokogiri (1.10.5) + mini_portile2 (~> 2.4.0) + rack (1.6.11) + rb-fsevent (0.9.7) + rb-inotify (0.9.7) + ffi (>= 0.5.0) + rouge (1.11.0) + safe_yaml (1.0.4) + sass (3.4.22) + sprockets (2.12.4) + hike (~> 1.2) + multi_json (~> 1.0) + rack (~> 1.0) + tilt (~> 1.1, != 1.3.0) + sprockets-helpers (1.2.1) + sprockets (>= 2.2) + sprockets-sass (1.3.1) + sprockets (~> 2.0) + tilt (~> 1.1) + thread_safe (0.3.5) + tilt (1.4.1) + tzinfo (1.2.2) + thread_safe (~> 0.1) + uglifier (2.7.2) + execjs (>= 0.3.0) + json (>= 1.8.0) + +PLATFORMS + ruby + +DEPENDENCIES + github-markdown + html-pipeline + jekyll (= 3.0.1) + jekyll-assets + jekyll-sitemap + jekyll-unsanitize (= 0.4) + json (= 1.8.6) + uglifier + +BUNDLED WITH + 1.16.1 diff --git a/README.md b/README.md index 394e1ecf1..766032f2a 100644 --- a/README.md +++ b/README.md @@ -1,233 +1,26 @@ -# NativeScript Documentation +## Articles -Home of the NativeScript documentation content that lives at . Start [contributing](#contributing) today! +### Getting started +* [Getting Started with NativeScript for Android](https://github.com/NativeScript/docs/wiki/Getting-Started-with-NativeScript-for-Android) +* [Getting Started with NativeScript for iOS](https://github.com/NativeScript/docs/wiki/Getting-started-with-NativeScript-for-iOS) -## What’s In This Document +### Writing Apps +* [NativeScript Android Application Initialization with JavaScript](https://github.com/NativeScript/docs/wiki/NativeScript-Android-Application-Initialization-with-JavaScript) +* [NativeScript Android Application Initialization with TypeScript](https://github.com/NativeScript/docs/wiki/NativeScript-Android-Application-Initialization-with-TypeScript) +* [NativeScript Modules (NSM)](https://github.com/NativeScript/docs/wiki/NativeScript-Modules-%28NSM%29) -* [Contributing 🍺](#contributing) -* [About Jekyll :nut_and_bolt:](#about-jekyll) -* [Configuration ⚙️](#configuration) -* [Local Setup :computer:](#local-setup) -* [Contributors ❤️](#contributors) +### Advanced topics +* [Advanced NativeScript Topics for iOS](https://github.com/NativeScript/docs/wiki/Advanced-NativeScript-Topics-for-iOS) -## Contributing -The NativeScript documentation is completely open-source and we love contributions. Whether you want to fix a typo or write an entire article, the NativeScript documentation is a great way to get started contributing to an open-source project. - -Don’t know where to start? Check out the [list of issues with the “help wanted” label](https://github.com/NativeScript/docs/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22). New to git or GitHub? [Join our community Slack chat](https://www.nativescript.org/slack-invitation-form) and we’ll be happy to help get you up and running. - -The `master` branch contains the most up-to-date version of the NativeScript documentation and its contents are uploaded to [docs.nativescript.org](https://docs.nativescript.org/). When contributing to the documentation, always create a branch for your work from `master` as this will facilitate easier pull request management. - -### Are my contributions limited to this repo only? - -No, my friend. There are many other code repositories in the NativeScript world you might also be interested in contributing to: - -- [nativescript-cli](https://github.com/NativeScript/nativescript-cli) - This repo contains the NativeScript command-line interface, which lets you create, build, and run apps using the NativeScript framework. The CLI is written in TypeScript. - -- [nativescript-angular](https://github.com/NativeScript/nativescript-angular) - This repository contains the TypeScript code that integrates Angular with NativeScript. - -- [nativescript-vue](https://github.com/nativescript-vue) - This community-run project allows NativeScript to integrate with Vue.js. - -- [ios-runtime](https://github.com/NativeScript/ios-runtime) - This repo contains the NativeScript iOS runtime — the code that hosts NativeScript iOS apps, and allows JavaScript code to be executed on iOS devices. The iOS runtime is written in a fun mix of C++, Objective-C, and more. - -- [android-runtime](https://github.com/NativeScript/android-runtime) - This repo contains the NativeScript Android — the code that hosts NativeScript Android apps, and allows JavaScript code to be executed on Android devices. The Android runtime is written in a fun mix of C++ and Java. - -You can go check them out and help to expand their docs, add plugins to it and even fix bugs. - -## About Jekyll -This documentation is built using [Jekyll](https://jekyllrb.com/docs/home/). More info on how to control the template, table of content and the project structure, in general, can be found in the [Build README](build/README.md) - -## Configuration - -There are two versions of the NativeScript documentation that generate similar output: `nativescript` and `angular`. The former builds the vanilla NativeScript docs at [docs.nativescript.org/start/introduction](https://docs.nativescript.org/start/introduction), while the latter discusses Angular-specific topics at [docs.nativescript.org/angular/start/introduction](https://docs.nativescript.org/angular/start/introduction). - -Most of the content in this repository is shared between the two environments, but occasionally you may need to add environment-specific content. When you have this need you have a few options. - -1. If you would like a page to appear in a single environment, add an `environment: angular` or `environment: nativescript` property to that page's front matter. Pages marked with an `environment` property will appear in a single environment, and pages _not_ marked with an `environment` property will be shared across all environments. - -2. If you have a page that should appear in both environments but has different content for certain sections, you can use our built-in environment block tags. The blocks are named `angular` and `nativescript`, respectively, and can be used like this: - -```md -{% nativescript %}This paragraph appears only in the vanilla NativeScript documentation{% endnativescript %} - -This paragraph appears in both environments. - -{% angular %}This appears only in the Angular NativeScript documentation{% endangular %} - ``` - -## Local Setup - -If you plan to work on a non-trivial change, you will most probably want to run the documentation locally in order to give your change a try before submitting a pull request. To provide you with this opportunity without installing a ton of libraries and loose time in configuration, we have prepared a virtual environment based on a docker image, where everything is prepared for you in advance. - -### Prerequisites - -Docker should be installed on your machine: - -* Open the [official Docker install page](https://docs.docker.com/engine/installation/) and follow the instructions. - -The NativeScript documentation is composed from multiple repositories: - -* [NativeScript Docs](https://github.com/NativeScript/docs) -* [NativeScript Modules](https://github.com/NativeScript/NativeScript) -* [NativeScript Angular](https://github.com/NativeScript/nativescript-angular) -* [NativeScript JavaScript SDK examples](https://github.com/NativeScript/nativescript-sdk-examples-js) -* [NativeScript Angular SDK examples](https://github.com/NativeScript/nativescript-sdk-examples-ng) - -### Building the docker image - -Start by cloning all required git repositories in some local folder (`ns-docs` in the following examples): - -Open a console box (**Windows users should run a Git bash session!**) and clone the required git repositories: - -```bash -mkdir ns-docs -cd ns-docs -git clone https://github.com/NativeScript/docs.git -git clone https://github.com/NativeScript/nativescript-angular.git -``` - -Optional: - -```bash -git clone https://github.com/NativeScript/NativeScript.git -git clone https://github.com/NativeScript/nativescript-sdk-examples-js.git -git clone https://github.com/NativeScript/nativescript-sdk-examples-ng.git -git clone https://github.com/NativeScript/nativescript-cli.git - -git clone https://github.com/NativeScript/nativescript-ui-samples.git -git clone https://github.com/NativeScript/nativescript-ui-samples-angular.git -git clone https://github.com/NativeScript/nativescript-ui-samples-vue.git -``` - -> **NOTE**: `nativescript-ui-...` are private repositories used for building the API Reference for the NativeScript UI components. -> **NOTE**: If you have these repositories locally from previous work with the documentation, be sure to delete them and start from scratch as some old files can cause problems with the current setup. - -Then, build the docker image by using the following command from the `ns-docs` folder: - -```bash -sudo docker build -t ns-docs:1.0 docs/build -``` - -> **NOTE**: If you received some unauthorized error, make sure you are logged into docker from the CLI. Just execute `docker login` and follow the instruction. One thing to have in mind is that docker username is your email, but docker ID is what you see on the top right when you log in to https://hub.docker.com. When executing `docker login` you need to enter your Docker ID. - -### Building the documentation - -Start the docker image created in the previous step from the **ns-docs** folder: - -```bash -sudo docker run --rm -t -i -v $(pwd):/root -p 9192:9192 -t ns-docs:1.0 -``` - -Due to the [poor performance of mounted volumes on Mac OS](https://docs.docker.com/docker-for-mac/osxfs/#performance-issues-solutions-and-roadmap) you may use the [`delegated`](https://docs.docker.com/docker-for-mac/osxfs-caching/#delegated) mount strategy: - -```bash -sudo docker run --rm -t -i -v $(pwd):/root:delegated -p 9192:9192 -t ns-docs:1.0 -``` - -### Adding content - -Edit an article in some of the repositories and navigate to http://localhost:9192 on the host machine. Notice that it might take some time for the changes to be reflected in the browser. - -### Making changes - -* Edit some files. -* Refresh your browser (depending on which files have been modified, it might take more or less time for the changes to take effect). - -## Contributors - -The following is a list of all the people that have contributed to the NativeScript documentation. Thanks for your contributions! - -[tsonevn](https://github.com/tsonevn)[NickIliev](https://github.com/NickIliev)[tjvantoll](https://github.com/tjvantoll)[etabakov](https://github.com/etabakov)[ErjanGavalji](https://github.com/ErjanGavalji)[ns-bot](https://github.com/ns-bot) - -[radeva](https://github.com/radeva)[vakrilov](https://github.com/vakrilov)[rdlauer](https://github.com/rdlauer)[N3ll](https://github.com/N3ll)[hdeshev](https://github.com/hdeshev)[tbozhikov](https://github.com/tbozhikov) - -[mbektchiev](https://github.com/mbektchiev)[ikoevska](https://github.com/ikoevska)[erikruth](https://github.com/erikruth)[nsndeck](https://github.com/nsndeck)[sis0k0](https://github.com/sis0k0)[petekanev](https://github.com/petekanev) - -[hamorphis](https://github.com/hamorphis)[vtrifonov](https://github.com/vtrifonov)[Plamen5kov](https://github.com/Plamen5kov)[PetyaSotirova](https://github.com/PetyaSotirova)[bundyo](https://github.com/bundyo)[alexziskind1](https://github.com/alexziskind1) - -[atanasovg](https://github.com/atanasovg)[sipacate](https://github.com/sipacate)[MartoYankov](https://github.com/MartoYankov)[sebawita](https://github.com/sebawita)[angeltsvetkov](https://github.com/angeltsvetkov)[teobugslayer](https://github.com/teobugslayer) - -[ggarabedian](https://github.com/ggarabedian)[ivanbuhov](https://github.com/ivanbuhov)[lini](https://github.com/lini)[dtopuzov](https://github.com/dtopuzov)[tdermendjiev](https://github.com/tdermendjiev)[zbranzov](https://github.com/zbranzov) - -[EmilStoychev](https://github.com/EmilStoychev)[jasssonpet](https://github.com/jasssonpet)[KristianDD](https://github.com/KristianDD)[darind](https://github.com/darind)[vchimev](https://github.com/vchimev)[enchev](https://github.com/enchev) - -[pkoleva](https://github.com/pkoleva)[Mitko-Kerezov](https://github.com/Mitko-Kerezov)[rosen-vladimirov](https://github.com/rosen-vladimirov)[jlooper](https://github.com/jlooper)[boevski](https://github.com/boevski)[tgpetrov](https://github.com/tgpetrov) - -[vmutafov](https://github.com/vmutafov)[manoldonev](https://github.com/manoldonev)[bdlb77](https://github.com/bdlb77)[paulpv](https://github.com/paulpv)[surdu](https://github.com/surdu)[roblav96](https://github.com/roblav96) - -[rynop](https://github.com/rynop)[tzraikov](https://github.com/tzraikov)[PanayotCankov](https://github.com/PanayotCankov)[bradmartin](https://github.com/bradmartin)[jpenna](https://github.com/jpenna)[getsetbro](https://github.com/getsetbro) - -[tailsu](https://github.com/tailsu)[sitefinitysteve](https://github.com/sitefinitysteve)[dmccuskey](https://github.com/dmccuskey)[elena-p](https://github.com/elena-p)[yyosifov](https://github.com/yyosifov)[parloti](https://github.com/parloti) - -[burkeholland](https://github.com/burkeholland)[pelegri](https://github.com/pelegri)[felipebueno](https://github.com/felipebueno)[jbristowe](https://github.com/jbristowe)[Lampei](https://github.com/Lampei)[zh-m](https://github.com/zh-m) - -[000panther](https://github.com/000panther)[mudlabs](https://github.com/mudlabs)[ShawnPavel](https://github.com/ShawnPavel)[tushutripathi](https://github.com/tushutripathi)[shiv19](https://github.com/shiv19)[adrian-niculescu](https://github.com/adrian-niculescu) - -[alejonext](https://github.com/alejonext)[AmitGurbani](https://github.com/AmitGurbani)[AntonDobrev](https://github.com/AntonDobrev)[baskarmib](https://github.com/baskarmib)[djenitoo](https://github.com/djenitoo)[fdnhkj](https://github.com/fdnhkj) - -[gbhojraj](https://github.com/gbhojraj)[Hakier](https://github.com/Hakier)[shirohana](https://github.com/shirohana)[blackpanther99](https://github.com/blackpanther99)[imcgonigle](https://github.com/imcgonigle)[ignaciolarranaga](https://github.com/ignaciolarranaga) - -[lonerzzz](https://github.com/lonerzzz)[Bjorn576](https://github.com/Bjorn576)[jayvolr](https://github.com/jayvolr)[jonnysamps](https://github.com/jonnysamps)[digitaldrummerj](https://github.com/digitaldrummerj)[LokeCarlsson](https://github.com/LokeCarlsson) - -[msaelices](https://github.com/msaelices)[milejko](https://github.com/milejko)[map7](https://github.com/map7)[m-abs](https://github.com/m-abs)[Nikhil22](https://github.com/Nikhil22)[noumaans](https://github.com/noumaans) - -[pedromorgan](https://github.com/pedromorgan)[Razzeee](https://github.com/Razzeee)[renestalder](https://github.com/renestalder)[rodrigopires](https://github.com/rodrigopires)[TedHopp](https://github.com/TedHopp)[WilcoBreedt](https://github.com/WilcoBreedt) - -[devoto13](https://github.com/devoto13)[eyal7773](https://github.com/eyal7773)[miroslavaivanova](https://github.com/miroslavaivanova)[mtekp](https://github.com/mtekp)[TsvetanMilanov](https://github.com/TsvetanMilanov)[ajoslin103](https://github.com/ajoslin103) - -[ADmad](https://github.com/ADmad)[airandfingers](https://github.com/airandfingers)[adamunion](https://github.com/adamunion)[AjaiDubey](https://github.com/AjaiDubey)[Fusty](https://github.com/Fusty)[ADjenkov](https://github.com/ADjenkov) - -[Alexander-Bliznyuk](https://github.com/Alexander-Bliznyuk)[kondasoft](https://github.com/kondasoft)[amjd](https://github.com/amjd)[the-AoG-guy](https://github.com/the-AoG-guy)[devdRew](https://github.com/devdRew)[MonsieurMan](https://github.com/MonsieurMan) - -[gupta-ankit](https://github.com/gupta-ankit)[ABoschman](https://github.com/ABoschman)[Burgov](https://github.com/Burgov)[bensooraj](https://github.com/bensooraj)[bsyk](https://github.com/bsyk)[benjlin](https://github.com/benjlin) - -[brandonpearson23](https://github.com/brandonpearson23)[clounie](https://github.com/clounie)[tonjohn](https://github.com/tonjohn)[CMRHDL](https://github.com/CMRHDL)[cameronnorman](https://github.com/cameronnorman)[celso-wo](https://github.com/celso-wo) - -[chuckmitchell](https://github.com/chuckmitchell)[crixx](https://github.com/crixx)[chrants](https://github.com/chrants)[yapcwed](https://github.com/yapcwed)[ctp-placebo](https://github.com/ctp-placebo)[chrismullins](https://github.com/chrismullins) - -[ClaudioMeinberg](https://github.com/ClaudioMeinberg)[dotlens](https://github.com/dotlens)[derskeal](https://github.com/derskeal)[Darkle](https://github.com/Darkle)[CoreyCole](https://github.com/CoreyCole)[ejsuncy](https://github.com/ejsuncy) - -[DTV96Calibre](https://github.com/DTV96Calibre)[DannyFeliz](https://github.com/DannyFeliz)[dennistang](https://github.com/dennistang)[DimitarTachev](https://github.com/DimitarTachev)[diogocapela](https://github.com/diogocapela)[donangel](https://github.com/donangel) - -[dogabudak](https://github.com/dogabudak)[DrQwertySilence](https://github.com/DrQwertySilence)[dyldawg](https://github.com/dyldawg)[ezesundayeze](https://github.com/ezesundayeze)[felipebernardes](https://github.com/felipebernardes)[FrancoisCamus](https://github.com/FrancoisCamus) - -[codepotato](https://github.com/codepotato)[sundayglee](https://github.com/sundayglee)[grgur](https://github.com/grgur)[harikrishnana2021](https://github.com/harikrishnana2021)[hristoborisov](https://github.com/hristoborisov)[hugocarreiracosta](https://github.com/hugocarreiracosta) - -[jagadish-kb](https://github.com/jagadish-kb)[jkulubya](https://github.com/jkulubya)[jayoma](https://github.com/jayoma)[n3wc](https://github.com/n3wc)[JmOkay](https://github.com/JmOkay)[jofftiquez](https://github.com/jofftiquez) - -[jrpool](https://github.com/jrpool)[jrz](https://github.com/jrz)[joshgking](https://github.com/joshgking)[TheOriginalJosh](https://github.com/TheOriginalJosh)[jpierront](https://github.com/jpierront)[jurgentreep](https://github.com/jurgentreep) - -[Ksantacr](https://github.com/Ksantacr)[kharysharpe](https://github.com/kharysharpe)[LeandroDG](https://github.com/LeandroDG)[lukesammy](https://github.com/lukesammy)[macknelson](https://github.com/macknelson)[mshanak](https://github.com/mshanak) - -[marablayev](https://github.com/marablayev)[mrcaste](https://github.com/mrcaste)[marklanhamhc](https://github.com/marklanhamhc)[hettiger](https://github.com/hettiger)[nemephx](https://github.com/nemephx)[DanekDanek](https://github.com/DanekDanek) - -[realtebo](https://github.com/realtebo)[MitzaCoder](https://github.com/MitzaCoder)[mhrabiee](https://github.com/mhrabiee)[mrmowji](https://github.com/mrmowji)[LiteCatDev](https://github.com/LiteCatDev)[Natalia-Hristova](https://github.com/Natalia-Hristova) - -[nicoeg](https://github.com/nicoeg)[nike47](https://github.com/nike47)[oluwaseye](https://github.com/oluwaseye)[oimyounis](https://github.com/oimyounis)[Omnicouleur](https://github.com/Omnicouleur)[developer82](https://github.com/developer82) - -[pzanitti](https://github.com/pzanitti)[pdvorchik](https://github.com/pdvorchik)[pascualstromsnes](https://github.com/pascualstromsnes)[dodongphure](https://github.com/dodongphure)[morph3o](https://github.com/morph3o)[qkdreyer](https://github.com/qkdreyer) - -[rajatraj733](https://github.com/rajatraj733)[rakeshgirase](https://github.com/rakeshgirase)[ReshmaPD](https://github.com/ReshmaPD)[RohanTalip](https://github.com/RohanTalip)[ffxsam](https://github.com/ffxsam)[SamVerschueren](https://github.com/SamVerschueren) - -[mastix](https://github.com/mastix)[sean-perkins](https://github.com/sean-perkins)[sebastianovide](https://github.com/sebastianovide)[jalkoby](https://github.com/jalkoby)[shauntif](https://github.com/shauntif)[simmstein](https://github.com/simmstein) - -[SirMaxxx](https://github.com/SirMaxxx)[DasAllFolks](https://github.com/DasAllFolks)[tadeucariolano](https://github.com/tadeucariolano)[Taremeh](https://github.com/Taremeh)[TechnicalSoup](https://github.com/TechnicalSoup)[Tetrygon](https://github.com/Tetrygon) - -[tralves](https://github.com/tralves)[fartek](https://github.com/fartek)[tdous](https://github.com/tdous)[e2l3n](https://github.com/e2l3n)[tonymporter](https://github.com/tonymporter)[trentvb](https://github.com/trentvb) - -[viragumathe5](https://github.com/viragumathe5)[VladimirAmiorkov](https://github.com/VladimirAmiorkov)[weech3r](https://github.com/weech3r)[williamho](https://github.com/williamho)[Xorbert](https://github.com/Xorbert)[ycherniavskyi](https://github.com/ycherniavskyi) - -[csj](https://github.com/csj)[diyews](https://github.com/diyews)[doorb02](https://github.com/doorb02)[Ayushraj1](https://github.com/Ayushraj1)[ishandutta2007](https://github.com/ishandutta2007)[jacostaperu](https://github.com/jacostaperu) - -[jamessouth](https://github.com/jamessouth)[johannbraun](https://github.com/johannbraun)[jyotendra](https://github.com/jyotendra)[narayananl23](https://github.com/narayananl23)[pavanser](https://github.com/pavanser)[peterennis](https://github.com/peterennis) - -[quintonn](https://github.com/quintonn)[saiberz](https://github.com/saiberz)[saknarak](https://github.com/saknarak)[seros00](https://github.com/seros00)[shendrekbharath](https://github.com/shendrekbharath)[stevo-knievo](https://github.com/stevo-knievo) - -[svalchinov](https://github.com/svalchinov)[tdsmithATabc](https://github.com/tdsmithATabc)[trevordowdle](https://github.com/trevordowdle)[tsira](https://github.com/tsira)[yavulan](https://github.com/yavulan)[yjaaidi](https://github.com/yjaaidi) - -[bangseongbeom](https://github.com/bangseongbeom) - - - - +## NativeScript API Reference. +### Modules +* ["application"](application/) +* ["file-system"](file-system/) +* ["image-source"](image-source/) +* ["location"](location/) +* ["promises"](promises/) +* ["text"](text/) +* ["http"](http/) +* ["local-settings"](local-settings/) diff --git a/_assets/javascripts/app.js b/_assets/javascripts/app.js new file mode 100644 index 000000000..008843c83 --- /dev/null +++ b/_assets/javascripts/app.js @@ -0,0 +1,501 @@ +function expandNavigation(url) { + return function(e) { + if (e.node) { + return; + } + var segments = url.split("/"); + var page = segments[segments.length - 1]; + var treeview = this; + + var dataSource = this.dataSource; + var node; + + for (var idx = 0; idx < segments.length; idx++) { + node = dataSource.get(segments[idx]); + + if (node) { + node.set("expanded", true); + dataSource = node.children; + } + } + + node && node.set("selected", true); + + this.unbind("dataBound", arguments.callee); + } +} + +function navigationTemplate(root) { + return function(data) { + var item = data.item; + var text = item.text; + + if (item.hasChildren) { + return text; + } + + var url = item.path; + + if (location.pathname.indexOf(".html") < 0) { + url = url.replace(".html", ""); + } + + while (item = item.parentNode()) { + url = item.path + "/" + url; + } + + return '' + text + ""; + } +} + +function preventParentSelection(e) { + if (this.dataItem(e.node).hasChildren) { + e.preventDefault(); + this.toggle(e.node); + } +} + +function traverseAnchors(elements, level) { + var html = ""; +} + +function initNSMenu() { + hidePanelBar(); + $(".ns-menu-trigger").addClass("-hidden"); + $("#side-nav__toggle").prop("checked", true); + + window.nsMenu.clone().kendoMenu({ + openOnClick: { + rootMenuItems: true + }, + closeOnClick: true, + animation: { open: { + effects: "fadeIn", + duration: 100 + }} + }).appendTo(".navigation__right"); +} + +function initPanelBar() { + $(".ns-menu-trigger").removeClass("-hidden"); + $("#side-nav__toggle").prop("checked", false); + + var menu = window.nsMenu.clone(); + + menu.children("li:nth-last-child(-n+2)") + .remove() + .wrapAll("") + .parent() + .kendoMenu() + .appendTo(".navigation__right"); + + menu.kendoPanelBar({ + expandMode: "single" + }) + .prependTo(".ns-navigation") + .click(function(e) { + e.stopPropagation(); + }); +} + +function initMenus(loading) { + var menu = $(".ns-menu"); + var isLoading = loading === true; + var isSmall = Math.min(window.innerWidth, window.outerWidth || 1024) < 1024; + var isContextMenu = menu.hasClass("k-panelbar"); + var responsive = isContextMenu && !isSmall; + + if (isLoading || responsive || !isContextMenu && isSmall) { + menu.each(function () { + var menuInstance = kendo.widgetInstance($(this)); + + menuInstance && menuInstance.destroy(); + menu.remove(); + }); + + window[(isLoading ? !isSmall : responsive) ? "initNSMenu" : "initPanelBar"](); + } +} + +function hidePanelBar() { + $(".k-panelbar").toggle(false); + $(".ns-menu-trigger").removeClass("k-state-selected"); + + $(document.documentElement).off("click", hidePanelBar); +} + +$(function(){ + + $("pre[lang]").each(function() { + if (this.parentNode.className.indexOf("k-content") >= 0) { + return; + } + + var langs = $(this).nextUntil(":not(pre)", "pre").add(this); + + var tabs = $.map(langs, function(item) { + return $("
  • ").text($(item).attr("lang")); + }); + + // No need for tabs if there's only one tab + if (tabs.length == 1) { + return; + } + + tabs[0].addClass("k-state-active"); + + var tabstrip = $("
    ") + .insertBefore(this) + .append($("
      ").append(tabs)) + .append(langs); + + langs.wrap("
      "); + + tabstrip.kendoTabStrip({ + animation: { + open: { + effects: "fadeIn" + } + } + }); + }); + + var codeSampleMapper = { + 'c#': 'clike', + 'appbuilder' : 'javascript', + 'javascript' : 'javascript', + 'typescript' : 'typescript', + 'kotlin': 'kotlin', + 'java':'java', + 'c++' : 'clike', + 'c' : 'clike', + 'css' : 'css', + 'objective-c' : 'objectivec', + 'xml' : 'markup' + }; + + var codeSampleExtensionMapper = { + '.xml': 'markup', + '.css' : 'css', + '.js' : 'javascript', + '.ts' : 'typescript', + '.kt':'kotlin', + '.java':'java' + }; + + // Enable Prism support by mapping the lang attributes to the language-* attribute Prim expects + $("pre").each(function(index){ + var lang = $(this).attr('lang') ? $(this).attr('lang').toLowerCase() : ""; + var langExtension = codeSampleMapper[lang]; + if(!langExtension) { + // No language found - check for file extension. + for (ext in codeSampleExtensionMapper){ + if (lang.lastIndexOf(ext, lang.length - ext.length) >= 0) { + langExtension = codeSampleExtensionMapper[ext]; + break; + } + } + } + if (!langExtension) { + // If still no language found, check if the first character is a “<”. + // If it is, assume markup. + if ($(this).text().charAt(0) === "<") { + langExtension = "markup"; + } + } + $(this).addClass('language-' + langExtension); + }); + Prism.highlightAll(); + + // Build the exercise sections + $(".exercise-start").each(function() { + var exerciseDiv = $("
      "); + $(this).before(exerciseDiv); + $(this).nextUntil(".exercise-end").addBack().appendTo(exerciseDiv); + }); + $(".exercise-end").remove(); + + // Detecting clipboard support without UA sniffing is basically impossible + // at the moment. See https://gist.github.com/jonrohan/81085b119d16cdd7868a. + // Edge, Chrome, and Firefox support the API but Safari does not. + // (Edge hits this if test because it has “Chrome” in its user agent string). + if (navigator.userAgent.match(/(Chrome|Firefox)/)) { + // Add copy buttons to all pre tags in exercises + $(".exercise pre, .add-copy-button").each(function() { + // Pre tags in exercises can remove the code button by including a div + // with the no-copy-button class name before them. + if ($(this).prev().hasClass("no-copy-button")) { + return; + } + + $(this) + .prepend("") + .wrap("
      "); + }); + } + + // Add copy-to-clipboard behavior to the copy buttons. + // See https://developers.google.com/web/updates/2015/04/cut-and-copy-commands?hl=en + $(".copy-button").on("click", function() { + window.getSelection().removeAllRanges(); + var codeElement = $(this).parent().find("code")[0]; + var range = document.createRange(); + range.selectNode(codeElement); + window.getSelection().addRange(range); + document.execCommand("copy"); + window.getSelection().removeAllRanges(); + $(this).blur(); + }); + + $("#markdown-toc").each(function() { + var ul = $("
        "); + + $("#page-article h2").each(function() { + var h2 = $(this); + + if (!/fields|configuration|properties|events|methods/i.test(h2.text())) { + return; + } + + $("
      • ") + .addClass("section") + .append(h2.children().clone()) + .appendTo(ul) + .mouseenter(function() { + var children = $(this).children("ul"); + + if (!children.length) { + children = $("
          "); + + h2.nextUntil("h2").filter("h3").each(function(){ + $("
        • ").append($(this).children().clone()).appendTo(children); + }); + + if (children.children().length) { + children.appendTo(this); + } + } + + children.show(); + }) + .mouseleave(function() { + $(this).children("ul").hide(); + }); + }); + + ul.appendTo(this); + }); + + var options = { + root: null, + rootMargin: "0px", + threshold: 1.0 + }; + + window.addEventListener("scroll", function(e) { + e.target.documentElement.classList[e.target.scrollingElement.scrollTop !== 0 ? "add" : "remove"]("ns-state-scrolled"); + }, { passive: true }); + + var visibleElements = []; + + var observer = new IntersectionObserver(function (entries) { + entries.forEach(function(entry) { + if (entry.intersectionRatio < 1) { + visibleElements.splice(visibleElements.indexOf(entry.target), 1); + } else { + visibleElements[entry.intersectionRect.y < entry.rootBounds.height ? "unshift" : "push"](entry.target); + } + }); + + if (visibleElements[0]) { + var topElement = { offsetTop: 9999999 }; + + visibleElements.forEach(function (element) { + if (element.offsetTop < topElement.offsetTop) { + topElement = element; + } + }); + + var prevParent = $(topElement).prevAll("h2")[0]; + + topElement = $('.right-nav__tree' + + (prevParent && topElement.nodeName !== "H2" ? ' [href$="#' + prevParent.id + '"] + ul' : '') + + ' [href$="#' + topElement.id + '"]'); + + if (topElement[0]) { + $(".right-nav__tree a").removeClass("ns-state-selected"); + + topElement.addClass("ns-state-selected"); + } + } + }, options); + + var seeAlso = $("#see-also"); + var seeAlsoLinks = seeAlso.next("ul"); + + seeAlso.remove(); + + var apiReferences = $("article > p > a[href*=api-reference]"); + + if (apiReferences[0]) { + apiReferences = $($.uniqueSort( + apiReferences + .clone() + .wrapAll("
          ") + .parent() + .html() + .toString() + .trim() + .split(/(?=<\/a>)/i)) + .join("")); + } + + var rightNavLinks = $(".right-nav__links"); + + var rightNav = $('\ +
          \ + \ + \ +
          \ +
          \ +
          ') + .insertBefore($("article")) + .children(".right-nav__tree"); + + var articleAnchors = $(traverseAnchors($("article > h2 > a"), 2)); + + if (articleAnchors.children()[0]) { + rightNav + .append($("
          In this article
          ")) + .append(articleAnchors); + } + + if (seeAlsoLinks[0]) { + rightNav + .append($("
          Related articles
          ")) + .append(seeAlsoLinks); + } + + if (apiReferences[0]) { + apiReferences.parent().remove(); + + rightNav + .append($("
          API Reference
          ")) + .append(apiReferences.wrap("
        • ").parent().wrapAll("
            ").parent()); + } + + if (rightNavLinks[0]) { + rightNav + .append($("
            Not finding the help you need?
            ")) + .append(rightNavLinks); + } + + $(document.documentElement).on("click", function() { + var toggle = $("#right-nav__toggle")[0]; + + if (toggle) { + toggle.checked = false; + } + }); + + window.addEventListener("resize", initMenus, { passive: true }); + + $(".ns-menu-trigger").on("click", function () { + var panelbar = $(".k-panelbar"); + var shouldBeVisible = !panelbar.is(":visible"); + + $(this).toggleClass("k-state-selected", shouldBeVisible); + panelbar.toggle(shouldBeVisible); + + if (shouldBeVisible) { + setTimeout(function () { + $(document.documentElement).on("click", hidePanelBar); + }); + } + }); + + $(".right-nav__container").on("click", function(e) { + e.stopPropagation(); + }); + + $("article > h2, article > h3").each(function(index, node) { + observer.observe(node); + }); + + var bodyObserver = new MutationObserver(function(entries) { + entries.forEach(function() { + if (document.body.classList.contains("gsc-overflow-hidden")) { + document.documentElement.classList.add("-overflow-hidden"); + } else { + document.documentElement.classList.remove("-overflow-hidden"); + } + }); + }); + + bodyObserver.observe(document.body, { + attributes: true, + attributeOldValue: true, + attributeFilter: ["class"] + }); + + $(".ns-tip-container .close-banner-button").click(function () { this.parentNode.remove(); }); +}); + +$(function() { + 'use strict'; + function createCookie(name,value,days) { + if (days) { + var date = new Date(); + date.setTime(date.getTime()+(days*24*60*60*1000)); + var expires = "; expires="+date.toGMTString(); + } + else var expires = ""; + + document.cookie = name+"="+value+expires+"; path=/"; + + } + + function readCookie(name) { + var nameEQ = name + "="; + var ca = document.cookie.split(';'); + + for(var i=0;i < ca.length;i++) { + var c = ca[i]; + while (c.charAt(0)==' ') c = c.substring(1,c.length); + if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); + } + return null; + } + + var banner = $('.tip-container'); + var close = $('.tip-close'); + var cookieName = 'ns-banner2-seen'; + var hasCookie = readCookie(cookieName); + + function onBannerClose() { + banner.slideUp('fast'); + createCookie(cookieName, true, 1); + return false; + } + + function handleBanner() { + if (!hasCookie) { + banner.slideDown('fast'); + close.on('click.tip', onBannerClose); + } + } + + window.setTimeout(handleBanner, 1000); +}); diff --git a/_assets/javascripts/feedback-form.js b/_assets/javascripts/feedback-form.js new file mode 100644 index 000000000..990ff58a4 --- /dev/null +++ b/_assets/javascripts/feedback-form.js @@ -0,0 +1,417 @@ +$(document).ready(function () { + + var Feedback = {}; + + var $window = $(window); + + var defaultFormValues = { + email: "", + inaccurateContent: false, + inaccurateOutdatedContentText: "", + otherMoreInformation: false, + otherMoreInformationText: "", + textErrors: false, + typosLinksElementsText: "", + outdatedSample: false, + inaccurateOutdatedCodeSamplesText: "", + otherFeedback: false, + textFeedback: "", + acceptFeedbackContact: false + }; + + var checkboxArea = $("#feedback-checkbox-area"); + + checkboxArea.click(function () { + checkboxArea.find("span.k-tooltip-validation").remove(); + checkboxArea.find("textarea").removeClass("k-invalid"); + }); + + var formIsProcessing = false; + //Util functions + var generateUUID = function () { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + }; + + var getCookieByName = function (name) { + //This is very crude, but necessary because currently there is some kind of url rewriting going on + //so the cookies are set for a base path but then additional navigation is done with url rewriting + //so we set the cookie name as complete path to avoid a problem where the cookie is set for multiple pages. + if (name === "yesNoFeedback") { + name = currentPath; + } + var match = document.cookie.match(new RegExp(name + '=([^;]+)')); + if (match) return match[1]; + }; + + //Init utility variables + var rawLocationObject = $(location); + var currentPath = rawLocationObject[0].origin + rawLocationObject[0].pathname; + var popupNotification = $("#popupNotification").kendoNotification().data("kendoNotification"); + var formPopupNotification = $("#feedback-form-popup-container").kendoNotification({ + appendTo: "#feedback-form-window" + }).data("kendoNotification"); + + var setCookieByName = function (name, value) { + var cookieUUID = getCookieByName("uuid"); + if (!cookieUUID) { + document.cookie = "uuid=" + generateUUID() + "; path=/"; + } + //This is very crude, but necessary because currently there is some kind of url rewriting going on + //so the cookies are set for a base path but then additional navigation is done with url rewriting + //so we set the cookie name as complete path to avoid a problem where the cookie is set for multiple pages. + if (name === "yesNoFeedback") { + name = currentPath; + } + document.cookie = name + "=" + value + ";"; + }; + + //Feedback menu controls + var feedbackButtonsContainer = $("#feedback-buttons-container"); + var feedbackSubmittedContainer = $("#feedback-submitted-container"); + var toggleFeedbackButtons = function (toggle) { + if (toggle) { + feedbackButtonsContainer.show(); + feedbackSubmittedContainer.hide(); + } else { + feedbackButtonsContainer.hide(); + feedbackSubmittedContainer.show(); + } + }; + + if (getCookieByName("yesNoFeedback")) { + toggleFeedbackButtons(false); + } else { + toggleFeedbackButtons(true); + } + + //FORM + //Init the form popup window + var win = $("#feedback-form-window").kendoWindow({ + title: "Article feedback", + actions: [], + draggable: true, + modal: true, + pinned: false, + visible: false, + resizable: false, + width: "700px" + }).data("kendoWindow"); + //Init form + var feedbackForm = $("#feedback-form"); + var formModel = kendo.observable(defaultFormValues); + var isFormModelEmpty = function () { + var isModelDefault = true; + for (var key in defaultFormValues) { + if (key === 'email') { + continue; + } + var isValueEqual = formModel[key] === defaultFormValues[key]; + if (!isValueEqual) { + isModelDefault = false; + break; + } + } + return isModelDefault; + }; + + var isFormModelSatisfied = function (key, formValue) { + var value = formModel[key]; + if (value) { + return formValue && formValue.length > 0; + } else { + return true; + } + }; + //Bind model to form + kendo.bind($("div#feedback-form-window"), formModel); + //Attach to form submit to adjust variables and send request + var emptyFormValidator = checkboxArea.kendoValidator({ + validateOnBlur: false, + messages: { + // defines a message for the custom validation rule + emptyForm: "You need to provide some feedback before submitting the form." + }, + rules: { + emptyForm: function (input) { + return !isFormModelEmpty(); + } + } + + }).data("kendoValidator"); + + var emailValidator = $("#feedback-email-input").kendoValidator({ + validateOnBlur: false, + messages: { + email: "Invalid email address." + }, + rules: { + email: function (input) { + if (input.val().length > 0) { + var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return re.test(input.val()); + } + return true; + } + } + }).data("kendoValidator"); + + var emailConsentValidator = $("#feedback-email-consent").kendoValidator({ + validateOnBlur: false, + messages: { + consent: "You have to agree first." + }, + rules: { + consent: function (input) { + var email = formModel["email"]; + console.log("email: " + email + ", checked: ", formModel["acceptFeedbackContact"]); + if (email.length > 0) { + return formModel["acceptFeedbackContact"]; + } + + return true; + } + } + }).data("kendoValidator"); + + // text validation is disabled for the new design of the form. In order to enable it + // it must be reworked!!! + var textAreaValidator = function (selector, formModelKey) { + return $(selector).kendoValidator({ + validateOnBlur: false, + messages: { + required: "Field should not be empty.", + htmlValidation: "HTML tags are not allowed.", + messageLength: "Message must not exceed 2500 characters.", + whiteSpaces: "Using only whitespace is not allowed.", + feedbackValidation: "Please select a category and provide some additional information." + }, + rules: { + emptyValidation: function (input) { + var text = input.val(); + + return isFormModelSatisfied(formModelKey, text); + }, + htmlValidation: function (input) { + var text = input.val(); + var matches = text.match(/(<([^>]+)>)/ig); + + return matches == null; + }, + messageLength: function (input) { + var text = input.val(); + + return text.length <= 2500; + }, + whiteSpaces: function (input) { + var text = input.val(); + if (text.length > 0) { + return $.trim(text) !== ""; + } + return true; + }, + feedbackValidation: function (input) { + var text = input.val(); + if (text.length > 0) { + return formModel[formModelKey]; + } + return true; + } + } + }).data("kendoValidator"); + }; + + feedbackForm.submit(function (e) { + e.preventDefault(); + //if form is processing do nothing. + if (formIsProcessing) { + return; + } + + formIsProcessing = true; + + if(isFormModelEmpty()){ + formPopupNotification.show("Please provide some feedback before submitting the form.", "Error"); + formIsProcessing = false; + return; + } + + if ((!formModel.outdatedSample || (formModel.outdatedSample && textAreaValidator("#feedback-code-sample-text-input", "outdatedSample").validate())) && + (!formModel.otherMoreInformation || (formModel.otherMoreInformation && textAreaValidator("#feedback-more-information-text-input", "otherMoreInformation").validate())) && + (!formModel.textErrors || (formModel.textErrors && textAreaValidator("#feedback-text-errors-text-input", "textErrors").validate())) && + (!formModel.inaccurateContent || (formModel.inaccurateContent && textAreaValidator("#feedback-inaccurate-content-text-input", "inaccurateContent").validate())) && + (!formModel.otherFeedback || (formModel.otherFeedback && textAreaValidator("#feedback-other-text-input", "otherFeedback").validate())) && + emailValidator.validate() && + emailConsentValidator.validate()) { + win.close(); + setCookieByName("submittingFeedback"); + formModel.yesNoFeedback = getCookieByName("yesNoFeedback") || "Not submitted"; + formModel.uuid = getCookieByName("uuid"); + formModel.path = currentPath; + formModel.sheetId = $("#hidden-sheet-id").val(); + $.ajax({ + url: "https://baas.kinvey.com/rpc/kid_Hk57KwIFf/custom/saveFeedback", + method: "POST", + dataType: "json", + contentType: "application/json; charset=utf-8", + data: JSON.stringify(formModel), + crossDomain: true, + beforeSend: function (xhr) { + xhr.setRequestHeader("Authorization", "Basic " + btoa("feedback:feedback")); + }, + success: function (data) { + formIsProcessing = false; + } + }); + } else { + formIsProcessing = false; + } + }); + + //Attach to close button inside form window + $("#form-close-button").click(function () { + win.close(); + }); + + //Attach to submit button inside form window + $("#form-submit-button").click(function () { + feedbackForm.submit(); + }); + + //Init buttons + $("#yesButton").click(function () { + setCookieByName("yesNoFeedback", "Yes"); + toggleFeedbackButtons(false); + Feedback.closeFeedback(); + Feedback.adjustNavigationPosition(); + }); + $("#noButton").click(function () { + setCookieByName("yesNoFeedback", "No"); + toggleFeedbackButtons(false); + Feedback.closeFeedback(); + Feedback.adjustNavigationPosition(); + win.center().open(); + }); + + + var windowHeight = $window.height(); + var headerHeight = $(".TK-Hat").outerHeight() + $(".ns-navigation").outerHeight(); + var footerHeight = $("#feedback-section").outerHeight() + $("footer").outerHeight(); + var articleHeight = windowHeight - (headerHeight + footerHeight); + var feedbackOffsetTop = document.body.scrollHeight - footerHeight; + var shouldOverlayFeedback = !getCookieByName("yesNoFeedback") && !getCookieByName("yesNoFeedbackClosed"); + var showingFeedbackBar = false; + var scrollFold = $window.scrollTop() + windowHeight; + var feedbackPinned = false; + + function updateVariables() { + windowHeight = $window.height(); + headerHeight = $(".TK-Hat").outerHeight() + $(".ns-navigation").outerHeight(); + footerHeight = $("#feedback-section").outerHeight() + $("footer").outerHeight(); + articleHeight = windowHeight - (headerHeight + footerHeight); + feedbackOffsetTop = document.body.scrollHeight - footerHeight; + scrollFold = $window.scrollTop() + windowHeight; + } + + Feedback = $.extend(Feedback, { + + init: function() { + + Feedback._events(); + + Feedback.adjustArticleHeight(); + Feedback.adjustNavigationPosition(); + + if (shouldOverlayFeedback) { + + showingFeedbackBar = true; + + window.setTimeout(function() { + showingFeedbackBar = false; + Feedback.toggleFeedback(); + Feedback.adjustNavigationPosition(); + }, 30000); + } + + }, + + + // #region events + _events: function() { + $window.scroll(Feedback._window_scroll); + $window.resize(Feedback._window_resize); + $(".ns-feedback .close-banner-button").click(Feedback._button_click); + }, + _window_scroll: function() { + updateVariables(); + + scrollFold = $window.scrollTop() + windowHeight; + + Feedback.toggleFeedback(); + Feedback.adjustNavigationPosition(); + }, + _window_resize: function() { + updateVariables(); + + Feedback.adjustArticleHeight(); + Feedback.toggleFeedback(); + Feedback.adjustNavigationPosition(); + }, + _button_click: function() { + Feedback.closeFeedback(); + Feedback.adjustNavigationPosition(); + }, + // #endregion + + + // #region adjusters + adjustNavigationPosition: function() { + var bottom = 0; + + if (!window.matchMedia('(max-width: 1200px)').matches) { + bottom = Math.max(feedbackPinned ? $("#feedback-section").outerHeight() : 0, scrollFold - feedbackOffsetTop ); + } + + $("#page-nav").css("bottom", bottom); + }, + adjustArticleHeight: function() { + $("#page-article").css("min-height", articleHeight); + }, + toggleFeedback: function() { + if (!shouldOverlayFeedback || showingFeedbackBar) { + return; + } + + if (scrollFold - $("#feedback-section").outerHeight() * 2 < feedbackOffsetTop) { + Feedback.pinFeedback(); + } + else { + Feedback.unpinFeedback(); + } + }, + // #endregion + + + // #region feedback bar + pinFeedback: function() { + feedbackPinned = true; + $("#feedback-section").addClass("-detached"); + }, + unpinFeedback: function() { + feedbackPinned = false; + $("#feedback-section").removeClass("-detached"); + }, + closeFeedback: function() { + shouldOverlayFeedback = false; + setCookieByName("yesNoFeedbackClosed"); + Feedback.unpinFeedback(); + } + // #endregion + + }); + + Feedback.init(); + + }); diff --git a/_assets/javascripts/prism.js b/_assets/javascripts/prism.js new file mode 100644 index 000000000..a03775ce5 --- /dev/null +++ b/_assets/javascripts/prism.js @@ -0,0 +1,18 @@ +/* PrismJS 1.17.1 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+c+csharp+java+json+kotlin+js-templates+typescript+objectivec+scss+js-extras+swift */ +var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(u){var c=/\blang(?:uage)?-([\w-]+)\b/i,a=0;var _={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function(e){return e instanceof L?new L(e.type,_.util.encode(e.content),e.alias):Array.isArray(e)?e.map(_.util.encode):e.replace(/&/g,"&").replace(/e.length)return;if(!(k instanceof L)){if(h&&y!=a.length-1){if(c.lastIndex=v,!(x=c.exec(e)))break;for(var b=x.index+(f&&x[1]?x[1].length:0),w=x.index+x[0].length,A=y,P=v,O=a.length;A"+n.content+""},!u.document)return u.addEventListener&&(_.disableWorkerMessageHandler||u.addEventListener("message",function(e){var a=JSON.parse(e.data),n=a.language,r=a.code,t=a.immediateClose;u.postMessage(_.highlight(r,_.languages[n],n)),t&&u.close()},!1)),_;var e=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();if(e&&(_.filename=e.src,e.hasAttribute("data-manual")&&(_.manual=!0)),!_.manual){function n(){_.manual||_.highlightAll()}"loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n):window.setTimeout(n,16):document.addEventListener("DOMContentLoaded",n)}return _}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); +Prism.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/i,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/i,inside:{punctuation:[/^=/,{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var n={"included-cdata":{pattern://i,inside:s}};n["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var i={};i[a]={pattern:RegExp("(<__[\\s\\S]*?>)(?:\\s*|[\\s\\S])*?(?=<\\/__>)".replace(/__/g,a),"i"),lookbehind:!0,greedy:!0,inside:n},Prism.languages.insertBefore("markup","cdata",i)}}),Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup; +!function(s){var t=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/,inside:{rule:/@[\w-]+/}},url:{pattern:RegExp("url\\((?:"+t.source+"|[^\n\r()]*)\\)","i"),inside:{function:/^url/i,punctuation:/^\(|\)$/}},selector:RegExp("[^{}\\s](?:[^{};\"']|"+t.source+")*?(?=\\s*\\{)"),string:{pattern:t,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var e=s.languages.markup;e&&(e.tag.addInlined("style","css"),s.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:e.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:s.languages.css}},alias:"language-css"}},e.tag))}(Prism); +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\b/,function:/\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/}; +Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},{pattern:/(^|[^.])\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,function:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=\s*($|[\r\n,.;})\]]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.js=Prism.languages.javascript; +Prism.languages.c=Prism.languages.extend("clike",{"class-name":{pattern:/(\b(?:enum|struct)\s+)\w+/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/,number:/(?:\b0x(?:[\da-f]+\.?[\da-f]*|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?)[ful]*/i}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+(?:[^\r\n\\]|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,alias:"property",inside:{string:{pattern:/(#\s*include\s*)(?:<.+?>|("|')(?:\\?.)+?\2)/,lookbehind:!0},directive:{pattern:/(#\s*)\b(?:define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/,lookbehind:!0,alias:"keyword"}}},constant:/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete Prism.languages.c.boolean; +Prism.languages.csharp=Prism.languages.extend("clike",{keyword:/\b(?:abstract|add|alias|as|ascending|async|await|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|descending|do|double|dynamic|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|from|get|global|goto|group|if|implicit|in|int|interface|internal|into|is|join|let|lock|long|namespace|new|null|object|operator|orderby|out|override|params|partial|private|protected|public|readonly|ref|remove|return|sbyte|sealed|select|set|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|value|var|virtual|void|volatile|where|while|yield)\b/,string:[{pattern:/@("|')(?:\1\1|\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0},{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*?\1/,greedy:!0}],"class-name":[{pattern:/\b[A-Z]\w*(?:\.\w+)*\b(?=\s+\w+)/,inside:{punctuation:/\./}},{pattern:/(\[)[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}},{pattern:/(\b(?:class|interface)\s+[A-Z]\w*(?:\.\w+)*\s*:\s*)[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}},{pattern:/((?:\b(?:class|interface|new)\s+)|(?:catch\s+\())[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}}],number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)f?/i,operator:/>>=?|<<=?|[-=]>|([-+&|?])\1|~|[-+*/%&|^!=<>]=?/,punctuation:/\?\.?|::|[{}[\];(),.:]/}),Prism.languages.insertBefore("csharp","class-name",{"generic-method":{pattern:/\w+\s*<[^>\r\n]+?>\s*(?=\()/,inside:{function:/^\w+/,"class-name":{pattern:/\b[A-Z]\w*(?:\.\w+)*\b/,inside:{punctuation:/\./}},keyword:Prism.languages.csharp.keyword,punctuation:/[<>(),.:]/}},preprocessor:{pattern:/(^\s*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(\s*#)\b(?:define|elif|else|endif|endregion|error|if|line|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}}),Prism.languages.dotnet=Prism.languages.cs=Prism.languages.csharp; +!function(e){var t=/\b(?:abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while|var|null|exports|module|open|opens|provides|requires|to|transitive|uses|with)\b/,a=/\b[A-Z](?:\w*[a-z]\w*)?\b/;e.languages.java=e.languages.extend("clike",{"class-name":[a,/\b[A-Z]\w*(?=\s+\w+\s*[;,=())])/],keyword:t,function:[e.languages.clike.function,{pattern:/(\:\:)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x[\da-f_]*\.?[\da-f_p+-]+\b|(?:\b\d[\d_]*\.?[\d_]*|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|([-+&|])\2|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),e.languages.insertBefore("java","class-name",{annotation:{alias:"punctuation",pattern:/(^|[^.])@\w+/,lookbehind:!0},namespace:{pattern:/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)[a-z]\w*(\.[a-z]\w*)+/,lookbehind:!0,inside:{punctuation:/\./}},generics:{pattern:/<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/,inside:{"class-name":a,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}}})}(Prism); +Prism.languages.json={property:{pattern:/"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,greedy:!0},string:{pattern:/"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,greedy:!0},comment:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,number:/-?\d+\.?\d*(e[+-]?\d+)?/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:true|false)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}}; +!function(e){e.languages.kotlin=e.languages.extend("clike",{keyword:{pattern:/(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/,lookbehind:!0},function:[/\w+(?=\s*\()/,{pattern:/(\.)\w+(?=\s*\{)/,lookbehind:!0}],number:/\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/,operator:/\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/}),delete e.languages.kotlin["class-name"],e.languages.insertBefore("kotlin","string",{"raw-string":{pattern:/("""|''')[\s\S]*?\1/,alias:"string"}}),e.languages.insertBefore("kotlin","keyword",{annotation:{pattern:/\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,alias:"builtin"}}),e.languages.insertBefore("kotlin","function",{label:{pattern:/\w+@|@\w+/,alias:"symbol"}});var n=[{pattern:/\$\{[^}]+\}/,inside:{delimiter:{pattern:/^\$\{|\}$/,alias:"variable"},rest:e.languages.kotlin}},{pattern:/\$\w+/,alias:"variable"}];e.languages.kotlin.string.inside=e.languages.kotlin["raw-string"].inside={interpolation:n}}(Prism); +!function(u){var e=u.languages.javascript["template-string"],n=e.pattern.source,a=e.inside.interpolation,i=a.inside["interpolation-punctuation"],r=a.pattern.source;function t(e,t){if(u.languages[e])return{pattern:RegExp("((?:"+t+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:e}}}}function o(e,t,n){var r={code:e,grammar:t,language:n};return u.hooks.run("before-tokenize",r),r.tokens=u.tokenize(r.code,r.grammar),u.hooks.run("after-tokenize",r),r.tokens}function d(e){var t={};t["interpolation-punctuation"]=i;var n=u.tokenize(e,t);if(3===n.length){var r=[1,1];r.push.apply(r,o(n[1],u.languages.javascript,"javascript")),n.splice.apply(n,r)}return new u.Token("interpolation",n,a.alias,e)}function c(a,e,i){var t=u.tokenize(a,{interpolation:{pattern:RegExp(r),lookbehind:!0}}),f=0,y={},n=o(t.map(function(e){if("string"==typeof e)return e;for(var t,n=e.content;-1!==a.indexOf((r=f++,t="___"+i.toUpperCase()+"_"+r+"___")););return y[t]=n,t;var r}).join(""),e,i),v=Object.keys(y);return f=0,function e(t){for(var n=0;n=v.length)return;var r=t[n];if("string"==typeof r||"string"==typeof r.content){var a=v[f],i="string"==typeof r?r:r.content,o=i.indexOf(a);if(-1!==o){++f;var s=i.substring(0,o),p=d(y[a]),l=i.substring(o+a.length),g=[];if(s&&g.push(s),g.push(p),l){var u=[l];e(u),g.push.apply(g,u)}"string"==typeof r?(t.splice.apply(t,[n,1].concat(g)),n+=g.length-1):r.content=g}}else{var c=r.content;Array.isArray(c)?e(c):e([c])}}}(n),new u.Token(i,n,"language-"+i,a)}u.languages.javascript["template-string"]=[t("css","\\b(?:styled(?:\\([^)]*\\))?(?:\\s*\\.\\s*\\w+(?:\\([^)]*\\))*)*|css(?:\\s*\\.\\s*(?:global|resolve))?|createGlobalStyle|keyframes)"),t("html","\\bhtml|\\.\\s*(?:inner|outer)HTML\\s*\\+?="),t("svg","\\bsvg"),t("markdown","\\b(?:md|markdown)"),t("graphql","\\b(?:gql|graphql(?:\\s*\\.\\s*experimental)?)"),e].filter(Boolean);var s={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};function f(e){return"string"==typeof e?e:Array.isArray(e)?e.map(f).join(""):f(e.content)}u.hooks.add("after-tokenize",function(e){e.language in s&&!function e(t){for(var n=0,r=t.length;n]?|\+\+?|!=?|<>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete Prism.languages.objectivec["class-name"]; +Prism.languages.scss=Prism.languages.extend("css",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},atrule:{pattern:/@[\w-]+(?:\([^()]+\)|[^(])*?(?=\s+[{;])/,inside:{rule:/@[\w-]+/}},url:/(?:[-a-z]+-)?url(?=\()/i,selector:{pattern:/(?=\S)[^@;{}()]?(?:[^@;{}()]|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}]+[:{][^}]+))/m,inside:{parent:{pattern:/&/,alias:"important"},placeholder:/%[-\w]+/,variable:/\$[-\w]+|#\{\$[-\w]+\}/}},property:{pattern:/(?:[\w-]|\$[-\w]+|#\{\$[-\w]+\})+(?=\s*:)/,inside:{variable:/\$[-\w]+|#\{\$[-\w]+\}/}}}),Prism.languages.insertBefore("scss","atrule",{keyword:[/@(?:if|else(?: if)?|for|each|while|import|extend|debug|warn|mixin|include|function|return|content)/i,{pattern:/( +)(?:from|through)(?= )/,lookbehind:!0}]}),Prism.languages.insertBefore("scss","important",{variable:/\$[-\w]+|#\{\$[-\w]+\}/}),Prism.languages.insertBefore("scss","function",{placeholder:{pattern:/%[-\w]+/,alias:"selector"},statement:{pattern:/\B!(?:default|optional)\b/i,alias:"keyword"},boolean:/\b(?:true|false)\b/,null:{pattern:/\bnull\b/,alias:"keyword"},operator:{pattern:/(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|or|not)(?=\s)/,lookbehind:!0}}),Prism.languages.scss.atrule.inside.rest=Prism.languages.scss; +!function(a){a.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+a.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),a.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+a.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),a.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:(?:Uint|Int)(?:8|16|32)|Uint8Clamped|Float(?:32|64))?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|(?:Weak)?(?:Set|Map)|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),a.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),a.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),a.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:/(\.\s*)#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*/,lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|location|navigator|performance|(?:local|session)Storage|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var e=["function","function-variable","method","method-variable","property-access"],t=0;t li { + position: relative; } + +.fa-li { + left: -2em; + position: absolute; + text-align: center; + width: 2em; + line-height: inherit; } + +.fa-border { + border: solid 0.08em #eee; + border-radius: .1em; + padding: .2em .25em .15em; } + +.fa-pull-left { + float: left; } + +.fa-pull-right { + float: right; } + +.fa.fa-pull-left, +.fas.fa-pull-left, +.far.fa-pull-left, +.fal.fa-pull-left, +.fab.fa-pull-left { + margin-right: .3em; } + +.fa.fa-pull-right, +.fas.fa-pull-right, +.far.fa-pull-right, +.fal.fa-pull-right, +.fab.fa-pull-right { + margin-left: .3em; } + +.fa-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; } + +.fa-pulse { + -webkit-animation: fa-spin 1s infinite steps(8); + animation: fa-spin 1s infinite steps(8); } + +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +.fa-rotate-90 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); } + +.fa-rotate-180 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; + -webkit-transform: rotate(180deg); + transform: rotate(180deg); } + +.fa-rotate-270 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; + -webkit-transform: rotate(270deg); + transform: rotate(270deg); } + +.fa-flip-horizontal { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; + -webkit-transform: scale(-1, 1); + transform: scale(-1, 1); } + +.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(1, -1); + transform: scale(1, -1); } + +.fa-flip-horizontal.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(-1, -1); + transform: scale(-1, -1); } + +:root .fa-rotate-90, +:root .fa-rotate-180, +:root .fa-rotate-270, +:root .fa-flip-horizontal, +:root .fa-flip-vertical { + -webkit-filter: none; + filter: none; } + +.fa-stack { + display: inline-block; + height: 2em; + line-height: 2em; + position: relative; + vertical-align: middle; + width: 2em; } + +.fa-stack-1x, +.fa-stack-2x { + left: 0; + position: absolute; + text-align: center; + width: 100%; } + +.fa-stack-1x { + line-height: inherit; } + +.fa-stack-2x { + font-size: 2em; } + +.fa-inverse { + color: #fff; } + +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen +readers do not read off random characters that represent icons */ +.fa-500px:before { + content: "\f26e"; } + +.fa-accessible-icon:before { + content: "\f368"; } + +.fa-accusoft:before { + content: "\f369"; } + +.fa-address-book:before { + content: "\f2b9"; } + +.fa-address-card:before { + content: "\f2bb"; } + +.fa-adjust:before { + content: "\f042"; } + +.fa-adn:before { + content: "\f170"; } + +.fa-adversal:before { + content: "\f36a"; } + +.fa-affiliatetheme:before { + content: "\f36b"; } + +.fa-alarm-clock:before { + content: "\f34e"; } + +.fa-algolia:before { + content: "\f36c"; } + +.fa-align-center:before { + content: "\f037"; } + +.fa-align-justify:before { + content: "\f039"; } + +.fa-align-left:before { + content: "\f036"; } + +.fa-align-right:before { + content: "\f038"; } + +.fa-allergies:before { + content: "\f461"; } + +.fa-amazon:before { + content: "\f270"; } + +.fa-amazon-pay:before { + content: "\f42c"; } + +.fa-ambulance:before { + content: "\f0f9"; } + +.fa-american-sign-language-interpreting:before { + content: "\f2a3"; } + +.fa-amilia:before { + content: "\f36d"; } + +.fa-anchor:before { + content: "\f13d"; } + +.fa-android:before { + content: "\f17b"; } + +.fa-angellist:before { + content: "\f209"; } + +.fa-angle-double-down:before { + content: "\f103"; } + +.fa-angle-double-left:before { + content: "\f100"; } + +.fa-angle-double-right:before { + content: "\f101"; } + +.fa-angle-double-up:before { + content: "\f102"; } + +.fa-angle-down:before { + content: "\f107"; } + +.fa-angle-left:before { + content: "\f104"; } + +.fa-angle-right:before { + content: "\f105"; } + +.fa-angle-up:before { + content: "\f106"; } + +.fa-angrycreative:before { + content: "\f36e"; } + +.fa-angular:before { + content: "\f420"; } + +.fa-app-store:before { + content: "\f36f"; } + +.fa-app-store-ios:before { + content: "\f370"; } + +.fa-apper:before { + content: "\f371"; } + +.fa-apple:before { + content: "\f179"; } + +.fa-apple-pay:before { + content: "\f415"; } + +.fa-archive:before { + content: "\f187"; } + +.fa-arrow-alt-circle-down:before { + content: "\f358"; } + +.fa-arrow-alt-circle-left:before { + content: "\f359"; } + +.fa-arrow-alt-circle-right:before { + content: "\f35a"; } + +.fa-arrow-alt-circle-up:before { + content: "\f35b"; } + +.fa-arrow-alt-down:before { + content: "\f354"; } + +.fa-arrow-alt-from-bottom:before { + content: "\f346"; } + +.fa-arrow-alt-from-left:before { + content: "\f347"; } + +.fa-arrow-alt-from-right:before { + content: "\f348"; } + +.fa-arrow-alt-from-top:before { + content: "\f349"; } + +.fa-arrow-alt-left:before { + content: "\f355"; } + +.fa-arrow-alt-right:before { + content: "\f356"; } + +.fa-arrow-alt-square-down:before { + content: "\f350"; } + +.fa-arrow-alt-square-left:before { + content: "\f351"; } + +.fa-arrow-alt-square-right:before { + content: "\f352"; } + +.fa-arrow-alt-square-up:before { + content: "\f353"; } + +.fa-arrow-alt-to-bottom:before { + content: "\f34a"; } + +.fa-arrow-alt-to-left:before { + content: "\f34b"; } + +.fa-arrow-alt-to-right:before { + content: "\f34c"; } + +.fa-arrow-alt-to-top:before { + content: "\f34d"; } + +.fa-arrow-alt-up:before { + content: "\f357"; } + +.fa-arrow-circle-down:before { + content: "\f0ab"; } + +.fa-arrow-circle-left:before { + content: "\f0a8"; } + +.fa-arrow-circle-right:before { + content: "\f0a9"; } + +.fa-arrow-circle-up:before { + content: "\f0aa"; } + +.fa-arrow-down:before { + content: "\f063"; } + +.fa-arrow-from-bottom:before { + content: "\f342"; } + +.fa-arrow-from-left:before { + content: "\f343"; } + +.fa-arrow-from-right:before { + content: "\f344"; } + +.fa-arrow-from-top:before { + content: "\f345"; } + +.fa-arrow-left:before { + content: "\f060"; } + +.fa-arrow-right:before { + content: "\f061"; } + +.fa-arrow-square-down:before { + content: "\f339"; } + +.fa-arrow-square-left:before { + content: "\f33a"; } + +.fa-arrow-square-right:before { + content: "\f33b"; } + +.fa-arrow-square-up:before { + content: "\f33c"; } + +.fa-arrow-to-bottom:before { + content: "\f33d"; } + +.fa-arrow-to-left:before { + content: "\f33e"; } + +.fa-arrow-to-right:before { + content: "\f340"; } + +.fa-arrow-to-top:before { + content: "\f341"; } + +.fa-arrow-up:before { + content: "\f062"; } + +.fa-arrows:before { + content: "\f047"; } + +.fa-arrows-alt:before { + content: "\f0b2"; } + +.fa-arrows-alt-h:before { + content: "\f337"; } + +.fa-arrows-alt-v:before { + content: "\f338"; } + +.fa-arrows-h:before { + content: "\f07e"; } + +.fa-arrows-v:before { + content: "\f07d"; } + +.fa-assistive-listening-systems:before { + content: "\f2a2"; } + +.fa-asterisk:before { + content: "\f069"; } + +.fa-asymmetrik:before { + content: "\f372"; } + +.fa-at:before { + content: "\f1fa"; } + +.fa-audible:before { + content: "\f373"; } + +.fa-audio-description:before { + content: "\f29e"; } + +.fa-autoprefixer:before { + content: "\f41c"; } + +.fa-avianex:before { + content: "\f374"; } + +.fa-aviato:before { + content: "\f421"; } + +.fa-aws:before { + content: "\f375"; } + +.fa-backward:before { + content: "\f04a"; } + +.fa-badge:before { + content: "\f335"; } + +.fa-badge-check:before { + content: "\f336"; } + +.fa-balance-scale:before { + content: "\f24e"; } + +.fa-balance-scale-left:before { + content: "\f515"; } + +.fa-balance-scale-right:before { + content: "\f516"; } + +.fa-ban:before { + content: "\f05e"; } + +.fa-band-aid:before { + content: "\f462"; } + +.fa-bandcamp:before { + content: "\f2d5"; } + +.fa-barcode:before { + content: "\f02a"; } + +.fa-barcode-alt:before { + content: "\f463"; } + +.fa-barcode-read:before { + content: "\f464"; } + +.fa-barcode-scan:before { + content: "\f465"; } + +.fa-bars:before { + content: "\f0c9"; } + +.fa-baseball:before { + content: "\f432"; } + +.fa-baseball-ball:before { + content: "\f433"; } + +.fa-basketball-ball:before { + content: "\f434"; } + +.fa-basketball-hoop:before { + content: "\f435"; } + +.fa-bath:before { + content: "\f2cd"; } + +.fa-battery-bolt:before { + content: "\f376"; } + +.fa-battery-empty:before { + content: "\f244"; } + +.fa-battery-full:before { + content: "\f240"; } + +.fa-battery-half:before { + content: "\f242"; } + +.fa-battery-quarter:before { + content: "\f243"; } + +.fa-battery-slash:before { + content: "\f377"; } + +.fa-battery-three-quarters:before { + content: "\f241"; } + +.fa-bed:before { + content: "\f236"; } + +.fa-beer:before { + content: "\f0fc"; } + +.fa-behance:before { + content: "\f1b4"; } + +.fa-behance-square:before { + content: "\f1b5"; } + +.fa-bell:before { + content: "\f0f3"; } + +.fa-bell-slash:before { + content: "\f1f6"; } + +.fa-bicycle:before { + content: "\f206"; } + +.fa-bimobject:before { + content: "\f378"; } + +.fa-binoculars:before { + content: "\f1e5"; } + +.fa-birthday-cake:before { + content: "\f1fd"; } + +.fa-bitbucket:before { + content: "\f171"; } + +.fa-bitcoin:before { + content: "\f379"; } + +.fa-bity:before { + content: "\f37a"; } + +.fa-black-tie:before { + content: "\f27e"; } + +.fa-blackberry:before { + content: "\f37b"; } + +.fa-blanket:before { + content: "\f498"; } + +.fa-blender:before { + content: "\f517"; } + +.fa-blind:before { + content: "\f29d"; } + +.fa-blogger:before { + content: "\f37c"; } + +.fa-blogger-b:before { + content: "\f37d"; } + +.fa-bluetooth:before { + content: "\f293"; } + +.fa-bluetooth-b:before { + content: "\f294"; } + +.fa-bold:before { + content: "\f032"; } + +.fa-bolt:before { + content: "\f0e7"; } + +.fa-bomb:before { + content: "\f1e2"; } + +.fa-book:before { + content: "\f02d"; } + +.fa-book-heart:before { + content: "\f499"; } + +.fa-book-open:before { + content: "\f518"; } + +.fa-bookmark:before { + content: "\f02e"; } + +.fa-bowling-ball:before { + content: "\f436"; } + +.fa-bowling-pins:before { + content: "\f437"; } + +.fa-box:before { + content: "\f466"; } + +.fa-box-alt:before { + content: "\f49a"; } + +.fa-box-check:before { + content: "\f467"; } + +.fa-box-fragile:before { + content: "\f49b"; } + +.fa-box-full:before { + content: "\f49c"; } + +.fa-box-heart:before { + content: "\f49d"; } + +.fa-box-open:before { + content: "\f49e"; } + +.fa-box-up:before { + content: "\f49f"; } + +.fa-box-usd:before { + content: "\f4a0"; } + +.fa-boxes:before { + content: "\f468"; } + +.fa-boxes-alt:before { + content: "\f4a1"; } + +.fa-boxing-glove:before { + content: "\f438"; } + +.fa-braille:before { + content: "\f2a1"; } + +.fa-briefcase:before { + content: "\f0b1"; } + +.fa-briefcase-medical:before { + content: "\f469"; } + +.fa-broadcast-tower:before { + content: "\f519"; } + +.fa-broom:before { + content: "\f51a"; } + +.fa-browser:before { + content: "\f37e"; } + +.fa-btc:before { + content: "\f15a"; } + +.fa-bug:before { + content: "\f188"; } + +.fa-building:before { + content: "\f1ad"; } + +.fa-bullhorn:before { + content: "\f0a1"; } + +.fa-bullseye:before { + content: "\f140"; } + +.fa-burn:before { + content: "\f46a"; } + +.fa-buromobelexperte:before { + content: "\f37f"; } + +.fa-bus:before { + content: "\f207"; } + +.fa-buysellads:before { + content: "\f20d"; } + +.fa-calculator:before { + content: "\f1ec"; } + +.fa-calendar:before { + content: "\f133"; } + +.fa-calendar-alt:before { + content: "\f073"; } + +.fa-calendar-check:before { + content: "\f274"; } + +.fa-calendar-edit:before { + content: "\f333"; } + +.fa-calendar-exclamation:before { + content: "\f334"; } + +.fa-calendar-minus:before { + content: "\f272"; } + +.fa-calendar-plus:before { + content: "\f271"; } + +.fa-calendar-times:before { + content: "\f273"; } + +.fa-camera:before { + content: "\f030"; } + +.fa-camera-alt:before { + content: "\f332"; } + +.fa-camera-retro:before { + content: "\f083"; } + +.fa-capsules:before { + content: "\f46b"; } + +.fa-car:before { + content: "\f1b9"; } + +.fa-caret-circle-down:before { + content: "\f32d"; } + +.fa-caret-circle-left:before { + content: "\f32e"; } + +.fa-caret-circle-right:before { + content: "\f330"; } + +.fa-caret-circle-up:before { + content: "\f331"; } + +.fa-caret-down:before { + content: "\f0d7"; } + +.fa-caret-left:before { + content: "\f0d9"; } + +.fa-caret-right:before { + content: "\f0da"; } + +.fa-caret-square-down:before { + content: "\f150"; } + +.fa-caret-square-left:before { + content: "\f191"; } + +.fa-caret-square-right:before { + content: "\f152"; } + +.fa-caret-square-up:before { + content: "\f151"; } + +.fa-caret-up:before { + content: "\f0d8"; } + +.fa-cart-arrow-down:before { + content: "\f218"; } + +.fa-cart-plus:before { + content: "\f217"; } + +.fa-cc-amazon-pay:before { + content: "\f42d"; } + +.fa-cc-amex:before { + content: "\f1f3"; } + +.fa-cc-apple-pay:before { + content: "\f416"; } + +.fa-cc-diners-club:before { + content: "\f24c"; } + +.fa-cc-discover:before { + content: "\f1f2"; } + +.fa-cc-jcb:before { + content: "\f24b"; } + +.fa-cc-mastercard:before { + content: "\f1f1"; } + +.fa-cc-paypal:before { + content: "\f1f4"; } + +.fa-cc-stripe:before { + content: "\f1f5"; } + +.fa-cc-visa:before { + content: "\f1f0"; } + +.fa-centercode:before { + content: "\f380"; } + +.fa-certificate:before { + content: "\f0a3"; } + +.fa-chalkboard:before { + content: "\f51b"; } + +.fa-chalkboard-teacher:before { + content: "\f51c"; } + +.fa-chart-area:before { + content: "\f1fe"; } + +.fa-chart-bar:before { + content: "\f080"; } + +.fa-chart-line:before { + content: "\f201"; } + +.fa-chart-pie:before { + content: "\f200"; } + +.fa-check:before { + content: "\f00c"; } + +.fa-check-circle:before { + content: "\f058"; } + +.fa-check-square:before { + content: "\f14a"; } + +.fa-chess:before { + content: "\f439"; } + +.fa-chess-bishop:before { + content: "\f43a"; } + +.fa-chess-bishop-alt:before { + content: "\f43b"; } + +.fa-chess-board:before { + content: "\f43c"; } + +.fa-chess-clock:before { + content: "\f43d"; } + +.fa-chess-clock-alt:before { + content: "\f43e"; } + +.fa-chess-king:before { + content: "\f43f"; } + +.fa-chess-king-alt:before { + content: "\f440"; } + +.fa-chess-knight:before { + content: "\f441"; } + +.fa-chess-knight-alt:before { + content: "\f442"; } + +.fa-chess-pawn:before { + content: "\f443"; } + +.fa-chess-pawn-alt:before { + content: "\f444"; } + +.fa-chess-queen:before { + content: "\f445"; } + +.fa-chess-queen-alt:before { + content: "\f446"; } + +.fa-chess-rook:before { + content: "\f447"; } + +.fa-chess-rook-alt:before { + content: "\f448"; } + +.fa-chevron-circle-down:before { + content: "\f13a"; } + +.fa-chevron-circle-left:before { + content: "\f137"; } + +.fa-chevron-circle-right:before { + content: "\f138"; } + +.fa-chevron-circle-up:before { + content: "\f139"; } + +.fa-chevron-double-down:before { + content: "\f322"; } + +.fa-chevron-double-left:before { + content: "\f323"; } + +.fa-chevron-double-right:before { + content: "\f324"; } + +.fa-chevron-double-up:before { + content: "\f325"; } + +.fa-chevron-down:before { + content: "\f078"; } + +.fa-chevron-left:before { + content: "\f053"; } + +.fa-chevron-right:before { + content: "\f054"; } + +.fa-chevron-square-down:before { + content: "\f329"; } + +.fa-chevron-square-left:before { + content: "\f32a"; } + +.fa-chevron-square-right:before { + content: "\f32b"; } + +.fa-chevron-square-up:before { + content: "\f32c"; } + +.fa-chevron-up:before { + content: "\f077"; } + +.fa-child:before { + content: "\f1ae"; } + +.fa-chrome:before { + content: "\f268"; } + +.fa-church:before { + content: "\f51d"; } + +.fa-circle:before { + content: "\f111"; } + +.fa-circle-notch:before { + content: "\f1ce"; } + +.fa-clipboard:before { + content: "\f328"; } + +.fa-clipboard-check:before { + content: "\f46c"; } + +.fa-clipboard-list:before { + content: "\f46d"; } + +.fa-clock:before { + content: "\f017"; } + +.fa-clone:before { + content: "\f24d"; } + +.fa-closed-captioning:before { + content: "\f20a"; } + +.fa-cloud:before { + content: "\f0c2"; } + +.fa-cloud-download:before { + content: "\f0ed"; } + +.fa-cloud-download-alt:before { + content: "\f381"; } + +.fa-cloud-upload:before { + content: "\f0ee"; } + +.fa-cloud-upload-alt:before { + content: "\f382"; } + +.fa-cloudscale:before { + content: "\f383"; } + +.fa-cloudsmith:before { + content: "\f384"; } + +.fa-cloudversify:before { + content: "\f385"; } + +.fa-club:before { + content: "\f327"; } + +.fa-code:before { + content: "\f121"; } + +.fa-code-branch:before { + content: "\f126"; } + +.fa-code-commit:before { + content: "\f386"; } + +.fa-code-merge:before { + content: "\f387"; } + +.fa-codepen:before { + content: "\f1cb"; } + +.fa-codiepie:before { + content: "\f284"; } + +.fa-coffee:before { + content: "\f0f4"; } + +.fa-cog:before { + content: "\f013"; } + +.fa-cogs:before { + content: "\f085"; } + +.fa-coins:before { + content: "\f51e"; } + +.fa-columns:before { + content: "\f0db"; } + +.fa-comment:before { + content: "\f075"; } + +.fa-comment-alt:before { + content: "\f27a"; } + +.fa-comment-alt-check:before { + content: "\f4a2"; } + +.fa-comment-alt-dots:before { + content: "\f4a3"; } + +.fa-comment-alt-edit:before { + content: "\f4a4"; } + +.fa-comment-alt-exclamation:before { + content: "\f4a5"; } + +.fa-comment-alt-lines:before { + content: "\f4a6"; } + +.fa-comment-alt-minus:before { + content: "\f4a7"; } + +.fa-comment-alt-plus:before { + content: "\f4a8"; } + +.fa-comment-alt-slash:before { + content: "\f4a9"; } + +.fa-comment-alt-smile:before { + content: "\f4aa"; } + +.fa-comment-alt-times:before { + content: "\f4ab"; } + +.fa-comment-check:before { + content: "\f4ac"; } + +.fa-comment-dots:before { + content: "\f4ad"; } + +.fa-comment-edit:before { + content: "\f4ae"; } + +.fa-comment-exclamation:before { + content: "\f4af"; } + +.fa-comment-lines:before { + content: "\f4b0"; } + +.fa-comment-minus:before { + content: "\f4b1"; } + +.fa-comment-plus:before { + content: "\f4b2"; } + +.fa-comment-slash:before { + content: "\f4b3"; } + +.fa-comment-smile:before { + content: "\f4b4"; } + +.fa-comment-times:before { + content: "\f4b5"; } + +.fa-comments:before { + content: "\f086"; } + +.fa-comments-alt:before { + content: "\f4b6"; } + +.fa-compact-disc:before { + content: "\f51f"; } + +.fa-compass:before { + content: "\f14e"; } + +.fa-compress:before { + content: "\f066"; } + +.fa-compress-alt:before { + content: "\f422"; } + +.fa-compress-wide:before { + content: "\f326"; } + +.fa-connectdevelop:before { + content: "\f20e"; } + +.fa-container-storage:before { + content: "\f4b7"; } + +.fa-contao:before { + content: "\f26d"; } + +.fa-conveyor-belt:before { + content: "\f46e"; } + +.fa-conveyor-belt-alt:before { + content: "\f46f"; } + +.fa-copy:before { + content: "\f0c5"; } + +.fa-copyright:before { + content: "\f1f9"; } + +.fa-couch:before { + content: "\f4b8"; } + +.fa-cpanel:before { + content: "\f388"; } + +.fa-creative-commons:before { + content: "\f25e"; } + +.fa-creative-commons-by:before { + content: "\f4e7"; } + +.fa-creative-commons-nc:before { + content: "\f4e8"; } + +.fa-creative-commons-nc-eu:before { + content: "\f4e9"; } + +.fa-creative-commons-nc-jp:before { + content: "\f4ea"; } + +.fa-creative-commons-nd:before { + content: "\f4eb"; } + +.fa-creative-commons-pd:before { + content: "\f4ec"; } + +.fa-creative-commons-pd-alt:before { + content: "\f4ed"; } + +.fa-creative-commons-remix:before { + content: "\f4ee"; } + +.fa-creative-commons-sa:before { + content: "\f4ef"; } + +.fa-creative-commons-sampling:before { + content: "\f4f0"; } + +.fa-creative-commons-sampling-plus:before { + content: "\f4f1"; } + +.fa-creative-commons-share:before { + content: "\f4f2"; } + +.fa-creative-commons-zero:before { + content: "\f4f3"; } + +.fa-credit-card:before { + content: "\f09d"; } + +.fa-credit-card-blank:before { + content: "\f389"; } + +.fa-credit-card-front:before { + content: "\f38a"; } + +.fa-cricket:before { + content: "\f449"; } + +.fa-crop:before { + content: "\f125"; } + +.fa-crosshairs:before { + content: "\f05b"; } + +.fa-crow:before { + content: "\f520"; } + +.fa-crown:before { + content: "\f521"; } + +.fa-css3:before { + content: "\f13c"; } + +.fa-css3-alt:before { + content: "\f38b"; } + +.fa-cube:before { + content: "\f1b2"; } + +.fa-cubes:before { + content: "\f1b3"; } + +.fa-curling:before { + content: "\f44a"; } + +.fa-cut:before { + content: "\f0c4"; } + +.fa-cuttlefish:before { + content: "\f38c"; } + +.fa-d-and-d:before { + content: "\f38d"; } + +.fa-dashcube:before { + content: "\f210"; } + +.fa-database:before { + content: "\f1c0"; } + +.fa-deaf:before { + content: "\f2a4"; } + +.fa-delicious:before { + content: "\f1a5"; } + +.fa-deploydog:before { + content: "\f38e"; } + +.fa-deskpro:before { + content: "\f38f"; } + +.fa-desktop:before { + content: "\f108"; } + +.fa-desktop-alt:before { + content: "\f390"; } + +.fa-deviantart:before { + content: "\f1bd"; } + +.fa-diagnoses:before { + content: "\f470"; } + +.fa-diamond:before { + content: "\f219"; } + +.fa-dice:before { + content: "\f522"; } + +.fa-dice-five:before { + content: "\f523"; } + +.fa-dice-four:before { + content: "\f524"; } + +.fa-dice-one:before { + content: "\f525"; } + +.fa-dice-six:before { + content: "\f526"; } + +.fa-dice-three:before { + content: "\f527"; } + +.fa-dice-two:before { + content: "\f528"; } + +.fa-digg:before { + content: "\f1a6"; } + +.fa-digital-ocean:before { + content: "\f391"; } + +.fa-discord:before { + content: "\f392"; } + +.fa-discourse:before { + content: "\f393"; } + +.fa-divide:before { + content: "\f529"; } + +.fa-dna:before { + content: "\f471"; } + +.fa-dochub:before { + content: "\f394"; } + +.fa-docker:before { + content: "\f395"; } + +.fa-dollar-sign:before { + content: "\f155"; } + +.fa-dolly:before { + content: "\f472"; } + +.fa-dolly-empty:before { + content: "\f473"; } + +.fa-dolly-flatbed:before { + content: "\f474"; } + +.fa-dolly-flatbed-alt:before { + content: "\f475"; } + +.fa-dolly-flatbed-empty:before { + content: "\f476"; } + +.fa-donate:before { + content: "\f4b9"; } + +.fa-door-closed:before { + content: "\f52a"; } + +.fa-door-open:before { + content: "\f52b"; } + +.fa-dot-circle:before { + content: "\f192"; } + +.fa-dove:before { + content: "\f4ba"; } + +.fa-download:before { + content: "\f019"; } + +.fa-draft2digital:before { + content: "\f396"; } + +.fa-dribbble:before { + content: "\f17d"; } + +.fa-dribbble-square:before { + content: "\f397"; } + +.fa-dropbox:before { + content: "\f16b"; } + +.fa-drupal:before { + content: "\f1a9"; } + +.fa-dumbbell:before { + content: "\f44b"; } + +.fa-dyalog:before { + content: "\f399"; } + +.fa-earlybirds:before { + content: "\f39a"; } + +.fa-ebay:before { + content: "\f4f4"; } + +.fa-edge:before { + content: "\f282"; } + +.fa-edit:before { + content: "\f044"; } + +.fa-eject:before { + content: "\f052"; } + +.fa-elementor:before { + content: "\f430"; } + +.fa-ellipsis-h:before { + content: "\f141"; } + +.fa-ellipsis-h-alt:before { + content: "\f39b"; } + +.fa-ellipsis-v:before { + content: "\f142"; } + +.fa-ellipsis-v-alt:before { + content: "\f39c"; } + +.fa-ember:before { + content: "\f423"; } + +.fa-empire:before { + content: "\f1d1"; } + +.fa-envelope:before { + content: "\f0e0"; } + +.fa-envelope-open:before { + content: "\f2b6"; } + +.fa-envelope-square:before { + content: "\f199"; } + +.fa-envira:before { + content: "\f299"; } + +.fa-equals:before { + content: "\f52c"; } + +.fa-eraser:before { + content: "\f12d"; } + +.fa-erlang:before { + content: "\f39d"; } + +.fa-ethereum:before { + content: "\f42e"; } + +.fa-etsy:before { + content: "\f2d7"; } + +.fa-euro-sign:before { + content: "\f153"; } + +.fa-exchange:before { + content: "\f0ec"; } + +.fa-exchange-alt:before { + content: "\f362"; } + +.fa-exclamation:before { + content: "\f12a"; } + +.fa-exclamation-circle:before { + content: "\f06a"; } + +.fa-exclamation-square:before { + content: "\f321"; } + +.fa-exclamation-triangle:before { + content: "\f071"; } + +.fa-expand:before { + content: "\f065"; } + +.fa-expand-alt:before { + content: "\f424"; } + +.fa-expand-arrows:before { + content: "\f31d"; } + +.fa-expand-arrows-alt:before { + content: "\f31e"; } + +.fa-expand-wide:before { + content: "\f320"; } + +.fa-expeditedssl:before { + content: "\f23e"; } + +.fa-external-link:before { + content: "\f08e"; } + +.fa-external-link-alt:before { + content: "\f35d"; } + +.fa-external-link-square:before { + content: "\f14c"; } + +.fa-external-link-square-alt:before { + content: "\f360"; } + +.fa-eye:before { + content: "\f06e"; } + +.fa-eye-dropper:before { + content: "\f1fb"; } + +.fa-eye-slash:before { + content: "\f070"; } + +.fa-facebook:before { + content: "\f09a"; } + +.fa-facebook-f:before { + content: "\f39e"; } + +.fa-facebook-messenger:before { + content: "\f39f"; } + +.fa-facebook-square:before { + content: "\f082"; } + +.fa-fast-backward:before { + content: "\f049"; } + +.fa-fast-forward:before { + content: "\f050"; } + +.fa-fax:before { + content: "\f1ac"; } + +.fa-feather:before { + content: "\f52d"; } + +.fa-female:before { + content: "\f182"; } + +.fa-field-hockey:before { + content: "\f44c"; } + +.fa-fighter-jet:before { + content: "\f0fb"; } + +.fa-file:before { + content: "\f15b"; } + +.fa-file-alt:before { + content: "\f15c"; } + +.fa-file-archive:before { + content: "\f1c6"; } + +.fa-file-audio:before { + content: "\f1c7"; } + +.fa-file-check:before { + content: "\f316"; } + +.fa-file-code:before { + content: "\f1c9"; } + +.fa-file-edit:before { + content: "\f31c"; } + +.fa-file-excel:before { + content: "\f1c3"; } + +.fa-file-exclamation:before { + content: "\f31a"; } + +.fa-file-image:before { + content: "\f1c5"; } + +.fa-file-medical:before { + content: "\f477"; } + +.fa-file-medical-alt:before { + content: "\f478"; } + +.fa-file-minus:before { + content: "\f318"; } + +.fa-file-pdf:before { + content: "\f1c1"; } + +.fa-file-plus:before { + content: "\f319"; } + +.fa-file-powerpoint:before { + content: "\f1c4"; } + +.fa-file-times:before { + content: "\f317"; } + +.fa-file-video:before { + content: "\f1c8"; } + +.fa-file-word:before { + content: "\f1c2"; } + +.fa-film:before { + content: "\f008"; } + +.fa-film-alt:before { + content: "\f3a0"; } + +.fa-filter:before { + content: "\f0b0"; } + +.fa-fire:before { + content: "\f06d"; } + +.fa-fire-extinguisher:before { + content: "\f134"; } + +.fa-firefox:before { + content: "\f269"; } + +.fa-first-aid:before { + content: "\f479"; } + +.fa-first-order:before { + content: "\f2b0"; } + +.fa-first-order-alt:before { + content: "\f50a"; } + +.fa-firstdraft:before { + content: "\f3a1"; } + +.fa-flag:before { + content: "\f024"; } + +.fa-flag-checkered:before { + content: "\f11e"; } + +.fa-flask:before { + content: "\f0c3"; } + +.fa-flickr:before { + content: "\f16e"; } + +.fa-flipboard:before { + content: "\f44d"; } + +.fa-fly:before { + content: "\f417"; } + +.fa-folder:before { + content: "\f07b"; } + +.fa-folder-open:before { + content: "\f07c"; } + +.fa-font:before { + content: "\f031"; } + +.fa-font-awesome:before { + content: "\f2b4"; } + +.fa-font-awesome-alt:before { + content: "\f35c"; } + +.fa-font-awesome-flag:before { + content: "\f425"; } + +.fa-font-awesome-logo-full:before { + content: "\f4e6"; } + +.fa-fonticons:before { + content: "\f280"; } + +.fa-fonticons-fi:before { + content: "\f3a2"; } + +.fa-football-ball:before { + content: "\f44e"; } + +.fa-football-helmet:before { + content: "\f44f"; } + +.fa-forklift:before { + content: "\f47a"; } + +.fa-fort-awesome:before { + content: "\f286"; } + +.fa-fort-awesome-alt:before { + content: "\f3a3"; } + +.fa-forumbee:before { + content: "\f211"; } + +.fa-forward:before { + content: "\f04e"; } + +.fa-foursquare:before { + content: "\f180"; } + +.fa-fragile:before { + content: "\f4bb"; } + +.fa-free-code-camp:before { + content: "\f2c5"; } + +.fa-freebsd:before { + content: "\f3a4"; } + +.fa-frog:before { + content: "\f52e"; } + +.fa-frown:before { + content: "\f119"; } + +.fa-fulcrum:before { + content: "\f50b"; } + +.fa-futbol:before { + content: "\f1e3"; } + +.fa-galactic-republic:before { + content: "\f50c"; } + +.fa-galactic-senate:before { + content: "\f50d"; } + +.fa-gamepad:before { + content: "\f11b"; } + +.fa-gas-pump:before { + content: "\f52f"; } + +.fa-gavel:before { + content: "\f0e3"; } + +.fa-gem:before { + content: "\f3a5"; } + +.fa-genderless:before { + content: "\f22d"; } + +.fa-get-pocket:before { + content: "\f265"; } + +.fa-gg:before { + content: "\f260"; } + +.fa-gg-circle:before { + content: "\f261"; } + +.fa-gift:before { + content: "\f06b"; } + +.fa-git:before { + content: "\f1d3"; } + +.fa-git-square:before { + content: "\f1d2"; } + +.fa-github:before { + content: "\f09b"; } + +.fa-github-alt:before { + content: "\f113"; } + +.fa-github-square:before { + content: "\f092"; } + +.fa-gitkraken:before { + content: "\f3a6"; } + +.fa-gitlab:before { + content: "\f296"; } + +.fa-gitter:before { + content: "\f426"; } + +.fa-glass-martini:before { + content: "\f000"; } + +.fa-glasses:before { + content: "\f530"; } + +.fa-glide:before { + content: "\f2a5"; } + +.fa-glide-g:before { + content: "\f2a6"; } + +.fa-globe:before { + content: "\f0ac"; } + +.fa-gofore:before { + content: "\f3a7"; } + +.fa-golf-ball:before { + content: "\f450"; } + +.fa-golf-club:before { + content: "\f451"; } + +.fa-goodreads:before { + content: "\f3a8"; } + +.fa-goodreads-g:before { + content: "\f3a9"; } + +.fa-google:before { + content: "\f1a0"; } + +.fa-google-drive:before { + content: "\f3aa"; } + +.fa-google-play:before { + content: "\f3ab"; } + +.fa-google-plus:before { + content: "\f2b3"; } + +.fa-google-plus-g:before { + content: "\f0d5"; } + +.fa-google-plus-square:before { + content: "\f0d4"; } + +.fa-google-wallet:before { + content: "\f1ee"; } + +.fa-graduation-cap:before { + content: "\f19d"; } + +.fa-gratipay:before { + content: "\f184"; } + +.fa-grav:before { + content: "\f2d6"; } + +.fa-greater-than:before { + content: "\f531"; } + +.fa-greater-than-equal:before { + content: "\f532"; } + +.fa-gripfire:before { + content: "\f3ac"; } + +.fa-grunt:before { + content: "\f3ad"; } + +.fa-gulp:before { + content: "\f3ae"; } + +.fa-h-square:before { + content: "\f0fd"; } + +.fa-h1:before { + content: "\f313"; } + +.fa-h2:before { + content: "\f314"; } + +.fa-h3:before { + content: "\f315"; } + +.fa-hacker-news:before { + content: "\f1d4"; } + +.fa-hacker-news-square:before { + content: "\f3af"; } + +.fa-hand-heart:before { + content: "\f4bc"; } + +.fa-hand-holding:before { + content: "\f4bd"; } + +.fa-hand-holding-box:before { + content: "\f47b"; } + +.fa-hand-holding-heart:before { + content: "\f4be"; } + +.fa-hand-holding-seedling:before { + content: "\f4bf"; } + +.fa-hand-holding-usd:before { + content: "\f4c0"; } + +.fa-hand-holding-water:before { + content: "\f4c1"; } + +.fa-hand-lizard:before { + content: "\f258"; } + +.fa-hand-paper:before { + content: "\f256"; } + +.fa-hand-peace:before { + content: "\f25b"; } + +.fa-hand-point-down:before { + content: "\f0a7"; } + +.fa-hand-point-left:before { + content: "\f0a5"; } + +.fa-hand-point-right:before { + content: "\f0a4"; } + +.fa-hand-point-up:before { + content: "\f0a6"; } + +.fa-hand-pointer:before { + content: "\f25a"; } + +.fa-hand-receiving:before { + content: "\f47c"; } + +.fa-hand-rock:before { + content: "\f255"; } + +.fa-hand-scissors:before { + content: "\f257"; } + +.fa-hand-spock:before { + content: "\f259"; } + +.fa-hands:before { + content: "\f4c2"; } + +.fa-hands-heart:before { + content: "\f4c3"; } + +.fa-hands-helping:before { + content: "\f4c4"; } + +.fa-hands-usd:before { + content: "\f4c5"; } + +.fa-handshake:before { + content: "\f2b5"; } + +.fa-handshake-alt:before { + content: "\f4c6"; } + +.fa-hashtag:before { + content: "\f292"; } + +.fa-hdd:before { + content: "\f0a0"; } + +.fa-heading:before { + content: "\f1dc"; } + +.fa-headphones:before { + content: "\f025"; } + +.fa-heart:before { + content: "\f004"; } + +.fa-heart-circle:before { + content: "\f4c7"; } + +.fa-heart-square:before { + content: "\f4c8"; } + +.fa-heartbeat:before { + content: "\f21e"; } + +.fa-helicopter:before { + content: "\f533"; } + +.fa-hexagon:before { + content: "\f312"; } + +.fa-hips:before { + content: "\f452"; } + +.fa-hire-a-helper:before { + content: "\f3b0"; } + +.fa-history:before { + content: "\f1da"; } + +.fa-hockey-puck:before { + content: "\f453"; } + +.fa-hockey-sticks:before { + content: "\f454"; } + +.fa-home:before { + content: "\f015"; } + +.fa-home-heart:before { + content: "\f4c9"; } + +.fa-hooli:before { + content: "\f427"; } + +.fa-hospital:before { + content: "\f0f8"; } + +.fa-hospital-alt:before { + content: "\f47d"; } + +.fa-hospital-symbol:before { + content: "\f47e"; } + +.fa-hotjar:before { + content: "\f3b1"; } + +.fa-hourglass:before { + content: "\f254"; } + +.fa-hourglass-end:before { + content: "\f253"; } + +.fa-hourglass-half:before { + content: "\f252"; } + +.fa-hourglass-start:before { + content: "\f251"; } + +.fa-houzz:before { + content: "\f27c"; } + +.fa-html5:before { + content: "\f13b"; } + +.fa-hubspot:before { + content: "\f3b2"; } + +.fa-i-cursor:before { + content: "\f246"; } + +.fa-id-badge:before { + content: "\f2c1"; } + +.fa-id-card:before { + content: "\f2c2"; } + +.fa-id-card-alt:before { + content: "\f47f"; } + +.fa-image:before { + content: "\f03e"; } + +.fa-images:before { + content: "\f302"; } + +.fa-imdb:before { + content: "\f2d8"; } + +.fa-inbox:before { + content: "\f01c"; } + +.fa-inbox-in:before { + content: "\f310"; } + +.fa-inbox-out:before { + content: "\f311"; } + +.fa-indent:before { + content: "\f03c"; } + +.fa-industry:before { + content: "\f275"; } + +.fa-industry-alt:before { + content: "\f3b3"; } + +.fa-infinity:before { + content: "\f534"; } + +.fa-info:before { + content: "\f129"; } + +.fa-info-circle:before { + content: "\f05a"; } + +.fa-info-square:before { + content: "\f30f"; } + +.fa-instagram:before { + content: "\f16d"; } + +.fa-internet-explorer:before { + content: "\f26b"; } + +.fa-inventory:before { + content: "\f480"; } + +.fa-ioxhost:before { + content: "\f208"; } + +.fa-italic:before { + content: "\f033"; } + +.fa-itunes:before { + content: "\f3b4"; } + +.fa-itunes-note:before { + content: "\f3b5"; } + +.fa-jack-o-lantern:before { + content: "\f30e"; } + +.fa-java:before { + content: "\f4e4"; } + +.fa-jedi-order:before { + content: "\f50e"; } + +.fa-jenkins:before { + content: "\f3b6"; } + +.fa-joget:before { + content: "\f3b7"; } + +.fa-joomla:before { + content: "\f1aa"; } + +.fa-js:before { + content: "\f3b8"; } + +.fa-js-square:before { + content: "\f3b9"; } + +.fa-jsfiddle:before { + content: "\f1cc"; } + +.fa-key:before { + content: "\f084"; } + +.fa-keybase:before { + content: "\f4f5"; } + +.fa-keyboard:before { + content: "\f11c"; } + +.fa-keycdn:before { + content: "\f3ba"; } + +.fa-kickstarter:before { + content: "\f3bb"; } + +.fa-kickstarter-k:before { + content: "\f3bc"; } + +.fa-kiwi-bird:before { + content: "\f535"; } + +.fa-korvue:before { + content: "\f42f"; } + +.fa-lamp:before { + content: "\f4ca"; } + +.fa-language:before { + content: "\f1ab"; } + +.fa-laptop:before { + content: "\f109"; } + +.fa-laravel:before { + content: "\f3bd"; } + +.fa-lastfm:before { + content: "\f202"; } + +.fa-lastfm-square:before { + content: "\f203"; } + +.fa-leaf:before { + content: "\f06c"; } + +.fa-leaf-heart:before { + content: "\f4cb"; } + +.fa-leanpub:before { + content: "\f212"; } + +.fa-lemon:before { + content: "\f094"; } + +.fa-less:before { + content: "\f41d"; } + +.fa-less-than:before { + content: "\f536"; } + +.fa-less-than-equal:before { + content: "\f537"; } + +.fa-level-down:before { + content: "\f149"; } + +.fa-level-down-alt:before { + content: "\f3be"; } + +.fa-level-up:before { + content: "\f148"; } + +.fa-level-up-alt:before { + content: "\f3bf"; } + +.fa-life-ring:before { + content: "\f1cd"; } + +.fa-lightbulb:before { + content: "\f0eb"; } + +.fa-line:before { + content: "\f3c0"; } + +.fa-link:before { + content: "\f0c1"; } + +.fa-linkedin:before { + content: "\f08c"; } + +.fa-linkedin-in:before { + content: "\f0e1"; } + +.fa-linode:before { + content: "\f2b8"; } + +.fa-linux:before { + content: "\f17c"; } + +.fa-lira-sign:before { + content: "\f195"; } + +.fa-list:before { + content: "\f03a"; } + +.fa-list-alt:before { + content: "\f022"; } + +.fa-list-ol:before { + content: "\f0cb"; } + +.fa-list-ul:before { + content: "\f0ca"; } + +.fa-location-arrow:before { + content: "\f124"; } + +.fa-lock:before { + content: "\f023"; } + +.fa-lock-alt:before { + content: "\f30d"; } + +.fa-lock-open:before { + content: "\f3c1"; } + +.fa-lock-open-alt:before { + content: "\f3c2"; } + +.fa-long-arrow-alt-down:before { + content: "\f309"; } + +.fa-long-arrow-alt-left:before { + content: "\f30a"; } + +.fa-long-arrow-alt-right:before { + content: "\f30b"; } + +.fa-long-arrow-alt-up:before { + content: "\f30c"; } + +.fa-long-arrow-down:before { + content: "\f175"; } + +.fa-long-arrow-left:before { + content: "\f177"; } + +.fa-long-arrow-right:before { + content: "\f178"; } + +.fa-long-arrow-up:before { + content: "\f176"; } + +.fa-loveseat:before { + content: "\f4cc"; } + +.fa-low-vision:before { + content: "\f2a8"; } + +.fa-luchador:before { + content: "\f455"; } + +.fa-lyft:before { + content: "\f3c3"; } + +.fa-magento:before { + content: "\f3c4"; } + +.fa-magic:before { + content: "\f0d0"; } + +.fa-magnet:before { + content: "\f076"; } + +.fa-male:before { + content: "\f183"; } + +.fa-mandalorian:before { + content: "\f50f"; } + +.fa-map:before { + content: "\f279"; } + +.fa-map-marker:before { + content: "\f041"; } + +.fa-map-marker-alt:before { + content: "\f3c5"; } + +.fa-map-pin:before { + content: "\f276"; } + +.fa-map-signs:before { + content: "\f277"; } + +.fa-mars:before { + content: "\f222"; } + +.fa-mars-double:before { + content: "\f227"; } + +.fa-mars-stroke:before { + content: "\f229"; } + +.fa-mars-stroke-h:before { + content: "\f22b"; } + +.fa-mars-stroke-v:before { + content: "\f22a"; } + +.fa-mastodon:before { + content: "\f4f6"; } + +.fa-maxcdn:before { + content: "\f136"; } + +.fa-medapps:before { + content: "\f3c6"; } + +.fa-medium:before { + content: "\f23a"; } + +.fa-medium-m:before { + content: "\f3c7"; } + +.fa-medkit:before { + content: "\f0fa"; } + +.fa-medrt:before { + content: "\f3c8"; } + +.fa-meetup:before { + content: "\f2e0"; } + +.fa-meh:before { + content: "\f11a"; } + +.fa-memory:before { + content: "\f538"; } + +.fa-mercury:before { + content: "\f223"; } + +.fa-microchip:before { + content: "\f2db"; } + +.fa-microphone:before { + content: "\f130"; } + +.fa-microphone-alt:before { + content: "\f3c9"; } + +.fa-microphone-alt-slash:before { + content: "\f539"; } + +.fa-microphone-slash:before { + content: "\f131"; } + +.fa-microsoft:before { + content: "\f3ca"; } + +.fa-minus:before { + content: "\f068"; } + +.fa-minus-circle:before { + content: "\f056"; } + +.fa-minus-hexagon:before { + content: "\f307"; } + +.fa-minus-octagon:before { + content: "\f308"; } + +.fa-minus-square:before { + content: "\f146"; } + +.fa-mix:before { + content: "\f3cb"; } + +.fa-mixcloud:before { + content: "\f289"; } + +.fa-mizuni:before { + content: "\f3cc"; } + +.fa-mobile:before { + content: "\f10b"; } + +.fa-mobile-alt:before { + content: "\f3cd"; } + +.fa-mobile-android:before { + content: "\f3ce"; } + +.fa-mobile-android-alt:before { + content: "\f3cf"; } + +.fa-modx:before { + content: "\f285"; } + +.fa-monero:before { + content: "\f3d0"; } + +.fa-money-bill:before { + content: "\f0d6"; } + +.fa-money-bill-alt:before { + content: "\f3d1"; } + +.fa-money-bill-wave:before { + content: "\f53a"; } + +.fa-money-bill-wave-alt:before { + content: "\f53b"; } + +.fa-money-check:before { + content: "\f53c"; } + +.fa-money-check-alt:before { + content: "\f53d"; } + +.fa-moon:before { + content: "\f186"; } + +.fa-motorcycle:before { + content: "\f21c"; } + +.fa-mouse-pointer:before { + content: "\f245"; } + +.fa-music:before { + content: "\f001"; } + +.fa-napster:before { + content: "\f3d2"; } + +.fa-neuter:before { + content: "\f22c"; } + +.fa-newspaper:before { + content: "\f1ea"; } + +.fa-nintendo-switch:before { + content: "\f418"; } + +.fa-node:before { + content: "\f419"; } + +.fa-node-js:before { + content: "\f3d3"; } + +.fa-not-equal:before { + content: "\f53e"; } + +.fa-notes-medical:before { + content: "\f481"; } + +.fa-npm:before { + content: "\f3d4"; } + +.fa-ns8:before { + content: "\f3d5"; } + +.fa-nutritionix:before { + content: "\f3d6"; } + +.fa-object-group:before { + content: "\f247"; } + +.fa-object-ungroup:before { + content: "\f248"; } + +.fa-octagon:before { + content: "\f306"; } + +.fa-odnoklassniki:before { + content: "\f263"; } + +.fa-odnoklassniki-square:before { + content: "\f264"; } + +.fa-old-republic:before { + content: "\f510"; } + +.fa-opencart:before { + content: "\f23d"; } + +.fa-openid:before { + content: "\f19b"; } + +.fa-opera:before { + content: "\f26a"; } + +.fa-optin-monster:before { + content: "\f23c"; } + +.fa-osi:before { + content: "\f41a"; } + +.fa-outdent:before { + content: "\f03b"; } + +.fa-page4:before { + content: "\f3d7"; } + +.fa-pagelines:before { + content: "\f18c"; } + +.fa-paint-brush:before { + content: "\f1fc"; } + +.fa-palette:before { + content: "\f53f"; } + +.fa-palfed:before { + content: "\f3d8"; } + +.fa-pallet:before { + content: "\f482"; } + +.fa-pallet-alt:before { + content: "\f483"; } + +.fa-paper-plane:before { + content: "\f1d8"; } + +.fa-paperclip:before { + content: "\f0c6"; } + +.fa-parachute-box:before { + content: "\f4cd"; } + +.fa-paragraph:before { + content: "\f1dd"; } + +.fa-parking:before { + content: "\f540"; } + +.fa-paste:before { + content: "\f0ea"; } + +.fa-patreon:before { + content: "\f3d9"; } + +.fa-pause:before { + content: "\f04c"; } + +.fa-pause-circle:before { + content: "\f28b"; } + +.fa-paw:before { + content: "\f1b0"; } + +.fa-paypal:before { + content: "\f1ed"; } + +.fa-pen:before { + content: "\f304"; } + +.fa-pen-alt:before { + content: "\f305"; } + +.fa-pen-square:before { + content: "\f14b"; } + +.fa-pencil:before { + content: "\f040"; } + +.fa-pencil-alt:before { + content: "\f303"; } + +.fa-pennant:before { + content: "\f456"; } + +.fa-people-carry:before { + content: "\f4ce"; } + +.fa-percent:before { + content: "\f295"; } + +.fa-percentage:before { + content: "\f541"; } + +.fa-periscope:before { + content: "\f3da"; } + +.fa-person-carry:before { + content: "\f4cf"; } + +.fa-person-dolly:before { + content: "\f4d0"; } + +.fa-person-dolly-empty:before { + content: "\f4d1"; } + +.fa-phabricator:before { + content: "\f3db"; } + +.fa-phoenix-framework:before { + content: "\f3dc"; } + +.fa-phoenix-squadron:before { + content: "\f511"; } + +.fa-phone:before { + content: "\f095"; } + +.fa-phone-plus:before { + content: "\f4d2"; } + +.fa-phone-slash:before { + content: "\f3dd"; } + +.fa-phone-square:before { + content: "\f098"; } + +.fa-phone-volume:before { + content: "\f2a0"; } + +.fa-php:before { + content: "\f457"; } + +.fa-pied-piper:before { + content: "\f2ae"; } + +.fa-pied-piper-alt:before { + content: "\f1a8"; } + +.fa-pied-piper-hat:before { + content: "\f4e5"; } + +.fa-pied-piper-pp:before { + content: "\f1a7"; } + +.fa-piggy-bank:before { + content: "\f4d3"; } + +.fa-pills:before { + content: "\f484"; } + +.fa-pinterest:before { + content: "\f0d2"; } + +.fa-pinterest-p:before { + content: "\f231"; } + +.fa-pinterest-square:before { + content: "\f0d3"; } + +.fa-plane:before { + content: "\f072"; } + +.fa-plane-alt:before { + content: "\f3de"; } + +.fa-play:before { + content: "\f04b"; } + +.fa-play-circle:before { + content: "\f144"; } + +.fa-playstation:before { + content: "\f3df"; } + +.fa-plug:before { + content: "\f1e6"; } + +.fa-plus:before { + content: "\f067"; } + +.fa-plus-circle:before { + content: "\f055"; } + +.fa-plus-hexagon:before { + content: "\f300"; } + +.fa-plus-octagon:before { + content: "\f301"; } + +.fa-plus-square:before { + content: "\f0fe"; } + +.fa-podcast:before { + content: "\f2ce"; } + +.fa-poo:before { + content: "\f2fe"; } + +.fa-portrait:before { + content: "\f3e0"; } + +.fa-pound-sign:before { + content: "\f154"; } + +.fa-power-off:before { + content: "\f011"; } + +.fa-prescription-bottle:before { + content: "\f485"; } + +.fa-prescription-bottle-alt:before { + content: "\f486"; } + +.fa-print:before { + content: "\f02f"; } + +.fa-procedures:before { + content: "\f487"; } + +.fa-product-hunt:before { + content: "\f288"; } + +.fa-project-diagram:before { + content: "\f542"; } + +.fa-pushed:before { + content: "\f3e1"; } + +.fa-puzzle-piece:before { + content: "\f12e"; } + +.fa-python:before { + content: "\f3e2"; } + +.fa-qq:before { + content: "\f1d6"; } + +.fa-qrcode:before { + content: "\f029"; } + +.fa-question:before { + content: "\f128"; } + +.fa-question-circle:before { + content: "\f059"; } + +.fa-question-square:before { + content: "\f2fd"; } + +.fa-quidditch:before { + content: "\f458"; } + +.fa-quinscape:before { + content: "\f459"; } + +.fa-quora:before { + content: "\f2c4"; } + +.fa-quote-left:before { + content: "\f10d"; } + +.fa-quote-right:before { + content: "\f10e"; } + +.fa-r-project:before { + content: "\f4f7"; } + +.fa-racquet:before { + content: "\f45a"; } + +.fa-ramp-loading:before { + content: "\f4d4"; } + +.fa-random:before { + content: "\f074"; } + +.fa-ravelry:before { + content: "\f2d9"; } + +.fa-react:before { + content: "\f41b"; } + +.fa-readme:before { + content: "\f4d5"; } + +.fa-rebel:before { + content: "\f1d0"; } + +.fa-receipt:before { + content: "\f543"; } + +.fa-rectangle-landscape:before { + content: "\f2fa"; } + +.fa-rectangle-portrait:before { + content: "\f2fb"; } + +.fa-rectangle-wide:before { + content: "\f2fc"; } + +.fa-recycle:before { + content: "\f1b8"; } + +.fa-red-river:before { + content: "\f3e3"; } + +.fa-reddit:before { + content: "\f1a1"; } + +.fa-reddit-alien:before { + content: "\f281"; } + +.fa-reddit-square:before { + content: "\f1a2"; } + +.fa-redo:before { + content: "\f01e"; } + +.fa-redo-alt:before { + content: "\f2f9"; } + +.fa-registered:before { + content: "\f25d"; } + +.fa-rendact:before { + content: "\f3e4"; } + +.fa-renren:before { + content: "\f18b"; } + +.fa-repeat:before { + content: "\f363"; } + +.fa-repeat-1:before { + content: "\f365"; } + +.fa-repeat-1-alt:before { + content: "\f366"; } + +.fa-repeat-alt:before { + content: "\f364"; } + +.fa-reply:before { + content: "\f3e5"; } + +.fa-reply-all:before { + content: "\f122"; } + +.fa-replyd:before { + content: "\f3e6"; } + +.fa-researchgate:before { + content: "\f4f8"; } + +.fa-resolving:before { + content: "\f3e7"; } + +.fa-retweet:before { + content: "\f079"; } + +.fa-retweet-alt:before { + content: "\f361"; } + +.fa-ribbon:before { + content: "\f4d6"; } + +.fa-road:before { + content: "\f018"; } + +.fa-robot:before { + content: "\f544"; } + +.fa-rocket:before { + content: "\f135"; } + +.fa-rocketchat:before { + content: "\f3e8"; } + +.fa-rockrms:before { + content: "\f3e9"; } + +.fa-route:before { + content: "\f4d7"; } + +.fa-rss:before { + content: "\f09e"; } + +.fa-rss-square:before { + content: "\f143"; } + +.fa-ruble-sign:before { + content: "\f158"; } + +.fa-ruler:before { + content: "\f545"; } + +.fa-ruler-combined:before { + content: "\f546"; } + +.fa-ruler-horizontal:before { + content: "\f547"; } + +.fa-ruler-vertical:before { + content: "\f548"; } + +.fa-rupee-sign:before { + content: "\f156"; } + +.fa-safari:before { + content: "\f267"; } + +.fa-sass:before { + content: "\f41e"; } + +.fa-save:before { + content: "\f0c7"; } + +.fa-scanner:before { + content: "\f488"; } + +.fa-scanner-keyboard:before { + content: "\f489"; } + +.fa-scanner-touchscreen:before { + content: "\f48a"; } + +.fa-schlix:before { + content: "\f3ea"; } + +.fa-school:before { + content: "\f549"; } + +.fa-screwdriver:before { + content: "\f54a"; } + +.fa-scribd:before { + content: "\f28a"; } + +.fa-scrubber:before { + content: "\f2f8"; } + +.fa-search:before { + content: "\f002"; } + +.fa-search-minus:before { + content: "\f010"; } + +.fa-search-plus:before { + content: "\f00e"; } + +.fa-searchengin:before { + content: "\f3eb"; } + +.fa-seedling:before { + content: "\f4d8"; } + +.fa-sellcast:before { + content: "\f2da"; } + +.fa-sellsy:before { + content: "\f213"; } + +.fa-server:before { + content: "\f233"; } + +.fa-servicestack:before { + content: "\f3ec"; } + +.fa-share:before { + content: "\f064"; } + +.fa-share-all:before { + content: "\f367"; } + +.fa-share-alt:before { + content: "\f1e0"; } + +.fa-share-alt-square:before { + content: "\f1e1"; } + +.fa-share-square:before { + content: "\f14d"; } + +.fa-shekel-sign:before { + content: "\f20b"; } + +.fa-shield:before { + content: "\f132"; } + +.fa-shield-alt:before { + content: "\f3ed"; } + +.fa-shield-check:before { + content: "\f2f7"; } + +.fa-ship:before { + content: "\f21a"; } + +.fa-shipping-fast:before { + content: "\f48b"; } + +.fa-shipping-timed:before { + content: "\f48c"; } + +.fa-shirtsinbulk:before { + content: "\f214"; } + +.fa-shoe-prints:before { + content: "\f54b"; } + +.fa-shopping-bag:before { + content: "\f290"; } + +.fa-shopping-basket:before { + content: "\f291"; } + +.fa-shopping-cart:before { + content: "\f07a"; } + +.fa-shower:before { + content: "\f2cc"; } + +.fa-shuttlecock:before { + content: "\f45b"; } + +.fa-sign:before { + content: "\f4d9"; } + +.fa-sign-in:before { + content: "\f090"; } + +.fa-sign-in-alt:before { + content: "\f2f6"; } + +.fa-sign-language:before { + content: "\f2a7"; } + +.fa-sign-out:before { + content: "\f08b"; } + +.fa-sign-out-alt:before { + content: "\f2f5"; } + +.fa-signal:before { + content: "\f012"; } + +.fa-simplybuilt:before { + content: "\f215"; } + +.fa-sistrix:before { + content: "\f3ee"; } + +.fa-sitemap:before { + content: "\f0e8"; } + +.fa-sith:before { + content: "\f512"; } + +.fa-skull:before { + content: "\f54c"; } + +.fa-skyatlas:before { + content: "\f216"; } + +.fa-skype:before { + content: "\f17e"; } + +.fa-slack:before { + content: "\f198"; } + +.fa-slack-hash:before { + content: "\f3ef"; } + +.fa-sliders-h:before { + content: "\f1de"; } + +.fa-sliders-h-square:before { + content: "\f3f0"; } + +.fa-sliders-v:before { + content: "\f3f1"; } + +.fa-sliders-v-square:before { + content: "\f3f2"; } + +.fa-slideshare:before { + content: "\f1e7"; } + +.fa-smile:before { + content: "\f118"; } + +.fa-smile-plus:before { + content: "\f4da"; } + +.fa-smoking:before { + content: "\f48d"; } + +.fa-smoking-ban:before { + content: "\f54d"; } + +.fa-snapchat:before { + content: "\f2ab"; } + +.fa-snapchat-ghost:before { + content: "\f2ac"; } + +.fa-snapchat-square:before { + content: "\f2ad"; } + +.fa-snowflake:before { + content: "\f2dc"; } + +.fa-sort:before { + content: "\f0dc"; } + +.fa-sort-alpha-down:before { + content: "\f15d"; } + +.fa-sort-alpha-up:before { + content: "\f15e"; } + +.fa-sort-amount-down:before { + content: "\f160"; } + +.fa-sort-amount-up:before { + content: "\f161"; } + +.fa-sort-down:before { + content: "\f0dd"; } + +.fa-sort-numeric-down:before { + content: "\f162"; } + +.fa-sort-numeric-up:before { + content: "\f163"; } + +.fa-sort-up:before { + content: "\f0de"; } + +.fa-soundcloud:before { + content: "\f1be"; } + +.fa-space-shuttle:before { + content: "\f197"; } + +.fa-spade:before { + content: "\f2f4"; } + +.fa-speakap:before { + content: "\f3f3"; } + +.fa-spinner:before { + content: "\f110"; } + +.fa-spinner-third:before { + content: "\f3f4"; } + +.fa-spotify:before { + content: "\f1bc"; } + +.fa-square:before { + content: "\f0c8"; } + +.fa-square-full:before { + content: "\f45c"; } + +.fa-stack-exchange:before { + content: "\f18d"; } + +.fa-stack-overflow:before { + content: "\f16c"; } + +.fa-star:before { + content: "\f005"; } + +.fa-star-exclamation:before { + content: "\f2f3"; } + +.fa-star-half:before { + content: "\f089"; } + +.fa-staylinked:before { + content: "\f3f5"; } + +.fa-steam:before { + content: "\f1b6"; } + +.fa-steam-square:before { + content: "\f1b7"; } + +.fa-steam-symbol:before { + content: "\f3f6"; } + +.fa-step-backward:before { + content: "\f048"; } + +.fa-step-forward:before { + content: "\f051"; } + +.fa-stethoscope:before { + content: "\f0f1"; } + +.fa-sticker-mule:before { + content: "\f3f7"; } + +.fa-sticky-note:before { + content: "\f249"; } + +.fa-stop:before { + content: "\f04d"; } + +.fa-stop-circle:before { + content: "\f28d"; } + +.fa-stopwatch:before { + content: "\f2f2"; } + +.fa-store:before { + content: "\f54e"; } + +.fa-store-alt:before { + content: "\f54f"; } + +.fa-strava:before { + content: "\f428"; } + +.fa-stream:before { + content: "\f550"; } + +.fa-street-view:before { + content: "\f21d"; } + +.fa-strikethrough:before { + content: "\f0cc"; } + +.fa-stripe:before { + content: "\f429"; } + +.fa-stripe-s:before { + content: "\f42a"; } + +.fa-stroopwafel:before { + content: "\f551"; } + +.fa-studiovinari:before { + content: "\f3f8"; } + +.fa-stumbleupon:before { + content: "\f1a4"; } + +.fa-stumbleupon-circle:before { + content: "\f1a3"; } + +.fa-subscript:before { + content: "\f12c"; } + +.fa-subway:before { + content: "\f239"; } + +.fa-suitcase:before { + content: "\f0f2"; } + +.fa-sun:before { + content: "\f185"; } + +.fa-superpowers:before { + content: "\f2dd"; } + +.fa-superscript:before { + content: "\f12b"; } + +.fa-supple:before { + content: "\f3f9"; } + +.fa-sync:before { + content: "\f021"; } + +.fa-sync-alt:before { + content: "\f2f1"; } + +.fa-syringe:before { + content: "\f48e"; } + +.fa-table:before { + content: "\f0ce"; } + +.fa-table-tennis:before { + content: "\f45d"; } + +.fa-tablet:before { + content: "\f10a"; } + +.fa-tablet-alt:before { + content: "\f3fa"; } + +.fa-tablet-android:before { + content: "\f3fb"; } + +.fa-tablet-android-alt:before { + content: "\f3fc"; } + +.fa-tablet-rugged:before { + content: "\f48f"; } + +.fa-tablets:before { + content: "\f490"; } + +.fa-tachometer:before { + content: "\f0e4"; } + +.fa-tachometer-alt:before { + content: "\f3fd"; } + +.fa-tag:before { + content: "\f02b"; } + +.fa-tags:before { + content: "\f02c"; } + +.fa-tape:before { + content: "\f4db"; } + +.fa-tasks:before { + content: "\f0ae"; } + +.fa-taxi:before { + content: "\f1ba"; } + +.fa-teamspeak:before { + content: "\f4f9"; } + +.fa-telegram:before { + content: "\f2c6"; } + +.fa-telegram-plane:before { + content: "\f3fe"; } + +.fa-tencent-weibo:before { + content: "\f1d5"; } + +.fa-tennis-ball:before { + content: "\f45e"; } + +.fa-terminal:before { + content: "\f120"; } + +.fa-text-height:before { + content: "\f034"; } + +.fa-text-width:before { + content: "\f035"; } + +.fa-th:before { + content: "\f00a"; } + +.fa-th-large:before { + content: "\f009"; } + +.fa-th-list:before { + content: "\f00b"; } + +.fa-themeisle:before { + content: "\f2b2"; } + +.fa-thermometer:before { + content: "\f491"; } + +.fa-thermometer-empty:before { + content: "\f2cb"; } + +.fa-thermometer-full:before { + content: "\f2c7"; } + +.fa-thermometer-half:before { + content: "\f2c9"; } + +.fa-thermometer-quarter:before { + content: "\f2ca"; } + +.fa-thermometer-three-quarters:before { + content: "\f2c8"; } + +.fa-thumbs-down:before { + content: "\f165"; } + +.fa-thumbs-up:before { + content: "\f164"; } + +.fa-thumbtack:before { + content: "\f08d"; } + +.fa-ticket:before { + content: "\f145"; } + +.fa-ticket-alt:before { + content: "\f3ff"; } + +.fa-times:before { + content: "\f00d"; } + +.fa-times-circle:before { + content: "\f057"; } + +.fa-times-hexagon:before { + content: "\f2ee"; } + +.fa-times-octagon:before { + content: "\f2f0"; } + +.fa-times-square:before { + content: "\f2d3"; } + +.fa-tint:before { + content: "\f043"; } + +.fa-toggle-off:before { + content: "\f204"; } + +.fa-toggle-on:before { + content: "\f205"; } + +.fa-toolbox:before { + content: "\f552"; } + +.fa-trade-federation:before { + content: "\f513"; } + +.fa-trademark:before { + content: "\f25c"; } + +.fa-train:before { + content: "\f238"; } + +.fa-transgender:before { + content: "\f224"; } + +.fa-transgender-alt:before { + content: "\f225"; } + +.fa-trash:before { + content: "\f1f8"; } + +.fa-trash-alt:before { + content: "\f2ed"; } + +.fa-tree:before { + content: "\f1bb"; } + +.fa-tree-alt:before { + content: "\f400"; } + +.fa-trello:before { + content: "\f181"; } + +.fa-triangle:before { + content: "\f2ec"; } + +.fa-tripadvisor:before { + content: "\f262"; } + +.fa-trophy:before { + content: "\f091"; } + +.fa-trophy-alt:before { + content: "\f2eb"; } + +.fa-truck:before { + content: "\f0d1"; } + +.fa-truck-container:before { + content: "\f4dc"; } + +.fa-truck-couch:before { + content: "\f4dd"; } + +.fa-truck-loading:before { + content: "\f4de"; } + +.fa-truck-moving:before { + content: "\f4df"; } + +.fa-truck-ramp:before { + content: "\f4e0"; } + +.fa-tshirt:before { + content: "\f553"; } + +.fa-tty:before { + content: "\f1e4"; } + +.fa-tumblr:before { + content: "\f173"; } + +.fa-tumblr-square:before { + content: "\f174"; } + +.fa-tv:before { + content: "\f26c"; } + +.fa-tv-retro:before { + content: "\f401"; } + +.fa-twitch:before { + content: "\f1e8"; } + +.fa-twitter:before { + content: "\f099"; } + +.fa-twitter-square:before { + content: "\f081"; } + +.fa-typo3:before { + content: "\f42b"; } + +.fa-uber:before { + content: "\f402"; } + +.fa-uikit:before { + content: "\f403"; } + +.fa-umbrella:before { + content: "\f0e9"; } + +.fa-underline:before { + content: "\f0cd"; } + +.fa-undo:before { + content: "\f0e2"; } + +.fa-undo-alt:before { + content: "\f2ea"; } + +.fa-uniregistry:before { + content: "\f404"; } + +.fa-universal-access:before { + content: "\f29a"; } + +.fa-university:before { + content: "\f19c"; } + +.fa-unlink:before { + content: "\f127"; } + +.fa-unlock:before { + content: "\f09c"; } + +.fa-unlock-alt:before { + content: "\f13e"; } + +.fa-untappd:before { + content: "\f405"; } + +.fa-upload:before { + content: "\f093"; } + +.fa-usb:before { + content: "\f287"; } + +.fa-usd-circle:before { + content: "\f2e8"; } + +.fa-usd-square:before { + content: "\f2e9"; } + +.fa-user:before { + content: "\f007"; } + +.fa-user-alt:before { + content: "\f406"; } + +.fa-user-alt-slash:before { + content: "\f4fa"; } + +.fa-user-astronaut:before { + content: "\f4fb"; } + +.fa-user-check:before { + content: "\f4fc"; } + +.fa-user-circle:before { + content: "\f2bd"; } + +.fa-user-clock:before { + content: "\f4fd"; } + +.fa-user-cog:before { + content: "\f4fe"; } + +.fa-user-edit:before { + content: "\f4ff"; } + +.fa-user-friends:before { + content: "\f500"; } + +.fa-user-graduate:before { + content: "\f501"; } + +.fa-user-lock:before { + content: "\f502"; } + +.fa-user-md:before { + content: "\f0f0"; } + +.fa-user-minus:before { + content: "\f503"; } + +.fa-user-ninja:before { + content: "\f504"; } + +.fa-user-plus:before { + content: "\f234"; } + +.fa-user-secret:before { + content: "\f21b"; } + +.fa-user-shield:before { + content: "\f505"; } + +.fa-user-slash:before { + content: "\f506"; } + +.fa-user-tag:before { + content: "\f507"; } + +.fa-user-tie:before { + content: "\f508"; } + +.fa-user-times:before { + content: "\f235"; } + +.fa-users:before { + content: "\f0c0"; } + +.fa-users-cog:before { + content: "\f509"; } + +.fa-ussunnah:before { + content: "\f407"; } + +.fa-utensil-fork:before { + content: "\f2e3"; } + +.fa-utensil-knife:before { + content: "\f2e4"; } + +.fa-utensil-spoon:before { + content: "\f2e5"; } + +.fa-utensils:before { + content: "\f2e7"; } + +.fa-utensils-alt:before { + content: "\f2e6"; } + +.fa-vaadin:before { + content: "\f408"; } + +.fa-venus:before { + content: "\f221"; } + +.fa-venus-double:before { + content: "\f226"; } + +.fa-venus-mars:before { + content: "\f228"; } + +.fa-viacoin:before { + content: "\f237"; } + +.fa-viadeo:before { + content: "\f2a9"; } + +.fa-viadeo-square:before { + content: "\f2aa"; } + +.fa-vial:before { + content: "\f492"; } + +.fa-vials:before { + content: "\f493"; } + +.fa-viber:before { + content: "\f409"; } + +.fa-video:before { + content: "\f03d"; } + +.fa-video-plus:before { + content: "\f4e1"; } + +.fa-video-slash:before { + content: "\f4e2"; } + +.fa-vimeo:before { + content: "\f40a"; } + +.fa-vimeo-square:before { + content: "\f194"; } + +.fa-vimeo-v:before { + content: "\f27d"; } + +.fa-vine:before { + content: "\f1ca"; } + +.fa-vk:before { + content: "\f189"; } + +.fa-vnv:before { + content: "\f40b"; } + +.fa-volleyball-ball:before { + content: "\f45f"; } + +.fa-volume-down:before { + content: "\f027"; } + +.fa-volume-mute:before { + content: "\f2e2"; } + +.fa-volume-off:before { + content: "\f026"; } + +.fa-volume-up:before { + content: "\f028"; } + +.fa-vuejs:before { + content: "\f41f"; } + +.fa-walking:before { + content: "\f554"; } + +.fa-wallet:before { + content: "\f555"; } + +.fa-warehouse:before { + content: "\f494"; } + +.fa-warehouse-alt:before { + content: "\f495"; } + +.fa-watch:before { + content: "\f2e1"; } + +.fa-weibo:before { + content: "\f18a"; } + +.fa-weight:before { + content: "\f496"; } + +.fa-weixin:before { + content: "\f1d7"; } + +.fa-whatsapp:before { + content: "\f232"; } + +.fa-whatsapp-square:before { + content: "\f40c"; } + +.fa-wheelchair:before { + content: "\f193"; } + +.fa-whistle:before { + content: "\f460"; } + +.fa-whmcs:before { + content: "\f40d"; } + +.fa-wifi:before { + content: "\f1eb"; } + +.fa-wikipedia-w:before { + content: "\f266"; } + +.fa-window:before { + content: "\f40e"; } + +.fa-window-alt:before { + content: "\f40f"; } + +.fa-window-close:before { + content: "\f410"; } + +.fa-window-maximize:before { + content: "\f2d0"; } + +.fa-window-minimize:before { + content: "\f2d1"; } + +.fa-window-restore:before { + content: "\f2d2"; } + +.fa-windows:before { + content: "\f17a"; } + +.fa-wine-glass:before { + content: "\f4e3"; } + +.fa-wolf-pack-battalion:before { + content: "\f514"; } + +.fa-won-sign:before { + content: "\f159"; } + +.fa-wordpress:before { + content: "\f19a"; } + +.fa-wordpress-simple:before { + content: "\f411"; } + +.fa-wpbeginner:before { + content: "\f297"; } + +.fa-wpexplorer:before { + content: "\f2de"; } + +.fa-wpforms:before { + content: "\f298"; } + +.fa-wrench:before { + content: "\f0ad"; } + +.fa-x-ray:before { + content: "\f497"; } + +.fa-xbox:before { + content: "\f412"; } + +.fa-xing:before { + content: "\f168"; } + +.fa-xing-square:before { + content: "\f169"; } + +.fa-y-combinator:before { + content: "\f23b"; } + +.fa-yahoo:before { + content: "\f19e"; } + +.fa-yandex:before { + content: "\f413"; } + +.fa-yandex-international:before { + content: "\f414"; } + +.fa-yelp:before { + content: "\f1e9"; } + +.fa-yen-sign:before { + content: "\f157"; } + +.fa-yoast:before { + content: "\f2b1"; } + +.fa-youtube:before { + content: "\f167"; } + +.fa-youtube-square:before { + content: "\f431"; } + +.sr-only { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; } + +.sr-only-focusable:active, .sr-only-focusable:focus { + clip: auto; + height: auto; + margin: 0; + overflow: visible; + position: static; + width: auto; } + +@font-face { + font-family: 'Font Awesome 5 Brands'; + font-style: normal; + font-weight: normal; + src: url("../fonts/font-awesome/fa-brands-400.eot"); + src: url("../fonts/font-awesome/fa-brands-400.eot?#iefix") format("embedded-opentype"), + url("../fonts/font-awesome/fa-brands-400.woff2") format("woff2"), + url("../fonts/font-awesome/fa-brands-400.woff") format("woff"), + url("../fonts/font-awesome/fa-brands-400.ttf") format("truetype"), + url("../fonts/font-awesome/fa-brands-400.svg#fontawesome") format("svg"); } + +.fab { + font-family: 'Font Awesome 5 Brands'; } + +@font-face { + font-family: 'Font Awesome 5 Pro'; + font-style: normal; + font-weight: 300; + src: url("../fonts/font-awesome/fa-light-300.eot"); + src: url("../fonts/font-awesome/fa-light-300.eot?#iefix") format("embedded-opentype"), + url("../fonts/font-awesome/fa-light-300.woff2") format("woff2"), + url("../fonts/font-awesome/fa-light-300.woff") format("woff"), + url("../fonts/font-awesome/fa-light-300.ttf") format("truetype"), + url("../fonts/font-awesome/fa-light-300.svg#fontawesome") format("svg"); } + +.fal { + font-family: 'Font Awesome 5 Pro'; + font-weight: 300; } + +@font-face { + font-family: 'Font Awesome 5 Pro'; + font-style: normal; + font-weight: 400; + src: url("../fonts/font-awesome/fa-regular-400.eot"); + src: url("../fonts/font-awesome/fa-regular-400.eot?#iefix") format("embedded-opentype"), + url("../fonts/font-awesome/fa-regular-400.woff2") format("woff2"), + url("../fonts/font-awesome/fa-regular-400.woff") format("woff"), + url("../fonts/font-awesome/fa-regular-400.ttf") format("truetype"), + url("../fonts/font-awesome/fa-regular-400.svg#fontawesome") format("svg"); } + +.far { + font-family: 'Font Awesome 5 Pro'; + font-weight: 400; } + +@font-face { + font-family: 'Font Awesome 5 Pro'; + font-style: normal; + font-weight: 900; + src: url("../fonts/font-awesome/fa-solid-900.eot"); + src: url("../fonts/font-awesome/fa-solid-900.eot?#iefix") format("embedded-opentype"), + url("../fonts/font-awesome/fa-solid-900.woff2") format("woff2"), + url("../fonts/font-awesome/fa-solid-900.woff") format("woff"), + url("../fonts/font-awesome/fa-solid-900.ttf") format("truetype"), + url("../fonts/font-awesome/fa-solid-900.svg#fontawesome") format("svg"); } + +.fa, +.fas { + font-family: 'Font Awesome 5 Pro'; + font-weight: 900; } diff --git a/_assets/stylesheets/styles.css b/_assets/stylesheets/styles.css new file mode 100644 index 000000000..c628c1cf1 --- /dev/null +++ b/_assets/stylesheets/styles.css @@ -0,0 +1,2805 @@ +@charset "utf-8"; + +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 300; + src: local("Open Sans Light"), local("OpenSans-Light"), url(../fonts/open-sans/open-sans-v13-latin-300.woff2) format("woff2"); +} + +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 300; + src: local("Open Sans Light Italic"), local("OpenSansLight-Italic"), url(../fonts/open-sans/open-sans-v13-latin-300italic.woff2) format("woff2"); +} + +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local("Open Sans"), local("OpenSans"), url(../fonts/open-sans/open-sans-v13-latin-regular.woff2) format("woff2"); +} + +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local("Open Sans Italic"), local("OpenSans-Italic"), url(../fonts/open-sans/open-sans-v13-latin-italic.woff2) format("woff2"); +} + +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local("Open Sans Semibold"), local("OpenSans-Semibold"), url(../fonts/open-sans/open-sans-v13-latin-600.woff2) format("woff2"); +} + +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local("Open Sans Semibold Italic"), local("OpenSans-SemiboldItalic"), url(../fonts/open-sans/open-sans-v13-latin-600italic.woff2) format("woff2"); +} + +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 700; + src: local("Open Sans Bold"), local("OpenSans-Bold"), url(../fonts/open-sans/open-sans-v13-latin-700.woff2) format("woff2"); +} + +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 700; + src: local("Open Sans Bold Italic"), local("OpenSans-BoldItalic"), url(../fonts/open-sans/open-sans-v13-latin-700italic.woff2) format("woff2"); +} + +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 800; + src: local("Open Sans Extrabold"), local("OpenSans-Extrabold"), url(../fonts/open-sans/open-sans-v13-latin-800.woff2) format("woff2"); +} + +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 800; + src: local("Open Sans Extrabold Italic"), local("OpenSans-ExtraboldItalic"), url(../fonts/open-sans/open-sans-v13-latin-800italic.woff2) format("woff2"); +} + +@font-face { + font-family: 'Open Sans Condensed'; + font-style: normal; + font-weight: 300; + src: local("Open Sans Cond Light"), local("OpenSans-CondensedLight"), url(../fonts/open-sans-condensed/open-sans-condensed-v10-latin-300.woff2) format("woff2"),; +} + +@font-face { + font-family: 'Open Sans Condensed'; + font-style: italic; + font-weight: 300; + src: local("Open Sans Cond Light Italic"), local("OpenSans-CondensedLightItalic"), url(../fonts/open-sans-condensed/open-sans-condensed-v10-latin-300italic.woff2) format("woff2"); +} + +@font-face { + font-family: 'Open Sans Condensed'; + font-style: normal; + font-weight: 700; + src: local("Open Sans Condensed Bold"), local("OpenSans-CondensedBold"), url(../fonts/open-sans-condensed/open-sans-condensed-v10-latin-700.woff2) format("woff2"); +} + + +html { + display: flex; + flex-direction: column; + font: 400 16px/22px "Open Sans", sans-serif; + align-items: center; + overflow-x: hidden; +} + +input, +textarea { + font-family: "Open Sans", sans-serif; +} + +body { + margin: 0; + color: var(--color-dark); + background: var(--background-base); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-rendering: geometricPrecision; + flex: 1 0 50%; + width: 50%; + max-width: 1280px; +} + +body.-landing { + flex: 1 0 90%; + width: 90%; +} + +/* Headings */ + +a { + cursor: pointer; + text-decoration: none; + color: var(--color-accent-light); +} + +a:hover { + color: var(--color-success); +} + +h1, h2, h3, h4, h5, h6 { + font-weight: normal; + line-height: 1.36em; +} + +article h1, article h4, article h5, article h6 { + margin-top: 0; +} + +article { + padding-bottom: 1em; +} + +article > hr { + border: solid var(--border-light-blue); + border-width: 0 0 1px; +} + +article img { + max-width: 100%; +} + +h1 > a, h2 > a, h3 > a, h4 > a, h5 > a, h6 > a, +h1 > a:hover, h2 > a:hover, h3 > a:hover, h4 > a:hover, h5 > a:hover, h6 > a:hover { + top: 80px; + width: auto; + color: var(--color-dark); + display: block; + position: relative; + margin-top: -75px; + margin-bottom: 100px; +} + +h2 > a:hover:before, h3 > a:hover:before, h4 > a:hover:before, h5 > a:hover:before, h6 > a:hover:before { + left: -1.4em; + content: "\f0c1"; + font-family: "Font Awesome 5 Pro"; + font-weight: 300; + font-size: .6em; + display: inline-block; + vertical-align: middle; + position: relative; + padding-right: .4em; + margin-right: -1.4em; + line-height: 1em; +} + +h1 { + font-size: 2.8rem; + letter-spacing: -.036em; +} + +h1:first-child, h2:first-child, h3:first-child, h4:first-child, h5:first-child, h6:first-child { + margin-top: 0; +} + +h2, +html .k-window-title { + font-size: 2.25rem; +} + +h2 { + margin: .6em 0 3em; +} + +h3 { + font-size: 1.75rem; + line-height: 1.28em; + margin: .8em 0 3.7em; +} + +h4 { + font-size: 1.3125rem; + line-height: 1.43em; +} + +h5 { + font-size: 1.125rem; +} + +.-allcaps { + font-weight: 600; + letter-spacing: -.02em; + text-transform: uppercase; +} + +pre { + font-size: .8125rem; + line-height: 1.36em; +} + +/* Navigation */ + +.ns-navigation, +.ns-tip-container { + background: var(--background-accent); + font-size: .95em; + height: 5.26em; + display: flex; + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 10; + width: calc(100% + 600px); + margin-left: -300px; +} + +.ns-tip-container { + height: 3em; + font-size: 1.13em; + align-items: center; + letter-spacing: -.03em; + color: var(--color-secondary); + background: var(--background-tip); +} + +body.-landing .ns-tip-container, +body.-landing .ns-navigation { + width: auto; + margin-left: unset; +} + +.ns-page:before, +.ns-start-links:before, +.ns-navigation:before, +.ns-tip-container:before { + position: absolute; + display: block; + content: "\a0"; + width: 100vw; + height: 100%; + left: calc((100% - 100vw) / 2); + background: inherit; + z-index: -1; + transition: box-shadow .3s ease-out; +} + +html.ns-state-scrolled .ns-navigation:before { + box-shadow: 0 2px 10px var(--transparent-dark-50); +} + +.navigation__logo { + width: 9.8em; + background: transparent no-repeat center center url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASkAAAA4CAMAAACWuv46AAABOFBMVEUAAAD///////////////////////////////////////////88Wv3///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////88Wv3///////88Wv3///////////+Imf7///////////////////////88Wv3///88Wv08Wv3///////////////////////88Wv08Wv08Wv08Wv08Wv3///88Wv3///88Wv08Wv08Wv3///88Wv3DzP7P1/9WcP3v8f9DYP29x/7q7f+5w/6XqP49W/2Rov5IZP2TpP7z9f/d4//Z3/9yh/5uhf5kfP12jP50if6RZI/pAAAAUXRSTlMAoNCwUJCAQHDxMAMQ+/QJYBTWxBm9DzctBs3JI95U662IHwvTtGPhjIRYKXRq+vja2HxHOwO5qaSWZiXnmjMI5ZN5XEMy8s2VcFNMSp5bnHc4p+yiAAAH3ElEQVR42u2caVfaQBSGLxIUkkIIYd8EBWTR1qq1orWrdrPb0Fpbu+///x+UzNzMZIFm6Wl7TuH5RCYwSZ5M3rnxJILJlUf3790d/ZK79+4/ugIzzpUH10a+uPbgBswy1y+PfHP5OswuDy+OAnDxCcwqD9+OgjGrqq5fHAXk4mxegFcujwJzeSZj/cEoBM9g9rhyLYypazM4qB6NOO/fvXo+5vzMJeaN0f7q3XvR8hBmjvsjk2+vCeOVay58Tigvv/GWpzBz3OMjioqivHGbQlV8VF2GmYPf670jgi9OUy6HF2Hm4DbOieDj6RRTr3jTn4p0uXm4XwIP/sm2HDaQT2eTTb3gTRfgj3AnSQiprMLfALcV3hSm+j8xpSaIwRYERDvZ2FqMS9nQ2wpvirwJY6qZGFNbAcFewqAJU8nKBuZPdgglB0FQ0jpBFuIl8MT3tqqygeZhinwJYSrGdncVOFHaEoOpLBKDCDCKhNKAAAwWiIXaEvgEtxWFaeDOp71MfTwNa4q0lbCmlBZdrAcRtUxsJCXwg9hWeFMi1cOaIrGwpqBaISS1Doi/43VwaQB+ENsKb0qkelhTZCOEKWSlqAaawMyEGg7L+LEN/sBthTcleBPaVHJ7sqmsPNA8THmiVOUDkYQNQunAmO0EoRyASb4oZxXwTakqV5UwpsiPsKZIYuA2lW2uGQubvewgYrAIw0iExXGNNqyMxdEPg17U4DYgHbp4aGiS2ikyJtPDimCTGOhA2ebaDKpdujLVritsLe27A5CP79bW9s1tgcTaS2k9aXy9QecEbdy0xvo21g4nmXptTfWwpkhNc5raSBEkNWQXDCSIDRmAiVvaZ9/L4yhiu9wEKJYJ74Rd4cu2qb5cu7p+xAaceitJTFoFGBPH4XtCf7NubguHdU5MoVdXAVaIjYTFFBf0/IMz1YWpl2+9TSG6ajfVJBa8TK2yNRu2obICJ0w2cghjMuxqx2EjqiltwZbydWGqnsS+hSknC/lfmPpCuKnRuTPVxZX53bcpsmcz1SFBTMEtYlAGylUM6uMUsbFF1zGWG+s7KnBUIYqpXDJN6dhJ2m1KsDvd1Olri6mzz45UF6ZennqbShLGosWUlghmasBbALRL9PN2KYN7reOH5ABAsuqo9HaAgqYtrKnUlECabAq5M9nU2emHl0SYGnuzLP5AU8jHD6dnHqbaDcLoC1M9lHOyWiq0uamiLA/ZT2QDVZiCHP1wS+RLTekwHeslXpfvAX5R0DqhYZ5kx7dYOJB0LFwcprZdpmr9vCI/JpTN0nh/WNdb8pjiFFOjr9ZUD2oqquqYDjvc1Jolu6CLptxVgjBVZ4dq/KBFWALrluzKJugGVACtTOwMFbPXZVouKGwfKhZTua20pDlNtdj8sU4oBUeVMPnqG2NL9YBXXxS0TQyPKprCsVwFipLxNlW6ya4CgAKzruXpOElJDHa+jwBA7TniqwlQsR5jNkkS7dsFbmqhCBSHKRkYzPy6w9TkRDewpXqwRI8CHODNWCbHTG3jaUVue5vCFTrAIX6jQNzEWX3ZaSwTQbIKKRxxjLqsiKuY3NTAbQpnDzGoHk+vPF/bTNlT3X+VgKZgx3aeY32MFUTyYSqbZPU2FgwF2CZuFsVNXL+rX8LWXollDdhBUx1wm3LvXNSzRkdT9lR/HajyjNLzaDPFlhqA1L1MifuUZto840vTTSlAWd1gdnMKm+4mmkqqLlOTdq7h2xSmOhLcFMStpnbsux7zY+qIRV3FHAgD1kfcSgHyS/FIK7UK1sprASv3LDC6Tcn4GEfnk03dRN1YIt/yZQr5ENaUq6SJ5QnlBHDi4qYwshouU/yWjs+BSooOCTz8PJPT4zUo5THKYIVIFyhFKuIQTbWnmCJ3sGNmeZ+bWvc2NTr/LVNKVJjCyWj5mIqqEGEK7/CqAHDgMBW3qBYDJkrPfUknmUi8oPQxxPvMSQJHaIeIimIlw27msL+9aaZSR/QK3jVvnQAirHpQjRicaoqnenhToFbEgabxiCLpfjdBuCmePomrewskazeVF7PCgeUP37sFVZPKbGpVVs3O9Nvp/ccY6XVQzbm3u7WHvRzxO2S3KaSx3+/dJGLkbWFFGmnU1qaaEqke3hRoNW7K/adJNKWmCGffbgoOCZLjKWRHAtggVtAfwB33nZy3KUGSDv4CERSnmUK+/o4pUVbFAOSU2xQW7Jyow9SxMELJZ4iNQ8BLxEZCnnDjt6YFMnUbKLqlZaop5F1IU8jOJR4zRwnCSaIpx+GnVLspTDcxLWXLxMJj2qw0iY2bBaDYmjMr4GUqaa/yee4h+nRTyHlIU0hdBHI1R5B2H01Rsrv8eLIOU2lnfVna4vte6wNSjIqjTHTzgCxxrameCp6m9hZT5virg8lxhgeAp6mzzwFMFSWDAljYMVqKQCl09c1WrncMmmRg+MD2XCajx44UgCW6RgOGKuGiIJ+OVGqtXGy7BAKtM8wt1Mq7XQlbsd/ebmazEumgvKpkcAwMvi1e0mnxRrlWjvStfSjSsLLZ2l0sup/gQFNTUv0Vb/6PHspDU8GfChKmRKr/108FoangT5oJU8Lhf/2kGZoK/vSiMCUuzP/66UU0FfyJ2DcuU2fn//UTsWhq/pS1J/2oQXz+5P78bRCfzN8wCsb8rTXfzN+E9MX87VrfzN/Y/ovM/wuAX34CigQonPAMA7gAAAAASUVORK5CYII="); + background-size: contain; +} + +.navigation__right { + flex: 1; + text-align: right; + visibility: hidden; + position: relative; +} + +.navigation__right, +.navigation__right > * { + height: 100%; +} + +.navigation__right .k-menu { + display: inline-block; + color: var(--color-light); + font-weight: 400; + border: 0; +} + +.ns-navigation .navigation__right > .k-menu > .k-item { + height: 100%; + border: 0; + opacity: 1; + display: flex; + align-items: center; +} + +.navigation__right > .k-menu > .k-item .k-link { + color: inherit; + padding: 0 1.5em; +} + +.ns-navigation .navigation__right > .k-menu > .k-item > .k-link { + line-height: 4.72em; +} + +.ns-navigation .navigation__right > .k-menu .k-separator { + background: var(--transparent-white-50); + font-size: inherit; + width: 1px; + height: 1.4em; + vertical-align: middle; + margin-top: 1.43em; +} + +html .ns-navigation .navigation__right .k-menu .k-link.-github { + padding: .8em; + font-size: 1.2em; + line-height: 1.2em; +} + +html .ns-navigation .navigation__right .k-menu .k-link.-github:hover { + background: none; +} + +html .ns-navigation .navigation__right .k-menu .k-link.-github a { + padding: 5px; + display: inline-block; + color: var(--color-light); +} + +html .ns-navigation .navigation__right .k-menu .k-link.-github a:hover, +.navigation__right > .k-menu > .k-item:not(.k-state-disabled) > .k-state-active, +.navigation__right > .k-menu > .k-item:not(.k-state-disabled) > .k-link:not(.ns-button):hover { + color: var(--color-menu-secondary); +} + +.k-panelbar, +html .ns-navigation .k-menu-group { + color: var(--color-accent); + background: var(--background-light); +} + +html .ns-menu > .k-item { + text-align: center; + flex-direction: column; + justify-content: center; +} + +html .ns-navigation .k-animation-container { + padding: 40px .71em .71em; + left: auto !important; + min-width: 100%; + text-align: left; + margin-top: -50px; +} + +html .ns-navigation .k-menu .k-menu-group { + border: 0; + text-align: left; + min-width: 12.8em; + box-shadow: 0 20px 40px var(--transparent-dark-20); + border-radius: 5px; + overflow: visible !important; +} + +html .ns-navigation .k-menu .k-menu-group:before { + content: ""; + display: block; + position: absolute; + top: -28px; + left: 50%; + width: 82px; + height: 42px; + margin-left: -41px; + background: radial-gradient(circle at bottom left,transparent 0,transparent 68.5%,#fff 70.5%), + radial-gradient(circle at bottom right,transparent 0,transparent 68.5%,#fff 70.5%); + background-position: 0 100%,100% 100%,100% 0,0 0; + background-size: 52% 100%; + background-repeat: no-repeat; + transform: scaleY(-1) scale(.35); +} +html .ns-navigation .k-menu-group .k-item { + overflow: hidden; +} + +html .ns-navigation .k-menu-group .k-item:first-child { + border-top-left-radius: 5px; + border-top-right-radius: 5px; +} + +html .ns-navigation .k-menu-group .k-item:last-child { + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; +} + +html .k-panelbar .k-group, +html .k-panelbar .k-item .k-link, +html .ns-navigation .k-menu-group .k-item .k-link { + line-height: 3.6em; + font-size: .92em; + font-weight: 600; + color: var(--color-secondary); + border: 0; + text-align: left; +} + +html .k-panelbar .k-item .k-state-hover, +html .k-panelbar .k-item .k-item .k-state-selected, +html .ns-navigation .k-menu-group .k-item .k-link:hover { + color: var(--color-secondary); + background: var(--transparent-dark-05); +} + +html .k-panelbar .k-group { + padding: 0; +} + +html .k-panelbar-collapse.k-icon, +html .k-panelbar-expand.k-icon { + right: 8px; +} + +.ns-menu-trigger { + position: absolute; + left: -5.8%; + width: 5em; + height: 100%; + color: var(--color-light); + font-size: 1em; + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; +} + +.ns-menu-trigger.k-state-selected, +.ns-menu-trigger:hover { + color: var(--color-secondary); + background: var(--color-light); +} + +.ns-navigation [target=_blank]:after, +.ns-start-links [target=_blank]:after, +.ns-menu-trigger:after { + font-family: "Font Awesome 5 Pro"; + margin: -.1em -.3em 0 .2em; +} + +.ns-navigation .k-menu-expand-arrow:before { + content: ""; + width: 0; + height: 0; + border-left: 3px solid transparent; + border-right: 3px solid transparent; + border-top: 5px solid var(--transparent-white-70); +} + +.ns-menu-trigger:after { + font-size: 1.5em; + content: "\f0c9"; + margin: 0; +} + +.ns-menu-trigger.k-state-selected:after { + content: "\00d7"; + font-size: 3em; +} + +.ns-navigation [target=_blank]:after, +.ns-start-links [target=_blank]:after { + content: "\f08e"; + font-weight: 300; + font-size: 11px; + position: absolute; + margin: -.5em 0 0 .5em; +} + +.ns-start-links [target=_blank]:after { + margin-top: 0; +} + +.k-panelbar { + position: absolute; + top: 100%; + left: -5.6%; + z-index: 10; + width: 40vw; + min-width: 250px; + height: auto; + border: 0; + text-align: left; + font-size: 1.2em; + font-weight: 600; + display: none; + border-radius: 0 5px 5px 5px; + box-shadow: 0 20px 40px var(--transparent-dark-20); +} + +/* Flavor Header */ + +.ns-flavor-header { + display: flex; + align-items: center; + font-size: .88em; + height: 4.71em; +} + +.ns-flavor-header a { + color: var(--color-dark); +} + +.ns-flavor-header a:hover .flavor-header__title:after { + color: var(--color-success); +} + +.flavor-header__search { + flex: 1; + padding-left: 3.57em; +} + +.flavor-header__search > div { + width: calc(100% + 300px); +} + +.flavor-header__navigation { + color: inherit; + width: 16.43em; + margin-left: -20em; +} + +.flavor-header__title { + font-size: 1.5em; + margin: 0; +} + +.flavor-header__title:after { + font-size: .57em; + display: block; + content: "< All Flavors"; + text-transform: uppercase; + line-height: 1; +} + +/* Left TOC */ + +/* TreeView */ + +html .k-treeview { + white-space: normal; + overflow: hidden; +} + +html .k-treeview .k-in { + border: 0; + cursor: pointer; + margin: 0; + padding-left: 1.87em; + user-select: none; +} + +.k-treeview .k-item > div { + display: flex; + align-items: center; +} + +.k-treeview-lines > .k-item > div > .k-icon { + display: none; +} + +.k-treeview-lines > .k-item > div > .k-in { + text-transform: uppercase; +} + +html .k-treeview .k-group .k-icon { + margin: .5em -1.71em 0 .71em; + font-size: .93em; + min-width: 1em; + align-self: flex-start; +} + +.k-treeview .k-group .k-group .k-in { + padding-top: .33em; + padding-bottom: .33em; + padding-right: .5em; + font-weight: 600; + text-transform: capitalize; +} + +html .k-treeview .k-icon:before, +.k-treeview-lines .k-group .k-group .k-in:before { + content: "\f15c"; + font-family: "Font Awesome 5 Pro"; + font-weight: 300; + font-size: 14px; + color: var(--color-secondary); + margin-left: -1.25em; + margin-right: .5em; +} + +.k-treeview-lines .k-group .k-group .k-icon + .k-in:before { + display: none; +} + +html .k-treeview .k-in > a { + color: inherit; + font-weight: inherit; +} + +html .k-treeview .k-icon:before { + font-weight: 400; + content: "\f105"; + margin: 0; + position: absolute; + display: inline-flex; + align-items: center; + justify-content: center; +} + +html .k-treeview .k-i-collapse:before { + content: "\f107"; +} + +html .k-treeview-lines > .k-item { + margin: 0 -1.6em 1.33em -.8em; + padding: 0; +} + +html .k-treeview-lines > .k-item > .k-group { + padding-top: .33em; +} + +html .k-treeview-lines > .k-item > .k-group > .k-item { + margin: 0 .3em; + padding: 0 0 0 .8em; + width: 100%; + box-sizing: border-box; +} + +html .k-treeview-lines > .k-item > .k-group > .k-item > .k-group .k-in { + font-weight: 400; + color: var(--color-accent); +} + +html .k-treeview-lines > .k-item > .k-group > .ns-state-expanded { + border: solid var(--border-light-blue); + border-width: 1px 0; + background: var(--background-special); +} + +html .k-treeview.k-treeview.k-treeview.k-treeview.k-treeview .k-state-selected { + color: var(--color-green); +} + +/* Page */ + +#page-inner-content { + display: flex; +} + +#page-article { + flex: 1; + min-width: 0; +} + +html.ns-root .-hidden { + display: none; +} + +/* Collapse button and container */ + +.ns-side-nav { + font-size: .88em; + margin: -.71em 1.8em 0 -22.86em; + overflow: hidden; + padding: 1.43em; +} + +.right-nav__input, +.side-nav__burger-input { + opacity: 0; + position: absolute; +} + +.navigation__burger-menu, +.side-nav__burger-menu { + display: none; + border: 0; + z-index: 1; + width: 2.22em; + height: 2.22em; + cursor: pointer; + font-size: 1.29em; + position: relative; + align-items: center; + justify-content: center; + background: var(--color-light); + color: var(--color-secondary); + transition: box-shadow .3s ease-out; + transition-delay: .2s; + box-shadow: 0 3px 20px var(--transparent-dark-15); +} + +.side-nav__burger-menu { + border-radius: 4px; +} + +.side-nav__burger-input:checked + .side-nav__burger-menu { + border-radius: 12px; +} + +.side-nav__burger-menu:before { + transform: rotate(-135deg); + transform-origin: center center; + transition: transform .2s ease-out; +} + +.side-nav__burger-menu:hover { + color: var(--color-dark); +} + +.right-nav__input:checked + label, +.side-nav__burger-input:checked + label { + box-shadow: 0 0 0 var(--transparent-dark-15); + transition-delay: -.3s; +} + +html body .side-nav__tree { + contain: content; + will-change: width, height; + transition: width .3s ease-out, max-height .3s ease-out; + background: var(--color-light); + box-shadow: 0 3px 20px var(--transparent-dark-15); + padding: 1.4em 1.72em 0 0; + width: 16.43em; + margin-top: 0; + border-radius: 12px; +} + +.side-nav__tree > ul { + font-size: 1.07em; + min-width: 15.33em; +} + +/* Breadcrumbs */ + +.ns-breadcrumb ul { + white-space: nowrap; + list-style: none; + padding: 0; +} + +.ns-breadcrumb ul li { + display: inline-block; +} + +.ns-breadcrumb ul li:after { + content: "/"; + display: inline-block; + margin: 0 5px; +} + +.ns-breadcrumb ul li:last-child:after { + display: none; +} + +/* Right TOC */ + +.right-nav__container { + transition: all 0.5s ease; + top: 6.25em; + margin-left: 1.25em; + position: -webkit-sticky; + position: sticky; + float: right; + margin-right: -17em; +} + +.right-nav__tree::-webkit-scrollbar { + width: 10px; + transition: all 0.7s ease; +} + + + +.right-nav__tree:hover::-webkit-scrollbar-thumb { + background: var(--border-light-blue); + border-radius: 10px; + +} + +.right-nav__tree { + scrollbar-width: thin; + scrollbar-color: transparent; +} + +.right-nav__tree:hover { + scrollbar-color: var(--border-light-blue); +} + + +.ns-tip-container ~ .ns-page .right-nav__container { + top: 7.6em; +} + + +.right-nav__tree { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + border-left: 1px solid var(--color-purple); + height: calc(100vh - 12.76em); + overflow-y: auto; +} + +.right-nav__tree ul { + list-style: none; + padding: 0 0 0 1.33em; + display: block; +} + +.right-nav__tree > ul { + font-size: .93em; + font-weight: 600; + width: 13.33em; + margin: 0 0 3.13em; + -webkit-user-select: text; + -moz-user-select: -moz-text; + -ms-user-select: text; + user-select: text; +} + +.right-nav__tree ul ul { + font-size: .93em; + font-weight: 400; + padding: 0; +} + +.right-nav__tree > div { + font-weight: 400; + vertical-align: middle; + margin-left: 1.25em; + margin-bottom: 1.5em; +} + +.right-nav__tree > div:first-child { + display: inline-block; +} + +.right-nav__tree li { + display: block; +} + +.right-nav__label { + display: none; + cursor: pointer; + width: 2.5em; + height: 2.5em; + vertical-align: middle; + align-items: center; + justify-content: center; + opacity: .75; +} + +.right-nav__label:hover { + opacity: 1; +} + +.copy-button.ns-button:before, +.right-nav__label:before { + content: "\f100"; + font-family: "Font Awesome 5 Pro"; + font-weight: 300; + font-size: 1.5em; +} + +.right-nav__input:checked + .right-nav__label:before { + content: "\f101"; +} + +.right-nav__tree ul a { + display: block; + padding: .33em 0; + position: relative; +} + +.right-nav__tree .-references + ul a { + text-transform: capitalize; +} + +.right-nav__tree .ns-state-selected:before { + content: "\a0"; + position: absolute; + top: 0; + left: -1.53em; + width: .2em; + height: 100%; + background: var(--background-green); +} + +.right-nav__tree a.ns-state-selected { + color: var(--color-green); +} + +div.right-nav__links { + text-transform: none; + padding-bottom: 30px; +} + +div.right-nav__links .ns-button { + padding-left: 1em; + padding-right: 1em; +} + +.right-nav__links a:not(.ns-button) { + margin-top: 1.56em; + display: block; +} +.hide { + display: none !important; +} + +.right-nav__links a:not(.ns-button) > i { + margin-right: .2em; +} + +/* Code Container */ + +html .nd-code-container .k-loading { + display: none; +} + +html .nd-code-container, +html .nd-code-container .k-item { + border: none; +} + +html .nd-code-container .k-item { + padding: 0 15px; +} + +html .nd-code-container .k-item.k-first { + padding-left: 0; +} + +html .nd-code-container .k-link { + font-weight: 600; + font-size: 12px; + text-transform: uppercase; + padding: 5px 0; + color: var(--color-accent); + border-bottom: 3px solid transparent; +} + +.nd-code-container .k-tabstrip-items { + margin-bottom: .5em; +} + +html .nd-code-container .k-tabstrip-items .k-state-active .k-link { + border-bottom-color: currentColor; + color: var(--color-green); +} + +html .nd-code-container .k-content { + padding: 0; + border: 0; + overflow: hidden; + margin: 0; +} + +html .nd-code-container pre { + overflow-x: auto; + font-weight: 400; + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; +} + +html .k-tabstrip-wrapper { + margin-bottom: 20px; +} + +html .nd-code-container.k-floatwrap:after { + display: none; +} + +/* Blockquote hints */ + +blockquote { + margin: 1.25em 0; + display: flex; + position: relative; + flex-direction: column; + justify-content: center; + background: var(--background-special); + border: 1px solid var(--border-light-blue); + padding: 1.25em 1.25em 1.25em 5.63em; + min-height: 3em; + border-radius: 4px; +} + +blockquote:before { + position: absolute; + content: "\a0"; + display: block; + top: .42em; + left: .42em; + width: 1em; + height: 1em; + font-size: 3.2em; + line-height: 1; + margin-right: .4em; + background: transparent center center url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2050%2050%22%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill%3Aurl%28%23New_Gradient_Swatch_1%29%3B%7D.cls-2%7Bfill%3A%23fff%3B%7D.cls-3%7Bfill%3A%2304a586%3B%7D%3C%2Fstyle%3E%3ClinearGradient%20id%3D%22New_Gradient_Swatch_1%22%20x1%3D%226.86%22%20y1%3D%2221.1%22%20x2%3D%2261.66%22%20y2%3D%2221.1%22%20gradientUnits%3D%22userSpaceOnUse%22%3E%3Cstop%20offset%3D%220%22%20stop-color%3D%22%23d1e4a5%22%2F%3E%3Cstop%20offset%3D%221%22%20stop-color%3D%22%2330ce91%22%2F%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Ctitle%3EArtboard%201%3C%2Ftitle%3E%3Cpath%20class%3D%22cls-1%22%20d%3D%22M43.14%2C18.14A18.14%2C18.14%2C0%2C1%2C0%2C18.24%2C35a1.87%2C1.87%2C0%2C0%2C1%2C1.17%2C1.73v5.48H30.59V36.71A1.86%2C1.86%2C0%2C0%2C1%2C31.75%2C35%2C18.13%2C18.13%2C0%2C0%2C0%2C43.14%2C18.14Z%22%2F%3E%3Cpath%20class%3D%22cls-2%22%20d%3D%22M23.83%2C22.38H18.46V20.44H31.54v1.94h-5.4V38.11H23.83Z%22%2F%3E%3Cpath%20class%3D%22cls-3%22%20d%3D%22M19%2C37.83H31a0%2C0%2C0%2C0%2C1%2C0%2C0v8.32A3.85%2C3.85%2C0%2C0%2C1%2C27.18%2C50H22.82A3.85%2C3.85%2C0%2C0%2C1%2C19%2C46.15V37.83A0%2C0%2C0%2C0%2C1%2C19%2C37.83Z%22%2F%3E%3C%2Fsvg%3E"); +} + +blockquote > *:first-child { + margin-top: 0; +} + +blockquote > *:last-child { + margin-bottom: 0; +} + +/* Button */ + +.ns-button { + display: inline-block; + color: var(--color-light); + background: var(--background-success); + border: 0; + border-radius: 4px; + font: 14px Avenir; + font-weight: 600; + min-width: 9.29em; + white-space: nowrap; + height: 2.86em; + line-height: 3.15em; + cursor: pointer; + vertical-align: top; + box-shadow: 0 3px 7px var(--transparent-dark-15); + transition: background .2s ease-out; +} + +.ns-button, +html .ns-navigation .navigation__right .k-menu .k-item .ns-button { + padding: 0 2.14em; + cursor: pointer !important; + box-sizing: border-box; + margin: 0 .36em; +} + +.ns-feedback .ns-button, +.footer__contribute > .ns-button, +html .ns-navigation .navigation__right .k-menu .k-item .ns-button { + height: 2.25em; + line-height: 2.45em; +} + +html .ns-navigation .navigation__right .k-menu .k-item .ns-button { + margin-left: 20px; + font-size: 1.05em; +} + +.ns-button:last-of-type, +html .ns-navigation .navigation__right > .k-menu > .k-last .ns-button { + margin-right: 0; +} + +.ns-button:first-of-type { + margin-left: 0; +} + +.ns-button:hover { + color: var(--color-light); + background: var(--background-success-hover); +} + +.ns-button.-action { + color: var(--color-light); + border-color: transparent; + background: var(--background-button); +} + +.ns-button.-action:hover { + background: var(--background-button-hover); +} + +.ns-button.-large { + height: 3em; + line-height: 3.15em; +} + +.ns-button.-hollow { + color: var(--background-button); + border: 1px solid currentColor; + background: transparent; + box-shadow: none; +} + +.ns-button.-hollow:hover { + color: var(--background-button-hover); + background: var(--background-special); +} + +/* Copy Button */ + +.ns-copy-container { + position: relative; +} + +.copy-button.ns-button { + font-size: 11px; + position: absolute; + right: 20px; + top: 14px; + display: none; + min-width: 0; + padding: 0 1em; +} + +.copy-button.ns-button:before { + content: "\f0c5"; + font-size: 1.4em; + line-height: 2.1em; + display: block; +} + +.ns-copy-container:hover .copy-button { + display: block; +} + +/* Landing page */ + +.-landing .ns-page { + display: flex; + flex-flow: wrap; + margin: 0 -1.25em; + position: relative; + justify-content: space-between; + background: var(--background-special); +} + +.-landing .ns-footer { + width: auto; + margin-left: unset; +} + +.ns-card, +.ns-card:hover { + padding: 1.88em 1.25em; + background: var(--color-light); + box-shadow: 0 3px 6px var(--transparent-dark-15); + color: var(--color-secondary); + display: inline-block; + margin: 1.88em .94em 0; + box-sizing: border-box; + border-radius: 12px; + flex: 1 1 16.5em; + cursor: default; + transition: transform .2s ease-out; + transition-property: transform, box-shadow; +} + +.ns-card:hover { + transform: translateY(5px); + box-shadow: 0 6px 12px var(--transparent-dark-15); +} + +a.ns-card:hover { + cursor: pointer; +} + +.ns-card span + a { + margin-top: 10px; +} + +.ns-card a { + display: block; + font-size: .88em; + font-weight: 600; +} + +.card__icon { + width: 4em; + height: 101%; + float: left; + margin-right: 1.25em; + fill: var(--color-secondary); +} + +.card__title { + color: var(--color-dark); + margin: 0 0 .5em; +} + +.card__title > span { + top: -2px; + position: relative; +} + +.card__description { + display: block; +} + +.ns-page > h1 { + margin: 1em .3em .4em; + width: 100%; +} + +.ns-start-links { + width: 100%; + margin-top: 3em; + background: var(--color-light); + position: relative; +} + +.ns-start-links #___gcse_0 { + width: 50%; + margin-left: auto; + margin-right: auto; +} + +.ns-start-links > div:first-of-type { + margin-top: 4em; +} + +.ns-start-links > div:last-of-type { + margin-bottom: 2.5em; +} + +.start-links__container { + display: flex; + flex-wrap: wrap; + align-items: flex-start; + justify-content: space-between; +} + +.start-links__category { + margin: 4em .94em 0; +} + +.start-links__container ul { + padding: 0; + list-style: none; +} + +.start-links__container li { + font-size: 1.31em; + line-height: 1; + margin: 1em 0; +} + +.start-links__container > * { + flex: 1 1 12.5em; +} + +.start-links__container hr { + border: 0; + background: none; + height: 0; + margin: 0; +} + +.start-links__title { + font-weight: 600; + margin: 1.42em 0 .9em; +} + +/* Footer */ + +.ns-footer { + z-index: 0; + font-size: .88em; + position: relative; + width: calc(100% + 600px); + margin-left: -300px; +} + +.ns-footer:after, +.ns-footer:before, +#feedback-section.-detached:before { + position: absolute; + display: block; + content: "\a0"; + width: 100vw; + height: 4.29em; + left: calc((100% - 100vw) / 2); + background: var(--background-footer-blue); + z-index: -1; +} + +.ns-footer:after { + height: 100%; + top: 0; + background: var(--background-base); + z-index: -2; +} + +#feedback-section.-detached:before { + position: fixed; +} + +.footer__form { + padding: 1.6em; + border-radius: 12px; + font-size: 1.14em; + background: var(--background-footer-gray); +} + +.footer__form { + display: flex; +} + +.footer__form > div > h4 { + font: 1.56rem Avenir; + font-weight: 900; + margin-bottom: .2em; +} + +.footer__form > div > h5 { + color: var(--transparent-dark-70); + font-size: .8em; + margin: .6em 0 0; +} + +/* Social Links */ + +.footer__social-links { + display: flex; + flex: 1; + align-items: center; + justify-content: space-evenly; + margin-right: -1.6em; +} + +.footer__social-links .slack-button, +.footer__social-links #fb-root~iframe { + vertical-align: top; +} + +.footer__social-links .slack-iframe { + margin: 0; +} + +.footer__social-links #fb-root { + display: none; +} + +.footer__social-links > span { + display: inline-block; + height: 23px; +} + +.footer__social-links > * { + margin: 0 5px; +} + +.footer__npm-link { + display: inline-block; + background: #555 0 50% no-repeat url("https://img.shields.io/npm/dt/nativescript.svg?style=popout&label=+&colorB=3C5AFD&logoWidth=48&logo=data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxOCA3Ij48cGF0aCBmaWxsPSIjQ0IzODM3IiBkPSJNMCAwdjZoNXYxaDRWNmg5VjAiPjwvcGF0aD48cGF0aCBmaWxsPSIjRkZGIiBkPSJNMSAxdjRoMlYyaDF2M2gxVjFoMXY1aDJWMmgxdjJIOHYxaDJWMWgxdjRoMlYyaDF2M2gxVjJoMXYzaDFWMSI+PC9wYXRoPjwvc3ZnPg=="); + width: 91px; + height: 20px; + border-left: 4px solid transparent; + background-size: cover; +} + +html .fb_iframe_widget { + display: inline-flex; +} + +.slack-button { + position: relative; + height: 20px; +} + +.slack-button img.is-active { + opacity: 0.7; +} + +.slack-iframe { + width: 330px; + height: 420px; + margin-top: -160px !important; + margin-left: -4px !important; +} + +.slack-popup { + width: 304px; + height: 230px; + overflow: hidden; + border-radius: 9px; + border: 1px solid #7f7f7f; +} + +.slack-wrap { + position: absolute; + bottom: 30px; + left: -150px; + opacity: 0; + pointer-events: none; + transition: opacity 0.5s; +} + +.slack-wrap.is-active { + opacity: 1; + pointer-events: all; +} + +.slack-wrap:after { + content: ""; + background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAMBAMAAACU11D1AAAAGFBMVEUAAAB/f39/f39/f39/f39/f3/////g4ODe2rlsAAAABnRSTlMA6z9A7h7TgndpAAAAQklEQVQI12MQT4OBQgbFMigzXZiBSRwmbMAAlIAJMwAl4MIgCagwWAIqDJEAC8MkChWANESiXAhIQiVcgMIwEAomAZ4yGWDCL5O6AAAAAElFTkSuQmCC') center bottom no-repeat; + display: block; + width: 22px; + height: 12px; + bottom: -11px; + position: absolute; + left: 50%; + margin-left: -11px; +} + +@media only screen and (max-width: 480px) { + .footer__social-links { + height: 80px + } +} + +.login { + background: white; + height: 230px !important; +} + +.login p { + font-size: 13px; + color: #444 !important; + background: #f1f1f1; + padding: 3px 5px 20px 5px; + font-family: Open Sans, sans-serif; +} + +.invite-another { + display: none; + margin: 50px 70px; + background: white !important; + padding: 0 !important; +} + +.invite-another:hover { + text-decoration: underline; + color: blue !important; + cursor: pointer; +} + +.login label { + margin-left: 10%; +} + +.slack-email { + margin-left: 10% !important; + width: 80% !important; + background: #fbfbfb; +} + +.get-invitation { + width: 40% !important; + float: right; + margin-right: 10%; + font-size: 14px !important; + margin-top: 10px; + background: #008ec2 !important; + font-weight: 100 !important; + cursor: pointer !important; +} + +.slack-button { + cursor: default; +} + +.slack-button img { + cursor: pointer; +} + + +.footer__newsletter-frame { + border: 0; + max-width: 100%; + height: 42px; + background: var(--background-light); + box-shadow: 0 3px 6px var(--transparent-dark-15); +} + +.-landing .ns-feedback, +.-landing .ns-footer:before { + height: 14.22em; +} + +.-landing .ns-feedback #feedback-section { + flex-direction: column; + align-items: center; + justify-content: center; + color: var(--color-light); +} + +.-landing .ns-feedback > div > div { + font-size: 1.5em; + padding: 0 0 1.43em; +} + +.ns-feedback .ns-button { + font-size: 1.135em; +} + +/* Sitemap */ + +.footer__sitemap-container { + display: flex; + flex-direction: column; +} + +.footer__sitemap-container > .row { + display: flex; + flex-direction: row; + align-items: center; +} + +.footer__sitemap-container .footer__links { + align-items: flex-start; + flex-wrap: wrap; +} + +.footer__links > div { + flex: 1; +} + +.footer__links h5 { + margin-bottom: -.3em; + font-size: .9em; +} + +.footer__links ul { + list-style: none; + padding: 0; + font-size: 1.29em; + line-height: 2.2em; + margin-bottom: 2em; +} + +.footer__contribute { + display: flex; + align-items: center; + justify-content: space-evenly; + font-size: 1.27em; + position: relative; + padding: 2em; + margin: 4em 0; + border: 2px solid var(--border-light-blue); + border-radius: 12px; +} + +.footer__contribute .ns-button { + font-size: .895em; +} + +.footer__contribute > * { + margin: 0 .67em 0 0; +} + +.footer__last-row { + height: 4.29em; + margin-top: 2.14em; +} + +.footer__last-row > .navigation__logo { + height: 2em; + width: 20em; + display: flex; + margin-top: -.5em; + align-items: flex-end; + background-position: 7em 0; + background-image: url("https://d2odgkulk9w7if.cloudfront.net/images/default-source/logos/progress-logo-min.png?sfvrsn=381d0dfe_2"); +} + +.footer__last-row > *:last-child { + flex: 1; + min-width: 0; +} + +.footer__copyright { + text-align: right; + color: var(--transparent-dark-50); +} + +.footer__copyright a { + color: var(--background-footer-blue); +} + +.footer__copyright a:hover { + text-decoration: underline; +} + +.footer__copyright > * { + white-space: nowrap; +} + +/* Feedback Form */ + +#feedback-checkbox-area { + margin-top: 24px; +} + +#feedback-form-window { + background-color: var(--background-light); + padding: 0 30px 30px; + overflow: hidden; +} + +html .k-overlay { + background: var(--transparent-dark-60); +} + +html div.k-window { + border: 0; + box-shadow: 0 0 20px rgba(0, 0, 0, .4); +} + +.k-widget.k-window input[type=text], +.k-widget.k-window textarea { + box-sizing: border-box; +} + +html .k-window-titlebar { + background: var(--background-light); + border: 0; + padding-top: 20px; +} + +html .k-window-title { + margin: 0 .3em; +} + +.feedback-extw__input, +.feedback-extw__textarea { + margin: 12px 0 30px; + padding: 10px; + width: 100%; + font-size: 14px; + color: var(--color-secondary); + box-sizing: border-box; + border: 1px solid var(--border-light-blue); + box-shadow: none; + outline: none; +} + +.feedback-extw__textarea { + margin: 10px 0 20px; + width: 100%; +} + +.feedback-extw__foot { + margin-top: 15px; +} + +html.ns-root input::-webkit-input-placeholder, +html.ns-root textarea::-webkit-input-placeholder { + font-size: inherit; + color: var(--transparent-dark-50); +} + +html.ns-root input::-moz-placeholder, +html.ns-root textarea::-moz-placeholder { + font-size: inherit; + color: var(--transparent-dark-50); +} + +html.ns-root input:-ms-input-placeholder, +html.ns-root textarea:-ms-input-placeholder { + font-size: inherit; + color: var(--transparent-dark-50); +} + +#send-feedback { + float: left; +} + +.feedback-extw__textarea.k-invalid { + border-color: var(--color-error); +} + +#feedback-form span.k-tooltip { + display: block; + position: absolute; + font-size: 13px; + color: var(--color-error); + border: 0; + background-clip: padding-box; + text-align: left; + padding: 5px 0; + margin-top: -26px; +} + +#feedback-form-window, +#feedback-form .k-tooltip .k-icon { + display: none; +} + +#feedback-form-window .k-notification { + position: fixed; + left: 20px; + width: calc(100% - 40px); + top: -60px; + background: var(--background-light); +} + +#feedback-menu-container { + color: var(--color-light); + margin: 0; + width: 100%; + display: flex; + align-items: center; + font-size: 1.5em; +} + +#feedback-menu-container a { + cursor: pointer; + color: var(--color-light); + opacity: .75; +} + +#feedback-menu-container a:hover { + opacity: 1; +} + +#feedback-buttons-container, +#feedback-submitted-container { + flex: 1; + display: flex; + align-items: center; + padding-right: 35px; +} + +#feedback-section { + display: flex; + align-items: center; + width: 100%; + height: inherit; + background: var(--background-footer-blue); +} + +#feedback-section.-detached { + position: fixed; + bottom: 0; + z-index: 10000; + width: calc(50% + 600px); +} + +.ns-feedback { + height: 4.29em; +} + +.feedback__title { + flex: 1; +} + +.close-banner-button { + width: 1.14em; + height: 1.14em; + position: fixed; + margin-top: 1px; + right: 1em; + display: flex; + align-items: center; + justify-content: center; +} + +.close-banner-button:before { + font-family: "Font Awesome 5 Pro"; + font-weight: 300; + font-size: .86em; + display: flex; + align-items: center; + justify-content: center; + content: "\f00d"; +} + +.ns-tip-container .close-banner-button { + position: absolute; + right: 0; +} + +/* Checkboxes and radios */ + +.tp-checkbox, +.tp-checkbox .checkbox__label { + display: flex; +} + +.tp-checkbox { + position: relative; +} + +.tp-checkbox.-ellipsis label .checkbox__text, +.tp-checkbox.-ellipsis label .radio__text, +.tp-radio.-ellipsis label .checkbox__text, +.tp-radio.-ellipsis label .radio__text { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + word-wrap: break-word; +} + +.tp-checkbox .checkbox__label, +.tp-radio .radio__label { + position: relative; + align-items: center; + padding: 8px 0; + width: 100%; + white-space: nowrap; + cursor: pointer; + -webkit-transition: color .3s; + transition: color .3s; +} + +.tp-checkbox .checkbox__label .checkbox__icon, +.tp-checkbox .checkbox__label .radio__icon, +.tp-radio .radio__label .checkbox__icon, +.tp-radio .radio__label .radio__icon { + -webkit-transition: color .3s; + transition: color .3s; +} + +.tp-checkbox .checkbox__label .checkbox__text, +.tp-checkbox .checkbox__label .radio__text, +.tp-radio .radio__label .checkbox__text, +.tp-radio .radio__label .radio__text { + display: inline-block; + vertical-align: middle; + white-space: normal; + margin-left: 8px; +} + +.tp-checkbox .checkbox__icon, +.tp-radio .radio__icon { + display: inline-flex; + align-items: center; + justify-content: center; + position: relative; + border: 1px solid rgba(45, 62, 80, .3); + -webkit-transition: border-color .3s; + transition: border-color .3s; +} + +.tp-checkbox .checkbox__icon:before, +.tp-radio .radio__icon:before { + content: "\f00c"; + font-family: "Font Awesome 5 Pro"; + font-size: 12px; + -webkit-transition: opacity .3s; + transition: opacity .3s; + opacity: 0; + display: flex; + align-items: center; + justify-content: center; +} + +.tp-checkbox.-ellipsis, +.tp-radio.-ellipsis { + width: 100% +} + +.tp-checkbox.-ellipsis label .checkbox__text, +.tp-checkbox.-ellipsis label .radio__text, +.tp-radio.-ellipsis label .checkbox__text, +.tp-radio.-ellipsis label .radio__text { + width: 100%; + padding-left: 21px; + margin-left: -16px +} + +.tp-checkbox .checkbox__input { + position: absolute; + top: 5px; + margin: 0; + width: 0; + height: 0; + z-index: 2; + opacity: 0; + cursor: pointer; +} + +.tp-checkbox .checkbox__input:checked + label .checkbox__icon:before, +.tp-checkbox .checkbox__input:checked + label .radio__icon:before { + opacity: 1; +} + +.tp-checkbox .checkbox__input:indeterminate + label .checkbox__icon:before { + opacity: 1; + content: ''; + top: 50%; + left: 50%; + width: 50%; + height: 50%; + margin: -25%; +} + +.tp-checkbox .checkbox__input:disabled, +.tp-checkbox .checkbox__input:disabled + label { + cursor: default; +} + +.tp-radio .radio__icon, +.tp-checkbox .checkbox__icon, +.tp-checkbox .checkbox__icon:before { + width: 1.2em; + height: 1.2em; + font-size: 11px; +} + +.tp-checkbox .checkbox__icon { + align-self: flex-start; + border: 1px solid var(--color-dark); + border-radius: 3px; +} + +.tp-checkbox .checkbox__icon:before { + width: 1em; + height: 1em; +} + +.tp-radio .radio__input:checked + label .checkbox__icon, +.tp-radio .radio__input:checked + label .radio__icon { + border-radius: 50%; +} + +.tp-radio .radio__input:checked + label .checkbox__icon:before, +.tp-radio .radio__input:checked + label .radio__icon:before { + opacity: 1; +} + +.tp-radio .radio__input:disabled, +.tp-radio .radio__input:disabled + label { + cursor: default; +} + +.tp-radio .radio__icon { + border-radius: 50%; +} + +.tp-radio .radio__icon:before { + width: 50%; + height: 50%; + border-radius: 50%; + content: "\a0"; + top: 50%; + left: 50%; + margin: -25% +} + +html .tp-checkbox { + line-height: 1em; +} + +.tp-checkbox .checkbox__icon { + background: var(--background-light); +} + +.tp-checkbox .checkbox__input:checked + label .checkbox__icon, +.tp-checkbox .checkbox__input:checked + label .radio__icon { + border-radius: 2px; + border-color: var(--color-dark); + background-color: var(--background-light); + color: var(--color-dark); +} + +/* checkbox span text */ +.tp-checkbox .checkbox__label .checkbox__text { + font-weight: 400; + color: var(--color-dark); +} + +.tp-radio .radio__input:checked + label .checkbox__icon, +.tp-radio .radio__input:checked + label .radio__icon { + border-color: var(--color-accent); + background-color: var(--background-light); + color: var(--color-dark); +} + +html .tp-checkbox.-disabled .checkbox__label .checkbox__icon { + border-color: var(--transparent-dark-20); +} + +html .tp-checkbox.-disabled .checkbox__label .checkbox__text { + color: var(--transparent-dark-50); +} + +html .tp-radio .radio__icon:before { + background-color: var(--background-accent); +} + +.tp-radio .radio__input:disabled + label .checkbox__icon, +.tp-radio .radio__input:disabled + label .radio__icon { + border-color: var(--transparent-dark-20); +} + +/* table styling (copied from the theme.css which is not loaded anymore */ +article table { + width: 100%; + margin: 1.25em 0; + text-align: left; + border: 1px solid var(--border-light-blue); + font-weight: 400; + background: var(--color-light); + border-radius: 4px; + border-spacing: 0; +} + +article table tr { + border-left-width: 0; + border-right-width: 0; +} + +article table th { + padding: .5em 1.25em; + font-size: .75em; + font-weight: 600; + text-transform: uppercase; + text-align: left; + vertical-align: middle; + line-height: normal; + border-left-width: 0; + border-right-width: 0; +} + +article table td { + padding: .63em .94em; + line-height: normal; + border-left-width: 0; + border-right-width: 0; + border-top: 1px solid var(--border-light-blue); +} + +article table td h2, +article table td h3, +article table td h4, +article table td h5 { + font-weight: 500; + margin: 0; +} + + + +/* Base16 Google Light Prism Theme */ + +pre, code { + font-size: 14px; +} + +a code { + font-size: inherit; + font-family: inherit; +} + +a code:after, +a code:before { + content: "\""; +} + +a strong { + font-weight: inherit; +} + +code[class*="language-"], +pre[class*="language-"] { + white-space: pre; + word-spacing: normal; + word-break: normal; + -moz-tab-size: 4; + tab-size: 4; + -webkit-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, +code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { + text-shadow: none; + background: var(--color-purple); +} + +pre[class*="language-"]::selection, pre[class*="language-"] ::selection, +code[class*="language-"]::selection, code[class*="language-"] ::selection { + text-shadow: none; + background: var(--color-purple); +} + +/* Code blocks */ +pre[class*="language-"] { + padding: 20px; + margin: 0 0 20px; + overflow: auto; + background: var(--color-light); + border: 1px solid var(--border-light-blue); + border-radius: 4px; +} + +/* Inline code */ +:not(pre) > code[class*="language-"] { + padding: .1em; + border-radius: .3em; +} + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: #b4b7b4; +} + +.token.punctuation { + color: #373b41; +} + +.token.namespace { + opacity: .7; +} + +.token.property { + color: #fba922; +} + +.token.selector { + color: #a36ac7; +} + +.token.attr-value, +.token.string, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { + color: #f96a38; +} + +.token.attr-name, +.token.control, +.token.function, +.token.directive, +.token.annotation.punctuation, +.token.class-name, +.token.unit { + color: var(--color-source-green); +} + +.token.operator, +.token.boolean, +.token.number, +.token.statement, +.token.tag, +.token.keyword, +.token.regex, +.token.atrule, +.token.placeholder, +.token.variable { + color: var(--color-accent); +} + +.token.deleted { + text-decoration: line-through; +} + +.token.inserted { + border-bottom: 1px dotted #1d1f21; + text-decoration: none; +} + +.token.italic { + font-style: italic; +} + +.token.important, +.token.bold { + font-weight: bold; +} + +.token.important { + color: #cc342b; +} + +.token.entity { + cursor: help; +} + +pre > code.highlight { + outline: 0.4em solid #cc342b; + outline-offset: .4em; +} + +/* Google Search box */ + +html .gsc-control-cse { + position: relative; + border: 0; + font-family: inherit; + padding: 0; + border-radius: 4px; + overflow: hidden; + box-shadow: 0 3px 6px var(--transparent-dark-15); +} + +html .-landing .gsc-control-cse { + box-shadow: none; + border: 1px solid var(--border-light-blue); +} + +.gsc-input-box table, +.gsc-input-box tr { + height: 36px; +} + +.-landing .gsc-input-box table, +.-landing .gsc-input-box tr { + height: 41px; +} + +.gsc-input-box table, +.gsc-input-box tbody, +.gsc-input-box td { + display: block; +} + +.gsc-input-box tr { + display: flex; + align-items: center; +} + +html .gsc-input-box { + border: 0; + outline: none; + box-shadow: none; +} + +.gsc-input::-webkit-input-placeholder { + color: var(--transparent-dark-50); +} + +html td.gsc-search-button { + position: relative; + order: 1; + width: 3em; + height: inherit; + display: flex; + align-items: center; + justify-content: center; + left: 0; + top: 0; + margin: 0; +} + +.landing td.gsc-search-button { + width: 4em; +} + +td.gsc-search-button:before { + content: "\f002"; + font-family: "Font Awesome 5 Pro"; + display: flex; + line-height: inherit; + font-size: 1.2em; + height: 100%; + width: 100%; + align-items: center; + justify-content: center; +} + +button.gsc-search-button { + position: absolute; + opacity: .01; + height: 100%; + cursor: pointer; + left: 0; + top: 0; + width: 100%; + padding: 0; +} + +.gsc-search-button svg { + margin-top: 2px; + font-size: 1rem; + width: 1em; + height: 1em; +} + +html form.gsc-search-box, +html table.gsc-search-box { + margin: 0; +} + +html table.gsc-search-box tr { + display: flex; +} + +html table.gsc-search-box .gsib_a { + padding: 0; + margin-right: 10px; +} + +html table.gsc-search-box .gsib_b { + margin-right: 10px; +} + +td.gsc-input { + order: 2; + flex: 1; +} + +html .gsc-search-box-tools .gsc-clear-button { + display: none; +} + +html .gsc-search-box-tools .gsc-search-box .gsc-input { + background: none !important; + text-indent: 0 !important; + padding-right: 0; +} + +html .gsst_a { + padding: 0; + display: flex; + align-items: center; + justify-content: center; +} + +html .gsib_a, +html .gsib_b { + padding-top: 0; + display: flex; + align-items: center; +} + +/* Google Search Results */ + +html .gsc-results-wrapper-overlay { + border-radius: 0; + overflow: auto; + box-shadow: none; + background: var(--background-base); + width: 100%; + height: auto; + top: 4.2em; + left: 0; + bottom: 0; + padding: 0 50px; + transition: all 0.25s linear; + box-sizing: border-box; +} + +html .gsc-wrapper .gsc-webResult.gsc-result, +html .gsc-results .gsc-imageResult { + border: 0; + background: var(--background-base); +} + +.gsc-above-wrapper-area { + position: relative; + width: 100%; + margin-top: 90px; + background: var(--background-base); +} + +html .gsc-results-close-btn { + z-index: 1; + top: 95px; + right: 40px; + position: fixed !important; + background: none; + display: flex; + align-items: center; + justify-content: center; + opacity: .75; +} + +html .gsc-results-close-btn:hover { + opacity: 1; +} + +html .gsc-results-close-btn:before { + font-family: "Font Awesome 5 Pro"; + font-weight: 300; + font-size: 24px; + content: "\f00d"; +} + +html .gsc-results { + padding-top: 20px; +} + +html .gsc-results:before { + margin-top: -130px; + padding: 10px 7px 90px; + content: "Search Results"; + font-size: 32px; + display: block; +} + +html .gsc-modal-background-image { + display: none; +} + +html .gsc-overflow-hidden { + overflow: visible; +} + +.-overflow-hidden { + overflow: hidden; +} + +.gs-webResult { + display: flex; + flex-direction: column; +} + +.gsc-url-top { + order: 2; +} + +html .gs-webResult.gs-result a.gs-title:link, +html .gs-webResult.gs-result a.gs-title:link b, +html .gs-imageResult a.gs-title:link, +html .gs-imageResult a.gs-title:link b, +html .gsc-results .gsc-cursor-box .gsc-cursor-page { + color: var(--color-accent); +} + +html .gs-webResult div.gs-visibleUrl { + color: var(--color-accent); + opacity: .7; +} + +html .gsc-result .gs-title { + overflow: visible; +} + +/* Responsiveness */ + +@media only screen and (max-width: 1800px) { + body.-landing { + flex: 1 0 90%; + width: 90%; + } +} + +@media only screen and (min-width: 1450px) { + #feedback-buttons-container, + #feedback-submitted-container { + padding-right: 0; + } +} + +@media only screen and (max-width: 1280px) { + html { + font-size: 14px; + } + + body { + flex: 1 0 90%; + width: 90%; + } + + .ns-navigation, + .ns-tip-container, + .ns-footer { + width: auto; + margin-left: unset; + } + + #feedback-section.-detached { + flex: 1 0 90%; + width: 90%; + } + + .side-nav__burger-input, + .side-nav__burger-menu { + display: inline-flex; + } + + html body .side-nav__tree { + width: 1em; + max-height: 0; + margin-top: -2.86em; + padding: 2.86em 1.72em 0 0; + } + + .side-nav__burger-input:checked ~ .side-nav__tree { + width: 16.43em; + max-height: 2500px; + } + + .side-nav__burger-input:checked + .side-nav__burger-menu:before { + transform: rotate(45deg); + } + + .flavor-header__search > div { + width: auto; + } + + .flavor-header__navigation { + margin-left: 10px; + } + + .ns-side-nav { + margin: -.71em 1.43em 0 -1.43em; + } + + .right-nav__label { + display: inline-flex; + position: absolute; + left: 0; + top: .94em; + z-index: 1; + } + + .right-nav__container { + position: fixed; + padding-right: 1.25em; + top: 4.13em; + right: -12.5em; + bottom: 0; + margin: 0; + z-index: 1; + } + + .right-nav__tree > div { + margin-top: 1.38em; + } + + .right-nav__tree { + overflow: hidden; + overflow-y: auto; + margin-top: 0; + width: 13.75em; + height: 100%; + background: var(--background-base); + transition: box-shadow .2s ease-out; + } + + .right-nav__sizer { + transition: width .2s ease-out; + width: 13.75em; + } + + .right-nav__tree > div, + .right-nav__tree > ul { + margin-left: 4.67em; + } + + .right-nav__input:checked ~ .right-nav__sizer { + width: 29em; + } + + .right-nav__input:checked ~ .right-nav__tree { + width: 17.8em; + box-shadow: -3px 0 6px var(--transparent-dark-15); + } + + .right-nav__input:checked ~ .right-nav__tree > ul { + margin-left: 1.33em; + } + + .right-nav__input:checked ~ .right-nav__tree > div { + margin-left: 2.5em; + } + + .right-nav__tree .ns-state-selected:before { + left: -2.87em; + } + + #feedback-buttons-container, + #feedback-submitted-container { + padding-right: 0; + } +} + +@media only screen and (max-width: 1100px) { + html { + font-size: 13px; + } + + .footer__form { + flex-direction: column; + } + + .footer__form > div > h5 { + margin: .6em 0 1.2em; + } + + .footer__social-links { + justify-content: space-between; + margin-right: 0; + } +} + + +@media only screen and (max-width: 1020px) { + html { + font-size: 13px; + } + + .ns-card, + .footer__links > div, + .start-links__category { + flex: auto; + } + + .navigation__logo { + margin-left: calc(-5.5% + 75px); + } + + .right-nav__container { + display: none; + } + + .navigation__burger-menu { + display: inline-block; + } + + #page-inner-content { + flex-direction: column; + } + + .ns-page .ns-side-nav .side-nav__tree { + margin-top: -2.6em; + padding: 2.6em 1.72em 0 0; + width: calc(100% - 1.66em); + border-radius: 4px; + } + + .side-nav__burger-input:checked + .side-nav__burger-menu { + border-radius: 4px; + } + + .side-nav__tree > .k-group:first-child { + margin-top: 1em; + } + + .side-nav__burger-input + .side-nav__burger-menu:before { + transform: rotate(90deg); + } + + .side-nav__burger-input:checked + .side-nav__burger-menu:before { + transform: rotate(270deg); + } + + .side-nav__burger-menu { + box-shadow: none; + width: 100%; + font-size: 1.2em; + font-family: inherit; + padding: 0 .8em; + box-sizing: border-box; + justify-content: space-between; + border-bottom: 1px solid var(--border-light-blue); + } + + .side-nav__burger-menu:before { + justify-self: flex-end; + font-family: 'Font Awesome 5 Pro'; + font-weight: 300; + order: 1; + } + + .side-nav__burger-menu:after { + content: "Table of Contents"; + font-family: inherit; + order: 0; + } + + html .k-treeview .k-group .k-group .k-in { + padding-top: .5em; + padding-bottom: .5em; + } + + .ns-side-nav { + margin: -.71em -1.43em 0; + } + + .flavor-header__navigation { + width: 15em; + margin-left: 0; + } + + .flavor-header__search { + padding-left: 0; + } + + html .gsc-control-cse { + box-shadow: none; + border: 1px solid var(--border-light-blue); + } + + .footer__links > div { + width: 50%; + } + + .footer__last-row { + margin-top: 1em; + } + + .footer__last-row, + .footer__contribute { + height: 100px; + flex-direction: column; + text-align: center; + align-content: space-between; + } + + .footer__contribute > p { + margin-bottom: 1em; + } + + .footer__last-row > .navigation__logo { + height: 2em; + width: 14em; + margin-top: -2em; + background-position-y: .2em; + background-size: auto 1.5em; + } + + .footer__copyright { + height: 3.8em; + text-align: right; + } + + .close-banner-button { + right: -4vw; + } + + .ns-start-links #___gcse_0 { + width: 94%; + } +} + +@media only screen and (max-width: 650px) { + .footer__social-links { + flex-flow: wrap; + } + + .footer__social-links > * { + margin-bottom: 5px; + } + + .footer__copyright { + height: 3.8em; + text-align: right; + } + + .footer__copyright > span:last-child { + display: flex; + flex-direction: column; + } +} + +@media only screen and (max-width: 500px) { + html .navigation__right .k-menu .-github { + display: none; + } + + .footer__last-row > .navigation__logo { + height: 4em; + width: 6.5em; + margin-top: 0; + background-position: 0 2em; + background-size: auto 1.5em; + display: block; + text-align: left; + } +} + +@media only screen and (max-width: 420px) { + .navigation__logo { + width: 2.8em; + height: 2.8em; + background-size: cover; + background-position-x: 0; + align-self: center; + } + + .footer__copyright > span:first-child { + display: flex; + flex-direction: column; + } +} + +.optanon-alert-box-wrapper{ + width: auto!important; +} diff --git a/_assets/stylesheets/variables.css b/_assets/stylesheets/variables.css new file mode 100644 index 000000000..4c486b029 --- /dev/null +++ b/_assets/stylesheets/variables.css @@ -0,0 +1,65 @@ +/*noinspection CssInvalidFunction*/ +:root { + --light: 255,255,255; + --dark: 0,39,52; + + --hs-neutral: 197, 11%; + --hs-accent: 229, 68%; + --hs-accent-light: 231, 99%; + + --gray: 0,0%; + + --color-light: rgb(var(--light)); + --color-dark: rgb(var(--dark)); + + --color-secondary: #455B66; + --color-green: #11CC71; + --color-success: #20C082; + --color-source-green: #5DB240; + --color-error: red; + --color-menu-secondary: #81ADFE; + + --color-accent: hsl(var(--hs-accent), 49%); + --color-accent-light: hsl(var(--hs-accent-light), 62%); + --color-purple: hsl(var(--hs-accent), 96%); + + --border-gray: var(--transparent-dark-40); + --border-light-blue: #DEE8F7; + + --color-progress-green: #5CE500; + + --background-base: #F8FAFD; + --background-special: #F2F7FF; + + --background-light: var(--color-light); + --background-accent: var(--color-accent); + --background-button: #5783FF; + --background-button-hover: #3B6DFD; + --background-success: var(--color-success); + --background-success-hover: #00A082; + --background-footer-blue: #092B66; + --background-footer-gray: #ECEBE9; + --background-dark: var(--color-dark); + --background-secondary: var(--color-secondary); + --background-purple: var(--color-purple); + --background-green: var(--color-green); + --background-tip: #FFEF64; + + --transparent-dark-02: rgba(var(--dark), .02); + --transparent-dark-05: rgba(var(--dark), .05); + --transparent-dark-10: rgba(var(--dark), .1); + --transparent-dark-15: rgba(var(--dark), .15); + --transparent-dark-20: rgba(var(--dark), .2); + --transparent-dark-40: rgba(var(--dark), .4); + --transparent-dark-50: rgba(var(--dark), .5); + --transparent-dark-60: rgba(var(--dark), .6); + --transparent-dark-70: rgba(var(--dark), .7); + --transparent-dark-90: rgba(var(--dark), .9); + + --transparent-white-10: rgba(var(--light), .1); + --transparent-white-20: rgba(var(--light), .2); + --transparent-white-50: rgba(var(--light), .5); + --transparent-white-70: rgba(var(--light), .7); + --transparent-white-80: rgba(var(--light), .8); + --transparent-white-90: rgba(var(--light), .9); +} diff --git a/_config.yml b/_config.yml new file mode 100644 index 000000000..8f0dd378f --- /dev/null +++ b/_config.yml @@ -0,0 +1,208 @@ +## The base url of the header links +headerbaseurl: //www.nativescript.org +nscookbookurl: "/cookbook/" +source: ./Content +# Release date in the format of: YYYY-MM-DD +release_date: "2016-11-16" +navigation: +## List your directory names and order here, like this: + start: + position: 10 + title: "Get Started" + expanded: true + core-concepts: + position: 20 + title: "CORE CONCEPTS" + "core-concepts/android-runtime": + position: 200 + title: "Android Runtime" + "core-concepts/android-runtime/getting-started": + position: 10 + title: "Getting started" + "core-concepts/android-runtime/metadata": + position: 20 + title: "Metadata" + "core-concepts/android-runtime/marshalling": + position: 30 + title: "Marshalling" + "core-concepts/android-runtime/generator": + position: 40 + title: "Generator" + "core-concepts/android-runtime/plugins": + position: 50 + title: "Plugins" + "core-concepts/android-runtime/how-to": + position: 60 + title: "How-To" + "core-concepts/android-runtime/debug": + position: 70 + title: "Debug" + "core-concepts/android-runtime/advanced-topics": + position: 80 + title: "Advanced topics" + "core-concepts/ios-runtime": + position: 300 + title: "iOS Runtime" + "core-concepts/ios-runtime/types": + position: 90 + title: "Types" + "core-concepts/ios-runtime/how-to": + position: 100 + title: "How-To" + integration-with-existing-ios-and-android-apps: + position: 30 + title: "INTEGRATING EXISTING NATIVE APPS" + best-practices: + position: 40 + title: "BEST PRACTICES" + ui: + position: 20 + title: "USER INTERFACE" + expanded: false + "ui/layouts": + position: 10 + title: "Layouts" + expanded: false + "ui/ns-framework-modules": + position: 30 + title: "Framework modules" + expanded: false + "ui/components": + position: 20 + title: "Components" + expanded: false + "ui/ng-framework-modules": + position: 30 + title: "Framework modules" + expanded: false + code-sharing: + position: 45 + title: "CODE SHARING" + tooling: + position: 50 + title: "TOOLING" + expanded: false + "tooling/publishing": + position: 100 + title: "Publishing" + "tooling/testing": + position: 150 + title: "Testing" + "tooling/testing/end-to-end-testing": + position: 100 + title: "End To End Testing" + "tooling/debugging": + position: 200 + title: "Debugging" + "tooling/docs-cli": + position: 300 + title: "Command-line interface" + hardware: + position: 60 + title: "HARDWARE АCCESS" + ng-hardware-access: + position: 60 + title: "HARDWARE АCCESS" + plugins: + position: 70 + title: "PLUGINS DEVELOPMENT" + releases: + position: 80 + title: "RELEASES" + app-templates: + position: 90 + title: "App Templates" + performance-optimizations: + position: 100 + title: "Performance optimizations" + ns-framework-modules: + position: 110 + title: "Framework modules" + ng-framework-modules: + position: 110 + title: "Framework modules" + guides: + position: 120 + title: "Guides" + "guides/integration-with-existing-ios-and-android-apps": + position: 100 + title: "Integration with existing iOS and Android apps" +## The product name +productName: "NativeScript" + +## Improve This Article button-related: +improveThis: + mapOfBaseUrls: + 0: + matchPattern: '^/cookbook/.*' + 1: + matchPattern: '^/code-samples/.*' + 2: + matchPattern: '^/tooling/docs-cli/.*' + trimRootPath: "/tooling/docs-cli" + baseUrl: "https://github.com/NativeScript/nativescript-cli/tree/master/docs/man_pages" + 3: + matchPattern: '^/ui/ng-components/(icon-fonts|modal-view-ng).*' + trimRootPath: "/ui/ng-components/" + pathUpdatePattern: ".md$" + baseUrl: "https://github.com/NativeScript/nativescript-sdk-examples-ng/tree/master/app/ng-ui-category/" + 4: + matchPattern: '^/ui/ng-components/.*' + trimRootPath: "/ui/ng-components/" + pathUpdatePattern: ".md$" + baseUrl: "https://github.com/NativeScript/nativescript-sdk-examples-ng/tree/master/app/ng-ui-widgets-category/" + 5: + matchPattern: '^/ui/components/(icon-fonts|modal-view).*' + trimRootPath: "/ui/components/" + pathUpdatePattern: ".md$" + baseUrl: "https://github.com/NativeScript/nativescript-sdk-examples-js/tree/master/app/ns-ui-category" + 6: + matchPattern: '^/ui/components/.*' + trimRootPath: "/ui/components/" + pathUpdatePattern: ".md$" + baseUrl: "https://github.com/NativeScript/nativescript-sdk-examples-js/tree/master/app/ns-ui-widgets-category/" + 7: + matchPattern: '.*' + baseUrl: "https://github.com/NativeScript/docs/blob/master/docs/" + +## Current flavor +flavor: + "NativeScript & Angular": + matchPattern: '^/angular/.*' + "NativeScript & Vue.JS": + matchPattern: '^/vuejs/.*' + "API Reference": + matchPattern: '^/api-reference/.*' + +## Assign layout and category per different paths +defaults: +- + scope: + path: "" + values: + layout: "page" + category: "default" + +# Aliases available in the markdown template. The below will expand {{site.foo}} to Bar in the output +# "foo": "Bar" +"current-version": "2.0.0" +"ns": "NativeScript" +"ns-cli": "NativeScript CLI" + +# Assets pipeline configuration +assets: + cachebust: soft + js_compressor: uglifier + +## Do not edit below this line +safe: false +markdown: MarkdownProcessor +kramdown: + toc_levels: 2..3 + smart_quotes: ["quot", "quot", "quot", "quot"] + input: GFM + +gems: + - jekyll-unsanitize +# Feedback Form Google Sheet ID +ff-sheet-id: 1Njk-CD9m_mKw_jSRBV2p6quwEOAKRZnUPJgeUrA1ZFA diff --git a/_config_angular.yml b/_config_angular.yml new file mode 100644 index 000000000..dcef0d064 --- /dev/null +++ b/_config_angular.yml @@ -0,0 +1,67 @@ +# The public documentation URL, used for sitemap.xml +url: "https://docs.nativescript.org/angular" +destination: ./angular + +## The application virtual path +baseurl: "/angular" + +## The highlighting in the header +nsselected: "" +ngselected: "selected" + +# Exclude files which should not be in the output +exclude: [Gemfile,Gemfile.lock,README.md,node_modules,dist, cookbook, ns-ui-widgets, ns-framework-modules, hardware, ui/components] + +# The google services configuration +google_tag_manager: GTM-W58JDD +google_custom_search: '001595215763381649090:asl7kpbijam' + +flavour: "angular" + +navigation: +## List your directory names and order here, like this: + "ui/ng-components": + position: 20 + title: "Components" + expanded: false + code-samples: + position: 81 + title: "CODE SAMPLES" + "ui/ng-components/ng-SideDrawer": + position: 3000 + title: "RadSideDrawer" + "ui/ng-components/ng-RadListView": + position: 4000 + title: "RadListView" + "ui/ng-components/ng-Calendar": + position: 5000 + title: "RadCalendar" + "ui/ng-components/ng-Chart": + position: 6000 + title: "RadChart" + "ui/ng-components/ng-Chart/Series": + position: 3 + "ui/ng-components/ng-Chart/Series/Types": + position: 2 + "ui/ng-components/ng-Chart/Axes": + position: 4 + "ui/ng-components/ng-Chart/Axes/Types": + position: 2 + "ui/ng-components/ng-AutoCompleteTextView": + position: 7000 + title: "RadAutoCompleteTextView" + "ui/ng-components/ng-DataForm": + position: 8000 + title: "RadDataForm" + "ui/ng-components/ng-DataForm/GettingStarted": + position: 20 + title: "Basics" + "ui/ng-components/ng-DataForm/Editors": + position: 30 + "ui/ng-components/ng-DataForm/Validation": + position: 40 + "ui/ng-components/ng-DataForm/Groups": + position: 50 + "ui/ng-components/ng-Gauge": + position: 9000 + title: "RadGauge" \ No newline at end of file diff --git a/_config_nativescript.yml b/_config_nativescript.yml new file mode 100644 index 000000000..46ad11906 --- /dev/null +++ b/_config_nativescript.yml @@ -0,0 +1,61 @@ +# The public documentation URL, used for sitemap.xml +url: "https://docs.nativescript.org" +destination: ./nativescript + +## The application virtual path +baseurl: "" +# Exclude files which should not be in the output +exclude: [Gemfile,Gemfile.lock,README.md,node_modules,dist, ng-framework-modules, ns-ui-widgets, ng-hardware-access, ui/ng-components] +## The highlighting in the header +nsselected: "selected" +ngselected: "" + + +flavour: "nativescript" +navigation: +## List your directory names and order here, like this: + "ui/components": + position: 20 + title: "Components" + expanded: false + "ui/components/SideDrawer": + position: 3000 + title: "RadSideDrawer" + "ui/components/RadListView": + position: 4000 + title: "RadListView" + "ui/components/Calendar": + position: 5000 + title: "RadCalendar" + "ui/components/Chart": + position: 6000 + title: "RadChart" + "ui/components/Chart/Series": + position: 3 + "ui/components/Chart/Series/Types": + position: 2 + "ui/components/Chart/Axes": + position: 4 + "ui/components/Chart/Axes/Types": + position: 2 + "ui/components/AutoCompleteTextView": + position: 7000 + title: "RadAutoCompleteTextView" + "ui/components/DataForm": + position: 8000 + title: "RadDataForm" + "ui/components/DataForm/GettingStarted": + position: 20 + title: "Basics" + "ui/components/DataForm/Editors": + position: 30 + "ui/components/DataForm/Validation": + position: 40 + "ui/components/DataForm/Groups": + position: 50 + "ui/components/Gauge": + position: 9000 + title: "RadGauge" +# The google services configuration +google_tag_manager: GTM-W58JDD +google_custom_search: '001595215763381649090:asl7kpbijam' diff --git a/_config_vuejs.yml b/_config_vuejs.yml new file mode 100644 index 000000000..9a184771a --- /dev/null +++ b/_config_vuejs.yml @@ -0,0 +1,103 @@ +headerbaseurl: //www.nativescript.org +# The public documentation URL, used for sitemap.xml +url: "https://docs.nativescript.org/vuejs" +destination: ./vuejs +## The application virtual path +baseurl: "/vuejs" +# Exclude files which should not be in the output +exclude: [Gemfile,Gemfile.lock,README.md,node_modules,dist, code-samples] +## The highlighting in the header +vjsselected: "selected" + +flavour: "vuejs" + +# The google services configuration +google_tag_manager: GTM-W58JDD +google_custom_search: '001595215763381649090:asl7kpbijam' + +## The base url of the header links +headerbaseurl: //www.nativescript.org +nscookbookurl: "/vuejs/" +source: ./ +# Release date in the format of: YYYY-MM-DD +release_date: "2016-11-16" + + +## The product name +productName: "NativeScript VueJS" + +## Assign layout and category per different paths +defaults: +- + scope: + path: "" + values: + layout: "page" + category: "default" + +# Aliases available in the markdown template. The below will expand {{site.foo}} to Bar in the output +# "foo": "Bar" +"current-version": "2.0.0" + +# Assets pipeline configuration +assets: + cachebust: soft + js_compressor: uglifier + +## Improve This Article button-related: +improveThis: + mapOfBaseUrls: + 0: + matchPattern: '.*' + baseUrl: "https://github.com/NativeScript/docs/blob/master/vuejs-docs" + +flavor: + "NativeScript & Vue.JS": + matchPattern: '^/.*' + +## Do not edit below this line +safe: false +highlighter: true +markdown: MarkdownProcessor +kramdown: + toc_levels: 2..3 + smart_quotes: ["quot", "quot", "quot", "quot"] + input: GFM +navigation: + "ns-ui": + position: 30 + title: "NativeScript UI" + expanded: true + "ns-ui/SideDrawer": + position: 10 + title: "RadSideDrawer" + "ns-ui/ListView": + position: 20 + title: "RadListView" + "ns-ui/Calendar": + position: 30 + title: "RadCalendar" + "ns-ui/Chart": + position: 40 + title: "RadChart" + "ns-ui/Chart/Series": + position: 3 + "ns-ui/Chart/Series/Types": + position: 2 + "ns-ui/Chart/Axes": + position: 4 + "ns-ui/Chart/Axes/Types": + position: 2 + "ns-ui/AutoCompleteTextView": + position: 50 + title: "RadAutoCompleteTextView" + "ns-ui/DataForm": + position: 60 + title: "RadDataForm" + "ns-ui/Gauge": + position: 70 + title: "RadGauge" +gems: + - jekyll-unsanitize +# Feedback Form Google Sheet ID +ff-sheet-id: 1Njk-CD9m_mKw_jSRBV2p6quwEOAKRZnUPJgeUrA1ZFA diff --git a/_includes/feedback-form.html b/_includes/feedback-form.html new file mode 100644 index 000000000..66eddb2cb --- /dev/null +++ b/_includes/feedback-form.html @@ -0,0 +1,116 @@ +
            +
            + {% javascript feedback-form %} + + +
            +
            +

            Tell us how we can improve this article

            + +
            +
            + +
            + + +
            + + +
            + + +
            + + +
            + + +
            + + +
            + + +
            + + +
            + + +
            + + + +
            + + +
            +
            +
            + +
            +
            +
            +
            diff --git a/_includes/footer.html b/_includes/footer.html new file mode 100644 index 000000000..90cd52854 --- /dev/null +++ b/_includes/footer.html @@ -0,0 +1,184 @@ + + + diff --git a/_includes/header.html b/_includes/header.html new file mode 100644 index 000000000..74dfb075e --- /dev/null +++ b/_includes/header.html @@ -0,0 +1,171 @@ +
            + + + + + + + diff --git a/_includes/improvethis.html b/_includes/improvethis.html new file mode 100644 index 000000000..64632fb06 --- /dev/null +++ b/_includes/improvethis.html @@ -0,0 +1,4 @@ + diff --git a/_includes/search.html b/_includes/search.html new file mode 100644 index 000000000..5a4b63a08 --- /dev/null +++ b/_includes/search.html @@ -0,0 +1,22 @@ + + + diff --git a/_layouts/index.html b/_layouts/index.html new file mode 100644 index 000000000..864400e27 --- /dev/null +++ b/_layouts/index.html @@ -0,0 +1,43 @@ + + + + + + + + {% if page.titletag %}{{page.titletag}}{% else %}{{page.title}}{% endif %} - NativeScript Docs + + + {% if page.description %}{% endif %} + {% if page.tags %}{% endif %} + + + {% stylesheet fontawesome-all %} + {% stylesheet variables %} + {% stylesheet styles %} + + + + + + {% javascript prism %} + {% javascript app %} + + +
            + {% include header.html %} +
            + +
            + +

            {{page.flavor}}

            +
            + +
            + + {{ content }} + + + diff --git a/_layouts/landing.html b/_layouts/landing.html new file mode 100644 index 000000000..16ecf7886 --- /dev/null +++ b/_layouts/landing.html @@ -0,0 +1,161 @@ + + + + + + + {{page.title}} + + + {% if page.description %}{% endif %} + {% if page.tags %}{% endif %} + + + {% stylesheet fontawesome-all %} + {% stylesheet variables %} + {% stylesheet styles %} + + + + + + {% javascript prism %} + {% javascript app %} + + +
            + {% include header.html %} +
            + + + + +
            +
            +
            +
            Not finding the help you need? Learn more about our professional support offerings.
            + Contact us +
            +
            + {% include footer.html %} +
            + + + diff --git a/_layouts/page.html b/_layouts/page.html new file mode 100644 index 000000000..cc3ee9c15 --- /dev/null +++ b/_layouts/page.html @@ -0,0 +1,70 @@ +--- +layout: index +--- +
            +
            +
            +
            + + +
            + +
            + +
            +
            + {% breadcrumb %} +
            +
            + {{ content }} +
            + {% include improvethis.html %} +
            +
            +
            +
            + +
            + {% if site.ff-sheet-id %}{% include feedback-form.html %}{% endif %} + {% include footer.html %} +
            diff --git a/_plugins/assets.rb b/_plugins/assets.rb new file mode 100644 index 000000000..32cfb7395 --- /dev/null +++ b/_plugins/assets.rb @@ -0,0 +1,14 @@ +require 'jekyll-assets' + +module Jekyll + module AssetsPlugin + class AssetPath + # Monkey patch to_s so it uses the baseurl option istead of assets.baseurl thus avoiding duplication + # Original implementation: https://github.com/ixti/jekyll-assets/blob/master/lib/jekyll/assets_plugin/asset_path.rb#L34 + + def to_s + "#{@asset.site.baseurl}/assets/#{path}#{query}#{anchor}" + end + end + end +end diff --git a/_plugins/breadcrumb.rb b/_plugins/breadcrumb.rb new file mode 100644 index 000000000..c52db0d65 --- /dev/null +++ b/_plugins/breadcrumb.rb @@ -0,0 +1,51 @@ +class BreadCrumbTag < Liquid::Tag + def render(context) + site = context.registers[:site] + + navigation = site.config['navigation'] + + url = context.environments.first['page']['url'].sub('.html', '') + + segments = url.split('/') + + html = '
              ' + + segments.each_with_index do |segment, index| + next if index == 0 + + item = {} + + if index == segments.size - 1 + text = context.environments.first['page']['title'] || segment + + html += "
            • #{text}
            • " + else + path = segments.slice(1,index).join('/'); + mapping = navigation[path] || {} + + pages = site.pages.find_all do |p| + p.dir.sub('/', '') == path + end + + pages.sort_by! {|a| [a.data['position'] || 1000000, a.data['title']]} + + text = mapping['title'] || segment; + + if pages.first + url = pages.first.url.sub('.html', '').sub('/', '') + else + url = path + end + + html += "
            • #{text}
            • " + end + + end + + html += '
            ' + + html + end +end + +Liquid::Template.register_tag('breadcrumb', BreadCrumbTag) diff --git a/_plugins/environment.rb b/_plugins/environment.rb new file mode 100644 index 000000000..825f417d8 --- /dev/null +++ b/_plugins/environment.rb @@ -0,0 +1,29 @@ +class EnvironmentTag < Liquid::Block + def current_environment + (ENV["JEKYLL_ENV"] || "").strip + end + + def render(context) + site = context.registers[:site] + if current_environment == expected_environment + super + else + "" + end + end +end + +class NativeScriptTag < EnvironmentTag + def expected_environment + "nativescript" + end +end + +class AngularTag < EnvironmentTag + def expected_environment + "angular" + end +end + +Liquid::Template.register_tag("nativescript", NativeScriptTag) +Liquid::Template.register_tag("angular", AngularTag) diff --git a/_plugins/flavor_generator.rb b/_plugins/flavor_generator.rb new file mode 100644 index 000000000..1b6883b05 --- /dev/null +++ b/_plugins/flavor_generator.rb @@ -0,0 +1,36 @@ +module Jekyll + class FlavorGenerator < Generator + def generate(site) + if @site.nil? + @site = site + end + + site.pages.each do |page| + matchFlavor(page) + end + end + + def matchFlavor(page) + if @urlMap.nil? + @urlMap = @site.config['flavor'] + end + + @urlMap.each do |idx, entry| + rootedPagePath = "/#{page.path}" + + if (Regexp.new(entry["matchPattern"]) =~ rootedPagePath) + page.data['flavor'] = idx + break + end + end + + if @site.config['flavour'] == 'angular' + page.data['flavor'] = 'NativeScript Angular' + end + + if (page.data['flavor'].nil?) + page.data['flavor'] = 'NativeScript Core' + end + end + end +end diff --git a/_plugins/improvethis_generator.rb b/_plugins/improvethis_generator.rb new file mode 100644 index 000000000..9fecf32ca --- /dev/null +++ b/_plugins/improvethis_generator.rb @@ -0,0 +1,50 @@ +module Jekyll + class ImproveThisGenerator < Generator + def generate(site) + if @site.nil? + @site = site + end + + site.pages.each do |page| + pageImproveThisUrl = getPageImproveThisUrl(page) + regexexp = /(?i)(?:ns-ui-widgets|ng-ui-widgets|ns-framework-modules|ng-framework-modules|ns-hardware-access|ng-hardware-access|common-screens)/; + if pageImproveThisUrl.nil? || pageImproveThisUrl.length == 0 || (!(page.path.match(regexexp).nil?)) + page.data['improvethisurl'] = '' + page.data['improvethisvisibilityclass'] = 'hide' + else + page.data['improvethisurl'] = pageImproveThisUrl + page.data['improvethisvisibilityclass'] = '' + end + end + end + + def getPageImproveThisUrl(page) + if @urlMap.nil? + @urlMap = @site.config['improveThis']['mapOfBaseUrls'] + end + + resultUrl = "" + @urlMap.each do |idx, entry| + rootedPagePath = "/#{page.path}" + + if (Regexp.new(entry["matchPattern"]) =~ rootedPagePath) + pagePath = rootedPagePath + if entry["pathUpdatePattern"] + updater = Regexp.new(entry["pathUpdatePattern"]) + pagePath = pagePath.gsub(updater, "") + end + if entry["baseUrl"] + if entry["trimRootPath"] + pagePath.sub!(entry["trimRootPath"], "") + end + # Ensure the baseUrl ends with a slash: + baseUrl = File.join(entry["baseUrl"], "") + resultUrl = "#{baseUrl}#{pagePath}" + end + break + end + end + resultUrl + end + end +end diff --git a/_plugins/jekyll_site_generator.rb b/_plugins/jekyll_site_generator.rb new file mode 100644 index 000000000..5195ba1ea --- /dev/null +++ b/_plugins/jekyll_site_generator.rb @@ -0,0 +1,16 @@ +module Jekyll + class JekyllSiteGenerator < Generator + def initialize(config) + @config = config + end + + def self.site + @@site + end + + def generate(site) + #HACK: store the site in a static field, so that we can access it in the markdown include filter during the render stage. + @@site = site unless site.nil? + end + end +end diff --git a/_plugins/lastMod_generator.rb b/_plugins/lastMod_generator.rb new file mode 100644 index 000000000..acf1dd319 --- /dev/null +++ b/_plugins/lastMod_generator.rb @@ -0,0 +1,39 @@ +class TimeStampTag < Liquid::Block + def initialize(tag_name, markup, tokens) + @text = markup + super + end + + def get_config(var) + if @config.nil? + @config = Jekyll.configuration({}) + end + @config["source"] + end + + def get_source() + if @source.nil? + @source = get_config "source" + end + @source + end + + def render(context) + contents = super + content = Liquid::Template.parse(contents).render context + content = URI.unescape(content) + dir = File.dirname(content) + filename = File.basename(content) + + filePath = File.join(get_source, content) + + if !Dir.exist?(File.join(get_source, dir)) || !File.exist?(filePath) + "#{get_config 'release_date'}" + end + + # aim for YYYY-MM-DD format https://www.google.com/sitemaps/protocol.html#lastmoddef + `cd "#{get_source}/#{dir}" && git log -1 --format=%cd --date=short "#{filename}"`.strip + end +end + +Liquid::Template.register_tag('timestamp', TimeStampTag) diff --git a/_plugins/markdown_processor.rb b/_plugins/markdown_processor.rb new file mode 100644 index 000000000..ad7398ebb --- /dev/null +++ b/_plugins/markdown_processor.rb @@ -0,0 +1,176 @@ +module Jekyll + + require 'html/pipeline' + require "liquid" + + class IncludeFilter < HTML::Pipeline::TextFilter + def initialize(text, context = nil, result = nil) + super text, context, result + @site = Jekyll::JekyllSiteGenerator.site + end + + def call + new_text = @text.gsub(/!!include\(([^\)]+)\)/) do + file_path = $1 + render_include(file_path) + end + + def render_include(file_path) + template_content = File.read(file_path) + + page = Page.new(@site, @site.source, '', file_path) + page.content = template_content + page.render(Hash.new, @site.site_payload) + + page.output + end + + new_text + end + end + + class RootRelativeFilter < HTML::Pipeline::Filter + + def call + doc.search('a').each do |a| + next if a['href'].nil? + + href = a['href'].strip + + if href.start_with? '/' + a['href'] = context[:baseurl] + href + end + + # Transform article .md links to .html + if /\.md(#.*?)?$/.match(href) + # Leave external(absolute) links alone + unless /^(https?:)?\/\//.match(href) + a['href'] = href.gsub(/\.md(#.*?)?$/, ".html#{$1}") + end + end + end + + doc.search('img').each do |img| + next if img['src'].nil? + + src = img['src'].strip + + if src.start_with? '/' + img['src'] = context[:baseurl] + src + end + end + + doc + end + + end + + class NSCookbookFilter < HTML::Pipeline::Filter + + def call + doc.search('a').each do |a| + next if a['href'].nil? + + href = a['href'].strip + + if href.include? "NS_COOKBOOK" + a['href'] = href.sub(/NS_COOKBOOK\/?/, context[:nscookbookurl]) + end + end + + doc + end + + end + + class ApiHeaderIdFilter < HTML::Pipeline::Filter + + def call + + doc.css('h2').each do |node| + text = node.text + + next unless text =~ /^Configuration|Events|Properties|Methods|Class Methods|Fields$/ + + prefix = text.downcase.gsub(' ', '-') + + node = node.next_element + + until node.nil? + break if node.name == 'h2' + + if node.name == 'h3' + id = node.text + id.gsub!(/ .*/, '') + id.gsub!(/`[^`]*`/, '') + id.gsub!(/\\/,'') + id.gsub!(/\*[^*]*\*/, '') + node['id'] = "#{prefix}-#{id}" + end + + node = node.next_element + end + + end + + doc + end + + end + + # based on https://github.com/jch/html-pipeline/blob/master/lib/html/pipeline/toc_filter.rb + class HeaderLinkFilter < HTML::Pipeline::Filter + + @@punctuation_regexp = RUBY_VERSION > "1.9" ? /[^\p{Word}\- ]/u : /[^\w\- ]/ + + def call + + doc.css('h1, h2, h3').each do |node| + + id = node['id'] + + unless id + id = node.text.downcase + id.gsub!(@@punctuation_regexp, '') # remove punctuation + id.gsub!(' ', '-') # replace spaces with dash + end + + node['id'] = id + + a = Nokogiri::XML::Node.new('a', doc) + a['href'] = "##{id}" + a.children = node.children + node.add_child a + end + + doc + end + end + + class Converters::Markdown::MarkdownProcessor + def initialize(config) + @config = config + + context = { + :gfm => false, + :baseurl => @config['baseurl'], + :nscookbookurl => @config['nscookbookurl'] + } + + @pipeline = HTML::Pipeline.new [ + IncludeFilter, + HTML::Pipeline::MarkdownFilter, + RootRelativeFilter, + NSCookbookFilter, + ApiHeaderIdFilter, + HeaderLinkFilter + ], context + + end + + def convert(content) + @pipeline.call(content)[:output].to_s + end + end + +end diff --git a/_plugins/navigation_generator.rb b/_plugins/navigation_generator.rb new file mode 100644 index 000000000..3a4ab55c5 --- /dev/null +++ b/_plugins/navigation_generator.rb @@ -0,0 +1,92 @@ +require "json" + +module Jekyll + + class NavigationGenerator < Generator + def initialize(config) + @navigation = Hash[(config['navigation'] || {}).map { |key, value| [/^#{key.gsub('*', '.*?')}$/, value] }] + end + + def current_environment + (ENV['JEKYLL_ENV'] || '').strip + end + + def other_environment(page) + page_environment = page['environment'] + page_environment and page_environment != current_environment + end + + def categories(site) + categories = {} + + site.pages.each do |page| + page_category = page.data['category'] + + next if other_environment(page) + next if page.data['publish'] == false + next unless page_category + + category_items = categories[page_category] + + unless category_items + categories[page_category] = category_items = [] + end + + url = page.url.sub('/', '') + + segments = url.split('/') + + segments.each_with_index do |segment, index| + item = category_items.find { |n| n['path'] == segment } + + unless item + item = { 'path' => segment } + + if index == segments.size - 1 + item['position'] = page.data['position'] if page.data['position'] + item['text'] = page.data['title'] + else + path = segments[0..index].join('/') + navigation_entry = @navigation.find { |key, value| path =~ key } + mapping = navigation_entry ? navigation_entry[1] : {} + item['text'] = mapping['title'] || segment + item['items'] = [] + item['position'] = mapping['position'] if mapping.has_key?('position') + item['expanded'] = mapping['expanded'] if mapping.has_key?('expanded') + end + + category_items << item + end + + category_items = item['items'] + + end + end + + categories.each { |key, value| sort!(value) } + + categories + end + + def generate(site) + categories(site).each do |key, value| + filename = "#{key}.json" + + FileUtils.mkdir_p(site.dest) unless File.exist?(site.dest) + + File.write(File.join(site.dest, filename), value.to_json) + + # Keep the file from being cleaned by Jekyll + site.keep_files << filename + end + end + + def sort!(items) + items.each {|item| sort!(item['items']) if item['items'] } + + # sorty by position, directory or file and then title (ignoring case) + items.sort_by! {|a| [a['position'] || 1000000, a.has_key?('items') ? -1 : 1, a['text'].downcase]} + end + + end +end diff --git a/_plugins/ns_cookbook.rb b/_plugins/ns_cookbook.rb new file mode 100644 index 000000000..200697d1e --- /dev/null +++ b/_plugins/ns_cookbook.rb @@ -0,0 +1,16 @@ +class NSCookbook < Liquid::Tag + def initialize(tag_name, url, tokens) + @url = url + + end + + def render(context) + site = context.registers[:site] + ns_cookbook = site.config['nscookbookurl'] + + # NS_COOKBOOK replaced by NSCookbookFilter + "NS_COOKBOOK/#{@url}" + end +end + +Liquid::Template.register_tag('ns_cookbook', NSCookbook) diff --git a/_plugins/page.rb b/_plugins/page.rb new file mode 100644 index 000000000..d83ee9548 --- /dev/null +++ b/_plugins/page.rb @@ -0,0 +1,21 @@ +module Jekyll + class Page + #https://github.com/jekyll/jekyll/blob/master/lib/jekyll/convertible.rb#L44 + def read_yaml(base, name, opts = {}) + begin + self.content = File.read(Jekyll.sanitized_path(base, name), + merged_file_read_opts(opts)) + if content =~ /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m + self.content = $POSTMATCH + self.data = SafeYAML.load($1.gsub(/{{site\.([^}]+)}}/) {|o| site.config[$1]} ) + end + rescue SyntaxError => e + Jekyll.logger.warn "YAML Exception reading #{File.join(base, name)}: #{e.message}" + rescue Exception => e + Jekyll.logger.warn "Error reading file #{File.join(base, name)}: #{e.message}" + end + + self.data ||= {} + end + end +end diff --git a/_plugins/redirect_generator.rb b/_plugins/redirect_generator.rb new file mode 100644 index 000000000..7bc846275 --- /dev/null +++ b/_plugins/redirect_generator.rb @@ -0,0 +1,81 @@ +module Jekyll + class RedirectGenerator < Generator + def initialize(config) + @config = config + end + + def generate(site) + site.config['redirect_pages'] = redirect_pages(site) + site.config['redirect_directories'] = redirect_directories(site) + + nginx_config = Page.new(site, site.source, '', 'nginx.conf') + nginx_config.content = File.read(File.join(site.source, 'nginx.conf')) + nginx_config.render(Hash.new, site.site_payload) + + FileUtils.mkdir_p(site.dest) unless File.directory?(site.dest) + + File.write(File.join(site.dest, 'nginx.conf'), nginx_config.output) + + site.static_files << nginx_config + end + + def redirect_pages(site) + pages = site.pages.find_all { |p| p.data.has_key?('previous_url') } + + pages.map! do |page| + previous_url = page.data['previous_url'].split(',') + previous_url.map!{ |url| url.strip } + + { 'url' => page.url, 'previous_url' => previous_url.uniq } + end + + pages + end + + def redirect_directories(site) + categories = NavigationGenerator.new(@config).categories(site) + + redirect_directories = [] + + categories.each do |key, category| + category.each do |item| + redirect_directories << redirect('', item) if item.has_key?('items') + end + end + + redirect_directories.flatten + end + + def redirect(path, directory) + result = [] + + page = first_page(directory) + + if path.empty? + path = directory['path'] + else + path = path + '/' + directory['path'] + end + if page + url = page['path'].sub('.html', '') + url = path + '/' + url unless path.empty? + + result << { 'path' => path, 'url' => url } + end + + directory['items'].each do |item| + result << redirect(path, item) if item.has_key?('items') + end + result + end + + def first_page(directory) + page = directory['items'].find { |item| !item.has_key?('items') } + + page = { 'path' => directory['items'].first['path'] } unless page + + page + end + + end +end diff --git a/_plugins/sitemap.xml b/_plugins/sitemap.xml new file mode 100644 index 000000000..fab2ed0f1 --- /dev/null +++ b/_plugins/sitemap.xml @@ -0,0 +1,9 @@ + + + {% capture site_url %}{% if site.url %}{{ site.url }}{% else %}{{ site.github.url }}{% endif %}{% endcapture %} + {% for post in site.html_pages %}{% unless post.sitemap == false %} + + {{ site_url }}{{ post.url | replace:'.html','' }} + + {% endunless %}{% endfor %} + diff --git a/_plugins/sitemap_generator.rb b/_plugins/sitemap_generator.rb new file mode 100644 index 000000000..ddc135dd0 --- /dev/null +++ b/_plugins/sitemap_generator.rb @@ -0,0 +1,13 @@ +require 'jekyll-sitemap' + +module Jekyll + + #override the method from the original Jekyll-sitemap gem so it always uses our template instead of using their built-in template + class JekyllSitemap < Jekyll::Generator + def source_path + File.expand_path('sitemap.xml', File.dirname(__FILE__)) + end + end + JekyllSitemap.new.source_path + +end diff --git a/_plugins/slug.rb b/_plugins/slug.rb new file mode 100644 index 000000000..7980f7b0b --- /dev/null +++ b/_plugins/slug.rb @@ -0,0 +1,18 @@ +class SlugTag < Liquid::Tag + def initialize(tag_name, slug_name, tokens) + @slug_name = slug_name.strip + end + + def render(context) + site = context.registers[:site] + page = site.pages.find {|p| p.data['slug'] == @slug_name} + if page + page.url.sub('.html', '') + else + page_url = context.environments.first["page"]["url"] + Jekyll.logger.warn "Slug:", "No page with slug `#{@slug_name}` in #{page_url}. Consider fixing the slug or use normal link." + end + end +end + +Liquid::Template.register_tag('slug', SlugTag) diff --git a/_plugins/snippet.rb b/_plugins/snippet.rb new file mode 100644 index 000000000..8e1155fdb --- /dev/null +++ b/_plugins/snippet.rb @@ -0,0 +1,57 @@ +require "json" + +class SnippetTag < Liquid::Tag + def initialize(tag_name, id, tokens) + @id = id.strip + end + + def snippet_dir + File.join(File.dirname(File.dirname(__FILE__)), "snippets") + end + + def render(context) + snippetPath = File.join(snippet_dir, "#{@id}.json") + if !File.exists? snippetPath + raise "Snippet file not found: #{snippetPath}" + end + snippet = JSON::parse(File.read(snippetPath)) + + result = "" + result += render_type snippet, "ts" + result += render_type snippet, "js" + result += render_type snippet, "xml" + result += render_type snippet, "html" + result += render_type snippet, "css" + + if result == "" + raise "No snippets found for: #{@id}" + end + + result + end + + def render_type(snippet, type) + case type + when "ts" + title = "TypeScript" + when "js" + title = "JavaScript" + when "html" + title = "HTML" + when "xml" + title = "XML" + when "css" + title = "CSS" + else + raise "Unknown snippet type: #{type}" + end + + if snippet.key? type + return "```#{title}\n#{snippet[type]}\n```\n" + else + return "" + end + end +end + +Liquid::Template.register_tag("snippet", SnippetTag) diff --git a/_plugins/typedoc_link_tag.rb b/_plugins/typedoc_link_tag.rb new file mode 100644 index 000000000..e2b37eb7c --- /dev/null +++ b/_plugins/typedoc_link_tag.rb @@ -0,0 +1,43 @@ +class TypeDocLinkTag < Liquid::Tag + def initialize(tag_name, text, tokens) + super + @text = text.strip + @arguments = text.strip.split(",") + end + + def render(context) + if @arguments.count == 0 + return + end + page_url = context.environments.first["page"]["url"] + localSite = context['site'] + + apiRefUrl = localSite['apirefurl'] + + moduleInfo = @arguments[0].split(":") + if moduleInfo.count < 2 + return + end + + puts "Resolved module info: #{moduleInfo[1]}" + + result = "\`#{moduleInfo[1]}\`" + + if @arguments.count > 1 + memberInfo = @arguments[1].split(':') + if memberInfo.count == 2 + puts "Resolved member info: #{memberInfo[1]}" + if memberInfo[0] != "member" + return result + else + memberAnchor = memberInfo[1].gsub(Regexp.new("\\(.*\\)"), "") + result = "\`#{memberInfo[1]}\`" + puts "Generating member info link: #{result}" + end + end + end + value = result + end + end + +Liquid::Template.register_tag('typedoc_link', TypeDocLinkTag) diff --git a/adding angular tags b/adding angular tags new file mode 100644 index 000000000..54face890 --- /dev/null +++ b/adding angular tags @@ -0,0 +1,17 @@ +@@ -124,7 +124,7 @@ QUnit.test("Hello World Sample Test:", function (assert) { + assert.equal( mainViewModel.createViewModel().message, "42 taps left", "Message, 42 taps left; equal succeeds." ); //Assert that the message is "42 taps left". +}); +``` + +{% angular %} +## TestBed Integration + +To use TestBed you have to alter your `karma.conf.js` to: +@@ -204,7 +204,7 @@ describe('Renderer E2E', () => { +``` + + +{% endangular%} + +## Run Your Tests + diff --git a/application/AndroidApplication.md b/application/AndroidApplication.md new file mode 100644 index 000000000..dd834e274 --- /dev/null +++ b/application/AndroidApplication.md @@ -0,0 +1,31 @@ +## Object: "application".AndroidApplication +The abstraction of an Android-specific application object. + +##### Properties + - **nativeApp** - _Application_. + The android.app.Application object instance provided to the init of the module. + - **context** - _Context_. + The application android.content.Context object instance. + - **currentActivity** - _Activity_. + The currently active (loaded) android.app.Activity. This property is automatically updated upon Activity events. + - **startActivity** - _Activity_. + The main (start) Activity for the application. + - **packageName** - _String_. + The name of the application package. + - **getActivity** - _Function_(intent _Intent_) _Object_. + This method is called by the JavaScript Bridge when navigation to a new activity is triggered. +The return value of this method should be com.tns.NativeScriptActivity.extends implementation. + - **onActivityCreated** - _Function_(activity _Activity_, bundle _Bundle_). + Direct handler of the android.app.Application.ActivityLifecycleCallbacks.onActivityCreated method. + - **onActivityDestroyed** - _Function_(activity _Activity_). + Direct handler of the android.app.Application.ActivityLifecycleCallbacks.onActivityDestroyed method. + - **onActivityStarted** - _Function_(activity _Activity_). + Direct handler of the android.app.Application.ActivityLifecycleCallbacks.onActivityDestroyed method. + - **onActivityPaused** - _Function_(activity _Activity_). + Direct handler of the android.app.Application.ActivityLifecycleCallbacks.onActivityPaused method. + - **onActivityResumed** - _Function_(activity _Activity_). + Direct handler of the android.app.Application.ActivityLifecycleCallbacks.onActivityResumed method. + - **onActivityStopped** - _Function_(activity _Activity_). + Direct handler of the android.app.Application.ActivityLifecycleCallbacks.onActivityStopped method. + - **onSaveActivityState** - _Function_(activity _Activity_, bundle _Bundle_). + Direct handler of the android.app.Application.ActivityLifecycleCallbacks.onSaveActivityState method. \ No newline at end of file diff --git a/application/HOW-TO.md b/application/HOW-TO.md new file mode 100644 index 000000000..8ddc9f205 --- /dev/null +++ b/application/HOW-TO.md @@ -0,0 +1,47 @@ +# Application +The Application module provides abstraction over the platform-specific Application implementations. +It is the main BCL module and is required for other BCL modules to work properly. +The default bootstrap.js implementation for each platform loads and initializes this module. +``` JavaScript +var app = require("application"); + +``` +The pre-required `app` module is used throughout the following code snippets. +### Initialization +``` JavaScript +// The native app instance depends on the target platform +var nativeAppInstance; +app.init(nativeAppInstance); + +``` +### Checking the target platform +Use the following code in case you need to check somewhere in your code the platform you are running against: +``` JavaScript +if (app.android) { + // we are running on Android device +} else if (app.ios) { + // we are running on iOS device +} + +``` +### Using the Android-specific implementation +Accessing the Android-specific object instance (will be undefined if running on iOS) +``` JavaScript +var androidApp = app.android; + +``` +Using the Android Application context +``` JavaScript +var context = app.android.context; + +// get the Files (Documents) folder (directory) +var dir = context.getFilesDir(); + +``` +Tracking the current Activity +``` JavaScript +if (androidApp.currentActivity === androidApp.startActivity) { + // We are currently in the main (start) activity of the application +} + +``` diff --git a/application/README.md b/application/README.md new file mode 100644 index 000000000..d5cad7193 --- /dev/null +++ b/application/README.md @@ -0,0 +1,36 @@ +# Module: "application" + +``` JavaScript +// To import the "application" module: +var application = require("application"); +``` + +**[How to "application"](HOW-TO.md)** + + +Object | Description +------|------------ +[AndroidApplication](../application/AndroidApplication.md) | The abstraction of an Android-specific application object. +[iOSApplication](../application/iOSApplication.md) | The abstraction of an iOS-specific application object. + +##### Variables + - **android** - [_AndroidApplication_](../application/AndroidApplication.md). + - **ios** - [_iOSApplication_](../application/iOSApplication.md). + +##### Functions + - **onLaunch()** _Object_ + The main entry point event. This method is expected to return an instance of the root UI for the application. +This will be an Activity extends for Android and a RootViewController for iOS. + - _**return**_ - _Object_ + - **onSuspend()** + This method will be called when the Application is suspended. + - **onResume()** + This method will be called when the Application is resumed after it has been suspended. + - **onExit()** + This method will be called when the Application is about to exit. + - **onLowMemory()** + This method will be called when there is low memory on the target device. + - **init(** nativeApp _Object_ **)** + Entry point for the module. Initializes the Application singleton and hooks application lifecycle events. + - **nativeApp** - _Object_ + The instance of the platform Application object - e.g. android.app.Application \ No newline at end of file diff --git a/application/iOSApplication.md b/application/iOSApplication.md new file mode 100644 index 000000000..3587852da --- /dev/null +++ b/application/iOSApplication.md @@ -0,0 +1,8 @@ +## Object: "application".iOSApplication +The abstraction of an iOS-specific application object. + +##### Properties + - **rootController** - _UIViewController_. + The root view controller for the application. + - **nativeApp** - _UIApplication_. + The android.app.Application object instance provided to the init of the module. \ No newline at end of file diff --git a/build-docs.sh b/build-docs.sh new file mode 100644 index 000000000..fe738fcd3 --- /dev/null +++ b/build-docs.sh @@ -0,0 +1,120 @@ +#!/bin/bash +set -ex + +SCRIPT_PATH="$( cd "$(dirname "$0")" ; pwd -P )" +ROOT=$SCRIPT_PATH"/bin" +CONTENT_ROOT=$ROOT"/Content" +WWW_ROOT=$ROOT"/site" +NS_DIST_ROOT=$ROOT"/nativescript" +NG_DIST_ROOT=$ROOT"/angular" + +DOCS_ROOT=$SCRIPT_PATH"/../../docs" +MODULES_ROOT=$SCRIPT_PATH"/../../NativeScript" +NG_ROOT=$SCRIPT_PATH"/../../nativescript-angular" +NS_DOCS_VERSIONS=$SCRIPT_PATH"/../../docs_versions" +SDK_ROOT_JS=$SCRIPT_PATH"/../../nativescript-sdk-examples-js" +SDK_ROOT_NG=$SCRIPT_PATH"/../../nativescript-sdk-examples-ng" +CLI_ROOT=$SCRIPT_PATH"/../../nativescript-cli" +VUEJS_ROOT=$SCRIPT_PATH"/../../docs/vuejs-docs" +NS_UI_SM=$SCRIPT_PATH"/../../nativescript-ui-samples" +NS_UI_SM_NG=$SCRIPT_PATH"/../../nativescript-ui-samples-angular" +NS_UI_DOCS=$SCRIPT_PATH"/ns_ui_docs" + +[ ! -d "$ROOT" ] || rm -rf $ROOT + +mkdir $ROOT + +[ -d "$CONTENT_ROOT" ] || mkdir $CONTENT_ROOT +[ -d "$WWW_ROOT" ] || mkdir $WWW_ROOT + +bundle config build.nokogiri --use-system-libraries + +[ ! -d $CLI_ROOT ] || (cd $CLI_ROOT && ./docs/build-jekyll-md.sh) + +cd $SCRIPT_PATH +bundle install + +cp -r $SCRIPT_PATH"/_config_vuejs.yml" \ + $SCRIPT_PATH"/_assets" \ + $SCRIPT_PATH"/_layouts" \ + $SCRIPT_PATH"/_plugins" \ + $SCRIPT_PATH"/_includes" \ + $SCRIPT_PATH"/fonts" \ + $VUEJS_ROOT + +rm $VUEJS_ROOT"/_plugins/redirect_generator.rb" \ +$VUEJS_ROOT"/_plugins/snippet.rb" \ +$VUEJS_ROOT"/_plugins/ns_cookbook.rb" + +# NativeScript UI Docs Api Reference build. Docs snippet injecting +if [ -d $NS_UI_DOCS ] && [ -d $NS_UI_SM ] && [ -d $NS_UI_SM_NG ]; then + cd $NS_UI_DOCS + npm i + gulp +fi + +[ ! -d $SDK_ROOT_NG ] || (cd $SDK_ROOT_NG && ./build-docs.sh) +[ ! -d $SDK_ROOT_JS ] || (cd $SDK_ROOT_JS && ./build-docs.sh) +[ ! -d $NG_ROOT ] || (cd $NG_ROOT && ./build-doc-snippets.sh) +[ ! -d $MODULES_ROOT ] || (cd $MODULES_ROOT && cp ./tools/scripts/build-docs.sh . && ./build-docs.sh) +[ ! -d $NG_ROOT ] || (cd $NG_ROOT && ./build-docs.sh) + +cp $SCRIPT_PATH"/_config_angular.yml" \ + $SCRIPT_PATH"/_config_nativescript.yml" \ + $SCRIPT_PATH"/_config.yml" \ + $ROOT + +cd $DOCS_ROOT"/build" +for JEKYLL_DIR in {_assets,_includes,_layouts,_plugins,fonts,images}; do + rsync -a --delete $JEKYLL_DIR $CONTENT_ROOT +done + +cp -R $DOCS_ROOT"/docs/./" $CONTENT_ROOT + +[ ! -d $SDK_ROOT_JS ] || cp -R $SDK_ROOT_JS"/dist/cookbook/ns-framework-modules" $CONTENT_ROOT +[ ! -d $SDK_ROOT_NG ] || cp -R $SDK_ROOT_NG"/dist/code-samples/ng-framework-modules" \ + $CONTENT_ROOT + +[ ! -d $CLI_ROOT ] || cp -R $CLI_ROOT"/docs-cli" $CONTENT_ROOT"/tooling" +[ ! -d $SDK_ROOT_JS ] || cp -R $SDK_ROOT_JS"/dist/cookbook/ns-ui-widgets/." $CONTENT_ROOT"/ui/components" +[ ! -d $SDK_ROOT_JS ] || cp -R $SDK_ROOT_JS"/dist/cookbook/ns-ui/." $CONTENT_ROOT"/ui/components" +[ ! -d $SDK_ROOT_NG ] || cp -R $SDK_ROOT_NG"/dist/code-samples/ng-ui-widgets/." $CONTENT_ROOT"/ui/ng-components" +[ ! -d $SDK_ROOT_NG ] || cp -R $SDK_ROOT_NG"/dist/code-samples/ng-ui/." $CONTENT_ROOT"/ui/ng-components" + +cp $SCRIPT_PATH"/nginx.conf" $CONTENT_ROOT + +cd $ROOT + +# Disable sitemap_generator plugin +SITEMAP_GENERATOR=$CONTENT_ROOT"/_plugins/sitemap_generator.rb" +if [ -f $SITEMAP_GENERATOR ] && [ "$1" != "SKIP_SITEMAP_GENERATOR_REMOVAL" ]; then + echo "Removing sitemap generator plugin" + rm $SITEMAP_GENERATOR +fi + +export JEKYLL_ENV="nativescript" +jekyll build --config _config_nativescript.yml,_config.yml + +[ ! -d $NG_ROOT ] || (export JEKYLL_ENV="angular" && jekyll build --config _config_angular.yml,_config.yml) + +cd $VUEJS_ROOT + +export JEKYLL_ENV="vuejs" +jekyll build --config _config_vuejs.yml --trace + +cp -R $VUEJS_ROOT"/vuejs" $WWW_ROOT + +cd $ROOT + +[ ! -d $MODULES_ROOT ] || cp -R $MODULES_ROOT"/bin/dist/api-reference" $WWW_ROOT +[ ! -d $NG_ROOT ] || cp -R $NG_ROOT"/nativescript-angular/bin/dist/ng-api-reference" $WWW_ROOT + +if [ -d $NS_UI_DOCS"/ns-ui-api-reference" ] && [ -d $NS_UI_SM ] && [ -d $NS_UI_SM_NG ]; then + cp -R $NS_UI_DOCS"/ns-ui-api-reference" $WWW_ROOT + +fi + +cp -R $NS_DIST_ROOT"/./" $WWW_ROOT +cp $DOCS_ROOT"/docs_versions.json" $WWW_ROOT +[ ! -d $NG_ROOT ] || cp -R $NG_DIST_ROOT"/./" $WWW_ROOT"/angular" +[ ! -d $NS_DOCS_VERSIONS ] || cp -R $NS_DOCS_VERSIONS"/./" $WWW_ROOT diff --git a/docs-watcher/index.js b/docs-watcher/index.js new file mode 100644 index 000000000..4b639a093 --- /dev/null +++ b/docs-watcher/index.js @@ -0,0 +1,18 @@ +const exec = require("child_process").exec, + JekyllService = require("./jekyll-service"), + SyncService = require("./sync-service"), + watchers = require("./watchers"), + WatcherService = watchers.WatcherService, + SourcesWatcher = watchers.SourcesWatcher; + +var watcher = new WatcherService().start(); +new SyncService(watcher).start(); +var jekyll = new JekyllService(watcher).start(); +var sourcesWatcher = new SourcesWatcher(jekyll).start(); + +process.on("SIGTERM", () => { + exec("pkill -9 -f jekyll", (error, stdout, stderr) => { + sourcesWatcher.stop(); + watcher.stop(); + }); +}); \ No newline at end of file diff --git a/docs-watcher/jekyll-service.js b/docs-watcher/jekyll-service.js new file mode 100644 index 000000000..2374be54f --- /dev/null +++ b/docs-watcher/jekyll-service.js @@ -0,0 +1,64 @@ +var path = require("path"), + paths = require("./paths"), + exec = require("child_process").exec; + +module.exports = class JekyllService { + constructor(watchService) { + this.watchService = watchService; + this.listeners = [{ + workDir: `${paths.root}/bin`, + cmd: "jekyll build --config _config_nativescript.yml,_config.yml --watch --incremental", + env: { JEKYLL_ENV: "nativescript" }, + cleanFolder: path.normalize(`${paths.binRoot}/nativescript/*`) + }, { + workDir: `${paths.root}/bin`, + cmd: "jekyll build --config _config_angular.yml,_config.yml --watch --incremental", + env: { JEKYLL_ENV: "angular" }, + cleanFolder: path.normalize(`${paths.binRoot}/angular/*`) + }]; + } + + start() { + this.listeners.forEach(l => { + var opts = { cwd: l.workDir }; + if (l.env) { + var env = process.env; + for (var key in l.env) { + env[key] = l.env[key]; + } + opts.env = env; + } + + l.proc = exec(l.cmd, opts, (error, stdout, stderr) => { }); + }); + + return this; + } + + restart() { + this.watchService.watching = false; + this.stop().then(() => { + this.start(); + this.watchService.watching = true; + }); + } + + stop() { + var stopPromises = this.listeners.map(l => { + return new Promise((resolve, reject) => { + if (l.proc) { + exec("pkill -9 -f jekyll", (error, stdout, stderr) => { + exec(`rm -rf ${l.cleanFolder}`, (error, stdout, stderr) => { + l.proc = null; + resolve(); + }); + }); + } else { + resolve(); + } + }); + }); + + return Promise.all(stopPromises); + } +} \ No newline at end of file diff --git a/docs-watcher/package.json b/docs-watcher/package.json new file mode 100644 index 000000000..b77ab9b30 --- /dev/null +++ b/docs-watcher/package.json @@ -0,0 +1,25 @@ +{ + "name": "docs-watcher", + "version": "0.0.1", + "description": "Retrieves external files for the NativeScript documentation", + "main": "index.js", + "repository": { + "type": "git", + "url": "git+https://github.com/telerik/nativescript-docs.git" + }, + "keywords": [ + "nativescript", + "documentation", + "watcher" + ], + "author": "Telerik ", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/telerik/nativescript-docs/issues" + }, + "homepage": "https://github.com/telerik/nativescript-docs#readme", + "dependencies": { + "chokidar": "1.7.0", + "fs-extra": "5.0.0" + } +} diff --git a/docs-watcher/paths.js b/docs-watcher/paths.js new file mode 100644 index 000000000..57100d7b8 --- /dev/null +++ b/docs-watcher/paths.js @@ -0,0 +1,39 @@ +var path = require("path"); + +module.exports.root = path.join(__dirname, ".."); +module.exports.wwwRoot = path.normalize(path.join(module.exports.root, "..", "..")); +module.exports.binRoot = path.join(module.exports.root, "bin"); +module.exports.contentPath = path.join(module.exports.binRoot, "Content"); +module.exports.distRoot = path.join(module.exports.binRoot, "site"); + +module.exports.docsRoot = path.join(module.exports.root, "..", "docs"); +module.exports.modulesRoot = path.join(module.exports.root, "..", "..", "NativeScript"); +module.exports.nativescriptAngularRoot = path.join(module.exports.root, "..", "..", "nativescript-angular"); +module.exports.sdkExamplesRootNG = path.join(module.exports.root, "..", "..", "nativescript-sdk-examples-ng"); +module.exports.sdkExamplesRootJS = path.join(module.exports.root, "..", "..", "nativescript-sdk-examples-js"); +module.exports.nsUISamples = path.join(module.exports.root, "..", "..", "nativescript-ui-samples"); +module.exports.nsUISamplesAngular = path.join(module.exports.root, "..", "..", "nativescript-ui-samples-angular"); +module.exports.nsUISamplesVue = path.join(module.exports.root, "..", "..", "nativescript-ui-samples-vue"); +module.exports.cliRoot = path.join(module.exports.root, "..", "..", "nativescript-cli"); +module.exports.vuejsRoot = path.join(module.exports.root, "..", "vuejs-docs"); +module.exports.docsVersions = path.join(module.exports.root, "..", "docs_versions"); + +module.exports.sourceFilesRoot = "/root"; +module.exports.assetsPaths = [ + path.join(module.exports.sourceFilesRoot, "docs", "build", "_assets"), + path.join(module.exports.sourceFilesRoot, "docs", "build", "_layouts"), + path.join(module.exports.sourceFilesRoot, "docs", "build", "_includes"), +]; + +module.exports.sourcePathsInImage = [ + `${module.exports.sourceFilesRoot}/docs`, + `${module.exports.sourceFilesRoot}/NativeScript`, + `${module.exports.sourceFilesRoot}/nativescript-angular`, + `${module.exports.sourceFilesRoot}/nativescript-cli`, + `${module.exports.sourceFilesRoot}/nativescript-sdk-examples-js`, + `${module.exports.sourceFilesRoot}/nativescript-sdk-examples-ng`, + `${module.exports.sourceFilesRoot}/nativescript-ui-samples`, + `${module.exports.sourceFilesRoot}/nativescript-ui-sidedrawer-angular`, + `${module.exports.sourceFilesRoot}/nativescript-ui-sidedrawer-vue`, + `${module.exports.sourceFilesRoot}/docs_versions`, +]; diff --git a/docs-watcher/start.sh b/docs-watcher/start.sh new file mode 100644 index 000000000..4e3794f1a --- /dev/null +++ b/docs-watcher/start.sh @@ -0,0 +1,54 @@ +#!/bin/bash +set -e + +PID=0 +sigterm_handler() { + echo "Caught SIGTERM signal! Shutting down..." + if [ $PID -ne 0 ]; then + kill -SIGTERM "$PID" + wait "$PID" + fi + exit 143; # 128 + 15 -- SIGTERM +} + +sigint_handler() { + echo "Caught SIGINT signal! Shutting down..." + if [ $PID -ne 0 ]; then + kill -SIGTERM "$PID" + wait "$PID" + fi + exit 130; # 128 + 2 -- SIGINT +} + +trap 'kill ${!}; sigterm_handler' SIGTERM +trap 'sigint_handler' SIGINT + +mkdir -p /www + +echo "Start copying mounted folders..." + +rsync --relative -az --exclude node_modules/ --exclude .git \ + /root/./docs \ + /root/./nativescript-angular \ + /www + +[ ! -d /root/./NativeScript ] || rsync --relative -az --exclude node_modules/ --exclude .git /root/./NativeScript /www +[ ! -d /root/./nativescript-sdk-examples-ng ] || rsync --relative -az --exclude node_modules/ --exclude .git /root/./nativescript-sdk-examples-ng /www +[ ! -d /root/./nativescript-sdk-examples-js ] || rsync --relative -az --exclude node_modules/ --exclude .git /root/./nativescript-sdk-examples-js /www +[ ! -d /root/./nativescript-cli ] || rsync --relative -az --exclude node_modules/ --exclude .git /root/./nativescript-cli /www +[ ! -d /root/./nativescript-ui-samples ] || rsync --relative -az --exclude node_modules/ --exclude .git /root/./nativescript-ui-samples /www +[ ! -d /root/./nativescript-ui-samples-angular ] || rsync --relative -az --exclude node_modules/ --exclude .git /root/./nativescript-ui-samples-angular /www +[ ! -d /root/./nativescript-ui-samples-vue ] || rsync --relative -az --exclude node_modules/ --exclude .git /root/./nativescript-ui-samples-vue /www +[ ! -d /root/./docs_versions ] || rsync --relative -az --exclude node_modules/ --exclude .git /root/./docs_versions /www + +/www/docs/build/build-docs.sh +/www/docs/build/nginx-setup.sh + +cd /www/docs/build/docs-watcher +npm install +node index.js & PID="$!" + +while true +do + tail -f /dev/null & wait ${!} +done \ No newline at end of file diff --git a/docs-watcher/sync-service.js b/docs-watcher/sync-service.js new file mode 100644 index 000000000..2ecdfa072 --- /dev/null +++ b/docs-watcher/sync-service.js @@ -0,0 +1,57 @@ +var exec = require("child_process").exec, + paths = require("./paths"); + +module.exports = class SyncService { + constructor(watchService) { + this.watchService = watchService; + this.silentSyncFolders = [ + `${paths.modulesRoot}/bin/dist/./api-reference`, + `${paths.vuejsRoot}/./vuejs`, + `${paths.root}/bin/./angular`, + `${paths.root}/bin/nativescript/./` + ]; + this.initialSyncFinished = false; + this.emptySyncCount = 0; + } + + start() { + if (this.silentSyncFolders.length < 1) { + return; + } + + if (!this.watchService.watching) { + setTimeout(() => this.start(), 2000); + return; + } + + var sources = this.silentSyncFolders.join(" "); + let rsyncScript = `rsync --relative --delete -az --info=NAME ${sources} ${paths.distRoot}`; + exec(rsyncScript, (error, stdout, stderr) => { + if (error) { + setTimeout(() => this.start(), 2000); + return; + } + + if (this.initialSyncFinished && !this.isEmptyOutput(stdout)) { + console.log(stdout); + } + + if (!this.initialSyncFinished && this.isEmptyOutput(stdout)) { + if (++this.emptySyncCount > 3) { + this.initialSyncFinished = true; + console.log("Documentation successfully built! You can start making changes."); + } + } + + setTimeout(() => this.start(), 2000); + }); + + return this; + } + + isEmptyOutput(stdout) { + stdout = stdout || ""; + let lines = stdout.split(/\r?\n/); + return lines.every(line => line == ""); + } +} \ No newline at end of file diff --git a/docs-watcher/watchers.js b/docs-watcher/watchers.js new file mode 100644 index 000000000..f4293fbc2 --- /dev/null +++ b/docs-watcher/watchers.js @@ -0,0 +1,270 @@ +let chokidar = require("chokidar"), + exec = require("child_process").exec, + path = require("path"), + fs = require("fs-extra"), + paths = require("./paths"); + +module.exports.WatcherService = class WatcherService { + constructor() { + this.sourcePaths = [{ + basePath: path.normalize(paths.docsRoot) + }, { + basePath: path.normalize(paths.vuejsRoot) + }, { + basePath: path.normalize(paths.modulesRoot), + distPaths: [ + `${paths.modulesRoot}/bin/dist/./snippets`, + `${paths.modulesRoot}/bin/dist/./cookbook` + ], + buildScript: `${paths.modulesRoot}/build-docs.sh` + }, { + basePath: path.normalize(paths.nativescriptAngularRoot), + distPaths: [`${paths.nativescriptAngularRoot}/bin/dist/./snippets`], + buildScript: `${paths.nativescriptAngularRoot}/build-doc-snippets.sh` + }, { + basePath: path.normalize(paths.sdkExamplesRootNG), + distPaths: [`${paths.sdkExamplesRootNG}/dist/./code-samples`], + buildScript: `${paths.sdkExamplesRootNG}/build-docs.sh` + }, { + basePath: path.normalize(paths.sdkExamplesRootJS), + distPaths: [`${paths.sdkExamplesRootJS}/dist/./code-samples`], + buildScript: `${paths.sdkExamplesRootJS}/build-docs.sh` + }, { + basePath: path.normalize(`${paths.cliRoot}/docs`), + distPaths: [`${paths.cliRoot}/./docs-cli`], + buildScript: `${paths.cliRoot}/docs/build-jekyll-md.sh` + }, { + basePath: path.normalize(paths.nsUISamples) + }, { + basePath: path.normalize(paths.nsUISamplesAngular) + }, { + basePath: path.normalize(paths.nsUISamplesVue) + }]; + } + + start() { + if (!this.watcher) { + var watchPaths = this.sourcePaths.map(x => x.basePath); + var chokidarOptions = { + persistent: true, + ignoreInitial: true, + ignored: [ + `${paths.nativescriptAngularRoot}/bin/dist/**`, + `${paths.sdkExamplesRootNG}/dist/**`, + `${paths.sdkExamplesRootJS}/dist/**`, + `${paths.nsUISamples}/dist/**`, + `${paths.nsUISamplesAngular}/dist/**`, + `${paths.nsUISamplesVue}/dist/**`, + "**/node_modules/**", + "**/.*", + "**/.git/**" + ] + }; + + this.watcher = chokidar.watch(watchPaths, chokidarOptions); + this.watcher + .on("add", f => this.changed(f)) + .on("change", f => this.changed(f)) + .on("unlink", f => this.removed(f)) + .on("error", error => console.error("Error", error)); + this.watching = true; + } + return this; + } + + stop() { + if (this.watcher) { + this.watcher.close(); + this.watcher = null; + } + } + + changed(f) { + if (!this.watching) { + return; + } + + var destFile = this.getDestFile(f); + if (!destFile) { + return; + } + + if (fs.existsSync(f)) { + ensureDestPath(destFile); + fs.copySync(f, destFile); + //console.log(`${destFile} updated`); + } + } + + removed(f) { + if (!this.watching) { + return; + } + + var destFile = this.getDestFile(f); + if (!destFile) { + return; + } + + if (fs.existsSync(destFile)) { + fs.unlinkSync(destFile); + //console.log(`${destFile} removed`); + } + } + + getDestFile(f) { + var sourcePath = this.sourcePaths.find(x => isChildOf(f, x.basePath)); + if (!sourcePath) { + return null; + } + + if (!sourcePath.buildScript) { + var relativePath = path.relative(sourcePath.basePath, f); + var destFile = path.join(paths.contentPath, relativePath); + return destFile; + } + + var distPaths = sourcePath.distPaths || []; + + if (fs.existsSync(sourcePath.buildScript) && distPaths.length > 0) { + console.log(`Triggering build script ${sourcePath.buildScript}`); + var workDir = path.dirname(sourcePath.buildScript); + this.watching = false; + var childProc = exec(sourcePath.buildScript, { cwd: workDir }, (error, stdout, stderr) => { + this.watching = true; + + if (error) { + console.log(`build script execution failed: ${error}`); + } else { + console.log(`Build script ${sourcePath.buildScript} successfully completed`); + } + + distPaths.forEach(distPath => { + var script = `rsync --relative -avzP ${distPath} ${paths.contentPath}`; + exec(script, (error, stdout, stderr) => { }); + }); + }); + + childProc.stdout.on("data", data => console.log(data.toString())); + childProc.stderr.on("data", data => console.log(data.toString())); + } + + return null; + } + +} + +module.exports.SourcesWatcher = class SourcesWatcher { + constructor(jekyllService) { + this.jekyllService = jekyllService; + } + + start() { + if (this.watcher) { + return; + } + + this.watcher = chokidar.watch(paths.sourcePathsInImage, { + persistent: true, + ignoreInitial: true, + usePolling: true, + interval: 1000, + ignored: ["**/node_modules/**", "**/*.tar.gz", "**/.*", "**/.git/**"] + }); + + this.watcher + .on("add", f => this.sourceFileChanged(f)) + .on("change", f => this.sourceFileChanged(f)) + .on("unlink", f => this.sourceFileRemoved(f)) + .on("error", error => console.error("Error", error)); + + return this; + } + + stop() { + if (this.watcher) { + this.watcher.close(); + this.watcher = null; + } + } + + sourceFileChanged(f) { + var filename = path.basename(f); + if (filename == "_config.yml" || filename == "_config_nativescript.yml" || filename == "_config_angular.yml") { + console.log(`${f} updated -> restarting jekyll service...`); + fs.copySync(f, path.join(paths.binRoot, filename)); + + this.jekyllService.restart(); + return; + } + + let assetsPath = paths.assetsPaths.find(ap => isChildOf(f, ap)); + if (assetsPath) { + var basePath = path.normalize(path.join(assetsPath, "..")); + var relativePath = path.relative(basePath, f); + var destination = path.join(paths.contentPath, relativePath); + + if (fs.existsSync(f)) { + console.log(`${destination} updated -> rebuilding site...`); + ensureDestPath(destination); + fs.copySync(f, destination); + this.jekyllService.restart(); + } + return; + } + + var relativePath = path.relative(paths.sourceFilesRoot, f); + var destFile = path.join(paths.wwwRoot, relativePath); + + if (fs.existsSync(f)) { + ensureDestPath(destFile); + fs.copySync(f, destFile); + console.log(`${destFile} updated -> rebuilding site...`); + } + } + + sourceFileRemoved(f) { + let assetsPath = paths.assetsPaths.find(ap => isChildOf(f, ap)); + if (assetsPath) { + var basePath = path.normalize(path.join(assetsPath, "..")); + var relativePath = path.relative(basePath, f); + var destination = path.join(paths.contentPath, relativePath); + + if (fs.existsSync(f)) { + console.log(`${destination} removed -> rebuilding site...`); + fs.unlinkSync(destFile); + this.jekyllService.restart(); + } + return; + } + + var relativePath = path.relative(paths.sourceFilesRoot, f); + var destFile = path.join(paths.wwwRoot, relativePath); + + if (fs.existsSync(destFile)) { + fs.unlinkSync(destFile); + console.log(`${destFile} removed -> rebuilding site...`); + } + } +} + +function isChildOf(child, parent) { + child = path.normalize(child); + parent = path.normalize(parent); + + if (child === parent) { + return false; + } + + var parentTokens = parent.split("/").filter(i => i.length); + var childTokens = child.split("/").filter(i => i.length); + return parentTokens.every((t, i) => childTokens[i].toLowerCase() === t.toLowerCase()); +} + +function ensureDestPath(filename) { + var folder = path.dirname(filename); + + if (!fs.existsSync(folder)) { + fs.ensureDirSync(folder); + } +} \ No newline at end of file diff --git a/file-system/File.md b/file-system/File.md new file mode 100644 index 000000000..e8863b302 --- /dev/null +++ b/file-system/File.md @@ -0,0 +1,35 @@ +## Class: "file-system".File +_Inherits:_ [_FileSystemEntity_](../file-system/FileSystemEntity.md) +Represents a File entity on the file system. + +##### Static Functions + - **exists(** path _String_ **)** _Boolean_ + Checks whether a File with the specified path already exists. + - **path** - _String_ + The path to check for. + - _**return**_ - _Boolean_ + - **fromPath(** path _String_ **)** [_File_](../file-system/File.md) + Gets or creates a File entity at the specified path. + - **path** - _String_ + The path to get/create the file at. + - _**return**_ - [_File_](../file-system/File.md) + +##### Instance Properties + - **extension** - _String_. + Gets the extension of the file. + - **isLocked** - _Boolean_. + Gets a value indicating whether the file is currently locked, meaning a background operation associated with this file is running. + +##### Instance Functions + - **readText(** encoding? _String_ **)** [_Promise_](../promises/Promise.md)... + Reads the content of the file as a string using the specified encoding (defaults to UTF-8). + - **encoding** - _(optional)_ - _String_ + An optional value specifying the preferred encoding (defaults to UTF-8). + - _**return**_ - [_Promise_](../promises/Promise.md) of _String_ + - **writeText(** content _String_, encoding? _String_ **)** [_Promise_](../promises/Promise.md)... + Writes the provided string to the file, using the specified encoding (defaults to UTF-8). + - **content** - _String_ + The content to be saved to the file. + - **encoding** - _(optional)_ - _String_ + An optional value specifying the preferred encoding (defaults to UTF-8). + - _**return**_ - [_Promise_](../promises/Promise.md) of _Object_ \ No newline at end of file diff --git a/file-system/FileSystemEntity.md b/file-system/FileSystemEntity.md new file mode 100644 index 000000000..713a1a413 --- /dev/null +++ b/file-system/FileSystemEntity.md @@ -0,0 +1,24 @@ +## Class: "file-system".FileSystemEntity +Represents a single entity on the file system. + +##### Instance Properties + - **lastModified** - _Date_. + Gets the Date object specifying the last time this entity was modified. + - **name** - _String_. + Gets the name of the entity. + - **path** - _String_. + Gets the fully-qualified path (including the extension for a File) of the entity. + - **parent** - [_Folder_](../file-system/Folder.md). + Gets the Folder object representing the parent of this entity. +Will be null for a root folder like Documents or Temporary. +This property is readonly. + +##### Instance Functions + - **remove()** [_Promise_](../promises/Promise.md)... + Removes (deletes) the current Entity from the file system. + - _**return**_ - [_Promise_](../promises/Promise.md) of _Object_ + - **rename(** newName _String_ **)** [_Promise_](../promises/Promise.md)... + Renames the current entity using the specified name. + - **newName** - _String_ + The new name to be applied to the entity. + - _**return**_ - [_Promise_](../promises/Promise.md) of _Object_ \ No newline at end of file diff --git a/file-system/Folder.md b/file-system/Folder.md new file mode 100644 index 000000000..a7cce01a7 --- /dev/null +++ b/file-system/Folder.md @@ -0,0 +1,47 @@ +## Class: "file-system".Folder +_Inherits:_ [_FileSystemEntity_](../file-system/FileSystemEntity.md) +Represents a Folder (directory) entity on the file system. + +##### Static Functions + - **fromPath(** path _String_ **)** [_Folder_](../file-system/Folder.md) + Gets or creates a Folder entity at the specified path. + - **path** - _String_ + The path to get/create the folder at. + - _**return**_ - [_Folder_](../file-system/Folder.md) + - **exists(** path _String_ **)** _Boolean_ + Checks whether a Folder with the specified path already exists. + - **path** - _String_ + The path to check for. + - _**return**_ - _Boolean_ + +##### Instance Properties + - **isKnown** - _Boolean_. + Determines whether this instance is a KnownFolder (accessed through the KnownFolders object). + +##### Instance Functions + - **contains(** name _String_ **)** _Boolean_ + Checks whether this Folder contains an Entity with the specified name. +The path of the folder is added to the name to resolve the complete path to check for. + - **name** - _String_ + The name of the entity to check for. + - _**return**_ - _Boolean_ + - **clear()** [_Promise_](../promises/Promise.md)... + Deletes all the files and folders (recursively), contained within this Folder. + - _**return**_ - [_Promise_](../promises/Promise.md) of _Object_ + - **getFile(** name _String_ **)** [_File_](../file-system/File.md) + Gets or creates a File entity with the specified name within this Folder. + - **name** - _String_ + The name of the file to get/create. + - _**return**_ - [_File_](../file-system/File.md) + - **getFolder(** name _String_ **)** [_Folder_](../file-system/Folder.md) + Gets or creates a Folder entity with the specified name within this Folder. + - **name** - _String_ + The name of the folder to get/create. + - _**return**_ - [_Folder_](../file-system/Folder.md) + - **getEntities()** [_Promise_](../promises/Promise.md)... + Gets all the top-level entities residing within this folder. + - _**return**_ - [_Promise_](../promises/Promise.md) of _Array_ of [_FileSystemEntity_](../file-system/FileSystemEntity.md) + - **eachEntity(** onEntity _Function_... **)** + Enumerates all the top-level FileSystem entities residing within this folder. + - **onEntity** - _Function_(entity [_FileSystemEntity_](../file-system/FileSystemEntity.md)) _Boolean_ + A callback that receives the current entity. If the callback returns false this will mean for the iteration to stop. \ No newline at end of file diff --git a/file-system/HOW-TO.md b/file-system/HOW-TO.md new file mode 100644 index 000000000..17b2ac94a --- /dev/null +++ b/file-system/HOW-TO.md @@ -0,0 +1,236 @@ +# File System +Using the file system requires the FileSystem module. +``` JavaScript +var fs = require("file-system"); + +``` +The pre-required `fs` module is used throughout the following code snippets. +## Path +### Normalize a Path +``` JavaScript +var documents = fs.knownFolders.documents(); +var testPath = "///test.txt"; + +// Get a normalized path such as /test.txt from ///test.txt +var normalizedPath = fs.path.normalize(documents.path + testPath); + +``` +### Path Join +Concatinate a path to a file by providing multiple path arguments. +``` JavaScript +var documents = fs.knownFolders.documents(); + +// Generate a path like /myFiles/test.txt +var path = fs.path.join(documents.path, "myFiles", "test.txt"); + +``` +### Get the Path Separator +``` JavaScript +// An OS dependant path separator, "\" or "/". +var separator = fs.path.separator; + +``` +### Get or Create a File With Path +The following example writes some text to a file created for path. +It will create a new file or overwrite an existing file. +``` JavaScript +var documents = fs.knownFolders.documents(); +var path = fs.path.join(documents.path, "FileFromPath.txt"); +var file = fs.File.fromPath(path); + +// Writing text to the file. +file.writeText("Something").then(function () { + // Succeeded writing to the file. +}).fail(function (error) { + // Failed to write to the file. +}); +``` +### Get or Create a Folder With Path +``` JavaScript +var path = fs.path.join(fs.knownFolders.documents().path, "music"); +var folder = fs.Folder.fromPath(path); + +``` +## Create +### Writing a string to a File +The following example writes some text to a file. +It will create a new file or overwrite an existing file. +``` JavaScript +var documents = fs.knownFolders.documents(); +var file = documents.getFile("Test_Write.txt"); + +// Writing text to the file. +file.writeText("Something").then(function () { + // Succeeded writing to the file. +}).fail(function (error) { + // Failed to write to the file. +}); +``` +### Get or Create a File +``` JavaScript +var documents = fs.knownFolders.documents(); +var file = documents.getFile("NewFileToCreate.txt"); + +``` +### Get or Create a Folder +``` JavaScript +var documents = fs.knownFolders.documents(); +var folder = documents.getFolder("NewFolderToCreate"); + +``` +## Read +### Reading from a File +The following example writes some text to a file and then reads it back. +``` JavaScript +var documents = fs.knownFolders.documents(); +var myFile = documents.getFile("Test_Write.txt"); + +var written; + +// Writing text to the file. +myFile.writeText("Something").then(function () { + // Succeeded writing to the file. + // Getting back the contents of the file. + myFile.readText().then(function (content) { + // Successfuly read the file's content. + }).fail(function (error) { + // Failed to read from the file. + }); +}).fail(function (error) { + // Failed to write to the file. +}); +``` +### Getting the Known Folders +Each app has several well known folders. This is how to access them: +``` JavaScript +// Getting the application's 'documents' folder. +var documents = fs.knownFolders.documents(); + +// Getting the application's 'temp' folder. +var temp = fs.knownFolders.temp(); + +``` +### Getting Folder Contents +Getting all files and folders within a folder: +``` JavaScript +var documents = fs.knownFolders.documents(); + +documents.getEntities().then(function (entities) { + // entities is array with the document's files and folders. + entities.forEach(function (entity) { + console.log(entity.name); + }); + +}).fail(function (error) { + // Failed to obtain folder's contents. + globalConsole.error(error.message); +}); +``` +### Enumerating Folder Contents +Getting all folder entities in array may be slow with large number of files. +Enumerating the folder entities would itterate the files one by one without blocking the UI. +``` JavaScript +var documents = fs.knownFolders.documents(); + +documents.eachEntity(function (entity) { + console.log(entity.name); + + // Return true to continue, or return false to stop the itteration. + return true; +}); + +``` +### Getting Parent Folder +``` JavaScript +var documents = fs.knownFolders.documents(); +var file = documents.getFile("Test.txt"); + +// The parent folder of the file would be the documents folder. +var parent = file.parent; + +``` +### Getting File Name and Extension +``` JavaScript +var documents = fs.knownFolders.documents(); +var file = documents.getFile("Test.txt"); + +// Getting the file name "Test.txt". +var fileName = file.name; + +// Getting the file extension ".txt". +var fileExtension = file.extension; + +``` +### Checking if a File Exists +``` JavaScript +var documents = fs.knownFolders.documents(); +var file = documents.getFile("Test.txt"); +var exists = fs.File.exists(file.path); + +``` +### Checking if a Folder Exists +``` JavaScript +var documents = fs.knownFolders.documents(); +var exists = fs.Folder.exists(documents.path); + +``` +## Update +### Renaming a File +``` JavaScript +var documents = fs.knownFolders.documents(); +var file = documents.getFile("Test.txt"); + +file.rename("Test_renamed.txt").then(function (result) { + // Successfully Renamed. +}).fail(function (error) { + // Failed to rename the file. +}); +``` +### Renaming a Folder +``` JavaScript +var folder = fs.knownFolders.documents(); +var myFolder = folder.getFolder("Test__"); + +myFolder.rename("Something").then(function (result) { + // Successfully Renamed. +}).fail(function (error) { + // Failed to rename the folder. +}); +``` +## Delete +### Removing a File +To 'delete', 'remove' or 'unlink' a file use the file's remove method: +``` JavaScript +var documents = fs.knownFolders.documents(); +var file = documents.getFile("AFileToRemove.txt"); +file.remove().then(function (result) { + // Success removing the file. +}).fail(function (error) { + // Failed to remove the file. +}); +``` +### Removing a Folder +``` JavaScript +var documents = fs.knownFolders.documents(); +var file = documents.getFolder("AFolderToRemove"); + +// Remove a folder and recursively its content. +file.remove().then(function (result) { + // Success removing the folder. +}).fail(function (error) { + // Failed to remove the folder. +}); +``` +### Clearing the Contents of a Folder +The clear method removes all files within a folder. +``` JavaScript +var documents = fs.knownFolders.documents(); +var folder = documents.getFolder("testFolderEmpty"); + +folder.clear().then(function () { + // Successfully cleared the folder. +}).fail(function (error) { + // Failed to clear the folder. +}); + +``` diff --git a/file-system/README.md b/file-system/README.md new file mode 100644 index 000000000..f6cf85b46 --- /dev/null +++ b/file-system/README.md @@ -0,0 +1,20 @@ +# Module: "file-system" + +``` JavaScript +// To import the "file-system" module: +var file_system = require("file-system"); +``` + +**[How to "file-system"](HOW-TO.md)** + + +Class | Description +------|------------ +[FileSystemEntity](../file-system/FileSystemEntity.md) | Represents a single entity on the file system. +[File](../file-system/File.md) | Represents a File entity on the file system. +[Folder](../file-system/Folder.md) | Represents a Folder (directory) entity on the file system. + +Namespace | Description +------|------------ +[knownFolders](../file-system/knownFolders/) | Provides access to the top-level Folders instances that are accessible from the application. Use these as entry points to access the FileSystem. +[path](../file-system/path/) | Enables path-specific operations like join, extension, etc. \ No newline at end of file diff --git a/file-system/knownFolders/README.md b/file-system/knownFolders/README.md new file mode 100644 index 000000000..c81ed156f --- /dev/null +++ b/file-system/knownFolders/README.md @@ -0,0 +1,10 @@ +## Namespace: "file-system".knownFolders +Provides access to the top-level Folders instances that are accessible from the application. Use these as entry points to access the FileSystem. + +##### Functions + - **documents()** [_Folder_](../../file-system/Folder.md) + Gets the Documents folder available for the current application. This Folder is private for the application and not accessible from Users/External apps. + - _**return**_ - [_Folder_](../../file-system/Folder.md) + - **temp()** [_Folder_](../../file-system/Folder.md) + Gets the Temporary (Caches) folder available for the current application. This Folder is private for the application and not accessible from Users/External apps. + - _**return**_ - [_Folder_](../../file-system/Folder.md) \ No newline at end of file diff --git a/file-system/path/README.md b/file-system/path/README.md new file mode 100644 index 000000000..ade4207d4 --- /dev/null +++ b/file-system/path/README.md @@ -0,0 +1,17 @@ +## Namespace: "file-system".path +Enables path-specific operations like join, extension, etc. + +##### Variables + - **separator** - _String_. + +##### Functions + - **normalize(** path _String_ **)** _String_ + Normalizes a path, taking care of occurrances like ".." and "//". + - **path** - _String_ + The path to be normalized. + - _**return**_ - _String_ + - **join(** ...paths Array of _String_ **)** _String_ + Joins all the provided string components, forming a valid and normalized path. + - **...paths** - Array of _String_ + An array of string components to be joined. + - _**return**_ - _String_ \ No newline at end of file diff --git a/fonts/Roboto-Light-webfont.svg b/fonts/Roboto-Light-webfont.svg new file mode 100644 index 000000000..8e84bbbac --- /dev/null +++ b/fonts/Roboto-Light-webfont.svg @@ -0,0 +1,1063 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Font data copyright Google 2011 +Designer : Google +Foundry URL : Googlecom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fonts/Roboto-Light-webfont.ttf b/fonts/Roboto-Light-webfont.ttf new file mode 100644 index 000000000..4cb64cfa9 Binary files /dev/null and b/fonts/Roboto-Light-webfont.ttf differ diff --git a/fonts/Roboto-Light-webfont.woff b/fonts/Roboto-Light-webfont.woff new file mode 100644 index 000000000..f6abd8713 Binary files /dev/null and b/fonts/Roboto-Light-webfont.woff differ diff --git a/fonts/Roboto-Regular-webfont.eot b/fonts/Roboto-Regular-webfont.eot new file mode 100644 index 000000000..869b3425c Binary files /dev/null and b/fonts/Roboto-Regular-webfont.eot differ diff --git a/fonts/Roboto-Regular-webfont.svg b/fonts/Roboto-Regular-webfont.svg new file mode 100644 index 000000000..83868bb29 --- /dev/null +++ b/fonts/Roboto-Regular-webfont.svg @@ -0,0 +1,1063 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Copyright : Font data copyright Google 2011 +Designer : Google +Foundry URL : Googlecom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fonts/Roboto-Regular-webfont.ttf b/fonts/Roboto-Regular-webfont.ttf new file mode 100644 index 000000000..c46f1dd76 Binary files /dev/null and b/fonts/Roboto-Regular-webfont.ttf differ diff --git a/fonts/Roboto-Regular-webfont.woff b/fonts/Roboto-Regular-webfont.woff new file mode 100644 index 000000000..6ff6afd8c Binary files /dev/null and b/fonts/Roboto-Regular-webfont.woff differ diff --git a/fonts/dual-100.eot b/fonts/dual-100.eot new file mode 100644 index 000000000..d4c27b4d2 Binary files /dev/null and b/fonts/dual-100.eot differ diff --git a/fonts/dual-100.ttf b/fonts/dual-100.ttf new file mode 100644 index 000000000..1ad7ac65d Binary files /dev/null and b/fonts/dual-100.ttf differ diff --git a/fonts/dual-100.woff b/fonts/dual-100.woff new file mode 100644 index 000000000..c55ccf904 Binary files /dev/null and b/fonts/dual-100.woff differ diff --git a/fonts/dual-100.woff2 b/fonts/dual-100.woff2 new file mode 100644 index 000000000..65fa5b44e Binary files /dev/null and b/fonts/dual-100.woff2 differ diff --git a/fonts/dual-300.eot b/fonts/dual-300.eot new file mode 100644 index 000000000..8d750328e Binary files /dev/null and b/fonts/dual-300.eot differ diff --git a/fonts/dual-300.ttf b/fonts/dual-300.ttf new file mode 100644 index 000000000..3ec30997d Binary files /dev/null and b/fonts/dual-300.ttf differ diff --git a/fonts/dual-300.woff b/fonts/dual-300.woff new file mode 100644 index 000000000..f522ac9d0 Binary files /dev/null and b/fonts/dual-300.woff differ diff --git a/fonts/dual-300.woff2 b/fonts/dual-300.woff2 new file mode 100644 index 000000000..49769a54d Binary files /dev/null and b/fonts/dual-300.woff2 differ diff --git a/fonts/dual-600.eot b/fonts/dual-600.eot new file mode 100644 index 000000000..70c883ee2 Binary files /dev/null and b/fonts/dual-600.eot differ diff --git a/fonts/dual-600.svg b/fonts/dual-600.svg new file mode 100644 index 000000000..d341352b4 --- /dev/null +++ b/fonts/dual-600.svg @@ -0,0 +1,1987 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fonts/dual-600.ttf b/fonts/dual-600.ttf new file mode 100644 index 000000000..a71bd2c84 Binary files /dev/null and b/fonts/dual-600.ttf differ diff --git a/fonts/dual-600.woff b/fonts/dual-600.woff new file mode 100644 index 000000000..d5add8a4f Binary files /dev/null and b/fonts/dual-600.woff differ diff --git a/fonts/dual-600.woff2 b/fonts/dual-600.woff2 new file mode 100644 index 000000000..b7ac7084d Binary files /dev/null and b/fonts/dual-600.woff2 differ diff --git a/fonts/ns-icons-4f5bcf65535f91c128a9f17b5b56aadd.eot b/fonts/ns-icons-4f5bcf65535f91c128a9f17b5b56aadd.eot new file mode 100644 index 000000000..3f734080d Binary files /dev/null and b/fonts/ns-icons-4f5bcf65535f91c128a9f17b5b56aadd.eot differ diff --git a/fonts/ns-icons-4f5bcf65535f91c128a9f17b5b56aadd.svg b/fonts/ns-icons-4f5bcf65535f91c128a9f17b5b56aadd.svg new file mode 100644 index 000000000..953ff7b1f --- /dev/null +++ b/fonts/ns-icons-4f5bcf65535f91c128a9f17b5b56aadd.svg @@ -0,0 +1,44 @@ + + + + + + +{ + "fontFamily": "ns-icons", + "majorVersion": 1, + "minorVersion": 0, + "fontURL": "https://www.nativescript.org/", + "copyright": "https://www.nativescript.org/", + "designer": "Telerik, A Progress Company", + "designerURL": "https://www.nativescript.org/", + "license": "Apache License, Version 2.0", + "licenseURL": "http://www.apache.org/licenses/LICENSE-2.0.html", + "description": "NativeScript Font\nFont generated by IcoMoon.", + "version": "Version 1.0", + "fontId": "ns-icons", + "psName": "ns-icons", + "subFamily": "Regular", + "fullName": "ns-icons" +} + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fonts/ns-icons-4f5bcf65535f91c128a9f17b5b56aadd.ttf b/fonts/ns-icons-4f5bcf65535f91c128a9f17b5b56aadd.ttf new file mode 100644 index 000000000..aabcb1de9 Binary files /dev/null and b/fonts/ns-icons-4f5bcf65535f91c128a9f17b5b56aadd.ttf differ diff --git a/fonts/ns-icons-4f5bcf65535f91c128a9f17b5b56aadd.woff b/fonts/ns-icons-4f5bcf65535f91c128a9f17b5b56aadd.woff new file mode 100644 index 000000000..ecd8e80ce Binary files /dev/null and b/fonts/ns-icons-4f5bcf65535f91c128a9f17b5b56aadd.woff differ diff --git a/fonts/open-sans-condensed/open-sans-condensed-v10-latin-300.woff2 b/fonts/open-sans-condensed/open-sans-condensed-v10-latin-300.woff2 new file mode 100644 index 000000000..fd7ee8886 Binary files /dev/null and b/fonts/open-sans-condensed/open-sans-condensed-v10-latin-300.woff2 differ diff --git a/fonts/open-sans-condensed/open-sans-condensed-v10-latin-300italic.woff2 b/fonts/open-sans-condensed/open-sans-condensed-v10-latin-300italic.woff2 new file mode 100644 index 000000000..cdc8bde85 Binary files /dev/null and b/fonts/open-sans-condensed/open-sans-condensed-v10-latin-300italic.woff2 differ diff --git a/fonts/open-sans-condensed/open-sans-condensed-v10-latin-700.woff2 b/fonts/open-sans-condensed/open-sans-condensed-v10-latin-700.woff2 new file mode 100644 index 000000000..c3e9d7265 Binary files /dev/null and b/fonts/open-sans-condensed/open-sans-condensed-v10-latin-700.woff2 differ diff --git a/fonts/open-sans/open-sans-v13-latin-300.woff2 b/fonts/open-sans/open-sans-v13-latin-300.woff2 new file mode 100644 index 000000000..96ae7edd3 Binary files /dev/null and b/fonts/open-sans/open-sans-v13-latin-300.woff2 differ diff --git a/fonts/open-sans/open-sans-v13-latin-800.woff2 b/fonts/open-sans/open-sans-v13-latin-800.woff2 new file mode 100644 index 000000000..26791be2a Binary files /dev/null and b/fonts/open-sans/open-sans-v13-latin-800.woff2 differ diff --git a/gruntfile.js b/gruntfile.js new file mode 100644 index 000000000..a3badfc80 --- /dev/null +++ b/gruntfile.js @@ -0,0 +1,28 @@ +module.exports = function(grunt) { + + //Construct and validate the arguments + var args = { + branch: grunt.option("branch") + }; + + (function validateInput(){ + if (!args.branch) {throw new Error("No branch specified!");} + }()); + + grunt.initConfig({ + exec: { + switchContentSubmoduleToTipOfBranch: { + cmd: "git checkout -f " + args.branch + + " && git pull --rebase" + + " && git submodule update --init --recursive", + cwd: "./Content" + } + } + }); + + grunt.loadNpmTasks("grunt-exec"); + + grunt.registerTask("default", [ + "exec:switchContentSubmoduleToTipOfBranch" + ]); +}; diff --git a/http/HOW-TO.md b/http/HOW-TO.md new file mode 100644 index 000000000..0bde7302e --- /dev/null +++ b/http/HOW-TO.md @@ -0,0 +1,74 @@ +# Http module +``` JavaScript +var http = require("http"); +``` +### Get string from URL +``` JavaScript +http.getString("http://httpbin.org/get").then(function (r) { + // Argument (r) is string! +}).fail(function (e) { + // Argument (e) is Error! + console.log(e); +}); + +``` +### Get JSON from URL +``` JavaScript +http.getJSON("http://httpbin.org/get").then(function (r) { + // Argument (r) is JSON! +}).fail(function (e) { + // Argument (e) is Error! + console.log(e); +}); + +``` +### Get Image from URL +``` JavaScript +http.getImage("http://www.google.com/images/errors/logo_sm_2.png").then(function (r) { + // Argument (r) is Image! +}).fail(function (e) { + // Argument (e) is Error! + console.log(e); +}); + +``` +### Get response status code +``` JavaScript +http.request({ url: "http://httpbin.org/get", method: "GET" }).then(function (response) { + // Argument (response) is HttpResponse! + var statusCode = response.statusCode; + +}).fail(function (e) { + // Argument (e) is Error! + console.log(e); +}); + +``` +### Get response headers +``` JavaScript +http.request({ url: "http://httpbin.org/get", method: "GET" }).then(function (response) { + for (var header in response.headers) { + console.log(header + ":" + response.headers[header]); + } + +}).fail(function (e) { + // Argument (e) is Error! + console.log(e); +}); + +``` +### Get response content +``` JavaScript +http.request({ url: "http://httpbin.org/get", method: "GET" }).then(function (response) { + // Argument (response) is HttpResponse! + // Content property of the response is HttpContent! + var str = response.content.toString(); + var obj = response.content.toJSON(); + var img = response.content.toImage(); + +}).fail(function (e) { + // Argument (e) is Error! + console.log(e); +}); + +``` diff --git a/http/HttpContent.md b/http/HttpContent.md new file mode 100644 index 000000000..5746d3a9f --- /dev/null +++ b/http/HttpContent.md @@ -0,0 +1,12 @@ +## Object: "http".HttpContent +Encapsulates the content of an HttpResponse. + +##### Properties + - **raw** - _Object_. + Gets the response body as raw data. + - **toString** - _Function_() _String_. + Gets the response body as string. + - **toJSON** - _Function_() _Object_. + Gets the response body as JSON object. + - **toImage** - _Function_() [_ImageSource_](../image-source/ImageSource.md). + Gets the response body as ImageSource. \ No newline at end of file diff --git a/http/HttpRequestOptions.md b/http/HttpRequestOptions.md new file mode 100644 index 000000000..778ba8b35 --- /dev/null +++ b/http/HttpRequestOptions.md @@ -0,0 +1,14 @@ +## Object: "http".HttpRequestOptions +Provides options for the http requests. + +##### Properties + - **url** - _String_. + Gets or sets the request url. + - **method** - _String_. + Gets or sets the request method. + - **headers** - _(optional)_ - _Object_. + Gets or sets the request headers in JSON format. + - **content** - _(optional)_ - _Object_. + Gets or sets the request body. + - **timeout** - _(optional)_ - _Number_. + Gets or sets the request timeout. \ No newline at end of file diff --git a/http/HttpResponse.md b/http/HttpResponse.md new file mode 100644 index 000000000..d04db87af --- /dev/null +++ b/http/HttpResponse.md @@ -0,0 +1,10 @@ +## Object: "http".HttpResponse +Encapsulates HTTP-response information from an HTTP-request. + +##### Properties + - **statusCode** - _Number_. + Gets the response status code. + - **headers** - _Object_. + Gets the response headers. + - **content** - _(optional)_ - [_HttpContent_](../http/HttpContent.md). + Gets the response content. \ No newline at end of file diff --git a/http/README.md b/http/README.md new file mode 100644 index 000000000..6a73795ed --- /dev/null +++ b/http/README.md @@ -0,0 +1,54 @@ +# Module: "http" + +``` JavaScript +// To import the "http" module: +var http = require("http"); +``` + +**[How to "http"](HOW-TO.md)** + + +Object | Description +------|------------ +[HttpRequestOptions](../http/HttpRequestOptions.md) | Provides options for the http requests. +[HttpResponse](../http/HttpResponse.md) | Encapsulates HTTP-response information from an HTTP-request. +[HttpContent](../http/HttpContent.md) | Encapsulates the content of an HttpResponse. + +##### Functions + - **getString(** url _String_ **)** [_Promise_](../promises/Promise.md)... + Downloads the content from the specified URL as a string. + - **url** - _String_ + The URL to request from. + - _**return**_ - [_Promise_](../promises/Promise.md) of _String_ + - **getString(** options [_HttpRequestOptions_](../http/HttpRequestOptions.md) **)** [_Promise_](../promises/Promise.md)... + Downloads the content from the specified URL as a string. + - **options** - [_HttpRequestOptions_](../http/HttpRequestOptions.md) + An object that specifies various request options. + - _**return**_ - [_Promise_](../promises/Promise.md) of _String_ + - **getJSON(** url _String_ **)** [_Promise_](../promises/Promise.md)... + _Types Parameters:_ _**T**_ + Downloads the content from the specified URL as a string and returns its JSON.parse representation. + - **url** - _String_ + The URL to request from. + - _**return**_ - [_Promise_](../promises/Promise.md) of _T_ + - **getJSON(** options [_HttpRequestOptions_](../http/HttpRequestOptions.md) **)** [_Promise_](../promises/Promise.md)... + _Types Parameters:_ _**T**_ + Downloads the content from the specified URL as a string and returns its JSON.parse representation. + - **options** - [_HttpRequestOptions_](../http/HttpRequestOptions.md) + An object that specifies various request options. + - _**return**_ - [_Promise_](../promises/Promise.md) of _T_ + - **getImage(** url _String_ **)** [_Promise_](../promises/Promise.md)... + Downloads the content from the specified URL and attempts to decode it as an image. + - **url** - _String_ + The URL to request from. + - _**return**_ - [_Promise_](../promises/Promise.md) of [_ImageSource_](../image-source/ImageSource.md) + - **getImage(** options [_HttpRequestOptions_](../http/HttpRequestOptions.md) **)** [_Promise_](../promises/Promise.md)... + Downloads the content from the specified URL and attempts to decode it as an image. + - **options** - [_HttpRequestOptions_](../http/HttpRequestOptions.md) + An object that specifies various request options. + - _**return**_ - [_Promise_](../promises/Promise.md) of [_ImageSource_](../image-source/ImageSource.md) + - **request(** options [_HttpRequestOptions_](../http/HttpRequestOptions.md) **)** [_Promise_](../promises/Promise.md)... + Makes a generic http request using the provided options and returns a HttpResponse Object. + - **options** - [_HttpRequestOptions_](../http/HttpRequestOptions.md) + An object that specifies various request options. + - _**return**_ - [_Promise_](../promises/Promise.md) of [_HttpResponse_](../http/HttpResponse.md) \ No newline at end of file diff --git a/image-source/HOW-TO.md b/image-source/HOW-TO.md new file mode 100644 index 000000000..c834a345e --- /dev/null +++ b/image-source/HOW-TO.md @@ -0,0 +1,41 @@ +# Image source +Using the image source requires the image-source module. +``` JavaScript +var imageSource = require("image-source"); +``` +The pre-required `imageSource` module is used throughout the following code snippets. +We also use fs module defined as follows: +``` JavaScript +var fs = require("file-system"); +``` +## Loading and saving images +### Load image using resource name +This is similar to loading Bitmap from `R.drawable.logo` on Android or calling `[UIImage imageNamed@"logo"]` on iOS +``` JavaScript +var img = imageSource.fromResource("logo"); + +``` +### Load image from URL +``` JavaScript +imageSource.fromUrl("http://www.google.com/images/errors/logo_sm_2.png").then(function (res) { + console.log("Image successfully loaded"); +}).fail(function (error) { + console.log("Error loading image: " + error); +}); + +``` +### Save image source to PNG or JPG file +``` JavaScript +var img = imageSource.fromResource("logo"); +var folder = fs.knownFolders.documents(); +var path = fs.path.join(folder.path, "Test.png"); +var saved = img.saveToFile(path, imageSource.ImageFormat.PNG); + +``` +### Load image from a local file +``` JavaScript +var folder = fs.knownFolders.documents(); +var path = fs.path.join(folder.path, "Test.png"); +var img = imageSource.fromFile(path); + +``` diff --git a/image-source/ImageFormat.md b/image-source/ImageFormat.md new file mode 100644 index 000000000..2e6f8ee04 --- /dev/null +++ b/image-source/ImageFormat.md @@ -0,0 +1,4 @@ +## Enum: "image-source".ImageFormat +Defines the recognized image formats. + - **PNG** - The W3C Portable Network Graphics (PNG) image format. + - **JPEG** - The Joint Photographic Experts Group (JPEG) image format. \ No newline at end of file diff --git a/image-source/ImageSource.md b/image-source/ImageSource.md new file mode 100644 index 000000000..695bbcc98 --- /dev/null +++ b/image-source/ImageSource.md @@ -0,0 +1,44 @@ +## Class: "image-source".ImageSource +Encapsulates the common abstraction behind a platform specific object (typically a Bitmap) that is used as a source for images. + +##### Instance Properties + - **height** - _Number_. + Gets the height of this instance. This is a read-only property. + - **width** - _Number_. + Gets the width of this instance. This is a read-only property. + - **ios** - _UIImage_. + The iOS-specific image instance. Will be undefined when running on Android. + - **android** - _Bitmap_. + The Android-specific image instance. Will be undefined when running on iOS. + +##### Instance Functions + - **loadFromResource(** name _String_ **)** _Boolean_ + Loads this instance from the specified resource name. + - **name** - _String_ + The name of the resource (without its extension). + - _**return**_ - _Boolean_ + - **loadFromFile(** path _String_ **)** _Boolean_ + Loads this instance from the specified file. + - **path** - _String_ + The location of the file on the file system. + - _**return**_ - _Boolean_ + - **loadFromData(** data _Object_ **)** _Boolean_ + Loads this instance from the specified native image data. + - **data** - _Object_ + The native data (byte array) to load the image from. This will be either Stream for Android or NSData for iOS. + - _**return**_ - _Boolean_ + - **setNativeSource(** source _Object_ **)** _Boolean_ + Sets the provided native source object (typically a Bitmap). +This will update either the android or ios properties, depending on the target os. + - **source** - _Object_ + The native image object. Will be either a Bitmap for Android or a UIImage for iOS. + - _**return**_ - _Boolean_ + - **saveToFile(** path _String_, format [_ImageFormat_](../image-source/ImageFormat.md), quality? _Number_ **)** _Boolean_ + Saves this instance to the specified file, using the provided image format and quality. + - **path** - _String_ + The path of the file on the file system to save to. + - **format** - [_ImageFormat_](../image-source/ImageFormat.md) + The format (encoding) of the image. + - **quality** - _(optional)_ - _Number_ + Optional parameter, specifying the quality of the encoding. Defaults to the maximum available quality. + - _**return**_ - _Boolean_ \ No newline at end of file diff --git a/image-source/README.md b/image-source/README.md new file mode 100644 index 000000000..cf24ba21c --- /dev/null +++ b/image-source/README.md @@ -0,0 +1,45 @@ +# Module: "image-source" + +``` JavaScript +// To import the "image-source" module: +var image_source = require("image-source"); +``` + +**[How to "image-source"](HOW-TO.md)** + + +Class | Description +------|------------ +[ImageSource](../image-source/ImageSource.md) | Encapsulates the common abstraction behind a platform specific object (typically a Bitmap) that is used as a source for images. + +Enum | Description +------|------------ +[ImageFormat](../image-source/ImageFormat.md) | Defines the recognized image formats. + +##### Functions + - **fromResource(** name _String_ **)** [_ImageSource_](../image-source/ImageSource.md) + Creates a new ImageSource instance and loads it from the specified resource name. + - **name** - _String_ + The name of the resource (without its extension). + - _**return**_ - [_ImageSource_](../image-source/ImageSource.md) + - **fromFile(** path _String_ **)** [_ImageSource_](../image-source/ImageSource.md) + Creates a new ImageSource instance and loads it from the specified file. + - **path** - _String_ + The location of the file on the file system. + - _**return**_ - [_ImageSource_](../image-source/ImageSource.md) + - **fromData(** data _Object_ **)** [_ImageSource_](../image-source/ImageSource.md) + Creates a new ImageSource instance and loads it from the specified resource name. + - **data** - _Object_ + The native data (byte array) to load the image from. This will be either Stream for Android or NSData for iOS. + - _**return**_ - [_ImageSource_](../image-source/ImageSource.md) + - **fromNativeSource(** source _Object_ **)** [_ImageSource_](../image-source/ImageSource.md) + Creates a new ImageSource instance and sets the provided native source object (typically a Bitmap). +The native source object will update either the android or ios properties, depending on the target os. + - **source** - _Object_ + The native image object. Will be either a Bitmap for Android or a UIImage for iOS. + - _**return**_ - [_ImageSource_](../image-source/ImageSource.md) + - **fromUrl(** url _String_ **)** [_Promise_](../promises/Promise.md)... + Downloads the image from the provided Url and creates a new ImageSource instance from it. + - **url** - _String_ + The link to the remote image object. This operation will download and decode the image. + - _**return**_ - [_Promise_](../promises/Promise.md) of [_ImageSource_](../image-source/ImageSource.md) \ No newline at end of file diff --git a/images/anchor.png b/images/anchor.png new file mode 100644 index 000000000..ee50a82d5 Binary files /dev/null and b/images/anchor.png differ diff --git a/images/api.png b/images/api.png new file mode 100644 index 000000000..207c410e3 Binary files /dev/null and b/images/api.png differ diff --git a/images/arrow.png b/images/arrow.png new file mode 100644 index 000000000..190630322 Binary files /dev/null and b/images/arrow.png differ diff --git a/images/column.png b/images/column.png new file mode 100644 index 000000000..a79ccb046 Binary files /dev/null and b/images/column.png differ diff --git a/images/file.png b/images/file.png new file mode 100644 index 000000000..166e599a7 Binary files /dev/null and b/images/file.png differ diff --git a/images/getting-started.png b/images/getting-started.png new file mode 100644 index 000000000..80cb6d222 Binary files /dev/null and b/images/getting-started.png differ diff --git a/images/howdoi.png b/images/howdoi.png new file mode 100644 index 000000000..eaed6bb58 Binary files /dev/null and b/images/howdoi.png differ diff --git a/images/icon-telerik-badge.png b/images/icon-telerik-badge.png new file mode 100644 index 000000000..a97b14e5e Binary files /dev/null and b/images/icon-telerik-badge.png differ diff --git a/images/important.png b/images/important.png new file mode 100644 index 000000000..d20e5d410 Binary files /dev/null and b/images/important.png differ diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 000000000..9e869701d Binary files /dev/null and b/images/logo.png differ diff --git a/images/menu.png b/images/menu.png new file mode 100644 index 000000000..741ebe8bd Binary files /dev/null and b/images/menu.png differ diff --git a/images/nav-arrow.png b/images/nav-arrow.png new file mode 100644 index 000000000..b8cf7c5b1 Binary files /dev/null and b/images/nav-arrow.png differ diff --git a/images/open.png b/images/open.png new file mode 100644 index 000000000..8345685fd Binary files /dev/null and b/images/open.png differ diff --git a/images/search.png b/images/search.png new file mode 100644 index 000000000..9859e389a Binary files /dev/null and b/images/search.png differ diff --git a/images/tap-logo.png b/images/tap-logo.png new file mode 100644 index 000000000..8d9cc0985 Binary files /dev/null and b/images/tap-logo.png differ diff --git a/images/tutorials.png b/images/tutorials.png new file mode 100644 index 000000000..13d9f907c Binary files /dev/null and b/images/tutorials.png differ diff --git a/local-settings/HOW-TO.md b/local-settings/HOW-TO.md new file mode 100644 index 000000000..8cff585da --- /dev/null +++ b/local-settings/HOW-TO.md @@ -0,0 +1,50 @@ +# Local Settings +``` JavaScript +var LocalSettings = require("local-settings"); + +``` +## Working with string, number and boolean values +### Set and get boolean value and provide default value in case it is not set +``` JavaScript +LocalSettings.setBoolean("boolKey", true); +var boolValue = LocalSettings.getBoolean("boolKey", false); + +``` +### Set and get string value +``` JavaScript +LocalSettings.setString("stringKey", "String value"); +var stringValue = LocalSettings.getString("stringKey"); + +``` +### Set and get numeric value. +We use `toFixed()` here in order to avoid floating point errors - ex: `54.321` becoming `54.320999999537`. +Beware the result of `toFixed()` is a string not a number therefore you cannot use `===` or `!==` when comparing with a number. +``` JavaScript +LocalSettings.setNumber("numberKey", 54.321); +var value = LocalSettings.getNumber("numberKey").toFixed(3); + +``` +### Reading values that are not set before while providing default value +``` JavaScript +var defaultValue = LocalSettings.getString("noStringKey", "No string value"); + +// will return "No string value" if there is no value for "noStringKey" +``` +### Reading values that are not set before not providing default value +``` JavaScript +var defaultValue = LocalSettings.getString("noStringKey"); + +// will return undefined if there is no value for "noStringKey" +``` +## Other functions +### Checking for existence of value for key +``` JavaScript +var hasKey = LocalSettings.hasKey("noBoolKey"); + +// will return false if there is no value for "noBoolKey" +``` +### Removing value for key +``` JavaScript +LocalSettings.remove("boolKey"); + +``` diff --git a/local-settings/README.md b/local-settings/README.md new file mode 100644 index 000000000..0b008bd0f --- /dev/null +++ b/local-settings/README.md @@ -0,0 +1,59 @@ +# Module: "local-settings" + +``` JavaScript +// To import the "local-settings" module: +var local_settings = require("local-settings"); +``` + +**[How to "local-settings"](HOW-TO.md)** + + +##### Functions + - **hasKey(** key _String_ **)** _Boolean_ + Checks whether such a key exists. + - **key** - _String_ + The key to check for. + - _**return**_ - _Boolean_ + - **getBoolean(** key _String_, defaultValue? _Boolean_ **)** _Boolean_ + Gets a value (if existing) for a key as a Boolean Object. A default value can be provided in case there is no existing value. + - **key** - _String_ + The key to check for. + - **defaultValue** - _(optional)_ - _Boolean_ + An optional value to be returned in case there is no existing value. + - _**return**_ - _Boolean_ + - **getString(** key _String_, defaultValue? _String_ **)** _String_ + Gets a value (if existing) for a key as a String Object. A default value can be provided in case there is no existing value. + - **key** - _String_ + The key to check for. + - **defaultValue** - _(optional)_ - _String_ + An optional value to be returned in case there is no existing value. + - _**return**_ - _String_ + - **getNumber(** key _String_, defaultValue? _Number_ **)** _Number_ + Gets a value (if existing) for a key as a Number Object. A default value can be provided in case there is no existing value. + - **key** - _String_ + The key to check for. + - **defaultValue** - _(optional)_ - _Number_ + An optional value to be returned in case there is no existing value. + - _**return**_ - _Number_ + - **setBoolean(** key _String_, value _Boolean_ **)** + Sets a Boolean Object for a key. + - **key** - _String_ + The key. + - **value** - _Boolean_ + The value. + - **setString(** key _String_, value _String_ **)** + Sets a String Object for a key. + - **key** - _String_ + The key. + - **value** - _String_ + The value. + - **setNumber(** key _String_, value _Number_ **)** + Sets a Number Object for a key. + - **key** - _String_ + The key. + - **value** - _Number_ + The value. + - **remove(** key _String_ **)** + Removes a value (if existing) for a key. + - **key** - _String_ + The key to check for. \ No newline at end of file diff --git a/location/Accuracy.md b/location/Accuracy.md new file mode 100644 index 000000000..2614de4f5 --- /dev/null +++ b/location/Accuracy.md @@ -0,0 +1,4 @@ +## Enum: "location".Accuracy +Specifies common accuracy values. + - **ANY** = **300** - The default accuracy. About 300 meters. + - **HIGH** = **3** - High accuracy. About 3 meters. \ No newline at end of file diff --git a/location/HOW-TO.md b/location/HOW-TO.md new file mode 100644 index 000000000..d07732eb1 --- /dev/null +++ b/location/HOW-TO.md @@ -0,0 +1,55 @@ +# Location +Using the location requires the Location module. +``` JavaScript +var LocationManager = require("location").LocationManager; +``` +## Other functions +### Test are location services available for this device +``` JavaScript +var isEnabled = LocationManager.isEnabled(); + +``` +### Get distance between two locations +``` JavaScript +var Location = require("location").Location; +var locSofia = new Location(); +locSofia.longitude = 42.696552; +locSofia.latitude = 23.32601; +var locNewYork = new Location(); +locNewYork.longitude = 40.71448; +locNewYork.latitude = -74.00598; +var distance = LocationManager.distance(locSofia, locNewYork); + +``` +## Getting location +### Receive continuous location updates +``` JavaScript +var locationManager = new LocationManager(); + +locationManager.startLocationMonitoring(function (location) { + console.log('Location received: ' + location); +}, function (error) { + console.log('Location error received: ' + error); +}); + +``` +### Get last known location +``` JavaScript +var locationManager = new LocationManager(); +var lastKnownLocation = locationManager.lastKnownLocation; + +``` +### Get location once +if there is `options.timeout` you will receive error on timeout. If `options.timeout` is 0 then the result is the same as the result from `LocationManager.lastKnownLocation` +and there will be no wait. You can use `options.maximumAge` to specify you don't want to receive locations older than specified time in ms. + +``` JavaScript +var locationModule = require("location"); +// options can also look like { maximumAge: 2000, timeout: 20 } +locationModule.getLocation({ maximumAge: 30000, timeout: 0 }).then(function (location) { + console.log('Location received: ' + location); +}).fail(function (error) { + console.log('Location error received: ' + error); +}); + +``` diff --git a/location/Location.md b/location/Location.md new file mode 100644 index 000000000..6126f7722 --- /dev/null +++ b/location/Location.md @@ -0,0 +1,24 @@ +## Class: "location".Location +A data class that encapsulates common properties for a geolocation. + +##### Instance Properties + - **latitude** - _Number_. + The latitude of the geolocation, in degrees. + - **longitude** - _Number_. + The longitude of the geolocation, in degrees. + - **altitude** - _Number_. + The altitude (if available), in meters above sea level. + - **horizontalAccuracy** - _Number_. + The horizontal accuracy, in meters. + - **verticalAccuracy** - _Number_. + The vertical accuracy, in meters. + - **speed** - _Number_. + The speed, in meters/second over ground. + - **direction** - _Number_. + The direction (course), in degrees. + - **timestamp** - _Date_. + The time at which this location was determined. + - **android** - _Location_. + The android-specific location object. + - **ios** - _CLLocation_. + The ios-specific location object. \ No newline at end of file diff --git a/location/LocationManager.md b/location/LocationManager.md new file mode 100644 index 000000000..be5b5781e --- /dev/null +++ b/location/LocationManager.md @@ -0,0 +1,38 @@ +## Class: "location".LocationManager +Provides methods for querying geolocation (in case available) on the target platform. + +##### Static Functions + - **isEnabled()** _Boolean_ + Checks whether the location services are switched ON for this device (on Android) or application (iOS). + - _**return**_ - _Boolean_ + - **distance(** loc1 [_Location_](../location/Location.md), loc2 [_Location_](../location/Location.md) **)** _Number_ + Measures the distance in meters between two locations. + - **loc1** - [_Location_](../location/Location.md) + The first location. + - **loc2** - [_Location_](../location/Location.md) + The second location. + - _**return**_ - _Number_ + +##### Instance Properties + - **desiredAccuracy** - _Number_. + The desired accuracy in meters. Defaults to DesiredAccuracy.HIGH + - **updateDistance** - _Number_. + The update distance filter in meters. Specifies how often to update. Default on iOS is no filter, on Android it is 0 meters. + - **minimumUpdateTime** - _Number_. + The minimum time interval between subsequent location updates, in milliseconds (ignored on iOS). + - **isStarted** - _Boolean_. + True if the location listener is already started. In this case all other start requests will be ignored. + - **lastKnownLocation** - [_Location_](../location/Location.md). + Returns last known location from device's location services or null of no known last location. + +##### Instance Functions + - **startLocationMonitoring(** onLocation _Function_..., onError? _Function_..., options? [_Options_](../location/Options.md) **)** + Starts location monitoring. + - **onLocation** - _Function_(location [_Location_](../location/Location.md)) _Object_ + A function that will be called upon every location update received. + - **onError** - _(optional)_ - _Function_(error _Error_) _Object_ + An optional error callback. + - **options** - _(optional)_ - [_Options_](../location/Options.md) + An optional object specifying location update settings. + - **stopLocationMonitoring()** + Stops location monitoring. \ No newline at end of file diff --git a/location/Options.md b/location/Options.md new file mode 100644 index 000000000..0b063f208 --- /dev/null +++ b/location/Options.md @@ -0,0 +1,14 @@ +## Object: "location".Options +Provides options for location monitoring. + +##### Properties + - **desiredAccuracy** - _(optional)_ - _Number_. + Specifies desired accuracy in meters. Defaults to DesiredAccuracy.HIGH + - **updateDistance** - _(optional)_ - _Number_. + Update distance filter in meters. Specifies how often to update. Default on iOS is no filter, on Android it is 0 meters + - **minimumUpdateTime** - _(optional)_ - _Number_. + Minimum time interval between location updates, in milliseconds (ignored on iOS) + - **maximumAge** - _(optional)_ - _Number_. + how old locations to receive in ms. + - **timeout** - _(optional)_ - _Number_. + how long to wait for a location in ms. \ No newline at end of file diff --git a/location/README.md b/location/README.md new file mode 100644 index 000000000..eeb8bdb0e --- /dev/null +++ b/location/README.md @@ -0,0 +1,31 @@ +# Module: "location" + +``` JavaScript +// To import the "location" module: +var location = require("location"); +``` + +**[How to "location"](HOW-TO.md)** + + +Class | Description +------|------------ +[Location](../location/Location.md) | A data class that encapsulates common properties for a geolocation. +[LocationManager](../location/LocationManager.md) | Provides methods for querying geolocation (in case available) on the target platform. + +Enum | Description +------|------------ +[Accuracy](../location/Accuracy.md) | Specifies common accuracy values. + +Object | Description +------|------------ +[Options](../location/Options.md) | Provides options for location monitoring. + +##### Functions + - **getLocation(** options? [_Options_](../location/Options.md) **)** [_Promise_](../promises/Promise.md)... + Fires a single shot location search. If you specify timeout in options, location search will fail on timeout. +If you specify timeout = 0 it just requests the last known location. +However if you specify maximumAge and the location received is older it won't be received. + - **options** - _(optional)_ - [_Options_](../location/Options.md) + An optional object specifying location update settings. + - _**return**_ - [_Promise_](../promises/Promise.md) of [_Location_](../location/Location.md) \ No newline at end of file diff --git a/nginx-setup.sh b/nginx-setup.sh new file mode 100644 index 000000000..810ef091d --- /dev/null +++ b/nginx-setup.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e + +SCRIPT_PATH="$( cd "$(dirname "$0")" ; pwd -P )" +NGINX_CONFIG=$SCRIPT_PATH"/bin/site/nginx.conf" + +cp $NGINX_CONFIG /etc/nginx +nginx diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 000000000..cea33a32f --- /dev/null +++ b/nginx.conf @@ -0,0 +1,221 @@ +worker_processes auto; + +events { + worker_connections 768; +} + +http { + include mime.types; + default_type application/octet-stream; + sendfile on; + keepalive_timeout 65; + gzip on; + gzip_disable "msie6"; + + server { + listen 9192 default_server; + listen [::]:9192 default_server; + + set $should_redirect 0; + if ($http_x_forwarded_proto) { + set $should_redirect 1; + } + + if ($http_x_forwarded_proto != 'https') { + set $should_redirect "${should_redirect}1"; + } + + set $hsts ""; + if ($http_x_forwarded_proto = 'https') { + set $hsts "max-age=31536000; includeSubDomains"; + } + + if ($should_redirect = 11) { + return 301 https://$host$request_uri; + } + + root /www/docs/build/bin/site; + + add_header Strict-Transport-Security $hsts always; + + server_name _; + set $host_and_port $host:$server_port; + set $proto http; + if ($http_x_forwarded_proto = "https") { + set $proto https; + set $host_and_port $host; + } + + rewrite ^/$ /start/landing.html last; + + rewrite ^/(.*)/$ $proto://$host_and_port/$1/start/landing.html permanent; + + {% for directory in site.redirect_directories %} + rewrite ^/{{ directory.path }}/?$ $proto://$host_and_port/{{ directory.url }} permanent; + {% endfor %} + + {% for page in site.redirect_pages %} + {% for redirect in page.previous_url %} + rewrite ^/{{ redirect | remove_first: '/' }}(\.html)?$ $proto://$host_and_port/{{ page.url | remove_first: '/' | replace: '.html', '' }} permanent; + {% endfor %} + {% endfor %} + + rewrite ^/vuejs$ $proto://$host_and_port/vuejs/nativescript-vuejs permanent; + + # Redirect old api reference + rewrite (?i)/apireference/(.*)$ $proto://$host_and_port/api-reference permanent; + rewrite ^/api-reference$ $proto://$host_and_port/api-reference/globals permanent; + rewrite ^/angular/api-reference/(.*) $proto://$host_and_port/api-reference/$1 permanent; + rewrite ^/angular/ns-ui-api-reference/(.*) $proto://$host_and_port/ns-ui-api-reference/$1 permanent; + rewrite ^/vuejs/ns-ui-api-reference/(.*) $proto://$host_and_port/ns-ui-api-reference/$1 permanent; + rewrite ^(/.*)?/ns-ui-api-reference$ $proto://$host_and_port/ns-ui-api-reference/globals permanent; + rewrite ^(/.*)?/ng-api-reference$ $proto://$host_and_port/ng-api-reference/globals permanent; + + # Redirect runtimes under core concepts + rewrite ^(/angular)?/runtimes/android/generator(.*)$ $proto://$host_and_port$1/core-concepts/android-runtime/binding-generator$2 permanent; + rewrite ^(/angular)?/runtimes/android/(.*) $proto://$host_and_port$1/core-concepts/android-runtime/$2 permanent; + rewrite ^/angular/runtimes/ios/how-to/Use-Native-Libraries$ $proto://$host_and_port/angular/plugins/Use-Native-iOS-Libraries permanent; + rewrite ^/runtimes/ios/how-to/Use-Native-Libraries$ $proto://$host_and_port/plugins/Use-Native-iOS-Libraries permanent; + rewrite ^(/angular)?/runtimes/ios/(.*) $proto://$host_and_port$1/core-concepts/ios-runtime/$2 permanent; + rewrite ^(/angular)?/runtimes/require$ $proto://$host_and_port$1/core-concepts/commonjs-modules permanent; + rewrite ^(/angular)?/core-concepts/project-structure$ $proto://$host_and_port$1/core-concepts/project-structure-app permanent; + + # Redirect CLI docs under Tooling + rewrite ^(/angular)?/docs-cli/(.*) $proto://$host_and_port$1/tooling/docs-cli/$2 permanent; + rewrite ^(/angular)?/tooling/docs-cli/cloud/setup $proto://$host_and_port$1/tooling/docs-cli/cloud/cloud-setup permanent; + + # Redirect the Cookbook under UI Widgets + rewrite ^/cookbook/ui/layouts/(.*) $proto://$host_and_port/ui/layouts/layout-containers permanent; + rewrite ^/cookbook/ui/(.*) $proto://$host_and_port/ui/ns-ui-widgets/$1 permanent; + + # Redirect "Using Plugins" article + rewrite ^/plugins/plugins $proto://$host_and_port/core-concepts/plugins permanent; + rewrite ^/plugins/CocoaPods $proto://$host_and_port/plugins/cocoapods permanent; + + # Redirect "How It Works" article + rewrite ^/start/how-it-works $proto://$host_and_port/core-concepts/technical-overview permanent; + + # Redirect Chrome DevTools article + rewrite ^(/angular)?/tooling/chrome-devtools $proto://$host_and_port$1/tooling/debugging/chrome-devtools permanent; + rewrite ^(/angular)?/tooling/app-templates $proto://$host_and_port$1/app-and-screen-templates/app-templates permanent; + + # Redirect Layout containers article + rewrite ^(/angular)?/ui/layout-containers$ $proto://$host_and_port$1/ui/layouts/layout-containers permanent; + rewrite ^(/angular)?/ui/layouts$ $proto://$host_and_port$1/ui/layouts/layouts permanent; + + # Redirect common screens section && app-and-screen-templates + rewrite ^/angular/app-and-screen-templates/common-screens/(.*) $proto://$host_and_port/angular/ui/components permanent; + rewrite ^(/angular)?/app-and-screen-templates/app-templates $proto://$host_and_port$1/app-templates/app-templates permanent; + + # Redirect publishing related articles + rewrite ^(/angular)?/publishing/android-abi-split $proto://$host_and_port$1/tooling/publishing/android-abi-split permanent; + rewrite ^(/angular)?/publishing/publishing-android-apps $proto://$host_and_port$1/tooling/publishing/publishing-android-apps permanent; + rewrite ^(/angular)?/publishing/publishing-ios-apps $proto://$host_and_port$1/tooling/publishing/publishing-ios-apps permanent; + rewrite ^(/angular)?/publishing/creating-launch-screens-ios $proto://$host_and_port$1/tooling/publishing/creating-launch-screens-ios permanent; + rewrite ^(/angular)?/publishing/creating-launch-screens-android $proto://$host_and_port$1/tooling/publishing/creating-launch-screens-android permanent; + + # Redirect Code Sharing story to Angular flavour + rewrite ^/code-sharing/intro $proto://$host_and_port/angular/code-sharing/intro permanent; + + # Redirect Lazy Loading article to Angular flavour + rewrite ^/performance-optimizations/lazy-loading $proto://$host_and_port/angular/performance-optimizations/lazy-loading permanent; + + # Redirect Angular Navigation article to Angular flavour + rewrite ^/core-concepts/angular-navigation $proto://$host_and_port/angular/core-concepts/angular-navigation permanent; + + # Redirect removed article to the Code Sharing intro + rewrite ^/angular/code-sharing/platform-specific-components $proto://$host_and_port/angular/code-sharing/intro permanent; + + # Redirect base Angular link + rewrite ^/angular$ $proto://$host_and_port/angular/start/introduction permanent; + rewrite ^/angular/start/how-it-works$ $proto://$host_and_port/angular/core-concepts/technical-overview permanent; + rewrite ^/angular/start/troubleshooting$ $proto://$host_and_port/angular/troubleshooting permanent; + rewrite ^/angular/core-concepts/navigation$ $proto://$host_and_port/angular/core-concepts/angular-navigation permanent; + rewrite ^/start/troubleshooting$ $proto://$host_and_port/troubleshooting permanent; + + # Redirect Angular Code Samples to UI Widgets + rewrite ^/angular/code-samples/ui/(.*) $proto://$host_and_port/angular/ui/ng-ui-widgets/$1 permanent; + rewrite ^/angular/code-samples/ui/layouts $proto://$host_and_port/angular/ui/layouts/layout-containers permanent; + rewrite ^/angular/code-samples/overview $proto://$host_and_port/angular/ui/ng-ui-widgets/action-bar permanent; # page doesn't exist, redirect to first UI widget + rewrite ^/angular/code-samples/modal-page $proto://$host_and_port/angular/ui/ng-ui-widgets/modal-page permanent; + rewrite ^/angular/ui/modal-view-ng $proto://$host_and_port/angular/ui/ng-components/modal-view-ng permanent; + rewrite ^/angular/ui/ng-ui-widgets/(.*) $proto://$host_and_port/angular/ui/ng-components/$1 permanent; + + rewrite ^/angular/ui/ng-components/ng-ListView/(.*) $proto://$host_and_port/angular/ui/ng-components/RadListView/$1 permanent; + rewrite ^/angular/ui/professional-ui-components/(.*) $proto://$host_and_port/angular/ui/ng-components/$1 permanent; + rewrite ^/angular/ui/professional-ui-components/ng-ListView$ $proto://$host_and_port/angular/ui/ng-components/ng-RadListView permanent; + rewrite ^/angular/code-samples/camera $proto://$host_and_port/angular/ng-hardware-access/camera permanent; + rewrite ^/angular/code-samples/location $proto://$host_and_port/angular/ng-hardware-access/location permanent; + rewrite ^/angular/ng-hardware-access/camera https://github.com/NativeScript/nativescript-camera/blob/master/README.md permanent; + rewrite ^/angular/ng-hardware-access/location https://github.com/NativeScript/nativescript-geolocation/blob/master/README.md permanent; + + rewrite ^/ui/list-view$ $proto://$host_and_port/angular/ui/ng-ui-widgets/listview permanent; + rewrite ^/listview$ $proto://$host_and_port/angular/ui/ng-ui-widgets/listview permanent; + + rewrite ^(/angular)?/ui/rich-components$ $proto://$host_and_port$1/ui/professional-ui-components/overview permanent; + rewrite ^(/angular)?/ui/professional-ui-components/migration$ $proto://$host_and_port/5-4/$1/ui/professional-ui-components/migration; + rewrite ^(/angular)?/ui/professional-ui-components/getting-started$ $proto://$host_and_port$1/ui/overview permanent; + rewrite ^(/angular)?/ui/professional-ui-components/overview$ $proto://$host_and_port$1/ui/overview permanent; + rewrite ^/angular/ui/ng-components/overview$ $proto://$host_and_port/angular/ui/overview permanent; + # rewrite ^/angular/ui/(.*) $proto://$host_and_port/angular/ui/components/ permanent; + + # Redirect Angular Code Samples (that were outside UI section) + rewrite ^/cookbook/formatted-string-ng $proto://$host_and_port/angular/ng-framework-modules/formatted-string permanent; + rewrite ^/angular/cookbook/formatted-string-ng $proto://$host_and_port/angular/ng-framework-modules/formatted-string permanent; + rewrite ^/angular/(cookbook|code-samples)/(application-settings|application|color|connectivity|file-system|fps-meter|http|platform|routing|timer|trace) $proto://$host_and_port/angular/ng-framework-modules/$2 permanent; + + # Redirect the Cookbook under Framework Modules + rewrite ^/cookbook/(trace|application-settings|application|color|connectivity|console|fetch|file-system|formatted-string|formatted-string-ng|fps-meter|http|image-source|platform|timer|xml-parser) $proto://$host_and_port/ns-framework-modules/$1 permanent; + rewrite ^/cookbook/data/observable $proto://$host_and_port/ns-framework-modules/observable permanent; + rewrite ^/cookbook/data/observable-array $proto://$host_and_port/ns-framework-modules/observable-array permanent; + rewrite ^/cookbook/data/virtual-array $proto://$host_and_port/ns-framework-modules/virtual-array permanent; + rewrite ^/ui/components/overview$ $proto://$host_and_port/ui/overview permanent; + rewrite ^/ui/modal-view $proto://$host_and_port/ui/components/modal-view permanent; + rewrite ^/ui/ns-ui-widgets/(.*) $proto://$host_and_port/ui/components/$1 permanent; + rewrite ^/ui/components/ListView/(.*) $proto://$host_and_port/ui/components/RadListView/$1 permanent; + rewrite ^/ui/professional-ui-components/(.*) $proto://$host_and_port/ui/components/$1 permanent; + rewrite ^/ui/professional-ui-components/ListView$ $proto://$host_and_port/ui/components/RadListView permanent; + rewrite ^/hardware/camera https://github.com/NativeScript/nativescript-camera/blob/master/README.md permanent; + rewrite ^/hardware/location https://github.com/NativeScript/nativescript-geolocation/blob/master/README.md permanent; + + # Redirect the Best Practices articles + rewrite ^(/angular)?/best-practices/(bundling-with-webpack|startup-times|images-optimisations) $proto://$host_and_port$1/performance-optimizations/$2 permanent; + rewrite ^(/angular)?/best-practices/(wire-backend|architecture-choice) $proto://$host_and_port$1/guides/$2 permanent; + + rewrite ^(/angular)?/integration-with-existing-ios-and-android-apps/extend-existing-android-app $proto://$host_and_port$1/guides/integration-with-existing-ios-and-android-apps/extend-existing-android-app permanent; + rewrite ^(/angular)?/integration-with-existing-ios-and-android-apps/extend-existing-ios-app $proto://$host_and_port$1/guides/integration-with-existing-ios-and-android-apps/extend-existing-ios-app permanent; + + rewrite ^/angular/best-practices/bundling-with-webpack $proto://$host_and_port/angular/performance-optimizations/bundling-with-webpack permanent; + + # Redirect the Angular Groceries tutorial to proper "Get Started" subsections + rewrite ^/(angular|start)/tutorial/ng-chapter-\d$ $proto://$host_and_port/angular/start/introduction permanent; + rewrite ^/tutorial/ng-chapter-\d$ $proto://$host_and_port/start/introduction permanent; + rewrite ^(/angular)?/start/hello-world/ng-chapter-0 $proto://$host_and_port$1/start/introduction permanent; + rewrite ^(/angular)?/start/hello-world/ng-chapter-1 $proto://$host_and_port$1/start/introduction permanent; + + # Redirect duplicate Icon Fonts aerticle to the updated UI examples + rewrite ^/ui/icon-fonts $proto://$host_and_port/ui/components/icon-fonts permanent; + rewrite ^/angular/ui/icon-fonts $proto://$host_and_port/angular/ui/ng-components/icon-fonts permanent; + rewrite ^(/angular)?/ui/ns-ui-widgets/icon-fonts $proto://$host_and_port$1/ui/icon-fonts permanent; + + # Redirect the JavaScript Groceries tutorial links + rewrite ^/start/getting-started $proto://$host_and_port/start/introduction permanent; + rewrite ^/start/tutorial/chapter-\d$ $proto://$host_and_port/start/introduction permanent; + rewrite ^/tutorial/chapter-\d$ $proto://$host_and_port/start/introduction permanent; + + # Redirect .html extension + rewrite ^/(.*)\.html$ $proto://$host_and_port/$1 permanent; + + # Remove trailing slash + rewrite ^/(.*)/$ $proto://$host_and_port/$1 permanent; + + location / { + try_files $uri $uri.html $uri/index.html @extensionless-html =404; + } + + location @extensionless-html { + rewrite ^(.*)$ $1.html last; + } + } +} + diff --git a/ns_ui_docs/gulpfile.js b/ns_ui_docs/gulpfile.js new file mode 100644 index 000000000..031a51188 --- /dev/null +++ b/ns_ui_docs/gulpfile.js @@ -0,0 +1,35 @@ +var gulp = require('gulp'); +var typedoc = require('gulp-typedoc'); +const shell = require('gulp-shell') +gulp.task("snippet-mdinject", shell.task('mdinject --root=./../../../nativescript-ui-samples --docsroot=./../../docs/ui/components --sourceext=".ts|.js|.xml|.css" --snippettitles="TypeScript|JavaScript|XML|CSS"')); +gulp.task("snippet-mdinject-ng", shell.task('mdinject --root=./../../../nativescript-ui-samples-angular --docsroot=./../../docs/ui/ng-components --sourceext=".ts|.js|.html|.css" --snippettitles="TypeScript|JavaScript|HTML|CSS"')); +gulp.task("snippet-mdinject-vue", shell.task('mdinject --root=./../../../nativescript-ui-samples-vue --docsroot=./../../vuejs-docs/ns-ui --sourceext=".ts|.js|.xml|.css" --snippettitles="TypeScript|JavaScript|XML|CSS"')); + +gulp.task("ns-ui-api-ref-build", function () { + return gulp + .src(["./node_modules/nativescript-ui-listview/{index,angular/index,angular/*-directives}.d.ts", + "./node_modules/nativescript-ui-autocomplete/{index,angular/index,angular/*-directives}.d.ts", + "./node_modules/nativescript-ui-dataform/{index,angular/index,angular/*-directives}.d.ts", + "./node_modules/nativescript-ui-chart/{index,angular/index,angular/*-directives}.d.ts", + "./node_modules/nativescript-ui-calendar/{index,angular/index,angular/*-directives}.d.ts", + "./node_modules/nativescript-ui-gauge/{index,angular/index,angular/*-directives}.d.ts", + "./node_modules/nativescript-ui-sidedrawer/{index,angular/index,angular/*-directives}.d.ts"]) + .pipe(typedoc({ + // TypeScript options (see typescript docs) + module: "commonjs", + mode: "file", + target: "es5", + includeDeclarations: true, + excludeExternals: true, + + // Output options (see typedoc docs) + out: "./ns-ui-api-reference", + // TypeDoc options (see typedoc docs) + name: "Progress NativeScript UI API", + ignoreCompilerErrors: true, + theme: "./node_modules/nativescript-typedoc-theme", + readme: "./README.md" + })); +}); + +gulp.task("default", gulp.series("snippet-mdinject", "snippet-mdinject-ng", "snippet-mdinject-vue", "ns-ui-api-ref-build")); \ No newline at end of file diff --git a/ns_ui_docs/package.json b/ns_ui_docs/package.json new file mode 100644 index 000000000..de337015e --- /dev/null +++ b/ns_ui_docs/package.json @@ -0,0 +1,22 @@ +{ + "name": "nativescript-ui-build-environment", + "version": "1.0.0", + "author": "Progress AD", + "dependencies": { + "gulp": "4.0.0", + "gulp-shell": "^0.7.0", + "gulp-typedoc": "2.2.1", + "markdown-snippet-injector": "^0.2.2", + "nativescript-typedoc-theme": "git://github.com/NativeScript/nativescript-typedoc-theme.git#master", + "nativescript-ui-autocomplete": "*", + "nativescript-ui-calendar": "*", + "nativescript-ui-chart": "*", + "nativescript-ui-dataform": "*", + "nativescript-ui-gauge": "*", + "nativescript-ui-listview": "*", + "nativescript-ui-sidedrawer": "*", + "@angular/core": "*", + "@nativescript/core": "*", + "typedoc": "0.14.2" + } +} diff --git a/promises/Deferred.md b/promises/Deferred.md new file mode 100644 index 000000000..beb9a596b --- /dev/null +++ b/promises/Deferred.md @@ -0,0 +1,27 @@ +## Object: "promises".Deferred +_Type parameters:_ _**Value**_ +_Extends:_ [_PromiseState_](../promises/PromiseState.md) of _Value_ +Deferred<Value> supports the explicit resolving and rejecting of the +promise and the registration of fulfillment handlers. +A Deferred<Value> should be only visible to the function that initially sets up +an asynchronous process. Callers of that function should only see the Promise<Value> that +is returned by promise(). + +##### Functions + - **promise()** [_Promise_](../promises/Promise.md)... + - _**return**_ - [_Promise_](../promises/Promise.md) of _Value_ + - **resolve(** result? _Value_ **)** [_Deferred_](../promises/Deferred.md)... + - **result** - _(optional)_ - _Value_ + - _**return**_ - [_Deferred_](../promises/Deferred.md) of _Value_ + - **reject(** err [_Rejection_](../promises/Rejection.md) **)** [_Deferred_](../promises/Deferred.md)... + - **err** - [_Rejection_](../promises/Rejection.md) + - _**return**_ - [_Deferred_](../promises/Deferred.md) of _Value_ + - **done(** f _Function_... **)** [_Deferred_](../promises/Deferred.md)... + - **f** - _Function_(v _Value_) + - _**return**_ - [_Deferred_](../promises/Deferred.md) of _Value_ + - **fail(** f _Function_... **)** [_Deferred_](../promises/Deferred.md)... + - **f** - _Function_(err [_Rejection_](../promises/Rejection.md)) + - _**return**_ - [_Deferred_](../promises/Deferred.md) of _Value_ + - **always(** f _Function_... **)** [_Deferred_](../promises/Deferred.md)... + - **f** - _Function_(v _Value_, err [_Rejection_](../promises/Rejection.md)) + - _**return**_ - [_Deferred_](../promises/Deferred.md) of _Value_ \ No newline at end of file diff --git a/promises/Generator.md b/promises/Generator.md new file mode 100644 index 000000000..b13c707dd --- /dev/null +++ b/promises/Generator.md @@ -0,0 +1,3 @@ +## Object: "promises".Generator +_Type parameters:_ _**E**_ +Promise Generators and Iterators. \ No newline at end of file diff --git a/promises/Iterator.md b/promises/Iterator.md new file mode 100644 index 000000000..1b854bbec --- /dev/null +++ b/promises/Iterator.md @@ -0,0 +1,9 @@ +## Object: "promises".Iterator +_Type parameters:_ _**E**_ + +##### Properties + - **current** - _E_. + +##### Functions + - **advance()** [_Promise_](../promises/Promise.md)... + - _**return**_ - [_Promise_](../promises/Promise.md) of _Boolean_ \ No newline at end of file diff --git a/promises/Promise.md b/promises/Promise.md new file mode 100644 index 000000000..85146387a --- /dev/null +++ b/promises/Promise.md @@ -0,0 +1,36 @@ +## Object: "promises".Promise +_Type parameters:_ _**Value**_ +_Extends:_ [_PromiseState_](../promises/PromiseState.md) of _Value_ +A Promise<Value> supports basic composition and registration of handlers that are called when the +promise is fulfilled. +When multiple handlers are registered with done(), fail(), or always(), they are called in the +same order. + +##### Functions + - **then(** f _Function_... **)** [_Promise_](../promises/Promise.md)... + _Types Parameters:_ _**T2**_ + Returns a promise that represents a promise chain that consists of this +promise and the promise that is returned by the function provided. +The function receives the value of this promise as soon it is resolved. +If this promise fails, the function is never called and the returned promise +will also fail. + - **f** - _Function_(v _Value_) [_Promise_](../promises/Promise.md) of _T2_ + - _**return**_ - [_Promise_](../promises/Promise.md) of _T2_ + - **then(** f _Function_... **)** [_Promise_](../promises/Promise.md)... + _Types Parameters:_ _**T2**_ + Returns a promise that represents a promise chain that consists of this +promise and the promise that is returned by the function provided. +The function receives the value of this promise as soon it is resolved. +If this promise fails, the function is never called and the returned promise +will also fail. + - **f** - _Function_(v _Value_) _T2_ + - _**return**_ - [_Promise_](../promises/Promise.md) of _T2_ + - **done(** f _Function_... **)** [_Promise_](../promises/Promise.md)... + - **f** - _Function_(v _Value_) + - _**return**_ - [_Promise_](../promises/Promise.md) of _Value_ + - **fail(** f _Function_... **)** [_Promise_](../promises/Promise.md)... + - **f** - _Function_(err [_Rejection_](../promises/Rejection.md)) + - _**return**_ - [_Promise_](../promises/Promise.md) of _Value_ + - **always(** f _Function_... **)** [_Promise_](../promises/Promise.md)... + - **f** - _Function_(v _Value_, err [_Rejection_](../promises/Rejection.md)) + - _**return**_ - [_Promise_](../promises/Promise.md) of _Value_ \ No newline at end of file diff --git a/promises/PromiseState.md b/promises/PromiseState.md new file mode 100644 index 000000000..3177d7e6a --- /dev/null +++ b/promises/PromiseState.md @@ -0,0 +1,8 @@ +## Object: "promises".PromiseState +_Type parameters:_ _**Value**_ +Both Promise<T> and Deferred<T> share these properties. + +##### Properties + - **status** - [_Status_](../promises/Status.md). + - **result** - _(optional)_ - _Value_. + - **error** - _(optional)_ - [_Rejection_](../promises/Rejection.md). \ No newline at end of file diff --git a/promises/README.md b/promises/README.md new file mode 100644 index 000000000..06a24ca16 --- /dev/null +++ b/promises/README.md @@ -0,0 +1,82 @@ +# Module: "promises" + +``` JavaScript +// To import the "promises" module: +var promises = require("promises"); +``` + +Enum | Description +------|------------ +[Status](../promises/Status.md) | The status of a Promise. Initially a Promise is Unfulfilled and may +change to Rejected or Resolved. +Once a promise is either Rejected or Resolved, it can not change its +status anymore. + +Object | Description +------|------------ +[Rejection](../promises/Rejection.md) | If a promise gets rejected, at least a message that indicates the error or +reason for the rejection must be provided. +[PromiseState](../promises/PromiseState.md) | Both Promise<T> and Deferred<T> share these properties. +[Promise](../promises/Promise.md) | A Promise<Value> supports basic composition and registration of handlers that are called when the +promise is fulfilled. +When multiple handlers are registered with done(), fail(), or always(), they are called in the +same order. +[Deferred](../promises/Deferred.md) | Deferred<Value> supports the explicit resolving and rejecting of the +promise and the registration of fulfillment handlers. +A Deferred<Value> should be only visible to the function that initially sets up +an asynchronous process. Callers of that function should only see the Promise<Value> that +is returned by promise(). +[Generator](../promises/Generator.md) | Promise Generators and Iterators. +[Iterator](../promises/Iterator.md) | + +##### Functions + - **defer()** [_Deferred_](../promises/Deferred.md)... + _Types Parameters:_ _**Value**_ + Module P: Generic Promises for TypeScript +Project, documentation, and license: https://github.com/pragmatrix/Promise +Returns a new "Deferred" value that may be resolved or rejected. + - _**return**_ - [_Deferred_](../promises/Deferred.md) of _Value_ + - **resolve(** v _Value_ **)** [_Promise_](../promises/Promise.md)... + _Types Parameters:_ _**Value**_ + Converts a value to a resolved promise. + - **v** - _Value_ + - _**return**_ - [_Promise_](../promises/Promise.md) of _Value_ + - **reject(** err [_Rejection_](../promises/Rejection.md) **)** [_Promise_](../promises/Promise.md)... + _Types Parameters:_ _**Value**_ + Returns a rejected promise. + - **err** - [_Rejection_](../promises/Rejection.md) + - _**return**_ - [_Promise_](../promises/Promise.md) of _Value_ + - **unfold(** unspool _Function_..., seed _Seed_ **)** [_Promise_](../promises/Promise.md)... + _Types Parameters:_ _**Seed**_, _**Element**_ + http://en.wikipedia.org/wiki/Anamorphism +Given a seed value, unfold calls the unspool function, waits for the returned promise to be resolved, and then +calls it again if a next seed value was returned. +All the values of all promise results are collected into the resulting promise which is resolved as soon +the last generated element value is resolved. + - **unspool** - _Function_(current _Seed_) { promise: [_Promise_](../promises/Promise.md) of _Element_, next: _Seed_ } + - **seed** - _Seed_ + - _**return**_ - [_Promise_](../promises/Promise.md) of Array of _Element_ + - **when(** ...promises Array of [_Promise_](../promises/Promise.md)... **)** [_Promise_](../promises/Promise.md)... + Creates a promise that gets resolved when all the promises in the argument list get resolved. +As soon one of the arguments gets rejected, the resulting promise gets rejected. +If no promises were provided, the resulting promise is immediately resolved. + - **...promises** - Array of [_Promise_](../promises/Promise.md) of _Object_ + - _**return**_ - [_Promise_](../promises/Promise.md) of Array of _Object_ + - **generator(** g _Function_... **)** [_Generator_](../promises/Generator.md)... + _Types Parameters:_ _**E**_ + - **g** - _Function_() _Function_() [_Promise_](../promises/Promise.md) of _E_ + - _**return**_ - [_Generator_](../promises/Generator.md) of _E_ + - **iterator(** f _Function_... **)** [_Iterator_](../promises/Iterator.md)... + _Types Parameters:_ _**E**_ + - **f** - _Function_() [_Promise_](../promises/Promise.md) of _E_ + - _**return**_ - [_Iterator_](../promises/Iterator.md) of _E_ + - **each(** gen [_Generator_](../promises/Generator.md)..., f _Function_... **)** [_Promise_](../promises/Promise.md)... + _Types Parameters:_ _**E**_ + Iterator functions. + - **gen** - [_Generator_](../promises/Generator.md) of _E_ + - **f** - _Function_(e _E_) + - _**return**_ - [_Promise_](../promises/Promise.md) of {} + - **isUndefined(** v _Object_ **)** _Boolean_ + std + - **v** - _Object_ + - _**return**_ - _Boolean_ \ No newline at end of file diff --git a/promises/Rejection.md b/promises/Rejection.md new file mode 100644 index 000000000..d030dc556 --- /dev/null +++ b/promises/Rejection.md @@ -0,0 +1,6 @@ +## Object: "promises".Rejection +If a promise gets rejected, at least a message that indicates the error or +reason for the rejection must be provided. + +##### Properties + - **message** - _String_. \ No newline at end of file diff --git a/promises/Status.md b/promises/Status.md new file mode 100644 index 000000000..7286992a2 --- /dev/null +++ b/promises/Status.md @@ -0,0 +1,8 @@ +## Enum: "promises".Status +The status of a Promise. Initially a Promise is Unfulfilled and may +change to Rejected or Resolved. +Once a promise is either Rejected or Resolved, it can not change its +status anymore. + - **Unfulfilled** = **0** + - **Rejected** = **1** + - **Resolved** = **2** \ No newline at end of file diff --git a/site-container/Dockerfile b/site-container/Dockerfile new file mode 100644 index 000000000..096322344 --- /dev/null +++ b/site-container/Dockerfile @@ -0,0 +1,14 @@ +FROM nginx:alpine + +RUN rm -rf /usr/share/nginx/html/* + +ADD site /usr/share/nginx/html + +ADD site/nginx.conf /etc/nginx + +RUN rm /etc/nginx/conf.d/default.conf \ + && echo "online" > /usr/share/nginx/html/_status.txt \ + && rm /usr/share/nginx/html/nginx.conf \ + && sed -i -e 's/\/www\/docs\/build\/bin\/site/\/usr\/share\/nginx\/html/g' /etc/nginx/nginx.conf + +EXPOSE 9192 diff --git a/site-container/build.sh b/site-container/build.sh new file mode 100644 index 000000000..c89b98959 --- /dev/null +++ b/site-container/build.sh @@ -0,0 +1,23 @@ +#!/bin/bash +set -e + +VER=${Version:-`cd docs && git describe --abbrev=0 && cd ..`} +DOCKER_IMAGE_URL=${DOCKER_IMAGE_URL:-"default-ns-docs"} + +echo "Start building docker image $DOCKER_IMAGE_URL (v$VER)" + +echo ">>> site-container (v$VER) > build.sh > step 1" +docker build -t ns-docs-build:$VER docs/build +echo ">>> site-container (v$VER) > build.sh > step 2" +docker run --rm -v $(pwd):/root --entrypoint "/bin/bash" -t ns-docs-build:$VER -c "/root/docs/build/build-docs.sh SKIP_SITEMAP_GENERATOR_REMOVAL && cp /root/docs/build/site-container/Dockerfile /root/docs/build/bin" +echo ">>> site-container (v$VER) > build.sh > step 3" +docker run --rm -v $(pwd):/root --entrypoint "/bin/bash" -t ns-docs-build:$VER -c "rm -rf ~/.npm ~/.bundle" +echo ">>> site-container (v$VER) > build.sh > step 4" +docker rmi ns-docs-build:$VER + +# echo ">>> site-container (v$VER) > build.sh > step 5" +# docker build -t $DOCKER_IMAGE_URL docs/build/bin + +echo ">>> site-container (v$VER) > build.sh > done" +# docker push $DOCKER_IMAGE_URL +# docker rmi $DOCKER_IMAGE_URL diff --git a/text/README.md b/text/README.md new file mode 100644 index 000000000..19ebe1ba6 --- /dev/null +++ b/text/README.md @@ -0,0 +1,10 @@ +# Module: "text" + +``` JavaScript +// To import the "text" module: +var text = require("text"); +``` + +Namespace | Description +------|------------ +[encoding](../text/encoding/) | \ No newline at end of file diff --git a/text/encoding/README.md b/text/encoding/README.md new file mode 100644 index 000000000..83a750248 --- /dev/null +++ b/text/encoding/README.md @@ -0,0 +1,9 @@ +## Namespace: "text".encoding + +##### Variables + - **ISO_8859_1** - _Object_. + - **US_ASCII** - _Object_. + - **UTF_16** - _Object_. + - **UTF_16BE** - _Object_. + - **UTF_16LE** - _Object_. + - **UTF_8** - _Object_. \ No newline at end of file diff --git a/timer/HOW-TO.md b/timer/HOW-TO.md new file mode 100644 index 000000000..80dd774d0 --- /dev/null +++ b/timer/HOW-TO.md @@ -0,0 +1,40 @@ +# Timer module +``` JavaScript +require("globals"); +// OR +var timer = require("timer"); +``` +### Evaluates an expression after 0 milliseconds. +``` JavaScript +timer.setTimeout(function () { +}); + +``` +### Evaluates an expression after a specified number of milliseconds. +``` JavaScript +timer.setTimeout(function () { +}, 500); + +``` +### Cancels the evaluation with the clearTimeout method. +``` JavaScript +var id = timer.setTimeout(function () { +}, 2000); + +// Clear timeout with specified id. +timer.clearTimeout(id); + +``` +### Evaluates an expression each time a specified number of milliseconds has elapsed. +``` JavaScript +timer.setInterval(function () { +}, 100); + +``` +### Cancel the interval previously started using the setInterval method. +``` JavaScript +var id = timer.setInterval(function () { + timer.clearInterval(id); +}, 100); + +``` diff --git a/update-changelog.sh b/update-changelog.sh new file mode 100644 index 000000000..764a015f8 --- /dev/null +++ b/update-changelog.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -e + +if [[ "$#" -ne "0" && "$#" -ne "2" || ( "$#" -eq "2" && "$1" -ne "changes" ) ]]; then + echo "Invalid arguments. Usage: $0 or $0 changes [branchname]" + exit +fi + +#Fetch the CHANGELOGs from the external repositories and push them to the current branch +[[ "$1" == "changes" ]] && changes="true" || changes="false" + + +if [[ "$changes" == "true" ]]; then + # bin links break on Vagrant with Windows host filesystem. + npm install --no-bin-links + + echo "Updating changelogs. Branch: $2" + grunt default --branch=$2 +fi