diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 000000000..e69de29bb diff --git a/11ty-bundle.js b/11ty-bundle.js new file mode 100644 index 000000000..5171d544f --- /dev/null +++ b/11ty-bundle.js @@ -0,0 +1,435 @@ + +/* ======================================================================== + * Bootstrap: dropdown.js v3.0.0 + * http://twbs.github.com/bootstrap/javascript.html#dropdowns + * ======================================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + + ++function ($) +{ + "use strict"; + + // DROPDOWN CLASS DEFINITION + // ========================= + + var backdrop = '.dropdown-backdrop' + var toggle = '[data-toggle=dropdown]' + var Dropdown = function (element) + { + var $el = $ (element).on ('click.bs.dropdown', this.toggle) + } + + Dropdown.prototype.toggle = function (e) + { + var $this = $ (this) + + if ($this.is ('.disabled, :disabled')) return + + var $parent = getParent ($this) + var isActive = $parent.hasClass ('open') + + clearMenus () + + if (!isActive) + { + if ('ontouchstart' in document.documentElement && !$parent.closest ('.navbar-nav').length) + { + // if mobile we we use a backdrop because click events don't delegate + $ (' + + + + + + + + + + + + diff --git a/cdn-scripts/index.html b/cdn-scripts/index.html new file mode 100644 index 000000000..4f234a658 --- /dev/null +++ b/cdn-scripts/index.html @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/demos/BSPMapGen/index.html b/demos/BSPMapGen/index.html new file mode 100644 index 000000000..9ea7d1114 --- /dev/null +++ b/demos/BSPMapGen/index.html @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

BSPMapGen

+ + + + source code + + +

HaxeFlixel port of Timothy Hely's "Using-BSP-Trees-to-Generate-Game-Maps".

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/BlendModeShaders/index.html b/demos/BlendModeShaders/index.html new file mode 100644 index 000000000..80d8a43b5 --- /dev/null +++ b/demos/BlendModeShaders/index.html @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

BlendModeShaders

+ + + + source code + + +

Example of how some blend modes can be replicated using GLSL shaders.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/Breakout/index.html b/demos/Breakout/index.html new file mode 100644 index 000000000..2df4c2c1c --- /dev/null +++ b/demos/Breakout/index.html @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Breakout

+ + + + source code + + +

A very simple, but solid Breakout clone originally created by Photonstorm (Richard Davey) in 20 minutes.

+ + + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/Calculator/index.html b/demos/Calculator/index.html new file mode 100644 index 000000000..b8a96f906 --- /dev/null +++ b/demos/Calculator/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Calculator

+ + + + source code + + +

An interactive calculator implemented using hscript.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/CollisionAndGrouping/index.html b/demos/CollisionAndGrouping/index.html new file mode 100644 index 000000000..be399a0dd --- /dev/null +++ b/demos/CollisionAndGrouping/index.html @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

CollisionAndGrouping

+ + + + source code + + +

A port of the Collision and Grouping demo by Zachary Tarvit featured on flixel.org/features.

+

Game objects in Flixel are can be stored in FlxGroups. Groups can be added to the game state to help automate and organize updating, drawing, collisions, camera control, scroll amounts, and more. When you want to avoid calling resource-intensive functions like FlxG.collide() more than a few times in each game loop, you can use nested groups as a way to simplify those calls. For example, let's say your game objects are divided into three different groups: Apples, Pears, and Bananas. And you want to see if the fruit have landed on the ground yet. You might be tempted to call FlxG.collide() three times: FlxG.collide(Apples, ground); FlxG.collide(Pears,ground); and so on. However, you can create a fourth group, called simply Fruit, and add each of the other groups to it. Then you can just call FlxG.collide(Fruit, ground); and you should see your performance improve notably.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/Colors/index.html b/demos/Colors/index.html new file mode 100644 index 000000000..9a22f83a1 --- /dev/null +++ b/demos/Colors/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Colors

+ + + + source code + + +

A showcase of the various FlxColor features.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/Cursor/index.html b/demos/Cursor/index.html new file mode 100644 index 000000000..669bf440d --- /dev/null +++ b/demos/Cursor/index.html @@ -0,0 +1,247 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Cursor

+ + + + source code + + +

A demo showcasing keyboard navigation with a flixel-ui instance. You can navigate +between buttons and click on them, as well as change the allowed input methods.

+

Controls:

+

Mouse: Click on stuff +Keyboard:

+
    +
  • TAB: Tab goes forward, Shift+Tab goes back
  • +
  • ARROWS: Arrows for up/down/left/right
  • +
  • WASD: W,A,S,D keys for up/down/left/right
  • +
  • NUMPAD: Numpad(8,4,6,2) keys for up/down/left/right, when NUMLOCK is on
  • +
+

Check "Wrap" to turn wrapping on and off.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/DynamicShadows/index.html b/demos/DynamicShadows/index.html new file mode 100644 index 000000000..a87df5db1 --- /dev/null +++ b/demos/DynamicShadows/index.html @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

DynamicShadows

+ + + + source code + + + + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/EZPlatformer/index.html b/demos/EZPlatformer/index.html new file mode 100644 index 000000000..127134f7d --- /dev/null +++ b/demos/EZPlatformer/index.html @@ -0,0 +1,241 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

EZPlatformer

+ + + + source code + + +

EZPlatformer is a really simple platformer which was originally created by Adam "Atomic" Saltsman as a tutorial for creating platformers with flixel.

+ +

Use WASD / the arrow Keys to move the red square around. Your objective is to collect all coins, at which point an exit appears.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FileBrowse/index.html b/demos/FileBrowse/index.html new file mode 100644 index 000000000..9aeefe84d --- /dev/null +++ b/demos/FileBrowse/index.html @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FileBrowse

+ + + + source code + + +

Demonstrates how to use file browsing on both Flash and Native (CPP/Neko) targets. The Flash target uses FileReference.browse(), while the Native target uses the systools.Dialogs.openFile(). The Native targets depend on the systools library, available on haxelibs.

+

Use the mouse wheel to zoom in and out, or the number keys to use a specific zoom level (1-5).

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/Filters/index.html b/demos/Filters/index.html new file mode 100644 index 000000000..22401da15 --- /dev/null +++ b/demos/Filters/index.html @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Filters

+ + + + source code + + + + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/Flappybalt/index.html b/demos/Flappybalt/index.html new file mode 100644 index 000000000..9c00f2e78 --- /dev/null +++ b/demos/Flappybalt/index.html @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

Flappybalt

+ + + + source code + + +

Controls: Spacebar

+

A cross-platform port of AdamAtomic's Flappybalt, converted to Haxe and HaxeFlixel. You can play this on your Android by downloading it from the Google Play Store if you'd like.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlipRotationAnimationTiles/index.html b/demos/FlipRotationAnimationTiles/index.html new file mode 100644 index 000000000..0ff613dbd --- /dev/null +++ b/demos/FlipRotationAnimationTiles/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlipRotationAnimationTiles

+ + + + source code + + +

This demo showcases how to use FlxTilemapExt and FlxTileSpecial to flip, rotate and animate tiles.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/Flixius/index.html b/demos/Flixius/index.html new file mode 100644 index 000000000..ce8575b4f --- /dev/null +++ b/demos/Flixius/index.html @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

Flixius

+ + + + source code + + +

A side-scrolling shooter. Made by @SeiferTim during a 30-min presentation on how easy it is to make prototypes in HaxeFlixel.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FloodFill/index.html b/demos/FloodFill/index.html new file mode 100644 index 000000000..c03b2f8a8 --- /dev/null +++ b/demos/FloodFill/index.html @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FloodFill

+ + + + source code + + + + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxAction/index.html b/demos/FlxAction/index.html new file mode 100644 index 000000000..eccb162d8 --- /dev/null +++ b/demos/FlxAction/index.html @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

FlxAction

+ + + + source code + + +

Showcases the flixel.input.actions API added in Flixel 4.6.0.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxAsepriteUtil/index.html b/demos/FlxAsepriteUtil/index.html new file mode 100644 index 000000000..fe4be9963 --- /dev/null +++ b/demos/FlxAsepriteUtil/index.html @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

FlxAsepriteUtils

+ + + + source code + + +

Showcases loading of an Aseprite [Sprite Sheet](https://aseprite.com/docs/sprite-sheet/#texture-atlases tools) using flixel.graphics.FlxAsepriteUtil API added in Flixel 5.4.0. This demo uses the loadAseAtlasAndTagsByIndex method to create animations.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxAsyncLoop/index.html b/demos/FlxAsyncLoop/index.html new file mode 100644 index 000000000..b68fce917 --- /dev/null +++ b/demos/FlxAsyncLoop/index.html @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxAsyncLoop

+ + + + source code + + +

Demonstration for the FlxAsyncLoop class, created by SeiferTim (Tim I Hely). +This utility allows you to setup a loop in a way that still allows update() and draw() to be called so you can show progress bars or whatever, instead of the game freezing and locking up until the loop has completed. +This demo will generate 5000 random little squares, showing a progress bar as it does so.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxAtlas/index.html b/demos/FlxAtlas/index.html new file mode 100644 index 000000000..66d0fa8e1 --- /dev/null +++ b/demos/FlxAtlas/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxAtlas

+ + + + source code + + +

An example of flixel.graphics.atlas.FlxAtlas.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxBitmapText/index.html b/demos/FlxBitmapText/index.html new file mode 100644 index 000000000..ae4faad89 --- /dev/null +++ b/demos/FlxBitmapText/index.html @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

FlxBitmapText

+ + + + source code + + + + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxBunnymark/index.html b/demos/FlxBunnymark/index.html new file mode 100644 index 000000000..c870a11c4 --- /dev/null +++ b/demos/FlxBunnymark/index.html @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxBunnyMark

+ + + + source code + + +

This is a HaxeFlixel port of the BunnyMark Benchmark.

+

The initial BunnyMark was created by Iain Lobb (code) and Amanda Lobb (art), then ported to haxe-NME by Joshua Granick, then enhanced by Philippe Elsass, now ported to HaxeFlixel by BeebleRox, and improved by impaler and Gama11.

+

Flash is limited to software rendering so there is a significant performance improvement when you use cpp targets. Cpp targets make use of drawTiles() GPU Acceleration and on a desktop it can display 10 000's of bunnies with additional variations of alpha and scaling. On the flash target however, rendering with alpha and scaling means a severe performance decrease.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxCamera/index.html b/demos/FlxCamera/index.html new file mode 100644 index 000000000..007c69d66 --- /dev/null +++ b/demos/FlxCamera/index.html @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxCamera

+ + + + source code + + +

This demo showcases different flixel camera features like zoom, lerp, lead and follow styles.

+

Demo created by ProG4mr after adding camera features : lerp and lead.

+

For full-window zoom out, look at the commented source code, note that fps drop significantly.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxCaveGenerator/index.html b/demos/FlxCaveGenerator/index.html new file mode 100644 index 000000000..30010e26b --- /dev/null +++ b/demos/FlxCaveGenerator/index.html @@ -0,0 +1,241 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxCaveGenerator

+ + + + source code + + +

A demo showing off the capabilites of FlxCaveGenerator.

+

Generating a cave for a FlxTilemap is really simple:

+
var caveData:String = FlxCaveGenerator.generateCaveString(Width, Height, SmoothingIterations, WallRatio);
+
+

The String generated can be used directly in FlxTilemap's loadMap() method.

+

You can use WASD or the arrow keys to move the little character around. :)

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxClothSprite/index.html b/demos/FlxClothSprite/index.html new file mode 100644 index 000000000..2b058bd9b --- /dev/null +++ b/demos/FlxClothSprite/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxClothSprite

+ + + + source code + + +

An example of flixel.addons.effects.FlxClothSprite.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxCollisions/index.html b/demos/FlxCollisions/index.html new file mode 100644 index 000000000..fd2124d69 --- /dev/null +++ b/demos/FlxCollisions/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxCollisions

+ + + + source code + + +

A port of FlxCollisions created by Adam Atomic, showing off flixel's 2D physics capabilities.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxEffectSprite/index.html b/demos/FlxEffectSprite/index.html new file mode 100644 index 000000000..e3d9e5dfd --- /dev/null +++ b/demos/FlxEffectSprite/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxEffectSprite

+ + + + source code + + +

An example of the flixel.addons.effects.chainable package.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxFSM/index.html b/demos/FlxFSM/index.html new file mode 100644 index 000000000..6c58c3ed9 --- /dev/null +++ b/demos/FlxFSM/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxFSM

+ + + + source code + + +

An example game using the finite state machine implementation in flixel.addons.util.FlxFSM.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxInvaders/index.html b/demos/FlxInvaders/index.html new file mode 100644 index 000000000..985bc40c4 --- /dev/null +++ b/demos/FlxInvaders/index.html @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxInvaders

+ + + + source code + + +

A simple invaders game in flixel originally created by Adam "Atomic" SaltsmanLink to the original GitHub repo. The source code is extremely well documented and thus very hepful for beginners.

+

Controls:

+

Left / right to move and spacebar to shoot.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxLightPuzzle/index.html b/demos/FlxLightPuzzle/index.html new file mode 100644 index 000000000..4ca35d164 --- /dev/null +++ b/demos/FlxLightPuzzle/index.html @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

FlxLightPuzzle

+ + + + source code + + + + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxMouseEvent/index.html b/demos/FlxMouseEvent/index.html new file mode 100644 index 000000000..6df22a850 --- /dev/null +++ b/demos/FlxMouseEvent/index.html @@ -0,0 +1,247 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxMouseEvent

+ + + + source code + + +

FlxMouseEvent allows FlxSprites to listen to mouse events like MouseDown, MouseUp, MouseOver and MouseOut.

+

To activate it, simply add sprites and implement the event callbacks:

+
import flixel.input.mouse.FlxMouseEvent;
+
+var sprite = new FlxSprite();
+FlxMouseEvent.add(sprite, onMouseDown, onMouseUp, onMouseOver, onMouseOut); 
+
+function onMouseDown(sprite:FlxSprite) {}
+function onMouseUp(sprite:FlxSprite) {}
+function onMouseOver(sprite:FlxSprite) {}
+function onMouseOut(sprite:FlxSprite) {}
+
+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxNape/index.html b/demos/FlxNape/index.html new file mode 100644 index 000000000..82ef3038c --- /dev/null +++ b/demos/FlxNape/index.html @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxNape

+ + + + source code + + +

This demo showcases the integration of the Nape Physics Engine with HaxeFlixel.

+

Thanks to ProG4mr for his work with these Demos and his work providing FlxNapeSprite and FlxNapeState. See the flixel-addons repository.

+

Thanks to Henry-T for his amazing CutUp demo!

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxNapeTerrain/index.html b/demos/FlxNapeTerrain/index.html new file mode 100644 index 000000000..c4d2efebf --- /dev/null +++ b/demos/FlxNapeTerrain/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxNapeTerrain

+ + + + source code + + +

A port of Nape's DestructibleTerrain sample to HaxeFlixel.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxNapeTilemap/index.html b/demos/FlxNapeTilemap/index.html new file mode 100644 index 000000000..5142533aa --- /dev/null +++ b/demos/FlxNapeTilemap/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxNapeTilemap

+ + + + source code + + +

An example of flixel.addons.nape.FlxNapeTilemap.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxPexParser/index.html b/demos/FlxPexParser/index.html new file mode 100644 index 000000000..150d5b407 --- /dev/null +++ b/demos/FlxPexParser/index.html @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxPexParser

+ + + + source code + + +

An example of flixel.addons.editors.pex.FlxPexParser. It creates a FlxEmitter from a .pex file created with the Pex Particle Editor.

+

You can drag your mouse to move the fireball.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxPieDial/index.html b/demos/FlxPieDial/index.html new file mode 100644 index 000000000..231645c95 --- /dev/null +++ b/demos/FlxPieDial/index.html @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

FlxPieDial

+ + + + source code + + +

An example of flixel.addons.display.FlxPieDial.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxPongApi/index.html b/demos/FlxPongApi/index.html new file mode 100644 index 000000000..8b07d9939 --- /dev/null +++ b/demos/FlxPongApi/index.html @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

FlxPongApi

+ + + + source code + + +

FlxPongApi demonstrates usage of the FlxGameJolt class in the flixel-addons package, which allows for simple communication with the GameJolt API. The gameplay itself is a sort of roguelike Pong game with various obstacles and enemy types that are encountered as the player progresses. The game is very simple visually, with no art assets and only four colors, with those colors selected programmatically and change very time you play.

+

You can play FlxPongApi on GameJolt here to see all the functions in action. You can view the source code for FlxGameJolt here.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxRandom/index.html b/demos/FlxRandom/index.html new file mode 100644 index 000000000..888ea4ddf --- /dev/null +++ b/demos/FlxRandom/index.html @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxRandom

+ + + + source code + + +

This is simply a collection of functions to test the updated FlxRandom class in HaxeFlixel.

+

The buttons on the right side of the display can be used to run a series of tests relating to each function of FlxRandom. Most of the tests will run the same function many times for benchmarking purposes. Others will compare the new class to the previous FlxRandom (which is stored in the source folder as OldFlxRandom), the new FlxRandom without inline, or pure Math.random().

+

Some tests may take some time to run, please be patient. Note that the 15-second script timeout has been overridden and set to 60 seconds.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxScene/index.html b/demos/FlxScene/index.html new file mode 100644 index 000000000..3025d3c2f --- /dev/null +++ b/demos/FlxScene/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxScene

+ + + + source code + + +

An example of flixel.addons.util.FlxScene.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxShape/index.html b/demos/FlxShape/index.html new file mode 100644 index 000000000..e3921d2f2 --- /dev/null +++ b/demos/FlxShape/index.html @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

FlxShape

+ + + + source code + + +

An example of the flixel.addons.display.shape package.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxSimplex/index.html b/demos/FlxSimplex/index.html new file mode 100644 index 000000000..a71c97a6c --- /dev/null +++ b/demos/FlxSimplex/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxSimplex

+ + + + source code + + +

Showcases flixel.addons.util.FlxSimplex (added in flixel-addons 2.7.0).

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxSkewedSprite/index.html b/demos/FlxSkewedSprite/index.html new file mode 100644 index 000000000..87bf3ce81 --- /dev/null +++ b/demos/FlxSkewedSprite/index.html @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

FlxSkewedSprite

+ + + + source code + + +

This is a demo of the FlxSkewedSprite class by Beeblerox. As you probably guessed, it allows you to skew sprites.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxSnake/index.html b/demos/FlxSnake/index.html new file mode 100644 index 000000000..ff196e198 --- /dev/null +++ b/demos/FlxSnake/index.html @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxSnake

+ + + + source code + + +

A basic snake game in flixel. Originally created by photonstorm, later ported to HaxeFlixel. Has been largely rewritten by Gama11.

+

Controls:

+

Arrow keys or WASD to control the snake's movement.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxSound/index.html b/demos/FlxSound/index.html new file mode 100644 index 000000000..058345600 --- /dev/null +++ b/demos/FlxSound/index.html @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxSound

+ + + + source code + + + + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxSpine/index.html b/demos/FlxSpine/index.html new file mode 100644 index 000000000..49cb35ade --- /dev/null +++ b/demos/FlxSpine/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxSpine

+ + + + source code + + +

This is a demo showing off the use of the FlxSpine class to integrate the Spine bone based animation system into HaxeFlixel.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxSpriteFilters/index.html b/demos/FlxSpriteFilters/index.html new file mode 100644 index 000000000..287280e6d --- /dev/null +++ b/demos/FlxSpriteFilters/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxSpriteFilters

+ + + + source code + + +

This demo shows bitmap filters being applied and updated on FlxSprites using the FlxSpriteFilter class.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxTeroids/index.html b/demos/FlxTeroids/index.html new file mode 100644 index 000000000..9bd35f1c2 --- /dev/null +++ b/demos/FlxTeroids/index.html @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxTeroids

+ + + + source code + + +

FlxTeroids is a simple Asteroids clone. The original GitHub repo by Adam "Atomic" Saltsman can be found here.

+

Controls:

+

Move - Arrow keys

+

Shoot -Space

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxTextFormat/index.html b/demos/FlxTextFormat/index.html new file mode 100644 index 000000000..243a05fe1 --- /dev/null +++ b/demos/FlxTextFormat/index.html @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

FlxTextFormat

+ + + + source code + + +

FlxTextFormats allow the use of different colors, border colors and font weights on the same FlxText.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxTilemapExt/index.html b/demos/FlxTilemapExt/index.html new file mode 100644 index 000000000..59a2222d2 --- /dev/null +++ b/demos/FlxTilemapExt/index.html @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxTilemapExt

+ + + + source code + + +

A demo of the sloped tiles possible by using the FlxTilemapExt class created by Peter Christiansen. The original demo can be found here, the original forum thread is here.

+

Controls:

+

Move - WASD / Arrow keys

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxTrailArea/index.html b/demos/FlxTrailArea/index.html new file mode 100644 index 000000000..d7b3b6591 --- /dev/null +++ b/demos/FlxTrailArea/index.html @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxTrailArea

+ + + + source code + + +

This demo shows the effects that can be accomplished with FlxTrailArea. +For every FlxSprite that is added to the area, a trail effect will be rendered on the area. It's more efficient than a regular FlxTrail due to the fact that it only uses a single bitmap.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxTween/index.html b/demos/FlxTween/index.html new file mode 100644 index 000000000..7cfab11b6 --- /dev/null +++ b/demos/FlxTween/index.html @@ -0,0 +1,282 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxTween

+ + + + source code + + +

HaxeFlixel has advanced tweening built in for interpolation over time.

+

Tweens are a useful part of any framework and its applications are many. It can be game object movements, color changes and even tweening variables over time. The current tween types include:

+
    +
  • VarTween
  • +
  • MultiVarTween
  • +
  • AngleTween
  • +
  • ColorTween
  • +
  • NumTween
  • +
  • LinearMotion
  • +
  • LinearPath
  • +
  • CircularMotion
  • +
  • CubicMotion
  • +
  • QuadMotion
  • +
  • QuadPath
  • +
+

There is also an impressive choice of Ease types for every Tween type to choose from:

+
    +
  • quadIn
  • +
  • quadOut
  • +
  • cubeIn
  • +
  • cubeOut
  • +
  • cubeInOut
  • +
  • quartIn
  • +
  • quartOut
  • +
  • quartInOut
  • +
  • quintIn
  • +
  • quintOut
  • +
  • quintInOut
  • +
  • sineIn
  • +
  • sineOut
  • +
  • sineInOut
  • +
  • bounceIn
  • +
  • bounceOut
  • +
  • bounceInOut
  • +
  • circIn
  • +
  • circOut
  • +
  • circInOut
  • +
  • expoIn
  • +
  • expoOut
  • +
  • expoInOut
  • +
  • backIn
  • +
  • backOut
  • +
  • backInOut
  • +
  • elasticIn
  • +
  • elasticOut
  • +
  • elasticInOut
  • +
+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FlxTypeText/index.html b/demos/FlxTypeText/index.html new file mode 100644 index 000000000..73759a7ff --- /dev/null +++ b/demos/FlxTypeText/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FlxTypeText

+ + + + source code + + +

This demo showcases the effects that can be accomplished with the use of the FlxTypeText class.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/FrameCollections/index.html b/demos/FrameCollections/index.html new file mode 100644 index 000000000..3e8cd00f0 --- /dev/null +++ b/demos/FrameCollections/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

FrameCollections

+ + + + source code + + +

An example of the flixel.graphics.frames package.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/GamepadTest/index.html b/demos/GamepadTest/index.html new file mode 100644 index 000000000..f9786a7a3 --- /dev/null +++ b/demos/GamepadTest/index.html @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

GamepadTest

+ + + + source code + + +

A demo showcasing HaxeFlixel's gamepad support.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/GridMovement/index.html b/demos/GridMovement/index.html new file mode 100644 index 000000000..1999a0d46 --- /dev/null +++ b/demos/GridMovement/index.html @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

GridMovement

+ + + + source code + + +

This showcases a classic retro grid movement.

+

Thanks to BuzzJeux.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/HeatmapPathfinding/index.html b/demos/HeatmapPathfinding/index.html new file mode 100644 index 000000000..282be91bd --- /dev/null +++ b/demos/HeatmapPathfinding/index.html @@ -0,0 +1,242 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

HeatmapPathfinding

+ + + + source code + + +

A demo showcasing an efficient method to have a lot of objects path to one target, using a heatmap. Inspired by this Gamasutra article.

+

Controls:

+
    +
  • Drag objects to place them
  • +
  • Elephants seek the McGuffin when placed
  • +
  • Click to add or remove walls
  • +
+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/MinimalistTD/index.html b/demos/MinimalistTD/index.html new file mode 100644 index 000000000..167640786 --- /dev/null +++ b/demos/MinimalistTD/index.html @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

MinimalistTD

+ + + + source code + + +

As the name would imply, this is a minimalist tower defense game. This was originally created by Gama11 for Ludum Dare 26. You can find the original source code for that here.

+

This was ported to the latest version of HaxeFlixel and OpenFL by Steve Richey.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/Mode/index.html b/demos/Mode/index.html new file mode 100644 index 000000000..d77004f72 --- /dev/null +++ b/demos/Mode/index.html @@ -0,0 +1,242 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Mode

+ + + + source code + + +

"A small (but sadly not that simple) demo game built on the flixel framework" by Adam "Atomic" Saltsman, which has later been ported to HaxeFlixel. You can find the GitHub repo of the original AS3 version here.

+

Controls:

+
    +
  • Arrow keys - Move
  • +
  • X - Jump
  • +
  • C - Shoot
  • +
+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/MosaicEffect/index.html b/demos/MosaicEffect/index.html new file mode 100644 index 000000000..6d5f9f695 --- /dev/null +++ b/demos/MosaicEffect/index.html @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + +
+ +
+
+ +
+ +

MosaicEffect

+ + + + source code + + +

Example of applying a GLSL shader to a FlxSprite to achieve a mosaic / pixelation effect.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/Parallax/index.html b/demos/Parallax/index.html new file mode 100644 index 000000000..5c59f0ce1 --- /dev/null +++ b/demos/Parallax/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Parallax

+ + + + source code + + +

This demo builds several layers of randomized objects (FlxTileblock and FlxSprite) with varying scrollFactor values to achieve a parallax effect when scrolling.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/Particles/index.html b/demos/Particles/index.html new file mode 100644 index 000000000..b52e6911b --- /dev/null +++ b/demos/Particles/index.html @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Particles

+ + + + source code + + +

A port of the Particles Demo by Zachary Tarvit featured on flixel.org/features.

+

In games, "particles" and "particle emitters" refer to a whole class of behaviors that are usually used for special effects and flavor. The "emitter" is the source and manager of the actual "particle" objects that are spewed out and/or floating around. FlxParticle is just an extension of FlxSprite, and FlxEmitter is just an extension of FlxGroup, so a particle system in Flixel isn't really that different from any normal group of sprites. It just adds some special behavior for creating and launching particles, and the particles themselves have some optional, special behavior to bounce more believably in platformer situations. FlxEmitter also has built-in variables that let you specify velocity ranges, rotation speeds, gravity, collision behaviors, and more. 

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/Pathfinding/index.html b/demos/Pathfinding/index.html new file mode 100644 index 000000000..96cf2e354 --- /dev/null +++ b/demos/Pathfinding/index.html @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

Pathfinding

+ + + + source code + + +

A port and improvement of the Pathfinding Demo by Bengsiswanto Hendrawan  featured on flixel.org/features.

+

Pathfinding just means figuring out how to (or if you can) get from A to B. FlxTilemap has a new function FlxTilemap.findPath() which returns a FlxPath object, which is just a collection of "nodes", or FlxPoint objects. Think of it as a list of (X,Y) coordinates in space, going from the starting location to the ending location. Once you have a valid path, you can pass that data to any FlxPath, along with the object it should follow. That function tells the object to start following the path, and you can specify the speed, direction (backward, yoyo, etc), and even tell the object to only follow the path horizontally (handy for objects with gravity applied). These flags mean that you can use paths for more than just character AI - they're also useful for elevators, moving platforms, and looping background animations. 

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/PixelPerfectCollision/index.html b/demos/PixelPerfectCollision/index.html new file mode 100644 index 000000000..c932c27f0 --- /dev/null +++ b/demos/PixelPerfectCollision/index.html @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

PixelPerfectCollision

+ + + + source code + + +

This demo showcases FlxG.pixelPerfectOverlap() / FlxCollision.pixelPerfectCheck().

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/ProjectJumper/index.html b/demos/ProjectJumper/index.html new file mode 100644 index 000000000..16e0e7cdf --- /dev/null +++ b/demos/ProjectJumper/index.html @@ -0,0 +1,298 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

ProjectJumper

+ + + + source code + + +

"Project Jumper" has been created by Chipacabra as a tutorial on developing a platformer game with flixel and has later been ported to Haxe(Flixel).

+

Controls:

+
    +
  • Move - W + A / Left + Right
  • +
  • Shoot - J / X
  • +
  • Jump - L / C
  • +
  • Select entry on the menu - space
  • +
+

The original tutorial series by Chipacabra:

+

Note that this tutorial is was originally written for AS3-Flixel. The concepts are still valid for HaxeFlixel you can see the entire demo was ported to HaxeFlixel to work the same.

+ + + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/RPGInterface/index.html b/demos/RPGInterface/index.html new file mode 100644 index 000000000..bec94c467 --- /dev/null +++ b/demos/RPGInterface/index.html @@ -0,0 +1,242 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

RPGInterface

+ + + + source code + + +

This is a simple demonstration of the flixel-ui engine in a fictional RPG.

+

It demonstrates how you can create flixel-ui's from xml layout files, and is also integrated with the firetongue localization library. Not only does this do automatic text replacements, but it also lets you specify UI tweaks for each locale. This example uses both English and Norwegian.

+

The Norwegian text on certain buttons is too long and would wrap in an ugly way without adjustment, so there are several tweaks to extend button widths if the current locale is Norwegian.

+

flixel-ui has many common UI widgets available, including:

+
    +
  • Buttons (both normal and toggle-able)
  • +
  • Checkboxes
  • +
  • Radio button groups
  • +
  • 9-slice chrome, in both scaling and tiling varieties
  • +
  • Tabbed menus (which can contain other flixel-ui widgets)
  • +
+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/Replay/index.html b/demos/Replay/index.html new file mode 100644 index 000000000..083ed25ca --- /dev/null +++ b/demos/Replay/index.html @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

Replay

+ + + + source code + + +

A port of the Replay demo by Guoboism featured on flixel.org/features..

+

Replays are a powerful new feature in Flixel. Replays are essentially a list of what keyboard keys were pressed, and what mouse inputs were given, during a specific time frame. Because Flixel is largely deterministic, we can use that information to recreate a gameplay session that someone else recorded, as long as we have the same SWF. Replays can be used for debugging, arcade-style "attract modes" or in-game demos, and even for cutscenes. Replays can be manipulated using the "VCR" panel on the debugger overlay, or directly through functions like FlxG.vcr.loadReplay(), FlxG.vcr.startRecording(), and FlxG.vcr.reloadReplay(). Adventurous game makers can also check out the more complex Mode source code to see an example of loading a replay from a file to create an "attract mode". 

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/Revenge/index.html b/demos/Revenge/index.html new file mode 100644 index 000000000..06eced744 --- /dev/null +++ b/demos/Revenge/index.html @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

Revenge

+ + + + source code + + +

This is a port of Revenge by Yadu Rajiv. You can find a presentation by him on making games with flixel here.

+

Controls:

+

Move - WASD or arrow keys

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/Save/index.html b/demos/Save/index.html new file mode 100644 index 000000000..525728609 --- /dev/null +++ b/demos/Save/index.html @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

Save

+ + + + source code + + +

A port of the Save Demo by Zachary Tarvit featured on flixel.org/features.

+

Flash includes a simple way to save data locally, and the FlxSave object allows you to interface with it. This system is not ideal for all things; for example, if you are doing online high scores, this won't really work. If you want players to be able to move and trade save game files, this isn't a good fit either. However, for fast and simple saving of local data, especially things like unlocked progress or user preferences, FlxSave is an easy and built-in option.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/ScaleModes/index.html b/demos/ScaleModes/index.html new file mode 100644 index 000000000..71082cb9e --- /dev/null +++ b/demos/ScaleModes/index.html @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

ScaleModes

+ + + + source code + + +

This demo showcases HaxeFlixel's scale modes, which are especially handy for mobile devices where a lot of different screen sizes have to be accounted for, or desktop games that can be resized.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/SetTileProperties/index.html b/demos/SetTileProperties/index.html new file mode 100644 index 000000000..0ac7aeb1d --- /dev/null +++ b/demos/SetTileProperties/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

SetTileProperties

+ + + + source code + + +

Showases the setTileProperties() method of FlxTilemap.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/SplitScreen/index.html b/demos/SplitScreen/index.html new file mode 100644 index 000000000..b4bd37c6d --- /dev/null +++ b/demos/SplitScreen/index.html @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

SplitScreen

+ + + + source code + + +

A port and improvement of the Split Screen demo by Philippe Mongeau featured on flixel.org/features.

+

One of the new features in Flixel is the introduction of a flexible and powerful camera class called (unsurprisingly) FlxCamera. By default, a new Flixel game project starts with one camera that is the same size as the Flash Player window, which can be referenced at FlxG.camera. You can replace that camera or add additional cameras to create effects like "split screen" views, or "picture in picture" style displays, or even mini-maps.

+

Each camera is an independent display object, with its own zoom, color tint, rotation, and scaling values. Finally, each game object maintains its own camera list, so you can easily instruct certain objects to only display on certain cameras. Adventurous game makers can also check out the more complex Mode source code for more ways to use cameras in-game.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/SubState/index.html b/demos/SubState/index.html new file mode 100644 index 000000000..6fad10219 --- /dev/null +++ b/demos/SubState/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

SubState

+ + + + source code + + +

An example of flixel.FlxSubState.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/TexturePackerAtlas/index.html b/demos/TexturePackerAtlas/index.html new file mode 100644 index 000000000..daa383e81 --- /dev/null +++ b/demos/TexturePackerAtlas/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

TexturePackerAtlas

+ + + + source code + + +

This demo showcases how to load TexturePacker data with a FlxSprite.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/TileMap/index.html b/demos/TileMap/index.html new file mode 100644 index 000000000..214b4a3d4 --- /dev/null +++ b/demos/TileMap/index.html @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

Tilemap

+ + + + source code + + +

A port and improvement of the Tilemap demo by Tim Plummer featured on flixel.org/features.

+

Flixel's FlxTilemap class was inspired by old video games, in which the environment was constructed using a grid of square "tiles". Each grid cell gets a number, or index, which refers to a particular square graphic. That tile graphic is then placed at the appropriate grid number. Tilemaps have many advantages: it is easy to figure out what tiles should be drawn on screen, what tiles an object overlaps, and what special properties each tile might have. Flixel also includes some built-in algorithms for automatically placing wall tiles and floor tiles based on a simple binary (1s and 0s) array of tile data. It is a simple system with a lot of flexibility, which makes it perfect for rapid prototyping.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/TiledEditor/index.html b/demos/TiledEditor/index.html new file mode 100644 index 000000000..651a5d852 --- /dev/null +++ b/demos/TiledEditor/index.html @@ -0,0 +1,241 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

TiledEditor

+ + + + source code + + +

This sample shows how to load a map from the Tiled Map Editor.

+

Demo Controls:

+
    +
  • Arrow Keys - Move
  • +
  • Space - Jump
  • +
+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/Tooltips/index.html b/demos/Tooltips/index.html new file mode 100644 index 000000000..18dad1d4a --- /dev/null +++ b/demos/Tooltips/index.html @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+ +

Tooltips

+ + + + source code + + +

An example showcasing how tooltips can be used in flixel-ui.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/Transitions/index.html b/demos/Transitions/index.html new file mode 100644 index 000000000..b4089f54f --- /dev/null +++ b/demos/Transitions/index.html @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + +
+ +
+
+ +
+ +

Transitions

+ + + + source code + + +

A showcase of the transition effects possible with the flixel.addons.effect.transition package.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/TurnBasedRPG/index.html b/demos/TurnBasedRPG/index.html new file mode 100644 index 000000000..5b6999629 --- /dev/null +++ b/demos/TurnBasedRPG/index.html @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+ +

TurnBasedRPG

+ + + + source code + + +

The Turn Based RPG game from this tutorial by SeiferTim.

+ + +
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + diff --git a/demos/index.html b/demos/index.html new file mode 100644 index 000000000..0f6792510 --- /dev/null +++ b/demos/index.html @@ -0,0 +1,790 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +

Demos

+ + + + +
+ + + + +

BSPMapGen

+ + {{demo.data.title}} +
+ + + + +

BlendModeShaders

+ + {{demo.data.title}} +
+ + + + +

Breakout

+ + {{demo.data.title}} +
+ + + + +

Calculator

+ + {{demo.data.title}} +
+ + + + +

CollisionAndGrouping

+ + {{demo.data.title}} +
+ + + + +

Colors

+ + {{demo.data.title}} +
+ + + + +

Cursor

+ + {{demo.data.title}} +
+ + + + +

DynamicShadows

+ + {{demo.data.title}} +
+ + + + +

EZPlatformer

+ + {{demo.data.title}} +
+ + + + +

FileBrowse

+ + {{demo.data.title}} +
+ + + + +

Filters

+ + {{demo.data.title}} +
+ + + + +

Flappybalt

+ + {{demo.data.title}} +
+ + + + +

FlipRotationAnimationTiles

+ + {{demo.data.title}} +
+ + + + +

Flixius

+ + {{demo.data.title}} +
+ + + + +

FloodFill

+ + {{demo.data.title}} +
+ + + + +

FlxAction

+ + {{demo.data.title}} +
+ + + + +

FlxAsepriteUtils

+ + {{demo.data.title}} +
+ + + + +

FlxAsyncLoop

+ + {{demo.data.title}} +
+ + + + +

FlxAtlas

+ + {{demo.data.title}} +
+ + + + +

FlxBitmapText

+ + {{demo.data.title}} +
+ + + + +

FlxBunnyMark

+ + {{demo.data.title}} +
+ + + + +

FlxCamera

+ + {{demo.data.title}} +
+ + + + +

FlxCaveGenerator

+ + {{demo.data.title}} +
+ + + + +

FlxClothSprite

+ + {{demo.data.title}} +
+ + + + +

FlxCollisions

+ + {{demo.data.title}} +
+ + + + +

FlxEffectSprite

+ + {{demo.data.title}} +
+ + + + +

FlxFSM

+ + {{demo.data.title}} +
+ + + + +

FlxInvaders

+ + {{demo.data.title}} +
+ + + + +

FlxLightPuzzle

+ + {{demo.data.title}} +
+ + + + +

FlxMouseEvent

+ + {{demo.data.title}} +
+ + + + +

FlxNape

+ + {{demo.data.title}} +
+ + + + +

FlxNapeTerrain

+ + {{demo.data.title}} +
+ + + + +

FlxNapeTilemap

+ + {{demo.data.title}} +
+ + + + +

FlxPexParser

+ + {{demo.data.title}} +
+ + + + +

FlxPieDial

+ + {{demo.data.title}} +
+ + + + +

FlxPongApi

+ + {{demo.data.title}} +
+ + + + +

FlxRandom

+ + {{demo.data.title}} +
+ + + + +

FlxScene

+ + {{demo.data.title}} +
+ + + + +

FlxShape

+ + {{demo.data.title}} +
+ + + + +

FlxSimplex

+ + {{demo.data.title}} +
+ + + + +

FlxSkewedSprite

+ + {{demo.data.title}} +
+ + + + +

FlxSnake

+ + {{demo.data.title}} +
+ + + + +

FlxSound

+ + {{demo.data.title}} +
+ + + + +

FlxSpine

+ + {{demo.data.title}} +
+ + + + +

FlxSpriteFilters

+ + {{demo.data.title}} +
+ + + + +

FlxTeroids

+ + {{demo.data.title}} +
+ + + + +

FlxTextFormat

+ + {{demo.data.title}} +
+ + + + +

FlxTilemapExt

+ + {{demo.data.title}} +
+ + + + +

FlxTrailArea

+ + {{demo.data.title}} +
+ + + + +

FlxTween

+ + {{demo.data.title}} +
+ + + + +

FlxTypeText

+ + {{demo.data.title}} +
+ + + + +

FrameCollections

+ + {{demo.data.title}} +
+ + + + +

GamepadTest

+ + {{demo.data.title}} +
+ + + + +

GridMovement

+ + {{demo.data.title}} +
+ + + + +

HeatmapPathfinding

+ + {{demo.data.title}} +
+ + + + +

MinimalistTD

+ + {{demo.data.title}} +
+ + + + +

Mode

+ + {{demo.data.title}} +
+ + + + +

MosaicEffect

+ + {{demo.data.title}} +
+ + + + +

Parallax

+ + {{demo.data.title}} +
+ + + + +

Particles

+ + {{demo.data.title}} +
+ + + + +

Pathfinding

+ + {{demo.data.title}} +
+ + + + +

PixelPerfectCollision

+ + {{demo.data.title}} +
+ + + + +

ProjectJumper

+ + {{demo.data.title}} +
+ + + + +

RPGInterface

+ + {{demo.data.title}} +
+ + + + +

Replay

+ + {{demo.data.title}} +
+ + + + +

Revenge

+ + {{demo.data.title}} +
+ + + + +

Save

+ + {{demo.data.title}} +
+ + + + +

ScaleModes

+ + {{demo.data.title}} +
+ + + + +

SetTileProperties

+ + {{demo.data.title}} +
+ + + + +

SplitScreen

+ + {{demo.data.title}} +
+ + + + +

SubState

+ + {{demo.data.title}} +
+ + + + +

TexturePackerAtlas

+ + {{demo.data.title}} +
+ + + + +

Tilemap

+ + {{demo.data.title}} +
+ + + + +

TiledEditor

+ + {{demo.data.title}} +
+ + + + +

Tooltips

+ + {{demo.data.title}} +
+ + + + +

Transitions

+ + {{demo.data.title}} +
+ + + + +

TurnBasedRPG

+ + {{demo.data.title}} +
+ + + +
+ + + + +
+ + + + + + + + + + + + diff --git a/documentation/.github/workflows/main.yml b/documentation/.github/workflows/main.yml new file mode 100644 index 000000000..b4ad5fa84 --- /dev/null +++ b/documentation/.github/workflows/main.yml @@ -0,0 +1,28 @@ +name: CI + +on: + push: + branches: [master] + workflow_dispatch: + repository_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: lix-pm/setup-lix@master + - uses: HaxeFlixel/setup-flixel@master + with: + haxe-version: 4.3.2 + flixel-versions: release + target: flash + - run: npm install + working-directory: api/dox + - run: haxe --cwd api --run Make xml pages + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{secrets.GITHUB_TOKEN}} + publish_dir: ./api/dox/out + cname: api.haxeflixel.com diff --git a/documentation/.gitignore b/documentation/.gitignore new file mode 100644 index 000000000..80f189490 --- /dev/null +++ b/documentation/.gitignore @@ -0,0 +1,4 @@ +api/xml/bin +api/dox/bin +api/dox/out +node_modules \ No newline at end of file diff --git a/documentation/.vscode/settings.json b/documentation/.vscode/settings.json new file mode 100644 index 000000000..e2cdd824a --- /dev/null +++ b/documentation/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "*.mtt": "xml" + } +} \ No newline at end of file diff --git a/documentation/LICENSE.md b/documentation/LICENSE.md new file mode 100644 index 000000000..a9e2a16bf --- /dev/null +++ b/documentation/LICENSE.md @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 HaxeFlixel + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/documentation/README.md b/documentation/README.md new file mode 100644 index 000000000..7622f0c95 --- /dev/null +++ b/documentation/README.md @@ -0,0 +1,43 @@ +![](https://raw.github.com/HaxeFlixel/haxeflixel.com/master/src/files/images/flixel-logos/flixel-docs.png) + +[flixel](https://github.com/HaxeFlixel/flixel) | [addons](https://github.com/HaxeFlixel/flixel-addons) | [ui](https://github.com/HaxeFlixel/flixel-ui) | [demos](https://github.com/HaxeFlixel/flixel-demos) | [tools](https://github.com/HaxeFlixel/flixel-tools) | [templates](https://github.com/HaxeFlixel/flixel-templates) | [docs](https://github.com/HaxeFlixel/flixel-docs) | [haxeflixel.com](https://github.com/HaxeFlixel/haxeflixel.com) + +[![CI](https://img.shields.io/github/actions/workflow/status/HaxeFlixel/flixel-docs/main.yml?branch=master&logo=github)](https://github.com/HaxeFlixel/flixel-docs/actions?query=workflow%3ACI) + +## About + +This is the main location for HaxeFlixel documentation. Pull requests from this location will be pushed to the live website periodically, so please help us improve the HaxeFlixel docs. + +## Contents + +* The "main" documentation available on [haxeflixel.com/documentation](https://haxeflixel.com/documentation). +* The API documentation. + +### Main documentation + +The main documentation is made up of `*.html.md` files in the `./documentation` folder. Each file and folder starts with a numerical prefix specifying the order listed on the [docpad website](https://github.com/HaxeFlixel/haxeflixel.com). + +Additional pages can be added using the same extension and using a header specifying the title as seen in the other pages. Eg: +``` + --- + title: "Documentation Page" + --- +``` + Use Regular GitHub flavoured markdown for the page. + Note `title:` above is case sensitive. + +The markdown syntax used in the docs is the [GitHub-Flavored-Markdown](https://help.github.com/articles/github-flavored-markdown), thus it's very convenient to directly edit the files via GitHub's web editor. + +### API documentation + +API documentation is provided in the `./api` folder, they are currently generated with [dox](https://github.com/HaxeFoundation/dox). You can view the API docs offline by cloning this directory, checking out the `gh-pages` branch, running `nekotools server` in `./api` and navigating to [localhost:2000](http://localhost:2000/). + +To generate the API docs yourself, you need to first run `npm install` in `api/dox`. Then run the following from the root directory: + +``` +haxe --cwd api --run Make xml pages server +``` + +The docs will now be generated in the `api/dox/out` folder and a local webserver started at `localhost:2000`. + +Note this will use your locally enabled haxelib flixel versions, e.g. if you have `haxelib git flixel` set to `dev` etc. diff --git a/documentation/about/index.html b/documentation/about/index.html new file mode 100644 index 000000000..3a9ba54fb --- /dev/null +++ b/documentation/about/index.html @@ -0,0 +1,397 @@ + + + + + + + + + + About | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

About

+ + + Edit + +

HaxeFlixel is an open source 2D game engine written for use with the Open Flash Library and the Haxe Toolkit, it is completely free for personal or commercial use. It enables multi-platform development for native targets on mobile and desktop as well as Flash and HTML5 on web platforms.

+

This project was founded by Alexander Hohlov, also known on Beeblerox on GitHub, who continues to be the project lead for the HaxeFlixel Organisation group. The project itself also has an active community with contributions from highly valued developers (by GitHub names) GameDevSam, impaler, Werdn, ProG4mr, Gama11, sergey-miryanov and more.

+
+

Haxe and OpenFL improves the longevity and opportunities for your Flixel Games.

+
+

HaxeFlixel is largely based on the AS3 version of Flixel written by Adam “Atomic” Saltsman. One of the major motivations for creating HaxeFlixel is overcoming the limitations of the ActionScript 3 language and the Adobe Flash and AIR runtime targets. HaxeFlixel has been able to incorporate and continues to add new language features of Haxe and incorporate exciting new runtime targets through OpenFL.

+

The aim of this website is to provide HaxeFlixel with a friendly and connected web presence. It has been developed by Chris Decoster with great input from the community. It provides a place for experienced developers and beginners alike, to easily share their experiences in developing and learning how to make games. We have seen the website form a central location to share resources and improve HaxeFlixel itself.

+

Everyone is highly encouraged to contribute to HaxeFlixel itself and the resources on this website.

+

+
+ +
+ +

Features Overview

+ +
    +
  • Display thousands of moving objects
  • +
  • Basic collisions between objects
  • +
  • Group objects together for simplicity
  • +
  • Easily generate and emit particles
  • +
  • Create game levels using Tilemaps
  • +
  • Text display and Bitmap Fonts
  • +
  • Math & Color utilities
  • +
  • Record and play back replays
  • +
  • Powerful interactive debugger
  • +
  • Path finding and following
  • +
  • Easy object recycling
  • +
+ +
+ +
+ +

Enhancements over AS3

+ +
    +
  • Use of a robust and powerful open source language Haxe
  • +
  • Cross platform development to Linux, Mac and Windows
  • +
  • Compile to Mobile and Desktop targets with native code
  • +
  • Impressive Native Performance using GPU acceleration
  • +
  • Advanced Physics with inbuilt Nape support
  • +
  • Improved debugger and interactive console
  • +
  • Texture batching and cache enhancements
  • +
  • Access to OpenFL native extensions
  • +
  • Flexible Asset Management System
  • +
  • Integrated Tweening system
  • +
+ +
+ +

+

Core Members

+ +
    + +
  • + +

    Beeblerox

    +
    + +

    The founding member and Author of HaxeFlixel, Alexander completed the first version of HaxeFlixel during 2011, his work is the reason for the project's success.

    +
  • +
  • + +

    Chris

    +
    + +

    Chris is a generalist developer who has worked on various features and bug fixes for the engine and tools. Chris is also responsible for our logo, website and forum and is a long time member of the project.

    +
  • +
  • + +

    GameDevSam

    +
    + +

    Sam is a formidable programmer who spends his working days doing GUI programming with AAA titles. Sam is also a passionate Indie developer and community organiser in the Baltimore area. He is responsible for many optimisations and improvements to the engine and has been a part of HaxeFlixel shortly after it began.

    +
  • +
  • + +

    Gama11

    +
    + +

    Gama11 is a highly valued contributor who has taken great pride in making our codebase consistent and structured. He took the lead on the HaxeFlixel 3.x API refactor and improvements to the codebase structure general.

    +
  • +
  • + +

    Larsiusprime

    +
    + +

    Lars is veteran Flixel developer who is best known for his main Indie game Defender's Quest. Lars is also the main dev behind making the flixel-ui framework.

    +
  • +
  • + +

    ProG4mr

    +
    + +

    Tiago is the programmer to thank for our Nape Physics support. Tiago has a flair for great demos and style and is a great multi talented developer.

    +
  • +
  • + +

    Sergey Miryanov

    +
    + +

    Sergey is an accomplished programmer who is a highly valued voice in discussions and planning for changes in the codebase. Sergey is a long time participator in the HaxeFlixel project.

    +
  • + +
+ +

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/actions/index.html b/documentation/actions/index.html new file mode 100644 index 000000000..cb20afe92 --- /dev/null +++ b/documentation/actions/index.html @@ -0,0 +1,574 @@ + + + + + + + + + + Actions | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Actions

+ + + API + + Edit + +

Players & designers care about actions (Mario jumps, Samus shoots, Captain +Falcon turns, brakes, and accelerates), whereas computers care about +inputs (The W key is PRESSED, the left mouse button was JUST_RELEASED, +gamepad #2's analog stick is MOVED with values x=0.4, y=-0.5).

+

The FlxAction API provides several benefits over handling every input case +directly:

+
    +
  • Declutter logic by focusing on actions, not inputs
  • +
  • Remove tight coupling between specific input bindings and actions
  • +
  • Makes it easy to refactor your input code
  • +
  • Makes it easy to support player-defined input bindings
  • +
  • Makes it easy to handle multiple input devices simultaneously
  • +
  • Allows use of the Steam Input API
  • +
  • Makes it easier to implement:
      +
    • AI-controlled players/bots
    • +
    • Replay systems (record actions, not inputs, then play them back)
    • +
    +
  • +
+

FlxAction

+

FlxActions come in two varieties: digital and analog. Digital is for on/off +actions like "JUMP" and "SHOOT". Analog is for things that need a range of +values, like jumping with more or less force, or moving a player or camera +around. (FlxActions are triggered by attached FlxActionInputs, described in +the next section).

+

Digital actions let you do things like: if(SHOOT.check()) doShoot(); in your +update loop rather than have a big ugly block that accounts for every input +device you support.

+

Analog actions let you do things like moveCharacter(MOVE.x, MOVE.y) or +fireLaserBeam(LASER_INTENSITY.x), nicely hiding whatever devices are actually +driving the input, and just providing you with the resulting floating point +values.

+

To create a FlxAction:

+
var jump = new FlxActionDigital();
+var move = new FlxActionAnalog();
+
+

You can optionally pass in a name and a callback in the constructor. If you +provide a callback, it will fire whenever the action is triggered.

+

If you are managing FlxActions yourself (as opposed to using the action +manager), you will need to update the actions every frame, either by doing +something like this:

+
function updateLoop()
+{
+    if (jump.check()) doJump();
+    if (move.check()) doMove(move.x, move.y);
+}
+
+

...or this:

+
function updateLoop()
+{
+    jump.update();
+    move.update();
+    if (jump.triggered) doJump();
+    if (move.triggered) doMove(move.x, move.y);
+}
+
+

FlxAction.update() will update the triggered property, fire the callback +if present, and update the x and y values (if an analog action).

+

FlxAction.check() will update the triggered property, fire the callback if present, update the x and y values (if an analog action), and return the +value of triggered.

+

Either is sufficient to keep the action updated. You must update each +action at least once per global update tick to ensure accurate input, but if you +accidentally update an action more than once per tick, it's okay -- an internal +safety check ensures that nothing bad happens.

+

If you don't want to manually update FlxActions, use the FlxActionManager, +which will keep them updated for you.

+

FlxActionInput

+

A FlxActionInput represents a specific input event on a specific input device, +like "when the A button on gamepad #1 is JUST_PRESSED", which you can use to +trigger a FlxAction.

+

These come in digital and analog forms for every device that Flixel supports. +The following are provided by default, but you can create your own by extending FlxActionInputDigital and FlxActionInputAnalog:

+
    +
  • FlxActionInputDigitalKeyboard
  • +
  • FlxActionInputDigitalMouse
  • +
  • FlxActionInputDigitalMouseWheel
  • +
  • FlxActionInputDigitalGamepad
  • +
  • FlxActionInputDigitalIFlxInput
  • +
  • FlxActionInputAnalogMouse
  • +
  • FlxActionInputAnalogMouseMotion
  • +
  • FlxActionInputAnalogMousePosition
  • +
  • FlxActionInputAnalogClickAndDragMouseMotion
  • +
  • FlxActionInputAnalogGamepad
  • +
+

You can attach inputs like this:

+
jump.addKey(SPACE, JUST_PRESSED);
+jump.addMouse(LEFT, JUST_PRESSED);
+jump.addGamepad(A, JUST_PRESSED, FIRST_ACTIVE);
+
+

These helper functions are a shorthand for this equivalent:

+
jump.add(new FlxActionInputDigitalKeyboard(SPACE, JUST_PRESSED));
+jump.add(new FlxActionInputDigitalMouse(LEFT, JUST_PRESSED));
+jump.add(new FlxActionInputDigitalGamepad(A, JUST_PRESSED, FIRST_ACTIVE);
+
+

This will cause the "jump" action to trigger on the frame where any of the +following conditions is met: space bar was just pressed, left mouse button was +just clicked, or the bottom face button on any gamepad was just pressed.

+

Each FlxActionInput class has its own parameters that let you define exactly +when the action should fire. For instance, here is the constructor for FlxActionInputDigitalKeyboard:

+
public function new(Key:FlxKey, Trigger:FlxInputState)
+
+

This requires you to specify a specific key, as well as an input state (PRESSED, +JUST_PRESSED, RELEASED, JUST_RELEASED).

+

Now here's the constructor for FlxActionInputDigitalGamepad, note that in +addition to specifying the button and the trigger state, we also have to specify +which gamepad we're listening for, since there could be more than one:

+
public function new(InputID:FlxGamepadInputID, Trigger:FlxInputState, GamepadID:Int = FlxInputDeviceID.FIRST_ACTIVE)
+
+

Now let's take a quick look at some analog inputs.

+

Here's FlxActionInputAnalogGamepad:

+
public function new(InputID:FlxGamepadInputID, Trigger:FlxAnalogState, Axis:FlxAnalogAxis = EITHER, GamepadID:Int = FlxInputDeviceID.FIRST_ACTIVE)
+
+

In addition to having to specify the input (left/right stick or left/right +trigger), the trigger state, and the gamepad ID, we also have to specify which +analog axis we care about (X, Y, EITHER, BOTH). (Note that for +single-axis analog inputs, such as analog triggers, only the x value will change +and the y value will always be zero).

+

Another example is FlxActionInputAnalogMousePosition:

+
public function new(Trigger:FlxAnalogState, Axis:FlxAnalogAxis = EITHER)
+
+

Since there's only ever one mouse, we don't need to specify the device, and we don't +need to specify a button since we just want the position. Whenever this action +updates the x and y values will match the mouse position.

+

FlxActionSet

+

A FlxActionSet is little more than a glorified array of FlxActions. There's +little reason to use them directly unless you are using the FlxActionManager, +but they can still be a convenient way to call update() on all your actions +at once.

+

FlxActionManager

+

FlxActionManager lets you manage multiple actions without having to update +them manually, and also lets you control action sets. Action sets are groups of +actions that can be selectively activated for specific input devices at specific times, which is great for local multiplayer games, games with complex input, and +games using the Steam Input API.

+

FlxActionManager is not initialized in Flixel by default, you have to add it yourself in your initialization code:

+
var actionManager = new FlxActionManager();
+FlxG.inputs.add(actionManager);
+
+

Once the action manager has been set up, you can simply add actions to it, and +it will ensure that all your actions are kept up to date:

+
//add actions one by one:
+actionManager.addAction(jump);
+actionManager.addAction(shoot);
+
+//add several actions at once:
+actionManager.addActions([action1, action2, action3, action4, action5]);
+
+

Then in your update loop you can simply check the triggered property, or just +wait for callbacks to fire, if you've set any.

+
function updateLoop()
+{
+    if (jump.triggered) doJump();
+    if (shoot.triggered) doShoot();
+}
+
+

Default action set

+

What's actually happening when you call addAction or addActions is that the +manager is asking for both actions and the action set you want to add them to:

+
public function addAction(Action:FlxAction, ActionSet:Int = 0):Bool
+
+

If you don't provide an action set, it assumes you want to add them to the first +one (index 0). And if you haven't defined any action sets, it will create one +for you at index 0, name it "default", and immediately activate it for all +devices.

+

NOTE: +By default, when you change FlxStates, the default action set, including all referenced actions and inputs, will be cleared out and destroyed. You can change +this behavior by modifying the FlxActionManager.resetOnStateSwitch policy.

+

If you're not juggling multiple action sets, you will probably never need to +worry about any of this -- just add new actions at the start of every state. +We like to explain what's going on under the hood just in case you encounter unexpected behavior.

+

Working with action sets

+

Only ONE action set is considered active at a given time for any given device, +but multiple devices can be subscribed to the same action set.

+

For instance, in an asymetrical co-op game where one person drives a tank +and the other mans the turret, gamepad #1 could use action set "drive" and +gamepad #2 could use action set "gunner". The same could go for the mouse, +the keyboard, etc. And in a single-player game you might want to just change +the action set of ALL input devices every time you switch to a different +screen, such as a menu.

+

FlxActionManager lets you:

+
    +
  • ADD action sets
  • +
  • REMOVE action sets
  • +
  • ACTIVATE an action set for a specific device
  • +
  • UPDATE all your action sets at once
  • +
  • ENFORCE the "only one action set active per device at a time" rule
  • +
+

To create and add an action set, do something like:

+
//where up, down, left, right, select are digital actions
+var set = new FlxActionSet("menu", [up, down, left, right, select]);
+var menuSetIndex = actionManager.addSet(set);
+
+

Note that addSet returns the action set's index. All operations on action sets +require the action set's index (an Int), not its name (a String). This is +for performance reasons. If you forget to store the action set, or otherwise +lose track of an action set's index, you can query it at any time by passing the +set's name to getSetIndex(). Just be sure not to do this repeatedly in +frequently called loops.

+

Steam Input

+

If you are using the steamwrap library, FlxActionManager gains the ability +to automatically create action sets from a steamwrap object derived from the +master vdf game actions file that Steam makes you set up. You must then ACTIVATE +one of those action sets for any connected steam controllers, which will +automatically attach the proper steam action inputs to the actions in the set. +You can also add as many regular FlxActionInputs as you like to any actions in +the sets.

+
var config = steamwrap.data.ControllerConfig.fromVDF(myVDF);
+actionManager.initSteam(config, digitalCallback, analogCallback);
+
+

NOTE: +If you are using the Steam Input API and/or a Steam Controller, you MUST use FlxActionManager in order to properly process Steam's API via FlxActions. +The only other alternative is to call the steamwrap functions directly.

+

JSON parsing

+

FlxActionManager can generate a JSON string representation of your action sets via exportToJson() You can also initialize your action sets by calling +initFromJson(), feeding in the parsed object representation of the same format.

+

The format is:

+
typedef ActionSetJsonArray = 
+{
+    @:optional var actionSets:Array<ActionSetJSON>;
+}
+
+typedef ActionSetJson =
+{
+    @:optional var name:String;
+    @:optional var analogActions:Array<String>;
+    @:optional var digitalActions:Array<String>;
+}
+
+

Which would look something like this in practice:

+
{
+    "actionSets" : [
+        {
+            "name" : "SomeSet",
+            "analogActions" : [
+                "some_analog_action_1",
+                "some_analog_action_2"
+            ],
+            "digitalActions" : [
+                "some_digital_action_1",
+                "some_digital_action_2"
+            ]
+        },
+        {
+            "name" : "AnotherSet",
+            "analogActions" : [
+                "another_analog_action_1",
+                "another_analog_action_2"
+            ],
+            "digitalActions" : [
+                "another_digital_action_1",
+                "another_digital_action_2"
+            ]
+        }
+    ]
+}
+
+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/android/index.html b/documentation/android/index.html new file mode 100644 index 000000000..d314c5010 --- /dev/null +++ b/documentation/android/index.html @@ -0,0 +1,355 @@ + + + + + + + + + + Android | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Android

+ + + Edit + +

+

The Android target makes use of a chain of frameworks to compile your native Android game from Haxe code. OpenFL uses the Hxcpp and the Android NDK specifically so no virtual machine is involved.

+

To set up android, run lime setup android after installing HaxeFlixel. You can choose to download necessary components (eg. Android SDK and NDK) or use existing installations.

+

The Haxe compiler uses its cpp target to compile your Haxe code for the LibSDL OpenGL library so that the Android NDK can then use this "native-code" for your Android game. You can read more about the Android NDK from Google here, however this process is completely automated by OpenFL. Android is part of the cpp group of targets and when developers mention cpp the topic may be relevant to HaxeFlixel Android.

+

With OpenFL using native-code and OpenGL with LibSDL, the rendering methods are different to where Flixel started with Flash. Android uses GPU accelerated Texture Batching for the best possible performance on mobile devices.

+

Conditionals

+
#if cpp
+//your android code
+#end
+
+#if android
+//your android code
+#end
+
+#if mobile
+//your android code
+#end
+

Project XML settings

+

Mobile platforms can use a window width and height of 0, which is a special value that uses the full resolution of the current display.

+
<window width="0" height="0" background="#FFFFFF" fps="60" />
+

OpenFL also exposes the following specific settings for the Android target:

+
<android target-sdk-version="17" />
+<window hardware="true" allow-shaders="true" require-shaders="true" if="cpp"/>
+<window vsync="true" antialiasing="4" if="cpp" />
+<window orientation="portrait" /> || <window orientation="landscape" if="cpp"/>
+

Custom PNG icons: (Check Iconography / Android Developers for more info)

+
<icon path="36.png" size="36" if="android" />
+<icon path="48.png" size="48" if="android" />
+<icon path="72.png" size="72" if="android" />
+<icon path="96.png" size="96" if="android" />
+

Compile Commands

+

Visual Studio Code, FlashDevelop and IntelliJ IDEA support Android compilation through their GUI.

+

Command line

+

The basic command to compile and test Android:

+
lime test android
+

Run this command from the root folder of your project; the default project.xml will be used automatically. For the test command to run on your device you should have it connected with ADB working correctly.

+

If you want to use the Android simulator, add -simulator when running/testing. Be sure your virtual device is API >=15 and has GPU enabled.

+
lime test android -simulator
+
+ +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/cheat-sheet/index.html b/documentation/cheat-sheet/index.html new file mode 100644 index 000000000..748310679 --- /dev/null +++ b/documentation/cheat-sheet/index.html @@ -0,0 +1,768 @@ + + + + + + + + + + Cheat Sheet | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Cheat Sheet

+ + + Edit + +

FlxSprite (Base)

+
package;
+
+import flixel.FlxSprite;
+import flixel.FlxG;
+
+class MySprite extends FlxSprite
+{
+    public function new()
+    {
+        super();
+    }
+
+    override public function update(elapsed:Float):Void
+    {
+        super.update(elapsed);
+    }
+}
+
+

FlxState (Base)

+
package;
+
+import flixel.FlxState;
+import flixel.FlxG;
+
+class MyState extends FlxState
+{
+    override public function create():Void
+    {
+        super.create();
+    }
+
+    override public function update(elapsed:Float):Void
+    {
+        super.update(elapsed);
+    }
+}
+
+

Switch FlxState

+
FlxG.switchState(new MyState());
+
+

Load FlxSprite

+
loadGraphic("assets/my_sprite.png");
+
+// OR dynamically create a rect
+makeGraphic(100, 100, 0xFFFFFFFF); // width, height, color (AARRGGBB hexadecimal)
+
+// to update bounding box by default (positioned on top left corner of the sprite)
+updateHitbox(); // or offset.set(10, 5); to shift bounding box 10 pixels horizontally and 5 pixels vertically
+
+

FlxText

+
    +
  • setFormat(font, size, color, alignment)
  • +
  • setBorderStyle(style, color, size)
  • +
+
import flixel.text.FlxText;
+import flixel.util.FlxColor;
+
+
myText = new FlxText(0, 0, 500); // x, y, width
+myText.text = "Hello World";
+myText.setFormat("assets/font.ttf", 20, FlxColor.WHITE, CENTER);
+myText.setBorderStyle(OUTLINE, FlxColor.RED, 1);
+
+

FlxButton

+
import flixel.ui.FlxButton;
+
+
myButton = new FlxButton(0, 0, "Label", myCallback);
+
+// Custom graphics (sprite sheet with 3 frames for normal / highlight / pressed)
+myButton.loadGraphic("assets/custom.png", true, width, height);
+
+
function myCallback():Void
+{
+}
+
+
    +
  • myButton.label is a FlxText, use setFormat() and setBorderStyle() to customise.
  • +
+

Sound Effects and Music

+

With the stock Project.xml, simply place them in your project's assets/music and assets/sounds subfolders and they're ready to use.

+

Sound effects are usually in WAV format (44.1 kHz source).

+

Music must be in MP3 format (44.1 kHz source) for Flash, and OGG for everything else. To support both Flash and non-Flash platforms without bundling both formats in your output, you can replace the stock <assets> tag in your Project.xml with this:

+
<assets path="assets" exclude="*.ogg" if="flash"/>
+<assets path="assets" exclude="*.mp3" unless="flash"/>
+
+

Play in your code:

+
// Play sound effect using AssetPaths
+FlxG.sound.play(AssetPaths.mySound__wav);
+// Play sound effect without AssetPaths
+FlxG.sound.play("assets/sounds/mySound.wav");
+
+// Loop music, Flash only
+FlxG.sound.playMusic(AssetPaths.myMusic__mp3);
+// Loop music, non-Flash only
+FlxG.sound.playMusic(AssetPaths.myMusic__ogg);
+// Loop music, Flash or non (getSound() adds .mp3 on Flash and .ogg otherwise)
+FlxG.sound.playMusic(FlxAssets.getSound("assets/music/myMusic"));
+
+

Keyboard Input

+
// 'A' key
+if (FlxG.keys.justPressed.A) {}
+if (FlxG.keys.pressed.A) {}
+if (FlxG.keys.justReleased.A) {}
+
+// Checking multiple keys:
+if (FlxG.keys.anyPressed([RIGHT, D])) {}
+
+

Keys

+

ANY

+

A...Z

+

UP DOWN LEFT RIGHT

+

SPACE ENTER ESCAPE

+

ZERO ONE TWO THREE...NINE

+

F1...F12

+

ALT +BACKSLASH +BACKSPACE +CAPSLOCK +CONTROL +DELETE +HOME +INSERT +QUOTE +PERIOD +PLUS +MINUS +PAGEUP +PAGEDOWN +RBRACKET +GRAVEACCENT +TAB +SLASH +SEMICOLON

+

NUMPADZERO NUMPADONE NUMPADTWO...NUMPADNINE

+

Mouse Input

+
if (FlxG.mouse.pressed) {}
+if (FlxG.mouse.justPressed) {}
+if (FlxG.mouse.justReleased) {}
+
+

Positional Data

+
// Relative to world space
+FlxG.mouse.x;
+FlxG.mouse.y;
+
+// Relative to screen
+FlxG.mouse.screenX;
+FlxG.mouse.screenY;
+
+

Wheel (mouse scroll)

+

Current "delta" value of mouse wheel. If the wheel was just scrolled up, it will have a positive value. If it was just scrolled down, it will have a negative value. If it wasn't just scroll this frame, it will be 0.

+
FlxG.mouse.wheel;
+
+

Up, Down, Over, Out Callbacks per Object

+
var clickableSprite:FlxSprite;
+
+// ...
+
+// register plugin in PlayState.create()
+FlxMouseEventManager.init();
+
+// ...
+
+// register callbacks
+var pixelPerfect = false;
+FlxMouseEventManager.add(clickableSprite, mousePressedCallback, mouseReleasedCallback, null, null, false, true, pixelPerfect, [FlxMouseButtonID.LEFT, FlxMouseButtonID.RIGHT]);
+
+// ...
+
+function mousePressedCallback(sprite:FlxSprite)
+{
+    if (FlxG.mouse.justPressed)
+    {
+        // left button was pressed
+    }
+    else if (FlxG.mouse.justPressedRight)
+    {
+        // right button was pressed
+    }
+}
+
+function mouseReleasedCallback(sprite:FlxSprite)
+{
+}
+
+

Touch Input

+
for (touch in FlxG.touches.list)
+{
+    if (touch.justPressed) {}
+    if (touch.pressed) {}
+    if (touch.justReleased) {}
+}
+
+

Positional Data

+
// Relative to world space
+touch.x;
+touch.y;
+
+// Relative to screen
+touch.screenX;
+touch.screenY;
+
+
    +
  • touchPointID: The unique ID of this touch.

    +
  • +
  • overlaps(objectOrGroup): Checks for overlap between this touch and another FlxObject or FlxGroup.

    +
  • +
+

Swipes (Input)

+

"Swipes" from both mouse and touch input that have just been released:

+
for (swipe in FlxG.swipes)
+{
+    // swipe.startPosition (FlxPoint)
+    // swipe.endPosition (FlxPoint)
+
+    // swipe.id (Int)
+
+    // swipe.distance (Float)
+    // swipe.angle (Float)
+    // swipe.duration (Float)
+}
+
+

FlxSignal

+
import flixel.util.FlxSignal;
+
+
// for signals that don't need data, use FlxSignal
+var signal = new FlxSignal();
+// for signals that need data, use FlxTypedSignal with the correct function type
+var stringSignal = new FlxTypedSignal<String->Void>();
+
+

Note: FlxSignal is nothing but a convenient shortcut for FlxTypedSignal<Void->Void>

+
signal.add(voidCallback); // type must be Void->Void
+stringSignal.add(stringCallback); // type must be String->Void
+
+
function voidCallback()
+{
+    trace("Hello");
+}
+
+function stringCallback(text:String)
+{
+    trace(text);
+}
+
+
// this will print "Hello World"
+signal.dispatch();
+stringSignal.dispatch("World");
+
+

You can have up to 4 parameters in your signal:

+
var collisionNotify = new FlxTypedSignal<FlxObject->FlxObject->Bool->Bool->Void>();
+collisionNotify.add(collisionCallback);
+
+function collisionCallback(source:FlxObject, target:FlxObject, shouldKillSource:Bool, shouldKillTarget:Bool):Void (...)
+
+

FlxTimer

+
import flixel.util.FlxTimer;
+
+
// time (seconds), callback, loops
+new FlxTimer().start(10.0, myCallback, 3);
+
+
function myCallback(timer:FlxTimer):Void
+{
+}
+
+
    +
  • Setting loops to 0 results in an endless loop.
  • +
  • reset(?NewTime) restarts the timer, optionally with a new duration.
  • +
  • cancel() stops the timer and removes it from the timer manager.
  • +
+

FlxRandom

+
// (Int) between 0 and 10
+FlxG.random.int(0, 10);
+
+// (Float) between 0.0 and 10.0
+FlxG.random.float(0.0, 10.0);
+
+// (Bool) Chance by percent
+FlxG.random.bool(50); // 50% chance to return 'true'
+FlxG.random.bool(10); // 10% chance to return 'true'
+
+

FlxTween

+

Check the demo to visualize all FlxTween types.

+
    +
  • tween(Object, Values, Duration, ?Options)
  • +
+
import flixel.tweens.FlxTween;
+import flixel.tweens.FlxEase;
+
+
// Moves sprite to position (100, 200) in 3 seconds
+FlxTween.tween(sprite, {x: 100, y: 200}, 3.0, {ease: FlxEase.quadInOut, complete: myCallback});
+
+
function myCallback(tween:FlxTween):Void
+{
+}
+
+

FlxTween Options

+

ease

+
{ease: FlxEase.quadInOut}
+
+

complete

+
{complete: callbackFunction}
+
+
function callbackFunction(tween:FlxTween):Void
+{
+}
+
+

type

+
{type: FlxTweenType.PINGPONG}
+
+
    +
  • FlxTweenType.BACKWARD: plays tween in reverse direction
  • +
  • FlxTweenType.LOOPING: restarts immediately when it finishes.
  • +
  • FlxTweenType.ONESHOT: stops and remove itself from its core container when it finishes.
  • +
  • FlxTweenType.PERSIST: stops when it finishes.
  • +
  • FlxTweenType.PINGPONG: plays tween hither and thither
  • +
+

loopDelay

+
{loopDelay: 1.0} // 1 second
+
+

startDelay

+
{startDelay: 2.0} // 2 seconds
+
+

FlxEase List

+

Check the demo to visualize all FlxEase types.

+
    +
  • backIn, backInOut, backOut
  • +
+
    +
  • bounceIn, bounceInOut, bounceOut
  • +
+
    +
  • circIn, circInOut, circOut
  • +
+
    +
  • cubeIn, cubeInOut, cubeOut
  • +
+
    +
  • elasticIn, elasticInOut, elasticOut
  • +
+
    +
  • expoIn, expoInOut, expoOut
  • +
+
    +
  • quadIn, quadInOut, quadOut
  • +
+
    +
  • quartIn, quartInOut, quartOut
  • +
+
    +
  • quintIn, quintInOut, quintOut
  • +
+
    +
  • sineIn, sineInOut, sineOut
  • +
+

Containers (FlxGroup)

+

FlxGroup is a shortcut for FlxTypedGroup<FlxBasic>. Use FlxTypedGroup<MyOwnClass> if you need to access your own variables and functions when iterating over the container.

+

Iteration

+
for (member in myGroup)
+{
+    member.x += 10;
+    member.mySpecificFunction(); // myGroup = FlxTypedGroup<MyOwnClass>
+}
+
+

Collision

+
FlxG.overlap(objectOrGroup1, objectOrGroup2, myCallback);
+
+
function myCallback(object1:FlxObject, object2:FlxObject):Void
+{
+}
+
+

Or use FlxG.collide() which calls FlxG.overlap() and presets the processCallback parameter to FlxObject.separate().

+

Setting World Bounds

+
// collision won't work outside the bounds, and by default they are only size of one screen
+FlxG.worldBounds.set(tilemap.x, tilemap.y, tilemap.width, tilemap.height);
+
+

Quick check whether there was a collision

+
// sets the touching flags
+FlxG.collide(player, level);
+
+if (player.isTouching(DOWN))
+{
+    // player stands on the ground and can jump 
+}
+
+// will reset touching flags when called
+super.update(elapsed);
+
+

Teleport sprite

+
// after setting the sprite's new position
+setPosition(10, 100);
+// don't forget to update 'last' variable if you don't want overlap callbacks for objects between old and new positions of the sprite
+last.set(x, y);
+
+

Pixel Perfect Collision

+
var overlapping = FlxG.pixelPerfectOverlap(sprite1, sprite2);
+
+

Drawing Shapes

+

Dynamically draw: circle, ellipse, line, polygon, triangle, rect, round rect and rect complex.

+
using flixel.util.FlxSpriteUtil;
+
+

Haxe docs about the using keyword: haxe.org/manual/lf-static-extension.html.

+
var canvas = new FlxSprite();
+canvas.makeGraphic(FlxG.width, FlxG.height, FlxColor.TRANSPARENT, true);
+add(canvas);
+
+

The last argument of makeGraphic() is Unique, whether the graphic should be an unique instance in the graphics cache, if you create multiple graphics like this, set it to true to avoid conflicts.

+
var lineStyle:LineStyle = {color: FlxColor.RED, thickness: 1};
+var drawStyle:DrawStyle = {smoothing: true};
+
+
// Circle
+canvas.drawCircle(x, y, radius, color, lineStyle, drawStyle);
+
+// Ellipse
+canvas.drawEllipse(x, y, width, height, color, lineStyle, drawStyle);
+
+// Line
+canvas.drawLine(startX, startY, endX, endY, lineStyle);
+
+// Polygon
+var vertices = new Array<FlxPoint>();
+vertices[0] = new FlxPoint(0, 0);
+vertices[1] = new FlxPoint(100, 0);
+vertices[2] = new FlxPoint(100, 300);
+vertices[3] = new FlxPoint(0, 100);
+canvas.drawPolygon(vertices, color, lineStyle, drawStyle);
+
+// Triangle
+canvas.drawTriangle(x, y, height, color, lineStyle, drawStyle);
+
+// Rect
+canvas.drawRect(x, y, width, height, color, lineStyle, drawStyle);
+
+// Round Rect
+canvas.drawRoundRect(x, y, width, height, ellipseWidth, ellipseHeight, color, lineStyle, drawStyle);
+
+// Rect Complex
+canvas.drawRoundRectComplex(x, y, width, height, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius, color, lineStyle, drawStyle);
+
+

Use canvas.fill(FlxColor.TRANSPARENT); to clear the canvas.

+

HUD

+
// prevents the sprite to scroll with the camera
+scrollFactor.set(0, 0);
+
+

Zooming game while leaving HUD intact

+
// create a new camera for the HUD
+uiCamera = new FlxCamera(0, 0, screenWidth, screenHeight);
+uiCamera.bgColor = FlxColor.TRANSPARENT;
+
+// add camera to list and set 'DefaultDrawTarget' to false
+FlxG.cameras.add(uiCamera, false);
+
+// add element to the camera
+hudElement.cameras = [uiCamera];
+
+FlxG.camera.bgColor = 0xff626a71;
+FlxG.camera.zoom = 0.5; // zoom only on the default camera
+
+

Debugger

+

Press ~ key to open it during runtime, or open by code with FlxG.debugger.visible = true.

+
// Log
+FlxG.log.add("My var: " + myVar);
+// or
+FlxG.log.redirectTraces = true;
+trace("My var: ", myVar);
+
+// Watch
+FlxG.watch.add(object, "property");
+
+// Add world space mouse position to watch list
+FlxG.watch.addMouse();
+
+// Create a tracker window for player (of class Player) showing "x", "y" and custom fields "jumping" and "ladder"
+FlxG.debugger.addTrackerProfile(new TrackerProfile(Player, ["x", "y", "jumping", "ladder"], []));
+FlxG.debugger.track(player, "Hero");
+
+

Hiding Cursor

+
FlxG.mouse.visible = false;
+
+

Adding Gravity

+
acceleration.y = 600;
+
+

Sort objects in FlxGroup

+
// sort by Y for top-down game
+group.sort(FlxSort.byY, FlxSort.ASCENDING);
+
+// sort with custom function (here: by Z)
+var group = new FlxTypedGroup<ZSprite>();
+group.sort(
+    function(order:Int, sprite1:ZSprite, sprite2:ZSprite):Int
+    {
+        return FlxSort.byValues(order, sprite1.z, sprite2.z);
+    },
+    FlxSort.ASCENDING
+);
+
+

FlxPoint Pool

+
// get from FlxPoint pool
+var tileSize = FlxPoint.get(16, 16);
+
+var actionTileset = FlxTileFrames.fromGraphic(FlxG.bitmap.add("assets/images/ui/actions.png"), tileSize);
+
+// release it back in pool to reuse
+tileSize.put();
+
+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/code-contributions/index.html b/documentation/code-contributions/index.html new file mode 100644 index 000000000..2634f0df8 --- /dev/null +++ b/documentation/code-contributions/index.html @@ -0,0 +1,316 @@ + + + + + + + + + + Code Contributions | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Code Contributions

+ + + Edit + +

Contributing code to HaxeFlixel is done all through the official git repositories on GitHub.

+

Use the Dev Branches

+

All repositories except the website and documentation use a dev branch which is the main entry point for features and bugfixes to accepted into the codebase. When the code is tested by the community it is then merged into master and released on haxelib.

+

To clarify: the dev branch on flixel-addons and flixel-demos is only compatible with the dev branch of flixel.

+

If you are making changes to the codebase that could include breaking changes or a new API, we make use of the pull request feature and suggest developers use a feature branch model. Feature branches are simply new branches with your code that are named with a title relating to your code.

+

Merge Approval

+

Before a major feature is merged into core our general workflow is to get approval from a core-contributor with push access.

+

Developers do have limited time so keep in mind some simple steps to get your pull request accepted:

+
    +
  • Clearly describe your use case or the problem/issue your code is developed for.
  • +
  • Conduct as much testing as possible on the supported targets of HaxeFlixel. If the code is for a specific target only make a clear note for developers to test.
  • +
  • Provide a link to a working, compilable demo of your code.
  • +
+

Contribute to the Stack

+

Everything about the technology stack of HaxeFlixel is open-source so you can contribute directly to the language, compiler and upstream libraries:

+ +

If you are wanting to contribute code, please review the style guide.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/code-style/index.html b/documentation/code-style/index.html new file mode 100644 index 000000000..092a63bd2 --- /dev/null +++ b/documentation/code-style/index.html @@ -0,0 +1,406 @@ + + + + + + + + + + Code Style | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Code Style

+ + + Edit + +

This page contains a few notes on HaxeFlixel's code style. Note that we use haxe-formatter to enforce consistent whitespace usage, bracket placement etc, so this page only focuses on naming conventions and other good practices not covered by an auto-formatter.

+

Functions

+

Function Names

+
function shootEnemy(target:Enemy, bullet:BulletType):Void
+
+

...is easier to read than

+
function shootAtASpecificEnemyWithABulletTypeOf(target:Enemy, bullet:BulletType):Void
+
+

...but still gets the idea of what this function does across. The second example has a lot of "noise"-words that don't provide any additional value. The following function name would still be acceptable, more accurate than example 1 even:

+
function shootBulletAtEnemy(target:Enemy, bullet:BulletType):Void
+
+

However, function names should also not be too short - you should be able to roughly know what a function does simply by reading its name - reading its description, if existent, should ideally not be necessary.

+

An example for a bad / too simple name would be shoot() instead of shootEnemy().

+

Parameter Names

+

Use lowerCamelCases for function parameters and use this to explicitly reference to class members (only when necessary):

+
function translate(words:String, bableFish:BableFish):Void
+{
+    this.words = words;
+}
+
+

Instead of:

+
function translate(Words:String, BableFish:BableFish):Void
+{
+    words = Words;
+}
+
+

In the core of HaxeFlixel, a lot of method parameters are capitalized (not preferred in Haxe). This is mostly legacy from the AS3 Flixel's code style and hard to change them all. However, newly written functions should follow the lowerCamelCase style.

+

Leveraging Type Inference

+

The Haxe compiler does not require you to declare the type of a variable (read more).

+
//This is unnecessary
+var name:String = "Merlin";
+var number:Int = 32;
+
+//This is preferred
+var name = "Merlin";
+var number = 32;
+
+

In some contexts however, doing so improves the readability of the code, for example because it's not immediately obvious what return type a function has:

+
var mystery:Answer = createAnAnswer();
+
+

Keyword Order

+

The original AS3 Flixel codebase ordered keywords like static public function. +HaxeFlixel has changed this convention to be more like every other (Haxe) library, the order of importance is as follows:

+
    +
  1. override
  2. +
  3. public / private
  4. +
  5. static
  6. +
  7. inline
  8. +
+

So static public function is changed to public static function. This also applies to variables eg public static var.

+

Field Order / Class Outline

+

The following rules apply, sorted by priority:

+
    +
  1. static fields before instance fields
  2. +
  3. public fields before private fields
  4. +
  5. regular variables before properties
  6. +
  7. getters and setters are the very end of a class (as they should always be private)
  8. +
+

Comments

+

Comments should only be used when you can't find a way to express the same thing in code. They tend to add noise to the code base and rarely get updated when the code changes, which results in misinformation and inaccurate comments.

+

Take the following comment section for example, it does not provide any additional value beyond what the code and the class / parameter names already tell you (one of the reasons why choosing good names is so important!). It should thus be removed completely.

+
/**
+ * Sets the position.
+ *
+ * @param    x    The x coordinate.
+ * @param    y     The y coordinate.
+ */
+public function setPosition(x:Int, y:Int):Void
+
+

Class Names

+

All type names should be prefixed by Flx, e.g.:

+
    +
  • FlxBasic
  • +
  • FlxObject
  • +
  • FlxSprite
  • +
  • etc..
  • +
+

Even though this is widely regarded as bad style, it still makes sense to follow this convention since it is so deeply ingrained into the flixel workflow and doing otherwise would be very inconsistent and confusing.

+

This convention does not come without its advantages, for example you can easily tell which classes belong to the engine and which ones don't when writing a game.

+

Under the hood types that HaxeFlixel devs will likely never see or use should not have the Flx prefix, this will serve as an indicator that they are off the beaten path.

+

Enum Value Names

+

The names of enum values are capitalized. The same convention applies to abstract enums.

+
enum FlxCameraFollowStyle
+{
+    LOCKON;
+    PLATFORMER;
+    TOPDOWN;
+    TOPDOWN_TIGHT;
+    SCREEN_BY_SCREEN;
+    NO_DEAD_ZONE;
+}
+
+

Using switch-case as an expression

+

Unlike in most other languages with object-oriented syntax, everything in Haxe is an expression. This extends to switch-case, meaning that it evaluates to a value. This value can be assigned to a variable, passed to a function or simply returned by a function:

+
function getColor(color:Color):Int
+{
+    return switch (color)
+    {
+        case Color.RED: 0xff0000;
+        case Color.BLUE: 0x0000ff;
+        case Color.GREEN: 0x00ff00;
+    }
+}
+
+

This is preferable to how this code would look like in a lot of other languages, for example C#:

+
int getColor(Color color) {
+    switch (color) {
+        case Color.RED:
+            return 0xff0000;
+        case Color.BLUE:
+            return 0x0000ff;
+        case Color.GREEN:
+            return 0x00ff00;
+    }
+    return 0x000000;
+}
+
+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/community-tutorials/index.html b/documentation/community-tutorials/index.html new file mode 100644 index 000000000..ee4036c16 --- /dev/null +++ b/documentation/community-tutorials/index.html @@ -0,0 +1,272 @@ + + + + + + + + + + Community Tutorials | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Community Tutorials

+ + + Edit + +

While we try our best to make good documentation and a good example tutorial, we can only do so much! +So this will be a big list to various external Community Tutorials made by other people!

+

Written

+ +

Videos

+ + + +
+
+ +
    + + + + + + + +
+ + +
+
+
+ + + + + + + + diff --git a/documentation/community/index.html b/documentation/community/index.html new file mode 100644 index 000000000..63e3a022e --- /dev/null +++ b/documentation/community/index.html @@ -0,0 +1,297 @@ + + + + + + + + + + Community | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Community

+ + + Edit + +

HaxeFlixel is a collaborative project from contributors all over the world.

+

If you need help or just want to chat , HaxeFlixel has a...

+ +

Other HaxeFlixel-related pages:

+ + + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/compiler-conditionals/index.html b/documentation/compiler-conditionals/index.html new file mode 100644 index 000000000..c510bbe02 --- /dev/null +++ b/documentation/compiler-conditionals/index.html @@ -0,0 +1,302 @@ + + + + + + + + + + Compiler Conditionals | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Compiler Conditionals

+ + + Edit + +

The Haxe compiler provides a robust solution for cross-platform development where you can use operators to define what targets receive your code. This functionality is invaluable for HaxeFlixel since we are targeting native mobile / desktop and web targets, all with different capabilities.

+

Conditional Compilation in the Haxe Manual

+

A basic example may include logic like this:

+
#if desktop
+
+// desktop only code
+
+#elseif mobile
+
+// mobile only code
+
+#end
+
+

Conditionals relevant to your HaxeFlixel games may include:

+
    +
  • mobile, desktop, web
  • +
  • ios, android, windows, mac, linux, html5
  • +
  • flash, cpp, neko, js
  • +
+

Multiple targets can be used together:

+
#if (mac || linux || android)
+
+// code specific for these platforms
+
+#end
+
+

To define your own it is as easy as adding to your Project.xml:

+
<haxedef name="magic" />
+
+

Now this will work:

+
#if magic
+// Create a dragon
+#end
+
+

Since Haxe lets you use some logic with the conditionals you can enable something just for mobile, as in:

+
<haxedef name="magic" if="mobile"/>
+
+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/conclusion/index.html b/documentation/conclusion/index.html new file mode 100644 index 000000000..cc9144eb9 --- /dev/null +++ b/documentation/conclusion/index.html @@ -0,0 +1,304 @@ + + + + + + + + + + Conclusion | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Conclusion

+ + + Edit + +

Now we have a pretty complete, working game! It's not too complex, but it should give you a full, well-rounded idea of how to make your own games in HaxeFlixel. I really hope you've enjoyed this tutorial, and take the time to play around with the code some more to try expanding the game even further. You could add more levels, add stairway objects to move between them, add more enemy types, and collectibles, and upgrades… the list goes on.

+

As mentioned previously, you can grab the complete source code for the game here.

+

The power of HaxeFlixel comes from it's balance of simplicity and versatility. With only a few lines of code you can do almost anything you can think of.

+

If you want to learn more about using HaxeFlixel, take a look at the documentation, and API for lots more in-depth information.

+

I'd like to thank Jens Fischer, Justo Delgado Baudí, the STL IGDA, and the HaxeFlixel Dev Community for helping me get this tutorial finished - a lot of editing and suggestions for improvement came from these people.

+

If you enjoyed this tutorial, if it helped you in some way, or if you have suggestions, I always appreciate feedback. You can let me know at seifertim@gmail.com or on twitter: @seifertim.

+

Thanks, and happy coding!

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/contributing/index.html b/documentation/contributing/index.html new file mode 100644 index 000000000..99068f3cc --- /dev/null +++ b/documentation/contributing/index.html @@ -0,0 +1,311 @@ + + + + + + + + + + Contributing | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Contributing

+ + + Edit + +

We welcome new contributors to this project. +Being open source and followed by people all over the world, you can help in many ways.

+

HaxeFlixel is a an open-source project with humble beginnings +sparked from a passion for the technology and game development. Everyone working on this project has come together +to create a friendly and flexible approach so that this library and community is not only enjoyable, but a robust solution for cross-platform 2D games.

+

Contribute Code

+

We are built on code contributions, which we gladly welcome - see the code contributions page.

+

Publicize HaxeFlixel

+

Help spread the word! What you can do to help:

+
    +
  • Star our GitHub Repository.
  • +
  • Follow us on Twitter.
  • +
  • Talk about us on social media: Twitter, blogs, forums.
  • +
  • Write about your experiences of HaxeFlixel on your favorite blog, social network.
  • +
  • Write about what you are doing with HaxeFlixel to inspire others by using our forum or your own site.
  • +
  • Record a video about your use or tutorial using HaxeFlixel.
  • +
  • Make an awesome game and attribute HaxeFlixel as the technology that helped make it happen ;)
  • +
+

Donations

+

HaxeFlixel is currently accepting donations via its Patreon page.

+

Please read this blog post to understand how the funds will be distributed.

+

@gamedevsam is the current treasurer for HaxeFlixel, contact him if you have any questions or suggestions regarding the use of donated funds.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/creating-a-new-project/index.html b/documentation/creating-a-new-project/index.html new file mode 100644 index 000000000..da84cc69f --- /dev/null +++ b/documentation/creating-a-new-project/index.html @@ -0,0 +1,343 @@ + + + + + + + + + + 2 - Creating a new project | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

2 - Creating a new project

+ + + Edit + +

Now we want to make sure that everything is installed properly - and we want to set up the framework for our game. So we're going to make a new project, open it with VSCode and test that it builds and runs.

+
    +
  1. In the command prompt, enter:

    +
     flixel tpl -n "TurnBasedRPG" -ide vscode
    +
    +

    This will create a new Flixel project using the blank template in the directory TurnBasedRPG (as well as naming the project TurnBasedRPG).

    +
  2. +
  3. Depending on how you've configured flixel-tools and whether the code command is available, flixel tpl might already have opened a VSCode window with the right folder automatically.

    +

    If not, simply open the TurnBasedRPG folder with File > Open Folder....

    +
  4. +
  5. Over on the left side of the screen, you should see your project. This will contain all the files that the template generated for us.

    +

    +
  6. +
  7. Next, let's make sure that our project builds and runs properly. By default, a fresh, new Flixel template project will launch the game in the PlayState. So go ahead and double-click to open that file from the project list. + This file is a very basic (and empty) example of a FlxState subclass. You can think of a FlxState a little bit like a 'scene'. When your game is running, one - and only one - state will be the active state. Anything 'added' to that state will be visible and accessible by the player, and, for the most part, will be segregated from other states in your game.

    +

    They are great for having different sections of your game that are sort of in a bubble from one another, such as a MenuState (which we will add later) and the PlayState (where the game is actually played).

    +

    You'll see that, at least for now, the PlayState only has two functions in it: create() and update(). When a state is loaded, its create() function is called. This is where you want to initialize all of the things in your state.

    +

    update() is where all the real magic happens - it is called every 'frame' in your game (by default 60 times per second). When a FlxState's update() is called, it will call update() on all of the objects that have been added to it. This is basically how everything in your game actually 'happens'. We will get to play with this more later on. + For now, we JUST want to see that the whole thing works, so, we're going to add a simple FlxText object to this state.

    +
  8. +
  9. In create(), right before the line that says super.create();, type out the following two lines:

    +
     var text = new FlxText(10, 10, 100, "Hello, World!");
    + add(text);
    +
    +

    While you're typing, code completion should pop up and suggest FlxText.

    +

    +

    Here, press Enter or simply type a ( - notice how the following lines has automatically been added to your imports at the top of the file:

    +
     import flixel.text.FlxText;
    +
    +

    Then save your changes (or simply enable auto-save via File > Auto Save).

    +
  10. +
  11. The moment of truth! Go down to the status bar in VSCode and verify that the HTML5 target is selected in the lower left:

    +

    +

    Then run the "build task" (or press the keyboard shortcut for it)!

    +

    +

    After a short moment, your default browser should pop up with a HaxeFlixel splash screen and then the text we just added:

    +

    +

    It worked! You've built and ran your first HaxeFlixel project!

    +

    At this point, you could try building it for Neko, Windows and Android to make sure they all work as well. If you run into problems with any of those, double-check your code, check out the OpenFL installation information, and if that doesn't help, get in touch with the community.

    +

    This is only a small step towards bigger and better things! In the next part, we'll actually define the game we're going to be building, and start putting it together!

    +
  12. +
+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/creating-a-tilemap/index.html b/documentation/creating-a-tilemap/index.html new file mode 100644 index 000000000..3bc6253c0 --- /dev/null +++ b/documentation/creating-a-tilemap/index.html @@ -0,0 +1,336 @@ + + + + + + + + + + 5 - Creating a Tilemap | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

5 - Creating a Tilemap

+ + + Edit + +

Now it's time to make some maps for the player to move around in! To do this, we're going to use a tool called Ogmo Editor. Ogmo is a free tilemap editor that works very nicely with HaxeFlixel. For this part of the tutorial, we're just going to use a simple 2-tile tilesheet with a tile for walls and a tile for floors.

+

You can make your own, with 16x16 pixel tiles, or use this one:

+

+

(Note: the first tile should be empty!)

+
    +
  1. Download and install Ogmo Editor 3, then launch it.

    +
  2. +
  3. Click on New Project and navigate to assets/data - save the project as turnBasedRPG.ogmo.

    +
  4. +
  5. On the General tab, you can rename your project, set the default level sizes, and more. Set it up like this:

    +

    +
  6. +
  7. On the Layers tab, make an Entity Layer called entities and a Tile Layer called walls:

    +

    +
  8. +
  9. On the Entities tab, make an entity called player:

    +

    +
  10. +
  11. Finally, on the Tilesets tab, make a new tileset called tiles and load the tiles from earlier:

    +

    +
  12. +
  13. When you're done, click on Save and you'll be brought to this screen:

    +

    +
  14. +
  15. Make sure you're on the walls layer, and using the tools at the top, draw out a simple map. Make sure it's completely encircled by walls (so the player can't wander off the map), and make the insides filled with floor tiles. You should end up with something like this:

    +

    +
  16. +
  17. Now, switch over to the 'entities' layer, and place your player entity somewhere in one of your rooms:

    +

    +
  18. +
  19. Hit Ctrl+S (Cmd+S on Mac), and save this level as room-001.json in assets/data.

    +
  20. +
+

We're done with Ogmo for now, so save all your changes and exit.

+

In the next part, we will learn how to load the newly created tilemap into our game.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/debugger-interaction/index.html b/documentation/debugger-interaction/index.html new file mode 100644 index 000000000..984a1f177 --- /dev/null +++ b/documentation/debugger-interaction/index.html @@ -0,0 +1,335 @@ + + + + + + + + + + Debugger - Interaction | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Debugger - Interaction

+ + + Edit + +

The interaction tool (enabled by the button in the debugger overlay) allows you to change game elements, e.g. move sprites, while the game is still running.

+

It is highly recommended, however, that you pause the game using VCR's pause button before using the interaction tool. You can always resume the game by clicking VCR's play button after you are done with the interaction. If the game is not paused during the interaction, objects affected by acceleration, for instance, will continue to move, making your work harder.

+

Interaction tools

+

When the interaction is enabled, a toolbar containing a few related tools is displayed on the left side of the screen. Below is a description of each tool.

+

Pointer

+

The pointer tool allows you to select game elements. In order to use it, simply click elements on the screen:

+

+

Currently only elements that extend FlxSprite can be selected (which exclude tiles of a tilemap, for instance). Elements that belong to your selection will be highlighted in red. If you click an empty space, the selection will be discarded.

+

You can add/remove elements to/from your existing selection by holding CTRL when you click elements. It is also possible to add/remove a group of elements by clicking and dragging the mouse cursor to create a selection area:

+

+

If you press the DELETE key when elements are selected, the debugger will invoke the kill() method of each element in that selection. You can also press DELETE while holding SHIFT to invoke the kill() method and additionally remove the elements from memory, i.e. elements will be removed from Flixel's display list.

+

Mover

+

The mover tool allows you to move game objects that were selected by the pointer tool. In order to use this functionality, select any element(s) using the pointer tool, then pick the mover tool and click-and-drag anywhere on the screen:

+

+

The selected elements will follow the movement of the mouse cursor until you release the mouse button.

+

The mover tool is also activated while the SHIFT key is kept pressed, so you can move selected elements at any time, even when any other tool is active. After performing a selection, hold SHIFT then click-and-drag anywhere on the screen to move the selected element(s):

+

+

When you stop pressing SHIFT, the element(s) will stop moving and your previously active tool will become effective again.

+

Transform

+

The transform tool allows you to resize and rotate a selected game object. In order to use this functionality, select a single element using the pointer tool, then pick the transform tool and click-and-drag any of the markers around the object:

+

+

The circular marker at the top-left corner of the selected object can be used to rotate it, while the squared markers can be used to resize it.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/debugger/index.html b/documentation/debugger/index.html new file mode 100644 index 000000000..3a37c7aed --- /dev/null +++ b/documentation/debugger/index.html @@ -0,0 +1,439 @@ + + + + + + + + + + Debugger | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Debugger

+ + + Edit + +

Flixel comes with a fairly powerful debugging overlay. You can open it with one of the default toggle keys (F2, ` and \ with a QWERTY keyboard layout). Note that these are configurable via FlxG.debugger.toggleKeys. Alternatively, you can do the same in code via the FlxG.debugger.visible flag.

+

Note that the debugger does not exist when compiling with FLX_NO_DEBUG. With the default Project.xml, this is the case in release mode. On the command line, use the -debug flag to build in debug mode instead (e.g. lime test neko -debug).

+

+

Debug draw

+

FlxG.debugger.drawDebug can be enabled to display the hitboxes of every FlxObject added to the state (alternatively, press the cube button in the upper right corner of the debugger).

+

+

The hitboxes are color-coded based on the collision properties. For FlxObject and FlxSprite this means:

+
    +
  • Blue for allowCollisions == NONE
  • +
  • Green for immovable objects
  • +
  • Red otherwise
  • +
+

The color is customizable via the debugBoundingBoxColor property.

+

The behavior of tiles in FlxTilemap is slightly different:

+
    +
  • Blue for allowCollisions == NONE
  • +
  • Green for allowCollisions == ANY
  • +
  • Pink for other values of allowCollisions
  • +
+

The Log Window

+

The log window is used to display traces and can be accessed via FlxG.log. You can also redirect any trace()-calls to it with FlxG.log.redirectTraces = true;. Using it is mostly a matter of preference, some people prefer to have their traces displayed in their IDE of choice (FlashDevelop's output panel for example).

+

Some flixel-internal errors will also be output to the log window.

+

Log styles

+

It's possible to customize things like text color, size, style or add a prefix by using log styles. FlxG.log.warn(), error() and notice() use pre-defined log styles.

+

Here's an example of how you could differentiate each trace by the player from others by adding a [Player] prefix and printing it in green:

+
var playerAction = new LogStyle("[Player]", "00FF40");
+FlxG.log.advanced(" Shoot", playerAction);
+
+

The Watch Window

+

It's very common to use trace()-calls to output the value of certain variables for debugging. However, this approach doesn't scale very well - at 60 fps, tracing the values of multiple variables results in a flood of messages. Breakpoints-debugging is great to inspect a game's internal state, but doesn't help when interrupting the execution is not an option, for example when debugging input logic.

+

This is where the watch window comes into play. It displays the values of variables using reflection. For example, to keep track of the player's position:

+
FlxG.watch.add(_player, "x");
+FlxG.watch.add(_player, "y");
+
+

The display string does not have to be the same as the variable's name, "numEnemies" is much more descriptive than "length" in this example:

+
FlxG.watch.add(_enemies, "length", "numEnemies");
+
+

+

For static variables, you pass the class instead of an object:

+
FlxG.watch.add(FlxG, "height");
+
+

It's also possible to edit the displayed values by clicking on them, entering a new value in the text field and pressing enter to confirm. This even works with FlxPoint objects.

+

To remove a watch entry again, simply call FlxG.watch.remove(object, variableName).

+

Quick watches

+

Quick watches are a lightweight alternative to a regular watch entry. They don't require a variable, they simply store a value for a String name. The following example stores the result of FlxG.keys.anyPressed(["UP", "W"]) under the name "Up key pressed" - this is updated every frame since it happens in update().

+
override public function update():Void
+{
+    super.update();
+    FlxG.watch.addQuick("Up key pressed", FlxG.keys.anyPressed(["UP", "W"]));
+}
+
+

To remove a quick watch entry, call FlxG.watch.removeQuick(name). +Quick watch values can not be modified.

+

Mouse watch

+

FlxG.watch.addMouse() is a convenient helper to display the current mouse position in the watch window. This can be useful to find the right coordinates to position UI elements at. You can also use the console command watchMouse to call this function.

+

The Stats Window

+

The stats window displays some basic profiling info:

+
    +
  1. FPS value
  2. +
  3. Memory usage in MB
  4. +
  5. The amount of update() calls this frame (and the time it took in ms)
  6. +
  7. The amount of draw() calls this frame (and the time it took in ms)
  8. +
  9. The size of the FlxQuadtree pool for collision detection
  10. +
  11. The size of the FlxList (used for quad trees) pool
  12. +
+

3 and 4 are especially useful when it comes to performance optimization ("Do I need to optimize my rendering or my update-logic?"). Of course this is only very basic data, profiling tools like Adobe Scout or hxScout provide much more detailed information.

+

+

The Bitmap Log Window

+

The Bitmap Log can be used to display BitmapData objects via FlxG.bitmapLog.add(bitmapData). This can be useful to debug logic that manipulates some BitmapData. The window provides a slideshow to scroll through logged bitmaps. You can use the middle mouse button to move the graphic around and the mouse wheel to zoom in and out.

+

You can also inspect flixel's internal BitmapData cache by calling FlxG.bitmapLog.viewCache() or entering the console command viewCache.

+

+

The Console Window

+

The console allows a limited subset of Haxe code to be parsed and executed at runtime via hscript. Commands like state._player.x = 50 or state._player.jump() as you'd expect. Especially on targets with long compile times, this can speed up development substantially.

+

It also supports auto completion for class fields and registered functions / objects / classes, similar to the completion popups in IDEs (albeit without documentation, which is not available at runtime).

+

+

state is the starting point for hscript and needs to be registered to the console to be available - Flixel already does this for you. The same goes for a few classes like FlxG or Math. To register further objects or classes, call FlxG.console.registerObject().

+

By default, the game is paused when the console text field receives focus. After a command is executed, the game progresses one frame so the effects can be seen.

+

The console stores executed commands (use the up and down keys to cycle through them). This history is persistent across executions of your game (but not across different target platforms).

+

Adding custom commands

+

Functions can also be registered to the console directly as commands via FlxG.console.registerFunction(). Here's an example with a function called "spawnEnemy", spawning a new enemy at the current mouse position in the Mode demo.

+
// in PlayState#create()
+FlxG.console.registerFunction("spawnEnemy", function() {
+    var mousePos = FlxG.mouse.getWorldPosition();
+    var enemy = _enemies.recycle(Enemy);
+    enemy.init(Std.int(mousePos.x), Std.int(mousePos.y), _enemyBullets, _bigGibs, _player);
+});
+
+

Tracker Windows

+

Tracker windows are a convenient way to inspect the most important properties of a class / object. Each tracker window is basically a watch window instance. It's the only window type that can be closed.

+

A tracker profile defines the properties that should be watched for a specific class. Let's take a look at the pre-defined tracker profile for FlxSprite:

+
new TrackerProfile(FlxSprite, ["frameWidth", "frameHeight", "alpha", "origin", "offset", "scale"], [FlxObject])
+
+

The first argument determines the class the profile belongs to, the second is an Array<String> containing the property names. The third argument is a list of extensions - in this case just FlxObject. This means that the properties defined in the tracker profile of FlxObject will be added to tracker windows for FlxSprite as well. This works recursively - FlxObject "extends" the FlxBasic tracker profile, so any properties of that profile will be added as well. This is why FlxG.debugger.track(_player) in Mode's PlayState#create() creates a window with a longer list of properties than you'd initially expect from the FlxSprite profile:

+

+

Alternatively, you can use the console to create tracker windows at runtime:

+

track(FlxG.state._player)

+

The real power of tracker windows comes with the ability to define custom profiles, for example for the Player class in Mode:

+
FlxG.debugger.addTrackerProfile(new TrackerProfile(Player, ["isReadyToJump", "_shootCounter", "_jumpPower"], [FlxBasic]));
+
+

(Note: calling addTrackerProfile() causes a crash on the latest haxelib release due to a bug. As a workaround, you can call FlxG.debugger.track(null); beforehand).

+

+

The VCR

+

Flixel's VCR feature (recording and replaying via FlxG.vcr) is mostly disabled by default and can be activated with the FLX_RECORD define. Even so, a few features are still available by default via the middle three buttons of the debugger:

+

+

The left button resets the current state via FlxG.resetState().

+

The middle button pauses / unpauses the game.

+

The right button pauses the game if it isn't already paused and skips ahead exactly one frame (one update() and one draw() call). This can be very useful for debugging certain issues.

+

If FLX_RECORD is defined, two more buttons are available:

+

+

The circle starts a new recording - it also resets the current state, since the VCR does not support recordings that start mid-state. If a recording has already been started, the button stops it and opens a file dialog to save it.

+

The button with the folder icon right allows loading record files and replaying them.

+

Adding Debugger Buttons

+

You can add custom buttons to the debugger header using FlxG.debugger.addButton(). This is what FlxNapeState from flixel-addons does if you use it - it adds a convenient "N" button to toggle Nape's debug draw.

+

+

Debugger buttons are persistent across states - FlxG.debugger.removeButton() has to be called manually to remove state-specific buttons.

+

Debugger Layouts

+

A debugger layout determines the initial position and size of each debugger window. The available layouts are described in the FlxDebuggerLayout enum. You can change the current layout by calling FlxG.debugger.setLayout().

+

Here's an example of FlxDebuggerLayout.RIGHT:

+

+

The Interaction Tool

+

The Interaction Tool, enabled by the icon in the debugger overlay, allows you to change game elements, e.g. move sprites, while the game is still running. Click here to learn more about the interaction tool.

+

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/desktop-targets/index.html b/documentation/desktop-targets/index.html new file mode 100644 index 000000000..785a7a95f --- /dev/null +++ b/documentation/desktop-targets/index.html @@ -0,0 +1,345 @@ + + + + + + + + + + Desktop Targets | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Desktop Targets

+ + + Edit + +

The desktop targets of HaxeFlixel run on all mainstream operating systems (OSX, Windows and Linux). They are all compiled to C++ through the Hxcpp library and are rendered through interfacing with the Simple DirectMedia Layer. The code for this part of the library is developed through NME which provides dll libs that openfl interfaces with.

+

The biggest advantage of desktop targets compared to web and mobile is the power of desktop CPU and GPU processors. More complex scenes, physics and number of objects rendered can give a larger creative freedom in the games you create.

+

Rendering in HaxeFlixel is done through the drawTiles API. OpenGL textures are used with the GPU to render Flixel sprites. This native C++ code and use of the GPU outperforms runtimes such as the Flash Player and Adobe AIR in most circumstances substantially.

+

Conditionals

+
#if cpp
+//your desktop code
+#end
+
+#if desktop
+//your desktop code
+#end
+

Project XML Settings

+

Desktop platforms can use a window width and height of 0, which is a special value that uses the full resolution of the current display.

+
<window width="0" height="0" background="#FFFFFF" fps="60" />
+
+

OpenFL also exposes the following specific settings for the desktop target:

+
<window hardware="true" allow-shaders="true" require-shaders="true" if="cpp"/>
+<window vsync="true" antialiasing="4" if="cpp" />
+<window orientation="portrait" /> || <window orientation="landscape" if="cpp"/>
+
+

Compile Commands

+

Visual Studio Code, FlashDevelop and IntelliJ IDEA support CPP desktop compilation through their GUI.

+

Command Line

+

The basic command to compile and test a native desktop target:

+
lime test windows
+lime test mac
+lime test linux -64
+

Run this command from the root folder of your project, the default project.xml will be used automatically. Using the test command will automatically launch the application created.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/documentation/images/00_getting_started/fd-appman-flixel.jpg b/documentation/documentation/images/00_getting_started/fd-appman-flixel.jpg new file mode 100644 index 000000000..7a5d61b86 Binary files /dev/null and b/documentation/documentation/images/00_getting_started/fd-appman-flixel.jpg differ diff --git a/documentation/documentation/images/00_getting_started/fd-flixel-screenshots.psd b/documentation/documentation/images/00_getting_started/fd-flixel-screenshots.psd new file mode 100644 index 000000000..f43d91621 Binary files /dev/null and b/documentation/documentation/images/00_getting_started/fd-flixel-screenshots.psd differ diff --git a/documentation/documentation/images/00_getting_started/fd-flixel-template.jpg b/documentation/documentation/images/00_getting_started/fd-flixel-template.jpg new file mode 100644 index 000000000..92c3817f9 Binary files /dev/null and b/documentation/documentation/images/00_getting_started/fd-flixel-template.jpg differ diff --git a/documentation/documentation/images/00_getting_started/hello-world.png b/documentation/documentation/images/00_getting_started/hello-world.png new file mode 100644 index 000000000..73d33fc49 Binary files /dev/null and b/documentation/documentation/images/00_getting_started/hello-world.png differ diff --git a/documentation/documentation/images/00_getting_started/vscode/change-config.gif b/documentation/documentation/images/00_getting_started/vscode/change-config.gif new file mode 100644 index 000000000..65dab8300 Binary files /dev/null and b/documentation/documentation/images/00_getting_started/vscode/change-config.gif differ diff --git a/documentation/documentation/images/00_getting_started/vscode/completion.png b/documentation/documentation/images/00_getting_started/vscode/completion.png new file mode 100644 index 000000000..297225256 Binary files /dev/null and b/documentation/documentation/images/00_getting_started/vscode/completion.png differ diff --git a/documentation/documentation/images/00_getting_started/vscode/flash-debugging.png b/documentation/documentation/images/00_getting_started/vscode/flash-debugging.png new file mode 100644 index 000000000..3f602828a Binary files /dev/null and b/documentation/documentation/images/00_getting_started/vscode/flash-debugging.png differ diff --git a/documentation/documentation/images/00_getting_started/vscode/launch-configs.png b/documentation/documentation/images/00_getting_started/vscode/launch-configs.png new file mode 100644 index 000000000..fcfb32057 Binary files /dev/null and b/documentation/documentation/images/00_getting_started/vscode/launch-configs.png differ diff --git a/documentation/documentation/images/00_getting_started/vscode/lime-dropdowns.png b/documentation/documentation/images/00_getting_started/vscode/lime-dropdowns.png new file mode 100644 index 000000000..fac1265c5 Binary files /dev/null and b/documentation/documentation/images/00_getting_started/vscode/lime-dropdowns.png differ diff --git a/documentation/documentation/images/00_getting_started/vscode/lime-installation.png b/documentation/documentation/images/00_getting_started/vscode/lime-installation.png new file mode 100644 index 000000000..7a485ee6b Binary files /dev/null and b/documentation/documentation/images/00_getting_started/vscode/lime-installation.png differ diff --git a/documentation/documentation/images/00_getting_started/vscode/problems.png b/documentation/documentation/images/00_getting_started/vscode/problems.png new file mode 100644 index 000000000..682642d55 Binary files /dev/null and b/documentation/documentation/images/00_getting_started/vscode/problems.png differ diff --git a/documentation/documentation/images/00_getting_started/vscode/run-build-task.png b/documentation/documentation/images/00_getting_started/vscode/run-build-task.png new file mode 100644 index 000000000..05cc962d3 Binary files /dev/null and b/documentation/documentation/images/00_getting_started/vscode/run-build-task.png differ diff --git a/documentation/documentation/images/00_getting_started/vscode/tasks.png b/documentation/documentation/images/00_getting_started/vscode/tasks.png new file mode 100644 index 000000000..5585bfaba Binary files /dev/null and b/documentation/documentation/images/00_getting_started/vscode/tasks.png differ diff --git a/documentation/documentation/images/00_getting_started/vscode/terminal.png b/documentation/documentation/images/00_getting_started/vscode/terminal.png new file mode 100644 index 000000000..085a18cc9 Binary files /dev/null and b/documentation/documentation/images/00_getting_started/vscode/terminal.png differ diff --git a/documentation/documentation/images/00_getting_started/vscode/vscode-plus-extensions.png b/documentation/documentation/images/00_getting_started/vscode/vscode-plus-extensions.png new file mode 100644 index 000000000..cb74618c7 Binary files /dev/null and b/documentation/documentation/images/00_getting_started/vscode/vscode-plus-extensions.png differ diff --git a/documentation/documentation/images/01_tutorial/browser_animated_player.gif b/documentation/documentation/images/01_tutorial/browser_animated_player.gif new file mode 100644 index 000000000..13e530256 Binary files /dev/null and b/documentation/documentation/images/01_tutorial/browser_animated_player.gif differ diff --git a/documentation/documentation/images/01_tutorial/browser_blue_dot.png b/documentation/documentation/images/01_tutorial/browser_blue_dot.png new file mode 100644 index 000000000..de5822b8d Binary files /dev/null and b/documentation/documentation/images/01_tutorial/browser_blue_dot.png differ diff --git a/documentation/documentation/images/01_tutorial/browser_blue_square.png b/documentation/documentation/images/01_tutorial/browser_blue_square.png new file mode 100644 index 000000000..de5822b8d Binary files /dev/null and b/documentation/documentation/images/01_tutorial/browser_blue_square.png differ diff --git a/documentation/documentation/images/01_tutorial/browser_coins.png b/documentation/documentation/images/01_tutorial/browser_coins.png new file mode 100644 index 000000000..74acfe52d Binary files /dev/null and b/documentation/documentation/images/01_tutorial/browser_coins.png differ diff --git a/documentation/documentation/images/01_tutorial/browser_combat_hud.png b/documentation/documentation/images/01_tutorial/browser_combat_hud.png new file mode 100644 index 000000000..f1ee5cd08 Binary files /dev/null and b/documentation/documentation/images/01_tutorial/browser_combat_hud.png differ diff --git a/documentation/documentation/images/01_tutorial/browser_enemy_brain.png b/documentation/documentation/images/01_tutorial/browser_enemy_brain.png new file mode 100644 index 000000000..2e96beada Binary files /dev/null and b/documentation/documentation/images/01_tutorial/browser_enemy_brain.png differ diff --git a/documentation/documentation/images/01_tutorial/browser_hello_world.png b/documentation/documentation/images/01_tutorial/browser_hello_world.png new file mode 100644 index 000000000..db0c07489 Binary files /dev/null and b/documentation/documentation/images/01_tutorial/browser_hello_world.png differ diff --git a/documentation/documentation/images/01_tutorial/browser_hud.png b/documentation/documentation/images/01_tutorial/browser_hud.png new file mode 100644 index 000000000..706795fa3 Binary files /dev/null and b/documentation/documentation/images/01_tutorial/browser_hud.png differ diff --git a/documentation/documentation/images/01_tutorial/browser_map_debugger.png b/documentation/documentation/images/01_tutorial/browser_map_debugger.png new file mode 100644 index 000000000..e5ccae7aa Binary files /dev/null and b/documentation/documentation/images/01_tutorial/browser_map_debugger.png differ diff --git a/documentation/documentation/images/01_tutorial/browser_options.png b/documentation/documentation/images/01_tutorial/browser_options.png new file mode 100644 index 000000000..56c43ad54 Binary files /dev/null and b/documentation/documentation/images/01_tutorial/browser_options.png differ diff --git a/documentation/documentation/images/01_tutorial/browser_zoomed.png b/documentation/documentation/images/01_tutorial/browser_zoomed.png new file mode 100644 index 000000000..14197c68f Binary files /dev/null and b/documentation/documentation/images/01_tutorial/browser_zoomed.png differ diff --git a/documentation/documentation/images/01_tutorial/ogmo_editor_blank.png b/documentation/documentation/images/01_tutorial/ogmo_editor_blank.png new file mode 100644 index 000000000..37da506d3 Binary files /dev/null and b/documentation/documentation/images/01_tutorial/ogmo_editor_blank.png differ diff --git a/documentation/documentation/images/01_tutorial/ogmo_editor_entities.png b/documentation/documentation/images/01_tutorial/ogmo_editor_entities.png new file mode 100644 index 000000000..3b9ead979 Binary files /dev/null and b/documentation/documentation/images/01_tutorial/ogmo_editor_entities.png differ diff --git a/documentation/documentation/images/01_tutorial/ogmo_editor_entities_coins.png b/documentation/documentation/images/01_tutorial/ogmo_editor_entities_coins.png new file mode 100644 index 000000000..7f0a77556 Binary files /dev/null and b/documentation/documentation/images/01_tutorial/ogmo_editor_entities_coins.png differ diff --git a/documentation/documentation/images/01_tutorial/ogmo_editor_entities_enemies.png b/documentation/documentation/images/01_tutorial/ogmo_editor_entities_enemies.png new file mode 100644 index 000000000..588cdb2da Binary files /dev/null and b/documentation/documentation/images/01_tutorial/ogmo_editor_entities_enemies.png differ diff --git a/documentation/documentation/images/01_tutorial/ogmo_editor_tiles.png b/documentation/documentation/images/01_tutorial/ogmo_editor_tiles.png new file mode 100644 index 000000000..ba298310c Binary files /dev/null and b/documentation/documentation/images/01_tutorial/ogmo_editor_tiles.png differ diff --git a/documentation/documentation/images/01_tutorial/ogmo_project_entities.png b/documentation/documentation/images/01_tutorial/ogmo_project_entities.png new file mode 100644 index 000000000..ed8d1c8a7 Binary files /dev/null and b/documentation/documentation/images/01_tutorial/ogmo_project_entities.png differ diff --git a/documentation/documentation/images/01_tutorial/ogmo_project_entities_coin.png b/documentation/documentation/images/01_tutorial/ogmo_project_entities_coin.png new file mode 100644 index 000000000..f51d94610 Binary files /dev/null and b/documentation/documentation/images/01_tutorial/ogmo_project_entities_coin.png differ diff --git a/documentation/documentation/images/01_tutorial/ogmo_project_entities_enemies.png b/documentation/documentation/images/01_tutorial/ogmo_project_entities_enemies.png new file mode 100644 index 000000000..4898f9b6e Binary files /dev/null and b/documentation/documentation/images/01_tutorial/ogmo_project_entities_enemies.png differ diff --git a/documentation/documentation/images/01_tutorial/ogmo_project_general.png b/documentation/documentation/images/01_tutorial/ogmo_project_general.png new file mode 100644 index 000000000..c75d0500e Binary files /dev/null and b/documentation/documentation/images/01_tutorial/ogmo_project_general.png differ diff --git a/documentation/documentation/images/01_tutorial/ogmo_project_layers.png b/documentation/documentation/images/01_tutorial/ogmo_project_layers.png new file mode 100644 index 000000000..7699c14f3 Binary files /dev/null and b/documentation/documentation/images/01_tutorial/ogmo_project_layers.png differ diff --git a/documentation/documentation/images/01_tutorial/ogmo_project_tilesets.png b/documentation/documentation/images/01_tutorial/ogmo_project_tilesets.png new file mode 100644 index 000000000..4b7d3b893 Binary files /dev/null and b/documentation/documentation/images/01_tutorial/ogmo_project_tilesets.png differ diff --git a/documentation/documentation/images/01_tutorial/vscode_files.png b/documentation/documentation/images/01_tutorial/vscode_files.png new file mode 100644 index 000000000..3d9575084 Binary files /dev/null and b/documentation/documentation/images/01_tutorial/vscode_files.png differ diff --git a/documentation/documentation/images/01_tutorial/vscode_flxtext_completion.png b/documentation/documentation/images/01_tutorial/vscode_flxtext_completion.png new file mode 100644 index 000000000..02a279f7e Binary files /dev/null and b/documentation/documentation/images/01_tutorial/vscode_flxtext_completion.png differ diff --git a/documentation/documentation/images/01_tutorial/vscode_override_completion.png b/documentation/documentation/images/01_tutorial/vscode_override_completion.png new file mode 100644 index 000000000..f73409ec6 Binary files /dev/null and b/documentation/documentation/images/01_tutorial/vscode_override_completion.png differ diff --git a/documentation/documentation/images/01_tutorial/vscode_run_build_task.png b/documentation/documentation/images/01_tutorial/vscode_run_build_task.png new file mode 100644 index 000000000..f629cbd55 Binary files /dev/null and b/documentation/documentation/images/01_tutorial/vscode_run_build_task.png differ diff --git a/documentation/documentation/images/01_tutorial/vscode_target_selection.png b/documentation/documentation/images/01_tutorial/vscode_target_selection.png new file mode 100644 index 000000000..aaf4b2cda Binary files /dev/null and b/documentation/documentation/images/01_tutorial/vscode_target_selection.png differ diff --git a/documentation/documentation/images/02_handbook/debugger/console-completion.png b/documentation/documentation/images/02_handbook/debugger/console-completion.png new file mode 100644 index 000000000..f5d6cc8b8 Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/console-completion.png differ diff --git a/documentation/documentation/images/02_handbook/debugger/debugger-overlay.png b/documentation/documentation/images/02_handbook/debugger/debugger-overlay.png new file mode 100644 index 000000000..628f56c00 Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/debugger-overlay.png differ diff --git a/documentation/documentation/images/02_handbook/debugger/draw-debug.png b/documentation/documentation/images/02_handbook/debugger/draw-debug.png new file mode 100644 index 000000000..47b4ee9ae Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/draw-debug.png differ diff --git a/documentation/documentation/images/02_handbook/debugger/icons/arrowRight.png b/documentation/documentation/images/02_handbook/debugger/icons/arrowRight.png new file mode 100644 index 000000000..970662e07 Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/icons/arrowRight.png differ diff --git a/documentation/documentation/images/02_handbook/debugger/icons/cursorCross.png b/documentation/documentation/images/02_handbook/debugger/icons/cursorCross.png new file mode 100644 index 000000000..350ec400b Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/icons/cursorCross.png differ diff --git a/documentation/documentation/images/02_handbook/debugger/icons/interactive.png b/documentation/documentation/images/02_handbook/debugger/icons/interactive.png new file mode 100644 index 000000000..cfa294b48 Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/icons/interactive.png differ diff --git a/documentation/documentation/images/02_handbook/debugger/icons/mover.png b/documentation/documentation/images/02_handbook/debugger/icons/mover.png new file mode 100644 index 000000000..03ee7cfc4 Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/icons/mover.png differ diff --git a/documentation/documentation/images/02_handbook/debugger/icons/pause.png b/documentation/documentation/images/02_handbook/debugger/icons/pause.png new file mode 100644 index 000000000..249f61c27 Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/icons/pause.png differ diff --git a/documentation/documentation/images/02_handbook/debugger/icons/transform.png b/documentation/documentation/images/02_handbook/debugger/icons/transform.png new file mode 100644 index 000000000..86ca88111 Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/icons/transform.png differ diff --git a/documentation/documentation/images/02_handbook/debugger/interaction-mover-shortcut.gif b/documentation/documentation/images/02_handbook/debugger/interaction-mover-shortcut.gif new file mode 100644 index 000000000..27a4c8803 Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/interaction-mover-shortcut.gif differ diff --git a/documentation/documentation/images/02_handbook/debugger/interaction-mover.gif b/documentation/documentation/images/02_handbook/debugger/interaction-mover.gif new file mode 100644 index 000000000..1ce34fe82 Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/interaction-mover.gif differ diff --git a/documentation/documentation/images/02_handbook/debugger/interaction-pointer-fine-picking.gif b/documentation/documentation/images/02_handbook/debugger/interaction-pointer-fine-picking.gif new file mode 100644 index 000000000..95918b0d4 Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/interaction-pointer-fine-picking.gif differ diff --git a/documentation/documentation/images/02_handbook/debugger/interaction-pointer-simple-select.gif b/documentation/documentation/images/02_handbook/debugger/interaction-pointer-simple-select.gif new file mode 100644 index 000000000..bf898d411 Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/interaction-pointer-simple-select.gif differ diff --git a/documentation/documentation/images/02_handbook/debugger/interaction-transform.gif b/documentation/documentation/images/02_handbook/debugger/interaction-transform.gif new file mode 100644 index 000000000..42882b456 Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/interaction-transform.gif differ diff --git a/documentation/documentation/images/02_handbook/debugger/layout-right.png b/documentation/documentation/images/02_handbook/debugger/layout-right.png new file mode 100644 index 000000000..0eac6a290 Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/layout-right.png differ diff --git a/documentation/documentation/images/02_handbook/debugger/nape-button.png b/documentation/documentation/images/02_handbook/debugger/nape-button.png new file mode 100644 index 000000000..1e6afb625 Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/nape-button.png differ diff --git a/documentation/documentation/images/02_handbook/debugger/stats-window.png b/documentation/documentation/images/02_handbook/debugger/stats-window.png new file mode 100644 index 000000000..4fc038b2d Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/stats-window.png differ diff --git a/documentation/documentation/images/02_handbook/debugger/track-player-custom.png b/documentation/documentation/images/02_handbook/debugger/track-player-custom.png new file mode 100644 index 000000000..56576ee02 Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/track-player-custom.png differ diff --git a/documentation/documentation/images/02_handbook/debugger/track-player.png b/documentation/documentation/images/02_handbook/debugger/track-player.png new file mode 100644 index 000000000..fd42f10a7 Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/track-player.png differ diff --git a/documentation/documentation/images/02_handbook/debugger/vcr-disabled.png b/documentation/documentation/images/02_handbook/debugger/vcr-disabled.png new file mode 100644 index 000000000..07c8a59d1 Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/vcr-disabled.png differ diff --git a/documentation/documentation/images/02_handbook/debugger/vcr-enabled.png b/documentation/documentation/images/02_handbook/debugger/vcr-enabled.png new file mode 100644 index 000000000..ffc12b79e Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/vcr-enabled.png differ diff --git a/documentation/documentation/images/02_handbook/debugger/view-cache.png b/documentation/documentation/images/02_handbook/debugger/view-cache.png new file mode 100644 index 000000000..fca01208a Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/view-cache.png differ diff --git a/documentation/documentation/images/02_handbook/debugger/watch-window.png b/documentation/documentation/images/02_handbook/debugger/watch-window.png new file mode 100644 index 000000000..b68a6debe Binary files /dev/null and b/documentation/documentation/images/02_handbook/debugger/watch-window.png differ diff --git a/documentation/documentation/images/02_handbook/flixel-display-list.png b/documentation/documentation/images/02_handbook/flixel-display-list.png new file mode 100644 index 000000000..a9ba68599 Binary files /dev/null and b/documentation/documentation/images/02_handbook/flixel-display-list.png differ diff --git a/documentation/documentation/images/02_handbook/flixel-state-0.png b/documentation/documentation/images/02_handbook/flixel-state-0.png new file mode 100644 index 000000000..1a389b254 Binary files /dev/null and b/documentation/documentation/images/02_handbook/flixel-state-0.png differ diff --git a/documentation/documentation/images/02_handbook/flixel-state-1.png b/documentation/documentation/images/02_handbook/flixel-state-1.png new file mode 100644 index 000000000..17dce4283 Binary files /dev/null and b/documentation/documentation/images/02_handbook/flixel-state-1.png differ diff --git a/documentation/documentation/images/02_handbook/nekovm-logo.png b/documentation/documentation/images/02_handbook/nekovm-logo.png new file mode 100644 index 000000000..e00bef374 Binary files /dev/null and b/documentation/documentation/images/02_handbook/nekovm-logo.png differ diff --git a/documentation/documentation/images/02_handbook/sprite-animation-example.png b/documentation/documentation/images/02_handbook/sprite-animation-example.png new file mode 100644 index 000000000..689bf2550 Binary files /dev/null and b/documentation/documentation/images/02_handbook/sprite-animation-example.png differ diff --git a/documentation/documentation/images/04_community/about-haxeflixel.png b/documentation/documentation/images/04_community/about-haxeflixel.png new file mode 100644 index 000000000..49de9bfab Binary files /dev/null and b/documentation/documentation/images/04_community/about-haxeflixel.png differ diff --git a/documentation/documentation/images/04_community/developers/Beeblerox.jpeg b/documentation/documentation/images/04_community/developers/Beeblerox.jpeg new file mode 100644 index 000000000..b6ea83359 Binary files /dev/null and b/documentation/documentation/images/04_community/developers/Beeblerox.jpeg differ diff --git a/documentation/documentation/images/04_community/developers/Gama11.png b/documentation/documentation/images/04_community/developers/Gama11.png new file mode 100644 index 000000000..26b4dd505 Binary files /dev/null and b/documentation/documentation/images/04_community/developers/Gama11.png differ diff --git a/documentation/documentation/images/04_community/developers/ProG4mr.jpeg b/documentation/documentation/images/04_community/developers/ProG4mr.jpeg new file mode 100644 index 000000000..d0703f367 Binary files /dev/null and b/documentation/documentation/images/04_community/developers/ProG4mr.jpeg differ diff --git a/documentation/documentation/images/04_community/developers/crazysam.png b/documentation/documentation/images/04_community/developers/crazysam.png new file mode 100644 index 000000000..59b14057c Binary files /dev/null and b/documentation/documentation/images/04_community/developers/crazysam.png differ diff --git a/documentation/documentation/images/04_community/developers/impaler.jpeg b/documentation/documentation/images/04_community/developers/impaler.jpeg new file mode 100644 index 000000000..bf98d9efe Binary files /dev/null and b/documentation/documentation/images/04_community/developers/impaler.jpeg differ diff --git a/documentation/documentation/images/04_community/developers/larsiusprime.jpeg b/documentation/documentation/images/04_community/developers/larsiusprime.jpeg new file mode 100644 index 000000000..9b0d409ea Binary files /dev/null and b/documentation/documentation/images/04_community/developers/larsiusprime.jpeg differ diff --git a/documentation/documentation/images/04_community/developers/sergey-miryanov.jpeg b/documentation/documentation/images/04_community/developers/sergey-miryanov.jpeg new file mode 100644 index 000000000..819346ba7 Binary files /dev/null and b/documentation/documentation/images/04_community/developers/sergey-miryanov.jpeg differ diff --git a/documentation/documentation/images/04_community/haxe-logo.png b/documentation/documentation/images/04_community/haxe-logo.png new file mode 100644 index 000000000..335c2a2fd Binary files /dev/null and b/documentation/documentation/images/04_community/haxe-logo.png differ diff --git a/documentation/documentation/images/04_community/upgrade-guide/openfl3-shaders.png b/documentation/documentation/images/04_community/upgrade-guide/openfl3-shaders.png new file mode 100644 index 000000000..277517d0a Binary files /dev/null and b/documentation/documentation/images/04_community/upgrade-guide/openfl3-shaders.png differ diff --git a/documentation/documentation/images/04_community/upgrade-guide/openfl8-shaders.png b/documentation/documentation/images/04_community/upgrade-guide/openfl8-shaders.png new file mode 100644 index 000000000..e3bcdca4b Binary files /dev/null and b/documentation/documentation/images/04_community/upgrade-guide/openfl8-shaders.png differ diff --git a/documentation/enemies-and-basic-ai/index.html b/documentation/enemies-and-basic-ai/index.html new file mode 100644 index 000000000..bf326404b --- /dev/null +++ b/documentation/enemies-and-basic-ai/index.html @@ -0,0 +1,550 @@ + + + + + + + + + + 9 - Enemies and Basic AI | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

9 - Enemies and Basic AI

+ + + Edit + +

What would a dungeon game be without enemies? Let's add some!

+
    +
  1. This should be second nature by now - add two new entity types in your Ogmo project, enemy and boss:

    +

    +
  2. +
  3. Then scatter some enemies and a boss around the map.

    +

    +
  4. +
  5. So we want to have 2 different enemies in our game. We'll need spritesheets for both of them, with 16x16 pixel frames and the same animation frames as our player. Name them enemy.png and boss.png and put them in the assets/images folder. You can use these, if you want (thanks, again, Vicky!):

    +

    +

    +

    Note: make sure that your enemy sprites are functionally the same - they should have the same number of frames for each facing animation.

    +
  6. +
  7. Let's add a new some code for enemies. Since we're going to have two different types of enemies, regular enemies and the boss, let's start by creating an EnemyType enumeration:

    +
     enum EnemyType
    + {
    +     REGULAR;
    +     BOSS;
    + }
    +
    +

    This basically just gives us two handy constants that we can use to distuingish them. We will put both the enum and our Enemy class into the same Enemy.hx "module" (that's what .hx files are called). The class is going to look very similar to our Player:

    +
     package;
    +
    + import flixel.FlxSprite;
    +
    + enum EnemyType
    + {
    +     REGULAR;
    +     BOSS;
    + }
    +
    + class Enemy extends FlxSprite
    + {
    +     static inline var WALK_SPEED:Float = 40;
    +     static inline var CHASE_SPEED:Float = 70;
    +
    +     var type:EnemyType;
    +
    +     public function new(x:Float, y:Float, type:EnemyType)
    +     {
    +         super(x, y);
    +         this.type = type;
    +         var graphic = if (type == BOSS) AssetPaths.boss__png else AssetPaths.enemy__png;
    +         loadGraphic(graphic, true, 16, 16);
    +         setFacingFlip(LEFT, false, false);
    +         setFacingFlip(RIGHT, true, false);
    +         animation.add("d_idle", [0]);
    +         animation.add("lr_idle", [3]);
    +         animation.add("u_idle", [6]);
    +         animation.add("d_walk", [0, 1, 0, 2], 6);
    +         animation.add("lr_walk", [3, 4, 3, 5], 6);
    +         animation.add("u_walk", [6, 7, 6, 8], 6);
    +         drag.x = drag.y = 10;
    +         setSize(8, 8);
    +         offset.x = 4;
    +         offset.y = 8;
    +     }
    +
    +     override public function update(elapsed:Float)
    +     {
    +         if (velocity.x != 0 || velocity.y != 0)
    +         {
    +             if (Math.abs(velocity.x) > Math.abs(velocity.y))
    +             {
    +                 if (velocity.x < 0)
    +                     facing = LEFT;
    +                 else
    +                     facing = RIGHT;
    +             }
    +             else
    +             {
    +                 if (velocity.y < 0)
    +                     facing = UP;
    +                 else
    +                     facing = DOWN;
    +             }
    +         }
    +
    +         switch (facing)
    +         {
    +             case LEFT, RIGHT:
    +                 animation.play("lr_" + action);
    +
    +             case UP:
    +                 animation.play("u_" + action);
    +
    +             case DOWN:
    +                 animation.play("d_" + action);
    +
    +             case _:
    +         }
    +
    +         super.update(elapsed);
    +     }
    + }
    +
    +

    The main difference is that we have a new type variable, which we will use to figure out which enemy sprite to load, and which one we're dealing with, etc.

    +
  8. +
  9. Next, we'll make a FlxGroup in our PlayState to hold our enemies, and load them into the map, very much the same way we did our coins.

    +

    At the top of our class, add:

    +
     var enemies:FlxTypedGroup<Enemy>;
    +
    +

    In the create function, right after we add our coin group:

    +
     enemies = new FlxTypedGroup<Enemy>();
    + add(enemies);
    +
    +

    We will also need to add two more cases to our placeEntities() function:

    +
     else if (entity.name == "enemy")
    + {
    +     enemies.add(new Enemy(entity.x + 4, entity.y, REGULAR));
    + }
    + else if (entity.name == "boss")
    + {
    +     enemies.add(new Enemy(entity.x + 4, entity.y, BOSS));
    + }
    +
    +

    Go ahead and test out your game to make sure the enemies are added properly.

    +
  10. +
  11. (optional step) Our placeEntities() is starting to get a bit repetitive. Each if checks entity.name, and each time we use entity.x and entity.y.

    +

    Let's fix this by using a switch-case instead of an if/else-chain, as well as adding some temporary x and y variables:

    +
     var x = entity.x;
    + var y = entity.y;
    +
    + switch (entity.name)
    + {
    +     case "player":
    +         player.setPosition(x, y);
    +
    +     case "coin":
    +         coins.add(new Coin(x + 4, y + 4));
    +
    +     case "enemy":
    +         enemies.add(new Enemy(x + 4, y, REGULAR));
    +
    +     case "boss":
    +         enemies.add(new Enemy(x + 4, y, BOSS));
    + }
    +
    +

    There, that's a lot easier to read!

    +
  12. +
+

Now let's give our enemies some brains.

+

In order to let our enemies 'think', we're going to utilize a very simple Finite-state Machine (FSM). Basically, the FSM works by saying that a given machine (or entity) can only be in one state at a time. For our enemies, we're going to give them 2 possible states: Idle and Chase. When they can't 'see' the player, they will be Idle - wandering around aimlessly. Once the player is in view, however, they will switch to the Chase state and run towards the player.

+
    +
  1. Shouldn't be that hard! First, we'll make our FSM class:

    +
     class FSM
    + {
    +     public var activeState:Float->Void;
    +
    +     public function new(initialState:Float->Void)
    +     {
    +         activeState = initialState;
    +     }
    +
    +     public function update(elapsed:Float)
    +     {
    +         activeState(elapsed);
    +     }
    + }
    +
    +
  2. +
  3. Next, we'll change our Enemy class a little.

    +

    We need to define these variables at the top of the class:

    +
     var brain:FSM;
    + var idleTimer:Float;
    + var moveDirection:Float;
    + var seesPlayer:Bool;
    + var playerPosition:FlxPoint;
    +
    +
  4. +
  5. At the end of the constructor, add:

    +
     brain = new FSM(idle);
    + idleTimer = 0;
    + playerPosition = FlxPoint.get();
    +
    +
  6. +
  7. And then add the following functions:

    +
     function idle(elapsed:Float)
    + {
    +     if (seesPlayer)
    +     {
    +         brain.activeState = chase;
    +     }
    +     else if (idleTimer <= 0)
    +     {
    +         // 95% chance to move
    +         if (FlxG.random.bool(95))
    +         {
    +             moveDirection = FlxG.random.int(0, 8) * 45;
    +
    +             velocity.setPolarDegrees(WALK_SPEED, moveDirection);
    +         }
    +         else
    +         {
    +             moveDirection = -1;
    +             velocity.x = velocity.y = 0;
    +         }
    +         idleTimer = FlxG.random.int(1, 4);
    +     }
    +     else
    +         idleTimer -= elapsed;
    +
    + }
    +
    + function chase(elapsed:Float)
    + {
    +     if (!seesPlayer)
    +     {
    +         brain.activeState = idle;
    +     }
    +     else
    +     {
    +         FlxVelocity.moveTowardsPoint(this, playerPosition, CHASE_SPEED);
    +     }
    + }
    +
    +

    Also add this line to update() before super.update(elapsed):

    +
     brain.update(elapsed);
    +
    +

    The way this is going to work is that each enemy will start in the Idle state. In the PlayState we will have each enemy check to see if it can see the player or not. If it can, it will switch to the Chase state, until it can't see the player anymore. While in the Idle state, every so often (in random intervals) it will choose a random direction to move in for a little while (with a small chance to just stand still). While in the Chase state, they will move directly towards the player.

    +
  8. +
  9. Let's jump over to the PlayState to add our player's vision logic. In update(), under the overlap and collision checks, add:

    +
     FlxG.collide(enemies, walls);
    + enemies.forEachAlive(checkEnemyVision);
    +
    +
  10. +
  11. Next, add the checkEnemyVision() function:

    +
     function checkEnemyVision(enemy:Enemy)
    + {
    +     if (walls.ray(enemy.getMidpoint(), player.getMidpoint()))
    +     {
    +         enemy.seesPlayer = true;
    +         enemy.playerPosition = player.getMidpoint();
    +     }
    +     else
    +     {
    +         enemy.seesPlayer = false;
    +     }
    + }
    +
    +

    Note how we need to modify two enemy variables for this. The default visibility in Haxe is private, so the compiler doesn't allow this. We will have to make them public instead:

    +
     public var seesPlayer:Bool;
    + public var playerPosition:FlxPoint;
    +
    +
  12. +
+

That's all there is to it! Try out your game and make sure it works.

+

+

Next, we'll add some UI to the game, and add our RPG-style combat so you can fight the enemies!

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/faq/index.html b/documentation/faq/index.html new file mode 100644 index 000000000..03d96838c --- /dev/null +++ b/documentation/faq/index.html @@ -0,0 +1,282 @@ + + + + + + + + + + FAQ | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

FAQ

+ + + Edit + +

Do I have to learn Flixel (AS3) before HaxeFlixel?

+

No, you have to learn HaxeFlixel to use HaxeFlixel, although previous experience with the AS3 version will help.

+

Do I have to learn OpenFL to use HaxeFlixel?

+

No, HaxeFlixel abstracts it completely.

+

Are there any more tutorials?

+

We have a dedicated Community Tutorials page that links to many external community made tutorials!

+

You can find the official HaxeFlixel "Dungeon Crawler" tutorial here.

+

I found a bug, where to report?

+

On the official GitHub repository.

+

My sounds are lagging!?

+

On some platforms, it helps to manually cache sounds: FlxG.sound.cache("sound"); or FlxG.sound.cacheAll(); to do all at once.

+

My player falls off-screen after walking a certain distance!

+

Collisions are limited to the area defined by FlxG.worldBounds. For example in platformers where this area needs to be larger, you need to adjust it manually.

+

Can I make 3D games with HaxeFlixel?

+

No, the framework is limited to 2D graphics. Well. Except for some crazy people.

+

How do I protect my assets from being stolen?

+

If you add embed="true" to the <assets path="assets"> tag of the Project.xml, the asset files are embedded into the .exe.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/flixel-addons/index.html b/documentation/flixel-addons/index.html new file mode 100644 index 000000000..bc7703c90 --- /dev/null +++ b/documentation/flixel-addons/index.html @@ -0,0 +1,306 @@ + + + + + + + + + + Flixel Addons | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Flixel Addons

+ + + Edit + +

The addons are a set of very useful, but nevertheless optional classes that not every game is going to need. That is why they are not quite important enough to be a part of HaxeFlixel's core.

+

Installing flixel-addons

+

The addons are designed to be used with haxelib and are hosted on the main HaxeFlixel GitHub account.

+
haxelib install flixel-addons
+

Now to verify you can see if flixel-addons is in your haxelib list:

+
haxelib list
+

To use the addons in a project simply add the following XML node to your OpenFL Project.xml file.

+
<haxelib name="flixel-addons" />
+

What's in the addons?

+ + + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/flixel-display-list/index.html b/documentation/flixel-display-list/index.html new file mode 100644 index 000000000..f8cb87602 --- /dev/null +++ b/documentation/flixel-display-list/index.html @@ -0,0 +1,324 @@ + + + + + + + + + + Flixel Display List | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Flixel Display List

+ + + Edit + +

The Flixel Display list is a specially designed structure for your game's sprites to be rendered.

+

FlxSprite != flash.display.Sprite

+

The Flash API has a display list that is populated by adding display objects in a parent child relationship. Sprites are an extended form of display objects that have extended features. They can be added, removed and can have their parent and children's depth changed with an easy to use API.

+

It is a common misconception for Flash developers to assume that FlxSprites in Flixel work like the Flash Sprites. FlxSprites also do not share the event system Flash Sprites have, so addEventListener() is also not available or necessary in most situations.

+

For performance reasons, Flixel has its own independent display list and it renders all of its FlxSprites onto a single Flash DisplayObject with each FlxCamera. For this reason, you cannot add a flash.display.sprite to a FlxState and you cannot add a FlxSprite to the main Flash stage.

+

You can see the display objects used in a typical Flixel game in this diagram. Note you can still place display objects above or below Flixel's camera. It is recommended to use FlxG.addChildBelowMouse() and FlxG.removeChild() for that.

+

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/flixel-tools/index.html b/documentation/flixel-tools/index.html new file mode 100644 index 000000000..89d596b4f --- /dev/null +++ b/documentation/flixel-tools/index.html @@ -0,0 +1,309 @@ + + + + + + + + + + Flixel Tools | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Flixel Tools

+ + + Edit + +

To make HaxeFlixel development easier, a set of command line tools has been developed with Haxe and Neko. With it you can easily create our demo projects, templates and more. Just like HaxeFlixel it is an open-source tool and additions/improvements from the community are welcome at the flixel-tools GitHub repository.

+

Installation

+

The tools are available on haxelib:

+
haxelib install flixel-tools
+
+

Setup

+

To set the tools up initially / to be able to use the flixel alias in your console:

+
haxelib run flixel-tools setup
+
+

Commands

+

create (c)

+

Create a new demo (in the current directory):

+
flixel create <name_or_number>
+
+

If no name or number is given, it will list all demos and prompt you for a choice, by number or name.

+

template (tpl)

+

To create a new project from the default template:

+
flixel tpl -n <name>
+
+

Any folder in the flixel-templates haxelib is treated as a template and can be created with the flixel tpl <foldername> syntax. This makes it easy to create custom templates.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/flxgroup/index.html b/documentation/flxgroup/index.html new file mode 100644 index 000000000..8a884933d --- /dev/null +++ b/documentation/flxgroup/index.html @@ -0,0 +1,352 @@ + + + + + + + + + + FlxGroup | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

FlxGroup

+ + + API + + Edit + +
import flixel.group.FlxGroup;
+
+

FlxGroups are an invaluable method of grouping your game objects in Flixel. In fact, there is no way around them, as FlxState itself extends FlxGroup. +The use cases for groups are vast: pooling to reuse objects, collision detection and setting up easy ways to access particular collections of objects. A great feature of FlxGroups are their ability to be nested when using collision detection. Doing collisions is also way more efficient than doing it for individual objects.

+

The API for FlxGroups is similar to other places in Flixel. Here is a basic example using a group to pool bullet objects, represented by a Bullet class, holding a maximum of 100 bullets:

+
var poolSize = 100;
+var bullets = new FlxTypedGroup<Bullet>(poolSize);
+
+for (i in 0...poolSize)
+{
+    var bullet = new Bullet();
+    bullet.kill();
+    bullets.add(bullet);
+}
+
+

Note how we did not use a regular FlxGroup, but a FlxTypedGroup<Bullet>. This means that this particular group can only store objects that are instances of the Bullet class or instances of Bullet subclasses. FlxGroup itself is nothing but a shortcut for FlxTypedGroup<FlxBasic>.

+

Now, say we want to retrieve bullet instance to use in a shoot method:

+
var bullet = bullets.recycle(Bullet);
+
+

If we had used a regular group here, we would have had to cast the return value of recycle() to a Bullet. By using a FlxTypedGroup<Bullet>, we have the benefit of type-safety.

+

add(Object:T):T;

+

You can add any type of Object that extends the base FlxGroup type, if you use FlxGroup this is FlxBasic.

+

remove(Object:T):T

+

Removes an object from a group, it will return the object you removed.

+

getFirstAvailable(ObjectClass:Class<T> = null):T

+

This will let you get the first FlxBasic object that has exists == false, this is typically used in object pooling when object may have used the kill() method. Note if you destroy() objects they will be made null in the FlxGroup and you wont be able to reuse them.

+

kill();

+

This will recursively kill() all objects so that they will be ready for use with getFirstAvailable.

+

sort(Function:Int->T->T->Int, Order:Int = FlxSort.ASCENDING);

+

Call this function to sort the group according to a particular value and order. You will need to specify a sorting function to do so. If you want to sort by something other than y, you will have to write a custom sorting function.

+

Otherwise, you can just use the pre-made FlxSort.byY() like so for Zelda-style-sorting:

+
group.sort(FlxSort.byY);
+
+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/flxsave/index.html b/documentation/flxsave/index.html new file mode 100644 index 000000000..9c02b764f --- /dev/null +++ b/documentation/flxsave/index.html @@ -0,0 +1,357 @@ + + + + + + + + + + FlxSave | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

FlxSave

+ + + API + + Edit + +
import flixel.util.FlxSave;
+
+

HaxeFlixel gives you the FlxSave class to manage saving and loading your game's data. You might use it to save and load a high score table, or the position and status of the player and enemies, or custom settings the player has selected. Like most of HaxeFlixel, FlxSave is cross-platform in functionality.

+

To use FlxSave you need a variable typed to that class. You can create your own variable (perhaps in your registry class, in your gameplay FlxState, or as a local variable in your save/load functions). You may also use the one that HaxeFlixel itself uses (FlxG.save).

+

The example code used below is largely taken from the HaxeFlixel save demo. If you have already installed HaxeFlixel, then to install the demo project just open a command line utility, navigate to the folder you would like to install into, and enter the command flixel create Save, or download the source via GitHub using the link on the demo web page.

+

Saving

+

So how can you save some of your game data? Once you have your variable, you will need to initialize, then bind it:

+
_gameSave = new FlxSave(); // initialize
+_gameSave.bind("SaveDemo"); // bind to the named save slot
+
+

Note the string "SaveDemo". This is how HaxeFlixel tracks what save slot you are binding to in local storage. If you want to have multiple saves, you will probably want to define a series of strings to identify each slot, eg. "SaveSlot1", "SaveSlot2", etc. and bind to the appropriate one. For more information on using multiple save slots, take a look at Wolfgang's article on the subject for AS3 Flixel, but keep in mind that the AS3 syntax is a little different from Haxe.

+

Note: If you plan to use FlxG.save you can skip the initializing and binding steps, as HaxeFlixel has done it for you.

+

Once bound, the save is essentially "live". To write to it you use the .data property of variable, treating it as an object:

+
_gameSave.data.boxPositions = new Array<FlxPoint>();
+_gameSave.data.boxPositions.push(box.getPosition());
+
+_gameSave.data.enemy = myEnemy;
+
+// save data
+_gameSave.flush();
+
+
flush()
+

Writes the local shared object to disk immediately. +Required on non-Flash targets.

+
Serialization
+

In certain cases you may need to serialize and unserialize your data (fancy words for "take my data and turn it into a specially formatted string, or back into data") to avoid errors, but you may want to try it without serialization unless you experience problems.

+

Loading

+

In order to retrieve your saved data, you simply make sure you have a correctly bound FlxSave variable and read each value from the .data property.

+
var position = _gameSave.data.boxPositions[tempCount];
+box.setPosition(position.x, position.y);
+
+

This means that, depending on your save needs, when loading a save slot you may need to loop through a long list of data to assign each of the values back to it's correct home.

+

Existing save data

+

When you save data to a given FlxSave save slot there is, of course, the possibility that data already exists in that slot (hopefully your saved data from an earlier save). One way to test for this is to check if one of your variables is null. If save data does already exist and you plan to save an entire fresh set of new data, then to avoid carrying over values from an earlier save you may wish to either go through and initialize or reset each of the potentially saved variables to some default value (or null) before saving your new set, or you may wish to erase the save data entirely (probably not a good idea if you're using FlxG.save).

+

FlxSave provides an .erase() method to help with this process, but keep in mind that calling it on a bound FlxSave variable will: immediately erase all the data in .data, save the slot in the erased state (any earlier data is now completely gone), and also destroy the binding to the save slot. This last point is important to note, as after the binding has been broken FlxSave may still let you assign to .data and even call other methods without errors to indicate that the data is not actually being stored at all. So if you do use the .erase() method, don't forget to call .bind() again before you save or load any further data.

+

Other methods

+

In the Save demo the application creates and binds a FlxSave variable when the demo state initializes (see PlayState#create()), and then leaves this variable accessible for loading and saving from that point on. This allows you to continually update the save object when necessary, but it's equally valid to create, initialize, and bind a FlxSave variable only when loading and saving. In that case you should familiarize yourself with .close() and .destroy()for safe and efficient handling of your FlxSave.

+

To review these additional methods and check out any other FlxSave functionality in more detail, take a look at the API documentation or look at the class definition itself (currently under the util package in the flixel library).

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/flxsprite/index.html b/documentation/flxsprite/index.html new file mode 100644 index 000000000..7cdf328a3 --- /dev/null +++ b/documentation/flxsprite/index.html @@ -0,0 +1,381 @@ + + + + + + + + + + FlxSprite | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

FlxSprite

+ + + API + + Edit + +
import flixel.FlxSprite;
+
+

FlxSprites are the core building blocks of all Flixel games. They offer a friendly API to add animation, movement and features for the needs of most games.

+

It is pretty common place to extend FlxSprite for your own game's needs; for example a SpaceShip class may extend FlxSprite but could have additional variables for the game like shieldStrength or shieldPower. When you extend FlxSprite it is important to remember to use super.update() if you override the update method, as you would do for any other FlxBasic.

+

loadGraphic()

+

This method is the easiest way to use a single image for your FlxSprite. Using the OpenFL asset system defined in the project xml file you simply have to define a path to your image and the compiler will do the rest.

+
var player = new FlxSprite();
+player.loadGraphic("assets/player.png");
+add(player);
+
+

makeGraphic()

+

This method is a handy way to make a simple color fill to quickly test a feature or have the basic shape.

+
var whiteSquare = new FlxSprite();
+whiteSquare.makeGraphic(200, 200, FlxColor.WHITE);
+add(whiteSquare);
+
+

Properties

+

Position: x, y

+
whiteSquare.x = 100;
+whiteSquare.y = 300;
+
+

Size: width, height

+

Automatically set in loadGraphic() or makeGraphic(), changing this will only affect the hitbox of this sprite, use scale to change the graphic's size.

+
// get
+var getWidth = whiteSquare.width;
+
+// set
+whiteSquare.width = 100;
+whiteSquare.height = 100;
+
+

Scale

+

(FlxPoint) +Change the size of your sprite's graphic. NOTE: The hitbox is not automatically adjusted, use updateHitbox() for that (or setGraphicSize()).

+
// twice as big
+whiteSquare.scale.set(2, 2);
+
+// 50%
+whiteSquare.scale.set(0.5, 0.5);
+
+

Offset

+

(FlxPoint) +Controls the position of the sprite's hitbox. Likely needs to be adjusted after changing a sprite's width, height or scale.

+
whiteSquare.offset.set(50, 50);
+
+

Origin

+

(FlxPoint) +Rotation axis. Default: center.

+

WARNING: If you change this, the visuals and the collisions will likely be pretty out-of-sync if you do any rotation.

+
// rotate from top-left corner instead of center
+whiteSquare.origin.set(0, 0);
+
+

​kill()

+

This method is useful for when you want to hide a sprite from the stage but keep it available to reuse later. For example you may want to respawn an enemy the player has killed.

+

destroy()

+

This method is destructive to the sprite and should be used when you want to make sure that the sprite will be cleared from memory. It is commonly used inside a FlxState's overridden destroy method.

+

Animation

+

Flixel supports spritesheet animation.

+

+
player.loadGraphic("assets/player.png", true, 32, 36);
+player.animation.add("walk", [0, 1, 0, 2], 5, true);
+player.animation.play("walk");
+
+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/flxstate/index.html b/documentation/flxstate/index.html new file mode 100644 index 000000000..bac825ba2 --- /dev/null +++ b/documentation/flxstate/index.html @@ -0,0 +1,400 @@ + + + + + + + + + + FlxState | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

FlxState

+ + + API + + Edit + +

This is the basis for your game's levels and menus, each described in a "state" structure. The state is a way of organising your game objects for the state that the game is currently in. For example, when you create level 0 of your game it's much more organized to only have the code for that level, not every level. Also it's good to use switching states to clear your memory, to avoid memory leaks. A typical Flixel game will have a separate FlxState class for every level and menu.

+

+

In each FlxState all the FlxSprites are added to be rendered.

+

+

Important Methods

+

create()

+

This is where you setup and create all your state's objects; for example your level tilemaps, your player sprites, spawn your initial enemies. Flixel runs this method before it starts to render your state so its the perfect place.

+

add(object:FlxBasic)

+

This is the place where you add your sprites, tilemaps etc to your state to be rendered. It works similar to OpenFL's display list API with addChild().

+

remove(object:FlxBasic)

+

This is the place where you remove sprites etc you have added to your state. Everything you remove still exists so you can add it back later. If you're not going to use the removed object again you might want to consider removing it from memory by setting it as null for example.

+

update(elapsed:Float)

+

This is the place where you can run code on every frame of your game. It's where you setup your input controls, trigger movement and almost all of your gameplay logic.

+
package;
+
+import flixel.FlxState;
+
+class FlxExampleState extends FlxState
+{
+    override public function create():Void
+    {
+        //create your state objects here
+    }
+
+    override public function update(elapsed:Float):Void
+    {
+        //call super to update the core state class
+        super.update(elapsed);
+    }
+}
+
+

Here is an example of a simple game state;

+
package;
+
+import flixel.tile.FlxTilemap;
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.FlxState;
+import flixel.graphics.FlxGraphic;
+
+class FlxExampleState extends FlxState
+{
+    var wizard:FlxSprite;
+    var level:FlxTilemap;
+
+    override public function create():Void
+    {
+        //create a main player
+        wizard = new FlxSprite(200, 200, 'assets/player.png');
+        wizard.maxVelocity.set(80, 200);
+        wizard.acceleration.y = 200; // gravity
+        wizard.drag.x = wizard.maxVelocity.x * 4;
+        add(wizard);
+
+        //create a tilemap level
+        level = new FlxTilemap();
+        level.loadMap('assets/level.csv', FlxGraphic.fromClass(GraphicAuto), 0, 0, AUTO);
+        add(level);
+    }
+
+    override public function update(elapsed:Float):Void
+    {
+        //control the player with keyboard
+        wizard.acceleration.x = 0;
+
+        if (FlxG.keys.pressed.LEFT)
+        {
+            wizard.acceleration.x = -wizard.maxVelocity.x * 4;
+        }
+        if (FlxG.keys.pressed.RIGHT)
+        {
+            wizard.acceleration.x = wizard.maxVelocity.x * 4;
+        }
+        if (FlxG.keys.justPressed.SPACE && wizard.isTouching(FLOOR))
+        {
+            wizard.velocity.y = -wizard.maxVelocity.y / 2;
+        }
+        super.update(elapsed);
+    }
+}
+
+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/flxtween/index.html b/documentation/flxtween/index.html new file mode 100644 index 000000000..c6ae73afa --- /dev/null +++ b/documentation/flxtween/index.html @@ -0,0 +1,415 @@ + + + + + + + + + + FlxTween | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

FlxTween

+ + + API + + Edit + +

A FlxTween allows you to create smooth interpolations and animations easily. Tweening is short for inbetweening: you only have to specify start and end values and the FlxTween class will generate all values between those two. If you want to see a FlxTween in action, this tween demo is available.

+

For example, if you want to move a FlxSprite across the screen, this code snippet would do it:

+
sprite.x = 200;
+sprite.y = 200;
+
+FlxTween.tween(sprite, { x: 600, y: 800 }, 2);
+
+

The first two lines specify the start position of the sprite, because the tween() method assumes the current position is the starting position.

+

The first parameter is the object you want to act upon; the second parameter is the map which contains the properties you want to interpolate, and their desired target values. Here, we want to translate the sprite in x to position 600 and in y to position 800. The third parameter specifies the duration of the tween in seconds, which in this case is 2 seconds.

+

Cancelling a Tween

+

If you start a tween using the code above, it will run until the desired values are reached, then stop. As the tween() method returns an object of type FlxTween, keeping this object in a variable allows you to access the current tween running if you wish to control it.

+

For example, this code stops the translation of the sprite if the player presses the spacebar of their keyboard:

+
var tween:FlxTween;
+
+public function new()
+{
+    super();
+    // set up sprite
+    tween = FlxTween.tween(sprite, { x:600, y:800 }, 2);
+}
+
+override public function update(elapsed:Float)
+{
+    super.update(elapsed);
+
+    if (FlxG.keys.justPressed.SPACE)
+        tween.cancel();
+}
+
+

Tweening Options

+

The tween() method takes an optional fourth parameter which is a map of options.

+

Possible values are:

+
    +
  • type: choose one of these:

    +
      +
    • FlxTween.ONESHOT: stops and removes itself from its core container when it finishes;
    • +
    • FlxTween.PERSIST: stops when it finishes. Unlike ONESHOT, this type of tween stays attached to the core container when it finishes. This means you can keep a reference to this tween and call start() whenever you need it. This does not work with ONESHOT;

      +
    • +
    • FlxTween.LOOPING: restarts immediately when it finishes;

      +
    • +
    • FlxTween.PINGPONG: plays tween "hither and thither". This is like LOOPING, but every second execution is in reverse direction;

      +
    • +
    • FlxTween.BACKWARD: plays tween in reverse direction.

      +
    • +
    +
  • +
  • onComplete: a callback function, which is called once the tween has finished. This is called every time the tween has finished one execution and comes in handy for repeating tweens (LOOPING and PINGPONG). The method must take a FlxTween and return nothing.

    +
  • +
  • ease: an optional easer function. This can be used to make the beginning and end of a tween smoother. The FlxEase class provides many static methods for this which should cover most cases. The following list shows all functions from FlxEase. In all of these, In can be replaced by Out or InOut, depending on where you want to apply the easing effect: at the beginning of the animation, at the end or at both sides.

    +
      +
    • backIn
    • +
    • bounceIn
    • +
    • circIn
    • +
    • cubeIn
    • +
    • elasticIn
    • +
    • expoIn
    • +
    • quadIn
    • +
    • quartIn
    • +
    • quintIn
    • +
    • sineIn
    • +
    +
  • +
  • startDelay: time to wait before starting this tween, in seconds.

    +
  • +
  • loopDelay: time to wait before this tween is repeated, in seconds. This only applies to LOOPING and PINGPONG.

    +
  • +
+

For example:

+
public function new()
+{
+    super();
+    // set up sprite
+    sprite.x = 200;
+    sprite.y = 200;
+    FlxTween.tween(sprite, { x: 600, y: 800 }, 2, { type: FlxTween.PINGPONG, ease: FlxEase.quadInOut, onComplete: changeColor, startDelay: 1, loopDelay: 2 });
+}
+
+function changeColor(tween:FlxTween):Void
+{
+    // change the color of the sprite here
+}
+
+

This code moves the sprite constantly between the two points (200|200) and (600|800), smoothly accelerating and decelerating. Each time the sprite arrives at one of those two points, its color changes. The animation starts after 1 second and then the sprite pauses at each point for 2 seconds.

+

Special Tweens

+

There are many more tweening methods in FlxTween, which are used for special cases:

+

color()

+

Tweens the red, green and blue part of a color independently, because normal tweening would screw up the colors.

+

Usage: color(Sprite : FlxSprite, Duration : Float, FromColor : Int, ToColor : Int, ?FromAlpha : Float, ?ToAlpha : Float, ?Options : TweenOptions)

+

Notice that unlike in the tween() method, the duration is specified before the color values and you have to enter the start and the end value. The options are the same as described above.

+

angle()

+

This method is for tweening the angle of a FlxSprite.

+

Usage: angle(Sprite : FlxSprite, FromAngle : Float, ToAngle : Float, Duration : Float, ?Options : TweenOptions)

+

Motion and Path Tweens

+

The FlxTween class also contains the methods linearMotion(), quadMotion(), cubicMotion() and circularMotion(), which make objects follow straight lines, smooth paths or circles.

+

The methods linearPath() and quadPath() can be used for longer paths defined through an array of points, instead of a fixed number of points.

+

If you want to use these methods please refer to the FlxTween API.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/game-development-tools/index.html b/documentation/game-development-tools/index.html new file mode 100644 index 000000000..fc53f89d9 --- /dev/null +++ b/documentation/game-development-tools/index.html @@ -0,0 +1,327 @@ + + + + + + + + + + Game Development Tools | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Game Development Tools

+ + + Edit + +

A concise list of tools useful to HaxeFlixel developers.This list is under construction. Suggest more, here.

+

External Flixel Libraries

+

A list of repos and libraries made with the purpose of extending HaxeFlixel's capabilities. One day, these may be officially incorporated into HaxeFlixel, but for now they serve a niche demand on their own.

+

Zerolib-flixel

+

A library of extensions, utilities, and other helpful classes for making games quickly in haxeflixel! There's also a framework agnostic version simply called Zerolib

+

djFlixel

+

djFlixel is a small library with some helpful tools for HaxeFlixel, including a multi-page menu system, keyboard/gamepad helpers, and very fun effects.

+

FlxAnimate

+

A repository made by CheemsAndFriends and DotWith made for playing all spritesheet formats and the mysterious but interesting export called Texture Atlas

+

FlxGif

+

Yagp's Gif Player for HaxeFlixel.

+

HxCodec

+

A library which adds native video support for OpenFL and HaxeFlixel.

+

flixel-depth

+

Flixel Depth is a fun 3D hack for making orthogonally 3D looking games using haxeflixel. It does so primarily by offsetting sprites according to the camera's current angle and scaling the primary game window down. This is NOT real 3D, you will still be making a 2D game, so expect a lot of edge cases!

+

depth-flixel (not to be confused with flixel-depth!)

+

A library aimed at making Stacked Sprites easy with Haxeflixel!

+

Graphics Editors

+

Gimp

+

An advanced bitmap based image editor that has many capabilities similar to commercial software. It can be used as a simple paint program, an expert quality photo retouching program, an online batch processing system, a mass production image renderer, an image format converter, etc.

+

Paint.NET

+

With an easy-to-learn but powerful set of tools, Paint.NET can be used for photo retouching, tilemap editing, pixel art editing, and so on. It contains advanced features such as levels and curves editing, noise addition and reduction, fractal and Perlin noise generation and more, but can also be used as a simple image editor.

+

Inkscape

+

An advanced vector image editor with an advanced editing toolset. Inkscape has capabilities similar to commercial software such as Adobe Illustrator, CorelDraw, or Xara X. Inkscape leverages the W3C standard Scalable Vector Graphics (SVG) file format. +Inkscape supports many advanced SVG features (markers, clones, alpha blending, etc.) and great care is taken in designing a streamlined interface. It is very easy to edit nodes, perform complex path operations, trace bitmaps and much more.

+

Krita

+

Krita is a free digital painting and illustration application. Krita offers CMYK support, HDR painting, perspective grids, dockers, filters, painting assistants, and many other features you would expect.

+

Aseprite

+

Aseprite is a program designed for drawing pixel art. It has layers, animation tools, tile map tools, blend modes, and many more useful features. It's not free, but it's a favorite for many developers.

+

Sound Editors

+

Audacity

+

Audacity is free, open source, cross-platform audio software for multi-track recording and editing.

+

LMMS

+

LMMS is a free cross-platform software which allows you to produce music with your computer.

+

ChipTone

+

An OpenFL based sound effects generator for video games, build by Tom Vian of SFBGames. Available on HTML5, Windows, and Mac!

+

LabChirp

+

LabChirp is a program for creating sound effects.

+

Map Editors

+

Tiled Map Editor

+

Tiled is a general purpose tile map editor. It is meant to be used for editing maps of any tile-based game, be it an RPG, a platformer or a Breakout clone. This demo shows how to load a Tiled map.

+

Source code: https://github.com/mapeditor/tiled

+

Ogmo Editor

+

Ogmo Editor is a generic level editor for indie game developers who use Windows. It also happens to be free and open source. The editor is built to be reconfigurable, so you can set it up to work well for your game project. This HaxeFlixel tutorial demonstrates how to create a simple top-down level with Ogmo.

+

Source code: https://github.com/Ogmo-Editor-3/OgmoEditor3-CE

+

LDtk

+

LDtk is a level editor created by the lead game designer of Dead Cells. This editor has some extra features work nicely with Haxe and HaxeFlixel, and focuses on being easy to use. This tutorial shows you how to use LDtk tile maps with HaxeFlixel.

+

Source code: https://github.com/deepnight/ldtk

+

Asset Utilities

+

ShoeBox

+

ShoeBox is a free Adobe Air based app for Windows and Mac OS X with game and UI related tools. It has many utilities that make asset management easier, such as sprite packing, sprite extraction, texture ripping, bitmap font creation, and more.

+

Texture Packer

+

Texture Packer does one thing very well - it packs several sprites into one large image to help reduce load times for your game. It's easy to use and easy to integrate with HaxeFlixel. This demo shows how to use a TexturePackerAtlas.

+

More Resources

+

ellisonleao/magictools

+

🎮 📝 A Github list of Game Development resources to make magic happen.

+

Newgrounds Wiki: Creator Resources

+

Curated list of tools and software of all kind, useful for non-programming related things such as art, animation and music!

+

(Archive.org) Ludum Dare List

+

(Likely outdated) Ludum Dare hosts a great list of tools for general game development.

+

(Archive.org)PixelProspector

+

(Likely outdated) Huge list of resources for game dev. A must read for indie developers.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/game-over-menu/index.html b/documentation/game-over-menu/index.html new file mode 100644 index 000000000..fe7a3c262 --- /dev/null +++ b/documentation/game-over-menu/index.html @@ -0,0 +1,418 @@ + + + + + + + + + + 11 - Game Over Menu | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

11 - Game Over Menu

+ + + Edit + +

Our game is really starting to come together! Now we need it to feel more like a 'game' with a win and lose scenario. For our (very simple) game, we'll just make it so that if you ever die in combat, you get a Game Over, and when you beat the boss enemy, you win. Both of these conditions will take you to the same FlxState to show you your score and allow you to play again if you want.

+
    +
  1. Let's start with PlayState. We need to add some flags to see if we're ending the game, and if the player has 'won' or not. So, add:

    +
     var ending:Bool;
    + var won:Bool;
    +
    +

    To the top of the class.

    +
  2. +
  3. Next, in update(), right under super.update(elapsed) add:

    +
     if (ending)
    + {
    +     return;
    + }
    +
    +

    We don't want to allow anything else to go on if we're ending the game and getting ready to switch states.

    +
  4. +
  5. Next, still in update(), we're going to change our logic in if (inCombat) to this:

    +
     if (!combatHud.visible)
    + {
    +     health = combatHud.playerHealth;
    +     hud.updateHUD(health, money);
    +     if (combatHud.outcome == DEFEAT)
    +     {
    +         ending = true;
    +         FlxG.camera.fade(FlxColor.BLACK, 0.33, false, doneFadeOut);
    +     }
    +     else
    +     {
    +         if (combatHud.outcome == VICTORY)
    +         {
    +             combatHud.enemy.kill();
    +             if (combatHud.enemy.type == BOSS)
    +             {
    +                 won = true;
    +                 ending = true;
    +                 FlxG.camera.fade(FlxColor.BLACK, 0.33, false, doneFadeOut);
    +             }
    +         }
    +         else
    +         {
    +             combatHud.enemy.flicker();
    +         }
    +         inCombat = false;
    +         player.active = true;
    +         enemies.active = true;
    +     }
    + }
    +
    +

    This will now check to see if the outcome was DEFEAT, and if it was, it will set our ending flag to true, and then tell the camera to start fading out - calling doneFadeOut() when it's done.

    +

    Similarly, if the outcome was VICTORY, and the enemy that was just defeated was type 1 (the boss), we set our won flag to true, and also start fading out.

    +
  6. +
  7. When the camera is done fading to black, we call this function, which will switch the state to our GameOverState (which you'll make in a second), passing it if the player won or not, and how much money they have.

    +
     function doneFadeOut()
    + {
    +     FlxG.switchState(new GameOverState(won, money));
    + }
    +
    +
  8. +
  9. Finally, we need to add the GameOverState. This is going to be a pretty simple FlxState where we show a message - either "Game Over" or "You Win!", depending on our won flag, and the final score for this player. We will also use flixel's save/load functionality to compare the previous highscores, and, if the new score is higher, replace the saved highscore, and show the highscore on the screen.

    +

    Finally, we have a button to take the player back to the main menu.

    +

    Here is the code for that State:

    +

    GameOverState.hx

    +
  10. +
+

If you test your game, you should be able to trigger the GameOverState by either dying in combat or defeating the boss, and then clicking on the button in the GameOverState will take you back to our MenuState so you can play again. If all of that works, you're on the right track! But… our MenuState is looking a little bland, now… let's fix that up!

+

+
    +
  1. Let's add a title and an options-button to the MenuState:

    +
     var titleText:FlxText;
    + var optionsButton:FlxButton;
    +
    +
  2. +
  3. Then, in create(), we'll add them to the state (and move the play-button as well):

    +
     titleText = new FlxText(20, 0, 0, "HaxeFlixel\nTutorial\nGame", 22);
    + titleText.alignment = CENTER;
    + titleText.screenCenter(X);
    + add(titleText);
    +
    + playButton = new FlxButton(0, 0, "Play", clickPlay);
    + playButton.x = (FlxG.width / 2) - playButton.width - 10;
    + playButton.y = FlxG.height - playButton.height - 10;
    + add(playButton);
    +
    + optionsButton = new FlxButton(0, 0, "Options", clickOptions);
    + optionsButton.x = (FlxG.width / 2) + 10;
    + optionsButton.y = FlxG.height - optionsButton.height - 10;
    + add(optionsButton);
    +
    +
  4. +
  5. Add the function that gets called when the options-button is clicked:

    +
     function clickOptions()
    + {
    +     FlxG.switchState(new OptionsState());
    + }
    +
    +
  6. +
  7. The OptionsState that is called from the options button is fairly simple. It will contain a button to allow the user to clear the saved data (highscores, etc), as well as a simple FlxBar to show the user the current volume level of the game with buttons to adjust it up or down. It will save the volume values so that each time the game starts, it will 'remember' what volume it was last set to (I know there's no sound…. yet ;))

    +

    The code for this State looks like this:

    +

    OptionsState.hx

    +

    The OptionsState class uses a different spritesheet for the volume adjustment buttons (because they should appear smaller than the default buttons). This asset must have 3 frames, one to represent each button state: NORMAL, HIGHLIGHT, and PRESSED. As long as we set up the frames in that order, the FlxButton class will handle the rest.

    +

    Once again, you can make your own, or use the image below. Place it in the assets/images folder, and you should be all set.

    +

    +

    Finally, we want our game to load the stored volume (if there is any) each time the game starts, so, go to Main.hx, and add this after the addChild() call:

    +
     var save = new FlxSave();
    + save.bind("TurnBasedRPG");
    + if (save.data.volume != null)
    + {
    +     FlxG.sound.volume = save.data.volume;
    + }
    + save.close();
    +
    +

    Pretty simple: it makes a new FlxSave object, binds it to our "TurnBasedRPG" and then checks if there is a volume value stored in it, and if there is, sets our game's volume to match, and then closes the save.

    +
  8. +
+

Test everything out, make sure it's working, and that if you change your volume under options and then exit the game, it retains the value the next time to get into the options screen.

+

+

Looking good! Next time we'll give our volume something to do by adding sound and music!

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/gamepads/index.html b/documentation/gamepads/index.html new file mode 100644 index 000000000..e5983a3ef --- /dev/null +++ b/documentation/gamepads/index.html @@ -0,0 +1,387 @@ + + + + + + + + + + Gamepads | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Gamepads

+ + + API + + Edit + +

Gamepad input for HaxeFlixel is provided through the FlxGamepad class and is available through FlxG.gamepads and the InputFrontEnd.

+

Since gamepads have a variety of manufacturers their keycodes provided to HaxeFlixel API differ from model to model. HaxeFlixel provides mappings that map buttons and sticks to common IDs for convenient use. Mappings are available for:

+
    +
  • XInput (Xbox 360, Xbox One, etc)
  • +
  • PS4
  • +
  • OUYA
  • +
  • Switch Joycons/Pro Controllers
  • +
  • Logitech
  • +
  • WiiRemote
  • +
  • Mayflash WiiRemote
  • +
  • MFi
  • +
  • PS Vita
  • +
+

For most gamepads HaxeFlixel will automatically detect the model and abstract the API inputs under a common "universal" gamepad model based on the Xbox 360 layout. The underlying device-specific "raw" inputs are still available for you to poll directly, if you choose.

+

Here's some example logic for basic detection using the "universal" gamepad API:

+
import flixel.FlxG;
+import flixel.FlxState;
+import flixel.input.gamepad.FlxGamepad;
+
+class PlayState extends FlxState
+{
+    override public function update(elapsed:Float):Void 
+    {
+        super.update(elapsed);
+
+        // Important: can be null if there's no active gamepad yet!
+        var gamepad:FlxGamepad = FlxG.gamepads.lastActive;
+        if (gamepad != null)
+        {
+            updateGamepadInput(gamepad);
+        }
+    }
+
+    function updateGamepadInput(gamepad:FlxGamepad):Void
+    {
+        if (gamepad.pressed.A)
+        {
+            trace("The bottom face button of the controller is pressed.");
+        }
+
+        if (gamepad.analog.justMoved.LEFT_STICK_X)
+        {
+            trace("The x axis of the left analog stick of the controller has been moved.");
+        }
+    }
+}
+
+

In this case, gamepad.pressed.A checks whether the bottom face button is pressed. On a PS4 controller this would be the "X" button, on an XBox 360 or XBox One controller this would be the "A" button.

+

Also, the gamepad.pressed.A syntax is shorthand for gamepad.pressed.check(FlxGamepadInputID.A). You want to use the latter syntax if you need to check a variable (which would be the case if the user can customize their inputs).

+

If you wanted to check a device-specific input, you would use the checkRaw function, like this: gamepad.pressed.checkRaw(PS4ID.X)

+

Device-specific inputs can be found in the flixel.input.gamepad.id package.

+

If you want to support a controller that HaxeFlixel doesn't provide the IDs for, the following methods of FlxGamePad methods should be helpful for working out what those IDs are:

+

Return the FlxGamepadInputID value under the "universal" gamepad model:

+
    +
  • firstPressedButtonID()
  • +
  • firstJustPressedButtonID()
  • +
  • firstJustReleasedButtonID()
  • +
+

Return the device-specific input ID value:

+
    +
  • firstPressedButtonRawID()
  • +
  • firstJustPressedButtonRawID()
  • +
  • firstJustReleasedButtonRawID()
  • +
+

Conditional to remove gamepads

+
FLX_NO_GAMEPAD
+
+

HaxeFlixel includes a conditional to omit using gamepads for optimization purposes if you are developing for a platform such as mobile, or your game just isn't designed for them.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/getting-started/index.html b/documentation/getting-started/index.html new file mode 100644 index 000000000..2372e2fad --- /dev/null +++ b/documentation/getting-started/index.html @@ -0,0 +1,265 @@ + + + + + + + + + + Getting Started | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Getting Started

+ + + Edit + +

Welcome to HaxeFlixel! To setup your Windows, Linux or Mac system to start making games, there are three steps:

+
    +
  1. Install Haxe
  2. +
  3. Install HaxeFlixel
  4. +
  5. Run Hello World
  6. +
+

After that, you have to choose an editor / IDE to work in. The most popular option is Visual Studio Code (VS Code) which has it's own pages here:

+ +

A more comprehensive list of options can be found on haxe.org.

+
+

Time to complete this installation is close to 20 minutes (depending on the speed of your Internet connection for downloading the components).

+

If you need more help, reach out via any of the communication channels.

+
+

Note: this guide is a community effort. If you think you can help us improve it, please submit a pull request on +GitHub - each page has an "Edit" button in the upper right corner for this.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/groundwork/index.html b/documentation/groundwork/index.html new file mode 100644 index 000000000..8d2105894 --- /dev/null +++ b/documentation/groundwork/index.html @@ -0,0 +1,498 @@ + + + + + + + + + + 3 - Groundwork | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

3 - Groundwork

+ + + Edit + +

Now it's time to think about what we actually want our game to be, and how we're going to pull it off.

+

The game we're going to help you build will be a very simple top-down 'dungeon crawler' game, where the player controls a single character, moves around a map, fights enemies and collects gold.

+

So, what does that all actually translate to in HaxeFlixel?

+
    +
  • First, we're going to need to setup our 'world' - this just means we'll need to have a FlxState where all the action happens, and figure out what we're going to put in the world.
  • +
  • For the dungeon itself, it will simply be a FlxTilemap - and we'll draw our maps in another tool.
  • +
  • We will need a FlxSprite to represent the player on the screen. This will be the sprite that player will be able to control.
  • +
  • Enemies will be FlxSprite objects as well, and we'll have a 'fancy' way to have different types of enemies.
  • +
  • We'll also need a HUD/Interface for the player to do stuff with and see what's going on. These will be a combination of FlxGroup, FlxSprite, FlxText, FlxButton objects and some other things.
  • +
+

We'll tackle each of these things one-by-one.

+

First up, let's create a simple menu. Eventually, we'll want a fancy MenuState with a button for options, but for right now, we'll just have a button that says "Play" and switches to our PlayState.

+
    +
  1. Go ahead and delete the line we added for our "Hello World" test within the PlayState.

    +
  2. +
  3. Now, right-click the source folder in VSCode's Explorer, select New File and enter MenuState.hx.

    +

    Then, you can just copy the content of PlayState.hx over, but replace the class name with MenuState:

    +
     class MenuState extends FlxState
    + {
    +
    +

    Right after the class declaration, we're going define a new variable. This is where you would define all the variables that you intend to use throughout a given class. We need to define a new FlxButton variable to use as our 'play' button. So, type:

    +
     var playButton:FlxButton;
    +
    +

    As before with FlxText, the import should be added automatically. If not, you can also add missing imports via the light bulb that should appear after saving the file when you have your cursor over FlxButton.

    +
  4. +
  5. Now, type the following on the lines before or after super.create(); within the create() method:

    +
     playButton = new FlxButton(0, 0, "Play", clickPlay);
    + add(playButton);
    +
    +

    (import flixel.ui.FlxButton;)

    +

    This creates a FlxButton object and assigns it to the playButton variable. We're telling it to make the button at position (0, 0) (the top left corner of the screen), to make it say "Play" on it, and to call the function clickPlay() when a user clicks the button (we yet have to implement clickPlay()). + Then we add the object to our state so that it can be shown and interacted with. + Don't worry about the position of the button right now, we're going to move it in a second.

    +
  6. +
  7. Now we need to define our clickPlay() function. Somewhere in the class, outside of any existing functions, type:

    +
     function clickPlay()
    + {
    +     FlxG.switchState(new PlayState());
    + }
    +
    +

    (import flixel.FlxG;)

    +

    This function calls FlxG.switchState(), which switches the state from whatever the current state is (MenuState) to a new instance of PlayState.

    +
  8. +
  9. Technically, at this point, the functionality would work - you could run your game and it would do what we want it to do, but we're missing a few things. + First, we want the button to be in a nicer place. Sure, we could set the x and y coordinates when we create it, but there's a simpler way to do it.

    +

    Back in create(), add a new line somewhere after we create our FlxButton, and before super.create(); type:

    +
     playButton.screenCenter();
    +
    +

    screenCenter() is a function which takes an object and centers it on the screen either horizontally, vertically or (by default) both. By calling it on our button, the button will be placed in the center of the screen.

    +
  10. +
  11. Next, we need to make sure that the game actually starts with our MenuState. Open Main.hx and replace the PlayState reference with MenuState.

    +
  12. +
  13. If you test your game out now, it should go straight to a black screen with our 'Play' button in the middle, and clicking the button will take you to another black screen. If that's what you get, it works! So far, so good!

    +
  14. +
+

Next, let's make a simple player sprite that you can move around on the screen.

+

First, we need to make a new Player class. You can think of classes as sort of a functional template. You can use them as-is in a project, but you also have the ability to extend them into new versions. You can kind of think of it as using tracing paper - when you extend a class, you put a new sheet of tracing paper on top - you can still see and use all the stuff in the original class (unless you draw over it), and you can add your own stuff.

+

We're going to be extending the FlxSprite class to create our Player class.

+
    +
  1. Create another new file in the source folder, this time called Player.hx.

    +
  2. +
  3. Let's create a very basic class which extends FlxSprite:

    +
     package;
    +
    + import flixel.FlxSprite;
    +
    + class Player extends FlxSprite
    + {
    +     public function new(x:Float = 0, y:Float = 0)
    +     {
    +         super(x, y);
    +     }
    + }
    +
    +

    With classes, we use the super keyword to refer to the parent class. So by calling super(x, y) within our constructor (called new), we are basically saying to go up the chain to our parent class, in this case FlxSprite, and call its constructor, passing it the x and y arguments that were passed to us.

    +
  4. +
  5. Next, we'll want to create a placeholder image to show us where our sprite is, so under super(x, y);, add:

    +
     makeGraphic(16, 16, FlxColor.BLUE);
    +
    +

    (import flixel.util.FlxColor;)

    +

    All we're doing here is saying that we want to make this sprite's graphic be a 16x16 pixel blue square.

    +
  6. +
  7. For right now, we just want to get the Player class initialized, make sure that it works, and try adding it to our PlayState. It's not going to move or do anything yet, that will come in a minute. So save the changes to our Player class, and go back to the PlayState. + We need to define our Player variable, so underneath the class line, add:

    +
     var player:Player;
    +
    +

    And in create(), before super.create(); add:

    +
     player = new Player(20, 20);
    + add(player);
    +
    +

    This simply assigns a new instance of our Player sprite to our player variable, telling it to be placed at (20, 20) on the screen, and adds it to our PlayState.

    +
  8. +
  9. If you run your project right now, you should see our blue player on the screen!

    +

    +

    Now let's get it to move around!

    +
  10. +
+

So, how do we actually want our player to move around on the screen? Let's support both arrow keys and WASD keys, in 8 directions: up, down, left, right, and diagonally. The player should move at a relatively fixed speed, but have a slight deceleration before stopping to give it just a little bit of 'feeling'.

+

First, define our player's movement speed and deceleration amounts:

+
    +
  1. In your player class, above the constructor, add:

    +
     static inline var SPEED:Float = 100;
    +
    +

    Since this is a constant value that won't change, we make it static inline as well as following the UPPER_CASE naming convention.

    +

    Then, in the constructor, after you call makeGraphic(), we need to add some drag:

    +
     drag.x = drag.y = 800;
    +
    +

    drag, in HaxeFlixel, is sort of a way to slow down an object when it's not being moved. This will prevent our player sprite from just running forever in the same direction when the user stops pressing any movement keys. + This is somewhat arbitrary based on what 'feels' right - we can come back and tweak the numbers later on.

    +
  2. +
  3. While there are plenty of ways to handle player movement, it can be simpler to add it to the Player class. We'll want to add a new function that will watch for player input and respond to it, so, make a new function:

    +
     function updateMovement()
    + {
    + }
    +
    +
  4. +
  5. First, inside that new function, we want to define some helper variables so we can easily tell which keys were pressed later on in the function:

    +
     var up:Bool = false;
    + var down:Bool = false;
    + var left:Bool = false;
    + var right:Bool = false;
    +
    +
  6. +
  7. Next, we want to actually find out which of these directions the player wants to move in. We'll do that by checking whether certain keys are currently being pressed:

    +
     up = FlxG.keys.anyPressed([UP, W]);
    + down = FlxG.keys.anyPressed([DOWN, S]);
    + left = FlxG.keys.anyPressed([LEFT, A]);
    + right = FlxG.keys.anyPressed([RIGHT, D]);
    +
    +

    (import flixel.FlxG;)

    +

    The anyPressed() function allows us to ask if any keys out of a list of keys are currently being pressed. You send it an array of keys (their names) and it will return true if any of them are pressed. There are a couple of similar functions to check for other key states we might use later on.

    +
  8. +
  9. Next, we want to cancel out opposing directions - if the player is pressing up and down at the same time, we're not going to move anywhere:

    +
     if (up && down)
    +     up = down = false;
    + if (left && right)
    +     left = right = false;
    +
    +
  10. +
  11. Next, we'll want to do something when the player is actually moving:

    +
     if (up || down || left || right)
    + {
    +
    + }
    +
    +
  12. +
  13. After that, we need to determine which direction to move the player in, and by how much. A common mistake in games that allow diagonal movement is something like this:

    +
     velocity.x = speed;
    + velocity.y = speed;
    +
    +

    While this will, technically, move something diagonally down and right, it will actually move much FASTER than it really should be moving. This is because of the way triangles work. So, for our player to move, we're not just going to set its velocity to speed - that would be too easy! Instead, we're going to calculate exactly what its velocity should be with angles!

    +

    The first part of this is to figure out what angle we want to have the player move based on the keys that are being pressed. With our player sprite's asset, angle 0 is to the right, and -90 (or 270) is up.

    +
     var newAngle:Float = 0;
    + if (up)
    + {
    +     newAngle = -90;
    +     if (left)
    +         newAngle -= 45;
    +     else if (right)
    +         newAngle += 45;
    + }
    + else if (down)
    + {
    +     newAngle = 90;
    +     if (left)
    +         newAngle += 45;
    +     else if (right)
    +         newAngle -= 45;
    + }
    + else if (left)
    +     newAngle = 180;
    + else if (right)
    +     newAngle = 0;
    +
    +

    All this will do is create a temporary variable to hold our angle, and then, based on which direction(s) the player is pressing, set that angle to the direction we plan on moving the player.

    +
  14. +
  15. Now that we know which angle the player should be moving in, we need to figure out with how much velocity it needs to move that way. We're going to do this by setting velocity.x to speed and velocity.y to 0. Then we rotate that point around (0, 0) by newAngle degrees.

    +
     velocity.setPolarDegrees(SPEED, newAngle);
    +
    +

    (import flixel.math.FlxPoint;)

    +

    ...and that's the end of our updateMovement() function!

    +
  16. +
  17. The only thing left to do is to override the update() function in Player.hx as well and call updateMovement() from it. VSCode can generate the necessary boilerplate code for you, just type override and a space, after which a completion popup should appear:

    +

    +

    Select update and press enter.

    +

    Now you just need to add the function call, after which it should look like this:

    +
     override function update(elapsed:Float)
    + {
    +     updateMovement();
    +     super.update(elapsed);
    + }
    +
    +

    The update() function, as you should remember, is called each 'frame' of the game. So, each time our PlayState gets its update() called, it calls update() on all of its members, including the player's update(). This in turn will run our updateMovement() logic and adjust the player's velocity accordingly. After that, it call its super.update(), which will take the velocity that we've just changed into account and figures out where the player sprite should move to.

    +
  18. +
+

Whew! It sounds a lot more complicated than it really is - if you try out the game right now, you'll see that you can run around the screen by pressing any combination of arrow keys and WASD!

+

Next, we'll work on making the player sprite actually look like something!

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/haxeflixel-conditionals/index.html b/documentation/haxeflixel-conditionals/index.html new file mode 100644 index 000000000..a8106d880 --- /dev/null +++ b/documentation/haxeflixel-conditionals/index.html @@ -0,0 +1,359 @@ + + + + + + + + + + HaxeFlixel Conditionals | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

HaxeFlixel Conditionals

+ + + Edit + +

What is "conditional compilation"?

+

Conditional compilation flags are a powerful feature Haxe offers to optimize your code by only compiling certain parts of it. For example, the following pseudo-code optimizes inputs based on the target platform:

+
#if (web || desktop)
+keyboardControls();
+mouseControls();
+#end
+
+#if desktop
+gamepadControls();
+#end
+
+#if mobile
+touchControls();
+#end
+
+

Basically, this means that for web or desktop targets, we want to have mouse and keyboard controls. In case of a mobile target, we want touch input. Like you can see, these so-called defines can also be nested: We only want gamepad controls to be available on non-web targets (line 4). So, all in all, these defines can be used largely like traditional if-statements, except their syntax varies slightly.

+

For more information on what defines are available, by default check out the OpenFL documentation on this topic.

+

HaxeFlixel specific defines

+

If you had a look at the OpenFL documentation, you might have found out that you can also set your own defines. When working with OpenFL, it's convenient to do so in the Project XML file. +HaxeFlixel makes use of this feature and allows you to optimize your game using the following defines (a list of them can also be found in the template):

+
// Example xml node to enable to Flixel record system.
+<haxedef name="FLX_RECORD" />
+

FLX_RECORD

+

Flixel features a powerful recording / playback feature which captures mouse and keyboard input. Since it's used rarely, we decided that it makes sense to turn it off by default. Setting this define however will enable it again.

+

FLX_MOUSE_ADVANCED

+

This define is required for middle and right mouse button input. On the flash target, a minimum flash player version of 11.2 is required. Listening to right click input will also disable the right-click menu of the flash player. There is currently no HTML5 support for this feature.

+

FLX_NO_NATIVE_CURSOR

+

By default, flixel uses the flash native cursor API. This gets rid of the almost unbearable mouse lag that is unavoidable otherwise. This define allows you to disable that - reasons for this might be that you want to target a flash player version older than 10.2 or that you need to use a cursor bigger than 32x32, which is not possible using the native cursor API.

+

FLX_NO_MOUSE

+

This allows you to optimize your game by compiling it without any mouse-related code, which can make sense for mobile targets. This is why in the template, if="mobile" is added to the haxedef set tag. Keep in mind that this might require you to use conditionals in your own code for anything related to FlxG.mouse, which does not exist if this define is set.

+

FLX_NO_KEYBOARD

+

This allows you to optimize your game by compiling it without any keyboard-related code, which can make sense for mobile targets. This is why in the template, if="mobile" is added to the haxedef set tag. Keep in mind that this might require you to use conditionals in your own code for anything related to FlxG.keyboard or FlxG.keys, which do not exist if this define is set.

+

FLX_NO_TOUCH

+

This allows you to optimize your game by compiling it without any touch-related code, which can make sense for desktop targets. This is why in the template, if="desktop" is added to the haxedef set tag. Keep in mind that this might require you to use conditionals in your own code for anything related to FlxG.touches, which does not exist if this define is set.

+

FLX_NO_GAMEPAD

+

This allows you to optimize your game by compiling it without any gamepad-related code. Keep in mind that this might require you to use conditionals in your own code for anything related to FlxG.gamepads, which does not exist if this define is set.

+

FLX_NO_SOUND_TRAY

+

This disables the flixel core sound tray, which appears whenever your adjust the volume via the 0 (mute the game), + or - keys. Note that this does not disable the ability to control the game's volume using these hotkeys, just the soundtray itself. You can disable volume control entirely by setting FlxG.sound.muteKeys, FlxG.sound.volumeUpKeys and FlxG.sound.volumeDownKeys to null.

+

FLX_NO_FOCUS_LOST_SCREEN

+

Flixel automatically pauses the game when it loses focus and shows its so-called "focus lost screen", which is basically an overlay darkening the screen area with a white "play-button" in the middle. Using this define disables that screen, but not the feature to automatically pause - use the FlxG.autoPause Bool for that.

+

FLX_NO_DEBUG

+

This disables the flixel core debugger, which you can toggle using the \ and ` keys. It makes sense to do so for release build, which is why unless="debug" is added to this tag in the template. It basically means that the flixel debugger is disabled when compiling a release, and enabled when compiling a debug build.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/haxeflixel-handbook/index.html b/documentation/haxeflixel-handbook/index.html new file mode 100644 index 000000000..16da4428e --- /dev/null +++ b/documentation/haxeflixel-handbook/index.html @@ -0,0 +1,316 @@ + + + + + + + + + + HaxeFlixel Handbook | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

HaxeFlixel Handbook

+ + + Edit + +

Welcome to the HaxeFlixel handbook. These pages are intended to answer common questions and explain the main ideas and structures behind most HaxeFlixel games. +As the types of games and use cases of HaxeFlixel are vast we appreciate developers making additions and improvements to this documentation through GitHub.

+

If you are familiar with AS3 and new to Haxe, we encourage you to read the AS3 and Haxe comparison.

+

HaxeFlixel's API is similar to the AS3 version, so existing documentation and resources for ActionScript 3 are still relevant.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/haxeflixel-targets/index.html b/documentation/haxeflixel-targets/index.html new file mode 100644 index 000000000..9b2161cda --- /dev/null +++ b/documentation/haxeflixel-targets/index.html @@ -0,0 +1,345 @@ + + + + + + + + + + HaxeFlixel Targets | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

HaxeFlixel Targets

+ + + Edit + +

HaxeFlixel currently supports the following targets through OpenFL:

+

Desktop

+
    +
  • Windows
  • +
  • Mac
  • +
  • Linux
  • +
+

Mobile

+ +

Web

+
    +
  • Flash
  • +
  • HTML5
  • +
+

Using these targets requires the appropriate SDK's and system setup assisted through the Lime setup commands.

+
lime setup windows
+lime setup mac
+lime setup android
+

HTML5

+

General HTML5 Guidelines

+
    +
  • Text: For now, you might prefer using bitmap fonts to avoid text issues. With regular fonts, you may favor larger text size (>12) in order to avoid blurriness, and try some manual adjustments if you have a scaling problem (or when you are trying to embed fonts, which is not supported).
  • +
  • Audio: You should use regular .ogg files . Though .mp3 and .wav files are supported, SoundJS may not recognise them and might stop your project from running until you delete/replace them.
  • +
  • Particles: You should keep the particle count low and not expect much in terms of performance.
  • +
+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/hello-world/index.html b/documentation/hello-world/index.html new file mode 100644 index 000000000..8b131e701 --- /dev/null +++ b/documentation/hello-world/index.html @@ -0,0 +1,305 @@ + + + + + + + + + + Hello World | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Hello World

+ + + Edit + +

"Hello World" is a common example of getting started with programming, here we will show you how to add Hello World with HaxeFlixel's FlxText. You can compile this test for any supported target platform.

+

Make sure you have installed Flixel, as well as set up the lime and flixel commands as explained previously.

+

Create a new HaxeFlixel Project

+

HaxeFlixel requires a basic structure of files for any project that can be created automatically for you. First open a command prompt and switch to the directory where you'd like to have the project using cd, for example:

+
cd C:\Users\<User>\Projects
+
+

Then run the template command (tpl for short):

+
flixel tpl -n "HelloWorld"
+
+

You will now see a new folder named "HelloWorld" with all the files for your project being created automatically.

+

Add the "Hello World" FlxText

+

Adding the text is as simple as opening the PlayState.hx file in the newly created source folder. The file should look like this:

+
package;
+
+import flixel.FlxState;
+
+class PlayState extends FlxState
+{
+    override public function create()
+    {
+        super.create();
+    }
+
+    override public function update(elapsed:Float)
+    {
+        super.update(elapsed);
+    }
+}
+
+

All you need to do is add the following three lines to the create() function (and save the file):

+
override public function create()
+{
+    super.create();
+
+    var text = new flixel.text.FlxText(0, 0, 0, "Hello World", 64);
+    text.screenCenter();
+    add(text);
+}
+
+

This will create a new FlxText instance with font size 64, center it on the screen and add() it so it is displayed.

+

Test the Project

+

Return to your command line window - now we can compile the project. First switch to the directory containing the Project.xml file:

+
cd HelloWorld
+
+

You can then compile to HTML5, Neko and Flash out of the box with these commands:

+
lime test html5
+lime test neko
+lime test flash
+
+

Other targets require further setup. For more details, check the "Advanced Setup" section of the Lime documentation.

+

If you struggled through any part of this tutorial, get in touch with the community for support.

+

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/index.html b/documentation/index.html new file mode 100644 index 000000000..0c9ff6c33 --- /dev/null +++ b/documentation/index.html @@ -0,0 +1,888 @@ + + + + + + + + + + Documentation | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Documentation

+ + + +

The HaxeFlixel documentation is provided from the flixel-docs repository and is open for contributions on GitHub that will be pushed here.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + +
+ +
+ + + + + + + + + + + + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +

+ + Discover HaxeFlixel Book +

+ +
+ +
+ + + + + + + + diff --git a/documentation/install-development-flixel/index.html b/documentation/install-development-flixel/index.html new file mode 100644 index 000000000..e88721e53 --- /dev/null +++ b/documentation/install-development-flixel/index.html @@ -0,0 +1,314 @@ + + + + + + + + + + Install development Flixel | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Install development Flixel

+ + + Edit + +

Developers may want to contribute and / or stay updated with the bleeding edge code of HaxeFlixel. Like any development code we caution the use of it as it may not have the same amount of testing as the stable version.

+

All new development is done on the dev branches of HaxeFlixel's GitHub repositories.

+

Prerequisites

+
    +
  • You must have completed the Getting Started guide to have the necessary dependencies (Haxe and OpenFL).

    +

    If you want to use development builds of OpenFL and Lime, please refer to these instructions:

    + +
  • +
  • Install Git

    +

    Windows-only note: ensure that during the installation process, you select the non-default option that allows you to use Git from the Windows command prompt (you'll also need to re-open your command prompt window after installation for Git to become available there).

    +
  • +
+

Install Flixel from GitHub

+

To obtain the newest version, please input the following command into your console:

+
haxelib git flixel https://github.com/HaxeFlixel/flixel
+
+

The same applies for any additional Flixel libraries:

+
haxelib git flixel-demos https://github.com/HaxeFlixel/flixel-demos
+haxelib git flixel-addons https://github.com/HaxeFlixel/flixel-addons
+haxelib git flixel-ui https://github.com/HaxeFlixel/flixel-ui
+
+

Should you want to use haxelib set <library> <version> to switch back to released versions, be sure to run haxelib dev <library> beforehand. haxelib git enables the "development directory" for a library, which overrides haxelib set commands.

+

Testing the installation with the Mode demo

+

Navigate to flixel-demos/Platformers/Mode. Compile and run the game with lime test <target>.

+

Need more help?

+

Get in touch with the community.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/install-haxeflixel/index.html b/documentation/install-haxeflixel/index.html new file mode 100644 index 000000000..ce4333ad6 --- /dev/null +++ b/documentation/install-haxeflixel/index.html @@ -0,0 +1,282 @@ + + + + + + + + + + Install HaxeFlixel | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Install HaxeFlixel

+ + + Edit + +

To install the latest stable version of HaxeFlixel, open a command prompt and run the following Haxelib commands:

+
haxelib install lime
+haxelib install openfl
+haxelib install flixel
+
+

After the installation is complete, you can compile games to HTML5, Flash and Neko out of the box.

+

To easily install additional libraries (addons, ui, demos, tools, templates...) in a single step, just run:

+
haxelib run lime setup flixel
+
+

Install the lime command

+
haxelib run lime setup
+
+

This makes lime available as a command (alias for haxelib run lime).

+

To compile to desktop and mobile targets, you have to make sure you have run the respective lime setup +commands. Each are specified in the +Lime "Advanced Setup" docs.

+

Install the flixel command

+

Run the following two commands to install flixel-tools (needed for project templates among other things):

+
haxelib install flixel-tools
+haxelib run flixel-tools setup
+
+

Updating HaxeFlixel

+

If a new version of Flixel has been released, and you want to update to it, you can use the following command to do so:

+
haxelib update flixel
+
+

If you wanted to update e.g. flixel-addons instead, just replace flixel with flixel-addons.

+

To stay informed about new releases, you can follow @HaxeFlixel on Twitter or check out our Blog from time to time.

+

Development version

+

If you are interested in using bleeding edge code from the development branch on GitHub, see instructions here.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/introduction-to-haxe/index.html b/documentation/introduction-to-haxe/index.html new file mode 100644 index 000000000..32e86a77e --- /dev/null +++ b/documentation/introduction-to-haxe/index.html @@ -0,0 +1,298 @@ + + + + + + + + + + Introduction to Haxe | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Introduction to Haxe

+ + + Edit + +

Haxe is a cross-platform toolkit for developing applications, games, multimedia and server side code natively. Cross-compiling your code offers longevity to your code base that is not possible for other methods of cross-platform development.

+

The Haxe programming language itself is high level and strictly typed. It allows for Object Orientated programming with similar to syntax in AS3 and Java. Haxe is often learnt quickly and loved by developers coming from similar languages. Haxe is a valuable language to learn not only for games, but server-side development, command line tools and various other technologies.

+

Haxe is an open source technology, free to use and modify. The Haxe Toolkit provides a powerful cross-platform standard library that lets your code solve problems and have a codebase that is more versatile.

+

Backed by the Haxe Foundation, industry sponsors and partners, it receives enterprise support and is sponsored and recognized by developers at a growing number of large companies such as Nickelodeon, Disney, TiVo, Stencyl and more.

+

Haxe is being developed on GitHub:

+ +

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/introduction-to-openfl/index.html b/documentation/introduction-to-openfl/index.html new file mode 100644 index 000000000..728ac1185 --- /dev/null +++ b/documentation/introduction-to-openfl/index.html @@ -0,0 +1,295 @@ + + + + + + + + + + Introduction to OpenFL | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Introduction to OpenFL

+ + + Edit + +

+

The Open Flash Library (OpenFL) previously known as NME, is an innovative framework designed to provide fast, productive development for Windows, Mac, Linux, iOS, Android, Flash and HTML5 – all using the same source code.

+

OpenFL has a history of providing the Flash API wherever possible however it is also used to extend upon that API. OpenFL is powered by the Haxe Toolkit's cross-compiler that lets it produce native code such as C++ for its target platforms.

+

OpenFL has a an active community of developers building games for the web, consoles, desktop and mobile devices. OpenFL is free to use and modify and it is currently being developed openly on GitHub. The project made from the combined work of talented and passionate developers over many years has resulted in a mature and advanced platform.

+

OpenFL targets include native cross-compiled C++ for desktop and mobile targets, as well as web targets such as Flash, HTML5 and experimental support for Emscripten. OpenFL is written primarily in the Haxe language as well as platform specific code integrating with SDKs and native APIs.

+

OpenFL provides HaxeFlixel with a familiar Flash API as well as an extended set of features for native targets. This includes the use of GPU accelerated texture batching through drawTiles, multi-threading and more.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/ios/index.html b/documentation/ios/index.html new file mode 100644 index 000000000..d55c952c1 --- /dev/null +++ b/documentation/ios/index.html @@ -0,0 +1,367 @@ + + + + + + + + + + iOS | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

iOS

+ + + Edit + +

+

The iOS target makes use of a chain of frameworks to compile your native iOS game from Haxe code. OpenFL uses the Hxcpp and XCode natively so no virtual machine is involved. +When you compile an iOS project an XCode project file is also automatically generated in the build directly so you can make use of the XCode profiler and toolset.

+

The Haxe compiler uses it's cpp target to compile your Haxe code for the LibSDL OpenGL library. +iOS is is part of the cpp group of targets so when developers mention cpp the topic will may be relevant to HaxeFlixel iOS.

+

With OpenFL using native-code and OpenGL with LibSDL, the rendering methods are different to where Flixel started with Flash. +iOS uses GPU accelerated Texture Batching for the best possible performance in mobile devices.

+

Conditionals

+
+
#if cpp
+//your iOS code
+#end
+
+#if ios
+//your iOS code
+#end
+
+#if mobile
+//your iOS code
+#end
+

Project XML settings

+

Mobile platforms can use a window width and height of 0, which is a special value that uses the full resolution of the current display.

+
<window width="0" height="0" background="#FFFFFF" fps="60" />
+

OpenFL also exposes the following specific settings for the iOS target:

+
<window hardware="true" allow-shaders="true" require-shaders="true" if="cpp"/>
+<window vsync="true" antialiasing="4" if="cpp" />
+<window orientation="portrait" /> || <window orientation="landscape" if="cpp"/>
+

Custom PNG icons and launch images: (Check iOS Icon and Image Sizes Guidelines for more info)

+
<set name="PRERENDERED_ICON" value="true" />
+
+<icon path="Icon.png" size="57" if="ios" />
+<icon path="Icon@2x.png" size="114" if="ios" />
+<icon path="Icon-72.png" size="72" if="ios" />
+<icon path="Icon-72@2x.png" size="144" if="ios" />
+
+<launchImage path="Default.png" width="320" height="480" if="ios" />
+<launchImage path="Default@2x.png" width="640" height="960" />
+<launchImage path="Default-Portrait~ipad.png" width="768" height="1024" if="ios" />
+<launchImage path="Default-Portrait@2x~ipad.png" width="1536" height="2048" if="ios" />
+<launchImage path="Default-Landscape~ipad.png" width="1024" height="768" if="ios" />
+<launchImage path="Default-Landscape@2x~ipad.png" width="2048" height="1536" if="ios" />
+<launchImage path="Default-568h@2x.png" width="640" height="1136" if="ios" />
+

Compile Commands

+

Visual Studio Code, FlashDevelop and IntelliJ IDEA support iOS compilation through their GUI.

+

Command line

+

The basic command to compile and test iOS:

+
lime test ios
+

Run this command from the root folder of your project, the default Project.xml will be used automatically.

+

If you want to use the iOS simulator, add -simulator when running/testing.

+
lime test ios -simulator
+
+ +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/keyboard/index.html b/documentation/keyboard/index.html new file mode 100644 index 000000000..94e5ce463 --- /dev/null +++ b/documentation/keyboard/index.html @@ -0,0 +1,371 @@ + + + + + + + + + + Keyboard | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Keyboard

+ + + API + + Edit + +

Keyboard input for HaxeFlixel is provided through the FlxKeyboard class and is available through FlxG.keys.

+

Key Lists

+

An object of type FlxKeyList contains a Bool for each key on the keyboard. The values are kept as an array internally, but you can easily refer to them by using special instance variables named after the key. For a full list of all available names look at the FlxKeyList documentation here.

+

FlxKeyboard uses the three key lists pressed, justPressed and justReleased to keep track of the keys. pressed contains true for all keys that are currently pressed. justPressed only contains true for all keys that have been pressed since the last frame.

+

Here's an example of how to put it all together:

+
override public function update(elapsed:Float):Void
+{
+    if (FlxG.keys.pressed.UP)
+    {
+        // The up arrow key is currently pressed
+        // This code is executed every frame, while the key is pressed
+    }
+
+    if (FlxG.keys.justPressed.LEFT)
+    {
+        // The left arrow key has just been pressed
+        // This code is only executed once, on the frame immediately after the key has been pressed
+    }
+
+    if (FlxG.keys.justReleased.LEFT)
+    {
+        // The left arrow key has just been released
+        // This code is only executed once, on the frame immediately after the key has been released
+    }
+
+    super.update(elapsed);
+}
+
+

Checking multiple keys

+

You can check multiple keys at once using the anyPressed(), anyJustPressed() and anyJustReleased() methods of FlxKeyboard. This allows you to bind multiple keys to one action easily, for example controlling the player with either WASD or the arrow keys. These methods take an Array of key names (as Strings) and return true if any of the given keys have the desired property.

+
override public function update(elapsed:Float):Void
+{
+    if (FlxG.keys.anyPressed([LEFT, A]))
+    {
+        // Move left
+    }
+
+    if (FlxG.keys.anyPressed([RIGHT, D]))
+    {
+        // Move right
+    }
+
+    super.update(elapsed);
+}
+
+

Conditionals

+

For general information on conditionals, please refer to this page.

+
    +
  • FLX_NO_KEYBOARD

    +

    This can be used to remove all keyboard-related logic from HaxeFlixel for optimization purposes, which can make sense on mobile targets, which is why it is combined with if="mobile" in the default Project.xml.

    +
  • +
+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/loading-the-tilemap/index.html b/documentation/loading-the-tilemap/index.html new file mode 100644 index 000000000..b9b28b42a --- /dev/null +++ b/documentation/loading-the-tilemap/index.html @@ -0,0 +1,372 @@ + + + + + + + + + + 6 - Loading the Tilemap | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

6 - Loading the Tilemap

+ + + Edit + +

One of the great things about using Ogmo with HaxeFlixel is that there is already a built-in class to load and use the maps. However, it's not in the 'standard' HaxeFlixel library - we have to install the flixel-addons library to get access to it.

+
    +
  1. Open up a new command prompt and enter:

    +
     haxelib install flixel-addons
    +
    +

    This should run and install the new library. Close the command prompt window when it's finished.

    +
  2. +
  3. Jump back into VSCode and open up your Project.xml file. We need to tell our project to include flixel-addons in the libraries.

    +
  4. +
  5. Look for a line that says:

    +
     <!--<haxelib name="flixel-addons" />-->
    +
    +

    and change it to:

    +
     <haxelib name="flixel-addons" />
    +
    +

    Save this change - you're now playing with flixel-addons!

    +
  6. +
  7. Go back to your PlayState, and, underneath where the player variable is defined, add:

    +
     var map:FlxOgmo3Loader;
    + var walls:FlxTilemap;
    +
    +

    We're basically just creating an object to hold our Ogmo map, and then another one to hold the FlxTilemap that we will generate from the Ogmo map.

    +
  8. +
  9. In create(), before we setup the player object, add:

    +
     map = new FlxOgmo3Loader(AssetPaths.turnBasedRPG__ogmo, AssetPaths.room_001__json);
    + walls = map.loadTilemap(AssetPaths.tiles__png, "walls");
    + walls.follow();
    + walls.setTileProperties(1, NONE);
    + walls.setTileProperties(2, ANY);
    + add(walls);
    +
    +

    This just loads our room file into our FlxOgmo3Loader object, generates our FlxTilemap from the 'walls' layer, and then sets tile 1 (our floor tile) to not collide, and tile 2 (walls) to collide from any direction. Then we add our tilemap to the state.

    +
  10. +
  11. Now, we need to make our player object get placed in the right location on the map. So, change where we initialize our player from:

    +
     player = new Player(20, 20);
    +
    +

    to:

    +
     player = new Player();
    + map.loadEntities(placeEntities, "entities");
    +
    +

    We're simply telling our map object to loop through all of the entities in our 'entities' layer, and call the placeEntities() for each one (which we're about to make now).

    +
  12. +
  13. Let's make the placeEntities() function now. When we call loadEntities() on our map, it will pass the data of all of the placed entities to whatever function we want. In our function, we need to take this information and do something with it. It will look like this now:

    +
     function placeEntities(entity:EntityData)
    + {
    +     if (entity.name == "player")
    +     {
    +         player.setPosition(entity.x, entity.y);
    +     }
    + }
    +
    +

    So, if this function gets passed an entity with the name "player", it will set our player object's x and y values to the entity's x and y values.

    +
  14. +
  15. Now, we want to add collisions to our state, so the player will bump into walls instead of just walking through them. So, in update(), after super.update(elapsed); add:

    +
     FlxG.collide(player, walls);
    +
    +

    All this does is check for overlaps between our player and the walls tilemap each update() call. If there are any overlaps, the objects are automatically separated from each other.

    +
  16. +
  17. Finally, we want to make a small tweak to the player sprite. It's a good idea to make sure that your player has a decent chance of making it through doorways. Since by default, our player sprite is the same size as our tiles (16x16 pixels), it makes it so the player has to thread the needle to make it through 1-tile wide doorways. To remedy this, we're going to change the player sprite's size and offsets. This won't change what is actually displayed for the player's graphic, only its hitbox.

    +

    So, in the Player class, in the constructor, under where we set the drag, add:

    +
     setSize(8, 8);
    + offset.set(4, 4);
    +
    +
  18. +
  19. Since we just changed the player's hitbox, we want to visualize it! Switch to HTML5 / Debug in the status bar and build the project. You can now press F2 to bring up HaxeFlixel's powerful debugging overlay.

    +

    Press the 3D-ish looking cube button in the upper right corner to render hitboxes:

    +

    +

    If you look closely, you can see that the player's is smaller than the tiles now.

    +
  20. +
+

In the next part, we'll talk about some small tweaks to the camera.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/mobile-targets/index.html b/documentation/mobile-targets/index.html new file mode 100644 index 000000000..7ba0289fc --- /dev/null +++ b/documentation/mobile-targets/index.html @@ -0,0 +1,540 @@ + + + + + + + + + + Mobile Targets | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Mobile Targets

+ + + Edit + +

With the penetration of mobile devices in the world ignoring mobile targets for your games and applications is ignoring a huge audience.

+

Mobile devices even though amazing have particular bottlenecks not present on desktop targets. The bottleneck most significant to HaxeFlixel games is the low powered CPU. HaxeFlixel's answer to this is to make use of GPU acceleration provided by OpenFL.

+

CPU

+

The processing power of mobile CPUs are often the biggest bottleneck when compared to a desktop target. Mobile CPUs are constrained by low power architectures and are simply not as powerful. Manipulating pixels like bitmap filters do with Flash software rendering is simply too slow for mobile devices. HaxeFlixel has answered this for Flixel games to use the GPU for rendering your sprites instead of using software rendering like its done with Flash.

+

Memory

+

Memory on mobile devices as you can imagine does not compare to the desktop. When we talk about memory it relates to how many textures your game can store to render as well as the amount of raw data and objects in your game's runtime state. Memory lets you cache objects for quick runtime access instead of creating objects during your gameplay which may cause skipping and low performance. This is why HaxeFlixel uses destroy method and has implemented support for texture atlas'.

+

Texture Size Limits

+

Due to the nature of mobile hardware there are often maximum sizes for textures that are much lower than desktop hardware. There is no definitive guide to size limits as it depends on the hardware of each device individually.

+

Here you can see an overview of size limits obtained from WebGL browsers http://webglstats.com/#h_texsize

+

You can also look up a device on glxbench.com, under the GL config tab look for GL_MAX_TEXTURE_SIZE.

+

Here is an overview of the variety in devices, feel free to add to the list;

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DeviceProcessorMax Texture SizeDisplay ResolutionMemory
+ +iPhone + + + +Armv6 + + + +1024x1024 + + + +480x320 + + + +128MB + +
+ +iPhone 3G + + + +Armv6 + + + +1024x1024 + + + +480x320 + + + +128MB + +
+ +iPhone 3GS + + + +Cortex-A8 + + + +2048x2048 + + + +480x320 + + + +256MB + +
+ +iPhone 4 + + + +Cortex-A8 + + + +2048x2048 + + + +960x640 + + + +512MB + +
+ +iPhone 4S + + + +Cortex-A9 Dual-Core + + + +4096x4096 + + + +960x640 + + + +512MB + +
+ +iPad + + + +Cortex-A8 + + + +2048x2048 + + + +1024x768 + + + +512MB + +
+ +iPad 2 + + + +Cortex-A9 Dual-Core + + + +2048x2048 + +4096x4096 (iOS 5.1) + + + +1024x768 + + + +512MB + +
iPad 3Cortex-A9 Dual-Core4096x40962048x15361024MB
+ +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/mouse/index.html b/documentation/mouse/index.html new file mode 100644 index 000000000..83f21c7f0 --- /dev/null +++ b/documentation/mouse/index.html @@ -0,0 +1,420 @@ + + + + + + + + + + Mouse | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Mouse

+ + + API + + Edit + +

Mouse input for HaxeFlixel is provided through the FlxMouse class and is available through FlxG.mouse. It is worth noting that it extends FlxPoint.

+

On non-mobile targets, the mouse starts out by being visible by default. You can set the visibility via FlxG.mouse.visible.

+

Left mouse button

+

The most common use of FlxG.mouse is checking the state of the left mouse button.

+
override public function update(elapsed:Float):Void
+{
+    if (FlxG.mouse.pressed)
+    {
+        // The left mouse button is currently pressed
+    }
+
+    if (FlxG.mouse.justPressed)
+    {
+        // The left mouse button has just been pressed
+    }
+
+    if (FlxG.mouse.justReleased)
+    {
+        // The left mouse button has just been released
+    }
+
+    super.update(elapsed);
+}
+
+
+

Exactly the same logic can be used for the middle and right mouse buttons. The properties are postfixed by Middle / Right, e.g. FlxG.mouse.pressedRight.

+

Cursor

+
import flixel.util.FlxColor;
+using flixel.util.FlxSpriteUtil;
+
+// Create a white circle to use as a cursor graphic
+var sprite = new FlxSprite();
+sprite.makeGraphic(15, 15, FlxColor.TRANSPARENT);
+sprite.drawCircle();
+
+// Load the sprite's graphic to the cursor
+FlxG.mouse.load(sprite.pixels);
+
+// Use the default mouse cursor again
+FlxG.mouse.unload();
+
+// To use the system cursor:
+FlxG.mouse.useSystemCursor = true;
+
+

Positional data

+

There are two kinds of position data available:

+
    +
  • World position (absolute)

    +
      FlxG.mouse.x
    +  FlxG.mouse.y
    +  FlxG.mouse.getWorldPosition(); // returns x / y as a FlxPoint
    +
    +
  • +
  • Screen position (relative)

    +
      FlxG.mouse.screenX
    +  FlxG.mouse.screenY
    +  FlxG.mouse.getScreenPosition(); // returns screenX / screenY as a FlxPoint
    +
    +
  • +
+

Mouse wheel

+

The current "delta" value of mouse wheel is provided in a simple Int property. If the wheel has just been scrolled up, it will have a positive value and vice versa. If it wasn't scrolled during the current frame, it's 0.

+
if (FlxG.mouse.wheel != 0)
+{
+    // Mouse wheel logic goes here, for example zooming in / out:
+    FlxG.camera.zoom += (FlxG.mouse.wheel / 10);
+}
+
+

Flash native cursor API

+

AS3-Flixel used a simple Sprite to display a bitmap graphic that is synchronized with the mouse position every frame. This approach is not optimal, as it causes what is commonly referred to as "mouse lag" - the cursor sprite lags behind the actual mouse position. Depending on the game's framerate and the player's mouse speed, this can be very noticeable and thus have a negative impact on the overall experience.

+

HaxeFlixel leverages the flash native cursor API for better mouse cursor performance. However, there are certain restrictions to native cursors:

+
    +
  • They can not exceed 32x32 pixels
  • +
  • No negative cursors are allowed, and the positive offsets are limited to the size
  • +
  • The targeted flash player version must be 10.2 or higher
  • +
+

Because of this, using the native cursor API is completely optional, see the section on the FLX_NO_NATIVE_CURSOR conditional.

+

Custom native cursors

+

You can use FlxG.mouse.load() for native cursors as usual, but if you want more fine-grained control, you can use the following functions:

+
FlxG.mouse.setSimpleNativeCursorData("custom", BitmapData);
+FlxG.mouse.registerNativeCursor("custom", MouseCursorData);
+
+

You can find more information on the MouseCursorData object here.

+

Use FlxG.mouse.setNativeCursor() to switch to an already registered native cursor.

+

Conditionals

+

For general information on conditionals, please refer to this page.

+
    +
  • FLX_NO_MOUSE_ADVANCED

    +

    By default, there are event listeners set up for both the middle and the right mouse button. There are two reasons for wanting to disable this:

    +
      +
    • it requires a minimum flash player version of 11.2
    • +
    • it removes the right-click menu of the flash-player
    • +
    +
  • +
  • FLX_NO_NATIVE_CURSOR

    +

    This disables the native cursor API on the flash target. For more info, check the "Flash native cursor API"-section above.

    +
  • +
  • FLX_NO_MOUSE

    +

    This can be used to remove all mouse-cursor-related logic from HaxeFlixel for optimization purposes, which can make sense on mobile targets, which is why it makes sense to combine this with if="mobile" in your Project.xml.

    +
  • +
+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/multiple-platforms/index.html b/documentation/multiple-platforms/index.html new file mode 100644 index 000000000..01bc38765 --- /dev/null +++ b/documentation/multiple-platforms/index.html @@ -0,0 +1,465 @@ + + + + + + + + + + 13 - Multiple Platforms | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

13 - Multiple Platforms

+ + + Edit + +

One of the big advantages of using HaxeFlixel is the ability to build your games for multiple platforms. You can build a working HTML5, Windows, Linux, Mac, Android and iOS game - all from the same code! So far, we've been working with HTML5, and, for the most part, you don't have to do too much to get your game working on other platforms - if you test it under Windows right now, it should mostly work just fine (although, without music, which we'll discuss later). However, you might run into some issues if you try to build it for a mobile device - at the very least, you won't be able to play it without a keyboard. We'll focus on Windows and Android in this tutorial and add a few things to make them work better on those platforms.

+

HaxeFlixel comes equipped with a powerful feature called conditionals. By adding some conditionals to your code, you can make it so that only certain pieces of code will be compiled depending on the conditionals you use. For example, if you are building for Android, which would probably not have a mouse, you could setup a conditional to skip over all mouse-related code. Alternately, you might also add some code to deal with touches, which would only work on mobile platforms, so you would make sure to wrap that logic in conditionals so that it doesn't try to build on Windows or HTML5.

+

It's not all that complicated. We'll start with something simple: adding the ability to toggle fullscreen mode on Windows.

+

Let's add a button to the OptionsState:

+
    +
  1. When we initialize and interact with our button, we only want to do it on desktop platforms. So, at the top of the class, add:

    +
     #if desktop
    + var fullscreenButton:FlxButton;
    + #end
    +
    +
  2. +
  3. In create(), somewhere after we add our volumeBar object, add:

    +
     #if desktop
    + fullscreenButton = new FlxButton(0, volumeBar.y + volumeBar.height + 8, FlxG.fullscreen ? "FULLSCREEN" : "WINDOWED", clickFullscreen);
    + fullscreenButton.screenCenter(X);
    + add(fullscreenButton);
    + #end
    +
    +
  4. +
  5. Then we need to add our callback function for that button:

    +
     #if desktop
    + function clickFullscreen()
    + {
    +     FlxG.fullscreen = !FlxG.fullscreen;
    +     fullscreenButton.text = FlxG.fullscreen ? "FULLSCREEN" : "WINDOWED";
    +     save.data.fullscreen = FlxG.fullscreen;
    + }
    + #end
    +
    +

    Yes, we wrap the entire function in our conditional - if we're not building for desktop, this function will not exist. You'll also notice that we are saving the value of FlxG.fullscreen - this will be used to 'remember' the game's screen state when they next launch the game.

    +
  6. +
  7. Next, let's change around our Main.hx so that when the game starts it will launch into whatever state the game was last in - fullscreen or not. We need to move things around a little, since we need to find out if we're going into fullscreen or not BEFORE we call new FlxGame(), but we need to set the volume AFTER, so new() should look like this:

    +
     var startFullscreen:Bool = false;
    + var save:FlxSave = new FlxSave();
    + save.bind("TurnBasedRPG");
    + #if desktop
    + if (save.data.fullscreen != null)
    + {
    +     startFullscreen = save.data.fullscreen;
    + }
    + #end
    +
    + super();
    + addChild(new FlxGame(320, 240, MenuState, 1, 60, 60, false, startFullscreen));
    +
    + if (save.data.volume != null)
    + {
    +     FlxG.sound.volume = save.data.volume;
    + }
    + save.close();
    +
    +
  8. +
  9. Next, we need to give players a way to exit the game if they're in fullscreen mode - since they won't easily have access to the close-button anymore. +We do that by adding a new button to the MenuState:

    +
     #if desktop
    + var exitButton:FlxButton;
    + #end
    +
    +

    And in create():

    +
     #if desktop
    + exitButton = new FlxButton(FlxG.width - 28, 8, "X", clickExit);
    + exitButton.loadGraphic(AssetPaths.button__png, true, 20, 20);
    + add(exitButton);
    + #end
    +
    +

    Then our callback function just looks like:

    +
     #if desktop
    + function clickExit()
    + {
    +     Sys.exit(0);
    + }
    + #end
    +
    +
  10. +
+

There you go! Now try it out on both HTML5 and Windows targets and notice the differences - you can't go fullscreen in HTML5, and you can in Windows. You also get the button to exit the game on the MenuState while on Windows.

+

To make our game work with Android, we have to make a few more changes. First, we need to make sure that our Project.xml is setup correctly so that our settings are right for Android.

+
    +
  1. In your app tag, at the very top of the file, add this attribute:

    +
     package="com.haxeflixel.turnBasedRPG"
    +
    +

    This will give your app a package name to be used on the Android device - it's best to be as unique as possible.

    +
  2. +
  3. You might be wondering how we're going to allow the user to move around in our game on a device without the keyboard or mouse. Well, HaxeFlixel comes with a FlxVirtualPad class which we can use to accept touch input from the user and translate it into movement. Head over to PlayState.hx:

    +

    Define:

    +
     #if mobile
    + public static var virtualPad:FlxVirtualPad;
    + #end
    +
    +

    Create and add (in create):

    +
     #if mobile
    + virtualPad = new FlxVirtualPad(FULL, NONE);
    + add(virtualPad);
    + #end
    +
    +
  4. +
  5. Since the player can't move while they're in combat, we're going to remove the distraction of our virtual pad while combat is happening. In the startCombat() function, add:

    +
     #if mobile
    + virtualPad.visible = false;
    + #end
    +
    +

    And, to make it reappear, in update(), somewhere around where we set inCombat to false, add:

    +
     #if mobile
    + virtualPad.visible = true;
    + #end
    +
    +
  6. +
  7. The only place where we actually check for button presses is in our Player class, in the updateMovement() function. We currently have a section of code that is setting different gs to true based on keyboard input - but since the keyboard might be disabled on some platforms, we need to change that to look like this:

    +
     #if FLX_KEYBOARD
    + up = FlxG.keys.anyPressed([UP, W]);
    + down = FlxG.keys.anyPressed([DOWN, S]);
    + left = FlxG.keys.anyPressed([LEFT, A]);
    + right = FlxG.keys.anyPressed([RIGHT, D]);
    + #end
    +
    +
  8. +
  9. Right after that logic, we'll add our logic that checks each of the buttons of our virtual pad to see which ones are pressed:

    +
     #if mobile
    + var virtualPad = PlayState.virtualPad;
    + up = up || virtualPad.buttonUp.pressed;
    + down = down || virtualPad.buttonDown.pressed;
    + left  = left || virtualPad.buttonLeft.pressed;
    + right = right || virtualPad.buttonRight.pressed;
    + #end
    +
    +

    Because of the way we've structured our movement logic, we don't need to make any other changes! Getting up set to true via keyboard or our virtual pad will do the same thing.

    +
  10. +
  11. Things are a little different for our combat screen. We could setup the virtual pad to work with our combat menu, but that would feel a little clunky, given that the user has the power to tap on whatever they want on the screen. Instead, we're going to utilize touches to figure out what the player wants to do.

    +

    This means, in our update function, we need to wrap everything that's currently inside updateKeyboardInput() with:

    +
     #if FLX_KEYBOARD
    + ...
    + #end
    +
    +
  12. +
  13. Inside of our if (!wait) statement, add:

    +
     updateTouchInput();
    +
    +

    And

    +
     function updateTouchInput()
    + {
    +     #if FLX_TOUCH
    +     for (touch in FlxG.touches.justReleased())
    +     {
    +         for (choice in choices.keys())
    +         {
    +             var text = choices[choice];
    +             if (touch.overlaps(text))
    +             {
    +                 selectSound.play();
    +                 selected = choice;
    +                 movePointer();
    +                 makeChoice();
    +                 return;
    +             }
    +         }
    +     }
    +     #end
    + }
    +
    +

    What this does is gets a list of all the touches that were just released this update and checks them one at a time to see if any were on top of one of our choices texts. If one of them is, we play our select sound, and act on the selection - ignoring any other touches that might have happened this update.

    +
  14. +
+

And that's everything! You should be able to run your game on HTML5, Windows (Neko, too!), and Android and have it work on each with slight variations. And you only have one project and one codebase!

+

Next we'll polish up our game and add a little juice to make it POP!

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/neko/index.html b/documentation/neko/index.html new file mode 100644 index 000000000..ab5c9ddfa --- /dev/null +++ b/documentation/neko/index.html @@ -0,0 +1,347 @@ + + + + + + + + + + Neko | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Neko

+ + + Edit + +

+

Neko is a high-level dynamically typed programming language and virtual machine. Neko as a target of HaxeFlixel and OpenFL supports an API close to the CPP builds of HaxeFlixel.

+

The NekoVM itself is part of the Haxe Toolkit and is used throughout Haxelib, Lime, OpenFL and flixel-tools to easily create cross-platform tools. Neko gives the power of the Haxe standard library to cross platform development tools.

+

Neko itself is also used server-side in websites and general backend systems like the Haxelib. It contains a fully featured threading and socket API as well as integration with the Apache server.

+

Joshua Granick:

+
+

"When NME (Now known as Lime/OpenFL) was first created, it was designed to provide graphics, sound and other media for the NekoVM, but since the performance was not yet ideal, Hugh then decided (if I have my order of events correct) to experiment with a C++ target for Haxe. It worked, and HXCPP was born."

+
+

Its advantages:

+
    +
  • Extremely fast compilation time that can run on Linux, Mac or Windows.
  • +
  • Since it uses almost the same API as the CPP builds, it is a quicker way to test. +When you test with Flash it will use a much different part of the Haxe API.
  • +
+

Its disadvantages:

+
    +
  • Being a virtual machine, it is does not perform as well as a native build using the SDL builds of Lime. +Performance can be close to the Flash Player depending on the context.
  • +
+

Conditionals

+
#if neko
+//your neko code
+#end
+
+#if desktop
+//your neko code
+#end
+

Command line

+

The basic command to compile and test the Neko target:

+
lime test neko
+
+ +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/openfl-project-xml-format/index.html b/documentation/openfl-project-xml-format/index.html new file mode 100644 index 000000000..b6088598e --- /dev/null +++ b/documentation/openfl-project-xml-format/index.html @@ -0,0 +1,269 @@ + + + + + + + + + + XML Project Format | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

XML Project Format

+ + + Edit + +

Every OpenFL project uses an XML file to setup the compile settings for your projects depending on your chosen target. This includes stage size, source paths, asset paths and more.

+

Click here to see the Project.xml from the default HaxeFlixel template.

+

This is a complete specification of the XML file:

+

Lime XML Project Format

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/pickups/index.html b/documentation/pickups/index.html new file mode 100644 index 000000000..1523c826a --- /dev/null +++ b/documentation/pickups/index.html @@ -0,0 +1,385 @@ + + + + + + + + + + 8 - Pickups | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

8 - Pickups

+ + + Edit + +

Now that we have our little guy running around our map, lets give him something to pick up. We'll add some simple coins that will add to the player's score when they are picked up.

+
    +
  1. Open up your project in Ogmo again, and click Edit Project.

    +
  2. +
  3. On the Entities tab, add a new entity:

    +

    +
  4. +
  5. Open up the level we used before, and, on the 'entities' layer, scatter a bunch of coins around:

    +

    +
  6. +
  7. We're going to make our coins be 8x8 pixels. For the coin's graphic, you can use this image , or make your own. Make sure you save this in assets/images.

    +
  8. +
  9. Get back into VSCode, and make a new Coin class:

    +
     package;
    +
    + import flixel.FlxSprite;
    +
    + class Coin extends FlxSprite
    + {
    +     public function new(x:Float, y:Float) 
    +     {
    +         super(x, y);
    +         loadGraphic(AssetPaths.coin__png, false, 8, 8);
    +     }
    + }
    +
    +
  10. +
  11. Now, head back to the PlayState. We need to change our map logic so that when it's loading the entities and sees a coin in our Ogmo file, it will add a Coin object to our state.

    +
  12. +
  13. First, let's make a group to hold all the coins in. At the top of our class, where we defined all our variables so far, add:

    +
     var coins:FlxTypedGroup<Coin>;
    +
    +

    Groups are like arrays of Flixel objects which can be used in a lot of different ways. In this case, since our group will only be containing coins, we will make it a FlxTypedGroup<Coin>.

    +

    In create(), after we add our walls, and before we initialize our player, we need to initialize and add our coin group:

    +
     coins = new FlxTypedGroup<Coin>();
    + add(coins);
    +
    +
  14. +
  15. Next, we just want to change our placeEntities() function to put a coin into our group every time it encounters one in our Ogmo file. At the end of our if statement, add:

    +
     else if (entity.name == "coin")
    + {
    +     coins.add(new Coin(entity.x + 4, entity.y + 4));
    + }
    +
    +

    This will simply create a new coin, tell it to be at the position defined in the Ogmo file (+4 to x and y to center it on the tile), and add it to the coin group.

    +
  16. +
  17. Now we need to have the player be able to collect the coins. We're going to use an overlap check to do this. In update(), after your FlxG.collide() call, add:

    +
    FlxG.overlap(player, coins, playerTouchCoin);
    +
    +

    This just says: every frame, check if there are any overlaps between the player and the coin group, and if there are, call playerTouchCoin.

    +
  18. +
  19. Let's add the playerTouchCoin() callback now:

    +
    function playerTouchCoin(player:Player, coin:Coin)
    +{
    +    if (player.alive && player.exists && coin.alive && coin.exists)
    +    {
    +        coin.kill();
    +    }
    +}
    +
    +

    This function simply verifies that the player and the coin that overlap each other are both alive and exist. If so, the coin is killed (we'll add the score a little later on).

    +

    If you run the game right now, as you walk around the map, each coin you touch will disappear. Works great, but it's a little boring… Let's add a little style!

    +
  20. +
  21. Go back to your Coin class, and add these functions:

    +
    override function kill()
    +{
    +    alive = false;
    +    FlxTween.tween(this, {alpha: 0, y: y - 16}, 0.33, {ease: FlxEase.circOut, onComplete: finishKill});
    +}
    +
    +function finishKill(_)
    +{
    +    exists = false;
    +}
    +
    +

    First, we override the kill() function - normally, by calling .kill() on an object, it will set both the alive and exists properties to false. In this case, we want to set alive to false, but we don't want to set exists to false just yet (objects which exists == false don't get drawn or updated). Instead, we initialize a FlxTween.

    +

    FlxTween is a powerful tool that lets you animate an object's properties. For our coins, we want to make it fade out while also rising up.

    +

    We set the duration to 0.33 seconds, and we are using the circOut easing style, to make the tween look a little nicer. Also we want to call finishKill() when the tween has completed, which just sets the coin's exists property to false, effectively removing it from the screen. By default, the tween type is set to ONESHOT so it is only executed once (instead of looping). You can change this by specifying a different type in the tween options, but in our case the default behavior is just what we need.

    +

    The type of the FlxTween complete callback is FlxTween->Void (receives a single FlxTween argument and returns nothing). In this case, we named it _ to indicate that we don't care about it, which is a common Haxe idiom (other than that, there's nothing special about it - to the compiler it's just an argument named _).

    +
  22. +
+

Try out the game now, and you'll notice the difference when you pick up coins! We'll do some more of this later on when we start adding 'juice' to our game.

+

+

In the next part, we'll talk about enemies!

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/polish/index.html b/documentation/polish/index.html new file mode 100644 index 000000000..c84f3297d --- /dev/null +++ b/documentation/polish/index.html @@ -0,0 +1,366 @@ + + + + + + + + + + 14 - Polish | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

14 - Polish

+ + + Edit + +

In this section, you're going to learn a few simple tricks to add some polish and juice to your game. Some of those have already been added here and there, but we'll go through a few places now to talk about them.

+

First up, there's a simple effect we can do with our camera to have it fade in or out. This works nice for transitions between states or screens. +We can add it to each of our states' create() function like so (right before super.create()):

+
FlxG.camera.fade(FlxColor.BLACK, 0.33, true);
+
+

Then, if you want to fade out (when switching states), you can do something like this:

+
FlxG.camera.fade(FlxColor.BLACK, 0.33, false, function()
+{
+    FlxG.switchState(new PlayState());
+});
+
+

Try adding this logic to all of your states and then see how much of an improvement it gives the flow of your game.

+

Next, let's give the player a little feedback whenever they get hurt in combat. We're going to make the screen shake briefly. So, go into the enemyAttack() function in CombatHUD and, right after we call FlxG.camera.flash (another neat little effect you can use in other projects), add:

+
FlxG.camera.shake(0.01, 0.2);
+
+

So, each time the player gets hurt in combat, the screen will flash white, and will shake a little bit for 0.2 seconds. Try it out!

+

I know we've used tweens a few times already, but lets add one to show the enemy getting hurt in combat. We're simply going to make a tween that moves the enemy a few pixels to the right, then triggers a second tween to move the enemy back - each one taking 0.1 seconds to complete. So, in the makeChoice() function of CombatHUD, right before we play the hurt sound for the enemy, add:

+
FlxTween.tween(enemySprite, {x: enemySprite.x + 4}, 0.1, {
+    onComplete: function(_)
+    {
+        FlxTween.tween(enemySprite, {x: enemySprite.x - 4}, 0.1);
+    }
+});
+
+

Check out how that looks. Tweens are a very simple and powerful tool to make your game feel more active when used properly.

+

Next, let's add a background effect to our CombatHUD to help bring our the combat screen out from the map a little bit. We're going to copy what's on the camera's buffer, desaturate it, and then apply a FlxWaveEffect to give it a wavy effect. HaxeFlixel has several effects like this that can be used for a number of effects (FlxGlitchEffect, FlxRainbowEffect...).

+
    +
  1. Open up the CombatHUD class and add this variable:

    +
     var screen:FlxSprite;
    +
    +
  2. +
  3. In the constructor, we'll initialize these two variables (add this before we create our background):

    +
     screen = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.TRANSPARENT);
    + var waveEffect = new FlxWaveEffect(FlxWaveMode.ALL, 4, -1, 4);
    + var waveSprite = new FlxEffectSprite(screen, [waveEffect]);
    + add(waveSprite);
    +
    +

    First, we make our screen, make it the size of the window, and just leave it empty for now. Then we create a FlxEffectSprite, tell it to target our screen, and set its properties. It only uses a single effect, our waveEffect instance (it's possible to chain multiple effects using FlxEffectSprite).

    +
  4. +
  5. Next, in initCombat we want to make our screen take a copy of whatever is on the camera's buffer and apply it to itself, and then desaturate the image. Our effect sprite will always copy whatever is on our screen every update automatically.

    +
     screen.drawFrame();
    + var screenPixels = screen.framePixels;
    +
    + if (FlxG.renderBlit)
    +     screenPixels.copyPixels(FlxG.camera.buffer, FlxG.camera.buffer.rect, new Point());
    + else
    +     screenPixels.draw(FlxG.camera.canvas, new Matrix(1, 0, 0, 1, 0, 0));
    +
    + var rc:Float = 1 / 3;
    + var gc:Float = 1 / 2;
    + var bc:Float = 1 / 6;
    + screenPixels.applyFilter(screenPixels, screenPixels.rect, new Point(), new ColorMatrixFilter([rc, gc, bc, 0, 0, rc, gc, bc, 0, 0, rc, gc, bc, 0, 0, 0, 0, 0, 1, 0]));
    +
    +
  6. +
+

That's all there is to it! Our effect sprite will fade in and out with the CombatHUD already. Try our the effect to see how it looks!

+

+

You might have noticed, while testing the game, that the mouse cursor can get in the way - especially since it's not needed outside of the menu states. We can remedy this pretty easily. +In the PlayState's create(), add:

+
#if FLX_MOUSE
+FlxG.mouse.visible = false;
+#end
+
+

And be sure to do the reverse (= true) in GameOverState's create() No more pesky mouse cursor when we don't need it!

+

There are plenty of other tweaks and tricks you can add to your games. Try playing around with the different addons special effects classes in HaxeFlixel and see what else you can come up with. Take a look at the demos for more examples.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/resources/index.html b/documentation/resources/index.html new file mode 100644 index 000000000..1b9d0f6b6 --- /dev/null +++ b/documentation/resources/index.html @@ -0,0 +1,262 @@ + + + + + + + + + + Resources | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Resources

+ + + Edit + +

Developing games in general is made easier by making the most of the resources in communities both online and offline.

+

We are here collecting resources to help you learn and make games. Code snippets, tutorials and general information for game development is all wanted, so please make a pull request to these pages and make these resources even better!

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/setup/index.html b/documentation/setup/index.html new file mode 100644 index 000000000..b8aa3c241 --- /dev/null +++ b/documentation/setup/index.html @@ -0,0 +1,310 @@ + + + + + + + + + + 1 - Setup | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

1 - Setup

+ + + Edit + +

The first things we need to do is install all of the components we need to work with HaxeFlixel. For that, please follow our general Getting Started guide. This will get you:

+
    +
  • Haxe
  • +
  • Lime
  • +
  • OpenFL
  • +
  • HaxeFlixel
  • +
+

In this tutorial we will be using Visual Studio Code (VSCode) as our editor. See here for setup and general usage instructions.

+

Assuming everything went smoothly, you should be all set - now we can actually get to the fun part and start coding!

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/sound-and-music/index.html b/documentation/sound-and-music/index.html new file mode 100644 index 000000000..64382f2db --- /dev/null +++ b/documentation/sound-and-music/index.html @@ -0,0 +1,441 @@ + + + + + + + + + + 12 - Sound and Music | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

12 - Sound and Music

+ + + Edit + +

Our game is really coming together now, but it's still missing something… there's no sound yet!

+

For this game, we're going to keep it simple (as usual). We're going to have a single, continuously looping track that plays while our game is running. We will also have several, simple sound effects that play for different actions. Playing sounds and music in HaxeFlixel is pretty easy, so this will go quickly!

+

First, you'll need to make your music and sounds. Patrick Crecelius from Fat Bard has provided some music for this tutorial - feel free to use it for this tutorial, or make your own.

+

We've also created some sound effects using Bfxr, which you can use if you like, or, make your own!

+

If you've been following along since the UI and Combat section, you already downloaded a few of these, but be sure you have them all.

+
    +
  • coin.wav - new! to be used when the player picks up a coin

    +
  • +
  • combat.wav - to be used when combat starts

    +
  • +
  • fled.wav - will play when the player successfully flees from combat

    +
  • +
  • hurt.wav - will play whenever either the player or the enemy hits with an attack

    +
  • +
  • lose.wav - will play when the player dies in combat

    +
  • +
  • miss.wav - will play whenever either the player or the enemy misses with an attack

    +
  • +
  • select.wav - used by buttons and when the player makes a selection

    +
  • +
  • step.wav - new! used by the player and the enemies for 'footstep' sounds

    +
  • +
  • win.wav - used when the player wins in combat

    +
  • +
+

Once you have your music, place it in assets/music, and your sound files should go in assets/sounds.

+

Now let's change our code to use these sounds:

+
    +
  1. First, open up MenuState.hx. Since we want our music to start as soon as the game starts, and loop continuously no matter what happens, we're going to add this to create().

    +
     if (FlxG.sound.music == null) // don't restart the music if it's already playing
    + {
    +     FlxG.sound.playMusic(AssetPaths.HaxeFlixel_Tutorial_Game__ogg, 1, true);
    + }
    +
    +

    We're also checking if the music is already playing, since we don't want to restart it unnecessarily in that case.

    +

    If you try your game out right now, it should play music!

    +
  2. +
  3. Next, we want to make our buttons all make a sound when they get clicked. This is simple, we just tell the button's onUp to load our sound. In the MenuState's create(), after you initialize the play-button, add this:

    +
     playButton.onUp.sound = FlxG.sound.load(AssetPaths.select__wav);
    +
    +
  4. +
  5. Now, you can do the same for the options button (changing playButton to optionsButton).

    +

    For each of the other buttons in our game - four of them in OptionsState, and one in GameOverState - the code already exists, but as a learning exercise, you can go through those files and see what was done.

    +
  6. +
  7. Next, let's give our player some footsteps. We don't want to create and destroy a new sound object every time we want to play the same sound, so we will create a FlxSound object to be used over and over. At the top of the Player class, add:

    +
     var stepSound:FlxSound;
    +
    +
  8. +
  9. Then, we need to load the footstep sound somewhere in the constructor:

    +
     stepSound = FlxG.sound.load(AssetPaths.step__wav);
    +
    +
  10. +
  11. Now go to our updateMovement() function, and, after we check if the player is moving (if ((velocity.x != 0 || velocity.y != 0) && touching == NONE)), add:

    +
     stepSound.play();
    +
    +

    A neat little property of FlxSound objects is that if you ever tell one to play, if it's already playing (and you haven't set the forceRestart flag), it won't play again. This means we can easily call play on our sound every frame, and it will sound as if the sound is just being looped - for as long as the player is moving, but will finish if the player has stopped moving, and not start up again while they are stationary.

    +
  12. +
  13. Now, let's give enemies their own footsteps, too. The difference is, instead of just always playing the step sound at full volume, we're going to change the volume based on the proximity of the enemy to the player. This will be easier than it sounds. First, add our sound variable to the top of Enemy.hx:

    +
     var stepSound:FlxSound;
    +
    +
  14. +
  15. And then, similarly to how we setup the Player class, add this to our constructor:

    +
     stepSound = FlxG.sound.load(AssetPaths.step__wav, 0.4);
    + stepSound.proximity(x, y, FlxG.camera.target, FlxG.width * 0.6);
    +
    +

    You'll notice that we are setting the volume to 0.4 (40%) this is because there will be plenty of enemies on the map, and there footsteps can get kind of annoying and loud (besides, they're probably walking around the dungeon barefoot, right?).

    +
  16. +
  17. We then setup our proximity for our sounds, setting it's position to the x and y position of this enemy, and telling it to target the FlxG.camera.target object (which happens to be our player!). Finally, we say that the radius of our footstep sound is a little bit more than half of the screen's width - so we should be able to hear enemies that are just off the screen, and all the enemies' footsteps will sound louder/softer based on their distance from the camera target.

    +
  18. +
  19. Next, similarly to where we added the player's step sounds, we're going to have the enemy play sounds, when it's playing it's walk animation. For these sounds, however, we will give the sound a position in the world.

    +
    stepSound.setPosition(x + frameWidth / 2, y + height);
    +stepSound.play();
    +
    +
  20. +
  21. Next, let's head over to PlayState. We really only need one sound to be in the PlayState itself, and that's the one for picking up a coin. While you could put this into the Coin class, because there could be a lot of coins loaded at once, and because we really can't pick up more than one coin at a time (so the sounds don't need to overlap), putting a single coin sound effect in our PlayState saves us a bit of overhead.

    +

    So, just like our other sounds, initialize the variable:

    +
    var coinSound:FlxSound;
    +
    +

    Load the sound in create():

    +
    coinSound = FlxG.sound.load(AssetPaths.coin__wav);
    +
    +

    And in playerTouchCoin(), inside the if-statement, add:

    +
    coinSound.play(true);
    +
    +

    This time we will use forceRestart so that if the player happens to pickup several coins close to each other the sound will keep up with them.

    +
  22. +
  23. All of the rest of our sounds, because they deal with combat, will be in our CombatHUD class.

    +

    Assuming you downloaded the CombatHUD file, the sounds should already be there, but as a learning exercise, it's a good idea to go through and check. This will help you better understand sounds for when you're working on your next game.

    +

    To initialize them:

    +
    var fledSound:FlxSound;
    +var hurtSound:FlxSound;
    +var loseSound:FlxSound;
    +var missSound:FlxSound;
    +var selectSound:FlxSound;
    +var winSound:FlxSound;
    +var combatSound:FlxSound;
    +
    +

    To load them:

    +
    fledSound = FlxG.sound.load(AssetPaths.fled__wav);
    +hurtSound = FlxG.sound.load(AssetPaths.hurt__wav);
    +loseSound = FlxG.sound.load(AssetPaths.lose__wav);
    +missSound = FlxG.sound.load(AssetPaths.miss__wav);
    +selectSound = FlxG.sound.load(AssetPaths.select__wav);
    +winSound = FlxG.sound.load(AssetPaths.win__wav);
    +combatSound = FlxG.sound.load(AssetPaths.combat__wav);
    +
    +

    You can probably figure out where they all go, but I'll go through them anyway.

    +

    In initCombat():

    +
    combatSound.play();
    +
    +

    In finishFadeIn():

    +
    selectSound.play();
    +
    +

    In update(), inside each of our three if statements related to button presses (if (_fire), else if (up), else if (down)):

    +
    selectSound.play();
    +
    +

    In makeChoice(), in our logic for a 'hit' (after _damages[1].text = "1";):

    +
    hurtSound.play();
    +
    +

    and in our miss logic:

    +
    missSound.play();
    +
    +

    Further down, if the player escapes (after outcome = ESCAPE):

    +
    fledSound.play();
    +
    +

    In enemyAttack(), if the enemy hits:

    +
    hurtSound.play();
    +
    +

    and if they miss:

    +
    missSound.play();
    +
    +

    Finally, in doneDamageOut(), after outcome = DEFEAT:

    +
    loseSound.play();
    +
    +

    and after outcome = VICTORY:

    +
    winSound.play();
    +
    +
  24. +
+

And that's it for sound! Play your game now, and you should hear all of the effects we've added (make sure your volume is up high enough, too!) It's starting to look like a real game! Next time, we'll get it working on multiple platforms!

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/sprites-and-animation/index.html b/documentation/sprites-and-animation/index.html new file mode 100644 index 000000000..92d62da36 --- /dev/null +++ b/documentation/sprites-and-animation/index.html @@ -0,0 +1,397 @@ + + + + + + + + + + 4 - Sprites and Animation | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

4 - Sprites and Animation

+ + + Edit + +

So we have a player sprite that moves around the screen. Great! But… we don't want it to just look like a block… so let's add some graphics!

+

First, you need to have the sprite's graphic. Using your image editor of choice, you can draw pretty much anything you want, and save it as a transparent .png. For our player sprite, we're going to have it be made up of 16x16 pixel frames, with two different frames for each of the 4-possible facing directions (left and right are used by the same 2 frames, since we will be flipping them later).

+

You can draw it yourself, if you want, or use this image, created by my friend Vicky Hedgecock for this tutorial:

+

+

Save your file in assets/images.

+

Now we need to actually load the player's graphic into the sprite. So, bring up your Player class again.

+
    +
  1. Remove the makeGraphic() call from your constructor, and replace it with:

    +
     loadGraphic(AssetPaths.player__png, true, 16, 16);
    +
    +

    This tells your sprite to use the player.png graphic, that it's animated, and that each frame is 16x16 pixels. AssetPaths is a class generated by a neat Haxe macro which builds its variables from the contents of your Project.xml's assets tag. Macros are a little complicated, but worth taking a look into at some point. In this case, we use AssetPaths as an easy way to reference our assets in code. Note that we could also just use a raw string path like "assets/images/player.png".

    +
  2. +
  3. Next, we want to allow the sprite to be flipped based on its facing value. This makes it so we only need sprites for one direction (left), and not two (left and right).

    +

    Add the following:

    +
     setFacingFlip(LEFT, false, false);
    + setFacingFlip(RIGHT, true, false);
    +
    +

    All we're doing here is saying that we don't want to flip anything when facing left (because our sprite already faces left), and to flip horizontally when facing right. We could do the same for up and down if we wanted.

    +
  4. +
  5. Then, we want to make the hitbox match the graphics. With this more top down perspective, it's good practice for the hitbox to match the feet, so let's set ours to the bottom middle of the sprite:

    +
     setSize(8, 8);
    + offset.set(4, 8);
    +
    +
  6. +
  7. Now, we need to define our animations. In our case, we want a unique animation for each direction, except the right-facing one will be a mirrored version of the left-facing animation. We also want a "idle" and "walk" animations, depending on whether the player is moving. So, add:

    +
     animation.add("d_idle", [0]);
    + animation.add("lr_idle", [3]);
    + animation.add("u_idle", [6]);
    + animation.add("d_walk", [0, 1, 0, 2], 6);
    + animation.add("lr_walk", [3, 4, 3, 5], 6);
    + animation.add("u_walk", [6, 7, 6, 8], 6);
    +
    +

    We're finished with the constructor changes, the final step is to change our updateMovement() function to tell the player sprite which way to face. So, modify our section which deals with setting the player's angle so that it will also set its facing, accordingly:

    +
     if (up || down || left || right)
    + {
    +     var newAngle:Float = 0;
    +     if (up)
    +     {
    +         newAngle = -90;
    +         if (left)
    +             newAngle -= 45;
    +         else if (right)
    +             newAngle += 45;
    +         facing = UP;
    +     }
    +     else if (down)
    +     {
    +         newAngle = 90;
    +         if (left)
    +             newAngle += 45;
    +         else if (right)
    +             newAngle -= 45;
    +         facing = DOWN;
    +     }
    +     else if (left)
    +     {
    +         newAngle = 180;
    +         facing = LEFT;
    +     }
    +     else if (right)
    +     {
    +         newAngle = 0;
    +         facing = RIGHT;
    +     }
    +
    +     // determine our velocity based on angle and speed
    +     velocity.setPolarDegrees(SPEED, newAngle);
    + }
    +
    +

    Now we can use this facing value to determine which animation to use, but we also need to know whether the player is currently moving or not. Using these values we will determine with animation to use:

    +
     var action = "idle";
    + // check if the player is moving, and not walking into walls
    + if ((velocity.x != 0 || velocity.y != 0) && touching == NONE)
    + {
    +     action = "walk";
    + }
    +
    + switch (facing)
    + {
    +     case LEFT, RIGHT:
    +         animation.play("lr_" + action);
    +     case UP:
    +         animation.play("u_" + action);
    +     case DOWN:
    +         animation.play("d_" + action);
    +     case _:
    + }
    +
    +

    Every time this function gets called, it will check to see which of the directions the player is pressing, and, based on those, which way the sprite should be facing, and which animation should be playing.

    +

    Note: Calling animation.play with an animation name matching the current animation will not restart the animation.

    +
  8. +
  9. Save your changes and run your project, and you should see your player sprite animate while being moved, and facing the right direction!

    +

    +
  10. +
+

Next, we'll talk about maps and collision!

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/the-power-of-haxeflixel/index.html b/documentation/the-power-of-haxeflixel/index.html new file mode 100644 index 000000000..bdc9843ef --- /dev/null +++ b/documentation/the-power-of-haxeflixel/index.html @@ -0,0 +1,315 @@ + + + + + + + + + + The Power of HaxeFlixel | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

The Power of HaxeFlixel

+ + + Edit + +

First, let me talk a bit about why you should use HaxeFlixel.

+

HaxeFlixel gets its roots from the AS3 Flixel Framework created by +Adam ‘Atomic’ Saltsman. If you’ve played Canabalt, +you’ve seen the early version of this framework in action. HaxeFlixel takes the idea and the general structure of +Flixel, separates it from Flash, and combines it with the power and freedom of Haxe - which is a +multi-platform language, so that you can write games that can be easily published to all sorts of platforms +(Windows, Linux, Mac, HTML5, iOS, Android, and more).

+

HaxeFlixel comes with a ton of built-in features - classes, utilities, and functions - that handle a lot +of common or complex things that you might need to do. And, because it’s open-source, if you find something that it +can’t do, it’s really easy to change the code - and if your changes would benefit others, +add them to the library.

+

It is a library that is easy to use, but offers the freedom and power to do anything you can think of without +limitations caused by a rigid interface.

+

You can find out more about HaxeFlixel here.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/troubleshooting/index.html b/documentation/troubleshooting/index.html new file mode 100644 index 000000000..c1a9a69fb --- /dev/null +++ b/documentation/troubleshooting/index.html @@ -0,0 +1,342 @@ + + + + + + + + + + Troubleshooting | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Troubleshooting

+ + + Edit + +

Unexpected behaviour one one may find with sources that are hard to determine.

+

Timestep

+

By default the library performs calculations with a fixed timestep, to change this set FlxG.fixedTimestep = false

+

Explanation of timesteps

+

If you are unfamiliar with timesteps, here is a quick explanation.

+

A fixed timestep results in FlxG.elapsed always returning the same value in each update() iteration. The result is that the game runs "slower" if the computer can't keep up with the update speed. So for example, if the game is supposed to run at 60 FPS and it's running at 30 FPS, the user will perceive it to run at half the expected speed.

+

A variable timestep results in FlxG.elapsed returning a value according to the time that passed since the last update() call, and the game running at perceivably the expected speed for the user. However if the framerate is too low and the coder hasn't been careful (or studied Numerical Analysis), it could result in unpredicted behaviour and a game that doesn't run slow but is simply unplayable or broken.

+

Framerate inconsistency in an empty FlxState

+

A possible cause for this is related to input handling. To fix, you may want to disable any inputs you don't use in your target platforms at compile time. +The library offers some conditional compilation flags for this:

+
    +
  • FLX_NO_MOUSE
  • +
  • FLX_NO_KEYBOARD
  • +
  • FLX_NO_TOUCH
  • +
  • FLX_NO_GAMEPAD
  • +
+

These can be passed as parameters preceded by -D if compiling via command line (for example -D FLX_NO_MOUSE), or passed by adding them to your Project.XML file if you have one. For example, someone who is publishing to multiple platforms could have:

+
<haxedef name="FLX_NO_MOUSE" if="mobile" />
+<haxedef name="FLX_NO_KEYBOARD" />
+<haxedef name="FLX_NO_TOUCH" if="desktop"/>
+<haxedef name="FLX_NO_GAMEPAD" if="web"/>
+
+

If you created your Project.XML from a template, these options are most likely already in the file but commented out.

+

Undesired stretching when window size varies

+

Assigning a new instance of any of the classes that inherit from BaseScaleMode to FlxG.scalemode will set this to the desired scaling. However these settings may override the zoom value set when instancing a FlxGame.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/tutorial/index.html b/documentation/tutorial/index.html new file mode 100644 index 000000000..ff6ec730d --- /dev/null +++ b/documentation/tutorial/index.html @@ -0,0 +1,304 @@ + + + + + + + + + + Tutorial | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Tutorial

+ + + Edit + +

Welcome to HaxeFlixel! In this tutorial, you will learn how to create a complete game in HaxeFlixel from start to finish, and then some. Each step is broken into smaller chunks to help you get through even the most complicated and daunting steps.

+

This tutorial is geared towards building for HTML5, Windows, and Android. We will work primarily with HTML5 most of the time.

+

We are going to be building a small dungeon crawler. You can see the finished product here:

+


+

+

+

If you have any questions or get stuck during this tutorial, you can get help here. Also, the finished game is part of flixel-demos, so you can always compare to the source code of the finished game if you're unsure about something.

+

So let's go ahead and get started!

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/ui-and-combat/index.html b/documentation/ui-and-combat/index.html new file mode 100644 index 000000000..0625262ee --- /dev/null +++ b/documentation/ui-and-combat/index.html @@ -0,0 +1,494 @@ + + + + + + + + + + 10 - UI and Combat | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

10 - UI and Combat

+ + + Edit + +

Now we want to show the player what's going on. So we need to have some kind of HUD on the screen to tell them what their current/max health is, and how many coins they have. For the health icon you can use this image , or make your own. Make sure you save this in assets/images.

+
    +
  1. We'll start by making a new HUD class which will hold all our HUD elements:

    +
     package;
    +
    + import flixel.FlxG;
    + import flixel.FlxSprite;
    + import flixel.group.FlxGroup.FlxTypedGroup;
    + import flixel.text.FlxText;
    + import flixel.util.FlxColor;
    +
    + using flixel.util.FlxSpriteUtil;
    +
    + class HUD extends FlxTypedGroup<FlxSprite>
    + {
    +     var background:FlxSprite;
    +     var healthCounter:FlxText;
    +     var moneyCounter:FlxText;
    +     var healthIcon:FlxSprite;
    +     var moneyIcon:FlxSprite;
    +
    +     public function new()
    +     {
    +         super();
    +         background = new FlxSprite().makeGraphic(FlxG.width, 20, FlxColor.BLACK);
    +         background.drawRect(0, 19, FlxG.width, 1, FlxColor.WHITE);
    +         healthCounter = new FlxText(16, 2, 0, "3 / 3", 8);
    +         healthCounter.setBorderStyle(SHADOW, FlxColor.GRAY, 1, 1);
    +         moneyCounter = new FlxText(0, 2, 0, "0", 8);
    +         moneyCounter.setBorderStyle(SHADOW, FlxColor.GRAY, 1, 1);
    +         healthIcon = new FlxSprite(4, healthCounter.y + (healthCounter.height/2)  - 4, AssetPaths.health__png);
    +         moneyIcon = new FlxSprite(FlxG.width - 12, moneyCounter.y + (moneyCounter.height/2)  - 4, AssetPaths.coin__png);
    +         moneyCounter.alignment = RIGHT;
    +         moneyCounter.x = moneyIcon.x - moneyCounter.width - 4;
    +         add(background);
    +         add(healthIcon);
    +         add(moneyIcon);
    +         add(healthCounter);
    +         add(moneyCounter);
    +         forEach(function(sprite) sprite.scrollFactor.set(0, 0));
    +     }
    +
    +     public function updateHUD(health:Int, money:Int)
    +     {
    +         healthCounter.text = health + " / 3";
    +         moneyCounter.text = Std.string(money);
    +         moneyCounter.x = moneyIcon.x - moneyCounter.width - 4;
    +     }
    + }
    +
    +

    This class extends FlxTypedGroup<FlxSprite> so that it can hold all of our FlxSprite objects. It is composed of 5 different items: a background (black, with a 1-pixel thick white line along the bottom), 2 FlxText objects: 1 for health, and 1 for money, and two FlxSprite objects, for the icons to go next to the FlxText objects. At the end of our constructor, we have a forEach() call - we use this to iterate through each of the items in this group, and it just sets their scrollFactor.x and scrollFactor.y to 0, meaning, even if the camera scrolls, all of these items will stay at the same position relative to the screen.

    +

    Finally, we have a function that we can call from anywhere to tell the HUD what it should display.

    +
  2. +
  3. Now let's get it to work and have it update whenever we pick up a coin. In your PlayState, add this to the top of the class:

    +
     var hud:HUD;
    + var money:Int = 0;
    + var health:Int = 3;
    +
    +
  4. +
  5. In create(), before super.create(), add:

    +
     hud = new HUD();
    + add(hud);
    +
    +
  6. +
  7. Finally, in the playerTouchCoin() function we added earlier, somewhere inside the if-statement, add:

    +
     money++;
    + hud.updateHUD(health, money);
    +
    +
  8. +
+

Go ahead and test out your game, and the HUD should update each time you pick up a coin!

+

+

If we had a way to 'hurt' the player, we could also update the health on the HUD… but in order to do that, we need to figure out how we're going to do combat!

+

Let's begin by establishing what we want our combat system to achieve. First, we're not going to be making the next Final Fantasy game here, this is just a basic demonstration to show how a few different elements can work. So, I think all we want to do is have a simple interface that appears when the player touches an enemy that shows the player's health, and the enemy's health (in a health bar, for obfuscation), and gives the player 2 options: FIGHT or FLEE.

+

If they choose to fight, we'll roll some random chance checks to see if the player hits the enemy, and if the enemy hits the player - a hit will do 1 damage. Once the enemy dies, we'll continue on. If they choose to flee, we'll do a check to see if they do flee or not - if they do, the interface closes and the enemy will be stunned for a few seconds so the player can move away. If they fail to flee, the enemy will get a free hit against the player. We'll also show the damage and misses on the interface.

+

This all seems simple enough, but it's actually going to require several components working together to make it work. It's the most complicated piece of our game so far.

+
    +
  1. The first component will be our CombatHUD class. This is a pretty big class - it's going to do most of the heavy lifting with our combat logic. You can see the complete class here:

    +

    CombatHUD.hx

    +

    Take some time to read through it to see how it works, then add it to your project.

    +

    We already have most of the assets used by the CombatHUD, but there is one image file we still need - an arrow the player can use to select a choice. Download it from this link (or make your own), name it pointer.png and add it to the assets/images folder.

    +

    The CombatHUD also uses something we haven't discussed yet: sounds. We'll dig in to this more in the Sound and Music section. For now, just download these files and place them in the assets/sounds folder. This will ensure the code compiles.

    + +
  2. +
  3. Now, you will need to add a small function to our Enemy class:

    +
     public function changeType(type:EnemyType)
    + {
    +     if (this.type != type)
    +     {
    +         this.type = type;
    +         var graphic = if (type == BOSS) AssetPaths.boss__png else AssetPaths.enemy__png;
    +         loadGraphic(graphic, true, 16, 16);
    +     }
    + }
    +
    +
  4. +
  5. Next, we need to get our CombatHUD into our PlayState. Add this to the top of the PlayState class:

    +
     var inCombat:Bool = false;
    + var combatHud:CombatHUD;
    +
    +
  6. +
  7. Move down to create(), and, after we add the HUD, and before we call super.create(), add:

    +
     combatHud = new CombatHUD();
    + add(combatHud);
    +
    +
  8. +
  9. Go down to our update(), and change it so that we're ONLY checking for collisions and overlaps when we're not in combat. Everything after the super.update() should look like this:

    +
     if (inCombat)
    + {
    +     if (!combatHud.visible)
    +     {
    +         health = combatHud.playerHealth;
    +         hud.updateHUD(health, money);
    +         if (combatHud.outcome == VICTORY)
    +         {
    +             combatHud.enemy.kill();
    +         }
    +         else
    +         {
    +             combatHud.enemy.flicker();
    +         }
    +         inCombat = false;
    +         player.active = true;
    +         enemies.active = true;
    +     }
    + }
    + else
    + {
    +     FlxG.collide(player, walls);
    +     FlxG.overlap(player, coins, playerTouchCoin);
    +     FlxG.collide(enemies, walls);
    +     enemies.forEachAlive(checkEnemyVision);
    +     FlxG.overlap(player, enemies, playerTouchEnemy);
    + }
    +
    +

    So, we're adding a check to see if the player touches an enemy. If they do, we'll call a callback to see if we should start combat or not.

    +

    If we're in combat, we're simply going to keep checking to see if the combat HUD is still visible - once it becomes invisible, we know that combat has finished, and we can determine the outcome. If the outcome is VICTORY (one of our four enum values), we will kill the enemy, but if the player fled the battle, we will make the enemy flicker, to show that the player is safe from fighting it again for a short amount of time.

    +
  10. +
  11. You may have noticed that our Enemy class does not have a flicker() function. That's because we're going to use one found in the FlxSpriteUtil class. Haxe has a nice feature to help us do so. Add this line at the top of the PlayState file, just after your imports:

    +
     using flixel.util.FlxSpriteUtil;
    +
    +

    This will allow us to use the APIs in the FlxSpriteUtil class, such as flicker(), which can be used on any FlxObject. For more on how this works, take a look at the Haxe documentation.

    +
  12. +
  13. Next, let's add the functions to handle the player touching an enemy:

    +
     function playerTouchEnemy(player:Player, enemy:Enemy)
    + {
    +     if (player.alive && player.exists && enemy.alive && enemy.exists && !enemy.isFlickering())
    +     {
    +         startCombat(enemy);
    +     }
    + }
    +
    + function startCombat(enemy:Enemy)
    + {
    +     inCombat = true;
    +     player.active = false;
    +     enemies.active = false;
    +     combatHud.initCombat(health, enemy);
    + }
    +
    +

    All we're doing here is verify that both the player and the enemy are alive and exist, as well as that the enemy is not flickering (flickering enemies are those we've just fled from). If so, we start combat.

    +

    The startCombat() function simply sets our inCombat flag (so we know not to do collisions), and sets the player and all the enemies to inactive, so they no longer update.

    +

    Finally, we call initCombat() in our CombatHUD, which initializes it and makes it start working.

    +
  14. +
  15. Finally, we want enemies that are flickering to not move - they should act kind of stunned for a second after the enemy flees.

    +

    In the Enemy class, under update(), add:

    +
     if (this.isFlickering())
    +     return;
    +
    +

    At the very top, before doing anything else in that function.

    +

    Note that isFlickering() comes from FlxSpriteUtil. So, just like before, you will also need to add the using line at the top of the Enemy class file:

    +
     using flixel.util.FlxSpriteUtil;
    +
    +
  16. +
+

And that should do it! Test out your game and make sure that it works!

+

+

Next, we'll cover winning and losing and setting up all our different states.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/upgrade-guide-3-x/index.html b/documentation/upgrade-guide-3-x/index.html new file mode 100644 index 000000000..5eb3dc732 --- /dev/null +++ b/documentation/upgrade-guide-3-x/index.html @@ -0,0 +1,1102 @@ + + + + + + + + + + Upgrade Guide 3.x | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Upgrade Guide 3.x

+ + + Edit + +

3.3.0

+

The minimum Haxe version for this release is 3.1.0.

+

On flash, gamepad support has been added. For your project to work, you have to modify your Project.xml so that either:

+
    +
  • <set name="SWF_VERSION" value="11.8" /> is used (min. flash player version 11.8) or
  • +
  • <haxedef name="FLX_NO_GAMEPAD" if="flash" /> is used.
  • +
+

When compiling to HTML5, make sure to remove <haxelib name="openfl" /> from your Project.xml. This is already being handled in flixel's own include.xml.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.2.xHaxeFlixel 3.3.0
FlxTween.multiVar()FlxTween.tween()
FlxTween.singleVar()FlxTween.tween()
FlxTween.fader(0, 5);FlxTween.tween(FlxG.sound, {volume: 0}, 5);
FlxSound.surviveFlxSound.persist
MouseEventManager.addSprite()MouseEventManager.add()
FlxObject.forceComplexRender = true;FlxObject.pixelPerfectRender = false;
FlxText.widthFlxText.fieldWidth
FlxSprite.setOriginToCenter()FlxSprite.centerOrigin()
FlxG.safeDestroy()FlxDestroyUtil.destroy()
FlxTilemap.scaleXFlxTilemap.scale.x
FlxTilemap.scaleYFlxTilemap.scale.y
sprite.animation.addByIndicies()sprite.animation.addByIndices()
sprite.animation.addByStringIndicies()sprite.animation.addByStringIndices()
FlxTimer.userDataremoved
FlxTween.userDataremoved
FlxG.sound.add()FlxG.sound.cache()
+

There has also been a slight optimization for simple FlxSprites in FLX_RENDER_BLIT mode (flash and HTML5). This might require an additional dirty = true; for the change to show up if you manipulate the sprite's BitmapData directly.

+

FlxSprite flipping

+

Flipping sprite graphics now works differently - the flipped variable has been removed, as well as the Reverse parameter of loadGraphic() and loadGraphicFromTexture(). You can now directly manipulate the new flipX and flipY variables (flipping vertically is now possible).

+

If you want to continue to use facing to flip the graphic (e.g. in a platformer), you can use the following logic:

+
sprite.setFacingFlip(RIGHT, false, false);
+sprite.setFacingFlip(LEFT, true, false);
+
+

FlxTimer and FlxPath

+

FlxPath and FlxTimer were being pooled internally, which could lead to buggy behaviour in certain use cases. Due to that, pooling has been removed from these classes.

+ + + + + + + + + + + + + + + + + +
HaxeFlixel 3.2.xHaxeFlixel 3.3.0
start()new FlxTimer() / FlxPath()
run()start()
+

Also, the following API changes have been made for consistency:

+ + + + + + + + + + + + + + + + + +
HaxeFlixel 3.2.xHaxeFlixel 3.3.0
pausedactive
abort()cancel()
+

3.2.0

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.1.0HaxeFlixel 3.2.0
FlxTween.multiVar(object, vars, duration, { delay: 1});FlxTween.multiVar(object, vars, duration, { startDelay: 1});
FlxG.camera.followAdjust(4, 5);FlxG.cameras.followLead.set(4, 5);
FlxTilemap.arrayToCSV()FlxStringUtil.arrayToCSV()
FlxTilemap.bitmapToCSV()FlxStringUtil.bitmapToCSV()
FlxTilemap.imageToCSV()FlxStringUtil.imageToCSV()
FlxMath.computeVelocity()FlxVelocity.computeVelocity()
FlxState.setSubState()FlxState.openSubState()
+

3.1.0

+

HaxeFlixel 3.1 is a continuation of our efforts of making the API cleaner and more intuitive, keeping the amount of bugs as low as possible and adding new features. It is one of the biggest releases so far.

+

This page is a summary of all breaking changes - for a more in-depth list of changes, please refer to the changelog.

+

FlxTypedButton / FlxButton refactor

+

FlxTypedButton has been completely refactored, which includes the following breaking API changes:

+
    +
  • A new FlxButtonEvent class was added for the onDown, onUp, onOver and onOut events. Instead of the setCallback()-functions, you now set callbacks like this:

    +
      button.onDown.callback = someFunction;
    +

    This class also contains a sound property:

    +
      button.onDown.sound = FlxG.sound.load("pathToASound");
    +

    You might say: "What happened to custom callback arguments? The callback has the type Void->Void!" + While that's true, you can still use callback arguments by leveraging function binding:

    +
      button.onDown.callback = someFunction.bind(1);
    +

    In that example, someFunction is of type Int->Void and will always be called with 1.

    +
  • +
  • labelOffset:FlxPoint is now an array (labelOffsets:Array<FlxPoint>) which uses the button status constants as indices for more control over the button position.

    +
  • +
  • The highlight frame of the button spritesheet is now ignored by default on mobile devices, since it does not make much sense there - you can't hover over a button on a touchscreen.
  • +
  • It is now possible to "swipe-press" a button, which means you can press it if the input (mouse or touch) has been moved over the button and then released. Previously, you could only press a button if the press happened while you were already hovering over the button. This especially makes FlxVirtualPad more usable.
  • +
+

FlxG.keys and FlxG.keyboard

+

In 3.0.0, FlxG.keyboard has been introduced. However, we realized that this does not make for an intuitive API - you can't tell the difference between the two from their name alone. In fact, even if you have been using the two for a while, it still seems confusing.

+

This is why me merged the two classes again. This required removing the following functions:

+
    +
  • FlxG.keyboard.pressed()
  • +
  • FlxG.keyboard.justPressed()
  • +
  • FlxG.keyboard.justReleased()
  • +
+

You should use the following functions instead:

+
    +
  • FlxG.keys.anyPressed()
  • +
  • FlxG.keys.anyJustPressed()
  • +
  • FlxG.keys.anyJustReleased()
  • +
+

Please note that those functions take an Array<String> instead of a variable amount of Strings. So the following...

+
if (FlxG.keyboard.pressed("LEFT", "RIGHT")) {}
+
+

...becomes:

+
if (FlxG.keys.anyPressed(["LEFT", "RIGHT"])) {}
+
+

FlxMouse refactor

+

The following breaking changes were made during the refactor of FlxMouse:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.0.xHaxeFlixel 3.1.0
FlxG.mouse.show();FlxG.mouse.visible = true;
FlxG.mouse.load();
FlxG.mouse.hide();FlxG.mouse.visible = false;
FlxState.useMouseremoved
+

Also, the mouse cursor is now visible by default on non-mobile devices.

+

The middle and right click event listeners are now set up by default, which means FLX_MOUSE_ADVANCED has turned into FLX_NO_MOUSE_ADVANCED.

+

The recording system and FlxRandom

+

To put it bluntly... FlxRandom was a bit of a mess in 3.0. Some of the functions were deterministic, others weren't, which as a result made it very difficult to create deterministic games suitable for the recording system.

+

In 3.1.0, FlxRandom has been refactored to be completely deterministic. A new algorithm for pseudo-random-number-generation was implemented, which makes old replays incompatible / they will have unpredictable results.

+

Additionally, the following functions have been added to FlxRandom:

+
    +
  • weightedPick()
  • +
  • weightedGetObject()
  • +
  • colorExt()
  • +
+

FlxSprite renamings

+

A noteworthy amount of fields inside of FlxSprite have been renamed to increase the consistency with other parts of the API:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.0.xHaxeFlixel 3.1.0
loadfromSprite()loadGraphicFromSprite()
setGraphicDimensions()setGraphicSize()
bakedRotationbakedRotationAngle
pixelsOverlapPoint()overlapsPoint()
loadImageFromTexture()loadGraphicFromTexture()
loadRotatedImageFromTexture()loadRotatedGraphicFromTexture()
setColorTransformation()setColorTransform()
+

Scale Modes

+

HaxeFlixel 3.1.0 introduces scale modes to simplify targeting multiple resolutions. FlxG.scaleMode can be an instance of the following classes:

+
    +
  • RatioScaleMode (default!)
  • +
  • FillScaleMode
  • +
  • FixedScaleMode
  • +
  • RelativeScaleMode
  • +
  • StageSizeScaleMode
  • +
+

This change made FlxG.autoResize obsolete and it has thus been removed.

+

You can also write a custom scale mode that extends BaseScaleMode.

+

Be sure to check out the ScaleModes demo.

+

FlxTypedGroup.sort()

+

The way FlxTypedGroup.sort() has been changed for a significant performance improvement. If you want to sort by y, you now have to use the following syntax:

+
group.sort(FlxSort.byY, FlxSort.ASCENDING);
+
+

Instead of:

+
group.sort("y", FlxSort.ASCENDING);
+// or
+group.sort();
+
+

If you want to sort by anything other than y, you'll have to write a custom sorting function, as can be seen in this example:

+
function sortByAlpha(Order:Int, Sprite1:FlxSprite, Sprite2:FlxSprite):Int
+{
+    return FlxSort.byValues(Order, Sprite1.alpha, Sprite2.alpha);
+}
+
+// usage on a FlxTypedGroup<FlxSprite>:
+group.sort(sortByAlpha);
+
+

Other breaking changes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.0HaxeFlixel 3.1
FlxTypedGroup.autoReviveMembersremoved
FlxG.gameFramerateFlxG.updateFramerate
FlxG.flashFramerateFlxG.drawFramerate
FlxG.gamepads.get()FlxG.gamepads.getByID()
FlxG.debugger.visualDebugFlxG.debugger.drawDebug
FlxG.pausedremoved (didn't have any functionality)
FlxArrayUtil.intToString()FlxStringUtil.toIntArray()
FlxArrayUtil.floatToString()FlxStringUtil.toFloatArray()
FlxMisc.openURL()FlxG.openURL()
FlxMiscremoved
FlxSoundUtilremoved (use a FlxTimer instead)
+

The classes from flixel.system.input have been moved to flixel.input.

+

FlxPoints in FlxObject and FlxSprite are now read-only / (default, null), which means you need to use .set() on them if you were previously creating new points. The following...

+
sprite.velocity = new FlxPoint(100, 50);
+
+

...becomes:

+
sprite.velocity.set(100, 50);
+
+

3.0.0

+

HaxeFlixel 3.0 is an evolution of the original Flixel API and while most of the API is very similar and quickly learnt, it requires some renames and modifications to update your code.

+

Major changes from version 2.10

+

We wanted to slim down up the core classes, which meant moving non-essential functionality into separate classes. We've also continued to focus on improving stability and adding features to the engine. Here's a quick overview of the biggest changes:

+ +
mySprite.animation.add(...);
+
+mySprite.animation.play(...);
+
+mySprite.animation.frameName = "String";
+
+mySprite.animation.frameIndex = Int;
+
+//inspect the advanced api features such as
+addByNames, addByStringIndicies, addByIndicies, addByPrefix, findSpriteFrame, randomFrame ...
+
+
    +
  • Added new FlxKeyShortcuts class, which replaces FlxG.keys. FlxG.keys.pressed is no longer a function, it's now an object, ex: if( FlxG.keys.pressed.ANY ) {...}

    +
  • +
  • Added new FlxSpriteGroup class, which allows an FlxGroup to behave like an FlxSprite. This is a powerful new construct that will simplify building UI controls.

    +
  • +
  • FlxU is now gone, we've moved all its functionality to several utility classes that specific contain functionality, ex: FlxArrayUtil, FlxAngle, FlxMath, FlxRandom, FlxSpriteUtil, FlxVelocity, etc.

    +
  • +
  • FlxSprite Filters are now in a separate FlxSpriteFilter utility class.

    +
  • +
+

Package Structure

+

HaxeFlixel no longer has an org package. Everything is now included as flixel.package.Class. For most cases you can just remove org. from your import statements.

+

This was a decision the core developers agreed upon, to make the package structure simpler and detach HaxeFlixel from old flash conventions.

+

FrontEnds and the FlxG refactor

+

Frontends in HaxeFlixel 3.x are a new structure to the core of Flixel and which tackles the often criticized bloated collection of static methods in FlxG.

+

Frontends are accessed in FlxG.frontend in a similar fashion to what Flixel devs are used to. Careful thought has been given to organise them into logical shortcuts. This way the api will be easier browse, remember and maintain.

+

For example in HaxeFlixel 2.x to add a FlxCamera you would use FlxG.addCamera(camera:FlxCamera);, this addCamera method has been moved into a camera frontend with all the other camera related shortcuts. +So the code in HaxeFlixel 3.x to add a FlxCamera is now FlxG.cameras.add(camera:FlxCamera).

+

The Flixel FrontEnds are as follows:

+
    +
  • FlxG.inputs
  • +
  • FlxG.console
  • +
  • FlxG.log
  • +
  • FlxG.bmpLog
  • +
  • FlxG.watch
  • +
  • FlxG.debugger
  • +
  • FlxG.vcr
  • +
  • FlxG.bitmap
  • +
  • FlxG.cameras
  • +
  • FlxG.plugins
  • +
  • FlxG.sound
  • +
+

More detail on the FrontEnds can be read on the FrontEnd docs page.

+

Core Assets

+

HaxeFlixel has system Assets for its debugger buttons, system sounds, etc. These assets were previously stored in every project in the assets/data folder. HaxeFlixel 3.x uses the OpenFL include.xml in core HaxeFlixel to omit the need to include them in every project.

+

So you do not need to have system assets anymore, everything in your project's ./assets/* folder should only be the assets you create.

+

New Debugger and Interactive Console

+

HaxeFlixel 3.x includes a powerful console and improved debugger. The new debugger system by default redirects the core trace() command to the log. Alternatively you can use FlxG.log.add() , FlxG.watch.add(), FlxG.log.warn and more.

+

New Flixel Command Line Tools

+

Our command line tools have been moved to an optional repository, so the old haxelib run flixel new command will not work. +Install the tools from haxelib just like flixel and run setup and follow the prompts:

+
haxelib install flixel-tools
+
+haxelib run flixel-tools setup
+

Now you can use the commands with just flixel, try the help command for more info.

+
flixel help
+
+//see the new template tool options with:
+flixel help template
+
+//Shorthand version to create a template with a custom name
+flixel tpl -n "CustomProject"
+

Automatic find and replace

+

A collection of most of the API name changes were collected for the flixel-tools command line tool. +You can see what it replaces here.

+

To run the find and replace the command is simple:

+
flixel convert
+

FlxG Changes

+

The main changes that developers will notice are as follows:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 2.xHaxeFlixel 3.x
FlxG.getLibraryName()FlxG.libraryName
FlxG.setDebuggerLayoutFlxG.debugger.setLayout
FlxG.logtrace()
FlxG.resetDebuggerLayoutFlxG.debugger.resetLayout
FlxG.visualDebugFlxG.debugger.visualDebug
FlxG.toggleKeysFlxG.debugger.toggleKeys
FlxG.DEBUGGER_STANDARDFlxDebugger.STANDARD
FlxG.DEBUGGER_MICROFlxDebugger.MICRO
FlxG.DEBUGGER_BIGFlxDebugger.BIG
FlxG.DEBUGGER_TOPFlxDebugger.TOP
FlxG.DEBUGGER_LEFTFlxDebugger.LEFT
FlxG.DEBUGGER_RIGHTFlxDebugger.RIGHT
FlxG.randomFlxRandom.float
FlxG.shuffleFlxArrayUtil.shuffle
FlxG.getRandomFlxArrayUtil.getRandom
FlxG.globalSeedFlxRandom.globalSeed
FlxG.tweenFlxTween.multiVar
FlxG.resetInputFlxG.inputs.reset
FlxG.REDFlxColor.RED
FlxG.GREENFlxColor.GREEN
FlxG.BLUEFlxColor.BLUE
FlxG.PINKFlxColor.PINK
FlxG.WHITEFlxColor.WHITE
FlxG.BLACKFlxColor.BLACK
FlxG.TRANSPARENTFlxColor.TRANSPARENT
FlxG.DEGFlxAngle.TO_DEG
FlxG.RADFlxAngle.TO_RAD
FlxG.flashGfxFlxSpriteUtil.flashGfx
FlxG.flashGfxSpriteFlxSpriteUtil.flashGfxSprite
FlxG.levelsReg.levels
FlxG.scoresReg.scores
FlxG.scoreReg.score
FlxG.savesReg.saves
FlxG.saveReg.save
FlxG.addCameraFlxG.cameras.add
FlxG.useBufferLockingFlxG.cameras.useBufferLocking
FlxG.lockCamerasFlxG.cameras.lock
FlxG.renderCamerasFlxG.cameras.render
FlxG.unlockCamerasFlxG.cameras.unlock
FlxG.removeCameraFlxG.cameras.remove
FlxG.resetCamerasFlxG.cameras.reset
FlxG.shakeFlxG.cameras.shake
FlxG.bgColorFlxG.cameras.bgColor
FlxG.warnFlxG.log.warn
FlxG.errorFlxG.log.error
FlxG.noticeFlxG.log.notice
FlxG.advancedLogFlxG.log.advanced
FlxG.clearLogFlxG.log.clear
FlxG.watchFlxG.watch.add
FlxG.unwatchFlxG.watch.remove
FlxG.playFlxG.sound.play
FlxG.playMusicFlxG.sound.playMusic
FlxG.loadSoundFlxG.sound.load
FlxG.addSoundFlxG.sound.add
FlxG.streamFlxG.sound.stream
FlxG.destroySoundsFlxG.sound.destroySounds
FlxG.updateSoundsFlxG.sound.updateSounds
FlxG.pauseSoundsFlxG.sound.pauseSounds
FlxG.resumeSoundsFlxG.sound.resumeSounds
FlxG.musicFlxG.sound.music
FlxG.soundsFlxG.sound.list
FlxG.muteFlxG.sound.muted
FlxG.volumeFlxG.sound.volume
FlxG.volumeHandlerFlxG.sound.volumeHandler
FlxG.keyVolumeUpFlxG.sound.keyVolumeUp
FlxG.keyVolumeDownFlxG.sound.keyVolumeDown
FlxG.keyMuteFlxG.sound.keyMute
FlxG.addPluginFlxG.plugins.add
FlxG.getPluginFlxG.plugins.get
FlxG.removePluginFlxG.plugins.remove
FlxG.removePluginTypeFlxG.plugins.removeType
FlxG.updatePluginsFlxG.plugins.update
FlxG.drawPluginsFlxG.plugins.draw
FlxG.pluginsFlxG.plugins.list
FlxG.loadReplayFlxG.vcr.loadReplay
FlxG.reloadReplayFlxG.vcr.reloadReplay
FlxG.stopReplayFlxG.vcr.stopReplay
FlxG.recordReplayFlxG.vcr.startRecording
FlxG.stopRecordingFlxG.vcr.stopRecording
FlxG.checkBitmapCacheFlxG.bitmap.checkCache
FlxG.createBitmapFlxG.bitmap.create
FlxG.addBitmapFlxG.bitmap.add
FlxG.removeBitmapFlxG.bitmap.remove
FlxG.getCacheKeyForFlxG.bitmap.getCacheKeyFor
FlxG.getUniqueBitmapKeyFlxG.bitmap.getUniqueKey
FlxG.clearBitmapCacheFlxG.bitmap.clearCache
FlxG.clearAssetsCacheFlxG.bitmap.clearAssetsCache
+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/upgrade-guide-4-0-0/index.html b/documentation/upgrade-guide-4-0-0/index.html new file mode 100644 index 000000000..ef01ecc81 --- /dev/null +++ b/documentation/upgrade-guide-4-0-0/index.html @@ -0,0 +1,1041 @@ + + + + + + + + + + Upgrade Guide 4.0.0 | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Upgrade Guide 4.0.0

+ + + Edit + +

4.4.0

+

Breaking changes in 4.4.0 are limited to usage with OpenFL 8. OpenFL 3.6.1 (Legacy or Next) is still fully supported. The breaking changes when upgrading to OpenFL 8.0.0 and Lime 6.3.0 are as follows:

+
    +
  • There is no support for blend modes (FlxSprite.blend). This is because drawQuads() (the rendering API replacing drawTiles() in OpenFL 8), doesn't support them. In some cases, blend modes may be emulated using shaders. An example of this can be seen in our BlendModeShaders demo.
  • +
  • Like already the case in OpenFL 3.6.1 + Next, the flixel.effects.postprocess API is not supported in OpenFL 8. As a replacement, a shader filter can be applied to the FlxGame instance or a FlxCamera as shown in the Filters demo.
  • +
  • OpenFL 3.6.1 with -Dnext had support for per-sprite, per-camera or game-wide GLSL shaders. All of these are still fully supported, but the syntax has changed a bit.
  • +
+

Here's a simple example of a shader found in FlxBunnyMark:

+

With OpenFL 3.6.1 + Next:

+
import openfl.display.Shader;
+
+class Invert extends Shader
+{
+    @fragment var fragment = '
+        void main()
+        {
+            vec4 color = texture2D(${Shader.uSampler}, ${Shader.vTexCoord});
+            gl_FragColor = vec4((1.0 - color.r) * color.a, (1.0 - color.g) * color.a, (1.0 - color.b) * color.a, color.a);
+        }';
+
+    public function new()
+    {
+        super();
+    }
+}
+
+

With OpenFL 8:

+
import flixel.system.FlxAssets.FlxShader;
+
+class Invert extends FlxShader
+{
+    @:glFragmentSource('
+        #pragma header
+
+        void main()
+        {
+            vec4 color = flixel_texture2D(bitmap, openfl_TextureCoordv);
+            gl_FragColor = vec4((1.0 - color.r) * color.a, (1.0 - color.g) * color.a, (1.0 - color.b) * color.a,   color.a);
+        }'
+    )
+
+    public function new()
+    {
+        super();
+    }
+}
+
+

To summarize the differences, shaders should...

+
    +
  • extend flixel.system.FlxAssets.FlxShader instead of openfl.display.Shader
  • +
  • use @:glFragmentSource() metadata for the shader source rather than a @fragment var
  • +
  • have #pragma header before main()
  • +
+

Attributes have changed as follows:

+ + + + + + + + + + + + + + + + + + + + + +
With OpenFL 3.6.1 + NextWith OpenFL 8
${Shader.uSampler}bitmap
${Shader.vTexCoord}openfl_TextureCoordv
${Shader.uTextureSize}openfl_TextureSize
+

You may also have noticed that in the invert shader example, texture2D() has been replaced with flixel_texture2D(). The former still works, but when using flixel_texture2D() in per-sprite shaders, the alpha and color transforms of a FlxSprite are already applied on the returned color, which was previously not supported. The effect of this can be seen when activating shaders as well as toggling "Simple" to "Complex" in FlxBunnyMark:

+ + + + + + + + + + + + + +
With OpenFL 3.6.1 + NextWith OpenFL 8
+

Further shader examples can be found in these demos, which are all compatible with both OpenFL 3.6.1 + Next and OpenFL 8:

+ +

4.2.0

+
    +
  • FlxTween.manager is now FlxTween.globalManager.
  • +
  • FlxTimer.manager is now FlxTimer.globalManager.
  • +
  • FlxCamera's scroll bounds now account for zoom. This means that you may need to adjust calls to setScrollBounds(), setScrollBoundsRect() or changes to the minScrollX / Y / maxScrollX / Y properties if they manually accounted for zoom.
  • +
  • The active variable of objects in flixel.util.helpers now defaults to true instead of false.
  • +
+

4.0.0

+

This guide is intended for users upgrading projects from version 3.3.x to 4.0.0. For non-breaking changes, please refer to the changelog.

+

The minimum required Haxe version for this release is 3.2.0.

+

A lot of changes can be handled with a simple find-and-replace in the editor of your choice.

+

elapsed argument added to update()

+

The function signature of update() changed to update(elapsed:Float). FlxG.elapsed is still available, but it is recommended to use the argument value instead.

+ + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
override public function update():Voidoverride public function update(elapsed:Float):Void
super.update();super.update(elapsed);
x += 100 * FlxG.elapsed;x += 100 * elapsed;
+

Introduction of flixel.math

+

A new flixel.math package was added. A number of flixel.util classes have been moved there:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
import flixel.util.FlxMathimport flixel.math.FlxMath
import flixel.util.FlxPointimport flixel.math.FlxPoint
import flixel.util.FlxVectorimport flixel.math.FlxVector
import flixel.util.FlxRectimport flixel.math.FlxRect
import flixel.util.FlxAngleimport flixel.math.FlxAngle
import flixel.util.FlxVelocityimport flixel.math.FlxVelocity
import flixel.util.FlxRandomimport flixel.math.FlxRandom
+

Move of "typed" classes:

+

Typed classes have been moved into the modules of the non-typed versions:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
import flixel.group.FlxTypedGroupimport flixel.group.FlxGroup
import flixel.group.FlxTypedSpriteGroupimport flixel.group.FlxSpriteGroup
import flixel.effects.particles.FlxTypedEmitterimport flixel.effects.particles.FlxEmitter
import flixel.ui.FlxTypedButtonimport flixel.ui.FlxButton
+

Changed integer constants to enums:

+

ActionScript 3 does not have enums, which is why a lot of these "value sets" were implemented using integer constants. For improved type-safety and to better fit the Haxe coding style, they have been converted to enums:

+

As long as it's not ambiguous, Haxe allows using just the enum value name without the enum's name. In the first case, the enum also does not need to be imported. For example, this means that both of these syntaxes are valid:

+
FlxG.camera.follow(LOCKON);
+FlxG.camera.follow(FlxCameraFollowStyle.LOCKON);
+
+

Which of these two styles is used is mostly a matter of personal preference.

+

FlxCamera shake modes:

+ + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
FlxCamera.SHAKE_BOTH_AXESflixel.util.FlxAxes.XY
FlxCamera.SHAKE_HORIZONTAL_ONLYflixel.util.FlxAxes.X
FlxCamera.SHAKE_VERTICAL_ONLYflixel.util.FlxAxes.Y
+

FlxCamera follow styles:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
FlxCamera.STYLE_LOCKONFlxCameraFollowStyle.LOCKON
FlxCamera.STYLE_NO_DEAD_ZONEFlxCameraFollowStyle.NO_DEAD_ZONE
FlxCamera.STYLE_PLATFORMERFlxCameraFollowStyle.PLATFORMER
FlxCamera.STYLE_SCREEN_BY_SCREENFlxCameraFollowStyle.SCREEN_BY_SCREEN
FlxCamera.STYLE_TOPDOWNFlxCameraFollowStyle.TOPDOWN
FlxCamera.STYLE_TOPDOWN_TIGHTFlxCameraFollowStyle.TOPDOWN_TIGHT
+

FlxText border styles:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
FlxText.BORDER_NONEFlxTextBorderStyle.NONE
FlxText.BORDER_OUTLINEFlxTextBorderStyle.OUTLINE
FlxText.BORDER_OUTLINE_FASTFlxTextBorderStyle.OUTLINE_FAST
FlxText.BORDER_SHADOWFlxTextBorderStyle.SHADOW
+

FlxTilemap auto-tiling options:

+ + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
FlxTilemap.ALTFlxTilemapAutoTiling.ALT
FlxTilemap.AUTOFlxTilemapAutoTiling.AUTO
FlxTilemap.OFFFlxTilemapAutoTiling.OFF
+

FlxBar fill directions:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
FlxBar.FILL_BOTTOM_TO_TOPFlxBarFillDirection.BOTTOM_TO_TOP
FlxBar.FILL_HORIZONTAL_INSIDE_OUTFlxBarFillDirection.HORIZONTAL_INSIDE_OUT
FlxBar.FILL_HORIZONTAL_OUTSIDE_INFlxBarFillDirection.HORIZONTAL_OUTSIDE_IN
FlxBar.FILL_LEFT_TO_RIGHTFlxBarFillDirection.LEFT_TO_RIGHT
FlxBar.FILL_RIGHT_TO_LEFTFlxBarFillDirection.RIGHT_TO_LEFT
FlxBar.FILL_TOP_TO_BOTTOMFlxBarFillDirection.TOP_TO_BOTTOM
FlxBar.FILL_VERTICAL_INSIDE_OUTFlxBarFillDirection.VERTICAL_INSIDE_OUT
FlxBar.FILL_VERTICAL_OUTSIDE_INFlxBarFillDirection.VERTICAL_OUTSIDE_IN
+

FlxG.html5 browser types:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
HTML5FrontEnd.INTERNET_EXPLORERFlxBrowser.INTERNET_EXPLORER
HTML5FrontEnd.CHROMEFlxBrowser.CHROME
HTML5FrontEnd.FIREFOXFlxBrowser.FIREFOX
HTML5FrontEnd.SAFARIFlxBrowser.SAFARI
HTML5FrontEnd.OPERAFlxBrowser.OPERA
+

Changed String constants to abstract enums:

+

Some static String constants have been changed to abstract enums. This is not a breaking changes, since the old String values are still compatible, but for the sake of type safety it is recommended to use the enum values instead:

+

As with regular enums, the enum name may be omitted.

+

FlxText alignment:

+ + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
text.alignment = "left";text.alignment = FlxTextAlign.LEFT;
text.alignment = "center";text.alignment = FlxTextAlign.CENTER;
text.alignment = "right";text.alignment = FlxTextAlign.RIGHT;
+

FlxG.keys keys:

+ + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
FlxG.keys.anyPressed(["SPACE", "W"])FlxG.keys.anyPressed([FlxKey.SPACE, FlxKey.W])
FlxG.keys.anyPressed(["SPACE", "W"])FlxG.keys.anyPressed([SPACE, W])
+

FlxSprite:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
getScreenXY()getScreenPosition()
cachedGraphicsgraphic
resetFrameBitmaps()removed (set dirty to true to regen graphic)
getFlxFrameBitmapData()updateFramePixels()
loadGraphicFromTexture()removed (assign a frames collection to frames)
loadRotatedGraphicFromTexture()removed (assign a frames collection to frames)
+

FlxCamera:

+ + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
boundsminScrollX, minScrollY, maxScrollX and maxScrollY
setBounds()setScrollBoundsRect()
follow()'s Offset argumentremoved
+

FlxTilemap:

+

loadMap() has been split up into loadMapFromArray() and loadMapFromCSV().

+

FlxGroup:

+

callAll() and setAll() have been removed - use forEach() instead:

+
// 3.3.x
+group.setAll("scrollFactor", FlxPoint.get(0, 0));
+group.callAll("kill");
+
+
// 4.0.0
+group.forEach(function(basic:FlxBasic)
+{
+    basic.scrollFactor.set(0, 0);
+    basic.kill();
+});
+
+

flixel.input.gamepad:

+

The hardware IDs of the different controller types are now mapped to a common FlxGamepadInputID. This avoids the need of having to handle multiple controller types - this now happens automatically under the hood.

+
// 3.3.x
+if (gamepad.pressed(XboxButtonID.A) ||
+    gamepad.pressed(OUYAButtonID.O) ||
+    gamepad.pressed(LogitechButtonID.TWO)) {} 
+
+
// 4.0.0
+if (gamepad.anyPressed([FlxGamepadInputID.A])) {}
+// or
+if (gamepad.pressed.A) {}
+
+

It is still possible to use the IDs from the flixel.input.gamepad.id classes via the functions with the Raw suffix.

+

Because of the poor driver support, the PS3 ID class / support for PS3 controllers have been removed.

+

FlxTimer:

+

Timers cannot be started right at construction anymore, instead you need to call start():

+
// 3.3.x
+new FlxTimer(time, onComplete, loops);
+
+
// 4.0.0
+new FlxTimer().start(time, onComplete, loops);
+
+

FlxPath:

+

FlxPath#start() no longer takes a FlxObject argument, instead, FlxObject now has a path property. This means FlxObject takes care of updating the path, taking care of the issue that paths are not paused along with the objects they work on in substates.

+
// 3.3.x
+var path = new FlxPath().start(object, points);
+
+
// 4.0.0
+object.path = new FlxPath().start(points);
+
+

FlxColor / FlxColorUtil refactor:

+

FlxColor is now an abstract, which means it can be used like an object, while the underlying type is still a regular Int. The static FlxColorUtil functions can now be used as member methods or properties:

+
// 3.3.x
+var color:Int = 0x008080;
+trace(FlxColorUtil.getGreen(color));
+
+
// 4.0.0
+var color:FlxColor = 0x008080;
+trace(color.green);
+
+

The amount of colors presets (FlxColor.RED etc..) has been reduced.

+

FlxEmitter refactor:

+

FlxEmitterExt has been merged into FlxEmitter. For circular emitters, FlxEmitterMode.CIRCLE can be used.

+

Most properties are now FlxRangeBounds objects which have a min and a max FlxRange object.

+

The separate color component Bounds have been merged into a FlxRangeBounds<FlxColor>.

+ + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
at()focusOn()
onemitting
+

FlxParticle changes:

+

Most properties are now FlxRange objects which have a start and an end value (for example velocityRange).

+ + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
maxLifespanlifespan
lifespanage (counts up instead of down)
+

FlxRandom refactor:

+

FlxRandom can now be instantiated and the static functions are now member methods. A pre-created instance is available via FlxG.random.

+

Some methods have also been renamed or removed:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
FlxRandom.intRanged(min, max)FlxG.random.int(min, max)
FlxRandom.floatRanged(min, max)FlxG.random.float(min, max)
FlxRandom.chanceRoll(chance)FlxG.random.bool(chance)
FlxRandom.weightedGetObject()removed (getObject() now has a range argument)
FlxRandom.colorExt()removed
+

FlxAngle changes:

+ + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
FlxAngle.getAngle(point1, point2)point1.angleBetween(point2)
FlxAngle.angleLimit()removed (use FlxMath.bound() instead)
+

There have been several changes to FlxAngle.rotatePoint():

+
    +
  • the y-axis is no longer inverted
  • +
  • rotation is now clockwise
  • +
  • moved to FlxPoint (rotate())
  • +
+
// 3.3.x
+var angle = 45;
+var point = FlxPoint.get(10, 5);
+FlxAngle.rotatePoint(x, y, pivotX, pivotY, angle, point);
+
+
// 4.0.0
+var angle = 45;
+var point = FlxPoint.get(10 + x, 5 + y);
+var pivot = FlxPoint.weak(pivotX, pivotY);
+point.rotate(pivot, angle);
+
+

FlxMath changes:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
newAmount = FlxMath.wrapValue(value, amount, max + 1)newAmount = FlxMath.wrapValue(value + amount, min, max)
FlxMath.getDistance(point1, point2)point1.distanceTo(point2)
FlxMath.MIN_VALUEFlxMath.MIN_VALUE_FLOAT
FlxMath.MAX_VALUEFlxMath.MAX_VALUE_FLOAT
+

Other:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HaxeFlixel 3.3.xHaxeFlixel 4.0.0
import flixel.text.FlxTextFieldimport flixel.addons.text.FlxTextField
FlxPoint#inFlxRect()FlxPoint#inRect()
FlxRect#containsFlxPoint()FlxRect#containsPoint()
flixel.plugin.MouseEventManagerflixel.input.mouse.FlxMouseEventManager
flixel.util.loaders.CachedGraphicsflixel.graphics.FlxGraphic
FlxArrayUtil.getRandom()FlxG.random.getObject()
+

FlxVelocity's accelerateTowards*()-functions now only take a single maxSpeed argument (instead of x and y).

+

The complete option of FlxTween is now called onComplete.

+

flixel-addons

+

Not all flixel-addons changes are covered here. Please check the changelog for the rest.

+

FlxNapeState refactor:

+

FlxNapeState is now FlxNapeSpace and no longer extends FlxState. This makes it possible to use the flixel.addons.nape package along with other FlxState subclasses (for example FlxUIState).

+
// flixel-addons 1.x.x
+import flixel.addons.nape.FlxNapeState;
+
+class PlayState extends FlxNapeState
+{
+    override public function create():Void
+    {
+        super.create();
+    }
+}
+
+
// flixel-addons 2.0.0
+import flixel.FlxState;
+import flixel.addons.nape.FlxNapeSpace;
+
+class PlayState extends FlxState
+{
+    override public function create():Void
+    {
+        super.create();
+        FlxNapeSpace.init();
+    }
+}
+
+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/using-haxelib/index.html b/documentation/using-haxelib/index.html new file mode 100644 index 000000000..f70cd08a6 --- /dev/null +++ b/documentation/using-haxelib/index.html @@ -0,0 +1,285 @@ + + + + + + + + + + Using Haxelib | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Using Haxelib

+ + + Edit + +

Haxelib is a package manager and utility that comes with your Haxe install. Here are the most used commands, the full usage docs are available here.

+

Installing a Library

+

Install a Haxelib library from lib.haxe.org:

+
haxelib install <library>
+

Install a Haxelib library from Git:

+
haxelib git <library> <url> <branch>
+

Note: haxelib git enables the development directory for that library, which silently prevents haxelib set from working. Use haxelib dev <library> to disable it.

+

Update your Haxelib libraries, including the ones from Git:

+
haxelib upgrade
+

Change to different version of a library:

+
haxelib set <library> <version>
+

Remove a library:

+
haxelib remove <library>
+

Using An Installed Library

+

To use a library in your HaxeFlixel project, add it to your project.xml:

+
<haxelib name="<library>" />
+
+

Updating Haxelib itself

+

To make sure you are using the latest version of Haxelib you can run the selfupdate command.

+
haxelib selfupdate
+
+ +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/visual-studio-code/index.html b/documentation/visual-studio-code/index.html new file mode 100644 index 000000000..56482de40 --- /dev/null +++ b/documentation/visual-studio-code/index.html @@ -0,0 +1,322 @@ + + + + + + + + + + Visual Studio Code | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Visual Studio Code

+ + + Edit + +

+

Visual Studio Code is an open-source, cross-platform, lightweight code editor by Microsoft. The Haxe extension seamlessly integrates with the compiler's IDE services and uses them for:

+
    +
  • Code Completion
  • +
  • Go to Definition
  • +
  • Go to Symbol
  • +
  • Find Usages
  • +
  • Finding Unused Imports
  • +
  • etc...
  • +
+

You can find detailed documentation for the Haxe extension in the Wiki, this page focuses on the Flixel-specific parts.

+

Installation

+
    +
  • Download and install the latest version of Visual Studio Code.
  • +
  • Go to the Extensions tab and install the Lime extension. This automatically installs the Haxe extension as well.

    +

    +
  • +
+

Project Configuration

+

VSCode stores its project-specific settings in a .vscode subfolder - flixel-tools can create one with sensible defaults for Flixel projects. Just select VSCode as your preferred editor during the setup command, or add -ide vscode to the command you're running.

+

Note: make sure you have the latest versions of flixel-tools and flixel-templates:

+
haxelib update flixel-tools
+haxelib update flixel-templates
+

You have several options for creating projects with a .vscode configuration:

+
    +
  1. Create a new, empty project:

    +
     flixel template -n "VSCodeTest" -ide vscode
    +
  2. +
  3. Create a new project based on one of the demos:

    +
     flixel create -ide vscode
    +
  4. +
  5. Add the .vscode folder to a project that already exists, for instance the current working directory:

    +
     flixel configure . -ide vscode
    +
  6. +
  7. Add VSCode config files to an entire directory of projects, like flixel-demos:

    +
     flixel configure C:\HaxeToolkit\haxe\lib\flixel-demos\git -ide vscode
    +
  8. +
+

Code Completion

+

Once you've installed the Lime extension and have a project with a .vscode folder, just open it with File -> Open Folder. If the workspace was correctly detected as a Lime project (needs a Project.xml file), you should notice these dropdown menus appearing in the status bar:

+

+

Code completion features should work out of the box now:

+

+

If you're having trouble, please refer to the Haxe extension's Troubleshooting guide.

+

Building

+

Building and running your projects in VSCode is done through tasks. You can view the list of available tasks via Tasks -> Run Task...:

+

+

To build and run your project, select the lime: test task. With Flixel's template, this is configured as the default build task, so you can also invoke it directly via Tasks -> Run Build Task... or by pressing Ctrl+Shift+B:

+

+

You may want to assign a shortcut to Run Task... or change the shortcut for Run Build Task... to something more convenient such as F5. You can do so in File -> Preferences -> Keyboard Shortcuts.

+

Finally, you can change the current configuration (combination of target and Debug/Release/Final) by using the dropdown menu in the status bar:

+

+

Compiler Errors / Problems View

+

By default, compiler errors and warnings are shown in the Terminal view at the bottom of the screen. You can navigate to the source of the error via Ctrl+Click on the file path:

+

+

Alternatively, you can switch to the Problems tab which has a nicer presentation. It shows errors / warnings from compilation as well as diagnostics that are updated each time you save a file:

+

+

Debugging

+

The .vscode template from flixel-tools already includes the launch.json needed for debugging. The Lime "Build + Debug" / "Debug" launch configurations support debugging with the following targets / extensions:

+ +

Simply "Start Debugging" with the "Build + Debug" launch configuration (make sure the "Debug" configuration for the target you want to debug is selected in the status bar). This first builds the project and then starts the debugger.

+

+

Here's what it should look like when you hit a breakpoint:

+

+

There is also a Macro launch configuration for debugging Haxe Macros.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/website-docs/index.html b/documentation/website-docs/index.html new file mode 100644 index 000000000..71a62d4c8 --- /dev/null +++ b/documentation/website-docs/index.html @@ -0,0 +1,298 @@ + + + + + + + + + + HaxeFlixel Website | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

HaxeFlixel Website

+ + + Edit + +

This website is built using the Docpad system which compiles the files to a static site on a community sponsored host. +Extensions and help with improving the website and our documentation are greatly appreciated.

+

Our Documentation

+

These documentation pages are an open-source project for the community to improve and extend. Notice the Edit button in the top right hand corner of every page. +This will link you right to the GitHub page of the documentation where you can fork and edit the pages right in the GitHub editor. +Anyone of the HaxeFlixel team can merge pull requests and changes will be uploaded to our host.

+

Everything is written in the GitHub flavoured markdown format. You can see the files written in markdown from the extension *.html.md.

+

The markdown format is parsed through marked with the GitHub markdown syntax enabled. +You can see a guide for the markdown syntax here.

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/where-to-now/index.html b/documentation/where-to-now/index.html new file mode 100644 index 000000000..251c17d56 --- /dev/null +++ b/documentation/where-to-now/index.html @@ -0,0 +1,258 @@ + + + + + + + + + + Where to now? | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+ +
+

Where to now?

+ + + Edit + +

If you have successfully compiled a Hello World sample, there are multiple places to jump to from here:

+
    +
  • Follow our step-by-step tutorial to learn how to make a simple turn based RPG.
  • +
  • Check out our large collection of demos to learn by example. Try improving a game and pulling one apart to see how it works!
  • +
  • Read about different aspects of Flixel in our handbook.
  • +
  • Browse our API documentation.
  • +
+

Also be sure to get in touch with the community if you have any questions along the way!

+

Furthermore, this documentation and website are open source and we welcome additions from users like you. :)

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/why-haxe/index.html b/documentation/why-haxe/index.html new file mode 100644 index 000000000..a63a77d94 --- /dev/null +++ b/documentation/why-haxe/index.html @@ -0,0 +1,304 @@ + + + + + + + + + + Why a Haxe Version | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

Why a Haxe Version

+ + + Edit + +

The original ActionScript 3 version of Flixel has proven to be an effective codebase to make 2D games quickly and easily for the Adobe Flash and AIR runtimes. Haxe and the Open Flash Library provide significant enhancements and opportunities that ActionScript 3, AIR and Flash are limited by. Haxe and the OpenFL offers more efficient and open source native runtimes to your code base that ActionScript 3 and Adobe Flash/Air are not able to provide. HaxeFlixel still retains the same Flash Player target, but you gain a familiar, yet superior open source language Haxe.

+

Use of a superior open source, cross-compiled language

+

Haxe as a toolkit and language provides features today that ActionScript developers have been seeking for years (ActionScript 4, cancelled code name "Next" compiler). The language ActionScript 3, although proven to be effective and easy to learn, can be a barrier itself.

+

The Haxe language offers a familiar syntax whilst being able to cross-compile to different target languages such as native C++, Neko, HTML5, PHP, Java and more. For example OpenFL is letting you target Linux natively where Adobe has discontinued their AIR support some time ago.

+

Haxe still lets you target Flash and AIR runtimes, whilst also opening the doors to much more. You gain the benefits of a superior language and open source runtime. For example, C++ works with OpenFL and LibSDL, which would not be possible with Adobe's workflow. HaxeFlixel is far from the only ActionScript library being ported to Haxe. HaxePunk and other projects can be found on GitHub and haxelib.

+

Native Targets are not a Virtual Machine

+

Haxe is a cross-compiled language which is unlike solutions such as Adobe Air that use a virtual machine to run on different platforms. When you compile your Haxe code to a native target, it is translated into the native language itself, such as C++. Native code running on your target runtime does not share the same overheads in performance that a virtual machine has, so your code is often much faster in comparison. HaxeFlixel also takes advantage of OpenFL's use of GPU accelerated rendering through their drawTiles api.

+

Open Source Extendible Framework

+

By using the Haxe Toolkit and OpenFL, advanced developers can extend and modify anything in the toolchain right down from the compiler and the native runtime code such as HXCPP and SDL. The developers and the community behind these tools have shown a constant improvement to the projects over many years. History has shown commercial solutions do not always prioritize developer requests, and even advanced developers can't just fix their issues or bugs they find themselves.

+

The source code for everything in the toolchain is available on GitHub:

+ + + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/documentation/zoom-and-cameras/index.html b/documentation/zoom-and-cameras/index.html new file mode 100644 index 000000000..4c6a6bdac --- /dev/null +++ b/documentation/zoom-and-cameras/index.html @@ -0,0 +1,318 @@ + + + + + + + + + + 7 - Zoom and Cameras | HaxeFlixel 2D Game Engine + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + + +
+

7 - Zoom and Cameras

+ + + Edit + +

When you run your game now, you'll notice that everything is really, really small. We're going to make it more visible by applying some zoom to our game so that we can get a better look at the action. This is a pretty quick change:

+
    +
  1. Open the Main.hx file. This class initializes your game, and there are a few things here that you could play with, if you want. We just need to change a couple of the arguments.

    +
  2. +
  3. Change the width and height arguments of new FlxGame() to 320 and 240 (half of their original values).

    +
  4. +
  5. If you ran the game right now, everything would be zoomed in, but the player would run off the screen pretty quick - we need to tell the camera to follow the player around. So, open the PlayState again.

    +
  6. +
  7. In the create function, after you add the player and before super.create(), add:

    +
     FlxG.camera.follow(player, TOPDOWN, 1);
    +
    +

    This simply tells the camera to follow the player using the TOPDOWN style, with a lerp of 1 (which helps the camera move a little more smoother).

    +
  8. +
+

That's it! Test out the game and see how it looks!

+

+

Next, let's give the player something to pickup around the map!

+ + +
+
+ + + + +
+
+
+ + + + + + + + diff --git a/finances/HaxeFlixel Balance Sheet 2015-06-01.csv b/finances/HaxeFlixel Balance Sheet 2015-06-01.csv new file mode 100644 index 000000000..451683c5a --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2015-06-01.csv @@ -0,0 +1,16 @@ +account,balance +Asset, +Bank, +Patreon,90.59 +Total for Bank,90.59 +Total Assets,90.59 +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,0.00 +Current Year Earnings,90.59 +Total equity,90.59 +, +Total Liabilities and Equity,90.59 diff --git a/finances/HaxeFlixel Balance Sheet 2015-07-01.csv b/finances/HaxeFlixel Balance Sheet 2015-07-01.csv new file mode 100644 index 000000000..b9a4aee2c --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2015-07-01.csv @@ -0,0 +1,16 @@ +account,balance +Asset, +Bank, +Patreon,182.17 +Total for Bank,182.17 +Total Assets,182.17 +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,0.00 +Current Year Earnings,182.17 +Total equity,182.17 +, +Total Liabilities and Equity,182.17 diff --git a/finances/HaxeFlixel Balance Sheet 2015-08-01.csv b/finances/HaxeFlixel Balance Sheet 2015-08-01.csv new file mode 100644 index 000000000..439a8f9c9 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2015-08-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,119.81 +Treasurer,0.00 +Total for Bank,119.81 +Total Assets,119.81 +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,0.00 +Current Year Earnings,119.81 +Total equity,119.81 +, +Total Liabilities and Equity,119.81 diff --git a/finances/HaxeFlixel Balance Sheet 2015-09-01.csv b/finances/HaxeFlixel Balance Sheet 2015-09-01.csv new file mode 100644 index 000000000..7d8c06182 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2015-09-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,205.63 +Treasurer,0.00 +Total for Bank,205.63 +Total Assets,205.63 +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,0.00 +Current Year Earnings,205.63 +Total equity,205.63 +, +Total Liabilities and Equity,205.63 diff --git a/finances/HaxeFlixel Balance Sheet 2015-10-01.csv b/finances/HaxeFlixel Balance Sheet 2015-10-01.csv new file mode 100644 index 000000000..d4813cbbd --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2015-10-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,296.33 +Treasurer,0.00 +Total for Bank,296.33 +Total Assets,296.33 +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,0.00 +Current Year Earnings,296.33 +Total equity,296.33 +, +Total Liabilities and Equity,296.33 diff --git a/finances/HaxeFlixel Balance Sheet 2015-11-01.csv b/finances/HaxeFlixel Balance Sheet 2015-11-01.csv new file mode 100644 index 000000000..653772eac --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2015-11-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,402.71 +Treasurer,0.00 +Total for Bank,402.71 +Total Assets,402.71 +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,0.00 +Current Year Earnings,402.71 +Total equity,402.71 +, +Total Liabilities and Equity,402.71 diff --git a/finances/HaxeFlixel Balance Sheet 2015-12-01.csv b/finances/HaxeFlixel Balance Sheet 2015-12-01.csv new file mode 100644 index 000000000..037016c01 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2015-12-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,515.38 +Treasurer,0.00 +Total for Bank,515.38 +Total Assets,515.38 +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,0.00 +Current Year Earnings,515.38 +Total equity,515.38 +, +Total Liabilities and Equity,515.38 diff --git a/finances/HaxeFlixel Balance Sheet 2016-01-01.csv b/finances/HaxeFlixel Balance Sheet 2016-01-01.csv new file mode 100644 index 000000000..6177945e3 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2016-01-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,632.72 +Treasurer,0.00 +Total for Bank,632.72 +Total Assets,632.72 +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,515.38 +Current Year Earnings,117.34 +Total equity,632.72 +, +Total Liabilities and Equity,632.72 diff --git a/finances/HaxeFlixel Balance Sheet 2016-02-01.csv b/finances/HaxeFlixel Balance Sheet 2016-02-01.csv new file mode 100644 index 000000000..f116d3859 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2016-02-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,117.81 +Treasurer,374.42 +Total for Bank,492.23 +Total Assets,492.23 +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,515.38 +Current Year Earnings,(23.15) +Total equity,492.23 +, +Total Liabilities and Equity,492.23 diff --git a/finances/HaxeFlixel Balance Sheet 2016-03-01.csv b/finances/HaxeFlixel Balance Sheet 2016-03-01.csv new file mode 100644 index 000000000..92c4fdc51 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2016-03-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,244.43 +Treasurer,374.42 +Total for Bank,618.85 +Total Assets,618.85 +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,515.38 +Current Year Earnings,103.47 +Total equity,618.85 +, +Total Liabilities and Equity,618.85 diff --git a/finances/HaxeFlixel Balance Sheet 2016-04-01.csv b/finances/HaxeFlixel Balance Sheet 2016-04-01.csv new file mode 100644 index 000000000..362036526 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2016-04-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,380.88 +Treasurer,223.67 +Total for Bank,604.55 +Total Assets,604.55 +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,515.38 +Current Year Earnings,89.17 +Total equity,604.55 +, +Total Liabilities and Equity,604.55 diff --git a/finances/HaxeFlixel Balance Sheet 2016-05-01.csv b/finances/HaxeFlixel Balance Sheet 2016-05-01.csv new file mode 100644 index 000000000..098e76638 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2016-05-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,526.95 +Treasurer,223.67 +Total for Bank,750.62 +Total Assets,750.62 +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,515.38 +Current Year Earnings,235.24 +Total equity,750.62 +, +Total Liabilities and Equity,750.62 diff --git a/finances/HaxeFlixel Balance Sheet 2016-06-01.csv b/finances/HaxeFlixel Balance Sheet 2016-06-01.csv new file mode 100644 index 000000000..9d02fd670 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2016-06-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,663.94 +Treasurer,346.75 +Total for Bank,"1,010.69" +Total Assets,"1,010.69" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,515.38 +Current Year Earnings,495.31 +Total equity,"1,010.69" +, +Total Liabilities and Equity,"1,010.69" diff --git a/finances/HaxeFlixel Balance Sheet 2016-07-01.csv b/finances/HaxeFlixel Balance Sheet 2016-07-01.csv new file mode 100644 index 000000000..17c205485 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2016-07-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,811.96 +Treasurer,358.48 +Total for Bank,"1,170.44" +Total Assets,"1,170.44" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,515.38 +Current Year Earnings,655.06 +Total equity,"1,170.44" +, +Total Liabilities and Equity,"1,170.44" diff --git a/finances/HaxeFlixel Balance Sheet 2016-08-01.csv b/finances/HaxeFlixel Balance Sheet 2016-08-01.csv new file mode 100644 index 000000000..aab8be026 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2016-08-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,980.85 +Treasurer,358.48 +Total for Bank,"1,339.33" +Total Assets,"1,339.33" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,515.38 +Current Year Earnings,823.95 +Total equity,"1,339.33" +, +Total Liabilities and Equity,"1,339.33" diff --git a/finances/HaxeFlixel Balance Sheet 2016-09-01.csv b/finances/HaxeFlixel Balance Sheet 2016-09-01.csv new file mode 100644 index 000000000..2461f5ab8 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2016-09-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,"1,138.37" +Treasurer,370.17 +Total for Bank,"1,508.54" +Total Assets,"1,508.54" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,515.38 +Current Year Earnings,993.16 +Total equity,"1,508.54" +, +Total Liabilities and Equity,"1,508.54" diff --git a/finances/HaxeFlixel Balance Sheet 2016-10-01.csv b/finances/HaxeFlixel Balance Sheet 2016-10-01.csv new file mode 100644 index 000000000..4b257ac1d --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2016-10-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,"1,311.89" +Treasurer,337.50 +Total for Bank,"1,649.39" +Total Assets,"1,649.39" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,515.38 +Current Year Earnings,"1,134.01" +Total equity,"1,649.39" +, +Total Liabilities and Equity,"1,649.39" diff --git a/finances/HaxeFlixel Balance Sheet 2016-11-01.csv b/finances/HaxeFlixel Balance Sheet 2016-11-01.csv new file mode 100644 index 000000000..91bf51916 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2016-11-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,"1,460.22" +Treasurer,384.22 +Total for Bank,"1,844.44" +Total Assets,"1,844.44" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,515.38 +Current Year Earnings,"1,329.06" +Total equity,"1,844.44" +, +Total Liabilities and Equity,"1,844.44" diff --git a/finances/HaxeFlixel Balance Sheet 2016-12-01.csv b/finances/HaxeFlixel Balance Sheet 2016-12-01.csv new file mode 100644 index 000000000..3a921ba2d --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2016-12-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,"1,612.38" +Treasurer,384.22 +Total for Bank,"1,996.60" +Total Assets,"1,996.60" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,515.38 +Current Year Earnings,"1,481.22" +Total equity,"1,996.60" +, +Total Liabilities and Equity,"1,996.60" diff --git a/finances/HaxeFlixel Balance Sheet 2017-01-01.csv b/finances/HaxeFlixel Balance Sheet 2017-01-01.csv new file mode 100644 index 000000000..1d104edb0 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2017-01-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,"1,769.11" +Treasurer,413.50 +Total for Bank,"2,182.61" +Total Assets,"2,182.61" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,"2,030.30" +Current Year Earnings,152.31 +Total equity,"2,182.61" +, +Total Liabilities and Equity,"2,182.61" diff --git a/finances/HaxeFlixel Balance Sheet 2017-02-01.csv b/finances/HaxeFlixel Balance Sheet 2017-02-01.csv new file mode 100644 index 000000000..5ce167405 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2017-02-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,"1,911.29" +Treasurer,413.50 +Total for Bank,"2,324.79" +Total Assets,"2,324.79" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,"2,030.30" +Current Year Earnings,294.49 +Total equity,"2,324.79" +, +Total Liabilities and Equity,"2,324.79" diff --git a/finances/HaxeFlixel Balance Sheet 2017-03-01.csv b/finances/HaxeFlixel Balance Sheet 2017-03-01.csv new file mode 100644 index 000000000..237eaae1e --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2017-03-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,"2,052.60" +Treasurer,113.20 +Total for Bank,"2,165.80" +Total Assets,"2,165.80" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,"2,030.30" +Current Year Earnings,135.50 +Total equity,"2,165.80" +, +Total Liabilities and Equity,"2,165.80" diff --git a/finances/HaxeFlixel Balance Sheet 2017-04-01.csv b/finances/HaxeFlixel Balance Sheet 2017-04-01.csv new file mode 100644 index 000000000..90a79e82a --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2017-04-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,"2,192.46" +Treasurer,113.20 +Total for Bank,"2,305.66" +Total Assets,"2,305.66" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,"2,030.30" +Current Year Earnings,275.36 +Total equity,"2,305.66" +, +Total Liabilities and Equity,"2,305.66" diff --git a/finances/HaxeFlixel Balance Sheet 2017-05-01.csv b/finances/HaxeFlixel Balance Sheet 2017-05-01.csv new file mode 100644 index 000000000..3842808d3 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2017-05-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,"2,331.44" +Treasurer,113.20 +Total for Bank,"2,444.64" +Total Assets,"2,444.64" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,"2,030.30" +Current Year Earnings,414.34 +Total equity,"2,444.64" +, +Total Liabilities and Equity,"2,444.64" diff --git a/finances/HaxeFlixel Balance Sheet 2017-06-01.csv b/finances/HaxeFlixel Balance Sheet 2017-06-01.csv new file mode 100644 index 000000000..10275060a --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2017-06-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,"2,464.45" +Treasurer,113.20 +Total for Bank,"2,577.65" +Total Assets,"2,577.65" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,"2,030.30" +Current Year Earnings,547.35 +Total equity,"2,577.65" +, +Total Liabilities and Equity,"2,577.65" diff --git a/finances/HaxeFlixel Balance Sheet 2017-07-01.csv b/finances/HaxeFlixel Balance Sheet 2017-07-01.csv new file mode 100644 index 000000000..78548a408 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2017-07-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,"2,598.39" +Treasurer,139.39 +Total for Bank,"2,737.78" +Total Assets,"2,737.78" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,"2,030.30" +Current Year Earnings,707.48 +Total equity,"2,737.78" +, +Total Liabilities and Equity,"2,737.78" diff --git a/finances/HaxeFlixel Balance Sheet 2017-08-01.csv b/finances/HaxeFlixel Balance Sheet 2017-08-01.csv new file mode 100644 index 000000000..8b9ff2bd3 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2017-08-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,"2,724.37" +Treasurer,139.39 +Total for Bank,"2,863.76" +Total Assets,"2,863.76" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,"2,030.30" +Current Year Earnings,833.46 +Total equity,"2,863.76" +, +Total Liabilities and Equity,"2,863.76" diff --git a/finances/HaxeFlixel Balance Sheet 2017-09-01.csv b/finances/HaxeFlixel Balance Sheet 2017-09-01.csv new file mode 100644 index 000000000..31210a7c4 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2017-09-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,125.88 +Treasurer,"2,117.50" +Total for Bank,"2,243.38" +Total Assets,"2,243.38" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,"2,029.08" +Current Year Earnings,214.30 +Total equity,"2,243.38" +, +Total Liabilities and Equity,"2,243.38" diff --git a/finances/HaxeFlixel Balance Sheet 2017-10-01.csv b/finances/HaxeFlixel Balance Sheet 2017-10-01.csv new file mode 100644 index 000000000..1a9179956 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2017-10-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,251.76 +Treasurer,"1,999.55" +Total for Bank,"2,251.31" +Total Assets,"2,251.31" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,"2,029.08" +Current Year Earnings,222.23 +Total equity,"2,251.31" +, +Total Liabilities and Equity,"2,251.31" diff --git a/finances/HaxeFlixel Balance Sheet 2017-11-01.csv b/finances/HaxeFlixel Balance Sheet 2017-11-01.csv new file mode 100644 index 000000000..dc444c906 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2017-11-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,373.20 +Treasurer,"1,999.55" +Total for Bank,"2,372.75" +Total Assets,"2,372.75" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,"2,029.08" +Current Year Earnings,343.67 +Total equity,"2,372.75" +, +Total Liabilities and Equity,"2,372.75" diff --git a/finances/HaxeFlixel Balance Sheet 2017-12-01.csv b/finances/HaxeFlixel Balance Sheet 2017-12-01.csv new file mode 100644 index 000000000..04b824568 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2017-12-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,490.20 +Treasurer,"1,999.55" +Total for Bank,"2,489.75" +Total Assets,"2,489.75" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,"2,029.08" +Current Year Earnings,460.67 +Total equity,"2,489.75" +, +Total Liabilities and Equity,"2,489.75" diff --git a/finances/HaxeFlixel Balance Sheet 2018-01-01.csv b/finances/HaxeFlixel Balance Sheet 2018-01-01.csv new file mode 100644 index 000000000..bead6ac14 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2018-01-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,607.40 +Treasurer,"1,999.55" +Total for Bank,"2,606.95" +Total Assets,"2,606.95" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,"2,489.75" +Current Year Earnings,117.20 +Total equity,"2,606.95" +, +Total Liabilities and Equity,"2,606.95" diff --git a/finances/HaxeFlixel Balance Sheet 2018-02-01.csv b/finances/HaxeFlixel Balance Sheet 2018-02-01.csv new file mode 100644 index 000000000..048db07db --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2018-02-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,724.65 +Treasurer,"1,699.55" +Total for Bank,"2,424.20" +Total Assets,"2,424.20" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,"2,489.75" +Current Year Earnings,(65.55) +Total equity,"2,424.20" +, +Total Liabilities and Equity,"2,424.20" diff --git a/finances/HaxeFlixel Balance Sheet 2018-03-01.csv b/finances/HaxeFlixel Balance Sheet 2018-03-01.csv new file mode 100644 index 000000000..7453177fc --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2018-03-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,842.04 +Treasurer,"1,699.55" +Total for Bank,"2,541.59" +Total Assets,"2,541.59" +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,"2,489.75" +Current Year Earnings,51.84 +Total equity,"2,541.59" +, +Total Liabilities and Equity,"2,541.59" diff --git a/finances/HaxeFlixel Balance Sheet 2018-04-01.csv b/finances/HaxeFlixel Balance Sheet 2018-04-01.csv new file mode 100644 index 000000000..502635b87 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2018-04-01.csv @@ -0,0 +1,17 @@ +account,balance +Asset, +Bank, +Patreon,115.55 +Treasurer,(75.24) +Total for Bank,40.31 +Total Assets,40.31 +, +Liability, +Total Liabilities,0.00 +, +Equity, +Previous Year(s) Earnings,"2,489.75" +Current Year Earnings,"(2,449.44)" +Total equity,40.31 +, +Total Liabilities and Equity,40.31 diff --git a/finances/HaxeFlixel Balance Sheet 2018-05-01.csv b/finances/HaxeFlixel Balance Sheet 2018-05-01.csv new file mode 100644 index 000000000..cd66a0087 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2018-05-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2018-05-01 +ACCOUNT NUMBER,ACCOUNTS,"May 01, 2018" +,Assets, +,Cash and Bank, +,Patreon,$225.38 +,Treasurer,-$75.24 +,Total Cash and Bank,$150.14 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$150.14 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,"$2,489.75" +,"Profit between Jan 1, 2018 and May 1, 2018","-$2,339.61" +,Total Retained Earnings,$150.14 +,Total Equity,$150.14 diff --git a/finances/HaxeFlixel Balance Sheet 2018-06-01.csv b/finances/HaxeFlixel Balance Sheet 2018-06-01.csv new file mode 100644 index 000000000..f4c402325 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2018-06-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2018-06-01 +ACCOUNT NUMBER,ACCOUNTS,"Jun 01, 2018" +,Assets, +,Cash and Bank, +,Patreon,$100.65 +,Treasurer,-$107.90 +,Total Cash and Bank,-$7.25 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,-$7.25 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,"$2,489.75" +,"Profit between Jan 1, 2018 and Jun 1, 2018","-$2,497.00" +,Total Retained Earnings,-$7.25 +,Total Equity,-$7.25 diff --git a/finances/HaxeFlixel Balance Sheet 2018-07-01.csv b/finances/HaxeFlixel Balance Sheet 2018-07-01.csv new file mode 100644 index 000000000..1f99599cf --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2018-07-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2018-07-01 +ACCOUNT NUMBER,ACCOUNTS,"Jul 01, 2018" +,Assets, +,Cash and Bank, +,Patreon,$205.89 +,Treasurer,-$107.90 +,Total Cash and Bank,$97.99 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$97.99 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,"$2,489.75" +,"Profit between Jan 1, 2018 and Jul 1, 2018","-$2,391.76" +,Total Retained Earnings,$97.99 +,Total Equity,$97.99 diff --git a/finances/HaxeFlixel Balance Sheet 2018-08-01.csv b/finances/HaxeFlixel Balance Sheet 2018-08-01.csv new file mode 100644 index 000000000..7bc278129 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2018-08-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2018-08-01 +ACCOUNT NUMBER,ACCOUNTS,"Aug 01, 2018" +,Assets, +,Cash and Bank, +,Patreon,$311.16 +,Treasurer,-$107.90 +,Total Cash and Bank,$203.26 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$203.26 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,"$2,489.75" +,"Profit between Jan 1, 2018 and Aug 1, 2018","-$2,286.49" +,Total Retained Earnings,$203.26 +,Total Equity,$203.26 diff --git a/finances/HaxeFlixel Balance Sheet 2018-09-01.csv b/finances/HaxeFlixel Balance Sheet 2018-09-01.csv new file mode 100644 index 000000000..700634ce5 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2018-09-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2018-09-01 +ACCOUNT NUMBER,ACCOUNTS,"Sep 01, 2018" +,Assets, +,Cash and Bank, +,Patreon,$97.98 +,Treasurer,$72.41 +,Total Cash and Bank,$170.39 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$170.39 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,"$2,489.75" +,"Profit between Jan 1, 2018 and Sep 1, 2018","-$2,319.36" +,Total Retained Earnings,$170.39 +,Total Equity,$170.39 diff --git a/finances/HaxeFlixel Balance Sheet 2018-10-01.csv b/finances/HaxeFlixel Balance Sheet 2018-10-01.csv new file mode 100644 index 000000000..76f07f17e --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2018-10-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2018-10-01 +ACCOUNT NUMBER,ACCOUNTS,"Oct 01, 2018" +,Assets, +,Cash and Bank, +,Patreon,$195.96 +,Treasurer,$72.41 +,Total Cash and Bank,$268.37 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$268.37 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,"$2,489.75" +,"Profit between Jan 1, 2018 and Oct 1, 2018","-$2,221.38" +,Total Retained Earnings,$268.37 +,Total Equity,$268.37 diff --git a/finances/HaxeFlixel Balance Sheet 2018-11-01.csv b/finances/HaxeFlixel Balance Sheet 2018-11-01.csv new file mode 100644 index 000000000..3f73a5fb0 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2018-11-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2018-11-01 +ACCOUNT NUMBER,ACCOUNTS,"Nov 01, 2018" +,Assets, +,Cash and Bank, +,Patreon,$280.95 +,Treasurer,$22.41 +,Total Cash and Bank,$303.36 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$303.36 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,"$2,489.75" +,"Profit between Jan 1, 2018 and Nov 1, 2018","-$2,186.39" +,Total Retained Earnings,$303.36 +,Total Equity,$303.36 diff --git a/finances/HaxeFlixel Balance Sheet 2018-12-01.csv b/finances/HaxeFlixel Balance Sheet 2018-12-01.csv new file mode 100644 index 000000000..59c7868c7 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2018-12-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2018-12-01 +ACCOUNT NUMBER,ACCOUNTS,"Dec 01, 2018" +,Assets, +,Cash and Bank, +,Patreon,$361.31 +,Treasurer,$22.41 +,Total Cash and Bank,$383.72 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$383.72 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,"$2,489.75" +,"Profit between Jan 1, 2018 and Dec 1, 2018","-$2,106.03" +,Total Retained Earnings,$383.72 +,Total Equity,$383.72 diff --git a/finances/HaxeFlixel Balance Sheet 2019-01-01.csv b/finances/HaxeFlixel Balance Sheet 2019-01-01.csv new file mode 100644 index 000000000..1498d6e44 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2019-01-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2019-01-01 +ACCOUNT NUMBER,ACCOUNTS,"Jan 01, 2019" +,Assets, +,Cash and Bank, +,Patreon,$438.33 +,Treasurer,$22.41 +,Total Cash and Bank,$460.74 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$460.74 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$383.72 +,"Profit between Jan 1, 2019 and Jan 1, 2019",$77.02 +,Total Retained Earnings,$460.74 +,Total Equity,$460.74 diff --git a/finances/HaxeFlixel Balance Sheet 2019-02-01.csv b/finances/HaxeFlixel Balance Sheet 2019-02-01.csv new file mode 100644 index 000000000..7b4e7ebc4 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2019-02-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2019-02-01 +ACCOUNT NUMBER,ACCOUNTS,"Feb 01, 2019" +,Assets, +,Cash and Bank, +,Patreon,$514.42 +,Treasurer,$22.41 +,Total Cash and Bank,$536.83 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$536.83 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$383.72 +,"Profit between Jan 1, 2019 and Feb 1, 2019",$153.11 +,Total Retained Earnings,$536.83 +,Total Equity,$536.83 diff --git a/finances/HaxeFlixel Balance Sheet 2019-03-01.csv b/finances/HaxeFlixel Balance Sheet 2019-03-01.csv new file mode 100644 index 000000000..89859c280 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2019-03-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2019-03-01 +ACCOUNT NUMBER,ACCOUNTS,"Mar 01, 2019" +,Assets, +,Cash and Bank, +,Patreon,$590.56 +,Treasurer,$22.41 +,Total Cash and Bank,$612.97 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$612.97 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$383.72 +,"Profit between Jan 1, 2019 and Mar 1, 2019",$229.25 +,Total Retained Earnings,$612.97 +,Total Equity,$612.97 diff --git a/finances/HaxeFlixel Balance Sheet 2019-04-01.csv b/finances/HaxeFlixel Balance Sheet 2019-04-01.csv new file mode 100644 index 000000000..ecdbee6a5 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2019-04-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2019-04-01 +ACCOUNT NUMBER,ACCOUNTS,"Apr 01, 2019" +,Assets, +,Cash and Bank, +,Patreon,$662.00 +,Treasurer,$22.41 +,Total Cash and Bank,$684.41 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$684.41 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$383.72 +,"Profit between Jan 1, 2019 and Apr 1, 2019",$300.69 +,Total Retained Earnings,$684.41 +,Total Equity,$684.41 diff --git a/finances/HaxeFlixel Balance Sheet 2019-05-01.csv b/finances/HaxeFlixel Balance Sheet 2019-05-01.csv new file mode 100644 index 000000000..b0117dff3 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2019-05-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2019-05-01 +ACCOUNT NUMBER,ACCOUNTS,"May 01, 2019" +,Assets, +,Cash and Bank, +,Patreon,$733.45 +,Treasurer,$22.41 +,Total Cash and Bank,$755.86 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$755.86 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$383.72 +,"Profit between Jan 1, 2019 and May 1, 2019",$372.14 +,Total Retained Earnings,$755.86 +,Total Equity,$755.86 diff --git a/finances/HaxeFlixel Balance Sheet 2019-06-01.csv b/finances/HaxeFlixel Balance Sheet 2019-06-01.csv new file mode 100644 index 000000000..8b01e307a --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2019-06-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2019-06-01 +ACCOUNT NUMBER,ACCOUNTS,"Jun 01, 2019" +,Assets, +,Cash and Bank, +,Patreon,$804.95 +,Treasurer,$22.41 +,Total Cash and Bank,$827.36 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$827.36 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$383.72 +,"Profit between Jan 1, 2019 and Jun 1, 2019",$443.64 +,Total Retained Earnings,$827.36 +,Total Equity,$827.36 diff --git a/finances/HaxeFlixel Balance Sheet 2019-07-01.csv b/finances/HaxeFlixel Balance Sheet 2019-07-01.csv new file mode 100644 index 000000000..153777ecb --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2019-07-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2019-07-01 +ACCOUNT NUMBER,ACCOUNTS,"Jul 01, 2019" +,Assets, +,Cash and Bank, +,Patreon,$876.45 +,Treasurer,$22.41 +,Total Cash and Bank,$898.86 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$898.86 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$383.72 +,"Profit between Jan 1, 2019 and Jul 1, 2019",$515.14 +,Total Retained Earnings,$898.86 +,Total Equity,$898.86 diff --git a/finances/HaxeFlixel Balance Sheet 2019-08-01.csv b/finances/HaxeFlixel Balance Sheet 2019-08-01.csv new file mode 100644 index 000000000..5c85ee4c8 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2019-08-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2019-08-01 +ACCOUNT NUMBER,ACCOUNTS,"Aug 01, 2019" +,Assets, +,Cash and Bank, +,Patreon,$947.86 +,Treasurer,$22.41 +,Total Cash and Bank,$970.27 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$970.27 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$383.72 +,"Profit between Jan 1, 2019 and Aug 1, 2019",$586.55 +,Total Retained Earnings,$970.27 +,Total Equity,$970.27 diff --git a/finances/HaxeFlixel Balance Sheet 2019-09-01.csv b/finances/HaxeFlixel Balance Sheet 2019-09-01.csv new file mode 100644 index 000000000..80f73fc65 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2019-09-01.csv @@ -0,0 +1,25 @@ +Balance Sheet +HaxeFlixel +As of 2019-09-01 +ACCOUNT NUMBER,ACCOUNTS,"Sep 01, 2019" +,Assets, +,Cash and Bank, +,Patreon,$71.42 +,Total Cash and Bank,$71.42 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$71.42 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$383.72 +,"Profit between Jan 1, 2019 and Sep 1, 2019",-$312.30 +,Total Retained Earnings,$71.42 +,Total Equity,$71.42 diff --git a/finances/HaxeFlixel Balance Sheet 2019-10-01.csv b/finances/HaxeFlixel Balance Sheet 2019-10-01.csv new file mode 100644 index 000000000..7383bdd10 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2019-10-01.csv @@ -0,0 +1,25 @@ +Balance Sheet +HaxeFlixel +As of 2019-10-01 +ACCOUNT NUMBER,ACCOUNTS,"Oct 01, 2019" +,Assets, +,Cash and Bank, +,Patreon,$142.82 +,Total Cash and Bank,$142.82 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$142.82 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$383.72 +,"Profit between Jan 1, 2019 and Oct 1, 2019",-$240.90 +,Total Retained Earnings,$142.82 +,Total Equity,$142.82 diff --git a/finances/HaxeFlixel Balance Sheet 2019-11-01.csv b/finances/HaxeFlixel Balance Sheet 2019-11-01.csv new file mode 100644 index 000000000..7d276ce92 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2019-11-01.csv @@ -0,0 +1,25 @@ +Balance Sheet +HaxeFlixel +As of 2019-11-01 +ACCOUNT NUMBER,ACCOUNTS,"Nov 01, 2019" +,Assets, +,Cash and Bank, +,Patreon,$214.23 +,Total Cash and Bank,$214.23 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$214.23 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$383.72 +,"Profit between Jan 1, 2019 and Nov 1, 2019",-$169.49 +,Total Retained Earnings,$214.23 +,Total Equity,$214.23 diff --git a/finances/HaxeFlixel Balance Sheet 2019-12-01.csv b/finances/HaxeFlixel Balance Sheet 2019-12-01.csv new file mode 100644 index 000000000..0e602ba2d --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2019-12-01.csv @@ -0,0 +1,25 @@ +Balance Sheet +HaxeFlixel +As of 2019-12-01 +ACCOUNT NUMBER,ACCOUNTS,"Dec 01, 2019" +,Assets, +,Cash and Bank, +,Patreon,$290.25 +,Total Cash and Bank,$290.25 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$290.25 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$383.72 +,"Profit between Jan 1, 2019 and Dec 1, 2019",-$93.47 +,Total Retained Earnings,$290.25 +,Total Equity,$290.25 diff --git a/finances/HaxeFlixel Balance Sheet 2020-01-01.csv b/finances/HaxeFlixel Balance Sheet 2020-01-01.csv new file mode 100644 index 000000000..005621981 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2020-01-01.csv @@ -0,0 +1,25 @@ +Balance Sheet +HaxeFlixel +As of 2020-01-01 +ACCOUNT NUMBER,ACCOUNTS,"Jan 01, 2020" +,Assets, +,Cash and Bank, +,Patreon,$366.28 +,Total Cash and Bank,$366.28 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$366.28 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$290.25 +,"Profit between Jan 1, 2020 and Jan 1, 2020",$76.03 +,Total Retained Earnings,$366.28 +,Total Equity,$366.28 diff --git a/finances/HaxeFlixel Balance Sheet 2020-02-01.csv b/finances/HaxeFlixel Balance Sheet 2020-02-01.csv new file mode 100644 index 000000000..1e15bcaa0 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2020-02-01.csv @@ -0,0 +1,25 @@ +Balance Sheet +HaxeFlixel +As of 2020-02-01 +ACCOUNT NUMBER,ACCOUNTS,"Feb 01, 2020" +,Assets, +,Cash and Bank, +,Patreon,$442.32 +,Total Cash and Bank,$442.32 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$442.32 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$290.25 +,"Profit between Jan 1, 2020 and Feb 1, 2020",$152.07 +,Total Retained Earnings,$442.32 +,Total Equity,$442.32 diff --git a/finances/HaxeFlixel Balance Sheet 2020-03-01.csv b/finances/HaxeFlixel Balance Sheet 2020-03-01.csv new file mode 100644 index 000000000..fbfc7195b --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2020-03-01.csv @@ -0,0 +1,25 @@ +Balance Sheet +HaxeFlixel +As of 2020-03-01 +ACCOUNT NUMBER,ACCOUNTS,"Mar 01, 2020" +,Assets, +,Cash and Bank, +,Patreon,$518.35 +,Total Cash and Bank,$518.35 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$518.35 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$290.25 +,"Profit between Jan 1, 2020 and Mar 1, 2020",$228.10 +,Total Retained Earnings,$518.35 +,Total Equity,$518.35 diff --git a/finances/HaxeFlixel Balance Sheet 2020-04-01.csv b/finances/HaxeFlixel Balance Sheet 2020-04-01.csv new file mode 100644 index 000000000..92d0d9ba2 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2020-04-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2020-04-01 +ACCOUNT NUMBER,ACCOUNTS,"Apr 01, 2020" +,Assets, +,Cash and Bank, +,Patreon,$84.71 +,Treasurer,$13.16 +,Total Cash and Bank,$97.87 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$97.87 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$290.25 +,"Profit between Jan 1, 2020 and Apr 1, 2020",-$192.38 +,Total Retained Earnings,$97.87 +,Total Equity,$97.87 diff --git a/finances/HaxeFlixel Balance Sheet 2020-05-01.csv b/finances/HaxeFlixel Balance Sheet 2020-05-01.csv new file mode 100644 index 000000000..e5fc39cbb --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2020-05-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2020-05-01 +ACCOUNT NUMBER,ACCOUNTS,"May 01, 2020" +,Assets, +,Cash and Bank, +,Patreon,$174.17 +,Treasurer,$13.16 +,Total Cash and Bank,$187.33 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$187.33 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$290.25 +,"Profit between Jan 1, 2020 and May 1, 2020",-$102.92 +,Total Retained Earnings,$187.33 +,Total Equity,$187.33 diff --git a/finances/HaxeFlixel Balance Sheet 2020-06-01.csv b/finances/HaxeFlixel Balance Sheet 2020-06-01.csv new file mode 100644 index 000000000..b520ab1a2 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2020-06-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2020-06-01 +ACCOUNT NUMBER,ACCOUNTS,"Jun 01, 2020" +,Assets, +,Cash and Bank, +,Patreon,$263.65 +,Treasurer,$13.16 +,Total Cash and Bank,$276.81 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$276.81 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$290.25 +,"Profit between Jan 1, 2020 and Jun 1, 2020",-$13.44 +,Total Retained Earnings,$276.81 +,Total Equity,$276.81 diff --git a/finances/HaxeFlixel Balance Sheet 2020-07-01.csv b/finances/HaxeFlixel Balance Sheet 2020-07-01.csv new file mode 100644 index 000000000..a8141a511 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2020-07-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2020-07-01 +ACCOUNT NUMBER,ACCOUNTS,"Jul 01, 2020" +,Assets, +,Cash and Bank, +,Patreon,$353.11 +,Treasurer,$13.16 +,Total Cash and Bank,$366.27 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$366.27 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$290.25 +,"Profit between Jan 1, 2020 and Jul 1, 2020",$76.02 +,Total Retained Earnings,$366.27 +,Total Equity,$366.27 diff --git a/finances/HaxeFlixel Balance Sheet 2020-08-01.csv b/finances/HaxeFlixel Balance Sheet 2020-08-01.csv new file mode 100644 index 000000000..b9b44b552 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2020-08-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2020-08-01 +ACCOUNT NUMBER,ACCOUNTS,"Aug 01, 2020" +,Assets, +,Cash and Bank, +,Patreon,$440.52 +,Treasurer,$13.16 +,Total Cash and Bank,$453.68 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$453.68 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$290.25 +,"Profit between Jan 1, 2020 and Aug 1, 2020",$163.43 +,Total Retained Earnings,$453.68 +,Total Equity,$453.68 diff --git a/finances/HaxeFlixel Balance Sheet 2020-09-01.csv b/finances/HaxeFlixel Balance Sheet 2020-09-01.csv new file mode 100644 index 000000000..def9d5718 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2020-09-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2020-09-01 +ACCOUNT NUMBER,ACCOUNTS,"Sep 01, 2020" +,Assets, +,Cash and Bank, +,Patreon,$530.57 +,Treasurer,$13.16 +,Total Cash and Bank,$543.73 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$543.73 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$290.25 +,"Profit between Jan 1, 2020 and Sep 1, 2020",$253.48 +,Total Retained Earnings,$543.73 +,Total Equity,$543.73 diff --git a/finances/HaxeFlixel Balance Sheet 2020-10-01.csv b/finances/HaxeFlixel Balance Sheet 2020-10-01.csv new file mode 100644 index 000000000..08aabb8d0 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2020-10-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2020-10-01 +ACCOUNT NUMBER,ACCOUNTS,"Oct 01, 2020" +,Assets, +,Cash and Bank, +,Patreon,$620.57 +,Treasurer,$13.16 +,Total Cash and Bank,$633.73 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$633.73 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$290.25 +,"Profit between Jan 1, 2020 and Oct 1, 2020",$343.48 +,Total Retained Earnings,$633.73 +,Total Equity,$633.73 diff --git a/finances/HaxeFlixel Balance Sheet 2020-11-01.csv b/finances/HaxeFlixel Balance Sheet 2020-11-01.csv new file mode 100644 index 000000000..142e9744b --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2020-11-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2020-11-01 +ACCOUNT NUMBER,ACCOUNTS,"Nov 01, 2020" +,Assets, +,Cash and Bank, +,Patreon,$710.63 +,Treasurer,$13.16 +,Total Cash and Bank,$723.79 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$723.79 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$290.25 +,"Profit between Jan 1, 2020 and Nov 1, 2020",$433.54 +,Total Retained Earnings,$723.79 +,Total Equity,$723.79 diff --git a/finances/HaxeFlixel Balance Sheet 2020-12-01.csv b/finances/HaxeFlixel Balance Sheet 2020-12-01.csv new file mode 100644 index 000000000..a7c1df9d3 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2020-12-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2020-12-01 +ACCOUNT NUMBER,ACCOUNTS,"Dec 01, 2020" +,Assets, +,Cash and Bank, +,Patreon,$800.63 +,Treasurer,$13.16 +,Total Cash and Bank,$813.79 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$813.79 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$290.25 +,"Profit between Jan 1, 2020 and Dec 1, 2020",$523.54 +,Total Retained Earnings,$813.79 +,Total Equity,$813.79 diff --git a/finances/HaxeFlixel Balance Sheet 2021-01-01.csv b/finances/HaxeFlixel Balance Sheet 2021-01-01.csv new file mode 100644 index 000000000..60967c665 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2021-01-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2021-01-01 +ACCOUNT NUMBER,ACCOUNTS,"Jan 01, 2021" +,Assets, +,Cash and Bank, +,Patreon,$883.46 +,Treasurer,$13.16 +,Total Cash and Bank,$896.62 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$896.62 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$813.79 +,"Profit between Jan 1, 2021 and Jan 1, 2021",$82.83 +,Total Retained Earnings,$896.62 +,Total Equity,$896.62 diff --git a/finances/HaxeFlixel Balance Sheet 2021-02-01.csv b/finances/HaxeFlixel Balance Sheet 2021-02-01.csv new file mode 100644 index 000000000..1cb8c57b4 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2021-02-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2021-02-01 +ACCOUNT NUMBER,ACCOUNTS,"Feb 01, 2021" +,Assets, +,Cash and Bank, +,Patreon,$966.32 +,Treasurer,$13.16 +,Total Cash and Bank,$979.48 +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,$979.48 +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$813.79 +,"Profit between Jan 1, 2021 and Feb 1, 2021",$165.69 +,Total Retained Earnings,$979.48 +,Total Equity,$979.48 diff --git a/finances/HaxeFlixel Balance Sheet 2021-03-01.csv b/finances/HaxeFlixel Balance Sheet 2021-03-01.csv new file mode 100644 index 000000000..7d2e1d1cf --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2021-03-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2021-03-01 +ACCOUNT NUMBER,ACCOUNTS,"Mar 01, 2021" +,Assets, +,Cash and Bank, +,Patreon,"$1,049.34" +,Treasurer,$13.16 +,Total Cash and Bank,"$1,062.50" +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,"$1,062.50" +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$813.95 +,"Profit between Jan 1, 2021 and Mar 1, 2021",$248.55 +,Total Retained Earnings,"$1,062.50" +,Total Equity,"$1,062.50" diff --git a/finances/HaxeFlixel Balance Sheet 2021-04-01.csv b/finances/HaxeFlixel Balance Sheet 2021-04-01.csv new file mode 100644 index 000000000..f442b64e5 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2021-04-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2021-04-01 +ACCOUNT NUMBER,ACCOUNTS,"Apr 01, 2021" +,Assets, +,Cash and Bank, +,Patreon,"$1,132.21" +,Treasurer,$13.16 +,Total Cash and Bank,"$1,145.37" +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,"$1,145.37" +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$813.95 +,"Profit between Jan 1, 2021 and Apr 1, 2021",$331.42 +,Total Retained Earnings,"$1,145.37" +,Total Equity,"$1,145.37" diff --git a/finances/HaxeFlixel Balance Sheet 2021-05-01.csv b/finances/HaxeFlixel Balance Sheet 2021-05-01.csv new file mode 100644 index 000000000..cf40b5d9b --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2021-05-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2021-05-01 +ACCOUNT NUMBER,ACCOUNTS,"May 01, 2021" +,Assets, +,Cash and Bank, +,Patreon,"$1,215.08" +,Treasurer,$13.16 +,Total Cash and Bank,"$1,228.24" +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,"$1,228.24" +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$813.95 +,"Profit between Jan 1, 2021 and May 1, 2021",$414.29 +,Total Retained Earnings,"$1,228.24" +,Total Equity,"$1,228.24" diff --git a/finances/HaxeFlixel Balance Sheet 2021-06-01.csv b/finances/HaxeFlixel Balance Sheet 2021-06-01.csv new file mode 100644 index 000000000..4df962246 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2021-06-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2021-06-01 +ACCOUNT NUMBER,ACCOUNTS,"Jun 01, 2021" +,Assets, +,Cash and Bank, +,Patreon,"$1,293.40" +,Treasurer,$13.16 +,Total Cash and Bank,"$1,306.56" +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,"$1,306.56" +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$813.95 +,"Profit between Jan 1, 2021 and Jun 1, 2021",$492.61 +,Total Retained Earnings,"$1,306.56" +,Total Equity,"$1,306.56" diff --git a/finances/HaxeFlixel Balance Sheet 2021-07-01.csv b/finances/HaxeFlixel Balance Sheet 2021-07-01.csv new file mode 100644 index 000000000..25c650e39 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2021-07-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2021-07-01 +ACCOUNT NUMBER,ACCOUNTS,"Jul 01, 2021" +,Assets, +,Cash and Bank, +,Patreon,"$1,371.73" +,Treasurer,$13.16 +,Total Cash and Bank,"$1,384.89" +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,"$1,384.89" +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$813.95 +,"Profit between Jan 1, 2021 and Jul 1, 2021",$570.94 +,Total Retained Earnings,"$1,384.89" +,Total Equity,"$1,384.89" diff --git a/finances/HaxeFlixel Balance Sheet 2021-08-01.csv b/finances/HaxeFlixel Balance Sheet 2021-08-01.csv new file mode 100644 index 000000000..66be98f53 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2021-08-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2021-08-01 +ACCOUNT NUMBER,ACCOUNTS,"Aug 01, 2021" +,Assets, +,Cash and Bank, +,Patreon,"$1,450.07" +,Treasurer,$13.16 +,Total Cash and Bank,"$1,463.23" +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,"$1,463.23" +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$813.95 +,"Profit between Jan 1, 2021 and Aug 1, 2021",$649.28 +,Total Retained Earnings,"$1,463.23" +,Total Equity,"$1,463.23" diff --git a/finances/HaxeFlixel Balance Sheet 2021-09-01.csv b/finances/HaxeFlixel Balance Sheet 2021-09-01.csv new file mode 100644 index 000000000..eb35d815d --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2021-09-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2021-09-01 +ACCOUNT NUMBER,ACCOUNTS,"Sep 01, 2021" +,Assets, +,Cash and Bank, +,Patreon,"$1,528.39" +,Treasurer,$13.16 +,Total Cash and Bank,"$1,541.55" +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,"$1,541.55" +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$813.95 +,"Profit between Jan 1, 2021 and Sep 1, 2021",$727.60 +,Total Retained Earnings,"$1,541.55" +,Total Equity,"$1,541.55" diff --git a/finances/HaxeFlixel Balance Sheet 2021-10-01.csv b/finances/HaxeFlixel Balance Sheet 2021-10-01.csv new file mode 100644 index 000000000..e069378c7 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2021-10-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2021-10-01 +ACCOUNT NUMBER,ACCOUNTS,"Oct 01, 2021" +,Assets, +,Cash and Bank, +,Patreon,"$1,608.43" +,Treasurer,$13.16 +,Total Cash and Bank,"$1,621.59" +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,"$1,621.59" +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$813.95 +,"Profit between Jan 1, 2021 and Oct 1, 2021",$807.64 +,Total Retained Earnings,"$1,621.59" +,Total Equity,"$1,621.59" diff --git a/finances/HaxeFlixel Balance Sheet 2021-11-01.csv b/finances/HaxeFlixel Balance Sheet 2021-11-01.csv new file mode 100644 index 000000000..7090b72b9 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2021-11-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2021-11-01 +ACCOUNT NUMBER,ACCOUNTS,"Nov 01, 2021" +,Assets, +,Cash and Bank, +,Patreon,"$1,688.56" +,Treasurer,$13.16 +,Total Cash and Bank,"$1,701.72" +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,"$1,701.72" +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$813.95 +,"Profit between Jan 1, 2021 and Nov 1, 2021",$887.77 +,Total Retained Earnings,"$1,701.72" +,Total Equity,"$1,701.72" diff --git a/finances/HaxeFlixel Balance Sheet 2021-12-01.csv b/finances/HaxeFlixel Balance Sheet 2021-12-01.csv new file mode 100644 index 000000000..10213df48 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2021-12-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2021-12-01 +ACCOUNT NUMBER,ACCOUNTS,"Dec 01, 2021" +,Assets, +,Cash and Bank, +,Patreon,"$1,768.68" +,Treasurer,$13.16 +,Total Cash and Bank,"$1,781.84" +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,"$1,781.84" +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,$813.95 +,"Profit between Jan 1, 2021 and Dec 1, 2021",$967.89 +,Total Retained Earnings,"$1,781.84" +,Total Equity,"$1,781.84" diff --git a/finances/HaxeFlixel Balance Sheet 2022-01-01.csv b/finances/HaxeFlixel Balance Sheet 2022-01-01.csv new file mode 100644 index 000000000..6b417df65 --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2022-01-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2022-01-01 +ACCOUNT NUMBER,ACCOUNTS,"Jan 01, 2022" +,Assets, +,Cash and Bank, +,Patreon,"$1,848.79" +,Treasurer,$13.16 +,Total Cash and Bank,"$1,861.95" +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,"$1,861.95" +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,"$1,781.84" +,"Profit between Jan 1, 2022 and Jan 1, 2022",$80.11 +,Total Retained Earnings,"$1,861.95" +,Total Equity,"$1,861.95" diff --git a/finances/HaxeFlixel Balance Sheet 2022-02-01.csv b/finances/HaxeFlixel Balance Sheet 2022-02-01.csv new file mode 100644 index 000000000..f0613c7df --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2022-02-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2022-02-01 +ACCOUNT NUMBER,ACCOUNTS,"Feb 01, 2022" +,Assets, +,Cash and Bank, +,Patreon,"$1,928.92" +,Treasurer,$13.16 +,Total Cash and Bank,"$1,942.08" +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,"$1,942.08" +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,"$1,781.84" +,"Profit between Jan 1, 2022 and Feb 1, 2022",$160.24 +,Total Retained Earnings,"$1,942.08" +,Total Equity,"$1,942.08" diff --git a/finances/HaxeFlixel Balance Sheet 2022-03-01.csv b/finances/HaxeFlixel Balance Sheet 2022-03-01.csv new file mode 100644 index 000000000..c165eb34b --- /dev/null +++ b/finances/HaxeFlixel Balance Sheet 2022-03-01.csv @@ -0,0 +1,26 @@ +Balance Sheet +HaxeFlixel +As of 2022-03-01 +ACCOUNT NUMBER,ACCOUNTS,"Mar 01, 2022" +,Assets, +,Cash and Bank, +,Patreon,"$2,009.03" +,Treasurer,$13.16 +,Total Cash and Bank,"$2,022.19" +,Other Current Assets, +,Total Other Current Assets,$0.00 +,Long-term Assets, +,Total Long-term Assets,$0.00 +,Total Assets,"$2,022.19" +,Liabilities, +,Current Liabilities, +,Total Current Liabilities,$0.00 +,Long-term Liabilities, +,Total Long-term Liabilities,$0.00 +,Total Liabilities,$0.00 +,Equity, +,Retained Earnings, +,Profit for all prior years,"$1,781.84" +,"Profit between Jan 1, 2022 and Mar 1, 2022",$240.35 +,Total Retained Earnings,"$2,022.19" +,Total Equity,"$2,022.19" diff --git a/finances/HaxeFlixel Detailed General Ledger from 2015-06-01 to 2015-06-30.csv b/finances/HaxeFlixel Detailed General Ledger from 2015-06-01 to 2015-06-30.csv new file mode 100644 index 000000000..7574f38d1 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2015-06-01 to 2015-06-30.csv @@ -0,0 +1,23 @@ +date,transaction,debit,credit +Patreon,,, +"June 1, 2015",Expense - Patreon Fees,0.00,5.00 +"June 1, 2015",Expense - CC Fees,0.00,4.41 +"June 1, 2015",Income - Patreon Donations,100.00,0.00 +Total Patreon,,100.00,9.41 +Net Movement,,,90.59 +,,, +Patreon Donations,,, +"June 1, 2015",Income - Patreon Donations,0.00,100.00 +Total Patreon Donations,,0.00,100.00 +Net Movement,,,100.00 +,,, +Payment Fees,,, +"June 1, 2015",Expense - CC Fees,4.41,0.00 +Total Payment Fees,,4.41,0.00 +Net Movement,,,4.41 +,,, +Patreon Fees,,, +"June 1, 2015",Expense - Patreon Fees,5.00,0.00 +Total Patreon Fees,,5.00,0.00 +Net Movement,,,5.00 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2015-07-01 to 2015-07-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2015-07-01 to 2015-07-31.csv new file mode 100644 index 000000000..f2a1de27b --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2015-07-01 to 2015-07-31.csv @@ -0,0 +1,53 @@ +date,transaction,debit,credit +Patreon,,, +"July 11, 2015",Transfer to Treasurer,0.00,159.96 +"July 1, 2015",Income - Patreon Donations,107.00,0.00 +"July 1, 2015",Expense - CC Fees,0.00,5.07 +"July 1, 2015",Expense - Patreon Fees,0.00,5.35 +"July 1, 2015",Expense - Donation to Thorbjørn Lindeijer (https://www.patreon.com/bjorn),0.00,5.00 +Total Patreon,,107.00,175.38 +Net Movement,,,(68.38) +,,, +Treasurer,,, +"July 11, 2015",Transfer from Patreon,159.96,0.00 +"July 11, 2015",Expense - Transfer to Chris Decoster (impaler),0.00,39.99 +"July 11, 2015",Expense - Paypal Transfer Fees,0.00,0.40 +"July 11, 2015",Expense - US Taxes (25% of 159.96),0.00,39.99 +"July 13, 2015",Expense - PayPal Fees,0.00,0.40 +"July 13, 2015",Expense - Transfer to Justo Delgado for OpenFL shader API improvements,0.00,79.18 +Total Treasurer,,159.96,159.96 +Net Movement,,,0.00 +,,, +Patreon Donations,,, +"July 1, 2015",Income - Patreon Donations,0.00,107.00 +Total Patreon Donations,,0.00,107.00 +Net Movement,,,107.00 +,,, +Payment Fees,,, +"July 11, 2015",Expense - Paypal Transfer Fees,0.40,0.00 +"July 13, 2015",Expense - PayPal Fees,0.40,0.00 +"July 1, 2015",Expense - CC Fees,5.07,0.00 +Total Payment Fees,,5.87,0.00 +Net Movement,,,5.87 +,,, +Patreon Fees,,, +"July 1, 2015",Expense - Patreon Fees,5.35,0.00 +Total Patreon Fees,,5.35,0.00 +Net Movement,,,5.35 +,,, +Website Maintenance,,, +"July 11, 2015",Expense - Transfer to Chris Decoster (impaler),39.99,0.00 +Total Website Maintenance,,39.99,0.00 +Net Movement,,,39.99 +,,, +Tax Fees,,, +"July 11, 2015",Expense - US Taxes (25% of 159.96),39.99,0.00 +Total Tax Fees,,39.99,0.00 +Net Movement,,,39.99 +,,, +Development Services,,, +"July 13, 2015",Expense - Transfer to Justo Delgado for OpenFL shader API improvements,79.18,0.00 +"July 1, 2015",Expense - Donation to Thorbjørn Lindeijer (https://www.patreon.com/bjorn),5.00,0.00 +Total Development Services,,84.18,0.00 +Net Movement,,,84.18 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2015-08-01 to 2015-08-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2015-08-01 to 2015-08-31.csv new file mode 100644 index 000000000..e7a5744a4 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2015-08-01 to 2015-08-31.csv @@ -0,0 +1,29 @@ +date,transaction,debit,credit +Patreon,,, +"Aug. 1, 2015",Expense - Donation to Thorbjørn Lindeijer (https://www.patreon.com/bjorn),0.00,5.00 +"Aug. 1, 2015",Income - Patreon Donations,108.00,0.00 +"Aug. 1, 2015",Expense - Patreon Fees,0.00,5.40 +"Aug. 3, 2015",Expense - CC Fees,0.00,4.95 +Total Patreon,,108.00,15.35 +Net Movement,,,92.65 +,,, +Patreon Donations,,, +"Aug. 1, 2015",Income - Patreon Donations,0.00,108.00 +Total Patreon Donations,,0.00,108.00 +Net Movement,,,108.00 +,,, +Payment Fees,,, +"Aug. 3, 2015",Expense - CC Fees,4.95,0.00 +Total Payment Fees,,4.95,0.00 +Net Movement,,,4.95 +,,, +Patreon Fees,,, +"Aug. 1, 2015",Expense - Patreon Fees,5.40,0.00 +Total Patreon Fees,,5.40,0.00 +Net Movement,,,5.40 +,,, +Development Services,,, +"Aug. 1, 2015",Expense - Donation to Thorbjørn Lindeijer (https://www.patreon.com/bjorn),5.00,0.00 +Total Development Services,,5.00,0.00 +Net Movement,,,5.00 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2015-09-01 to 2015-09-30.csv b/finances/HaxeFlixel Detailed General Ledger from 2015-09-01 to 2015-09-30.csv new file mode 100644 index 000000000..bcba26634 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2015-09-01 to 2015-09-30.csv @@ -0,0 +1,23 @@ +date,transaction,debit,credit +Patreon,,, +"Sept. 1, 2015",Income - Patreon Donations,100.00,0.00 +"Sept. 1, 2015",Expense - CC Fees,0.00,4.23 +"Sept. 1, 2015",Expense - Patreon Fees,0.00,5.00 +Total Patreon,,100.00,9.23 +Net Movement,,,90.77 +,,, +Patreon Donations,,, +"Sept. 1, 2015",Income - Patreon Donations,0.00,100.00 +Total Patreon Donations,,0.00,100.00 +Net Movement,,,100.00 +,,, +Payment Fees,,, +"Sept. 1, 2015",Expense - CC Fees,4.23,0.00 +Total Payment Fees,,4.23,0.00 +Net Movement,,,4.23 +,,, +Patreon Fees,,, +"Sept. 1, 2015",Expense - Patreon Fees,5.00,0.00 +Total Patreon Fees,,5.00,0.00 +Net Movement,,,5.00 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2015-10-01 to 2015-10-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2015-10-01 to 2015-10-31.csv new file mode 100644 index 000000000..cf24233bc --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2015-10-01 to 2015-10-31.csv @@ -0,0 +1,23 @@ +date,transaction,debit,credit +Patreon,,, +"Oct. 1, 2015",Income - Patreon Donations,100.00,0.00 +"Oct. 1, 2015",Expense - Patreon Fees,0.00,5.00 +"Oct. 1, 2015",Expense - CC Fees,0.00,4.30 +Total Patreon,,100.00,9.30 +Net Movement,,,90.70 +,,, +Patreon Donations,,, +"Oct. 1, 2015",Income - Patreon Donations,0.00,100.00 +Total Patreon Donations,,0.00,100.00 +Net Movement,,,100.00 +,,, +Payment Fees,,, +"Oct. 1, 2015",Expense - CC Fees,4.30,0.00 +Total Payment Fees,,4.30,0.00 +Net Movement,,,4.30 +,,, +Patreon Fees,,, +"Oct. 1, 2015",Expense - Patreon Fees,5.00,0.00 +Total Patreon Fees,,5.00,0.00 +Net Movement,,,5.00 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2015-11-01 to 2015-11-30.csv b/finances/HaxeFlixel Detailed General Ledger from 2015-11-01 to 2015-11-30.csv new file mode 100644 index 000000000..8b80607ea --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2015-11-01 to 2015-11-30.csv @@ -0,0 +1,23 @@ +date,transaction,debit,credit +Patreon,,, +"Nov. 1, 2015",Income - Patreon Donations,118.00,0.00 +"Nov. 1, 2015",Expense - CC Fees,0.00,5.72 +"Nov. 1, 2015",Expense - Patreon Fees,0.00,5.90 +Total Patreon,,118.00,11.62 +Net Movement,,,106.38 +,,, +Patreon Donations,,, +"Nov. 1, 2015",Income - Patreon Donations,0.00,118.00 +Total Patreon Donations,,0.00,118.00 +Net Movement,,,118.00 +,,, +Payment Fees,,, +"Nov. 1, 2015",Expense - CC Fees,5.72,0.00 +Total Payment Fees,,5.72,0.00 +Net Movement,,,5.72 +,,, +Patreon Fees,,, +"Nov. 1, 2015",Expense - Patreon Fees,5.90,0.00 +Total Patreon Fees,,5.90,0.00 +Net Movement,,,5.90 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2015-12-01 to 2015-12-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2015-12-01 to 2015-12-31.csv new file mode 100644 index 000000000..badbe6169 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2015-12-01 to 2015-12-31.csv @@ -0,0 +1,23 @@ +date,transaction,debit,credit +Patreon,,, +"Dec. 1, 2015",Income - Patreon Donations,125.00,0.00 +"Dec. 1, 2015",Expense - CC Fees,0.00,6.08 +"Dec. 1, 2015",Expense - Patreon Fees,0.00,6.25 +Total Patreon,,125.00,12.33 +Net Movement,,,112.67 +,,, +Patreon Donations,,, +"Dec. 1, 2015",Income - Patreon Donations,0.00,125.00 +Total Patreon Donations,,0.00,125.00 +Net Movement,,,125.00 +,,, +Payment Fees,,, +"Dec. 1, 2015",Expense - CC Fees,6.08,0.00 +Total Payment Fees,,6.08,0.00 +Net Movement,,,6.08 +,,, +Patreon Fees,,, +"Dec. 1, 2015",Expense - Patreon Fees,6.25,0.00 +Total Patreon Fees,,6.25,0.00 +Net Movement,,,6.25 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2016-01-01 to 2016-01-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2016-01-01 to 2016-01-31.csv new file mode 100644 index 000000000..d38857e0b --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2016-01-01 to 2016-01-31.csv @@ -0,0 +1,41 @@ +date,transaction,debit,credit +Patreon,,, +"Jan. 1, 2016",Expense - Patreon Fees,0.00,6.50 +"Jan. 1, 2016",Expense - CC Fees,0.00,6.16 +"Jan. 22, 2016",Transfer to Treasurer,0.00,632.56 +"Jan. 1, 2016",Income - Patreon Donations,130.00,0.00 +Total Patreon,,130.00,645.22 +Net Movement,,,(515.22) +,,, +Treasurer,,, +"Jan. 22, 2016",Transfer from Patreon,632.56,0.00 +"Jan. 22, 2016",Expense - US Taxes (25% of 632.56),0.00,158.14 +"Jan. 22, 2016",Expense - Donation to Jeff Ward (http://jcward.com/),0.00,100.00 +Total Treasurer,,632.56,258.14 +Net Movement,,,374.42 +,,, +Patreon Donations,,, +"Jan. 1, 2016",Income - Patreon Donations,0.00,130.00 +Total Patreon Donations,,0.00,130.00 +Net Movement,,,130.00 +,,, +Payment Fees,,, +"Jan. 1, 2016",Expense - CC Fees,6.16,0.00 +Total Payment Fees,,6.16,0.00 +Net Movement,,,6.16 +,,, +Patreon Fees,,, +"Jan. 1, 2016",Expense - Patreon Fees,6.50,0.00 +Total Patreon Fees,,6.50,0.00 +Net Movement,,,6.50 +,,, +Tax Fees,,, +"Jan. 22, 2016",Expense - US Taxes (25% of 632.56),158.14,0.00 +Total Tax Fees,,158.14,0.00 +Net Movement,,,158.14 +,,, +Development Services,,, +"Jan. 22, 2016",Expense - Donation to Jeff Ward (http://jcward.com/),100.00,0.00 +Total Development Services,,100.00,0.00 +Net Movement,,,100.00 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2016-02-01 to 2016-02-29.csv b/finances/HaxeFlixel Detailed General Ledger from 2016-02-01 to 2016-02-29.csv new file mode 100644 index 000000000..42c64fcc5 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2016-02-01 to 2016-02-29.csv @@ -0,0 +1,23 @@ +date,transaction,debit,credit +Patreon,,, +"Feb. 1, 2016",Expense - Patreon Fees,0.00,6.50 +"Feb. 1, 2016",Expense - CC Fees,0.00,5.85 +"Feb. 1, 2016",Income - Patreon Donations,130.00,0.00 +Total Patreon,,130.00,12.35 +Net Movement,,,117.65 +,,, +Patreon Donations,,, +"Feb. 1, 2016",Income - Patreon Donations,0.00,130.00 +Total Patreon Donations,,0.00,130.00 +Net Movement,,,130.00 +,,, +Payment Fees,,, +"Feb. 1, 2016",Expense - CC Fees,5.85,0.00 +Total Payment Fees,,5.85,0.00 +Net Movement,,,5.85 +,,, +Patreon Fees,,, +"Feb. 1, 2016",Expense - Patreon Fees,6.50,0.00 +Total Patreon Fees,,6.50,0.00 +Net Movement,,,6.50 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2016-03-01 to 2016-03-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2016-03-01 to 2016-03-31.csv new file mode 100644 index 000000000..b0e0909f7 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2016-03-01 to 2016-03-31.csv @@ -0,0 +1,35 @@ +date,transaction,debit,credit +Patreon,,, +"March 1, 2016",Expense - CC Fees,0.00,6.38 +"March 1, 2016",Income - Patreon Donations,140.00,0.00 +"March 1, 2016",Expense - Patreon Fees,0.00,7.00 +Total Patreon,,140.00,13.38 +Net Movement,,,126.62 +,,, +Treasurer,,, +"March 15, 2016",Expense - Donation to Mika Palmu (FlashDevelop) for work improving HaxeFlixel Setup,0.00,150.00 +"March 15, 2016",Expense - PayPal Transfer Fee,0.00,0.75 +Total Treasurer,,0.00,150.75 +Net Movement,,,(150.75) +,,, +Patreon Donations,,, +"March 1, 2016",Income - Patreon Donations,0.00,140.00 +Total Patreon Donations,,0.00,140.00 +Net Movement,,,140.00 +,,, +Payment Fees,,, +"March 1, 2016",Expense - CC Fees,6.38,0.00 +"March 15, 2016",Expense - PayPal Transfer Fee,0.75,0.00 +Total Payment Fees,,7.13,0.00 +Net Movement,,,7.13 +,,, +Patreon Fees,,, +"March 1, 2016",Expense - Patreon Fees,7.00,0.00 +Total Patreon Fees,,7.00,0.00 +Net Movement,,,7.00 +,,, +Development Services,,, +"March 15, 2016",Expense - Donation to Mika Palmu (FlashDevelop) for work improving HaxeFlixel Setup,150.00,0.00 +Total Development Services,,150.00,0.00 +Net Movement,,,150.00 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2016-04-01 to 2016-04-30.csv b/finances/HaxeFlixel Detailed General Ledger from 2016-04-01 to 2016-04-30.csv new file mode 100644 index 000000000..a8f59e18d --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2016-04-01 to 2016-04-30.csv @@ -0,0 +1,23 @@ +date,transaction,debit,credit +Patreon,,, +"April 1, 2016",Income - Patreon Donations,151.00,0.00 +"April 1, 2016",Expense - Patreon Fees,0.00,7.55 +"April 1, 2016",Expense - CC Fees,0.00,7.00 +Total Patreon,,151.00,14.55 +Net Movement,,,136.45 +,,, +Patreon Donations,,, +"April 1, 2016",Income - Patreon Donations,0.00,151.00 +Total Patreon Donations,,0.00,151.00 +Net Movement,,,151.00 +,,, +Payment Fees,,, +"April 1, 2016",Expense - CC Fees,7.00,0.00 +Total Payment Fees,,7.00,0.00 +Net Movement,,,7.00 +,,, +Patreon Fees,,, +"April 1, 2016",Expense - Patreon Fees,7.55,0.00 +Total Patreon Fees,,7.55,0.00 +Net Movement,,,7.55 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2016-05-01 to 2016-05-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2016-05-01 to 2016-05-31.csv new file mode 100644 index 000000000..94237ad3f --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2016-05-01 to 2016-05-31.csv @@ -0,0 +1,35 @@ +date,transaction,debit,credit +Patreon,,, +"May 1, 2016",Income - Patreon Donations,153.16,0.00 +"May 1, 2016",Expense - CC Fees,0.00,7.09 +"May 2, 2016",Expense - Patreon Fees,0.00,7.66 +Total Patreon,,153.16,14.75 +Net Movement,,,138.41 +,,, +Treasurer,,, +"May 2, 2016",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,96.77,0.00 +"May 31, 2016",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,26.31,0.00 +Total Treasurer,,123.08,0.00 +Net Movement,,,123.08 +,,, +Patreon Donations,,, +"May 1, 2016",Income - Patreon Donations,0.00,153.16 +Total Patreon Donations,,0.00,153.16 +Net Movement,,,153.16 +,,, +Book Sales,,, +"May 2, 2016",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,0.00,96.77 +"May 31, 2016",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,0.00,26.31 +Total Book Sales,,0.00,123.08 +Net Movement,,,123.08 +,,, +Payment Fees,,, +"May 1, 2016",Expense - CC Fees,7.09,0.00 +Total Payment Fees,,7.09,0.00 +Net Movement,,,7.09 +,,, +Patreon Fees,,, +"May 2, 2016",Expense - Patreon Fees,7.66,0.00 +Total Patreon Fees,,7.66,0.00 +Net Movement,,,7.66 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2016-06-01 to 2016-06-30.csv b/finances/HaxeFlixel Detailed General Ledger from 2016-06-01 to 2016-06-30.csv new file mode 100644 index 000000000..5d7f1d80e --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2016-06-01 to 2016-06-30.csv @@ -0,0 +1,33 @@ +date,transaction,debit,credit +Patreon,,, +"June 1, 2016",Income - Patreon Donations,160.16,0.00 +"June 1, 2016",Expense - CC Fees,0.00,7.50 +"June 1, 2016",Expense - Patreon Fees,0.00,8.01 +Total Patreon,,160.16,15.51 +Net Movement,,,144.65 +,,, +Treasurer,,, +"June 29, 2016",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,11.73,0.00 +Total Treasurer,,11.73,0.00 +Net Movement,,,11.73 +,,, +Patreon Donations,,, +"June 1, 2016",Income - Patreon Donations,0.00,160.16 +Total Patreon Donations,,0.00,160.16 +Net Movement,,,160.16 +,,, +Book Sales,,, +"June 29, 2016",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,0.00,11.73 +Total Book Sales,,0.00,11.73 +Net Movement,,,11.73 +,,, +Payment Fees,,, +"June 1, 2016",Expense - CC Fees,7.50,0.00 +Total Payment Fees,,7.50,0.00 +Net Movement,,,7.50 +,,, +Patreon Fees,,, +"June 1, 2016",Expense - Patreon Fees,8.01,0.00 +Total Patreon Fees,,8.01,0.00 +Net Movement,,,8.01 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2016-07-01 to 2016-07-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2016-07-01 to 2016-07-31.csv new file mode 100644 index 000000000..c6b589277 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2016-07-01 to 2016-07-31.csv @@ -0,0 +1,23 @@ +date,transaction,debit,credit +Patreon,,, +"July 1, 2016",Income - Patreon Donations,164.16,0.00 +"July 1, 2016",Expense - Patreon Fees,0.00,8.21 +"July 1, 2016",Expense - Processing Fees,0.00,7.93 +Total Patreon,,164.16,16.14 +Net Movement,,,148.02 +,,, +Patreon Donations,,, +"July 1, 2016",Income - Patreon Donations,0.00,164.16 +Total Patreon Donations,,0.00,164.16 +Net Movement,,,164.16 +,,, +Payment Fees,,, +"July 1, 2016",Expense - Processing Fees,7.93,0.00 +Total Payment Fees,,7.93,0.00 +Net Movement,,,7.93 +,,, +Patreon Fees,,, +"July 1, 2016",Expense - Patreon Fees,8.21,0.00 +Total Patreon Fees,,8.21,0.00 +Net Movement,,,8.21 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2016-08-01 to 2016-08-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2016-08-01 to 2016-08-31.csv new file mode 100644 index 000000000..67c3d0237 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2016-08-01 to 2016-08-31.csv @@ -0,0 +1,33 @@ +date,transaction,debit,credit +Patreon,,, +"Aug. 1, 2016",Income - Patreon Donations,187.00,0.00 +"Aug. 1, 2016",Expense - Processing Fees,0.00,8.76 +"Aug. 1, 2016",Expense - Patreon Fees,0.00,9.35 +Total Patreon,,187.00,18.11 +Net Movement,,,168.89 +,,, +Treasurer,,, +"Aug. 9, 2016",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,11.69,0.00 +Total Treasurer,,11.69,0.00 +Net Movement,,,11.69 +,,, +Patreon Donations,,, +"Aug. 1, 2016",Income - Patreon Donations,0.00,187.00 +Total Patreon Donations,,0.00,187.00 +Net Movement,,,187.00 +,,, +Book Sales,,, +"Aug. 9, 2016",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,0.00,11.69 +Total Book Sales,,0.00,11.69 +Net Movement,,,11.69 +,,, +Payment Fees,,, +"Aug. 1, 2016",Expense - Processing Fees,8.76,0.00 +Total Payment Fees,,8.76,0.00 +Net Movement,,,8.76 +,,, +Patreon Fees,,, +"Aug. 1, 2016",Expense - Patreon Fees,9.35,0.00 +Total Patreon Fees,,9.35,0.00 +Net Movement,,,9.35 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2016-09-01 to 2016-09-30.csv b/finances/HaxeFlixel Detailed General Ledger from 2016-09-01 to 2016-09-30.csv new file mode 100644 index 000000000..dfb6ad7c0 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2016-09-01 to 2016-09-30.csv @@ -0,0 +1,41 @@ +date,transaction,debit,credit +Patreon,,, +"Sept. 1, 2016",Income - Patreon Donations,179.00,0.00 +"Sept. 1, 2016",Expense - Processing Fees,0.00,8.11 +"Sept. 1, 2016",Expense - Patreon Fees,0.00,8.95 +Total Patreon,,179.00,17.06 +Net Movement,,,161.94 +,,, +Treasurer,,, +"Sept. 4, 2016",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,17.58,0.00 +"Sept. 28, 2016",Expense - PayPal Transfer Fee,0.00,0.25 +"Sept. 28, 2016",Expense - Bounty claimed by PeyTy (https://github.com/HaxeFlixel/flixel/issues/1753),0.00,50.00 +Total Treasurer,,17.58,50.25 +Net Movement,,,(32.67) +,,, +Patreon Donations,,, +"Sept. 1, 2016",Income - Patreon Donations,0.00,179.00 +Total Patreon Donations,,0.00,179.00 +Net Movement,,,179.00 +,,, +Book Sales,,, +"Sept. 4, 2016",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,0.00,17.58 +Total Book Sales,,0.00,17.58 +Net Movement,,,17.58 +,,, +Payment Fees,,, +"Sept. 28, 2016",Expense - PayPal Transfer Fee,0.25,0.00 +"Sept. 1, 2016",Expense - Processing Fees,8.11,0.00 +Total Payment Fees,,8.36,0.00 +Net Movement,,,8.36 +,,, +Patreon Fees,,, +"Sept. 1, 2016",Expense - Patreon Fees,8.95,0.00 +Total Patreon Fees,,8.95,0.00 +Net Movement,,,8.95 +,,, +Development Services,,, +"Sept. 28, 2016",Expense - Bounty claimed by PeyTy (https://github.com/HaxeFlixel/flixel/issues/1753),50.00,0.00 +Total Development Services,,50.00,0.00 +Net Movement,,,50.00 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2016-10-01 to 2016-10-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2016-10-01 to 2016-10-31.csv new file mode 100644 index 000000000..425b39b1d --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2016-10-01 to 2016-10-31.csv @@ -0,0 +1,33 @@ +date,transaction,debit,credit +Patreon,,, +"Oct. 1, 2016",Income - Patreon Donations,178.00,0.00 +"Oct. 1, 2016",Expense - Patreon Fees,0.00,8.90 +"Oct. 1, 2016",Expense - Processing Fees,0.00,8.01 +Total Patreon,,178.00,16.91 +Net Movement,,,161.09 +,,, +Treasurer,,, +"Oct. 31, 2016",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,46.72,0.00 +Total Treasurer,,46.72,0.00 +Net Movement,,,46.72 +,,, +Patreon Donations,,, +"Oct. 1, 2016",Income - Patreon Donations,0.00,178.00 +Total Patreon Donations,,0.00,178.00 +Net Movement,,,178.00 +,,, +Book Sales,,, +"Oct. 31, 2016",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,0.00,46.72 +Total Book Sales,,0.00,46.72 +Net Movement,,,46.72 +,,, +Payment Fees,,, +"Oct. 1, 2016",Expense - Processing Fees,8.01,0.00 +Total Payment Fees,,8.01,0.00 +Net Movement,,,8.01 +,,, +Patreon Fees,,, +"Oct. 1, 2016",Expense - Patreon Fees,8.90,0.00 +Total Patreon Fees,,8.90,0.00 +Net Movement,,,8.90 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2016-11-01 to 2016-11-30.csv b/finances/HaxeFlixel Detailed General Ledger from 2016-11-01 to 2016-11-30.csv new file mode 100644 index 000000000..eaef37e77 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2016-11-01 to 2016-11-30.csv @@ -0,0 +1,23 @@ +date,transaction,debit,credit +Patreon,,, +"Nov. 1, 2016",Income - Patreon Donations,173.00,0.00 +"Nov. 1, 2016",Expense - Processing Fees,0.00,8.01 +"Nov. 1, 2016",Expense - Patreon Fees,0.00,8.65 +Total Patreon,,173.00,16.66 +Net Movement,,,156.34 +,,, +Patreon Donations,,, +"Nov. 1, 2016",Income - Patreon Donations,0.00,173.00 +Total Patreon Donations,,0.00,173.00 +Net Movement,,,173.00 +,,, +Payment Fees,,, +"Nov. 1, 2016",Expense - Processing Fees,8.01,0.00 +Total Payment Fees,,8.01,0.00 +Net Movement,,,8.01 +,,, +Patreon Fees,,, +"Nov. 1, 2016",Expense - Patreon Fees,8.65,0.00 +Total Patreon Fees,,8.65,0.00 +Net Movement,,,8.65 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2016-12-01 to 2016-12-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2016-12-01 to 2016-12-31.csv new file mode 100644 index 000000000..b69b8dccd --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2016-12-01 to 2016-12-31.csv @@ -0,0 +1,33 @@ +date,transaction,debit,credit +Patreon,,, +"Dec. 1, 2016",Income - Patreon Donations,173.00,0.00 +"Dec. 1, 2016",Expense - Processing Fees,0.00,7.77 +"Dec. 1, 2016",Expense - Patreon Fees,0.00,8.65 +Total Patreon,,173.00,16.42 +Net Movement,,,156.58 +,,, +Treasurer,,, +"Dec. 30, 2016",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,29.28,0.00 +Total Treasurer,,29.28,0.00 +Net Movement,,,29.28 +,,, +Patreon Donations,,, +"Dec. 1, 2016",Income - Patreon Donations,0.00,173.00 +Total Patreon Donations,,0.00,173.00 +Net Movement,,,173.00 +,,, +Book Sales,,, +"Dec. 30, 2016",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,0.00,29.28 +Total Book Sales,,0.00,29.28 +Net Movement,,,29.28 +,,, +Payment Fees,,, +"Dec. 1, 2016",Expense - Processing Fees,7.77,0.00 +Total Payment Fees,,7.77,0.00 +Net Movement,,,7.77 +,,, +Patreon Fees,,, +"Dec. 1, 2016",Expense - Patreon Fees,8.65,0.00 +Total Patreon Fees,,8.65,0.00 +Net Movement,,,8.65 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2017-01-01 to 2017-01-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2017-01-01 to 2017-01-31.csv new file mode 100644 index 000000000..27edd9b48 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2017-01-01 to 2017-01-31.csv @@ -0,0 +1,23 @@ +date,transaction,debit,credit +Patreon,,, +"Jan. 1, 2017",Income - Patreon Donations,168.00,0.00 +"Jan. 1, 2017",Expense - Processing Fees,0.00,7.29 +"Jan. 1, 2017",Expense - Patreon Fees,0.00,8.40 +Total Patreon,,168.00,15.69 +Net Movement,,,152.31 +,,, +Patreon Donations,,, +"Jan. 1, 2017",Income - Patreon Donations,0.00,168.00 +Total Patreon Donations,,0.00,168.00 +Net Movement,,,168.00 +,,, +Payment Fees,,, +"Jan. 1, 2017",Expense - Processing Fees,7.29,0.00 +Total Payment Fees,,7.29,0.00 +Net Movement,,,7.29 +,,, +Patreon Fees,,, +"Jan. 1, 2017",Expense - Patreon Fees,8.40,0.00 +Total Patreon Fees,,8.40,0.00 +Net Movement,,,8.40 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2017-02-01 to 2017-02-28.csv b/finances/HaxeFlixel Detailed General Ledger from 2017-02-01 to 2017-02-28.csv new file mode 100644 index 000000000..4a534061e --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2017-02-01 to 2017-02-28.csv @@ -0,0 +1,39 @@ +date,transaction,debit,credit +Patreon,,, +"Feb. 1, 2017",Income - Patreon Donations,157.00,0.00 +"Feb. 1, 2017",Expense - Processing Fees,0.00,6.97 +"Feb. 1, 2017",Expense - Patreon Fees,0.00,7.85 +Total Patreon,,157.00,14.82 +Net Movement,,,142.18 +,,, +Treasurer,,, +"Feb. 7, 2017",Expense - Donation to Jens Fischer (Gama11) for long term HaxeFlixel support,0.00,330.00 +"Feb. 25, 2017",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,29.70,0.00 +Total Treasurer,,29.70,330.00 +Net Movement,,,(300.30) +,,, +Patreon Donations,,, +"Feb. 1, 2017",Income - Patreon Donations,0.00,157.00 +Total Patreon Donations,,0.00,157.00 +Net Movement,,,157.00 +,,, +Book Sales,,, +"Feb. 25, 2017",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,0.00,29.70 +Total Book Sales,,0.00,29.70 +Net Movement,,,29.70 +,,, +Payment Fees,,, +"Feb. 1, 2017",Expense - Processing Fees,6.97,0.00 +Total Payment Fees,,6.97,0.00 +Net Movement,,,6.97 +,,, +Patreon Fees,,, +"Feb. 1, 2017",Expense - Patreon Fees,7.85,0.00 +Total Patreon Fees,,7.85,0.00 +Net Movement,,,7.85 +,,, +Development Services,,, +"Feb. 7, 2017",Expense - Donation to Jens Fischer (Gama11) for long term HaxeFlixel support,330.00,0.00 +Total Development Services,,330.00,0.00 +Net Movement,,,330.00 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2017-03-01 to 2017-03-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2017-03-01 to 2017-03-31.csv new file mode 100644 index 000000000..d87930205 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2017-03-01 to 2017-03-31.csv @@ -0,0 +1,23 @@ +date,transaction,debit,credit +Patreon,,, +"March 1, 2017",Income - Patreon Donations,156.00,0.00 +"March 1, 2017",Expense - Processing Fees,0.00,6.89 +"March 1, 2017",Expense - Patreon Fees,0.00,7.80 +Total Patreon,,156.00,14.69 +Net Movement,,,141.31 +,,, +Patreon Donations,,, +"March 1, 2017",Income - Patreon Donations,0.00,156.00 +Total Patreon Donations,,0.00,156.00 +Net Movement,,,156.00 +,,, +Payment Fees,,, +"March 1, 2017",Expense - Processing Fees,6.89,0.00 +Total Payment Fees,,6.89,0.00 +Net Movement,,,6.89 +,,, +Patreon Fees,,, +"March 1, 2017",Expense - Patreon Fees,7.80,0.00 +Total Patreon Fees,,7.80,0.00 +Net Movement,,,7.80 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2017-04-01 to 2017-04-30.csv b/finances/HaxeFlixel Detailed General Ledger from 2017-04-01 to 2017-04-30.csv new file mode 100644 index 000000000..ec5b46cf7 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2017-04-01 to 2017-04-30.csv @@ -0,0 +1,23 @@ +date,transaction,debit,credit +Patreon,,, +"April 1, 2017",Income - Patreon Donations,155.00,0.00 +"April 1, 2017",Expense - Processing Fees,0.00,7.39 +"April 1, 2017",Expense - Patreon Fees,0.00,7.75 +Total Patreon,,155.00,15.14 +Net Movement,,,139.86 +,,, +Patreon Donations,,, +"April 1, 2017",Income - Patreon Donations,0.00,155.00 +Total Patreon Donations,,0.00,155.00 +Net Movement,,,155.00 +,,, +Payment Fees,,, +"April 1, 2017",Expense - Processing Fees,7.39,0.00 +Total Payment Fees,,7.39,0.00 +Net Movement,,,7.39 +,,, +Patreon Fees,,, +"April 1, 2017",Expense - Patreon Fees,7.75,0.00 +Total Patreon Fees,,7.75,0.00 +Net Movement,,,7.75 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2017-05-01 to 2017-05-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2017-05-01 to 2017-05-31.csv new file mode 100644 index 000000000..1dd4d52b6 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2017-05-01 to 2017-05-31.csv @@ -0,0 +1,23 @@ +date,transaction,debit,credit +Patreon,,, +"May 1, 2017",Expense,0.00,7.32 +"May 1, 2017",Expense,0.00,7.70 +"May 1, 2017",Income - Patreon Donations,154.00,0.00 +Total Patreon,,154.00,15.02 +Net Movement,,,138.98 +,,, +Patreon Donations,,, +"May 1, 2017",Income - Patreon Donations,0.00,154.00 +Total Patreon Donations,,0.00,154.00 +Net Movement,,,154.00 +,,, +Payment Fees,,, +"May 1, 2017",Expense,7.32,0.00 +Total Payment Fees,,7.32,0.00 +Net Movement,,,7.32 +,,, +Patreon Fees,,, +"May 1, 2017",Expense,7.70,0.00 +Total Patreon Fees,,7.70,0.00 +Net Movement,,,7.70 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2017-06-01 to 2017-06-30.csv b/finances/HaxeFlixel Detailed General Ledger from 2017-06-01 to 2017-06-30.csv new file mode 100644 index 000000000..d0cbb7d03 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2017-06-01 to 2017-06-30.csv @@ -0,0 +1,33 @@ +date,transaction,debit,credit +Patreon,,, +"June 1, 2017",Income - Patreon Donations,147.00,0.00 +"June 1, 2017",Expense - Processing Fees,0.00,6.64 +"June 1, 2017",Expense - Patreon Fees,0.00,7.35 +Total Patreon,,147.00,13.99 +Net Movement,,,133.01 +,,, +Treasurer,,, +"June 29, 2017",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,26.19,0.00 +Total Treasurer,,26.19,0.00 +Net Movement,,,26.19 +,,, +Patreon Donations,,, +"June 1, 2017",Income - Patreon Donations,0.00,147.00 +Total Patreon Donations,,0.00,147.00 +Net Movement,,,147.00 +,,, +Book Sales,,, +"June 29, 2017",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,0.00,26.19 +Total Book Sales,,0.00,26.19 +Net Movement,,,26.19 +,,, +Payment Fees,,, +"June 1, 2017",Expense - Processing Fees,6.64,0.00 +Total Payment Fees,,6.64,0.00 +Net Movement,,,6.64 +,,, +Patreon Fees,,, +"June 1, 2017",Expense - Patreon Fees,7.35,0.00 +Total Patreon Fees,,7.35,0.00 +Net Movement,,,7.35 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2017-07-01 to 2017-07-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2017-07-01 to 2017-07-31.csv new file mode 100644 index 000000000..d1a473c31 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2017-07-01 to 2017-07-31.csv @@ -0,0 +1,23 @@ +date,transaction,debit,credit +Patreon,,, +"July 1, 2017",Income - Patreon Donations,148.00,0.00 +"July 1, 2017",Expense - Processing Fees,0.00,6.66 +"July 1, 2017",Expense - Patreon Fees,0.00,7.40 +Total Patreon,,148.00,14.06 +Net Movement,,,133.94 +,,, +Patreon Donations,,, +"July 1, 2017",Income - Patreon Donations,0.00,148.00 +Total Patreon Donations,,0.00,148.00 +Net Movement,,,148.00 +,,, +Payment Fees,,, +"July 1, 2017",Expense - Processing Fees,6.66,0.00 +Total Payment Fees,,6.66,0.00 +Net Movement,,,6.66 +,,, +Patreon Fees,,, +"July 1, 2017",Expense - Patreon Fees,7.40,0.00 +Total Patreon Fees,,7.40,0.00 +Net Movement,,,7.40 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2017-08-01 to 2017-08-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2017-08-01 to 2017-08-31.csv new file mode 100644 index 000000000..072990e02 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2017-08-01 to 2017-08-31.csv @@ -0,0 +1,47 @@ +date,transaction,debit,credit +Patreon,,, +"Aug. 1, 2017",Income - Patreon Donations,139.00,0.00 +"Aug. 1, 2017",Expense - Processing Fees,0.00,6.07 +"Aug. 1, 2017",Expense - Patreon Fees,0.00,6.95 +"Aug. 22, 2017",Transfer to Treasurer,0.00,"2,723.15" +Total Patreon,,139.00,"2,736.17" +Net Movement,,,"(2,597.17)" +,,, +Treasurer,,, +"Aug. 22, 2017",Transfer from Patreon,"2,723.15",0.00 +"Aug. 22, 2017",Expense - PayPal Transfer Fee,0.00,19.00 +"Aug. 26, 2017",Expense - Donation to msghero for blog post published on 08/26/2017,0.00,50.00 +"Aug. 22, 2017",Expense - US Income Taxes (25% of 2704.15),0.00,676.04 +Total Treasurer,,"2,723.15",745.04 +Net Movement,,,"1,978.11" +,,, +Patreon Donations,,, +"Aug. 1, 2017",Income - Patreon Donations,0.00,139.00 +Total Patreon Donations,,0.00,139.00 +Net Movement,,,139.00 +,,, +Payment Fees,,, +"Aug. 1, 2017",Expense - Processing Fees,6.07,0.00 +Total Payment Fees,,6.07,0.00 +Net Movement,,,6.07 +,,, +Patreon Fees,,, +"Aug. 1, 2017",Expense - Patreon Fees,6.95,0.00 +Total Patreon Fees,,6.95,0.00 +Net Movement,,,6.95 +,,, +PayPal Fee,,, +"Aug. 22, 2017",Expense - PayPal Transfer Fee,19.00,0.00 +Total PayPal Fee,,19.00,0.00 +Net Movement,,,19.00 +,,, +Tax Fees,,, +"Aug. 22, 2017",Expense - US Income Taxes (25% of 2704.15),676.04,0.00 +Total Tax Fees,,676.04,0.00 +Net Movement,,,676.04 +,,, +Development Services,,, +"Aug. 26, 2017",Expense - Donation to msghero for blog post published on 08/26/2017,50.00,0.00 +Total Development Services,,50.00,0.00 +Net Movement,,,50.00 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2017-09-01 to 2017-09-30.csv b/finances/HaxeFlixel Detailed General Ledger from 2017-09-01 to 2017-09-30.csv new file mode 100644 index 000000000..bd101ba1a --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2017-09-01 to 2017-09-30.csv @@ -0,0 +1,39 @@ +date,transaction,debit,credit +Patreon,,, +"Sept. 1, 2017",Income - Patreon Donations,139.00,0.00 +"Sept. 1, 2017",Expense - Processing Fees,0.00,6.17 +"Sept. 1, 2017",Expense - Patreon Fees,0.00,6.95 +Total Patreon,,139.00,13.12 +Net Movement,,,125.88 +,,, +Treasurer,,, +"Sept. 6, 2017",Expense - Donation to Tim Hely for sponsoring a 09/2017 game jam,0.00,150.00 +"Sept. 17, 2017",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,32.05,0.00 +Total Treasurer,,32.05,150.00 +Net Movement,,,(117.95) +,,, +Patreon Donations,,, +"Sept. 1, 2017",Income - Patreon Donations,0.00,139.00 +Total Patreon Donations,,0.00,139.00 +Net Movement,,,139.00 +,,, +Book Sales,,, +"Sept. 17, 2017",Income - Discover Haxeflixel Book Contributions from Leonardo Cavaletti,0.00,32.05 +Total Book Sales,,0.00,32.05 +Net Movement,,,32.05 +,,, +Payment Fees,,, +"Sept. 1, 2017",Expense - Processing Fees,6.17,0.00 +Total Payment Fees,,6.17,0.00 +Net Movement,,,6.17 +,,, +Patreon Fees,,, +"Sept. 1, 2017",Expense - Patreon Fees,6.95,0.00 +Total Patreon Fees,,6.95,0.00 +Net Movement,,,6.95 +,,, +Development Services,,, +"Sept. 6, 2017",Expense - Donation to Tim Hely for sponsoring a 09/2017 game jam,150.00,0.00 +Total Development Services,,150.00,0.00 +Net Movement,,,150.00 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2017-10-01 to 2017-10-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2017-10-01 to 2017-10-31.csv new file mode 100644 index 000000000..f63e7eafd --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2017-10-01 to 2017-10-31.csv @@ -0,0 +1,23 @@ +date,transaction,debit,credit +Patreon,,, +"Oct. 1, 2017",Income - Patreon Donations,139.00,0.00 +"Oct. 1, 2017",Expense - Processing Fees,0.00,6.17 +"Oct. 1, 2017",Expense - Patreon Fees,0.00,6.95 +Total Patreon,,139.00,13.12 +Net Movement,,,125.88 +,,, +Patreon Donations,,, +"Oct. 1, 2017",Income - Patreon Donations,0.00,139.00 +Total Patreon Donations,,0.00,139.00 +Net Movement,,,139.00 +,,, +Payment Fees,,, +"Oct. 1, 2017",Expense - Processing Fees,6.17,0.00 +Total Payment Fees,,6.17,0.00 +Net Movement,,,6.17 +,,, +Patreon Fees,,, +"Oct. 1, 2017",Expense - Patreon Fees,6.95,0.00 +Total Patreon Fees,,6.95,0.00 +Net Movement,,,6.95 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2017-11-01 to 2017-11-30.csv b/finances/HaxeFlixel Detailed General Ledger from 2017-11-01 to 2017-11-30.csv new file mode 100644 index 000000000..79d7da574 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2017-11-01 to 2017-11-30.csv @@ -0,0 +1,23 @@ +date,transaction,debit,credit +Patreon,,, +"Nov. 1, 2017",Income - Patreon Donations,134.00,0.00 +"Nov. 1, 2017",Expense - Processing Fees,0.00,5.86 +"Nov. 1, 2017",Expense - Patreon Fees,0.00,6.70 +Total Patreon,,134.00,12.56 +Net Movement,,,121.44 +,,, +Patreon Donations,,, +"Nov. 1, 2017",Income - Patreon Donations,0.00,134.00 +Total Patreon Donations,,0.00,134.00 +Net Movement,,,134.00 +,,, +Payment Fees,,, +"Nov. 1, 2017",Expense - Processing Fees,5.86,0.00 +Total Payment Fees,,5.86,0.00 +Net Movement,,,5.86 +,,, +Patreon Fees,,, +"Nov. 1, 2017",Expense - Patreon Fees,6.70,0.00 +Total Patreon Fees,,6.70,0.00 +Net Movement,,,6.70 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2017-12-01 to 2017-12-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2017-12-01 to 2017-12-31.csv new file mode 100644 index 000000000..d04ac1233 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2017-12-01 to 2017-12-31.csv @@ -0,0 +1,23 @@ +date,transaction,debit,credit +Patreon,,, +"Dec. 1, 2017",Income - Patreon Donations,129.00,0.00 +"Dec. 1, 2017",Expense - Processing Fees,0.00,5.55 +"Dec. 1, 2017",Expense - Patreon Fees,0.00,6.45 +Total Patreon,,129.00,12.00 +Net Movement,,,117.00 +,,, +Patreon Donations,,, +"Dec. 1, 2017",Income - Patreon Donations,0.00,129.00 +Total Patreon Donations,,0.00,129.00 +Net Movement,,,129.00 +,,, +Payment Fees,,, +"Dec. 1, 2017",Expense - Processing Fees,5.55,0.00 +Total Payment Fees,,5.55,0.00 +Net Movement,,,5.55 +,,, +Patreon Fees,,, +"Dec. 1, 2017",Expense - Patreon Fees,6.45,0.00 +Total Patreon Fees,,6.45,0.00 +Net Movement,,,6.45 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2018-01-01 to 2018-01-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2018-01-01 to 2018-01-31.csv new file mode 100644 index 000000000..9a46974f0 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2018-01-01 to 2018-01-31.csv @@ -0,0 +1,33 @@ +date,transaction,debit,credit +Patreon,,, +"Jan. 1, 2018",Income - Patreon Donations,128.70,0.00 +"Jan. 1, 2018",Expense - Processing Fees,0.00,5.06 +"Jan. 1, 2018",Expense - Patreon Fees,0.00,6.44 +Total Patreon,,128.70,11.50 +Net Movement,,,117.20 +,,, +Treasurer,,, +"Jan. 20, 2018",Expense - MsgHero receivable,0.00,300.00 +Total Treasurer,,0.00,300.00 +Net Movement,,,(300.00) +,,, +Patreon Donations,,, +"Jan. 1, 2018",Income - Patreon Donations,0.00,128.70 +Total Patreon Donations,,0.00,128.70 +Net Movement,,,128.70 +,,, +Payment Fees,,, +"Jan. 1, 2018",Expense - Processing Fees,5.06,0.00 +Total Payment Fees,,5.06,0.00 +Net Movement,,,5.06 +,,, +Patreon Fees,,, +"Jan. 1, 2018",Expense - Patreon Fees,6.44,0.00 +Total Patreon Fees,,6.44,0.00 +Net Movement,,,6.44 +,,, +Development Services,,, +"Jan. 20, 2018",Expense - MsgHero receivable,300.00,0.00 +Total Development Services,,300.00,0.00 +Net Movement,,,300.00 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2018-02-01 to 2018-02-28.csv b/finances/HaxeFlixel Detailed General Ledger from 2018-02-01 to 2018-02-28.csv new file mode 100644 index 000000000..638993a08 --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2018-02-01 to 2018-02-28.csv @@ -0,0 +1,23 @@ +date,transaction,debit,credit +Patreon,,, +"Feb. 1, 2018",Income - Patreon Donations,128.70,0.00 +"Feb. 1, 2018",Expense - Processing Fees,0.00,5.01 +"Feb. 1, 2018",Expense - Patreon Fees,0.00,6.44 +Total Patreon,,128.70,11.45 +Net Movement,,,117.25 +,,, +Patreon Donations,,, +"Feb. 1, 2018",Income - Patreon Donations,0.00,128.70 +Total Patreon Donations,,0.00,128.70 +Net Movement,,,128.70 +,,, +Payment Fees,,, +"Feb. 1, 2018",Expense - Processing Fees,5.01,0.00 +Total Payment Fees,,5.01,0.00 +Net Movement,,,5.01 +,,, +Patreon Fees,,, +"Feb. 1, 2018",Expense - Patreon Fees,6.44,0.00 +Total Patreon Fees,,6.44,0.00 +Net Movement,,,6.44 +,,, diff --git a/finances/HaxeFlixel Detailed General Ledger from 2018-03-01 to 2018-03-31.csv b/finances/HaxeFlixel Detailed General Ledger from 2018-03-01 to 2018-03-31.csv new file mode 100644 index 000000000..c22d9d3df --- /dev/null +++ b/finances/HaxeFlixel Detailed General Ledger from 2018-03-01 to 2018-03-31.csv @@ -0,0 +1,43 @@ +date,transaction,debit,credit +Patreon,,, +"March 1, 2018",Income - Patreon Donations,128.70,0.00 +"March 1, 2018",Expense - Processing Fees,0.00,4.87 +"March 1, 2018",Expense - Patreon Fees,0.00,6.44 +"March 26, 2018",Transfer to Treasurer,0.00,842.04 +Total Patreon,,128.70,853.35 +Net Movement,,,(724.65) +,,, +Treasurer,,, +"March 26, 2018",Transfer from Patreon,842.04,0.00 +"March 26, 2018",Expense - Paypal Transfer Fee (1%),0.00,8.43 +"March 26, 2018",Expense - US Income Taxes (25% of 833.61),0.00,208.40 +"March 27, 2018",Expense - Donation to Jens Fischer (Gama11) for long term HaxeFlixel support,0.00,"2,400.00" +Total Treasurer,,842.04,"2,616.83" +Net Movement,,,"(1,774.79)" +,,, +Patreon Donations,,, +"March 1, 2018",Income - Patreon Donations,0.00,128.70 +Total Patreon Donations,,0.00,128.70 +Net Movement,,,128.70 +,,, +Payment Fees,,, +"March 1, 2018",Expense - Processing Fees,4.87,0.00 +Total Payment Fees,,4.87,0.00 +Net Movement,,,4.87 +,,, +Patreon Fees,,, +"March 26, 2018",Expense - Paypal Transfer Fee (1%),8.43,0.00 +"March 1, 2018",Expense - Patreon Fees,6.44,0.00 +Total Patreon Fees,,14.87,0.00 +Net Movement,,,14.87 +,,, +Tax Fees,,, +"March 26, 2018",Expense - US Income Taxes (25% of 833.61),208.40,0.00 +Total Tax Fees,,208.40,0.00 +Net Movement,,,208.40 +,,, +Development Services,,, +"March 27, 2018",Expense - Donation to Jens Fischer (Gama11) for long term HaxeFlixel support,"2,400.00",0.00 +Total Development Services,,"2,400.00",0.00 +Net Movement,,,"2,400.00" +,,, diff --git a/finances/HaxeFlixel Profit and Loss from 2018-04-01 to 2018-04-30.csv b/finances/HaxeFlixel Profit and Loss from 2018-04-01 to 2018-04-30.csv new file mode 100644 index 000000000..8f45448fd --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2018-04-01 to 2018-04-30.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2018-04-01 to 2018-04-30 +"" +ACCOUNT NUMBER,ACCOUNTS,"Apr 01, 2018 to Apr 30, 2018" +,Income, +,Patreon Donations,$126.70 +,Total Income,$126.70 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$126.70 +"" +,Operating Expenses, +,Patreon Fees,$6.34 +,Payment Fees,$4.81 +,Total Operating Expenses,$11.15 +"" +,Net Profit,$115.55 diff --git a/finances/HaxeFlixel Profit and Loss from 2018-05-01 to 2018-05-31.csv b/finances/HaxeFlixel Profit and Loss from 2018-05-01 to 2018-05-31.csv new file mode 100644 index 000000000..2e542425b --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2018-05-01 to 2018-05-31.csv @@ -0,0 +1,22 @@ +Profit and Loss +HaxeFlixel +Date Range: 2018-05-01 to 2018-05-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"May 01, 2018 to May 31, 2018" +,Income, +,Patreon Donations,$120.00 +,Total Income,$120.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$120.00 +"" +,Operating Expenses, +,Development Services,$200.00 +,Patreon Fees,$6.00 +,PayPal Fee,$2.26 +,Payment Fees,$4.17 +,Tax Fees,$55.78 +,Total Operating Expenses,$268.21 +"" +,Net Profit,-$148.21 diff --git a/finances/HaxeFlixel Profit and Loss from 2018-06-01 to 2018-06-30.csv b/finances/HaxeFlixel Profit and Loss from 2018-06-01 to 2018-06-30.csv new file mode 100644 index 000000000..a3ad6c196 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2018-06-01 to 2018-06-30.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2018-06-01 to 2018-06-30 +"" +ACCOUNT NUMBER,ACCOUNTS,"Jun 01, 2018 to Jun 30, 2018" +,Income, +,Patreon Donations,$110.00 +,Total Income,$110.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$110.00 +"" +,Operating Expenses, +,Patreon Fees,$5.50 +,Payment Fees,$3.85 +,Total Operating Expenses,$9.35 +"" +,Net Profit,$100.65 diff --git a/finances/HaxeFlixel Profit and Loss from 2018-07-01 to 2018-07-31.csv b/finances/HaxeFlixel Profit and Loss from 2018-07-01 to 2018-07-31.csv new file mode 100644 index 000000000..ba0b8e6c3 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2018-07-01 to 2018-07-31.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2018-07-01 to 2018-07-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Jul 01, 2018 to Jul 31, 2018" +,Income, +,Patreon Donations,$115.00 +,Total Income,$115.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$115.00 +"" +,Operating Expenses, +,Patreon Fees,$5.75 +,Payment Fees,$4.01 +,Total Operating Expenses,$9.76 +"" +,Net Profit,$105.24 diff --git a/finances/HaxeFlixel Profit and Loss from 2018-08-01 to 2018-08-31.csv b/finances/HaxeFlixel Profit and Loss from 2018-08-01 to 2018-08-31.csv new file mode 100644 index 000000000..11e572c36 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2018-08-01 to 2018-08-31.csv @@ -0,0 +1,22 @@ +Profit and Loss +HaxeFlixel +Date Range: 2018-08-01 to 2018-08-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Aug 01, 2018 to Aug 31, 2018" +,Income, +,Patreon Donations,$115.00 +,Total Income,$115.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$115.00 +"" +,Operating Expenses, +,Patreon Fees,$5.75 +,PayPal Fee,$8.11 +,Payment Fees,$3.98 +,Tax Fees,$77.79 +,Website Maintenance,$44.95 +,Total Operating Expenses,$140.58 +"" +,Net Profit,-$25.58 diff --git a/finances/HaxeFlixel Profit and Loss from 2018-09-01 to 2018-09-30.csv b/finances/HaxeFlixel Profit and Loss from 2018-09-01 to 2018-09-30.csv new file mode 100644 index 000000000..37e6fc089 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2018-09-01 to 2018-09-30.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2018-09-01 to 2018-09-30 +"" +ACCOUNT NUMBER,ACCOUNTS,"Sep 01, 2018 to Sep 30, 2018" +,Income, +,Patreon Donations,$107.00 +,Total Income,$107.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$107.00 +"" +,Operating Expenses, +,Patreon Fees,$5.35 +,Payment Fees,$3.67 +,Total Operating Expenses,$9.02 +"" +,Net Profit,$97.98 diff --git a/finances/HaxeFlixel Profit and Loss from 2018-10-01 to 2018-10-31.csv b/finances/HaxeFlixel Profit and Loss from 2018-10-01 to 2018-10-31.csv new file mode 100644 index 000000000..01df0d772 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2018-10-01 to 2018-10-31.csv @@ -0,0 +1,20 @@ +Profit and Loss +HaxeFlixel +Date Range: 2018-10-01 to 2018-10-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Oct 01, 2018 to Oct 31, 2018" +,Income, +,Patreon Donations,$107.00 +,Total Income,$107.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$107.00 +"" +,Operating Expenses, +,Development Services,$50.00 +,Patreon Fees,$5.35 +,Payment Fees,$3.67 +,Total Operating Expenses,$59.02 +"" +,Net Profit,$47.98 diff --git a/finances/HaxeFlixel Profit and Loss from 2018-11-01 to 2018-11-30.csv b/finances/HaxeFlixel Profit and Loss from 2018-11-01 to 2018-11-30.csv new file mode 100644 index 000000000..6b0853afd --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2018-11-01 to 2018-11-30.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2018-11-01 to 2018-11-30 +"" +ACCOUNT NUMBER,ACCOUNTS,"Nov 01, 2018 to Nov 30, 2018" +,Income, +,Patreon Donations,$93.00 +,Total Income,$93.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$93.00 +"" +,Operating Expenses, +,Patreon Fees,$4.65 +,Payment Fees,$3.36 +,Total Operating Expenses,$8.01 +"" +,Net Profit,$84.99 diff --git a/finances/HaxeFlixel Profit and Loss from 2018-12-01 to 2018-12-31.csv b/finances/HaxeFlixel Profit and Loss from 2018-12-01 to 2018-12-31.csv new file mode 100644 index 000000000..f67b21eef --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2018-12-01 to 2018-12-31.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2018-12-01 to 2018-12-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Dec 01, 2018 to Dec 31, 2018" +,Income, +,Patreon Donations,$88.00 +,Total Income,$88.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$88.00 +"" +,Operating Expenses, +,Patreon Fees,$4.40 +,Payment Fees,$3.24 +,Total Operating Expenses,$7.64 +"" +,Net Profit,$80.36 diff --git a/finances/HaxeFlixel Profit and Loss from 2019-01-01 to 2019-01-31.csv b/finances/HaxeFlixel Profit and Loss from 2019-01-01 to 2019-01-31.csv new file mode 100644 index 000000000..8c403da75 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2019-01-01 to 2019-01-31.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2019-01-01 to 2019-01-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Jan 01, 2019 to Jan 31, 2019" +,Income, +,Patreon Donations,$84.00 +,Total Income,$84.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$84.00 +"" +,Operating Expenses, +,Patreon Fees,$4.20 +,Payment Fees,$2.78 +,Total Operating Expenses,$6.98 +"" +,Net Profit,$77.02 diff --git a/finances/HaxeFlixel Profit and Loss from 2019-02-01 to 2019-02-28.csv b/finances/HaxeFlixel Profit and Loss from 2019-02-01 to 2019-02-28.csv new file mode 100644 index 000000000..5bace76c1 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2019-02-01 to 2019-02-28.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2019-02-01 to 2019-02-28 +"" +ACCOUNT NUMBER,ACCOUNTS,"Feb 01, 2019 to Feb 28, 2019" +,Income, +,Patreon Donations,$83.00 +,Total Income,$83.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$83.00 +"" +,Operating Expenses, +,Patreon Fees,$4.15 +,Payment Fees,$2.76 +,Total Operating Expenses,$6.91 +"" +,Net Profit,$76.09 diff --git a/finances/HaxeFlixel Profit and Loss from 2019-03-01 to 2019-03-31.csv b/finances/HaxeFlixel Profit and Loss from 2019-03-01 to 2019-03-31.csv new file mode 100644 index 000000000..5871dd3e9 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2019-03-01 to 2019-03-31.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2019-03-01 to 2019-03-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Mar 01, 2019 to Mar 31, 2019" +,Income, +,Patreon Donations,$83.00 +,Total Income,$83.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$83.00 +"" +,Operating Expenses, +,Patreon Fees,$4.15 +,Payment Fees,$2.71 +,Total Operating Expenses,$6.86 +"" +,Net Profit,$76.14 diff --git a/finances/HaxeFlixel Profit and Loss from 2019-04-01 to 2019-04-30.csv b/finances/HaxeFlixel Profit and Loss from 2019-04-01 to 2019-04-30.csv new file mode 100644 index 000000000..9c4cff5c2 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2019-04-01 to 2019-04-30.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2019-04-01 to 2019-04-30 +"" +ACCOUNT NUMBER,ACCOUNTS,"Apr 01, 2019 to Apr 30, 2019" +,Income, +,Patreon Donations,$78.00 +,Total Income,$78.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$78.00 +"" +,Operating Expenses, +,Patreon Fees,$3.90 +,Payment Fees,$2.66 +,Total Operating Expenses,$6.56 +"" +,Net Profit,$71.44 diff --git a/finances/HaxeFlixel Profit and Loss from 2019-05-01 to 2019-05-31.csv b/finances/HaxeFlixel Profit and Loss from 2019-05-01 to 2019-05-31.csv new file mode 100644 index 000000000..a389ba40a --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2019-05-01 to 2019-05-31.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2019-05-01 to 2019-05-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"May 01, 2019 to May 31, 2019" +,Income, +,Patreon Donations,$78.00 +,Total Income,$78.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$78.00 +"" +,Operating Expenses, +,Patreon Fees,$3.90 +,Payment Fees,$2.65 +,Total Operating Expenses,$6.55 +"" +,Net Profit,$71.45 diff --git a/finances/HaxeFlixel Profit and Loss from 2019-06-01 to 2019-06-30.csv b/finances/HaxeFlixel Profit and Loss from 2019-06-01 to 2019-06-30.csv new file mode 100644 index 000000000..987ed14da --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2019-06-01 to 2019-06-30.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2019-06-01 to 2019-06-30 +"" +ACCOUNT NUMBER,ACCOUNTS,"Jun 01, 2019 to Jun 30, 2019" +,Income, +,Patreon Donations,$78.00 +,Total Income,$78.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$78.00 +"" +,Operating Expenses, +,Patreon Fees,$3.90 +,Payment Fees,$2.60 +,Total Operating Expenses,$6.50 +"" +,Net Profit,$71.50 diff --git a/finances/HaxeFlixel Profit and Loss from 2019-07-01 to 2019-07-31.csv b/finances/HaxeFlixel Profit and Loss from 2019-07-01 to 2019-07-31.csv new file mode 100644 index 000000000..1b015ee07 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2019-07-01 to 2019-07-31.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2019-07-01 to 2019-07-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Jul 01, 2019 to Jul 31, 2019" +,Income, +,Patreon Donations,$78.00 +,Total Income,$78.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$78.00 +"" +,Operating Expenses, +,Patreon Fees,$3.90 +,Payment Fees,$2.60 +,Total Operating Expenses,$6.50 +"" +,Net Profit,$71.50 diff --git a/finances/HaxeFlixel Profit and Loss from 2019-08-01 to 2019-08-31.csv b/finances/HaxeFlixel Profit and Loss from 2019-08-01 to 2019-08-31.csv new file mode 100644 index 000000000..905526fd5 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2019-08-01 to 2019-08-31.csv @@ -0,0 +1,23 @@ +Profit and Loss +HaxeFlixel +Date Range: 2019-08-01 to 2019-08-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Aug 01, 2019 to Aug 31, 2019" +,Income, +,Patreon Donations,$78.00 +,Total Income,$78.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$78.00 +"" +,Operating Expenses, +,Development Services,$600.00 +,Patreon Fees,$3.90 +,PayPal Fee,$9.48 +,Payment Fees,$2.69 +,Tax Fees,$60.79 +,Website Maintenance,$300.00 +,Total Operating Expenses,$976.86 +"" +,Net Profit,-$898.86 diff --git a/finances/HaxeFlixel Profit and Loss from 2019-09-01 to 2019-09-30.csv b/finances/HaxeFlixel Profit and Loss from 2019-09-01 to 2019-09-30.csv new file mode 100644 index 000000000..b22bec544 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2019-09-01 to 2019-09-30.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2019-09-01 to 2019-09-30 +"" +ACCOUNT NUMBER,ACCOUNTS,"Sep 01, 2019 to Sep 30, 2019" +,Income, +,Patreon Donations,$78.00 +,Total Income,$78.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$78.00 +"" +,Operating Expenses, +,Patreon Fees,$3.90 +,Payment Fees,$2.68 +,Total Operating Expenses,$6.58 +"" +,Net Profit,$71.42 diff --git a/finances/HaxeFlixel Profit and Loss from 2019-10-01 to 2019-10-31.csv b/finances/HaxeFlixel Profit and Loss from 2019-10-01 to 2019-10-31.csv new file mode 100644 index 000000000..59b90d34f --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2019-10-01 to 2019-10-31.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2019-10-01 to 2019-10-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Oct 01, 2019 to Oct 31, 2019" +,Income, +,Patreon Donations,$78.00 +,Total Income,$78.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$78.00 +"" +,Operating Expenses, +,Patreon Fees,$3.90 +,Payment Fees,$2.70 +,Total Operating Expenses,$6.60 +"" +,Net Profit,$71.40 diff --git a/finances/HaxeFlixel Profit and Loss from 2019-11-01 to 2019-11-30.csv b/finances/HaxeFlixel Profit and Loss from 2019-11-01 to 2019-11-30.csv new file mode 100644 index 000000000..106a30eb5 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2019-11-01 to 2019-11-30.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2019-11-01 to 2019-11-30 +"" +ACCOUNT NUMBER,ACCOUNTS,"Nov 01, 2019 to Nov 30, 2019" +,Income, +,Patreon Donations,$78.00 +,Total Income,$78.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$78.00 +"" +,Operating Expenses, +,Patreon Fees,$3.90 +,Payment Fees,$2.69 +,Total Operating Expenses,$6.59 +"" +,Net Profit,$71.41 diff --git a/finances/HaxeFlixel Profit and Loss from 2019-12-01 to 2019-12-31.csv b/finances/HaxeFlixel Profit and Loss from 2019-12-01 to 2019-12-31.csv new file mode 100644 index 000000000..9c9dfcbb0 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2019-12-01 to 2019-12-31.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2019-12-01 to 2019-12-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Dec 01, 2019 to Dec 31, 2019" +,Income, +,Patreon Donations,$83.00 +,Total Income,$83.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$83.00 +"" +,Operating Expenses, +,PayPal Fee,$4.15 +,Payment Fees,$2.83 +,Total Operating Expenses,$6.98 +"" +,Net Profit,$76.02 diff --git a/finances/HaxeFlixel Profit and Loss from 2020-01-01 to 2020-01-31.csv b/finances/HaxeFlixel Profit and Loss from 2020-01-01 to 2020-01-31.csv new file mode 100644 index 000000000..0dd62a2c6 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2020-01-01 to 2020-01-31.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2020-01-01 to 2020-01-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Jan 01, 2020 to Jan 31, 2020" +,Income, +,Patreon Donations,$83.00 +,Total Income,$83.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$83.00 +"" +,Operating Expenses, +,Patreon Fees,$4.15 +,Payment Fees,$2.82 +,Total Operating Expenses,$6.97 +"" +,Net Profit,$76.03 diff --git a/finances/HaxeFlixel Profit and Loss from 2020-01.csv b/finances/HaxeFlixel Profit and Loss from 2020-01.csv new file mode 100644 index 000000000..0dd62a2c6 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2020-01.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2020-01-01 to 2020-01-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Jan 01, 2020 to Jan 31, 2020" +,Income, +,Patreon Donations,$83.00 +,Total Income,$83.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$83.00 +"" +,Operating Expenses, +,Patreon Fees,$4.15 +,Payment Fees,$2.82 +,Total Operating Expenses,$6.97 +"" +,Net Profit,$76.03 diff --git a/finances/HaxeFlixel Profit and Loss from 2020-02-01 to 2020-02-29.csv b/finances/HaxeFlixel Profit and Loss from 2020-02-01 to 2020-02-29.csv new file mode 100644 index 000000000..15f9a2469 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2020-02-01 to 2020-02-29.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2020-02-01 to 2020-02-29 +"" +ACCOUNT NUMBER,ACCOUNTS,"Feb 01, 2020 to Feb 29, 2020" +,Income, +,Patreon Donations,$83.00 +,Total Income,$83.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$83.00 +"" +,Operating Expenses, +,Patreon Fees,$4.15 +,Payment Fees,$2.81 +,Total Operating Expenses,$6.96 +"" +,Net Profit,$76.04 diff --git a/finances/HaxeFlixel Profit and Loss from 2020-02.csv b/finances/HaxeFlixel Profit and Loss from 2020-02.csv new file mode 100644 index 000000000..15f9a2469 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2020-02.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2020-02-01 to 2020-02-29 +"" +ACCOUNT NUMBER,ACCOUNTS,"Feb 01, 2020 to Feb 29, 2020" +,Income, +,Patreon Donations,$83.00 +,Total Income,$83.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$83.00 +"" +,Operating Expenses, +,Patreon Fees,$4.15 +,Payment Fees,$2.81 +,Total Operating Expenses,$6.96 +"" +,Net Profit,$76.04 diff --git a/finances/HaxeFlixel Profit and Loss from 2020-03.csv b/finances/HaxeFlixel Profit and Loss from 2020-03.csv new file mode 100644 index 000000000..8f5e2fcb4 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2020-03.csv @@ -0,0 +1,22 @@ +Profit and Loss +HaxeFlixel +Date Range: 2020-03-01 to 2020-03-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Mar 01, 2020 to Mar 31, 2020" +,Income, +,Patreon Donations,$83.00 +,Total Income,$83.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$83.00 +"" +,Operating Expenses, +,Game Jam Prize,$400.00 +,Patreon Fees,$4.15 +,PayPal Fee,$5.19 +,Payment Fees,$2.82 +,Tax Fees,$100.00 +,Total Operating Expenses,$512.16 +"" +,Net Profit,-$429.16 diff --git a/finances/HaxeFlixel Profit and Loss from 2020-04.csv b/finances/HaxeFlixel Profit and Loss from 2020-04.csv new file mode 100644 index 000000000..8ac91b7d6 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2020-04.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2020-04-01 to 2020-04-30 +"" +ACCOUNT NUMBER,ACCOUNTS,"Apr 01, 2020 to Apr 30, 2020" +,Income, +,Patreon Donations,$93.00 +,Total Income,$93.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$93.00 +"" +,Operating Expenses, +,Patreon Fees,$4.65 +,Payment Fees,$3.64 +,Total Operating Expenses,$8.29 +"" +,Net Profit,$84.71 diff --git a/finances/HaxeFlixel Profit and Loss from 2020-05.csv b/finances/HaxeFlixel Profit and Loss from 2020-05.csv new file mode 100644 index 000000000..8d642d59d --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2020-05.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2020-05-01 to 2020-05-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"May 01, 2020 to May 31, 2020" +,Income, +,Patreon Donations,$98.00 +,Total Income,$98.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$98.00 +"" +,Operating Expenses, +,Patreon Fees,$4.90 +,Payment Fees,$3.64 +,Total Operating Expenses,$8.54 +"" +,Net Profit,$89.46 diff --git a/finances/HaxeFlixel Profit and Loss from 2020-06.csv b/finances/HaxeFlixel Profit and Loss from 2020-06.csv new file mode 100644 index 000000000..92c874218 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2020-06.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2020-06-01 to 2020-06-30 +"" +ACCOUNT NUMBER,ACCOUNTS,"Jun 01, 2020 to Jun 30, 2020" +,Income, +,Patreon Donations,$98.00 +,Total Income,$98.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$98.00 +"" +,Operating Expenses, +,Patreon Fees,$4.90 +,Payment Fees,$3.62 +,Total Operating Expenses,$8.52 +"" +,Net Profit,$89.48 diff --git a/finances/HaxeFlixel Profit and Loss from 2020-07.csv b/finances/HaxeFlixel Profit and Loss from 2020-07.csv new file mode 100644 index 000000000..792404df3 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2020-07.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2020-07-01 to 2020-07-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Jul 01, 2020 to Jul 31, 2020" +,Income, +,Patreon Donations,$98.00 +,Total Income,$98.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$98.00 +"" +,Operating Expenses, +,Patreon Fees,$4.90 +,Payment Fees,$3.64 +,Total Operating Expenses,$8.54 +"" +,Net Profit,$89.46 diff --git a/finances/HaxeFlixel Profit and Loss from 2020-08.csv b/finances/HaxeFlixel Profit and Loss from 2020-08.csv new file mode 100644 index 000000000..83aed90c5 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2020-08.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2020-08-01 to 2020-08-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Aug 01, 2020 to Aug 31, 2020" +,Income, +,Patreon Donations,$95.00 +,Total Income,$95.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$95.00 +"" +,Operating Expenses, +,Patreon Fees,$4.75 +,Payment Fees,$2.84 +,Total Operating Expenses,$7.59 +"" +,Net Profit,$87.41 diff --git a/finances/HaxeFlixel Profit and Loss from 2020-09.csv b/finances/HaxeFlixel Profit and Loss from 2020-09.csv new file mode 100644 index 000000000..84ee67341 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2020-09.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2020-09-01 to 2020-09-30 +"" +ACCOUNT NUMBER,ACCOUNTS,"Sep 01, 2020 to Sep 30, 2020" +,Income, +,Patreon Donations,$97.00 +,Total Income,$97.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$97.00 +"" +,Operating Expenses, +,Patreon Fees,$4.85 +,Payment Fees,$2.10 +,Total Operating Expenses,$6.95 +"" +,Net Profit,$90.05 diff --git a/finances/HaxeFlixel Profit and Loss from 2020-10.csv b/finances/HaxeFlixel Profit and Loss from 2020-10.csv new file mode 100644 index 000000000..794705178 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2020-10.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2020-10-01 to 2020-10-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Oct 01, 2020 to Oct 31, 2020" +,Income, +,Patreon Donations,$97.00 +,Total Income,$97.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$97.00 +"" +,Operating Expenses, +,Patreon Fees,$4.85 +,Payment Fees,$2.15 +,Total Operating Expenses,$7.00 +"" +,Net Profit,$90.00 diff --git a/finances/HaxeFlixel Profit and Loss from 2020-11.csv b/finances/HaxeFlixel Profit and Loss from 2020-11.csv new file mode 100644 index 000000000..4494e7150 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2020-11.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2020-11-01 to 2020-11-30 +"" +ACCOUNT NUMBER,ACCOUNTS,"Nov 01, 2020 to Nov 30, 2020" +,Income, +,Patreon Donations,$97.00 +,Total Income,$97.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$97.00 +"" +,Operating Expenses, +,Patreon Fees,$4.85 +,Payment Fees,$2.09 +,Total Operating Expenses,$6.94 +"" +,Net Profit,$90.06 diff --git a/finances/HaxeFlixel Profit and Loss from 2020-12.csv b/finances/HaxeFlixel Profit and Loss from 2020-12.csv new file mode 100644 index 000000000..fc36eeded --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2020-12.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2020-12-01 to 2020-12-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Dec 01, 2020 to Dec 31, 2020" +,Income, +,Patreon Donations,$97.00 +,Total Income,$97.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$97.00 +"" +,Operating Expenses, +,Patreon Fees,$4.85 +,Payment Fees,$2.15 +,Total Operating Expenses,$7.00 +"" +,Net Profit,$90.00 diff --git a/finances/HaxeFlixel Profit and Loss from 2021-01.csv b/finances/HaxeFlixel Profit and Loss from 2021-01.csv new file mode 100644 index 000000000..bb5851693 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2021-01.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2021-01-01 to 2021-01-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Jan 01, 2021 to Jan 31, 2021" +,Income, +,Patreon Donations,$89.00 +,Total Income,$89.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$89.00 +"" +,Operating Expenses, +,Patreon Fees,$4.45 +,Payment Fees,$1.72 +,Total Operating Expenses,$6.17 +"" +,Net Profit,$82.83 diff --git a/finances/HaxeFlixel Profit and Loss from 2021-02.csv b/finances/HaxeFlixel Profit and Loss from 2021-02.csv new file mode 100644 index 000000000..75883acde --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2021-02.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2021-02-01 to 2021-02-28 +"" +ACCOUNT NUMBER,ACCOUNTS,"Feb 01, 2021 to Feb 28, 2021" +,Income, +,Patreon Donations,$89.00 +,Total Income,$89.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$89.00 +"" +,Operating Expenses, +,Patreon Fees,$4.45 +,Payment Fees,$1.69 +,Total Operating Expenses,$6.14 +"" +,Net Profit,$82.86 diff --git a/finances/HaxeFlixel Profit and Loss from 2021-03.csv b/finances/HaxeFlixel Profit and Loss from 2021-03.csv new file mode 100644 index 000000000..277bf6a36 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2021-03.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2021-03-01 to 2021-03-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Mar 01, 2021 to Mar 31, 2021" +,Income, +,Patreon Donations,$89.00 +,Total Income,$89.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$89.00 +"" +,Operating Expenses, +,Patreon Fees,$4.45 +,Payment Fees,$1.69 +,Total Operating Expenses,$6.14 +"" +,Net Profit,$82.86 diff --git a/finances/HaxeFlixel Profit and Loss from 2021-04.csv b/finances/HaxeFlixel Profit and Loss from 2021-04.csv new file mode 100644 index 000000000..91b03e686 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2021-04.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2021-04-01 to 2021-04-30 +"" +ACCOUNT NUMBER,ACCOUNTS,"Apr 01, 2021 to Apr 30, 2021" +,Income, +,Patreon Donations,$89.00 +,Total Income,$89.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$89.00 +"" +,Operating Expenses, +,Patreon Fees,$4.45 +,Payment Fees,$1.68 +,Total Operating Expenses,$6.13 +"" +,Net Profit,$82.87 diff --git a/finances/HaxeFlixel Profit and Loss from 2021-05.csv b/finances/HaxeFlixel Profit and Loss from 2021-05.csv new file mode 100644 index 000000000..c051e9e95 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2021-05.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2021-05-01 to 2021-05-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"May 01, 2021 to May 31, 2021" +,Income, +,Patreon Donations,$89.00 +,Total Income,$89.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$89.00 +"" +,Operating Expenses, +,Patreon Fees,$4.45 +,Payment Fees,$1.68 +,Total Operating Expenses,$6.13 +"" +,Net Profit,$82.87 diff --git a/finances/HaxeFlixel Profit and Loss from 2021-06.csv b/finances/HaxeFlixel Profit and Loss from 2021-06.csv new file mode 100644 index 000000000..6772ee0cc --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2021-06.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2021-06-01 to 2021-06-30 +"" +ACCOUNT NUMBER,ACCOUNTS,"Jun 01, 2021 to Jun 30, 2021" +,Income, +,Patreon Donations,$84.00 +,Total Income,$84.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$84.00 +"" +,Operating Expenses, +,Patreon Fees,$4.20 +,Payment Fees,$1.48 +,Total Operating Expenses,$5.68 +"" +,Net Profit,$78.32 diff --git a/finances/HaxeFlixel Profit and Loss from 2021-07.csv b/finances/HaxeFlixel Profit and Loss from 2021-07.csv new file mode 100644 index 000000000..c4e451610 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2021-07.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2021-07-01 to 2021-07-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Jul 01, 2021 to Jul 31, 2021" +,Income, +,Patreon Donations,$84.00 +,Total Income,$84.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$84.00 +"" +,Operating Expenses, +,Patreon Fees,$4.20 +,Payment Fees,$1.47 +,Total Operating Expenses,$5.67 +"" +,Net Profit,$78.33 diff --git a/finances/HaxeFlixel Profit and Loss from 2021-08.csv b/finances/HaxeFlixel Profit and Loss from 2021-08.csv new file mode 100644 index 000000000..6f4398a87 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2021-08.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2021-08-01 to 2021-08-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Aug 01, 2021 to Aug 31, 2021" +,Income, +,Patreon Donations,$84.00 +,Total Income,$84.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$84.00 +"" +,Operating Expenses, +,Patreon Fees,$4.20 +,Payment Fees,$1.46 +,Total Operating Expenses,$5.66 +"" +,Net Profit,$78.34 diff --git a/finances/HaxeFlixel Profit and Loss from 2021-09.csv b/finances/HaxeFlixel Profit and Loss from 2021-09.csv new file mode 100644 index 000000000..dff0fe8a9 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2021-09.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2021-09-01 to 2021-09-30 +"" +ACCOUNT NUMBER,ACCOUNTS,"Sep 01, 2021 to Sep 30, 2021" +,Income, +,Patreon Donations,$84.00 +,Total Income,$84.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$84.00 +"" +,Operating Expenses, +,Patreon Fees,$4.20 +,Payment Fees,$1.48 +,Total Operating Expenses,$5.68 +"" +,Net Profit,$78.32 diff --git a/finances/HaxeFlixel Profit and Loss from 2021-10.csv b/finances/HaxeFlixel Profit and Loss from 2021-10.csv new file mode 100644 index 000000000..94c832947 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2021-10.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2021-10-01 to 2021-10-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Oct 01, 2021 to Oct 31, 2021" +,Income, +,Patreon Donations,$86.00 +,Total Income,$86.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$86.00 +"" +,Operating Expenses, +,Patreon Fees,$4.30 +,Payment Fees,$1.66 +,Total Operating Expenses,$5.96 +"" +,Net Profit,$80.04 diff --git a/finances/HaxeFlixel Profit and Loss from 2021-11.csv b/finances/HaxeFlixel Profit and Loss from 2021-11.csv new file mode 100644 index 000000000..7de43f5c5 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2021-11.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2021-11-01 to 2021-11-30 +"" +ACCOUNT NUMBER,ACCOUNTS,"Nov 01, 2021 to Nov 30, 2021" +,Income, +,Patreon Donations,$86.00 +,Total Income,$86.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$86.00 +"" +,Operating Expenses, +,Patreon Fees,$4.30 +,Payment Fees,$1.57 +,Total Operating Expenses,$5.87 +"" +,Net Profit,$80.13 diff --git a/finances/HaxeFlixel Profit and Loss from 2021-12.csv b/finances/HaxeFlixel Profit and Loss from 2021-12.csv new file mode 100644 index 000000000..6df04e700 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2021-12.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2021-12-01 to 2021-12-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Dec 01, 2021 to Dec 31, 2021" +,Income, +,Patreon Donations,$86.00 +,Total Income,$86.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$86.00 +"" +,Operating Expenses, +,Patreon Fees,$4.30 +,Payment Fees,$1.58 +,Total Operating Expenses,$5.88 +"" +,Net Profit,$80.12 diff --git a/finances/HaxeFlixel Profit and Loss from 2022-01.csv b/finances/HaxeFlixel Profit and Loss from 2022-01.csv new file mode 100644 index 000000000..1528c33d2 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2022-01.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2022-01-01 to 2022-01-31 +"" +ACCOUNT NUMBER,ACCOUNTS,"Jan 01, 2022 to Jan 31, 2022" +,Income, +,Patreon Donations,$86.00 +,Total Income,$86.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$86.00 +"" +,Operating Expenses, +,Patreon Fees,$4.30 +,Payment Fees,$1.59 +,Total Operating Expenses,$5.89 +"" +,Net Profit,$80.11 diff --git a/finances/HaxeFlixel Profit and Loss from 2022-02.csv b/finances/HaxeFlixel Profit and Loss from 2022-02.csv new file mode 100644 index 000000000..8ec650803 --- /dev/null +++ b/finances/HaxeFlixel Profit and Loss from 2022-02.csv @@ -0,0 +1,19 @@ +Profit and Loss +HaxeFlixel +Date Range: 2022-02-01 to 2022-02-28 +"" +ACCOUNT NUMBER,ACCOUNTS,"Feb 01, 2022 to Feb 28, 2022" +,Income, +,Patreon Donations,$86.00 +,Total Income,$86.00 +"" +,Total Cost of Goods Sold,$0.00 +"" +,Gross Profit,$86.00 +"" +,Operating Expenses, +,Patreon Fees,$4.30 +,Payment Fees,$1.57 +,Total Operating Expenses,$5.87 +"" +,Net Profit,$80.13 diff --git a/images/IGG_FundedWithBadges_WhiteOutlined_RGB_Rectangle.png b/images/IGG_FundedWithBadges_WhiteOutlined_RGB_Rectangle.png new file mode 100755 index 000000000..cc3fb39cb Binary files /dev/null and b/images/IGG_FundedWithBadges_WhiteOutlined_RGB_Rectangle.png differ diff --git a/images/blog/10_community/forums.png b/images/blog/10_community/forums.png new file mode 100644 index 000000000..44fcc8983 Binary files /dev/null and b/images/blog/10_community/forums.png differ diff --git a/images/blog/10_community/github.png b/images/blog/10_community/github.png new file mode 100644 index 000000000..78ad43eb8 Binary files /dev/null and b/images/blog/10_community/github.png differ diff --git a/images/blog/11_light/flp_level4.png b/images/blog/11_light/flp_level4.png new file mode 100644 index 000000000..66dbfd89a Binary files /dev/null and b/images/blog/11_light/flp_level4.png differ diff --git a/images/blog/11_light/flp_logo_594x382.png b/images/blog/11_light/flp_logo_594x382.png new file mode 100644 index 000000000..2e954c37c Binary files /dev/null and b/images/blog/11_light/flp_logo_594x382.png differ diff --git a/images/blog/11_light/flp_menu.png b/images/blog/11_light/flp_menu.png new file mode 100644 index 000000000..215e26a57 Binary files /dev/null and b/images/blog/11_light/flp_menu.png differ diff --git a/images/blog/13_dragonbones/dragonbones_export.png b/images/blog/13_dragonbones/dragonbones_export.png new file mode 100644 index 000000000..4f92f35d5 Binary files /dev/null and b/images/blog/13_dragonbones/dragonbones_export.png differ diff --git a/images/blog/13_dragonbones/dragonbones_preview.gif b/images/blog/13_dragonbones/dragonbones_preview.gif new file mode 100644 index 000000000..4d4d5e2ff Binary files /dev/null and b/images/blog/13_dragonbones/dragonbones_preview.gif differ diff --git a/images/blog/13_dragonbones/dragonbones_stock.jpg b/images/blog/13_dragonbones/dragonbones_stock.jpg new file mode 100644 index 000000000..d2d4446aa Binary files /dev/null and b/images/blog/13_dragonbones/dragonbones_stock.jpg differ diff --git a/images/blog/14_newgrounds_jam/ng_loves_flixel.png b/images/blog/14_newgrounds_jam/ng_loves_flixel.png new file mode 100644 index 000000000..24b1a59a0 Binary files /dev/null and b/images/blog/14_newgrounds_jam/ng_loves_flixel.png differ diff --git a/images/blog/15_blogs_back/pathfinding.png b/images/blog/15_blogs_back/pathfinding.png new file mode 100644 index 000000000..d3745aa01 Binary files /dev/null and b/images/blog/15_blogs_back/pathfinding.png differ diff --git a/images/blog/15_blogs_back/platforming.mp4 b/images/blog/15_blogs_back/platforming.mp4 new file mode 100644 index 000000000..532b6c537 Binary files /dev/null and b/images/blog/15_blogs_back/platforming.mp4 differ diff --git a/images/blog/16_release/all_files.png b/images/blog/16_release/all_files.png new file mode 100644 index 000000000..f5e7491fd Binary files /dev/null and b/images/blog/16_release/all_files.png differ diff --git a/images/blog/16_release/anim-time_scale.mp4 b/images/blog/16_release/anim-time_scale.mp4 new file mode 100644 index 000000000..a5b3d5978 Binary files /dev/null and b/images/blog/16_release/anim-time_scale.mp4 differ diff --git a/images/blog/16_release/export-sheet.png b/images/blog/16_release/export-sheet.png new file mode 100644 index 000000000..44c4ec3cc Binary files /dev/null and b/images/blog/16_release/export-sheet.png differ diff --git a/images/blog/16_release/snowman.png b/images/blog/16_release/snowman.png new file mode 100644 index 000000000..0e49e3c08 Binary files /dev/null and b/images/blog/16_release/snowman.png differ diff --git a/images/blog/16_release/split.jpg b/images/blog/16_release/split.jpg new file mode 100644 index 000000000..cdf6f548f Binary files /dev/null and b/images/blog/16_release/split.jpg differ diff --git a/images/blog/16_release/tag-frames.gif b/images/blog/16_release/tag-frames.gif new file mode 100644 index 000000000..a26849a90 Binary files /dev/null and b/images/blog/16_release/tag-frames.gif differ diff --git a/images/blog/debuggerInteraction.gif b/images/blog/debuggerInteraction.gif new file mode 100644 index 000000000..943f6866d Binary files /dev/null and b/images/blog/debuggerInteraction.gif differ diff --git a/images/blog/hfm-logo.svg b/images/blog/hfm-logo.svg new file mode 100644 index 000000000..15df40a40 --- /dev/null +++ b/images/blog/hfm-logo.svg @@ -0,0 +1,122 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/blog/hfscreen.png b/images/blog/hfscreen.png new file mode 100644 index 000000000..bdfd5f38f Binary files /dev/null and b/images/blog/hfscreen.png differ diff --git a/images/blog/msg_intro/haxeui.png b/images/blog/msg_intro/haxeui.png new file mode 100644 index 000000000..1a743069c Binary files /dev/null and b/images/blog/msg_intro/haxeui.png differ diff --git a/images/blog/msg_intro/indiegogo.png b/images/blog/msg_intro/indiegogo.png new file mode 100644 index 000000000..1e3b8b4c8 Binary files /dev/null and b/images/blog/msg_intro/indiegogo.png differ diff --git a/images/blog/openfl5/cameraBuffers.jpg b/images/blog/openfl5/cameraBuffers.jpg new file mode 100644 index 000000000..f56de5e0f Binary files /dev/null and b/images/blog/openfl5/cameraBuffers.jpg differ diff --git a/images/blog/openfl5/drawDebug.jpg b/images/blog/openfl5/drawDebug.jpg new file mode 100644 index 000000000..7e807072f Binary files /dev/null and b/images/blog/openfl5/drawDebug.jpg differ diff --git a/images/blog/openfl5/drawTriangles.png b/images/blog/openfl5/drawTriangles.png new file mode 100644 index 000000000..115f8f973 Binary files /dev/null and b/images/blog/openfl5/drawTriangles.png differ diff --git a/images/blog/openfl5/lighting.jpg b/images/blog/openfl5/lighting.jpg new file mode 100644 index 000000000..b8327510b Binary files /dev/null and b/images/blog/openfl5/lighting.jpg differ diff --git a/images/blog/shadedBunnies.gif b/images/blog/shadedBunnies.gif new file mode 100644 index 000000000..0e3fab7aa Binary files /dev/null and b/images/blog/shadedBunnies.gif differ diff --git a/images/blog/title-logo.swf b/images/blog/title-logo.swf new file mode 100644 index 000000000..ebd2d7991 Binary files /dev/null and b/images/blog/title-logo.swf differ diff --git a/images/demos/BSPMapGen.png b/images/demos/BSPMapGen.png new file mode 100644 index 000000000..e8b6d8618 Binary files /dev/null and b/images/demos/BSPMapGen.png differ diff --git a/images/demos/BlendModeShaders.png b/images/demos/BlendModeShaders.png new file mode 100644 index 000000000..b5f73c908 Binary files /dev/null and b/images/demos/BlendModeShaders.png differ diff --git a/images/demos/BlendModes.png b/images/demos/BlendModes.png new file mode 100644 index 000000000..a7bc60d06 Binary files /dev/null and b/images/demos/BlendModes.png differ diff --git a/images/demos/Breakout.png b/images/demos/Breakout.png new file mode 100644 index 000000000..d2d8e57ae Binary files /dev/null and b/images/demos/Breakout.png differ diff --git a/images/demos/Calculator.png b/images/demos/Calculator.png new file mode 100644 index 000000000..2f75b09c7 Binary files /dev/null and b/images/demos/Calculator.png differ diff --git a/images/demos/CollisionAndGrouping.png b/images/demos/CollisionAndGrouping.png new file mode 100644 index 000000000..62f3da56b Binary files /dev/null and b/images/demos/CollisionAndGrouping.png differ diff --git a/images/demos/Colors.png b/images/demos/Colors.png new file mode 100644 index 000000000..b41896d21 Binary files /dev/null and b/images/demos/Colors.png differ diff --git a/images/demos/Cursor.png b/images/demos/Cursor.png new file mode 100644 index 000000000..ed8b02aa8 Binary files /dev/null and b/images/demos/Cursor.png differ diff --git a/images/demos/DynamicShadows.png b/images/demos/DynamicShadows.png new file mode 100644 index 000000000..5bcac82c8 Binary files /dev/null and b/images/demos/DynamicShadows.png differ diff --git a/images/demos/EZPlatformer.png b/images/demos/EZPlatformer.png new file mode 100644 index 000000000..596253643 Binary files /dev/null and b/images/demos/EZPlatformer.png differ diff --git a/images/demos/FileBrowse.png b/images/demos/FileBrowse.png new file mode 100644 index 000000000..4b9f46dff Binary files /dev/null and b/images/demos/FileBrowse.png differ diff --git a/images/demos/Filters.png b/images/demos/Filters.png new file mode 100644 index 000000000..cf1205fde Binary files /dev/null and b/images/demos/Filters.png differ diff --git a/images/demos/Flappybalt.png b/images/demos/Flappybalt.png new file mode 100644 index 000000000..d5838e141 Binary files /dev/null and b/images/demos/Flappybalt.png differ diff --git a/images/demos/FlipRotationAnimationTiles.png b/images/demos/FlipRotationAnimationTiles.png new file mode 100644 index 000000000..f72b2640f Binary files /dev/null and b/images/demos/FlipRotationAnimationTiles.png differ diff --git a/images/demos/Flixius.png b/images/demos/Flixius.png new file mode 100644 index 000000000..3705cb38f Binary files /dev/null and b/images/demos/Flixius.png differ diff --git a/images/demos/FloodFill.png b/images/demos/FloodFill.png new file mode 100644 index 000000000..353853830 Binary files /dev/null and b/images/demos/FloodFill.png differ diff --git a/images/demos/FlxAction.png b/images/demos/FlxAction.png new file mode 100644 index 000000000..cd1c7ded3 Binary files /dev/null and b/images/demos/FlxAction.png differ diff --git a/images/demos/FlxAsepriteUtil.png b/images/demos/FlxAsepriteUtil.png new file mode 100644 index 000000000..d351693ac Binary files /dev/null and b/images/demos/FlxAsepriteUtil.png differ diff --git a/images/demos/FlxAsepriteUtils.png b/images/demos/FlxAsepriteUtils.png new file mode 100644 index 000000000..d351693ac Binary files /dev/null and b/images/demos/FlxAsepriteUtils.png differ diff --git a/images/demos/FlxAsyncLoop.png b/images/demos/FlxAsyncLoop.png new file mode 100644 index 000000000..1a01a8fa8 Binary files /dev/null and b/images/demos/FlxAsyncLoop.png differ diff --git a/images/demos/FlxAtlas.png b/images/demos/FlxAtlas.png new file mode 100644 index 000000000..fa4f42794 Binary files /dev/null and b/images/demos/FlxAtlas.png differ diff --git a/images/demos/FlxBitmapText.png b/images/demos/FlxBitmapText.png new file mode 100644 index 000000000..0a06285d3 Binary files /dev/null and b/images/demos/FlxBitmapText.png differ diff --git a/images/demos/FlxBloom.png b/images/demos/FlxBloom.png new file mode 100644 index 000000000..d2fffba1b Binary files /dev/null and b/images/demos/FlxBloom.png differ diff --git a/images/demos/FlxBlur.png b/images/demos/FlxBlur.png new file mode 100644 index 000000000..e31f3fea6 Binary files /dev/null and b/images/demos/FlxBlur.png differ diff --git a/images/demos/FlxBunnyMark.png b/images/demos/FlxBunnyMark.png new file mode 100644 index 000000000..8ab599b05 Binary files /dev/null and b/images/demos/FlxBunnyMark.png differ diff --git a/images/demos/FlxCamera.png b/images/demos/FlxCamera.png new file mode 100644 index 000000000..d49813b1b Binary files /dev/null and b/images/demos/FlxCamera.png differ diff --git a/images/demos/FlxCaveGenerator.png b/images/demos/FlxCaveGenerator.png new file mode 100644 index 000000000..9835c8d9a Binary files /dev/null and b/images/demos/FlxCaveGenerator.png differ diff --git a/images/demos/FlxClothSprite.png b/images/demos/FlxClothSprite.png new file mode 100644 index 000000000..8de4e487e Binary files /dev/null and b/images/demos/FlxClothSprite.png differ diff --git a/images/demos/FlxCollisions.png b/images/demos/FlxCollisions.png new file mode 100644 index 000000000..632651413 Binary files /dev/null and b/images/demos/FlxCollisions.png differ diff --git a/images/demos/FlxEffectSprite.png b/images/demos/FlxEffectSprite.png new file mode 100644 index 000000000..acf106151 Binary files /dev/null and b/images/demos/FlxEffectSprite.png differ diff --git a/images/demos/FlxFSM.png b/images/demos/FlxFSM.png new file mode 100644 index 000000000..25db2f2ef Binary files /dev/null and b/images/demos/FlxFSM.png differ diff --git a/images/demos/FlxInvaders.png b/images/demos/FlxInvaders.png new file mode 100644 index 000000000..f85b9e1f5 Binary files /dev/null and b/images/demos/FlxInvaders.png differ diff --git a/images/demos/FlxLightPuzzle.png b/images/demos/FlxLightPuzzle.png new file mode 100644 index 000000000..414da325e Binary files /dev/null and b/images/demos/FlxLightPuzzle.png differ diff --git a/images/demos/FlxMouseEvent.png b/images/demos/FlxMouseEvent.png new file mode 100644 index 000000000..5c0160e27 Binary files /dev/null and b/images/demos/FlxMouseEvent.png differ diff --git a/images/demos/FlxNape.png b/images/demos/FlxNape.png new file mode 100644 index 000000000..548000962 Binary files /dev/null and b/images/demos/FlxNape.png differ diff --git a/images/demos/FlxNapeTerrain.png b/images/demos/FlxNapeTerrain.png new file mode 100644 index 000000000..9332e2899 Binary files /dev/null and b/images/demos/FlxNapeTerrain.png differ diff --git a/images/demos/FlxNapeTilemap.png b/images/demos/FlxNapeTilemap.png new file mode 100644 index 000000000..c6aaac6cf Binary files /dev/null and b/images/demos/FlxNapeTilemap.png differ diff --git a/images/demos/FlxPexParser.png b/images/demos/FlxPexParser.png new file mode 100644 index 000000000..a01d3a5bd Binary files /dev/null and b/images/demos/FlxPexParser.png differ diff --git a/images/demos/FlxPieDial.png b/images/demos/FlxPieDial.png new file mode 100644 index 000000000..086e5d938 Binary files /dev/null and b/images/demos/FlxPieDial.png differ diff --git a/images/demos/FlxPongApi.png b/images/demos/FlxPongApi.png new file mode 100644 index 000000000..e3708066a Binary files /dev/null and b/images/demos/FlxPongApi.png differ diff --git a/images/demos/FlxRandom.png b/images/demos/FlxRandom.png new file mode 100644 index 000000000..b65c7b8b0 Binary files /dev/null and b/images/demos/FlxRandom.png differ diff --git a/images/demos/FlxScene.png b/images/demos/FlxScene.png new file mode 100644 index 000000000..b0daba885 Binary files /dev/null and b/images/demos/FlxScene.png differ diff --git a/images/demos/FlxShape.png b/images/demos/FlxShape.png new file mode 100644 index 000000000..d12ab1ac8 Binary files /dev/null and b/images/demos/FlxShape.png differ diff --git a/images/demos/FlxSimplex.png b/images/demos/FlxSimplex.png new file mode 100644 index 000000000..a2dbfaf30 Binary files /dev/null and b/images/demos/FlxSimplex.png differ diff --git a/images/demos/FlxSkewedSprite.png b/images/demos/FlxSkewedSprite.png new file mode 100644 index 000000000..5af1deb77 Binary files /dev/null and b/images/demos/FlxSkewedSprite.png differ diff --git a/images/demos/FlxSnake.png b/images/demos/FlxSnake.png new file mode 100644 index 000000000..72f7d16d1 Binary files /dev/null and b/images/demos/FlxSnake.png differ diff --git a/images/demos/FlxSound.png b/images/demos/FlxSound.png new file mode 100644 index 000000000..0bf090e14 Binary files /dev/null and b/images/demos/FlxSound.png differ diff --git a/images/demos/FlxSpine.png b/images/demos/FlxSpine.png new file mode 100644 index 000000000..516d7e0d6 Binary files /dev/null and b/images/demos/FlxSpine.png differ diff --git a/images/demos/FlxSpriteFilters.png b/images/demos/FlxSpriteFilters.png new file mode 100644 index 000000000..84310dd96 Binary files /dev/null and b/images/demos/FlxSpriteFilters.png differ diff --git a/images/demos/FlxTeroids.png b/images/demos/FlxTeroids.png new file mode 100644 index 000000000..ec53c0cf8 Binary files /dev/null and b/images/demos/FlxTeroids.png differ diff --git a/images/demos/FlxTextFormat.png b/images/demos/FlxTextFormat.png new file mode 100644 index 000000000..e5c061df0 Binary files /dev/null and b/images/demos/FlxTextFormat.png differ diff --git a/images/demos/FlxTilemapExt.png b/images/demos/FlxTilemapExt.png new file mode 100644 index 000000000..001eb0061 Binary files /dev/null and b/images/demos/FlxTilemapExt.png differ diff --git a/images/demos/FlxTrailArea.png b/images/demos/FlxTrailArea.png new file mode 100644 index 000000000..9fb34e8a9 Binary files /dev/null and b/images/demos/FlxTrailArea.png differ diff --git a/images/demos/FlxTween.png b/images/demos/FlxTween.png new file mode 100644 index 000000000..05a36cb68 Binary files /dev/null and b/images/demos/FlxTween.png differ diff --git a/images/demos/FlxTypeText.png b/images/demos/FlxTypeText.png new file mode 100644 index 000000000..bb7e4aca5 Binary files /dev/null and b/images/demos/FlxTypeText.png differ diff --git a/images/demos/FrameCollections.png b/images/demos/FrameCollections.png new file mode 100644 index 000000000..04b4874b8 Binary files /dev/null and b/images/demos/FrameCollections.png differ diff --git a/images/demos/GamepadTest.png b/images/demos/GamepadTest.png new file mode 100644 index 000000000..ef4c5099d Binary files /dev/null and b/images/demos/GamepadTest.png differ diff --git a/images/demos/GridMovement.png b/images/demos/GridMovement.png new file mode 100644 index 000000000..932dd8a7b Binary files /dev/null and b/images/demos/GridMovement.png differ diff --git a/images/demos/HeatmapPathfinding.png b/images/demos/HeatmapPathfinding.png new file mode 100644 index 000000000..d5ee0fad4 Binary files /dev/null and b/images/demos/HeatmapPathfinding.png differ diff --git a/images/demos/MinimalistTD.png b/images/demos/MinimalistTD.png new file mode 100644 index 000000000..e34782e53 Binary files /dev/null and b/images/demos/MinimalistTD.png differ diff --git a/images/demos/Mode.png b/images/demos/Mode.png new file mode 100644 index 000000000..154c12026 Binary files /dev/null and b/images/demos/Mode.png differ diff --git a/images/demos/MosaicEffect.png b/images/demos/MosaicEffect.png new file mode 100644 index 000000000..b0a71047f Binary files /dev/null and b/images/demos/MosaicEffect.png differ diff --git a/images/demos/NeonVector.png b/images/demos/NeonVector.png new file mode 100644 index 000000000..105c07aa6 Binary files /dev/null and b/images/demos/NeonVector.png differ diff --git a/images/demos/Parallax.png b/images/demos/Parallax.png new file mode 100644 index 000000000..c87d66dcf Binary files /dev/null and b/images/demos/Parallax.png differ diff --git a/images/demos/Particles.png b/images/demos/Particles.png new file mode 100644 index 000000000..f625dfc9e Binary files /dev/null and b/images/demos/Particles.png differ diff --git a/images/demos/Pathfinding.png b/images/demos/Pathfinding.png new file mode 100644 index 000000000..32009988e Binary files /dev/null and b/images/demos/Pathfinding.png differ diff --git a/images/demos/PixelPerfectCollision.png b/images/demos/PixelPerfectCollision.png new file mode 100644 index 000000000..b76263a8e Binary files /dev/null and b/images/demos/PixelPerfectCollision.png differ diff --git a/images/demos/ProjectJumper.png b/images/demos/ProjectJumper.png new file mode 100644 index 000000000..99223ca13 Binary files /dev/null and b/images/demos/ProjectJumper.png differ diff --git a/images/demos/RPGInterface.png b/images/demos/RPGInterface.png new file mode 100644 index 000000000..74f3003bf Binary files /dev/null and b/images/demos/RPGInterface.png differ diff --git a/images/demos/Replay.png b/images/demos/Replay.png new file mode 100644 index 000000000..2072d5e10 Binary files /dev/null and b/images/demos/Replay.png differ diff --git a/images/demos/Revenge.png b/images/demos/Revenge.png new file mode 100644 index 000000000..ae671c4d2 Binary files /dev/null and b/images/demos/Revenge.png differ diff --git a/images/demos/Save.png b/images/demos/Save.png new file mode 100644 index 000000000..871243df4 Binary files /dev/null and b/images/demos/Save.png differ diff --git a/images/demos/ScaleModes.png b/images/demos/ScaleModes.png new file mode 100644 index 000000000..d3c24adf7 Binary files /dev/null and b/images/demos/ScaleModes.png differ diff --git a/images/demos/SetTileProperties.png b/images/demos/SetTileProperties.png new file mode 100644 index 000000000..433273205 Binary files /dev/null and b/images/demos/SetTileProperties.png differ diff --git a/images/demos/SplitScreen.png b/images/demos/SplitScreen.png new file mode 100644 index 000000000..ebddb8dc3 Binary files /dev/null and b/images/demos/SplitScreen.png differ diff --git a/images/demos/SubState.png b/images/demos/SubState.png new file mode 100644 index 000000000..b37786fb7 Binary files /dev/null and b/images/demos/SubState.png differ diff --git a/images/demos/TexturePackerAtlas.png b/images/demos/TexturePackerAtlas.png new file mode 100644 index 000000000..f79bd2dea Binary files /dev/null and b/images/demos/TexturePackerAtlas.png differ diff --git a/images/demos/TiledEditor.png b/images/demos/TiledEditor.png new file mode 100644 index 000000000..a908a15b8 Binary files /dev/null and b/images/demos/TiledEditor.png differ diff --git a/images/demos/Tilemap.png b/images/demos/Tilemap.png new file mode 100644 index 000000000..295adddf9 Binary files /dev/null and b/images/demos/Tilemap.png differ diff --git a/images/demos/Tooltips.png b/images/demos/Tooltips.png new file mode 100644 index 000000000..e00ef7962 Binary files /dev/null and b/images/demos/Tooltips.png differ diff --git a/images/demos/Transitions.png b/images/demos/Transitions.png new file mode 100644 index 000000000..83e531ab7 Binary files /dev/null and b/images/demos/Transitions.png differ diff --git a/images/demos/TurnBasedRPG.png b/images/demos/TurnBasedRPG.png new file mode 100644 index 000000000..bd8cd476a Binary files /dev/null and b/images/demos/TurnBasedRPG.png differ diff --git a/images/discover-haxeflixel.png b/images/discover-haxeflixel.png new file mode 100644 index 000000000..941b55342 Binary files /dev/null and b/images/discover-haxeflixel.png differ diff --git a/images/favicon.ico b/images/favicon.ico new file mode 100644 index 000000000..62957be82 Binary files /dev/null and b/images/favicon.ico differ diff --git a/images/flixel-logos/HaxeFlixel.png b/images/flixel-logos/HaxeFlixel.png new file mode 100644 index 000000000..b52c0faed Binary files /dev/null and b/images/flixel-logos/HaxeFlixel.png differ diff --git a/images/flixel-logos/HaxeFlixel.svg b/images/flixel-logos/HaxeFlixel.svg new file mode 100644 index 000000000..4ae1e3a1d --- /dev/null +++ b/images/flixel-logos/HaxeFlixel.svg @@ -0,0 +1,10 @@ + + + + + + + + +HaxeFlixel + \ No newline at end of file diff --git a/images/flixel-logos/flixel-addons.png b/images/flixel-logos/flixel-addons.png new file mode 100644 index 000000000..c3627745e Binary files /dev/null and b/images/flixel-logos/flixel-addons.png differ diff --git a/images/flixel-logos/flixel-addons.svg b/images/flixel-logos/flixel-addons.svg new file mode 100644 index 000000000..5612e0d41 --- /dev/null +++ b/images/flixel-logos/flixel-addons.svg @@ -0,0 +1,11 @@ + + + + + + + + + +flixel-addons + \ No newline at end of file diff --git a/images/flixel-logos/flixel-demos.png b/images/flixel-logos/flixel-demos.png new file mode 100644 index 000000000..88e32d406 Binary files /dev/null and b/images/flixel-logos/flixel-demos.png differ diff --git a/images/flixel-logos/flixel-demos.svg b/images/flixel-logos/flixel-demos.svg new file mode 100644 index 000000000..4142ba27f --- /dev/null +++ b/images/flixel-logos/flixel-demos.svg @@ -0,0 +1,11 @@ + + + + + + + + + +flixel-demos + \ No newline at end of file diff --git a/images/flixel-logos/flixel-docs.png b/images/flixel-logos/flixel-docs.png new file mode 100644 index 000000000..9bc7f3764 Binary files /dev/null and b/images/flixel-logos/flixel-docs.png differ diff --git a/images/flixel-logos/flixel-docs.svg b/images/flixel-logos/flixel-docs.svg new file mode 100644 index 000000000..411a3c557 --- /dev/null +++ b/images/flixel-logos/flixel-docs.svg @@ -0,0 +1,11 @@ + + + + + + + + + +flixel-docs + \ No newline at end of file diff --git a/images/flixel-logos/flixel-templates.png b/images/flixel-logos/flixel-templates.png new file mode 100644 index 000000000..aed052cbe Binary files /dev/null and b/images/flixel-logos/flixel-templates.png differ diff --git a/images/flixel-logos/flixel-templates.svg b/images/flixel-logos/flixel-templates.svg new file mode 100644 index 000000000..20746a71c --- /dev/null +++ b/images/flixel-logos/flixel-templates.svg @@ -0,0 +1,11 @@ + + + + + + + + + +flixel-templates + \ No newline at end of file diff --git a/images/flixel-logos/flixel-tools.png b/images/flixel-logos/flixel-tools.png new file mode 100644 index 000000000..d888598f4 Binary files /dev/null and b/images/flixel-logos/flixel-tools.png differ diff --git a/images/flixel-logos/flixel-tools.svg b/images/flixel-logos/flixel-tools.svg new file mode 100644 index 000000000..244b42015 --- /dev/null +++ b/images/flixel-logos/flixel-tools.svg @@ -0,0 +1,11 @@ + + + + + + + + + +flixel-tools + \ No newline at end of file diff --git a/images/flixel-logos/flixel-ui.png b/images/flixel-logos/flixel-ui.png new file mode 100644 index 000000000..31c634cb7 Binary files /dev/null and b/images/flixel-logos/flixel-ui.png differ diff --git a/images/flixel-logos/flixel-ui.svg b/images/flixel-logos/flixel-ui.svg new file mode 100644 index 000000000..f9453b199 --- /dev/null +++ b/images/flixel-logos/flixel-ui.svg @@ -0,0 +1,11 @@ + + + + + + + + + +flixel-ui + \ No newline at end of file diff --git a/images/flixel-logos/haxeflixel-medal.gif b/images/flixel-logos/haxeflixel-medal.gif new file mode 100644 index 000000000..9c1068631 Binary files /dev/null and b/images/flixel-logos/haxeflixel-medal.gif differ diff --git a/images/flixel-logos/haxeflixel.com.png b/images/flixel-logos/haxeflixel.com.png new file mode 100644 index 000000000..25dee802f Binary files /dev/null and b/images/flixel-logos/haxeflixel.com.png differ diff --git a/images/flixel-logos/haxeflixel.com.svg b/images/flixel-logos/haxeflixel.com.svg new file mode 100644 index 000000000..6d6cf63af --- /dev/null +++ b/images/flixel-logos/haxeflixel.com.svg @@ -0,0 +1,11 @@ + + + + + + + + + +haxeflixel.com + \ No newline at end of file diff --git a/images/flixel.svg b/images/flixel.svg new file mode 100644 index 000000000..1e069fb10 --- /dev/null +++ b/images/flixel.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/images/footer-shadow.png b/images/footer-shadow.png new file mode 100644 index 000000000..3ba1ac47a Binary files /dev/null and b/images/footer-shadow.png differ diff --git a/images/haxe.svg b/images/haxe.svg new file mode 100644 index 000000000..92705db59 --- /dev/null +++ b/images/haxe.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/images/haxeflixel-header.png b/images/haxeflixel-header.png new file mode 100644 index 000000000..4ca5bf4b0 Binary files /dev/null and b/images/haxeflixel-header.png differ diff --git a/images/haxeflixel-header.svg b/images/haxeflixel-header.svg new file mode 100644 index 000000000..353bf2035 --- /dev/null +++ b/images/haxeflixel-header.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/images/haxeflixel-logo.png b/images/haxeflixel-logo.png new file mode 100644 index 000000000..4ca5bf4b0 Binary files /dev/null and b/images/haxeflixel-logo.png differ diff --git a/images/haxeflixel.svg b/images/haxeflixel.svg new file mode 100644 index 000000000..38ddf5bd3 --- /dev/null +++ b/images/haxeflixel.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/images/highlight-bg.png b/images/highlight-bg.png new file mode 100644 index 000000000..f4a1f357b Binary files /dev/null and b/images/highlight-bg.png differ diff --git a/images/openfl-logo.png b/images/openfl-logo.png new file mode 100644 index 000000000..ca3c18d89 Binary files /dev/null and b/images/openfl-logo.png differ diff --git a/images/openfl-text-logo.svg b/images/openfl-text-logo.svg new file mode 100644 index 000000000..ab465548f --- /dev/null +++ b/images/openfl-text-logo.svg @@ -0,0 +1,83 @@ + + + +image/svg+xml + + + + + + + + + + \ No newline at end of file diff --git a/images/openfl.jpg b/images/openfl.jpg new file mode 100644 index 000000000..857458694 Binary files /dev/null and b/images/openfl.jpg differ diff --git a/images/openfl.svg b/images/openfl.svg new file mode 100644 index 000000000..535a26293 --- /dev/null +++ b/images/openfl.svg @@ -0,0 +1,34 @@ + + + Slice 1 + Created with Sketch (http://www.bohemiancoding.com/sketch) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/images/patreon-logo.svg b/images/patreon-logo.svg new file mode 100644 index 000000000..4cf79b604 --- /dev/null +++ b/images/patreon-logo.svg @@ -0,0 +1,8 @@ + + + + + diff --git a/images/patreon-wordmark.svg b/images/patreon-wordmark.svg new file mode 100644 index 000000000..0bd8735fb --- /dev/null +++ b/images/patreon-wordmark.svg @@ -0,0 +1,28 @@ + + + + + diff --git a/images/sdl.svg b/images/sdl.svg new file mode 100644 index 000000000..2d6b65e17 --- /dev/null +++ b/images/sdl.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/images/showcase.xcf b/images/showcase.xcf new file mode 100644 index 000000000..ec6c0c4cd Binary files /dev/null and b/images/showcase.xcf differ diff --git a/images/showcase/BOSSES FOREVER 2.BRO.png b/images/showcase/BOSSES FOREVER 2.BRO.png new file mode 100644 index 000000000..26772bcf7 Binary files /dev/null and b/images/showcase/BOSSES FOREVER 2.BRO.png differ diff --git a/images/showcase/Blasting Agent Ultimate Edition.png b/images/showcase/Blasting Agent Ultimate Edition.png new file mode 100644 index 000000000..d56c75400 Binary files /dev/null and b/images/showcase/Blasting Agent Ultimate Edition.png differ diff --git a/images/showcase/Bring It On!.png b/images/showcase/Bring It On!.png new file mode 100644 index 000000000..22db68355 Binary files /dev/null and b/images/showcase/Bring It On!.png differ diff --git a/images/showcase/Bronko Blue.png b/images/showcase/Bronko Blue.png new file mode 100644 index 000000000..c273c57ba Binary files /dev/null and b/images/showcase/Bronko Blue.png differ diff --git a/images/showcase/Canabalt.png b/images/showcase/Canabalt.png new file mode 100644 index 000000000..3303c9e2d Binary files /dev/null and b/images/showcase/Canabalt.png differ diff --git a/images/showcase/Cardinal Quest 2.png b/images/showcase/Cardinal Quest 2.png new file mode 100644 index 000000000..fd61cce5c Binary files /dev/null and b/images/showcase/Cardinal Quest 2.png differ diff --git a/images/showcase/Cheap Golf.png b/images/showcase/Cheap Golf.png new file mode 100644 index 000000000..eae11f8e2 Binary files /dev/null and b/images/showcase/Cheap Golf.png differ diff --git a/images/showcase/Chibi Ninja Shino-kun.png b/images/showcase/Chibi Ninja Shino-kun.png new file mode 100644 index 000000000..db3a1815d Binary files /dev/null and b/images/showcase/Chibi Ninja Shino-kun.png differ diff --git a/images/showcase/Defender's Quest II.png b/images/showcase/Defender's Quest II.png new file mode 100644 index 000000000..b2247e110 Binary files /dev/null and b/images/showcase/Defender's Quest II.png differ diff --git a/images/showcase/Defender's Quest Valley of the Forgotten.png b/images/showcase/Defender's Quest Valley of the Forgotten.png new file mode 100644 index 000000000..f646f7278 Binary files /dev/null and b/images/showcase/Defender's Quest Valley of the Forgotten.png differ diff --git a/images/showcase/Dfragmente.png b/images/showcase/Dfragmente.png new file mode 100644 index 000000000..20dddb9d6 Binary files /dev/null and b/images/showcase/Dfragmente.png differ diff --git a/images/showcase/Don't Move.png b/images/showcase/Don't Move.png new file mode 100644 index 000000000..e67f13c74 Binary files /dev/null and b/images/showcase/Don't Move.png differ diff --git a/images/showcase/Eggsolotl.png b/images/showcase/Eggsolotl.png new file mode 100644 index 000000000..3301a0d53 Binary files /dev/null and b/images/showcase/Eggsolotl.png differ diff --git a/images/showcase/Even the Ocean.png b/images/showcase/Even the Ocean.png new file mode 100644 index 000000000..e85df4e09 Binary files /dev/null and b/images/showcase/Even the Ocean.png differ diff --git a/images/showcase/Fist's Elimination Tower.png b/images/showcase/Fist's Elimination Tower.png new file mode 100644 index 000000000..397dfd760 Binary files /dev/null and b/images/showcase/Fist's Elimination Tower.png differ diff --git a/images/showcase/Flitter Inc..png b/images/showcase/Flitter Inc..png new file mode 100644 index 000000000..1faee6c69 Binary files /dev/null and b/images/showcase/Flitter Inc..png differ diff --git a/images/showcase/Friday Night Funkin'.png b/images/showcase/Friday Night Funkin'.png new file mode 100644 index 000000000..bab75a593 Binary files /dev/null and b/images/showcase/Friday Night Funkin'.png differ diff --git a/images/showcase/Future Knight DX.png b/images/showcase/Future Knight DX.png new file mode 100644 index 000000000..efeb0ca73 Binary files /dev/null and b/images/showcase/Future Knight DX.png differ diff --git a/images/showcase/Future Knight Remake.png b/images/showcase/Future Knight Remake.png new file mode 100644 index 000000000..58728a499 Binary files /dev/null and b/images/showcase/Future Knight Remake.png differ diff --git a/images/showcase/GULAG PARADISE.png b/images/showcase/GULAG PARADISE.png new file mode 100644 index 000000000..fef4710e9 Binary files /dev/null and b/images/showcase/GULAG PARADISE.png differ diff --git a/images/showcase/Genial Santa Claus 2.png b/images/showcase/Genial Santa Claus 2.png new file mode 100644 index 000000000..aacabef87 Binary files /dev/null and b/images/showcase/Genial Santa Claus 2.png differ diff --git a/images/showcase/Glitch Lab.png b/images/showcase/Glitch Lab.png new file mode 100644 index 000000000..6d56fe7cb Binary files /dev/null and b/images/showcase/Glitch Lab.png differ diff --git a/images/showcase/Glorch's Great Escape.png b/images/showcase/Glorch's Great Escape.png new file mode 100644 index 000000000..521a16096 Binary files /dev/null and b/images/showcase/Glorch's Great Escape.png differ diff --git a/images/showcase/Go! Go! PogoGirl.png b/images/showcase/Go! Go! PogoGirl.png new file mode 100644 index 000000000..0c2b677dc Binary files /dev/null and b/images/showcase/Go! Go! PogoGirl.png differ diff --git a/images/showcase/Heck House.png b/images/showcase/Heck House.png new file mode 100644 index 000000000..5ed8a0ec2 Binary files /dev/null and b/images/showcase/Heck House.png differ diff --git "a/images/showcase/Holobunnies Pause Caf\303\251.png" "b/images/showcase/Holobunnies Pause Caf\303\251.png" new file mode 100644 index 000000000..99a31af1b Binary files /dev/null and "b/images/showcase/Holobunnies Pause Caf\303\251.png" differ diff --git a/images/showcase/HyperBoarder.png b/images/showcase/HyperBoarder.png new file mode 100644 index 000000000..8dde73aa5 Binary files /dev/null and b/images/showcase/HyperBoarder.png differ diff --git a/images/showcase/Idle Farmer.png b/images/showcase/Idle Farmer.png new file mode 100644 index 000000000..6abc91e0e Binary files /dev/null and b/images/showcase/Idle Farmer.png differ diff --git a/images/showcase/LAZA KNITEZ!!.png b/images/showcase/LAZA KNITEZ!!.png new file mode 100644 index 000000000..e26279351 Binary files /dev/null and b/images/showcase/LAZA KNITEZ!!.png differ diff --git a/images/showcase/Monster Match.png b/images/showcase/Monster Match.png new file mode 100644 index 000000000..c09aeb7e7 Binary files /dev/null and b/images/showcase/Monster Match.png differ diff --git a/images/showcase/One Ship Two Ship Redshift Blueshift.png b/images/showcase/One Ship Two Ship Redshift Blueshift.png new file mode 100644 index 000000000..c34e1cd79 Binary files /dev/null and b/images/showcase/One Ship Two Ship Redshift Blueshift.png differ diff --git a/images/showcase/Peasant Knight.png b/images/showcase/Peasant Knight.png new file mode 100644 index 000000000..7a7944014 Binary files /dev/null and b/images/showcase/Peasant Knight.png differ diff --git a/images/showcase/Polaritron.png b/images/showcase/Polaritron.png new file mode 100644 index 000000000..d01142550 Binary files /dev/null and b/images/showcase/Polaritron.png differ diff --git a/images/showcase/Renegade Racing.png b/images/showcase/Renegade Racing.png new file mode 100644 index 000000000..ee5c0252f Binary files /dev/null and b/images/showcase/Renegade Racing.png differ diff --git a/images/showcase/SLIDE-0000.png b/images/showcase/SLIDE-0000.png new file mode 100644 index 000000000..a41924030 Binary files /dev/null and b/images/showcase/SLIDE-0000.png differ diff --git a/images/showcase/SUPER Cute Alien.png b/images/showcase/SUPER Cute Alien.png new file mode 100644 index 000000000..e976c25f9 Binary files /dev/null and b/images/showcase/SUPER Cute Alien.png differ diff --git a/images/showcase/Saving Alley Cats!.png b/images/showcase/Saving Alley Cats!.png new file mode 100644 index 000000000..a857bbe4c Binary files /dev/null and b/images/showcase/Saving Alley Cats!.png differ diff --git a/images/showcase/Shifter.png b/images/showcase/Shifter.png new file mode 100644 index 000000000..672b22102 Binary files /dev/null and b/images/showcase/Shifter.png differ diff --git a/images/showcase/Slime Time.png b/images/showcase/Slime Time.png new file mode 100644 index 000000000..c9531ccd6 Binary files /dev/null and b/images/showcase/Slime Time.png differ diff --git a/images/showcase/Solid Aether.png b/images/showcase/Solid Aether.png new file mode 100644 index 000000000..11569e530 Binary files /dev/null and b/images/showcase/Solid Aether.png differ diff --git a/images/showcase/Sort!Sort!Sort!.png b/images/showcase/Sort!Sort!Sort!.png new file mode 100644 index 000000000..4b2f6b712 Binary files /dev/null and b/images/showcase/Sort!Sort!Sort!.png differ diff --git a/images/showcase/Spacejacked.png b/images/showcase/Spacejacked.png new file mode 100644 index 000000000..c872095df Binary files /dev/null and b/images/showcase/Spacejacked.png differ diff --git a/images/showcase/Spooksville, USA.png b/images/showcase/Spooksville, USA.png new file mode 100644 index 000000000..f80c95130 Binary files /dev/null and b/images/showcase/Spooksville, USA.png differ diff --git a/images/showcase/Super Slime Arena.png b/images/showcase/Super Slime Arena.png new file mode 100644 index 000000000..c87e76ba2 Binary files /dev/null and b/images/showcase/Super Slime Arena.png differ diff --git a/images/showcase/The Enchanted Cave 2.png b/images/showcase/The Enchanted Cave 2.png new file mode 100644 index 000000000..6f31938a4 Binary files /dev/null and b/images/showcase/The Enchanted Cave 2.png differ diff --git a/images/showcase/The Wolf's Bite.png b/images/showcase/The Wolf's Bite.png new file mode 100644 index 000000000..105e8563a Binary files /dev/null and b/images/showcase/The Wolf's Bite.png differ diff --git a/images/showcase/Tomb Explorer.png b/images/showcase/Tomb Explorer.png new file mode 100644 index 000000000..17b699d65 Binary files /dev/null and b/images/showcase/Tomb Explorer.png differ diff --git a/images/showcase/UPSQUID.png b/images/showcase/UPSQUID.png new file mode 100644 index 000000000..7433e19ed Binary files /dev/null and b/images/showcase/UPSQUID.png differ diff --git a/images/showcase/Viking Warfare.png b/images/showcase/Viking Warfare.png new file mode 100644 index 000000000..7b8b00c94 Binary files /dev/null and b/images/showcase/Viking Warfare.png differ diff --git a/images/showcase/Werewolf Tycoon.png b/images/showcase/Werewolf Tycoon.png new file mode 100644 index 000000000..6a3e71769 Binary files /dev/null and b/images/showcase/Werewolf Tycoon.png differ diff --git a/images/showcase/Willy and Mathilda's Houseboat Adventure.png b/images/showcase/Willy and Mathilda's Houseboat Adventure.png new file mode 100644 index 000000000..d4c8eab00 Binary files /dev/null and b/images/showcase/Willy and Mathilda's Houseboat Adventure.png differ diff --git a/images/showcase/[Speer DX].png b/images/showcase/[Speer DX].png new file mode 100644 index 000000000..4eb9ba10f Binary files /dev/null and b/images/showcase/[Speer DX].png differ diff --git a/images/showcase/millstone.png b/images/showcase/millstone.png new file mode 100644 index 000000000..7c2f712bd Binary files /dev/null and b/images/showcase/millstone.png differ diff --git a/images/showcase/raw/Defender's Quest II.png b/images/showcase/raw/Defender's Quest II.png new file mode 100644 index 000000000..50941d099 Binary files /dev/null and b/images/showcase/raw/Defender's Quest II.png differ diff --git a/images/showcase/raw/ribbon.png b/images/showcase/raw/ribbon.png new file mode 100644 index 000000000..e445d3681 Binary files /dev/null and b/images/showcase/raw/ribbon.png differ diff --git a/images/showcase/raw/ribbon.svg b/images/showcase/raw/ribbon.svg new file mode 100644 index 000000000..09efa382a --- /dev/null +++ b/images/showcase/raw/ribbon.svg @@ -0,0 +1,78 @@ + + + + + + + + + + image/svg+xml + + + + + + + Coming soon... + + diff --git a/images/showcase/spaceSpuds.png b/images/showcase/spaceSpuds.png new file mode 100644 index 000000000..77f27dc9d Binary files /dev/null and b/images/showcase/spaceSpuds.png differ diff --git a/images/site-bg.png b/images/site-bg.png new file mode 100755 index 000000000..bfd6bf2a6 Binary files /dev/null and b/images/site-bg.png differ diff --git a/images/sponsors/gold/kongregate/kongregate_anthill.png b/images/sponsors/gold/kongregate/kongregate_anthill.png new file mode 100644 index 000000000..f968afcc8 Binary files /dev/null and b/images/sponsors/gold/kongregate/kongregate_anthill.png differ diff --git a/images/sponsors/gold/kongregate/kongregate_anthill.svg b/images/sponsors/gold/kongregate/kongregate_anthill.svg new file mode 100644 index 000000000..41250c211 --- /dev/null +++ b/images/sponsors/gold/kongregate/kongregate_anthill.svg @@ -0,0 +1,1060 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/sponsors/gold/solar-powered/logo-solarpoweredgames-inverted-256.png b/images/sponsors/gold/solar-powered/logo-solarpoweredgames-inverted-256.png new file mode 100644 index 000000000..9e1d6ed1d Binary files /dev/null and b/images/sponsors/gold/solar-powered/logo-solarpoweredgames-inverted-256.png differ diff --git a/images/sponsors/gold/solar-powered/logo-solarpoweredgames-inverted-512.png b/images/sponsors/gold/solar-powered/logo-solarpoweredgames-inverted-512.png new file mode 100644 index 000000000..531bb341c Binary files /dev/null and b/images/sponsors/gold/solar-powered/logo-solarpoweredgames-inverted-512.png differ diff --git a/images/sponsors/platinum/blue-bottle-games/bbgLogo256x256.png b/images/sponsors/platinum/blue-bottle-games/bbgLogo256x256.png new file mode 100644 index 000000000..f32360670 Binary files /dev/null and b/images/sponsors/platinum/blue-bottle-games/bbgLogo256x256.png differ diff --git a/images/sponsors/platinum/blue-bottle-games/bbgLogo512x512.png b/images/sponsors/platinum/blue-bottle-games/bbgLogo512x512.png new file mode 100644 index 000000000..fdf639738 Binary files /dev/null and b/images/sponsors/platinum/blue-bottle-games/bbgLogo512x512.png differ diff --git a/images/sponsors/platinum/blue-bottle-games/bbgLogoColor256x256.png b/images/sponsors/platinum/blue-bottle-games/bbgLogoColor256x256.png new file mode 100644 index 000000000..bfcc79026 Binary files /dev/null and b/images/sponsors/platinum/blue-bottle-games/bbgLogoColor256x256.png differ diff --git a/images/sponsors/platinum/blue-bottle-games/bbgLogoColor512x512.png b/images/sponsors/platinum/blue-bottle-games/bbgLogoColor512x512.png new file mode 100644 index 000000000..539c8b148 Binary files /dev/null and b/images/sponsors/platinum/blue-bottle-games/bbgLogoColor512x512.png differ diff --git a/images/sponsors/platinum/level-up-labs/lul_logo_circle.png b/images/sponsors/platinum/level-up-labs/lul_logo_circle.png new file mode 100644 index 000000000..9a5b264e9 Binary files /dev/null and b/images/sponsors/platinum/level-up-labs/lul_logo_circle.png differ diff --git a/images/sponsors/platinum/level-up-labs/lul_logo_full.png b/images/sponsors/platinum/level-up-labs/lul_logo_full.png new file mode 100644 index 000000000..d496729af Binary files /dev/null and b/images/sponsors/platinum/level-up-labs/lul_logo_full.png differ diff --git a/images/sponsors/platinum/level-up-labs/lul_logo_small_square.png b/images/sponsors/platinum/level-up-labs/lul_logo_small_square.png new file mode 100644 index 000000000..b0a900d1f Binary files /dev/null and b/images/sponsors/platinum/level-up-labs/lul_logo_small_square.png differ diff --git a/images/sponsors/silver/aseprite/aseprite-logo.png b/images/sponsors/silver/aseprite/aseprite-logo.png new file mode 100644 index 000000000..3a9ba59aa Binary files /dev/null and b/images/sponsors/silver/aseprite/aseprite-logo.png differ diff --git a/images/sponsors/silver/ludoko/logotype256.png b/images/sponsors/silver/ludoko/logotype256.png new file mode 100644 index 000000000..30af0cac7 Binary files /dev/null and b/images/sponsors/silver/ludoko/logotype256.png differ diff --git a/images/sponsors/silver/ludoko/logotype256_bw.png b/images/sponsors/silver/ludoko/logotype256_bw.png new file mode 100644 index 000000000..5239149fa Binary files /dev/null and b/images/sponsors/silver/ludoko/logotype256_bw.png differ diff --git a/images/sponsors/silver/ludoko/logotype256_bw_whitetext.png b/images/sponsors/silver/ludoko/logotype256_bw_whitetext.png new file mode 100644 index 000000000..53e40e844 Binary files /dev/null and b/images/sponsors/silver/ludoko/logotype256_bw_whitetext.png differ diff --git a/images/sponsors/silver/ludoko/logotype256_whitetext.png b/images/sponsors/silver/ludoko/logotype256_whitetext.png new file mode 100644 index 000000000..d723ce87e Binary files /dev/null and b/images/sponsors/silver/ludoko/logotype256_whitetext.png differ diff --git a/images/sponsors/silver/ludoko/logotype512.png b/images/sponsors/silver/ludoko/logotype512.png new file mode 100644 index 000000000..d88ebc5cd Binary files /dev/null and b/images/sponsors/silver/ludoko/logotype512.png differ diff --git a/images/sponsors/silver/ludoko/logotype512_bw.png b/images/sponsors/silver/ludoko/logotype512_bw.png new file mode 100644 index 000000000..4b669710c Binary files /dev/null and b/images/sponsors/silver/ludoko/logotype512_bw.png differ diff --git a/images/sponsors/silver/ludoko/logotype512_bw_whitetext.png b/images/sponsors/silver/ludoko/logotype512_bw_whitetext.png new file mode 100644 index 000000000..b4092cbba Binary files /dev/null and b/images/sponsors/silver/ludoko/logotype512_bw_whitetext.png differ diff --git a/images/sponsors/silver/ludoko/logotype512_whitetext.png b/images/sponsors/silver/ludoko/logotype512_whitetext.png new file mode 100644 index 000000000..ad04e564b Binary files /dev/null and b/images/sponsors/silver/ludoko/logotype512_whitetext.png differ diff --git a/images/sponsors/silver/lukehut/lukehut-logo-256.png b/images/sponsors/silver/lukehut/lukehut-logo-256.png new file mode 100644 index 000000000..a52f7a79d Binary files /dev/null and b/images/sponsors/silver/lukehut/lukehut-logo-256.png differ diff --git a/images/sponsors/silver/lukehut/lukehut-logo-512.png b/images/sponsors/silver/lukehut/lukehut-logo-512.png new file mode 100644 index 000000000..9992444f7 Binary files /dev/null and b/images/sponsors/silver/lukehut/lukehut-logo-512.png differ diff --git a/images/sponsors/silver/txori/txori.svg b/images/sponsors/silver/txori/txori.svg new file mode 100644 index 000000000..786b68f09 --- /dev/null +++ b/images/sponsors/silver/txori/txori.svg @@ -0,0 +1,31 @@ + + + + +]> + + + + + + + + + + + + + diff --git a/images/sponsors/silver/txori/txori_nocolor.svg b/images/sponsors/silver/txori/txori_nocolor.svg new file mode 100644 index 000000000..fcb576dd6 --- /dev/null +++ b/images/sponsors/silver/txori/txori_nocolor.svg @@ -0,0 +1,31 @@ + + + + +]> + + + + + + + + + + + + + diff --git a/images/targets/android-logo.svg b/images/targets/android-logo.svg new file mode 100644 index 000000000..9e2173a81 --- /dev/null +++ b/images/targets/android-logo.svg @@ -0,0 +1,68 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/images/targets/apple-logo.svg b/images/targets/apple-logo.svg new file mode 100644 index 000000000..91863387c --- /dev/null +++ b/images/targets/apple-logo.svg @@ -0,0 +1,59 @@ + + + + + + + + image/svg+xml + + Apple Logo + + + + + + + diff --git a/images/targets/blackberry-logo.svg b/images/targets/blackberry-logo.svg new file mode 100644 index 000000000..c74060150 --- /dev/null +++ b/images/targets/blackberry-logo.svg @@ -0,0 +1,98 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/images/targets/flash-logo.svg b/images/targets/flash-logo.svg new file mode 100644 index 000000000..0e239bfd9 --- /dev/null +++ b/images/targets/flash-logo.svg @@ -0,0 +1,56 @@ + + + + + + + + image/svg+xml + + + + + + + + diff --git a/images/targets/github-logo.svg b/images/targets/github-logo.svg new file mode 100644 index 000000000..37fa923df --- /dev/null +++ b/images/targets/github-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/targets/html5-logo.svg b/images/targets/html5-logo.svg new file mode 100644 index 000000000..f74c70b1b --- /dev/null +++ b/images/targets/html5-logo.svg @@ -0,0 +1,54 @@ + + + + + + image/svg+xml + + + + + + + HTML5 Logo Badge + + diff --git a/images/targets/humble-logo.svg b/images/targets/humble-logo.svg new file mode 100644 index 000000000..d049a084d --- /dev/null +++ b/images/targets/humble-logo.svg @@ -0,0 +1,24 @@ + + + + H - White + Created with Sketch. + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/images/targets/ios-logo.png b/images/targets/ios-logo.png new file mode 100644 index 000000000..c11a2b033 Binary files /dev/null and b/images/targets/ios-logo.png differ diff --git a/images/targets/itch-logo.svg b/images/targets/itch-logo.svg new file mode 100644 index 000000000..4a4ac250b --- /dev/null +++ b/images/targets/itch-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/targets/linux-logo.svg b/images/targets/linux-logo.svg new file mode 100644 index 000000000..925939f0a --- /dev/null +++ b/images/targets/linux-logo.svg @@ -0,0 +1,15 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/images/targets/newgrounds-logo.svg b/images/targets/newgrounds-logo.svg new file mode 100644 index 000000000..614f59799 --- /dev/null +++ b/images/targets/newgrounds-logo.svg @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + diff --git a/images/targets/ouya-logo.svg b/images/targets/ouya-logo.svg new file mode 100644 index 000000000..40a691748 --- /dev/null +++ b/images/targets/ouya-logo.svg @@ -0,0 +1,12 @@ + + + Slice 1 + Created with Sketch (http://www.bohemiancoding.com/sketch) + + + + + + + + \ No newline at end of file diff --git a/images/targets/ps-logo.svg b/images/targets/ps-logo.svg new file mode 100644 index 000000000..7764bebfa --- /dev/null +++ b/images/targets/ps-logo.svg @@ -0,0 +1,67 @@ + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/images/targets/steam-logo.svg b/images/targets/steam-logo.svg new file mode 100644 index 000000000..a7c9d2461 --- /dev/null +++ b/images/targets/steam-logo.svg @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/images/targets/switch-logo.svg b/images/targets/switch-logo.svg new file mode 100644 index 000000000..9c0ad5145 --- /dev/null +++ b/images/targets/switch-logo.svg @@ -0,0 +1,69 @@ + + + + + +Created by potrace 1.13, written by Peter Selinger 2001-2015 + + + image/svg+xml + + + + + + + + + + diff --git a/images/targets/windows-logo.svg b/images/targets/windows-logo.svg new file mode 100644 index 000000000..9722d4c97 --- /dev/null +++ b/images/targets/windows-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/targets/xbox-logo.svg b/images/targets/xbox-logo.svg new file mode 100644 index 000000000..3765f8b4a --- /dev/null +++ b/images/targets/xbox-logo.svg @@ -0,0 +1,68 @@ + + + + + Xbox Logo + + + + image/svg+xml + + Xbox Logo + + + + + + + + + diff --git a/img/-Sj6dYEkaR-500.png b/img/-Sj6dYEkaR-500.png new file mode 100644 index 000000000..dfadb8d30 Binary files /dev/null and b/img/-Sj6dYEkaR-500.png differ diff --git a/img/-WZKiW85FK-190.png b/img/-WZKiW85FK-190.png new file mode 100644 index 000000000..aab2f0810 Binary files /dev/null and b/img/-WZKiW85FK-190.png differ diff --git a/img/-mtXjeEUa2-70.png b/img/-mtXjeEUa2-70.png new file mode 100644 index 000000000..4b2dc41db Binary files /dev/null and b/img/-mtXjeEUa2-70.png differ diff --git a/img/-vgKp93k3k-190.png b/img/-vgKp93k3k-190.png new file mode 100644 index 000000000..327a99ea9 Binary files /dev/null and b/img/-vgKp93k3k-190.png differ diff --git a/img/0FNNcbKeJ8-190.png b/img/0FNNcbKeJ8-190.png new file mode 100644 index 000000000..12391c090 Binary files /dev/null and b/img/0FNNcbKeJ8-190.png differ diff --git a/img/0cjG6YHzNn-190.png b/img/0cjG6YHzNn-190.png new file mode 100644 index 000000000..3d15c113e Binary files /dev/null and b/img/0cjG6YHzNn-190.png differ diff --git a/img/1SRz1xYIIc-345.png b/img/1SRz1xYIIc-345.png new file mode 100644 index 000000000..fe7875305 Binary files /dev/null and b/img/1SRz1xYIIc-345.png differ diff --git a/img/1T_St2pqxb-190.png b/img/1T_St2pqxb-190.png new file mode 100644 index 000000000..b7c96e1d7 Binary files /dev/null and b/img/1T_St2pqxb-190.png differ diff --git a/img/1TemQh-yVL-190.png b/img/1TemQh-yVL-190.png new file mode 100644 index 000000000..2850fd392 Binary files /dev/null and b/img/1TemQh-yVL-190.png differ diff --git a/img/2Zz0vots9k-70.png b/img/2Zz0vots9k-70.png new file mode 100644 index 000000000..5097a828f Binary files /dev/null and b/img/2Zz0vots9k-70.png differ diff --git a/img/2y8Lkzb0dE-70.png b/img/2y8Lkzb0dE-70.png new file mode 100644 index 000000000..ba60ef685 Binary files /dev/null and b/img/2y8Lkzb0dE-70.png differ diff --git a/img/3NXRWH7_Wd-500.png b/img/3NXRWH7_Wd-500.png new file mode 100644 index 000000000..c7e0753ae Binary files /dev/null and b/img/3NXRWH7_Wd-500.png differ diff --git a/img/3TWCGqeWc1-190.png b/img/3TWCGqeWc1-190.png new file mode 100644 index 000000000..914476206 Binary files /dev/null and b/img/3TWCGqeWc1-190.png differ diff --git a/img/3_YAsCvhPf-190.png b/img/3_YAsCvhPf-190.png new file mode 100644 index 000000000..883d21398 Binary files /dev/null and b/img/3_YAsCvhPf-190.png differ diff --git a/img/40GISMb-eK-190.png b/img/40GISMb-eK-190.png new file mode 100644 index 000000000..5bc04eb43 Binary files /dev/null and b/img/40GISMb-eK-190.png differ diff --git a/img/45WyOf-3fK-345.png b/img/45WyOf-3fK-345.png new file mode 100644 index 000000000..8a91a88d0 Binary files /dev/null and b/img/45WyOf-3fK-345.png differ diff --git a/img/4KrJsA0eyn-70.png b/img/4KrJsA0eyn-70.png new file mode 100644 index 000000000..539589918 Binary files /dev/null and b/img/4KrJsA0eyn-70.png differ diff --git a/img/4WdbK5WEP2-345.png b/img/4WdbK5WEP2-345.png new file mode 100644 index 000000000..d5f3bd7f8 Binary files /dev/null and b/img/4WdbK5WEP2-345.png differ diff --git a/img/4kHOArBn0P-345.png b/img/4kHOArBn0P-345.png new file mode 100644 index 000000000..e7c427188 Binary files /dev/null and b/img/4kHOArBn0P-345.png differ diff --git a/img/4rG4yqTMOY-190.png b/img/4rG4yqTMOY-190.png new file mode 100644 index 000000000..e1bc2ded6 Binary files /dev/null and b/img/4rG4yqTMOY-190.png differ diff --git a/img/50ywStP0IL-345.png b/img/50ywStP0IL-345.png new file mode 100644 index 000000000..74b38de87 Binary files /dev/null and b/img/50ywStP0IL-345.png differ diff --git a/img/5U5WPafU9y-70.png b/img/5U5WPafU9y-70.png new file mode 100644 index 000000000..3f38c05ae Binary files /dev/null and b/img/5U5WPafU9y-70.png differ diff --git a/img/6LSyTQpiUO-160.png b/img/6LSyTQpiUO-160.png new file mode 100644 index 000000000..81fbfb2a5 Binary files /dev/null and b/img/6LSyTQpiUO-160.png differ diff --git a/img/77t9CqnHio-345.png b/img/77t9CqnHio-345.png new file mode 100644 index 000000000..bc8bbc4f2 Binary files /dev/null and b/img/77t9CqnHio-345.png differ diff --git a/img/7bYh9u3fHh-190.png b/img/7bYh9u3fHh-190.png new file mode 100644 index 000000000..e27405519 Binary files /dev/null and b/img/7bYh9u3fHh-190.png differ diff --git a/img/7cGuekZ4qQ-190.png b/img/7cGuekZ4qQ-190.png new file mode 100644 index 000000000..6659699ef Binary files /dev/null and b/img/7cGuekZ4qQ-190.png differ diff --git a/img/7oVGGyB_6--190.png b/img/7oVGGyB_6--190.png new file mode 100644 index 000000000..39f48d885 Binary files /dev/null and b/img/7oVGGyB_6--190.png differ diff --git a/img/8M5-TvC3IU-70.png b/img/8M5-TvC3IU-70.png new file mode 100644 index 000000000..d0b31e31d Binary files /dev/null and b/img/8M5-TvC3IU-70.png differ diff --git a/img/8SGJrrhGxJ-70.png b/img/8SGJrrhGxJ-70.png new file mode 100644 index 000000000..7acda0425 Binary files /dev/null and b/img/8SGJrrhGxJ-70.png differ diff --git a/img/8oy8WUoHuB-190.png b/img/8oy8WUoHuB-190.png new file mode 100644 index 000000000..521a1ebbf Binary files /dev/null and b/img/8oy8WUoHuB-190.png differ diff --git a/img/9XoANB5Nsu-190.png b/img/9XoANB5Nsu-190.png new file mode 100644 index 000000000..bd5bc17eb Binary files /dev/null and b/img/9XoANB5Nsu-190.png differ diff --git a/img/9Zsrgy6xdE-190.png b/img/9Zsrgy6xdE-190.png new file mode 100644 index 000000000..751546c51 Binary files /dev/null and b/img/9Zsrgy6xdE-190.png differ diff --git a/img/9rOJMsP9Wy-190.png b/img/9rOJMsP9Wy-190.png new file mode 100644 index 000000000..9d3de1596 Binary files /dev/null and b/img/9rOJMsP9Wy-190.png differ diff --git a/img/ARjAJnclMs-190.png b/img/ARjAJnclMs-190.png new file mode 100644 index 000000000..f8ee257aa Binary files /dev/null and b/img/ARjAJnclMs-190.png differ diff --git a/img/BCjPUjuJ8T-190.png b/img/BCjPUjuJ8T-190.png new file mode 100644 index 000000000..08cd39330 Binary files /dev/null and b/img/BCjPUjuJ8T-190.png differ diff --git a/img/BPwu2IXtG4-70.png b/img/BPwu2IXtG4-70.png new file mode 100644 index 000000000..291bdfe1a Binary files /dev/null and b/img/BPwu2IXtG4-70.png differ diff --git a/img/Bb00opaufk-70.png b/img/Bb00opaufk-70.png new file mode 100644 index 000000000..2eaed68f3 Binary files /dev/null and b/img/Bb00opaufk-70.png differ diff --git a/img/BuQUD7MKMY-345.png b/img/BuQUD7MKMY-345.png new file mode 100644 index 000000000..68f1b3e1d Binary files /dev/null and b/img/BuQUD7MKMY-345.png differ diff --git a/img/CjluTE4WdT-345.png b/img/CjluTE4WdT-345.png new file mode 100644 index 000000000..c9f9f5771 Binary files /dev/null and b/img/CjluTE4WdT-345.png differ diff --git a/img/CupougKmr1-190.png b/img/CupougKmr1-190.png new file mode 100644 index 000000000..2433a5d14 Binary files /dev/null and b/img/CupougKmr1-190.png differ diff --git a/img/D2dVPScivh-500.png b/img/D2dVPScivh-500.png new file mode 100644 index 000000000..1ee211689 Binary files /dev/null and b/img/D2dVPScivh-500.png differ diff --git a/img/D7j4R4ZHag-345.png b/img/D7j4R4ZHag-345.png new file mode 100644 index 000000000..3b2ffe5f6 Binary files /dev/null and b/img/D7j4R4ZHag-345.png differ diff --git a/img/DG7oCS8HCW-70.png b/img/DG7oCS8HCW-70.png new file mode 100644 index 000000000..375e08820 Binary files /dev/null and b/img/DG7oCS8HCW-70.png differ diff --git a/img/Dt3XwPTCKP-160.png b/img/Dt3XwPTCKP-160.png new file mode 100644 index 000000000..1bf022037 Binary files /dev/null and b/img/Dt3XwPTCKP-160.png differ diff --git a/img/Dwl21CD7lv-70.png b/img/Dwl21CD7lv-70.png new file mode 100644 index 000000000..8a43dabf3 Binary files /dev/null and b/img/Dwl21CD7lv-70.png differ diff --git a/img/E4Sw8emk_F-190.png b/img/E4Sw8emk_F-190.png new file mode 100644 index 000000000..6ffbb429a Binary files /dev/null and b/img/E4Sw8emk_F-190.png differ diff --git a/img/EQDZfHJCXT-190.png b/img/EQDZfHJCXT-190.png new file mode 100644 index 000000000..83b44bebe Binary files /dev/null and b/img/EQDZfHJCXT-190.png differ diff --git a/img/ETqvW6XJJJ-345.png b/img/ETqvW6XJJJ-345.png new file mode 100644 index 000000000..f81744fca Binary files /dev/null and b/img/ETqvW6XJJJ-345.png differ diff --git a/img/FB_apkuTDr-190.png b/img/FB_apkuTDr-190.png new file mode 100644 index 000000000..81dc7a404 Binary files /dev/null and b/img/FB_apkuTDr-190.png differ diff --git a/img/GKiw1_WDfj-345.png b/img/GKiw1_WDfj-345.png new file mode 100644 index 000000000..985261502 Binary files /dev/null and b/img/GKiw1_WDfj-345.png differ diff --git a/img/H1i6tMKCgG-70.png b/img/H1i6tMKCgG-70.png new file mode 100644 index 000000000..e2e2b4691 Binary files /dev/null and b/img/H1i6tMKCgG-70.png differ diff --git a/img/HRqFNLgLLW-500.png b/img/HRqFNLgLLW-500.png new file mode 100644 index 000000000..3861ae954 Binary files /dev/null and b/img/HRqFNLgLLW-500.png differ diff --git a/img/H_qGc6MVpP-70.png b/img/H_qGc6MVpP-70.png new file mode 100644 index 000000000..6ceb2f794 Binary files /dev/null and b/img/H_qGc6MVpP-70.png differ diff --git a/img/I18rOd7b4x-70.png b/img/I18rOd7b4x-70.png new file mode 100644 index 000000000..b8df1fa7f Binary files /dev/null and b/img/I18rOd7b4x-70.png differ diff --git a/img/I5dPZcwzpS-190.png b/img/I5dPZcwzpS-190.png new file mode 100644 index 000000000..659943781 Binary files /dev/null and b/img/I5dPZcwzpS-190.png differ diff --git a/img/IVlu3ZWz1O-70.png b/img/IVlu3ZWz1O-70.png new file mode 100644 index 000000000..1d43e28f9 Binary files /dev/null and b/img/IVlu3ZWz1O-70.png differ diff --git a/img/IZ17_p9gYf-190.png b/img/IZ17_p9gYf-190.png new file mode 100644 index 000000000..73ad01bd4 Binary files /dev/null and b/img/IZ17_p9gYf-190.png differ diff --git a/img/IphGadmtH6-190.png b/img/IphGadmtH6-190.png new file mode 100644 index 000000000..778f79d1e Binary files /dev/null and b/img/IphGadmtH6-190.png differ diff --git a/img/IrbEINVxhA-190.png b/img/IrbEINVxhA-190.png new file mode 100644 index 000000000..5f7701422 Binary files /dev/null and b/img/IrbEINVxhA-190.png differ diff --git a/img/J6XlpxRw6h-190.png b/img/J6XlpxRw6h-190.png new file mode 100644 index 000000000..e7fb1aea3 Binary files /dev/null and b/img/J6XlpxRw6h-190.png differ diff --git a/img/Jkkz53MJ-k-345.png b/img/Jkkz53MJ-k-345.png new file mode 100644 index 000000000..6a529c0fc Binary files /dev/null and b/img/Jkkz53MJ-k-345.png differ diff --git a/img/KUUWueus4x-70.png b/img/KUUWueus4x-70.png new file mode 100644 index 000000000..510232bc5 Binary files /dev/null and b/img/KUUWueus4x-70.png differ diff --git a/img/KyT-s4N-Hk-70.png b/img/KyT-s4N-Hk-70.png new file mode 100644 index 000000000..b47c6b5f3 Binary files /dev/null and b/img/KyT-s4N-Hk-70.png differ diff --git a/img/LS2vrEZrnp-70.png b/img/LS2vrEZrnp-70.png new file mode 100644 index 000000000..86352edb2 Binary files /dev/null and b/img/LS2vrEZrnp-70.png differ diff --git a/img/M4bT7albjw-345.png b/img/M4bT7albjw-345.png new file mode 100644 index 000000000..8dae11029 Binary files /dev/null and b/img/M4bT7albjw-345.png differ diff --git a/img/MSTaI8cpsH-70.png b/img/MSTaI8cpsH-70.png new file mode 100644 index 000000000..74abfbb2f Binary files /dev/null and b/img/MSTaI8cpsH-70.png differ diff --git a/img/MYJL2Cx4f9-190.png b/img/MYJL2Cx4f9-190.png new file mode 100644 index 000000000..9e75dbb9d Binary files /dev/null and b/img/MYJL2Cx4f9-190.png differ diff --git a/img/NMnh2XY8Zl-160.png b/img/NMnh2XY8Zl-160.png new file mode 100644 index 000000000..b920b84dd Binary files /dev/null and b/img/NMnh2XY8Zl-160.png differ diff --git a/img/NOvOuM6YBC-190.png b/img/NOvOuM6YBC-190.png new file mode 100644 index 000000000..135cd694b Binary files /dev/null and b/img/NOvOuM6YBC-190.png differ diff --git a/img/Nwy0g7ihoy-70.png b/img/Nwy0g7ihoy-70.png new file mode 100644 index 000000000..a86899da9 Binary files /dev/null and b/img/Nwy0g7ihoy-70.png differ diff --git a/img/O1WRx9iC84-345.png b/img/O1WRx9iC84-345.png new file mode 100644 index 000000000..1a7661311 Binary files /dev/null and b/img/O1WRx9iC84-345.png differ diff --git a/img/OG5snczQKF-190.png b/img/OG5snczQKF-190.png new file mode 100644 index 000000000..1783f2f82 Binary files /dev/null and b/img/OG5snczQKF-190.png differ diff --git a/img/OM87glflIX-70.png b/img/OM87glflIX-70.png new file mode 100644 index 000000000..831933439 Binary files /dev/null and b/img/OM87glflIX-70.png differ diff --git a/img/OT7GDS1uhJ-190.png b/img/OT7GDS1uhJ-190.png new file mode 100644 index 000000000..3688ed339 Binary files /dev/null and b/img/OT7GDS1uhJ-190.png differ diff --git a/img/OYPUg5Kg8z-190.png b/img/OYPUg5Kg8z-190.png new file mode 100644 index 000000000..30c2d9fad Binary files /dev/null and b/img/OYPUg5Kg8z-190.png differ diff --git a/img/OlUqudf6-n-190.png b/img/OlUqudf6-n-190.png new file mode 100644 index 000000000..95a42e0b0 Binary files /dev/null and b/img/OlUqudf6-n-190.png differ diff --git a/img/Ow0s4_XtYl-345.png b/img/Ow0s4_XtYl-345.png new file mode 100644 index 000000000..402117522 Binary files /dev/null and b/img/Ow0s4_XtYl-345.png differ diff --git a/img/PdRDkjNl8A-190.png b/img/PdRDkjNl8A-190.png new file mode 100644 index 000000000..e1440f4f1 Binary files /dev/null and b/img/PdRDkjNl8A-190.png differ diff --git a/img/PzJSs7oRus-70.png b/img/PzJSs7oRus-70.png new file mode 100644 index 000000000..e1639921d Binary files /dev/null and b/img/PzJSs7oRus-70.png differ diff --git a/img/QJE0t1VZBm-70.png b/img/QJE0t1VZBm-70.png new file mode 100644 index 000000000..1f0de806b Binary files /dev/null and b/img/QJE0t1VZBm-70.png differ diff --git a/img/QfJ37gpRpi-190.png b/img/QfJ37gpRpi-190.png new file mode 100644 index 000000000..366170d58 Binary files /dev/null and b/img/QfJ37gpRpi-190.png differ diff --git a/img/RQBjsZ6m8k-190.png b/img/RQBjsZ6m8k-190.png new file mode 100644 index 000000000..495d13563 Binary files /dev/null and b/img/RQBjsZ6m8k-190.png differ diff --git a/img/RSpOB-EqiC-70.png b/img/RSpOB-EqiC-70.png new file mode 100644 index 000000000..df01a7a34 Binary files /dev/null and b/img/RSpOB-EqiC-70.png differ diff --git a/img/RnqM4seRVH-190.png b/img/RnqM4seRVH-190.png new file mode 100644 index 000000000..c0b79cfdb Binary files /dev/null and b/img/RnqM4seRVH-190.png differ diff --git a/img/RoPikhHZx8-190.png b/img/RoPikhHZx8-190.png new file mode 100644 index 000000000..98f52225f Binary files /dev/null and b/img/RoPikhHZx8-190.png differ diff --git a/img/SBGCUXDedu-190.png b/img/SBGCUXDedu-190.png new file mode 100644 index 000000000..73e72d71c Binary files /dev/null and b/img/SBGCUXDedu-190.png differ diff --git a/img/SQs_430MYm-70.png b/img/SQs_430MYm-70.png new file mode 100644 index 000000000..cb10624fb Binary files /dev/null and b/img/SQs_430MYm-70.png differ diff --git a/img/ScyX9BPuOI-70.png b/img/ScyX9BPuOI-70.png new file mode 100644 index 000000000..4a17bcd66 Binary files /dev/null and b/img/ScyX9BPuOI-70.png differ diff --git a/img/SwKZY8wWY3-70.png b/img/SwKZY8wWY3-70.png new file mode 100644 index 000000000..0671c7df3 Binary files /dev/null and b/img/SwKZY8wWY3-70.png differ diff --git a/img/TWG6WkIhpM-190.png b/img/TWG6WkIhpM-190.png new file mode 100644 index 000000000..ccc3d584b Binary files /dev/null and b/img/TWG6WkIhpM-190.png differ diff --git a/img/U6iSVURDe8-345.png b/img/U6iSVURDe8-345.png new file mode 100644 index 000000000..925f0ce10 Binary files /dev/null and b/img/U6iSVURDe8-345.png differ diff --git a/img/UQdOaT-M7O-345.png b/img/UQdOaT-M7O-345.png new file mode 100644 index 000000000..cb7ecf369 Binary files /dev/null and b/img/UQdOaT-M7O-345.png differ diff --git a/img/UUdazRtv8a-345.png b/img/UUdazRtv8a-345.png new file mode 100644 index 000000000..d38240eec Binary files /dev/null and b/img/UUdazRtv8a-345.png differ diff --git a/img/Ugh1RN6lnU-190.png b/img/Ugh1RN6lnU-190.png new file mode 100644 index 000000000..f67afc221 Binary files /dev/null and b/img/Ugh1RN6lnU-190.png differ diff --git a/img/UgyYMhM3IF-70.png b/img/UgyYMhM3IF-70.png new file mode 100644 index 000000000..d3b240bc4 Binary files /dev/null and b/img/UgyYMhM3IF-70.png differ diff --git a/img/V_jpzIjeJ7-345.png b/img/V_jpzIjeJ7-345.png new file mode 100644 index 000000000..eb4bcf910 Binary files /dev/null and b/img/V_jpzIjeJ7-345.png differ diff --git a/img/Ve_3xm0DOU-70.png b/img/Ve_3xm0DOU-70.png new file mode 100644 index 000000000..861c1dc0e Binary files /dev/null and b/img/Ve_3xm0DOU-70.png differ diff --git a/img/Vl6P4ncYvX-190.png b/img/Vl6P4ncYvX-190.png new file mode 100644 index 000000000..b5f47af1b Binary files /dev/null and b/img/Vl6P4ncYvX-190.png differ diff --git a/img/Vto2vrbYgv-70.png b/img/Vto2vrbYgv-70.png new file mode 100644 index 000000000..52bbe4901 Binary files /dev/null and b/img/Vto2vrbYgv-70.png differ diff --git a/img/W6vswqafsb-70.png b/img/W6vswqafsb-70.png new file mode 100644 index 000000000..389279b12 Binary files /dev/null and b/img/W6vswqafsb-70.png differ diff --git a/img/W7nG69CBkh-70.png b/img/W7nG69CBkh-70.png new file mode 100644 index 000000000..6957d8c9b Binary files /dev/null and b/img/W7nG69CBkh-70.png differ diff --git a/img/WZ3z3P7JRM-70.png b/img/WZ3z3P7JRM-70.png new file mode 100644 index 000000000..880071b6d Binary files /dev/null and b/img/WZ3z3P7JRM-70.png differ diff --git a/img/WaumSw8puB-190.png b/img/WaumSw8puB-190.png new file mode 100644 index 000000000..6f672479d Binary files /dev/null and b/img/WaumSw8puB-190.png differ diff --git a/img/WjXBpnI0z9-190.png b/img/WjXBpnI0z9-190.png new file mode 100644 index 000000000..5f01610ad Binary files /dev/null and b/img/WjXBpnI0z9-190.png differ diff --git a/img/X5mJmcbkrO-345.png b/img/X5mJmcbkrO-345.png new file mode 100644 index 000000000..b412c8e78 Binary files /dev/null and b/img/X5mJmcbkrO-345.png differ diff --git a/img/XDTUGSKT1Y-70.png b/img/XDTUGSKT1Y-70.png new file mode 100644 index 000000000..127c98a8b Binary files /dev/null and b/img/XDTUGSKT1Y-70.png differ diff --git a/img/XNTnrVw-vC-345.png b/img/XNTnrVw-vC-345.png new file mode 100644 index 000000000..1e848b30f Binary files /dev/null and b/img/XNTnrVw-vC-345.png differ diff --git a/img/XVJZ3vXYuN-70.png b/img/XVJZ3vXYuN-70.png new file mode 100644 index 000000000..bf513b444 Binary files /dev/null and b/img/XVJZ3vXYuN-70.png differ diff --git a/img/XmNguaoj0m-190.png b/img/XmNguaoj0m-190.png new file mode 100644 index 000000000..4657d92d0 Binary files /dev/null and b/img/XmNguaoj0m-190.png differ diff --git a/img/YCEY-EdeM_-70.png b/img/YCEY-EdeM_-70.png new file mode 100644 index 000000000..4c22996c4 Binary files /dev/null and b/img/YCEY-EdeM_-70.png differ diff --git a/img/YUKYCikuhf-190.png b/img/YUKYCikuhf-190.png new file mode 100644 index 000000000..f57b2ae4f Binary files /dev/null and b/img/YUKYCikuhf-190.png differ diff --git a/img/Yp1dvkpkVT-70.png b/img/Yp1dvkpkVT-70.png new file mode 100644 index 000000000..4ce19a3fd Binary files /dev/null and b/img/Yp1dvkpkVT-70.png differ diff --git a/img/ZQkM1ZDPDp-190.png b/img/ZQkM1ZDPDp-190.png new file mode 100644 index 000000000..a06fe7b8a Binary files /dev/null and b/img/ZQkM1ZDPDp-190.png differ diff --git a/img/_DWvAZxydH-70.png b/img/_DWvAZxydH-70.png new file mode 100644 index 000000000..fcc69ebc3 Binary files /dev/null and b/img/_DWvAZxydH-70.png differ diff --git a/img/_J8bdY3dKA-70.png b/img/_J8bdY3dKA-70.png new file mode 100644 index 000000000..aa8db2483 Binary files /dev/null and b/img/_J8bdY3dKA-70.png differ diff --git a/img/_W77a1WDFT-345.png b/img/_W77a1WDFT-345.png new file mode 100644 index 000000000..32b05458d Binary files /dev/null and b/img/_W77a1WDFT-345.png differ diff --git a/img/_Ygx-qyGas-70.png b/img/_Ygx-qyGas-70.png new file mode 100644 index 000000000..34f5b32dc Binary files /dev/null and b/img/_Ygx-qyGas-70.png differ diff --git a/img/aFiH7aeoe2-70.png b/img/aFiH7aeoe2-70.png new file mode 100644 index 000000000..0df3befd0 Binary files /dev/null and b/img/aFiH7aeoe2-70.png differ diff --git a/img/apCjJxXFAT-190.png b/img/apCjJxXFAT-190.png new file mode 100644 index 000000000..dc98003ec Binary files /dev/null and b/img/apCjJxXFAT-190.png differ diff --git a/img/b_5YcqRX3t-190.png b/img/b_5YcqRX3t-190.png new file mode 100644 index 000000000..f4006eb6b Binary files /dev/null and b/img/b_5YcqRX3t-190.png differ diff --git a/img/borFyH2zCq-190.png b/img/borFyH2zCq-190.png new file mode 100644 index 000000000..7f9aa8406 Binary files /dev/null and b/img/borFyH2zCq-190.png differ diff --git a/img/btPQpUCEGS-70.png b/img/btPQpUCEGS-70.png new file mode 100644 index 000000000..8971c1bb7 Binary files /dev/null and b/img/btPQpUCEGS-70.png differ diff --git a/img/d6aGiPFv61-345.png b/img/d6aGiPFv61-345.png new file mode 100644 index 000000000..37a37cad0 Binary files /dev/null and b/img/d6aGiPFv61-345.png differ diff --git a/img/dD6t4Swi4G-190.png b/img/dD6t4Swi4G-190.png new file mode 100644 index 000000000..9f4f13039 Binary files /dev/null and b/img/dD6t4Swi4G-190.png differ diff --git a/img/dX2SzcUeBV-345.png b/img/dX2SzcUeBV-345.png new file mode 100644 index 000000000..065e1a8f6 Binary files /dev/null and b/img/dX2SzcUeBV-345.png differ diff --git a/img/e6PJVAr4gh-70.png b/img/e6PJVAr4gh-70.png new file mode 100644 index 000000000..ea3f0a520 Binary files /dev/null and b/img/e6PJVAr4gh-70.png differ diff --git a/img/ea6ncWkcsD-70.png b/img/ea6ncWkcsD-70.png new file mode 100644 index 000000000..c66c34270 Binary files /dev/null and b/img/ea6ncWkcsD-70.png differ diff --git a/img/egrlnDpaDR-70.png b/img/egrlnDpaDR-70.png new file mode 100644 index 000000000..2d3c29fa8 Binary files /dev/null and b/img/egrlnDpaDR-70.png differ diff --git a/img/fYe_1RqJGQ-70.png b/img/fYe_1RqJGQ-70.png new file mode 100644 index 000000000..3818ef611 Binary files /dev/null and b/img/fYe_1RqJGQ-70.png differ diff --git a/img/faS4uiaJSZ-345.png b/img/faS4uiaJSZ-345.png new file mode 100644 index 000000000..93947dbaa Binary files /dev/null and b/img/faS4uiaJSZ-345.png differ diff --git a/img/fq8xOYBtMj-70.png b/img/fq8xOYBtMj-70.png new file mode 100644 index 000000000..3e510c5eb Binary files /dev/null and b/img/fq8xOYBtMj-70.png differ diff --git a/img/g37XWC3c3U-345.png b/img/g37XWC3c3U-345.png new file mode 100644 index 000000000..cd14dd60e Binary files /dev/null and b/img/g37XWC3c3U-345.png differ diff --git a/img/gBEMYHjd0U-70.png b/img/gBEMYHjd0U-70.png new file mode 100644 index 000000000..da7f01655 Binary files /dev/null and b/img/gBEMYHjd0U-70.png differ diff --git a/img/gGykIZad3o-160.png b/img/gGykIZad3o-160.png new file mode 100644 index 000000000..5068c94c5 Binary files /dev/null and b/img/gGykIZad3o-160.png differ diff --git a/img/gJZQZDzDHD-190.png b/img/gJZQZDzDHD-190.png new file mode 100644 index 000000000..971900938 Binary files /dev/null and b/img/gJZQZDzDHD-190.png differ diff --git a/img/gfigMvgmCK-190.png b/img/gfigMvgmCK-190.png new file mode 100644 index 000000000..9de053221 Binary files /dev/null and b/img/gfigMvgmCK-190.png differ diff --git a/img/ggceZx6i1--345.png b/img/ggceZx6i1--345.png new file mode 100644 index 000000000..95b7fd08e Binary files /dev/null and b/img/ggceZx6i1--345.png differ diff --git a/img/h2K-p0OjOC-70.png b/img/h2K-p0OjOC-70.png new file mode 100644 index 000000000..a31b83249 Binary files /dev/null and b/img/h2K-p0OjOC-70.png differ diff --git a/img/hS77AUflYu-345.png b/img/hS77AUflYu-345.png new file mode 100644 index 000000000..96e348c5c Binary files /dev/null and b/img/hS77AUflYu-345.png differ diff --git a/img/hjG9NoxM3o-70.png b/img/hjG9NoxM3o-70.png new file mode 100644 index 000000000..4e3c4483b Binary files /dev/null and b/img/hjG9NoxM3o-70.png differ diff --git a/img/i3zxifHYIp-70.png b/img/i3zxifHYIp-70.png new file mode 100644 index 000000000..7fcc5b721 Binary files /dev/null and b/img/i3zxifHYIp-70.png differ diff --git a/img/iAu6FDHCdp-190.png b/img/iAu6FDHCdp-190.png new file mode 100644 index 000000000..48a17ff65 Binary files /dev/null and b/img/iAu6FDHCdp-190.png differ diff --git a/img/iPqRy1TYoW-190.png b/img/iPqRy1TYoW-190.png new file mode 100644 index 000000000..d2a4d2f30 Binary files /dev/null and b/img/iPqRy1TYoW-190.png differ diff --git a/img/icUHFkYb7L-190.png b/img/icUHFkYb7L-190.png new file mode 100644 index 000000000..156274ad0 Binary files /dev/null and b/img/icUHFkYb7L-190.png differ diff --git a/img/imR-ldQb34-70.png b/img/imR-ldQb34-70.png new file mode 100644 index 000000000..c0ec75589 Binary files /dev/null and b/img/imR-ldQb34-70.png differ diff --git a/img/j9B1z4mYt4-190.png b/img/j9B1z4mYt4-190.png new file mode 100644 index 000000000..7a58b6913 Binary files /dev/null and b/img/j9B1z4mYt4-190.png differ diff --git a/img/jDnmZigRD1-70.png b/img/jDnmZigRD1-70.png new file mode 100644 index 000000000..77ee4a406 Binary files /dev/null and b/img/jDnmZigRD1-70.png differ diff --git a/img/jIXv2gvWt5-190.png b/img/jIXv2gvWt5-190.png new file mode 100644 index 000000000..832141e6a Binary files /dev/null and b/img/jIXv2gvWt5-190.png differ diff --git a/img/jxLpKeIGnz-190.png b/img/jxLpKeIGnz-190.png new file mode 100644 index 000000000..3e51c0803 Binary files /dev/null and b/img/jxLpKeIGnz-190.png differ diff --git a/img/k8yA8ncnUK-345.png b/img/k8yA8ncnUK-345.png new file mode 100644 index 000000000..8fbee6c9d Binary files /dev/null and b/img/k8yA8ncnUK-345.png differ diff --git a/img/kOoOz4rgsV-70.png b/img/kOoOz4rgsV-70.png new file mode 100644 index 000000000..eb6f64bd7 Binary files /dev/null and b/img/kOoOz4rgsV-70.png differ diff --git a/img/k_1csJMDy_-70.png b/img/k_1csJMDy_-70.png new file mode 100644 index 000000000..e26be0509 Binary files /dev/null and b/img/k_1csJMDy_-70.png differ diff --git a/img/ke93AsqQeH-345.png b/img/ke93AsqQeH-345.png new file mode 100644 index 000000000..bcee6717a Binary files /dev/null and b/img/ke93AsqQeH-345.png differ diff --git a/img/kfA7EDxCLO-190.png b/img/kfA7EDxCLO-190.png new file mode 100644 index 000000000..cea3d9e00 Binary files /dev/null and b/img/kfA7EDxCLO-190.png differ diff --git a/img/ksoRzEj969-70.png b/img/ksoRzEj969-70.png new file mode 100644 index 000000000..68a98c85d Binary files /dev/null and b/img/ksoRzEj969-70.png differ diff --git a/img/ktWKl8eb4X-345.png b/img/ktWKl8eb4X-345.png new file mode 100644 index 000000000..e2c4b94c7 Binary files /dev/null and b/img/ktWKl8eb4X-345.png differ diff --git a/img/lG5HI7XnNQ-70.png b/img/lG5HI7XnNQ-70.png new file mode 100644 index 000000000..6fea468c8 Binary files /dev/null and b/img/lG5HI7XnNQ-70.png differ diff --git a/img/lcJKGwrvFA-190.png b/img/lcJKGwrvFA-190.png new file mode 100644 index 000000000..30376324a Binary files /dev/null and b/img/lcJKGwrvFA-190.png differ diff --git a/img/lh5Qr0J1Jo-190.png b/img/lh5Qr0J1Jo-190.png new file mode 100644 index 000000000..140dde0a4 Binary files /dev/null and b/img/lh5Qr0J1Jo-190.png differ diff --git a/img/llMpODTPPH-70.png b/img/llMpODTPPH-70.png new file mode 100644 index 000000000..10e2a964f Binary files /dev/null and b/img/llMpODTPPH-70.png differ diff --git a/img/m7sfAfFfcI-345.png b/img/m7sfAfFfcI-345.png new file mode 100644 index 000000000..7f997e384 Binary files /dev/null and b/img/m7sfAfFfcI-345.png differ diff --git a/img/n0PqDu19dN-70.png b/img/n0PqDu19dN-70.png new file mode 100644 index 000000000..b4428342a Binary files /dev/null and b/img/n0PqDu19dN-70.png differ diff --git a/img/nGETI4TTPU-190.png b/img/nGETI4TTPU-190.png new file mode 100644 index 000000000..30c424402 Binary files /dev/null and b/img/nGETI4TTPU-190.png differ diff --git a/img/nc18lMmzph-345.png b/img/nc18lMmzph-345.png new file mode 100644 index 000000000..2d0ef2487 Binary files /dev/null and b/img/nc18lMmzph-345.png differ diff --git a/img/nfp5L76vcr-70.png b/img/nfp5L76vcr-70.png new file mode 100644 index 000000000..de618c16c Binary files /dev/null and b/img/nfp5L76vcr-70.png differ diff --git a/img/nzTe2BrQjr-190.png b/img/nzTe2BrQjr-190.png new file mode 100644 index 000000000..19fdb5d93 Binary files /dev/null and b/img/nzTe2BrQjr-190.png differ diff --git a/img/o4HlgDzGde-70.png b/img/o4HlgDzGde-70.png new file mode 100644 index 000000000..aa810fa92 Binary files /dev/null and b/img/o4HlgDzGde-70.png differ diff --git a/img/o6SLAGyB8a-190.png b/img/o6SLAGyB8a-190.png new file mode 100644 index 000000000..19fb272f5 Binary files /dev/null and b/img/o6SLAGyB8a-190.png differ diff --git a/img/oD7IDcIu8D-70.png b/img/oD7IDcIu8D-70.png new file mode 100644 index 000000000..d6e01bf84 Binary files /dev/null and b/img/oD7IDcIu8D-70.png differ diff --git a/img/ohfUR-xfn2-190.png b/img/ohfUR-xfn2-190.png new file mode 100644 index 000000000..1f39b5b92 Binary files /dev/null and b/img/ohfUR-xfn2-190.png differ diff --git a/img/ott6DJNhzO-345.png b/img/ott6DJNhzO-345.png new file mode 100644 index 000000000..fd462d93f Binary files /dev/null and b/img/ott6DJNhzO-345.png differ diff --git a/img/oyeDP55y9i-345.png b/img/oyeDP55y9i-345.png new file mode 100644 index 000000000..a224ff7c4 Binary files /dev/null and b/img/oyeDP55y9i-345.png differ diff --git a/img/pN_gFP3Jrd-70.png b/img/pN_gFP3Jrd-70.png new file mode 100644 index 000000000..f7d25c1c8 Binary files /dev/null and b/img/pN_gFP3Jrd-70.png differ diff --git a/img/pWjvvUlSqL-500.png b/img/pWjvvUlSqL-500.png new file mode 100644 index 000000000..c885975da Binary files /dev/null and b/img/pWjvvUlSqL-500.png differ diff --git a/img/peqSfMQ3SW-345.png b/img/peqSfMQ3SW-345.png new file mode 100644 index 000000000..bca29e734 Binary files /dev/null and b/img/peqSfMQ3SW-345.png differ diff --git a/img/pg0vFqDr5i-345.png b/img/pg0vFqDr5i-345.png new file mode 100644 index 000000000..8803b41a4 Binary files /dev/null and b/img/pg0vFqDr5i-345.png differ diff --git a/img/prPc-DoArN-70.png b/img/prPc-DoArN-70.png new file mode 100644 index 000000000..62718f50e Binary files /dev/null and b/img/prPc-DoArN-70.png differ diff --git a/img/qBzdl9Wx5L-190.png b/img/qBzdl9Wx5L-190.png new file mode 100644 index 000000000..2cb080ca3 Binary files /dev/null and b/img/qBzdl9Wx5L-190.png differ diff --git a/img/qZx1f162zB-190.png b/img/qZx1f162zB-190.png new file mode 100644 index 000000000..4c92e6920 Binary files /dev/null and b/img/qZx1f162zB-190.png differ diff --git a/img/qar9aOQSM4-190.png b/img/qar9aOQSM4-190.png new file mode 100644 index 000000000..5c64b90f4 Binary files /dev/null and b/img/qar9aOQSM4-190.png differ diff --git a/img/qixY3fC4EO-70.png b/img/qixY3fC4EO-70.png new file mode 100644 index 000000000..4b32b6745 Binary files /dev/null and b/img/qixY3fC4EO-70.png differ diff --git a/img/qndur4CsHk-190.png b/img/qndur4CsHk-190.png new file mode 100644 index 000000000..86114807c Binary files /dev/null and b/img/qndur4CsHk-190.png differ diff --git a/img/rYHUwZJLQg-345.png b/img/rYHUwZJLQg-345.png new file mode 100644 index 000000000..fb94e1ad3 Binary files /dev/null and b/img/rYHUwZJLQg-345.png differ diff --git a/img/s12ZDsnf8N-70.png b/img/s12ZDsnf8N-70.png new file mode 100644 index 000000000..55d9c905b Binary files /dev/null and b/img/s12ZDsnf8N-70.png differ diff --git a/img/s6pOfJuoRC-345.png b/img/s6pOfJuoRC-345.png new file mode 100644 index 000000000..db52270f9 Binary files /dev/null and b/img/s6pOfJuoRC-345.png differ diff --git a/img/sIqTTPwBNQ-70.png b/img/sIqTTPwBNQ-70.png new file mode 100644 index 000000000..49427afc1 Binary files /dev/null and b/img/sIqTTPwBNQ-70.png differ diff --git a/img/sKi5ShiLQ--70.png b/img/sKi5ShiLQ--70.png new file mode 100644 index 000000000..918a7303a Binary files /dev/null and b/img/sKi5ShiLQ--70.png differ diff --git a/img/sRF6piCbQ3-345.png b/img/sRF6piCbQ3-345.png new file mode 100644 index 000000000..8236b8514 Binary files /dev/null and b/img/sRF6piCbQ3-345.png differ diff --git a/img/ssmsDlZZDr-160.png b/img/ssmsDlZZDr-160.png new file mode 100644 index 000000000..936d07df9 Binary files /dev/null and b/img/ssmsDlZZDr-160.png differ diff --git a/img/t-yWoMN2rG-70.png b/img/t-yWoMN2rG-70.png new file mode 100644 index 000000000..c923fb6e5 Binary files /dev/null and b/img/t-yWoMN2rG-70.png differ diff --git a/img/tLmr0MJcfR-190.png b/img/tLmr0MJcfR-190.png new file mode 100644 index 000000000..7977b0aaf Binary files /dev/null and b/img/tLmr0MJcfR-190.png differ diff --git a/img/tXZFVUUexO-190.png b/img/tXZFVUUexO-190.png new file mode 100644 index 000000000..7facde3ed Binary files /dev/null and b/img/tXZFVUUexO-190.png differ diff --git a/img/tnFy541nb1-70.png b/img/tnFy541nb1-70.png new file mode 100644 index 000000000..9034621ae Binary files /dev/null and b/img/tnFy541nb1-70.png differ diff --git a/img/tnvmJVwfme-345.png b/img/tnvmJVwfme-345.png new file mode 100644 index 000000000..e5363836a Binary files /dev/null and b/img/tnvmJVwfme-345.png differ diff --git a/img/u9NLfshB-S-345.png b/img/u9NLfshB-S-345.png new file mode 100644 index 000000000..bb1f1012c Binary files /dev/null and b/img/u9NLfshB-S-345.png differ diff --git a/img/uCRXLDhdxO-190.png b/img/uCRXLDhdxO-190.png new file mode 100644 index 000000000..3d70a28c3 Binary files /dev/null and b/img/uCRXLDhdxO-190.png differ diff --git a/img/v7N8A9enAV-500.png b/img/v7N8A9enAV-500.png new file mode 100644 index 000000000..6033caab5 Binary files /dev/null and b/img/v7N8A9enAV-500.png differ diff --git a/img/vLTwUmubrc-345.png b/img/vLTwUmubrc-345.png new file mode 100644 index 000000000..95be8912d Binary files /dev/null and b/img/vLTwUmubrc-345.png differ diff --git a/img/vmGJwckt-d-345.png b/img/vmGJwckt-d-345.png new file mode 100644 index 000000000..3d7665de4 Binary files /dev/null and b/img/vmGJwckt-d-345.png differ diff --git a/img/wYnkCev6Yu-70.png b/img/wYnkCev6Yu-70.png new file mode 100644 index 000000000..0a0ca90c5 Binary files /dev/null and b/img/wYnkCev6Yu-70.png differ diff --git a/img/x93w_sCXNr-70.png b/img/x93w_sCXNr-70.png new file mode 100644 index 000000000..f4d7f07a1 Binary files /dev/null and b/img/x93w_sCXNr-70.png differ diff --git a/img/xZCPZGFwkF-345.png b/img/xZCPZGFwkF-345.png new file mode 100644 index 000000000..63d6cf7d0 Binary files /dev/null and b/img/xZCPZGFwkF-345.png differ diff --git a/img/xcWjfOAvli-500.png b/img/xcWjfOAvli-500.png new file mode 100644 index 000000000..acc5c8fc5 Binary files /dev/null and b/img/xcWjfOAvli-500.png differ diff --git a/img/xfxSpYw5D_-70.png b/img/xfxSpYw5D_-70.png new file mode 100644 index 000000000..3b20b37b6 Binary files /dev/null and b/img/xfxSpYw5D_-70.png differ diff --git a/img/xxw_xGFY7S-70.png b/img/xxw_xGFY7S-70.png new file mode 100644 index 000000000..b463066b1 Binary files /dev/null and b/img/xxw_xGFY7S-70.png differ diff --git a/img/y-hi_Q_dfb-160.png b/img/y-hi_Q_dfb-160.png new file mode 100644 index 000000000..bf9850b93 Binary files /dev/null and b/img/y-hi_Q_dfb-160.png differ diff --git a/img/yDKFcOk-zt-70.png b/img/yDKFcOk-zt-70.png new file mode 100644 index 000000000..8612072be Binary files /dev/null and b/img/yDKFcOk-zt-70.png differ diff --git a/img/yID7IgsuIy-70.png b/img/yID7IgsuIy-70.png new file mode 100644 index 000000000..4270ba1fa Binary files /dev/null and b/img/yID7IgsuIy-70.png differ diff --git a/img/zG3R4If8vB-190.png b/img/zG3R4If8vB-190.png new file mode 100644 index 000000000..5e16509e0 Binary files /dev/null and b/img/zG3R4If8vB-190.png differ diff --git a/img/zZjbBc1Tiv-70.png b/img/zZjbBc1Tiv-70.png new file mode 100644 index 000000000..7c7a48bb4 Binary files /dev/null and b/img/zZjbBc1Tiv-70.png differ diff --git a/img/zbJ-X6OLNI-190.png b/img/zbJ-X6OLNI-190.png new file mode 100644 index 000000000..9639a782c Binary files /dev/null and b/img/zbJ-X6OLNI-190.png differ diff --git a/img/zmT33jU3p1-190.png b/img/zmT33jU3p1-190.png new file mode 100644 index 000000000..18fac844c Binary files /dev/null and b/img/zmT33jU3p1-190.png differ diff --git a/index.html b/index.html new file mode 100644 index 000000000..249b60520 --- /dev/null +++ b/index.html @@ -0,0 +1,340 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+
+ + + +

HaxeFlixel

+ +

Create cross-platform games easier and free.
All with one codebase.

+ +

+ Getting Started + GitHub +

+ +
+ +
+ + + + + +
+ + + + + +
+ Discord + Patreon + +
+ +
+ +
+ +
+ +

Cross-compile your games natively to:

+ +
+ Windows + Linux + Mac + Android + iOS + Flash + HTML5 +
+
+ +
+ +
+ +

Browse and learn from our 77 demos:

+ + + + + + #{{demo.data.title}} + + + + + + #{{demo.data.title}} + + + + + + #{{demo.data.title}} + + + + + + #{{demo.data.title}} + + + + + + #{{demo.data.title}} + + + + + + #{{demo.data.title}} + + + +
+ +
+ + +
+ +

Powered by open source cross-platform tech:

+ +
+ + Haxe Logo + + + + + OpenFL Logo + + + + + Flixel Logo + + = + + HaxeFlixel logo + +

+ +
+ +
+ +
+ +
+ +

Our platinum and gold sponsors:

+ + + +
+ + + See all our Sponsors + + +
+ +
+ + + + + + + + + + + + + + diff --git a/showcase/BOSSES FOREVER 2.BRO/index.html b/showcase/BOSSES FOREVER 2.BRO/index.html new file mode 100644 index 000000000..9f516f7d7 --- /dev/null +++ b/showcase/BOSSES FOREVER 2.BRO/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

BOSSES FOREVER 2.BRO

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Blasting Agent Ultimate Edition/index.html b/showcase/Blasting Agent Ultimate Edition/index.html new file mode 100644 index 000000000..1208cd4dc --- /dev/null +++ b/showcase/Blasting Agent Ultimate Edition/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Blasting Agent: Ultimate Edition

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Bring It On!/index.html b/showcase/Bring It On!/index.html new file mode 100644 index 000000000..bbbf1fb83 --- /dev/null +++ b/showcase/Bring It On!/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Bring It On!

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Bronko Blue/index.html b/showcase/Bronko Blue/index.html new file mode 100644 index 000000000..9310bbcbf --- /dev/null +++ b/showcase/Bronko Blue/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Bronko Blue

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Canabalt/index.html b/showcase/Canabalt/index.html new file mode 100644 index 000000000..f9646cc8c --- /dev/null +++ b/showcase/Canabalt/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Canabalt

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Cardinal Quest 2/index.html b/showcase/Cardinal Quest 2/index.html new file mode 100644 index 000000000..98d98774b --- /dev/null +++ b/showcase/Cardinal Quest 2/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Cardinal Quest 2

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Cheap Golf/index.html b/showcase/Cheap Golf/index.html new file mode 100644 index 000000000..840e9f922 --- /dev/null +++ b/showcase/Cheap Golf/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Cheap Golf

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Chibi Ninja Shino-kun/index.html b/showcase/Chibi Ninja Shino-kun/index.html new file mode 100644 index 000000000..441e54d23 --- /dev/null +++ b/showcase/Chibi Ninja Shino-kun/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Chibi Ninja Shino-kun

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Defender's Quest II/index.html b/showcase/Defender's Quest II/index.html new file mode 100644 index 000000000..ff9fa229d --- /dev/null +++ b/showcase/Defender's Quest II/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Defender's Quest II

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Defender's Quest Valley of the Forgotten/index.html b/showcase/Defender's Quest Valley of the Forgotten/index.html new file mode 100644 index 000000000..bfc7174af --- /dev/null +++ b/showcase/Defender's Quest Valley of the Forgotten/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Defender's Quest: Valley of the Forgotten

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Dfragmente/index.html b/showcase/Dfragmente/index.html new file mode 100644 index 000000000..6ea625fe5 --- /dev/null +++ b/showcase/Dfragmente/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Dfragmente

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Don't Move/index.html b/showcase/Don't Move/index.html new file mode 100644 index 000000000..3628e85e4 --- /dev/null +++ b/showcase/Don't Move/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Don't Move

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Eggsolotl/index.html b/showcase/Eggsolotl/index.html new file mode 100644 index 000000000..54e23be6d --- /dev/null +++ b/showcase/Eggsolotl/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Eggsolotl

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Even the Ocean/index.html b/showcase/Even the Ocean/index.html new file mode 100644 index 000000000..851584617 --- /dev/null +++ b/showcase/Even the Ocean/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Even the Ocean

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Fist's Elimination Tower/index.html b/showcase/Fist's Elimination Tower/index.html new file mode 100644 index 000000000..5b9bf39c8 --- /dev/null +++ b/showcase/Fist's Elimination Tower/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Fist's Elimination Tower

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Flitter Inc./index.html b/showcase/Flitter Inc./index.html new file mode 100644 index 000000000..b27287caa --- /dev/null +++ b/showcase/Flitter Inc./index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Flitter Inc.

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Friday Night Funkin'/index.html b/showcase/Friday Night Funkin'/index.html new file mode 100644 index 000000000..ae243ad78 --- /dev/null +++ b/showcase/Friday Night Funkin'/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Friday Night Funkin'

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Future Knight DX/index.html b/showcase/Future Knight DX/index.html new file mode 100644 index 000000000..c85879fae --- /dev/null +++ b/showcase/Future Knight DX/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Future Knight DX

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/GULAG PARADISE/index.html b/showcase/GULAG PARADISE/index.html new file mode 100644 index 000000000..84af459ff --- /dev/null +++ b/showcase/GULAG PARADISE/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

GULAG PARADISE

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Genial Santa Claus 2/index.html b/showcase/Genial Santa Claus 2/index.html new file mode 100644 index 000000000..79f7fcc60 --- /dev/null +++ b/showcase/Genial Santa Claus 2/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Genial Santa Claus 2

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Glitch Lab/index.html b/showcase/Glitch Lab/index.html new file mode 100644 index 000000000..e307d1149 --- /dev/null +++ b/showcase/Glitch Lab/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Glitch Lab

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Glorch's Great Escape/index.html b/showcase/Glorch's Great Escape/index.html new file mode 100644 index 000000000..fa80379db --- /dev/null +++ b/showcase/Glorch's Great Escape/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Glorch's Great Escape

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Go! Go! PogoGirl/index.html b/showcase/Go! Go! PogoGirl/index.html new file mode 100644 index 000000000..1a535c56d --- /dev/null +++ b/showcase/Go! Go! PogoGirl/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Go! Go! PogoGirl

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Heck House/index.html b/showcase/Heck House/index.html new file mode 100644 index 000000000..674127dda --- /dev/null +++ b/showcase/Heck House/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Heck House

+ + + + +
+ + + + + + + + + + + + diff --git "a/showcase/Holobunnies Pause Caf\303\251/index.html" "b/showcase/Holobunnies Pause Caf\303\251/index.html" new file mode 100644 index 000000000..9c2b43a57 --- /dev/null +++ "b/showcase/Holobunnies Pause Caf\303\251/index.html" @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Holobunnies: Pause Café

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/HyperBoarder/index.html b/showcase/HyperBoarder/index.html new file mode 100644 index 000000000..50f2e244b --- /dev/null +++ b/showcase/HyperBoarder/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

HyperBoarder

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Idle Farmer/index.html b/showcase/Idle Farmer/index.html new file mode 100644 index 000000000..995b028ae --- /dev/null +++ b/showcase/Idle Farmer/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Idle Farmer

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/LAZA KNITEZ!!/index.html b/showcase/LAZA KNITEZ!!/index.html new file mode 100644 index 000000000..196eb3fc1 --- /dev/null +++ b/showcase/LAZA KNITEZ!!/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

LAZA KNITEZ!!

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Monster Match/index.html b/showcase/Monster Match/index.html new file mode 100644 index 000000000..9fcc10bcd --- /dev/null +++ b/showcase/Monster Match/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Monster Match

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/One Ship Two Ship Redshift Blueshift/index.html b/showcase/One Ship Two Ship Redshift Blueshift/index.html new file mode 100644 index 000000000..8eadb7b19 --- /dev/null +++ b/showcase/One Ship Two Ship Redshift Blueshift/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

One Ship Two Ship Redshift Blueshift

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Peasant Knight/index.html b/showcase/Peasant Knight/index.html new file mode 100644 index 000000000..348a7eec1 --- /dev/null +++ b/showcase/Peasant Knight/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Peasant Knight

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Polaritron/index.html b/showcase/Polaritron/index.html new file mode 100644 index 000000000..3e9acd214 --- /dev/null +++ b/showcase/Polaritron/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Polaritron

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Renegade Racing/index.html b/showcase/Renegade Racing/index.html new file mode 100644 index 000000000..d0d676771 --- /dev/null +++ b/showcase/Renegade Racing/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Renegade Racing

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/SLIDE-0000/index.html b/showcase/SLIDE-0000/index.html new file mode 100644 index 000000000..b46e02105 --- /dev/null +++ b/showcase/SLIDE-0000/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

SLIDE-0000

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Saving Alley Cats!/index.html b/showcase/Saving Alley Cats!/index.html new file mode 100644 index 000000000..aab1c0605 --- /dev/null +++ b/showcase/Saving Alley Cats!/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Saving Alley Cats!

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Shifter/index.html b/showcase/Shifter/index.html new file mode 100644 index 000000000..6c5ffc8e0 --- /dev/null +++ b/showcase/Shifter/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Shifter

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Slime Time/index.html b/showcase/Slime Time/index.html new file mode 100644 index 000000000..15de42aff --- /dev/null +++ b/showcase/Slime Time/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Slime Time

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Solid Aether/index.html b/showcase/Solid Aether/index.html new file mode 100644 index 000000000..7ff876cdc --- /dev/null +++ b/showcase/Solid Aether/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Solid Aether

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Sort!Sort!Sort!/index.html b/showcase/Sort!Sort!Sort!/index.html new file mode 100644 index 000000000..59d9b7455 --- /dev/null +++ b/showcase/Sort!Sort!Sort!/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Sort!Sort!Sort!

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Spacejacked/index.html b/showcase/Spacejacked/index.html new file mode 100644 index 000000000..14695a4fa --- /dev/null +++ b/showcase/Spacejacked/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Spacejacked

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Spooksville, USA/index.html b/showcase/Spooksville, USA/index.html new file mode 100644 index 000000000..9d38771b8 --- /dev/null +++ b/showcase/Spooksville, USA/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Spooksville, USA

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Super Slime Arena/index.html b/showcase/Super Slime Arena/index.html new file mode 100644 index 000000000..dab7f6efb --- /dev/null +++ b/showcase/Super Slime Arena/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Super Slime Arena

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/The Enchanted Cave 2/index.html b/showcase/The Enchanted Cave 2/index.html new file mode 100644 index 000000000..335d1240c --- /dev/null +++ b/showcase/The Enchanted Cave 2/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

The Enchanted Cave 2

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/The Wolf's Bite/index.html b/showcase/The Wolf's Bite/index.html new file mode 100644 index 000000000..d978338ba --- /dev/null +++ b/showcase/The Wolf's Bite/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

The Wolf's Bite

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Tomb Explorer/index.html b/showcase/Tomb Explorer/index.html new file mode 100644 index 000000000..48b89f22d --- /dev/null +++ b/showcase/Tomb Explorer/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Tomb Explorer

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/UPSQUID/index.html b/showcase/UPSQUID/index.html new file mode 100644 index 000000000..1260982b6 --- /dev/null +++ b/showcase/UPSQUID/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

UPSQUID

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Viking Warfare/index.html b/showcase/Viking Warfare/index.html new file mode 100644 index 000000000..bc2d7f4a0 --- /dev/null +++ b/showcase/Viking Warfare/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Viking Warfare

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Werewolf Tycoon/index.html b/showcase/Werewolf Tycoon/index.html new file mode 100644 index 000000000..c405a82fd --- /dev/null +++ b/showcase/Werewolf Tycoon/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Werewolf Tycoon

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/Willy and Mathilda's Houseboat Adventure/index.html b/showcase/Willy and Mathilda's Houseboat Adventure/index.html new file mode 100644 index 000000000..3be132bda --- /dev/null +++ b/showcase/Willy and Mathilda's Houseboat Adventure/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Willy and Mathilda's Houseboat Adventure

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/[Speer DX]/index.html b/showcase/[Speer DX]/index.html new file mode 100644 index 000000000..27a22211c --- /dev/null +++ b/showcase/[Speer DX]/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

[Speer DX]

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/index.html b/showcase/index.html new file mode 100644 index 000000000..91e3f6b35 --- /dev/null +++ b/showcase/index.html @@ -0,0 +1,3590 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

Showcase

+ + + + + + +
+ +
+ + + + + + + +
+ +

Canabalt

+ + + + + Canabalt + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Chibi Ninja Shino-kun

+ + + + + Chibi Ninja Shino-kun + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + +
+ +

Bring It On!

+ + + + + Bring It On! + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +

Go! Go! PogoGirl

+ + + + + Go! Go! PogoGirl + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + +
+ +

Friday Night Funkin'

+ + + + + Friday Night Funkin' + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Renegade Racing

+ + + + + Renegade Racing + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

Defender's Quest: Valley of the Forgotten

+ + + + + Defender's Quest: Valley of the Forgotten + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + +
+ +

Defender's Quest II

+ + + + + Defender's Quest II + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + +
+ +

[Speer DX]

+ + + + + [Speer DX] + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Future Knight DX

+ + + + + Future Knight DX + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +

millstone

+ + + + + millstone + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +

UPSQUID

+ + + + + UPSQUID + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Eggsolotl

+ + + + + Eggsolotl + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Spooksville, USA

+ + + + + Spooksville, USA + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + +
+ +

Heck House

+ + + + + Heck House + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Monster Match

+ + + + + Monster Match + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Peasant Knight

+ + + + + Peasant Knight + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Solid Aether

+ + + + + Solid Aether + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Flitter Inc.

+ + + + + Flitter Inc. + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Super Slime Arena

+ + + + + Super Slime Arena + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Cheap Golf

+ + + + + Cheap Golf + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Even the Ocean

+ + + + + Even the Ocean + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Fist's Elimination Tower

+ + + + + Fist's Elimination Tower + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Glorch's Great Escape

+ + + + + Glorch's Great Escape + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

The Wolf's Bite

+ + + + + The Wolf's Bite + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Holobunnies: Pause Café

+ + + + + Holobunnies: Pause Café + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Tomb Explorer

+ + + + + Tomb Explorer + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Slime Time

+ + + + + Slime Time + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Willy and Mathilda's Houseboat Adventure

+ + + + + Willy and Mathilda's Houseboat Adventure + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Blasting Agent: Ultimate Edition

+ + + + + Blasting Agent: Ultimate Edition + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+ +

One Ship Two Ship Redshift Blueshift

+ + + + + One Ship Two Ship Redshift Blueshift + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

HyperBoarder

+ + + + + HyperBoarder + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Sort!Sort!Sort!

+ + + + + Sort!Sort!Sort! + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Genial Santa Claus 2

+ + + + + Genial Santa Claus 2 + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

The Enchanted Cave 2

+ + + + + The Enchanted Cave 2 + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Werewolf Tycoon

+ + + + + Werewolf Tycoon + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Spacejacked

+ + + + + Spacejacked + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Shifter

+ + + + + Shifter + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Dfragmente

+ + + + + Dfragmente + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Viking Warfare

+ + + + + Viking Warfare + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Polaritron

+ + + + + Polaritron + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

LAZA KNITEZ!!

+ + + + + LAZA KNITEZ!! + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Glitch Lab

+ + + + + Glitch Lab + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Cardinal Quest 2

+ + + + + Cardinal Quest 2 + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

spaceSpuds

+ + + + + spaceSpuds + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Idle Farmer

+ + + + + Idle Farmer + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Bronko Blue

+ + + + + Bronko Blue + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Saving Alley Cats!

+ + + + + Saving Alley Cats! + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

SLIDE-0000

+ + + + + SLIDE-0000 + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

GULAG PARADISE

+ + + + + GULAG PARADISE + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

BOSSES FOREVER 2.BRO

+ + + + + BOSSES FOREVER 2.BRO + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + +
+ +

Don't Move

+ + + + + Don't Move + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + +
+ + +
+ + + + + + + + + + + + diff --git a/showcase/millstone/index.html b/showcase/millstone/index.html new file mode 100644 index 000000000..91eae4074 --- /dev/null +++ b/showcase/millstone/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

millstone

+ + + + +
+ + + + + + + + + + + + diff --git a/showcase/spaceSpuds/index.html b/showcase/spaceSpuds/index.html new file mode 100644 index 000000000..ace722ef7 --- /dev/null +++ b/showcase/spaceSpuds/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +

spaceSpuds

+ + + + +
+ + + + + + + + + + + + diff --git a/sponsors/index.html b/sponsors/index.html new file mode 100644 index 000000000..a1bf41a60 --- /dev/null +++ b/sponsors/index.html @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+ +

Sponsors

+ +
+ +
+ + +
+ + + + +
+ + + + + + + + + + + + diff --git a/styles/highlighting.less b/styles/highlighting.less new file mode 100644 index 000000000..a543526a4 --- /dev/null +++ b/styles/highlighting.less @@ -0,0 +1,29 @@ +pre { + background-color: #1E1E1E; + display: block; + overflow-x: auto; + font-family: Monaco, Menlo, Consolas, "Courier New", monospace; + font-size: 14px; + color: #FFFFFF; +} +.highlighted .mtk1 { color: #FFFFFF; } +.highlighted .mtk2 { color: #FFFFFF; } +.highlighted .mtk3 { color: #6796E6; } +.highlighted .mtk4 { color: #608B4E; } +.highlighted .mtk5 { color: #569CD6; } +.highlighted .mtk6 { color: #D16969; } +.highlighted .mtk7 { color: #D7BA7D; } +.highlighted .mtk8 { color: #B5CEA8; } +.highlighted .mtk9 { color: #CE9178; } +.highlighted .mtk10 { color: #646695; } +.highlighted .mtk11 { color: #4EC9B0; } +.highlighted .mtk12 { color: #DCDCAA; } +.highlighted .mtk13 { color: #9CDCFE; } +.highlighted .mtk14 { color: #000080; } +.highlighted .mtk15 { color: #F44747; } +.highlighted .mtk16 { color: #C586C0; } +.highlighted .mtk17 { color: #D4D4D4; } +.highlighted .mtk18 { color: #808080; } +.highlighted .mtki { font-style: italic; } +.highlighted .mtkb { font-weight: bold; } +.highlighted .mtku { text-decoration: underline; } diff --git a/styles/mixins/style.less b/styles/mixins/style.less new file mode 100644 index 000000000..7aada2eab --- /dev/null +++ b/styles/mixins/style.less @@ -0,0 +1,66 @@ +/* Mixin helpers +-------------------------------------------------- */ + +.button-style() { + font-size: 20px; + background: #ECECEC; + border-radius: 10px; + padding: 16px 30px; + text-decoration: none; + text-shadow: 0px 1px 0px #fff; + border: 1px solid #a7a7a7; + box-shadow: 0px 2px 1px white inset, 0px -2px 8px white, 0px 2px 5px rgba(0, 0, 0, 0.1), 0px 8px 10px rgba(0, 0, 0, 0.1); + -webkit-transition: box-shadow 0.5s; + + &:hover { + box-shadow: 0px 2px 1px white inset, 0px -2px 20px white, 0px 2px 5px rgba(0, 0, 0, 0.1), 0px 8px 10px rgba(0, 0, 0, 0.1); + } + + &:active { + top: 2px; + position: relative; + box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.5) inset, 0px -2px 20px white, 0px 1px 5px rgba(0, 0, 0, 0.1), 0px 2px 10px rgba(0, 0, 0, 0.1); + background: -webkit-linear-gradient(top, #d1d1d1 0%, #ECECEC 100%); + } +} + +.hover-scale-fx(@scaleTo:1.2, @duration:.1s, @scaleBack:1) { + -moz-transform: scale(@scaleBack); + -webkit-transform: scale(@scaleBack); + -o-transform: scale(@scaleBack); + -ms-transform: scale(@scaleBack); + transform: scale(@scaleBack); + + -moz-transition: all @duration ease-in-out; + -webkit-transition: all @duration ease-in-out; + -ms-transition: all @duration ease-in-out; + -o-transition: all @duration ease-in-out; + transition: all @duration ease-in-out; + + &:hover { + -moz-transform: scale(@scaleTo); + -webkit-transform: scale(@scaleTo); + -o-transform: scale(@scaleTo); + -ms-transform: scale(@scaleTo); + transform: scale(@scaleTo); + } + +} + +.grayscale() { + filter: url("data:image/svg+xml;utf8,#grayscale"); /* Firefox 10+, Firefox on Android */ + filter: gray; /* IE6-9 */ + -webkit-filter: grayscale(100%); /* Chrome 19+, Safari 6+, Safari 6+ iOS */ +} + +.nograyscale() { + filter: url("data:image/svg+xml;utf8,#grayscale"); + -webkit-filter: grayscale(0%); +} + +.opacityAll(@value:1) { + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=@value*100)"; + -moz-opacity: @value; + -khtml-opacity: @value; + opacity: @value; +} \ No newline at end of file diff --git a/styles/sections/blog.less b/styles/sections/blog.less new file mode 100644 index 000000000..2e64fa388 --- /dev/null +++ b/styles/sections/blog.less @@ -0,0 +1,16 @@ +/* Blog +-------------------------------------------------- */ +.twitter-widget { + margin-top: 70px; +} + +.post-date { + text-align:right; + color: #b8b8b8; +} + +.post-date-preview { + position: relative; + top: -35px; + height: 0px; +} \ No newline at end of file diff --git a/styles/sections/demos.less b/styles/sections/demos.less new file mode 100644 index 000000000..c61bf7d71 --- /dev/null +++ b/styles/sections/demos.less @@ -0,0 +1,65 @@ +/* Demos +-------------------------------------------------- */ + +.demo-page.center-align-a img { + .box-shadow(~"0 1px 5px #696969, 0 -2px 5px #F2F2F2"); +} + +.demo-page.center-align-a p { + display: inline; + position: absolute; + text-align: center; + width: 190px; + color: white; + background: rgba(0, 0, 0, 0.7); + padding: 10px; +} + +#page-tr-info { + float: right; + margin-top: -60px; + position: relative; + z-index: 99; +} + +#githubBtn-tr-info { + float: right; + margin-top: -60px; + position: relative; + z-index: 99; +} + +.demo-button { + cursor: pointer; + cursor: hand; +} + +.demo-button .logo { + fill: #afafaf; +} + +.flash-button.active .logo, +.flash-button:hover .logo { + fill: red; +} + +.html5-button.active .logo, +.html5-button:hover .logo { + fill: orange; +} + +.flash-warning { + margin: 0 auto; + display: none; + text-align: center; +} + +.html5-demo { + border: none; + margin: 0 auto; + display: block; +} + +.install-flash-player-prompt { + width: 110px; +} \ No newline at end of file diff --git a/styles/sections/docs.less b/styles/sections/docs.less new file mode 100644 index 000000000..e8e648947 --- /dev/null +++ b/styles/sections/docs.less @@ -0,0 +1,144 @@ +/* Docs +-------------------------------------------------- */ + +.doc-nav .nav > .active > a, .doc-nav .nav > .active:hover > a, .doc-nav .nav > .active:focus > a { + background-color: rgba(0, 0, 0, 0); + border-left: 1px solid @active-color; + color: @active-color; + font-weight: bold; +} + +.doc-nav a { + display: block; + margin-left: 14px; +} + +.doc-nav { + position: static; + top: 80px; + background-color: #F4F8FF; + border-radius: 6px; + margin-bottom: 30px; + margin-top: 30px; + padding-bottom: 10px; + padding-top: 10px; + text-shadow: 0 1px 0 #FFFFFF; +} + +.doc-nav .nav > li > a { + display: block; + color: #000000; + padding: 5px 20px; +} + +.doc-nav .nav > li > a:hover, +.doc-nav .nav > li > a:focus { + text-decoration: none; + background-color: #FFF; + border-left: 1px solid #000000; +} + +.doc-nav .nav > .active > a, +.doc-nav .nav > .active:hover > a, +.doc-nav .nav > .active:focus > a { + font-weight: bold; + color: #000000; + background-color: #FFF; + border-left: 1px solid #000000; +} + +.doc-nav .nav .nav { + display: none; + margin-bottom: 8px; +} + +.doc-nav .nav .nav > li > a { + padding-top: 3px; + padding-bottom: 3px; + padding-left: 30px; + font-size: 90%; +} + +.doc-list-item { + margin-bottom: -16px; +} + +.doc-list span { + font-size: 0.8em; + margin-right: 7px; +} + +.sideBySide{ + width:48%; + float:left; +} + +.spacer-right{ + margin-right:20px; +} + +.clear{ + clear:both; +} + +.members-list { + padding-left: 0; +} + +.members-list > li { + list-style: none; +} + +.gist pre { + box-shadow: none; +} + +@media (max-width: @screen-md-min) { + .sideBySide{ + width:100%; + float:none; + } +} + +@media screen and (min-width: 992px) { + .doc-nav .nav > .active > ul { + display: block; + } + + .doc-nav.affix, + .doc-nav.affix-bottom { + width: 213px; + } + + .doc-nav.affix { + top: 80px; + } + + .doc-nav.affix-bottom { + position: absolute; + } + + .doc-nav.affix-bottom, + .doc-nav.affix { + margin-top: 30px; + margin-bottom: 0; + } +} + +.highlighted .container { + padding-left: 0; + padding-right: 0; + display: inline; +} + +.highlighted .container:before, .highlighted .container:after { + clear: none; + content: none; +} + +@media screen and (min-width: 1200px) { + .doc-nav.affix-bottom, + .doc-nav.affix { + width: 263px; + } +} \ No newline at end of file diff --git a/styles/sections/footer.less b/styles/sections/footer.less new file mode 100644 index 000000000..9a654b5eb --- /dev/null +++ b/styles/sections/footer.less @@ -0,0 +1,86 @@ +/* Footer +-------------------------------------------------- */ + +.footer-main { + margin-top: 60px; + background: url("/images/footer-shadow.png") repeat-x scroll 0 0 #515151; + min-height: 110px; + text-shadow: none; +} + +footer:before { + background-image: -webkit-linear-gradient(left, #ffdb2d 0%, #ffdb2d 20%, #e30019 20%, #e30019 40%, #9CB641 40%, #9CB641 60%, #1a2eef 60%, #1a2eef 80%, #00abf3 80%, #00abf3 100%); + background-image: -moz-linear-gradient(left center, #ffdb2d 0%, #ffdb2d 20%, #e30019 20%, #e30019 40%, #9CB641 40%, #9CB641 60%, #1a2eef 60%, #1a2eef 80%, #00abf3 80%, #00abf3 100%); + top: 1; + content: ""; + height: 4px; + left: 0; + position: absolute; + right: 0; +} + +.footer-powered-by { + color: #FFFFFF; + float: right; + margin-top: 20px; +} + +.footer-powered-by p { + display: inline; +} + +.footer-powered-by img { + width: 40px; + .hover-scale-fx(1.2); + margin: 6px; +} + +.footer-social { + margin-top: 28px; + float: left; +} + +.footer-patreon { + margin-left: 20px; + white-space: nowrap; + img { + height: 40px; + margin-left: 0px; + } + + img.patreon-wordmark { + height: 60px; + margin-left: -15px; + } +} + + +#demoSWF { + display: block; + margin: 0 auto; +} + +@media (max-width: @screen-md-min) { + .footer-powered-by { + float: none; + margin-top: 40px; + margin-bottom: 40px; + white-space: nowrap; + + text-align: center; + } + + .footer-powered-by a{ + display: inline-block; + } + + .footer-social { + float: none; + text-align: center; + } + + .footer-powered-by p { + display: inline-block; + margin-bottom: 26px; + } +} \ No newline at end of file diff --git a/styles/sections/fundraiser.less b/styles/sections/fundraiser.less new file mode 100644 index 000000000..79d9092b0 --- /dev/null +++ b/styles/sections/fundraiser.less @@ -0,0 +1,68 @@ +.fundraiser-header { + display: flex; +} + +.indiegogo-frame { + margin: 20px; +} + +.success-text { + display: flex; +} + +.success-text span { + margin: 10px; +} + +.thankyou-backers { + text-align: center; +} + +.backer-list { + display: flex; + justify-content: center; + flex-wrap: wrap; + list-style: none; + padding: 0; + margin: 0 auto; +} + +.backer { + position: relative; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + width: 240px; + height: 120px; + margin: 10px; + padding: 10px; + text-align: center; + border: 1px solid #c4c4c4; + border-radius: 4px; +} + +.backer-amount { + position: absolute; + bottom: 0; + right: 0; + margin: 0; + padding: 10px; +} + +.backer h4 { + margin: 10px; + overflow: hidden; +} + +@media screen and (max-width: 740px) { + .indiegogo-frame { + display: none; + } + + .fundraiser-header { + flex-direction: column; + align-items: center; + text-align: center; + } +} \ No newline at end of file diff --git a/styles/sections/home.less b/styles/sections/home.less new file mode 100644 index 000000000..22f89c43a --- /dev/null +++ b/styles/sections/home.less @@ -0,0 +1,191 @@ +@import "../mixins/style"; +@import "../../../files/vendor/LESSHat/lesshat.less"; +@import 'https://fonts.googleapis.com/css?family=VT323'; + +/* Homepage styles +-------------------------------------------------- */ + +.flixel-footer-logo { + height: 40px; +} + +.footer-powered-by img.openfl-footer-logo { + width: 46px; +} + +.lead-line { + font-size: 30px; + font-weight: 200; + padding-bottom: 30px; +} + +.lead-line-large { + font-size: 30px; + font-weight: 200; +} + +.carousel-inner > .item > img, .carousel-inner > .item > a > img { + width: 100%; +} + +.home-button { + .button-style(); + margin-left: 4; + margin-right: 4px; + text-align: center; +} + +.sponsors-button { + font-size: 24px; + display: block; + width: 300px; + margin: 0 auto; +} + +.platinum-container { + display: flex; + justify-content: center; + align-items: center; + font-family: 'VT323', monospace; + font-size: 56px; +} + +.home-header { + margin-top: 5em; +} + +.home-header h1 { + font-size: 6em; + line-height: 1; +} + +.home-social { + margin-top: 2em; +} + +.home-section-features { + position: relative; + padding: 1em; + text-align: left; + font-size: 1.1em; +} + +.home-section { + position: relative; + padding: 1em; + text-align: center; +} + +.demos-home img { + margin: 10px; + .box-shadow(~"0 1px 5px #696969, 0 -2px 5px #F2F2F2"); +} + +.platform-logos-home img { + padding: 10px; + .opacityAll(.7); + .hover-scale-fx(1.1); + .grayscale(); +} + +.platform-logos-home img:hover { + .opacityAll(1); + .nograyscale(); +} + +.platform-demos-home img { + .hover-scale-fx(1.1); + padding: 10px; +} + +.twitter-follow-button.twitter-follow-button { + height: 36px; +} + +.home-big-logo img { + .hover-scale-fx(1.1); +} + +.navbar-fixed-top { + box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.3); +} + +.icon-next.tweet-next { + right: 0; + position: absolute; + left: 100%; +} + +.icon-prev.tweet-prev { + right: 100%; + position: absolute; + left: 0; +} + +.home-section-powered { + text-align: center; + img { + .hover-scale-fx(1.03); + } +} + +.home-section-powered span { + font-size: 48px; + padding: 20px; +} + +.patreon-home { + img { + max-width: 240px; + vertical-align: top; + margin-left: 30px; + } +} + +.backer-hr { + margin-top: 60px; +} + +@media (max-width: @screen-md-min) { + .home-button { + margin-top: 20px; + margin-bottom: 20px; + display:block; + } +} + +@media (max-width: @screen-lg-min) { + .demos-home.home-section { + max-width: 700px; + margin: 0 auto; + } +} + +@media (max-width: @screen-sm-min) { + .home-header h1 { + font-size: 4em; + } +} + +.sponsor-logos-container { + display: flex; + justify-content: center; + align-items: center; +} + +.lead-line-large { + text-align: center; +} + +.home-sponsor-logos { + img { + margin: 16px; + max-height: 174px; + } +} + +@media (max-width: @screen-lg-min) { + .sponsor-logos-container { + flex-direction: column; + } +} diff --git a/styles/sections/showcase.less b/styles/sections/showcase.less new file mode 100644 index 000000000..8bebab383 --- /dev/null +++ b/styles/sections/showcase.less @@ -0,0 +1,39 @@ +.showcase-targets img { + padding-top: 10px; + .opacityAll(.7); +} + +.showcases-target-active img { + .nograyscale(); + .opacityAll(.7); +} + +.showcases-target img { + .grayscale(); + .opacityAll(.1); +} + +.showcase-grid .col-md-4:nth-child(3n+1) { + clear: both; +} +.showcase-game-thumbnail img { + .box-shadow(~"0 1px 5px #696969, 0 -2px 5px #F2F2F2"); + width: 100%; + max-width: 500px; + height: auto; +} + +.showcase-game { + padding-bottom: 40px; + h3 + { + height: 60px; + width: 540px; + position: relative; + bottom: 10px; + display: table-cell; + vertical-align: bottom; + } +} + + diff --git a/styles/style.css b/styles/style.css new file mode 100644 index 000000000..4c11f8d3f --- /dev/null +++ b/styles/style.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap v3.0.0 + * + * Copyright 2013 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world by @mdo and @fat. + */@import url(https://fonts.googleapis.com/css?family=Ubuntu:400,700,400italic,700italic);/*! normalize.css v2.1.0 | MIT License | git.io/normalize */@import 'https://fonts.googleapis.com/css?family=VT323';article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden]{display:none}html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{font-size:2em;margin:.67em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}@media print{*{text-shadow:none !important;color:#000 !important;background:transparent !important;box-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:2cm .5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.table td,.table th{background-color:#fff !important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}*,*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:'Ubuntu',sans-serif;font-size:16px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}button,input,select[multiple],textarea{background-image:none}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;-o-transition:all 0.2s ease-in-out;-ms-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:22px;margin-bottom:22px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);border:0}p{margin:0 0 11px}.lead{margin-bottom:22px;font-size:18.4px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:24px}}small{font-size:85%}cite{font-style:normal}.text-muted{color:#999}.text-primary{color:#428bca}.text-warning{color:#c09853}.text-danger{color:#b94a48}.text-success{color:#468847}.text-info{color:#3a87ad}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:'Ubuntu',sans-serif;font-weight:500;line-height:1.1}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{margin-top:22px;margin-bottom:11px}h1 small,h2 small,h3 small{font-size:65%}h4,h5,h6{margin-top:11px;margin-bottom:11px}h4 small,h5 small,h6 small{font-size:75%}h1,.h1{font-size:41px}h2,.h2{font-size:34px}h3,.h3{font-size:28px}h4,.h4{font-size:20px}h5,.h5{font-size:16px}h6,.h6{font-size:14px}.page-header{padding-bottom:10px;margin:44px 0 22px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:11px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-bottom:22px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}.dl-horizontal dd:before,.dl-horizontal dd:after{content:" ";display:table}.dl-horizontal dd:after{clear:both}.dl-horizontal dd:before,.dl-horizontal dd:after{content:" ";display:table}.dl-horizontal dd:after{clear:both}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:11px 22px;margin:0 0 22px;border-left:5px solid #eee}blockquote p{font-size:20px;font-weight:300;line-height:1.25}blockquote p:last-child{margin-bottom:0}blockquote small{display:block;line-height:1.42857143;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:22px;font-style:normal;line-height:1.42857143}code,pre{font-family:Monaco,Menlo,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#000;background-color:#f3f3f3;white-space:nowrap;border-radius:4px;border:1px solid #e1e1e8}pre{display:block;padding:10.5px;margin:0 0 11px;font-size:15px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre.prettyprint{margin-bottom:22px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.container:before,.container:after{content:" ";display:table}.container:after{clear:both}.container:before,.container:after{content:" ";display:table}.container:after{clear:both}.row{margin-left:-15px;margin-right:-15px}.row:before,.row:after{content:" ";display:table}.row:after{clear:both}.row:before,.row:after{content:" ";display:table}.row:after{clear:both}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11{float:left}.col-xs-1{width:8.33333333%}.col-xs-2{width:16.66666667%}.col-xs-3{width:25%}.col-xs-4{width:33.33333333%}.col-xs-5{width:41.66666667%}.col-xs-6{width:50%}.col-xs-7{width:58.33333333%}.col-xs-8{width:66.66666667%}.col-xs-9{width:75%}.col-xs-10{width:83.33333333%}.col-xs-11{width:91.66666667%}.col-xs-12{width:100%}@media (min-width:768px){.container{max-width:750px}.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11{float:left}.col-sm-1{width:8.33333333%}.col-sm-2{width:16.66666667%}.col-sm-3{width:25%}.col-sm-4{width:33.33333333%}.col-sm-5{width:41.66666667%}.col-sm-6{width:50%}.col-sm-7{width:58.33333333%}.col-sm-8{width:66.66666667%}.col-sm-9{width:75%}.col-sm-10{width:83.33333333%}.col-sm-11{width:91.66666667%}.col-sm-12{width:100%}.col-sm-push-1{left:8.33333333%}.col-sm-push-2{left:16.66666667%}.col-sm-push-3{left:25%}.col-sm-push-4{left:33.33333333%}.col-sm-push-5{left:41.66666667%}.col-sm-push-6{left:50%}.col-sm-push-7{left:58.33333333%}.col-sm-push-8{left:66.66666667%}.col-sm-push-9{left:75%}.col-sm-push-10{left:83.33333333%}.col-sm-push-11{left:91.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-3{right:25%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-6{right:50%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-9{right:75%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-11{right:91.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-11{margin-left:91.66666667%}}@media (min-width:992px){.container{max-width:970px}.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11{float:left}.col-md-1{width:8.33333333%}.col-md-2{width:16.66666667%}.col-md-3{width:25%}.col-md-4{width:33.33333333%}.col-md-5{width:41.66666667%}.col-md-6{width:50%}.col-md-7{width:58.33333333%}.col-md-8{width:66.66666667%}.col-md-9{width:75%}.col-md-10{width:83.33333333%}.col-md-11{width:91.66666667%}.col-md-12{width:100%}.col-md-push-0{left:auto}.col-md-push-1{left:8.33333333%}.col-md-push-2{left:16.66666667%}.col-md-push-3{left:25%}.col-md-push-4{left:33.33333333%}.col-md-push-5{left:41.66666667%}.col-md-push-6{left:50%}.col-md-push-7{left:58.33333333%}.col-md-push-8{left:66.66666667%}.col-md-push-9{left:75%}.col-md-push-10{left:83.33333333%}.col-md-push-11{left:91.66666667%}.col-md-pull-0{right:auto}.col-md-pull-1{right:8.33333333%}.col-md-pull-2{right:16.66666667%}.col-md-pull-3{right:25%}.col-md-pull-4{right:33.33333333%}.col-md-pull-5{right:41.66666667%}.col-md-pull-6{right:50%}.col-md-pull-7{right:58.33333333%}.col-md-pull-8{right:66.66666667%}.col-md-pull-9{right:75%}.col-md-pull-10{right:83.33333333%}.col-md-pull-11{right:91.66666667%}.col-md-offset-0{margin-left:0}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-3{margin-left:25%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-6{margin-left:50%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-9{margin-left:75%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-11{margin-left:91.66666667%}}@media (min-width:1200px){.container{max-width:1170px}.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11{float:left}.col-lg-1{width:8.33333333%}.col-lg-2{width:16.66666667%}.col-lg-3{width:25%}.col-lg-4{width:33.33333333%}.col-lg-5{width:41.66666667%}.col-lg-6{width:50%}.col-lg-7{width:58.33333333%}.col-lg-8{width:66.66666667%}.col-lg-9{width:75%}.col-lg-10{width:83.33333333%}.col-lg-11{width:91.66666667%}.col-lg-12{width:100%}.col-lg-push-0{left:auto}.col-lg-push-1{left:8.33333333%}.col-lg-push-2{left:16.66666667%}.col-lg-push-3{left:25%}.col-lg-push-4{left:33.33333333%}.col-lg-push-5{left:41.66666667%}.col-lg-push-6{left:50%}.col-lg-push-7{left:58.33333333%}.col-lg-push-8{left:66.66666667%}.col-lg-push-9{left:75%}.col-lg-push-10{left:83.33333333%}.col-lg-push-11{left:91.66666667%}.col-lg-pull-0{right:auto}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-3{right:25%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-6{right:50%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-9{right:75%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-11{right:91.66666667%}.col-lg-offset-0{margin-left:0}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-11{margin-left:91.66666667%}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:22px}.table thead>tr>th,.table tbody>tr>th,.table tfoot>tr>th,.table thead>tr>td,.table tbody>tr>td,.table tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border:1px solid #ddd}.table thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed thead>tr>th,.table-condensed tbody>tr>th,.table-condensed tfoot>tr>th,.table-condensed thead>tr>td,.table-condensed tbody>tr>td,.table-condensed tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*="col-"]{float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8;border-color:#d6e9c6}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6;border-color:#c9e2b3}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede;border-color:#eed3d7}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc;border-color:#e6c1c7}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3;border-color:#fbeed5}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc;border-color:#f8e5be}@media (max-width:768px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;overflow-x:scroll;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0;background-color:#fff}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>thead>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>thead>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:22px;font-size:24px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}select[multiple],select[size]{height:auto}select optgroup{font-size:inherit;font-style:inherit;font-family:inherit}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}input[type="number"]::-webkit-outer-spin-button,input[type="number"]::-webkit-inner-spin-button{height:auto}output{display:block;padding-top:7px;font-size:16px;line-height:1.42857143;color:#555;vertical-align:middle}.form-control:-moz-placeholder{color:#999}.form-control::-moz-placeholder{color:#999}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control{display:block;width:100%;height:36px;padding:6px 12px;font-size:16px;line-height:1.42857143;color:#555;vertical-align:middle;background-color:#fff;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:-webkit-border-color ease-in-out .15s -webkit-box-shadow ease-in-out .15s;-moz-transition:-moz-border-color ease-in-out .15s -moz-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s box-shadow ease-in-out .15s;-ms-transition:border-color ease-in-out .15s box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s box-shadow ease-in-out .15s;-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee}textarea .form-control{height:auto}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:22px;margin-top:10px;margin-bottom:10px;padding-left:20px;vertical-align:middle}.radio label,.checkbox label{display:inline;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:33px;padding:5px 10px;font-size:14px;line-height:1.5;border-radius:3px}select .input-sm{height:33px;line-height:33px}textarea .input-sm{height:auto}.input-lg{height:48px;padding:10px 16px;font-size:20px;line-height:1.33;border-radius:6px}select .input-lg{height:48px;line-height:48px}textarea .input-lg{height:auto}.has-warning .help-block,.has-warning .control-label{color:#c09853}.has-warning .form-control{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.has-warning .input-group-addon{color:#c09853;border-color:#c09853;background-color:#fcf8e3}.has-error .help-block,.has-error .control-label{color:#b94a48}.has-error .form-control{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.has-error .input-group-addon{color:#b94a48;border-color:#b94a48;background-color:#f2dede}.has-success .help-block,.has-success .control-label{color:#468847}.has-success .form-control{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.has-success .input-group-addon{color:#468847;border-color:#468847;background-color:#dff0d8}.form-control-static{margin-bottom:0;padding-top:7px}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-group:before,.form-horizontal .form-group:after{content:" ";display:table}.form-horizontal .form-group:after{clear:both}.form-horizontal .form-group:before,.form-horizontal .form-group:after{content:" ";display:table}.form-horizontal .form-group:after{clear:both}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:16px;font-weight:normal;line-height:1.42857143;text-align:center;vertical-align:middle;cursor:pointer;border:1px solid transparent;border-radius:4px;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);-moz-box-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);box-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;-webkit-opacity:.65;-moz-opacity:.65;opacity:.65;filter:alpha(opacity=65);-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle .btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle .btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle .btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle .btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle .btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle .btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle .btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle .btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle .btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle .btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle .btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle .btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-link{color:#428bca;font-weight:normal;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:20px;line-height:1.33;border-radius:6px}.btn-sm,.btn-xs{padding:5px 10px;font-size:14px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px}.btn-block{display:block;width:100%;padding-left:0;padding-right:0}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity 0.15s linear;-moz-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;-ms-transition:opacity 0.15s linear;transition:opacity 0.15s linear;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height 0.35s ease;-moz-transition:height 0.35s ease;-o-transition:height 0.35s ease;-ms-transition:height 0.35s ease;transition:height 0.35s ease;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url('/vendor/twitter-bootstrap-3/fonts/glyphicons-halflings-regular.eot');src:url('/vendor/twitter-bootstrap-3/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('/vendor/twitter-bootstrap-3/fonts/glyphicons-halflings-regular.woff') format('woff'),url('/vendor/twitter-bootstrap-3/fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('/vendor/twitter-bootstrap-3/fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased}.glyphicon:empty{width:1em}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-print:before{content:"\e045"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-briefcase:before{content:"\1f4bc"}.glyphicon-calendar:before{content:"\1f4c5"}.glyphicon-pushpin:before{content:"\1f4cc"}.glyphicon-paperclip:before{content:"\1f4ce"}.glyphicon-camera:before{content:"\1f4f7"}.glyphicon-lock:before{content:"\1f512"}.glyphicon-bell:before{content:"\1f514"}.glyphicon-bookmark:before{content:"\1f516"}.glyphicon-fire:before{content:"\1f525"}.glyphicon-wrench:before{content:"\1f527"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;border-bottom:0 dotted;content:""}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:16px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0, 0, 0, 0.175);-moz-box-shadow:0 6px 12px rgba(0, 0, 0, 0.175);box-shadow:0 6px 12px rgba(0, 0, 0, 0.175);-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:10px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#fff;background-color:#428bca}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#428bca}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-header{display:block;padding:3px 20px;font-size:14px;line-height:1.42857143;color:#999}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0 dotted;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}}.btn-default .caret{border-top-color:#333}.btn-primary .caret,.btn-success .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret{border-top-color:#fff}.dropup .btn-default .caret{border-bottom-color:#333}.dropup .btn-primary .caret,.dropup .btn-success .caret,.dropup .btn-warning .caret,.dropup .btn-danger .caret,.dropup .btn-info .caret{border-bottom-color:#fff}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:none}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar:before,.btn-toolbar:after{content:" ";display:table}.btn-toolbar:after{clear:both}.btn-toolbar:before,.btn-toolbar:after{content:" ";display:table}.btn-toolbar:after{clear:both}.btn-toolbar .btn-group{float:left}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group,.btn-toolbar>.btn-group+.btn-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group-xs>.btn{padding:5px 10px;font-size:14px;line-height:1.5;border-radius:3px;padding:1px 5px}.btn-group-sm>.btn{padding:5px 10px;font-size:14px;line-height:1.5;border-radius:3px}.btn-group-lg>.btn{padding:10px 16px;font-size:20px;line-height:1.33;border-radius:6px}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);-moz-box-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);box-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{content:" ";display:table}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{content:" ";display:table}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child>.btn:last-child,.btn-group-vertical>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified .btn{float:none;display:table-cell;width:1%}[data-toggle="buttons"]>.btn>input[type="radio"],[data-toggle="buttons"]>.btn>input[type="checkbox"]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group.col{float:none;padding-left:0;padding-right:0}.input-group .form-control{width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:48px;padding:10px 16px;font-size:20px;line-height:1.33;border-radius:6px}select .input-group-lg>.form-control,select .input-group-lg>.input-group-addon,select .input-group-lg>.input-group-btn>.btn{height:48px;line-height:48px}textarea .input-group-lg>.form-control,textarea .input-group-lg>.input-group-addon,textarea .input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:33px;padding:5px 10px;font-size:14px;line-height:1.5;border-radius:3px}select .input-group-sm>.form-control,select .input-group-sm>.input-group-addon,select .input-group-sm>.input-group-btn>.btn{height:33px;line-height:33px}textarea .input-group-sm>.form-control,textarea .input-group-sm>.input-group-addon,textarea .input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:16px;font-weight:normal;line-height:1;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:14px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:20px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-4px}.input-group-btn>.btn:hover,.input-group-btn>.btn:active{z-index:2}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav:before,.nav:after{content:" ";display:table}.nav:after{clear:both}.nav:before,.nav:after{content:" ";display:table}.nav:after{clear:both}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:10px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}}.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;margin-right:0}.nav-tabs.nav-justified>.active>a{border-bottom-color:#fff}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:5px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;margin-right:0}.nav-tabs-justified>.active>a{border-bottom-color:#fff}.tabbable:before,.tabbable:after{content:" ";display:table}.tabbable:after{clear:both}.tabbable:before,.tabbable:after{content:" ";display:table}.tabbable:after{clear:both}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.nav .caret{border-top-color:#428bca;border-bottom-color:#428bca}.nav a:hover .caret{border-top-color:#2a6496;border-bottom-color:#2a6496}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;z-index:1000;min-height:50px;margin-bottom:22px;border:1px solid transparent}.navbar:before,.navbar:after{content:" ";display:table}.navbar:after{clear:both}.navbar:before,.navbar:after{content:" ";display:table}.navbar:after{clear:both}@media (min-width:768px){.navbar{border-radius:4px}}.navbar-header:before,.navbar-header:after{content:" ";display:table}.navbar-header:after{clear:both}.navbar-header:before,.navbar-header:after{content:" ";display:table}.navbar-header:after{clear:both}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse:before,.navbar-collapse:after{content:" ";display:table}.navbar-collapse:after{clear:both}.navbar-collapse:before,.navbar-collapse:after{content:" ";display:table}.navbar-collapse:after{clear:both}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-collapse .navbar-nav.navbar-left:first-child{margin-left:-15px}.navbar-collapse .navbar-nav.navbar-right:last-child{margin-right:-15px}.navbar-collapse .navbar-text:last-child{margin-right:0}}.container>.navbar-header,.container>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;border-width:0 0 1px}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{z-index:1030;top:0}.navbar-fixed-bottom{bottom:0;margin-bottom:0}.navbar-brand{float:left;padding:14px 15px;font-size:20px;line-height:22px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;border:1px solid transparent;border-radius:4px}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:22px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:22px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:14px;padding-bottom:14px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:7px;margin-bottom:7px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{float:none;margin-left:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-nav.pull-right>li>.dropdown-menu,.navbar-nav>li>.dropdown-menu.pull-right{left:auto;right:0}.navbar-btn{margin-top:7px;margin-bottom:7px}.navbar-text{float:left;margin-top:14px;margin-bottom:14px}@media (min-width:768px){.navbar-text{margin-left:15px;margin-right:15px}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#ccc}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e6e6e6}.navbar-default .navbar-nav>.dropdown>a:hover .caret,.navbar-default .navbar-nav>.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}.navbar-default .navbar-nav>.open>a .caret,.navbar-default .navbar-nav>.open>a:hover .caret,.navbar-default .navbar-nav>.open>a:focus .caret{border-top-color:#555;border-bottom-color:#555}.navbar-default .navbar-nav>.dropdown>a .caret{border-top-color:#777;border-bottom-color:#777}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}.navbar-inverse .navbar-nav>.dropdown>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-nav>.dropdown>a .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .navbar-nav>.open>a .caret,.navbar-inverse .navbar-nav>.open>a:hover .caret,.navbar-inverse .navbar-nav>.open>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.breadcrumb{padding:8px 15px;margin-bottom:22px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{display:inline-block;padding-left:0;margin:22px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.42857143;text-decoration:none;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#F4F8FF}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:20px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:14px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:22px 0;list-style:none;text-align:center}.pager:before,.pager:after{content:" ";display:table}.pager:after{clear:both}.pager:before,.pager:after{content:" ";display:table}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#F4F8FF}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:14px;font-weight:bold;color:#fff;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#999;border-radius:10px}.badge:empty{display:none}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.btn .badge{position:relative;top:-1px}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;font-size:24px;font-weight:200;line-height:2.14285714;color:inherit;background-color:#eee}.jumbotron h1{line-height:1;color:inherit}.jumbotron p{line-height:1.4}.container .jumbotron{border-radius:6px}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1{font-size:72px}}.thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;-o-transition:all 0.2s ease-in-out;-ms-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto;display:block}.thumbnail>img{display:block;max-width:100%;height:auto}a.thumbnail:hover,a.thumbnail:focus{border-color:#428bca}.thumbnail>img{margin-left:auto;margin-right:auto}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:22px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#468847}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#356635}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#3a87ad}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#2d6987}.alert-warning{background-color:#fcf8e3;border-color:#fbeed5;color:#c09853}.alert-warning hr{border-top-color:#f8e5be}.alert-warning .alert-link{color:#a47e3c}.alert-danger{background-color:#f2dede;border-color:#eed3d7;color:#b94a48}.alert-danger hr{border-top-color:#e6c1c7}.alert-danger .alert-link{color:#953b39}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:22px;margin-bottom:22px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0;height:100%;font-size:14px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width 0.6s ease;-moz-transition:width 0.6s ease;-o-transition:width 0.6s ease;-ms-transition:width 0.6s ease;transition:width 0.6s ease;-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a .list-group-item{color:#555}a .list-group-item .list-group-item-heading{color:#333}a .list-group-item:hover,a .list-group-item:focus{text-decoration:none;background-color:#F4F8FF}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:22px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0, 0, 0, 0.05);-moz-box-shadow:0 1px 1px rgba(0, 0, 0, 0.05);box-shadow:0 1px 1px rgba(0, 0, 0, 0.05);-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-body:before,.panel-body:after{content:" ";display:table}.panel-body:after{clear:both}.panel-body:before,.panel-body:after{content:" ";display:table}.panel-body:after{clear:both}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0}.panel>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel>.list-group .list-group-item:last-child{border-bottom:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table{margin-bottom:0}.panel>.panel-body+.table{border-top:1px solid #ddd}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-title{margin-top:0;margin-bottom:0;font-size:18px}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#F4F8FF;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-group .panel{margin-bottom:0;border-radius:4px;overflow:hidden}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#F4F8FF;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-warning{border-color:#fbeed5}.panel-warning>.panel-heading{color:#c09853;background-color:#fcf8e3;border-color:#fbeed5}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#fbeed5}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#fbeed5}.panel-danger{border-color:#eed3d7}.panel-danger>.panel-heading{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#eed3d7}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#eed3d7}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:24px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;-webkit-opacity:.2;-moz-opacity:.2;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;-webkit-opacity:.5;-moz-opacity:.5;opacity:.5;filter:alpha(opacity=50)}button .close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}body .modal-open,.modal-open .navbar-fixed-top,.modal-open .navbar-fixed-bottom{margin-right:15px}.modal{display:none;overflow:auto;overflow-y:scroll;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040}.modal.fade .modal-dialog{-moz-transform:translate(0, -25%);-o-transform:translate(0, -25%);-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform 0.3s ease-out;-moz-transition:-moz-transform 0.3s ease-out;-o-transition:-o-transform 0.3s ease-out;transition:transform 0.3s ease-out}.modal.in .modal-dialog{-moz-transform:translate(0, 0);-o-transform:translate(0, 0);-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);transform:translate(0, 0)}.modal-dialog{margin-left:auto;margin-right:auto;width:auto;padding:10px;z-index:1050}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0, 0, 0, 0.5);-moz-box-shadow:0 3px 9px rgba(0, 0, 0, 0.5);box-shadow:0 3px 9px rgba(0, 0, 0, 0.5);-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box;outline:none}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1030;background-color:#000}.modal-backdrop.fade{-webkit-opacity:0;-moz-opacity:0;opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{-webkit-opacity:.5;-moz-opacity:.5;opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.42857143px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:20px}.modal-footer{margin-top:15px;padding:19px 20px 20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer:before,.modal-footer:after{content:" ";display:table}.modal-footer:after{clear:both}.modal-footer:before,.modal-footer:after{content:" ";display:table}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media screen and (min-width:768px){.modal-dialog{left:50%;right:auto;width:600px;padding-top:30px;padding-bottom:30px}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0, 0, 0, 0.5);-moz-box-shadow:0 5px 15px rgba(0, 0, 0, 0.5);box-shadow:0 5px 15px rgba(0, 0, 0, 0.5);-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}}.tooltip{position:absolute;z-index:1030;display:block;visibility:visible;font-size:14px;line-height:1.4;-webkit-opacity:0;-moz-opacity:0;opacity:0;filter:alpha(opacity=0)}.tooltip.in{-webkit-opacity:.9;-moz-opacity:.9;opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;right:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);white-space:normal}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:16px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);bottom:-11px}.popover.top .arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,0.25)}.popover.right .arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom .arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.popover.bottom .arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,0.25)}.popover.left .arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:0.6s ease-in-out left;-moz-transition:0.6s ease-in-out left;-o-transition:0.6s ease-in-out left;-ms-transition:0.6s ease-in-out left;transition:0.6s ease-in-out left;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;-webkit-opacity:.5;-moz-opacity:.5;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-control.left{background-image:-webkit-gradient(linear, 0 top, 100% top, from(rgba(0,0,0,0.5)), to(rgba(0,0,0,0.0001)));background-image:-webkit-linear-gradient(left, color-stop(rgba(0,0,0,0.5) 0), color-stop(rgba(0,0,0,0.0001) 100%));background-image:-moz-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:linear-gradient(to right, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-gradient(linear, 0 top, 100% top, from(rgba(0,0,0,0.0001)), to(rgba(0,0,0,0.5)));background-image:-webkit-linear-gradient(left, color-stop(rgba(0,0,0,0.0001) 0), color-stop(rgba(0,0,0,0.5) 100%));background-image:-moz-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:linear-gradient(to right, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;-webkit-opacity:.9;-moz-opacity:.9;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;left:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after{content:" ";display:table}.clearfix:after{clear:both}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.affix{position:fixed}@-ms-viewport{width:device-width}@media screen and (max-width:400px){@-ms-viewport{width:320px}}.hidden{display:none !important;visibility:hidden !important}.visible-xs{display:none !important}tr .visible-xs{display:none !important}th .visible-xs,td .visible-xs{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}tr .visible-xs{display:table-row !important}th .visible-xs,td .visible-xs{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-xs.visible-sm{display:block !important}tr .visible-xs.visible-sm{display:table-row !important}th .visible-xs.visible-sm,td .visible-xs.visible-sm{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-xs.visible-md{display:block !important}tr .visible-xs.visible-md{display:table-row !important}th .visible-xs.visible-md,td .visible-xs.visible-md{display:table-cell !important}}@media (min-width:1200px){.visible-xs.visible-lg{display:block !important}tr .visible-xs.visible-lg{display:table-row !important}th .visible-xs.visible-lg,td .visible-xs.visible-lg{display:table-cell !important}}.visible-sm{display:none !important}tr .visible-sm{display:none !important}th .visible-sm,td .visible-sm{display:none !important}@media (max-width:767px){.visible-sm.visible-xs{display:block !important}tr .visible-sm.visible-xs{display:table-row !important}th .visible-sm.visible-xs,td .visible-sm.visible-xs{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}tr .visible-sm{display:table-row !important}th .visible-sm,td .visible-sm{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-sm.visible-md{display:block !important}tr .visible-sm.visible-md{display:table-row !important}th .visible-sm.visible-md,td .visible-sm.visible-md{display:table-cell !important}}@media (min-width:1200px){.visible-sm.visible-lg{display:block !important}tr .visible-sm.visible-lg{display:table-row !important}th .visible-sm.visible-lg,td .visible-sm.visible-lg{display:table-cell !important}}.visible-md{display:none !important}tr .visible-md{display:none !important}th .visible-md,td .visible-md{display:none !important}@media (max-width:767px){.visible-md.visible-xs{display:block !important}tr .visible-md.visible-xs{display:table-row !important}th .visible-md.visible-xs,td .visible-md.visible-xs{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-md.visible-sm{display:block !important}tr .visible-md.visible-sm{display:table-row !important}th .visible-md.visible-sm,td .visible-md.visible-sm{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}tr .visible-md{display:table-row !important}th .visible-md,td .visible-md{display:table-cell !important}}@media (min-width:1200px){.visible-md.visible-lg{display:block !important}tr .visible-md.visible-lg{display:table-row !important}th .visible-md.visible-lg,td .visible-md.visible-lg{display:table-cell !important}}.visible-lg{display:none !important}tr .visible-lg{display:none !important}th .visible-lg,td .visible-lg{display:none !important}@media (max-width:767px){.visible-lg.visible-xs{display:block !important}tr .visible-lg.visible-xs{display:table-row !important}th .visible-lg.visible-xs,td .visible-lg.visible-xs{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-lg.visible-sm{display:block !important}tr .visible-lg.visible-sm{display:table-row !important}th .visible-lg.visible-sm,td .visible-lg.visible-sm{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-lg.visible-md{display:block !important}tr .visible-lg.visible-md{display:table-row !important}th .visible-lg.visible-md,td .visible-lg.visible-md{display:table-cell !important}}@media (min-width:1200px){.visible-lg{display:block !important}tr .visible-lg{display:table-row !important}th .visible-lg,td .visible-lg{display:table-cell !important}}.hidden-xs{display:block !important}tr .hidden-xs{display:table-row !important}th .hidden-xs,td .hidden-xs{display:table-cell !important}@media (max-width:767px){.hidden-xs{display:none !important}tr .hidden-xs{display:none !important}th .hidden-xs,td .hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-xs.hidden-sm{display:none !important}tr .hidden-xs.hidden-sm{display:none !important}th .hidden-xs.hidden-sm,td .hidden-xs.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-xs.hidden-md{display:none !important}tr .hidden-xs.hidden-md{display:none !important}th .hidden-xs.hidden-md,td .hidden-xs.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-xs.hidden-lg{display:none !important}tr .hidden-xs.hidden-lg{display:none !important}th .hidden-xs.hidden-lg,td .hidden-xs.hidden-lg{display:none !important}}.hidden-sm{display:block !important}tr .hidden-sm{display:table-row !important}th .hidden-sm,td .hidden-sm{display:table-cell !important}@media (max-width:767px){.hidden-sm.hidden-xs{display:none !important}tr .hidden-sm.hidden-xs{display:none !important}th .hidden-sm.hidden-xs,td .hidden-sm.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}tr .hidden-sm{display:none !important}th .hidden-sm,td .hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-sm.hidden-md{display:none !important}tr .hidden-sm.hidden-md{display:none !important}th .hidden-sm.hidden-md,td .hidden-sm.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-sm.hidden-lg{display:none !important}tr .hidden-sm.hidden-lg{display:none !important}th .hidden-sm.hidden-lg,td .hidden-sm.hidden-lg{display:none !important}}.hidden-md{display:block !important}tr .hidden-md{display:table-row !important}th .hidden-md,td .hidden-md{display:table-cell !important}@media (max-width:767px){.hidden-md.hidden-xs{display:none !important}tr .hidden-md.hidden-xs{display:none !important}th .hidden-md.hidden-xs,td .hidden-md.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-md.hidden-sm{display:none !important}tr .hidden-md.hidden-sm{display:none !important}th .hidden-md.hidden-sm,td .hidden-md.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}tr .hidden-md{display:none !important}th .hidden-md,td .hidden-md{display:none !important}}@media (min-width:1200px){.hidden-md.hidden-lg{display:none !important}tr .hidden-md.hidden-lg{display:none !important}th .hidden-md.hidden-lg,td .hidden-md.hidden-lg{display:none !important}}.hidden-lg{display:block !important}tr .hidden-lg{display:table-row !important}th .hidden-lg,td .hidden-lg{display:table-cell !important}@media (max-width:767px){.hidden-lg.hidden-xs{display:none !important}tr .hidden-lg.hidden-xs{display:none !important}th .hidden-lg.hidden-xs,td .hidden-lg.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-lg.hidden-sm{display:none !important}tr .hidden-lg.hidden-sm{display:none !important}th .hidden-lg.hidden-sm,td .hidden-lg.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-lg.hidden-md{display:none !important}tr .hidden-lg.hidden-md{display:none !important}th .hidden-lg.hidden-md,td .hidden-lg.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}tr .hidden-lg{display:none !important}th .hidden-lg,td .hidden-lg{display:none !important}}.visible-print{display:none !important}tr .visible-print{display:none !important}th .visible-print,td .visible-print{display:none !important}@media print{.visible-print{display:block !important}tr .visible-print{display:table-row !important}th .visible-print,td .visible-print{display:table-cell !important}.hidden-print{display:none !important}tr .hidden-print{display:none !important}th .hidden-print,td .hidden-print{display:none !important}}body{background-image:url(/images/highlight-bg.png),url(/images/site-bg.png);background-repeat:no-repeat,repeat;background-position:center top,left top}a{text-decoration:none;transition:all .25s ease 0s}a:hover{text-decoration:none}a,object{outline:0}a.showcaseTarget:hover>img{-moz-transform:scale(1);-webkit-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1);-moz-transition:all .1s ease-in-out;-webkit-transition:all .1s ease-in-out;-ms-transition:all .1s ease-in-out;-o-transition:all .1s ease-in-out;transition:all .1s ease-in-out}a.showcaseTarget:hover>img:hover{-moz-transform:scale(1.1);-webkit-transform:scale(1.1);-o-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}hr{border-color:lightgray}blockquote{background-color:#F8F9FF}.columns-2{-webkit-columns:2;-moz-columns:2;columns:2}.members-list img{max-width:40px;float:left}h3:before{display:block;content:" ";margin-top:-60px;height:60px;visibility:hidden}.columns-2>h3{margin:0}.columns-2>ul{margin-bottom:0}table{width:100%;margin-bottom:22px}table thead>tr>th,table tbody>tr>th,table tfoot>tr>th,table thead>tr>td,table tbody>tr>td,table tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border:1px solid #ddd}table thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}table tbody+tbody{border-top:2px solid #ddd}table .table{background-color:#fff}.navbar-brand{padding:10px}.search-form{float:right}@media (max-width:992px){.search-form{display:none}}@media (max-width:1200px){.search-form{display:none}}@media (max-width:768px){.search-form{display:none}}.inverse-dropdown{background-color:#222 !important;border-color:#080808 !important}.inverse-dropdown.divider{background-color:#000 !important}.inverse-dropdown>li>a{color:#9d9d9d !important}.inverse-dropdown>li>a:hover{color:#fff !important;background-color:#000 !important}.nav .caret{border-top-color:#ffffff;border-bottom-color:#ffffff}.nav a:hover .caret{border-top-color:#ffffff;border-bottom-color:#ffffff}.btn{font-size:20px;background:#ECECEC;border-radius:10px;padding:16px 30px;text-decoration:none;text-shadow:0 1px 0 #fff;border:1px solid #a7a7a7;box-shadow:0 2px 1px white inset,0 -2px 8px white,0 2px 5px rgba(0,0,0,0.1),0 8px 10px rgba(0,0,0,0.1);-webkit-transition:box-shadow .5s}.btn:hover{box-shadow:0 2px 1px white inset,0 -2px 20px white,0 2px 5px rgba(0,0,0,0.1),0 8px 10px rgba(0,0,0,0.1)}.btn:active{top:2px;position:relative;box-shadow:0 1px 2px rgba(0,0,0,0.5) inset,0 -2px 20px white,0 1px 5px rgba(0,0,0,0.1),0 2px 10px rgba(0,0,0,0.1);background:-webkit-linear-gradient(top, #d1d1d1 0, #ECECEC 100%)}.btn-header{float:right;margin-top:-60px;padding:4px 6px;position:relative}.btn-api{float:right;margin-top:-62px;margin-right:85px;padding:4px 6px;position:relative}.btn-edit{float:right;margin-top:-62px;padding:4px 6px;position:relative}.btn-source{float:right;margin-top:20px;padding:4px 6px;position:relative;z-index:99}.title{position:relative;padding-bottom:14px}.title:before{background-image:-webkit-linear-gradient(left, #ffdb2d 0, #ffdb2d 20%, #e30019 20%, #e30019 40%, #9CB641 40%, #9CB641 60%, #1a2eef 60%, #1a2eef 80%, #00abf3 80%, #00abf3 100%);background-image:-moz-linear-gradient(left center, #ffdb2d 0, #ffdb2d 20%, #e30019 20%, #e30019 40%, #9CB641 40%, #9CB641 60%, #1a2eef 60%, #1a2eef 80%, #00abf3 80%, #00abf3 100%);bottom:-6px;content:"";height:4px;left:0;margin-bottom:8px;position:absolute;right:0}pre .title:before{background-image:none}.center-align-a{padding:1em;text-align:center}.center-align-a>a{position:relative;padding:14px;display:inline-table}.container-main{margin-top:24px;margin-bottom:150px;background:#ffffff;border:1px solid #D0D0D0;border-radius:10px;min-height:820px;padding:16px;overflow:hidden}.container-main-content{max-width:600px;margin:0 auto}.heading-menu-item>a{margin-left:0}.sponsor-logos img{margin:16px;max-height:216px}.level-up-labs-logo{height:94px}.aseprite-logo{max-width:234px}code{padding:0;padding-top:.2em;padding-bottom:.2em;margin:0;font-size:85%;background-color:rgba(27,31,35,0.05);border-radius:3px;border:0}code:not(.hljs)::before,code:not(.hljs)::after{letter-spacing:-0.2em;content:"\00a0"}.flixel-footer-logo{height:40px}.footer-powered-by img.openfl-footer-logo{width:46px}.lead-line{font-size:30px;font-weight:200;padding-bottom:30px}.lead-line-large{font-size:30px;font-weight:200}.carousel-inner>.item>img,.carousel-inner>.item>a>img{width:100%}.home-button{font-size:20px;background:#ECECEC;border-radius:10px;padding:16px 30px;text-decoration:none;text-shadow:0 1px 0 #fff;border:1px solid #a7a7a7;box-shadow:0 2px 1px white inset,0 -2px 8px white,0 2px 5px rgba(0,0,0,0.1),0 8px 10px rgba(0,0,0,0.1);-webkit-transition:box-shadow .5s;margin-left:4;margin-right:4px;text-align:center}.home-button:hover{box-shadow:0 2px 1px white inset,0 -2px 20px white,0 2px 5px rgba(0,0,0,0.1),0 8px 10px rgba(0,0,0,0.1)}.home-button:active{top:2px;position:relative;box-shadow:0 1px 2px rgba(0,0,0,0.5) inset,0 -2px 20px white,0 1px 5px rgba(0,0,0,0.1),0 2px 10px rgba(0,0,0,0.1);background:-webkit-linear-gradient(top, #d1d1d1 0, #ECECEC 100%)}.sponsors-button{font-size:24px;display:block;width:300px;margin:0 auto}.platinum-container{display:flex;justify-content:center;align-items:center;font-family:'VT323',monospace;font-size:56px}.home-header{margin-top:5em}.home-header h1{font-size:6em;line-height:1}.home-social{margin-top:2em}.home-section-features{position:relative;padding:1em;text-align:left;font-size:1.1em}.home-section{position:relative;padding:1em;text-align:center}.demos-home img{margin:10px;-moz-box-shadow:0 1px 5px #696969, 0 -2px 5px #F2F2F2;-webkit-box-shadow:0 1px 5px #696969, 0 -2px 5px #F2F2F2;box-shadow:0 1px 5px #696969, 0 -2px 5px #F2F2F2}.platform-logos-home img{padding:10px;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=@value*100)";-moz-opacity:.7;-khtml-opacity:.7;opacity:.7;-moz-transform:scale(1);-webkit-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1);-moz-transition:all .1s ease-in-out;-webkit-transition:all .1s ease-in-out;-ms-transition:all .1s ease-in-out;-o-transition:all .1s ease-in-out;transition:all .1s ease-in-out;filter:url("data:image/svg+xml;utf8,#grayscale");filter:gray;-webkit-filter:grayscale(100%)}.platform-logos-home img:hover{-moz-transform:scale(1.1);-webkit-transform:scale(1.1);-o-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}.platform-logos-home img:hover{-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=@value*100)";-moz-opacity:1;-khtml-opacity:1;opacity:1;filter:url("data:image/svg+xml;utf8,#grayscale");-webkit-filter:grayscale(0)}.platform-demos-home img{-moz-transform:scale(1);-webkit-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1);-moz-transition:all .1s ease-in-out;-webkit-transition:all .1s ease-in-out;-ms-transition:all .1s ease-in-out;-o-transition:all .1s ease-in-out;transition:all .1s ease-in-out;padding:10px}.platform-demos-home img:hover{-moz-transform:scale(1.1);-webkit-transform:scale(1.1);-o-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}.twitter-follow-button.twitter-follow-button{height:36px}.home-big-logo img{-moz-transform:scale(1);-webkit-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1);-moz-transition:all .1s ease-in-out;-webkit-transition:all .1s ease-in-out;-ms-transition:all .1s ease-in-out;-o-transition:all .1s ease-in-out;transition:all .1s ease-in-out}.home-big-logo img:hover{-moz-transform:scale(1.1);-webkit-transform:scale(1.1);-o-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}.navbar-fixed-top{box-shadow:0 0 3px 3px rgba(0,0,0,0.3)}.icon-next.tweet-next{right:0;position:absolute;left:100%}.icon-prev.tweet-prev{right:100%;position:absolute;left:0}.home-section-powered{text-align:center}.home-section-powered img{-moz-transform:scale(1);-webkit-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1);-moz-transition:all .1s ease-in-out;-webkit-transition:all .1s ease-in-out;-ms-transition:all .1s ease-in-out;-o-transition:all .1s ease-in-out;transition:all .1s ease-in-out}.home-section-powered img:hover{-moz-transform:scale(1.03);-webkit-transform:scale(1.03);-o-transform:scale(1.03);-ms-transform:scale(1.03);transform:scale(1.03)}.home-section-powered span{font-size:48px;padding:20px}.patreon-home img{max-width:240px;vertical-align:top;margin-left:30px}.backer-hr{margin-top:60px}@media (max-width:992px){.home-button{margin-top:20px;margin-bottom:20px;display:block}}@media (max-width:1200px){.demos-home.home-section{max-width:700px;margin:0 auto}}@media (max-width:768px){.home-header h1{font-size:4em}}.sponsor-logos-container{display:flex;justify-content:center;align-items:center}.lead-line-large{text-align:center}.home-sponsor-logos img{margin:16px;max-height:174px}@media (max-width:1200px){.sponsor-logos-container{flex-direction:column}}pre{background-color:#1E1E1E;display:block;overflow-x:auto;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:14px;color:#FFFFFF}.highlighted .mtk1{color:#FFFFFF}.highlighted .mtk2{color:#FFFFFF}.highlighted .mtk3{color:#6796E6}.highlighted .mtk4{color:#608B4E}.highlighted .mtk5{color:#569CD6}.highlighted .mtk6{color:#D16969}.highlighted .mtk7{color:#D7BA7D}.highlighted .mtk8{color:#B5CEA8}.highlighted .mtk9{color:#CE9178}.highlighted .mtk10{color:#646695}.highlighted .mtk11{color:#4EC9B0}.highlighted .mtk12{color:#DCDCAA}.highlighted .mtk13{color:#9CDCFE}.highlighted .mtk14{color:#000080}.highlighted .mtk15{color:#F44747}.highlighted .mtk16{color:#C586C0}.highlighted .mtk17{color:#D4D4D4}.highlighted .mtk18{color:#808080}.highlighted .mtki{font-style:italic}.highlighted .mtkb{font-weight:bold}.highlighted .mtku{text-decoration:underline}.footer-main{margin-top:60px;background:url("/images/footer-shadow.png") repeat-x scroll 0 0 #515151;min-height:110px;text-shadow:none}footer:before{background-image:-webkit-linear-gradient(left, #ffdb2d 0, #ffdb2d 20%, #e30019 20%, #e30019 40%, #9CB641 40%, #9CB641 60%, #1a2eef 60%, #1a2eef 80%, #00abf3 80%, #00abf3 100%);background-image:-moz-linear-gradient(left center, #ffdb2d 0, #ffdb2d 20%, #e30019 20%, #e30019 40%, #9CB641 40%, #9CB641 60%, #1a2eef 60%, #1a2eef 80%, #00abf3 80%, #00abf3 100%);top:1;content:"";height:4px;left:0;position:absolute;right:0}.footer-powered-by{color:#FFFFFF;float:right;margin-top:20px}.footer-powered-by p{display:inline}.footer-powered-by img{width:40px;-moz-transform:scale(1);-webkit-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);transform:scale(1);-moz-transition:all .1s ease-in-out;-webkit-transition:all .1s ease-in-out;-ms-transition:all .1s ease-in-out;-o-transition:all .1s ease-in-out;transition:all .1s ease-in-out;margin:6px}.footer-powered-by img:hover{-moz-transform:scale(1.2);-webkit-transform:scale(1.2);-o-transform:scale(1.2);-ms-transform:scale(1.2);transform:scale(1.2)}.footer-social{margin-top:28px;float:left}.footer-patreon{margin-left:20px;white-space:nowrap}.footer-patreon img{height:40px;margin-left:0}.footer-patreon img.patreon-wordmark{height:60px;margin-left:-15px}#demoSWF{display:block;margin:0 auto}@media (max-width:992px){.footer-powered-by{float:none;margin-top:40px;margin-bottom:40px;white-space:nowrap;text-align:center}.footer-powered-by a{display:inline-block}.footer-social{float:none;text-align:center}.footer-powered-by p{display:inline-block;margin-bottom:26px}}.doc-nav .nav>.active>a,.doc-nav .nav>.active:hover>a,.doc-nav .nav>.active:focus>a{background-color:rgba(0,0,0,0);border-left:1px solid #000000;color:#000000;font-weight:bold}.doc-nav a{display:block;margin-left:14px}.doc-nav{position:static;top:80px;background-color:#F4F8FF;border-radius:6px;margin-bottom:30px;margin-top:30px;padding-bottom:10px;padding-top:10px;text-shadow:0 1px 0 #FFFFFF}.doc-nav .nav>li>a{display:block;color:#000000;padding:5px 20px}.doc-nav .nav>li>a:hover,.doc-nav .nav>li>a:focus{text-decoration:none;background-color:#FFF;border-left:1px solid #000000}.doc-nav .nav>.active>a,.doc-nav .nav>.active:hover>a,.doc-nav .nav>.active:focus>a{font-weight:bold;color:#000000;background-color:#FFF;border-left:1px solid #000000}.doc-nav .nav .nav{display:none;margin-bottom:8px}.doc-nav .nav .nav>li>a{padding-top:3px;padding-bottom:3px;padding-left:30px;font-size:90%}.doc-list-item{margin-bottom:-16px}.doc-list span{font-size:.8em;margin-right:7px}.sideBySide{width:48%;float:left}.spacer-right{margin-right:20px}.clear{clear:both}.members-list{padding-left:0}.members-list>li{list-style:none}.gist pre{box-shadow:none}@media (max-width:992px){.sideBySide{width:100%;float:none}}@media screen and (min-width:992px){.doc-nav .nav>.active>ul{display:block}.doc-nav.affix,.doc-nav.affix-bottom{width:213px}.doc-nav.affix{top:80px}.doc-nav.affix-bottom{position:absolute}.doc-nav.affix-bottom,.doc-nav.affix{margin-top:30px;margin-bottom:0}}.highlighted .container{padding-left:0;padding-right:0;display:inline}.highlighted .container:before,.highlighted .container:after{clear:none;content:none}@media screen and (min-width:1200px){.doc-nav.affix-bottom,.doc-nav.affix{width:263px}}.demo-page.center-align-a img{-moz-box-shadow:0 1px 5px #696969, 0 -2px 5px #F2F2F2;-webkit-box-shadow:0 1px 5px #696969, 0 -2px 5px #F2F2F2;box-shadow:0 1px 5px #696969, 0 -2px 5px #F2F2F2}.demo-page.center-align-a p{display:inline;position:absolute;text-align:center;width:190px;color:white;background:rgba(0,0,0,0.7);padding:10px}#page-tr-info{float:right;margin-top:-60px;position:relative;z-index:99}#githubBtn-tr-info{float:right;margin-top:-60px;position:relative;z-index:99}.demo-button{cursor:pointer;cursor:hand}.demo-button .logo{fill:#afafaf}.flash-button.active .logo,.flash-button:hover .logo{fill:red}.html5-button.active .logo,.html5-button:hover .logo{fill:orange}.flash-warning{margin:0 auto;display:none;text-align:center}.html5-demo{border:none;margin:0 auto;display:block}.install-flash-player-prompt{width:110px}.showcase-targets img{padding-top:10px;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=@value*100)";-moz-opacity:.7;-khtml-opacity:.7;opacity:.7}.showcases-target-active img{filter:url("data:image/svg+xml;utf8,#grayscale");-webkit-filter:grayscale(0);-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=@value*100)";-moz-opacity:.7;-khtml-opacity:.7;opacity:.7}.showcases-target img{filter:url("data:image/svg+xml;utf8,#grayscale");filter:gray;-webkit-filter:grayscale(100%);-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=@value*100)";-moz-opacity:.1;-khtml-opacity:.1;opacity:.1}.showcase-grid .col-md-4:nth-child(3n+1){clear:both}.showcase-game-thumbnail img{-moz-box-shadow:0 1px 5px #696969, 0 -2px 5px #F2F2F2;-webkit-box-shadow:0 1px 5px #696969, 0 -2px 5px #F2F2F2;box-shadow:0 1px 5px #696969, 0 -2px 5px #F2F2F2;width:100%;max-width:500px;height:auto}.showcase-game{padding-bottom:40px}.showcase-game h3{height:60px;width:540px;position:relative;bottom:10px;display:table-cell;vertical-align:bottom}.fundraiser-header{display:flex}.indiegogo-frame{margin:20px}.success-text{display:flex}.success-text span{margin:10px}.thankyou-backers{text-align:center}.backer-list{display:flex;justify-content:center;flex-wrap:wrap;list-style:none;padding:0;margin:0 auto}.backer{position:relative;display:flex;flex-direction:row;align-items:center;justify-content:center;width:240px;height:120px;margin:10px;padding:10px;text-align:center;border:1px solid #c4c4c4;border-radius:4px}.backer-amount{position:absolute;bottom:0;right:0;margin:0;padding:10px}.backer h4{margin:10px;overflow:hidden}@media screen and (max-width:740px){.indiegogo-frame{display:none}.fundraiser-header{flex-direction:column;align-items:center;text-align:center}}.twitter-widget{margin-top:70px}.post-date{text-align:right;color:#b8b8b8}.post-date-preview{position:relative;top:-35px;height:0} \ No newline at end of file diff --git a/vendor/LESSHat/LICENSE b/vendor/LESSHat/LICENSE new file mode 100644 index 000000000..f45b78b1e --- /dev/null +++ b/vendor/LESSHat/LICENSE @@ -0,0 +1,44 @@ +MIT License + +Copyright (c) 2012 +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +BSD License + +Copyright (c) 2012 +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Organization nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/vendor/LESSHat/README.rdoc b/vendor/LESSHat/README.rdoc new file mode 100644 index 000000000..b2a555108 --- /dev/null +++ b/vendor/LESSHat/README.rdoc @@ -0,0 +1,26 @@ +=LESS HAT + +==Features + +All CSS3 properties which need to be prefixed + +Unlimited number of anything, shadows, gradients, gradient swatches. + +Configurable -turn off all other browsers and get just CSS3 which you want + +SVG gradient fallback for IE9 + +Prefix free - everywhere use only W3C syntax and Less Hat takes care of it + + +==About + +A supersonic bunch of smart LESS mixins. + +Homepage and examples: http://lesshat.com + +From creators of: http://csshat.com + +==License + +LESS Hat is dual-licensed under the new BSD and MIT licenses, see LICENCE file above. diff --git a/vendor/LESSHat/lesshat.less b/vendor/LESSHat/lesshat.less new file mode 100644 index 000000000..f564ea703 --- /dev/null +++ b/vendor/LESSHat/lesshat.less @@ -0,0 +1,2198 @@ +// LESS Hat 1.1.2 +// LESSHat.com +// From creators of CSSHat.com +// 2012 +// Petr Brzek & Jan Kuca + + +// @GlobalConfig + +// .animation +// .animation-delay +// .animation-direction +// .animation-duration +// .animation-fill-mode +// .animation-timing-function +// .animation-iteration-count +// .animation-name +// .animation-play-state +// .keyframes - in future +// .appearance +// .backface-visibility +// .background-clip +// .background-image +// .background-origin +// .background-size +// .border-radius +// .border-top-left-radius +// .border-top-right-radius +// .border-bottom-left-radius +// .border-bottom-right-radius +// .border-image +// .box-shadow +// .box-sizing +// .columns +// .column-count +// .column-gap +// .column-rule +// .column-width +// .font-face +// .gradient +// .opacity +// .perspective +// .perspective-origin +// .size +// .transform +// .transform-origin +// .transform-style +// .translate +// .translate3d +// .translateX +// .translateY +// .translateZ +// .scale +// .scale3d +// .scaleX +// .scaleY +// .scaleZ +// .rotate +// .rotate3d +// .rotateX +// .rotateY +// .rotateZ +// .skew +// .skewX +// .skewY +// .transition +// .transition-property +// .transition-duration +// .transition-timing-function +// .transition-delay +// .user-select +// DEPRECATED mixins + + +// @GlobalConfig + +// Config supported browsers for your project + +@w3c: true; // Unprefixed W3C syntax +@webkit: true; // Chrome 7+, Safari 5+, iOS5, Android +@moz: true; // Firefox 4+ +@opera: true; // Opera 10.5+ +@ms: true; // IE 10+ + +// Signals + +@webkitSignal: 1; +@mozSignal: 2; +@operaSignal: 3; +@msSignal: 4; +@w3cSignal: 5; + +// .animation + +.animation(...){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + @processing: ~`(function(){ var arg = "@{arguments}".replace("[","").replace("]","") || "none"; if( !/^\w*([ X])/.test(arg) ) { arg = arg.replace(/,/g,"") } return arg; })()`; + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-animation: @processing;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-animation: @processing;} + .inception (@signal, @arguments) when (@signal = 3) { -o-animation: @processing;} + .inception (@signal, @arguments) when (@signal = 4) { -ms-animation: @processing;} + .inception (@signal, @arguments) when (@signal = 5) { animation: @processing;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .animation(nameAnimation 2s linear alternate anim 3s linear alternate ); } + + +// .animation-delay + +.animation-delay(...){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + @processing: ~`(function(){ var arg = "@{arguments}" || "0"; arg = arg.replace("[","").replace("]",""); return arg; }())`; + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-animation-delay: @processing;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-animation-delay: @processing;} + .inception (@signal, @arguments) when (@signal = 3) { -o-animation-delay: @processing;} + .inception (@signal, @arguments) when (@signal = 4) { -ms-animation-delay: @processing;} + .inception (@signal, @arguments) when (@signal = 5) { animation-delay: @processing;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .animation-delay(1s); } +// element{ .animation-delay(750ms, 2s, 3s); } // For multiple animation-direction + + +// .animation-direction + +.animation-direction(...){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + @processing: ~`(function(){ var arg = "@{arguments}" || "normal"; arg = arg.replace("[","").replace("]",""); return arg; }())`; + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-animation-direction: @processing;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-animation-direction: @processing;} + .inception (@signal, @arguments) when (@signal = 3) { -o-animation-direction: @processing;} + .inception (@signal, @arguments) when (@signal = 4) { -ms-animation-direction: @processing;} + .inception (@signal, @arguments) when (@signal = 5) { animation-direction: @processing;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .animation-direction(); } +// element{ .animation-direction(normal, alternate); } + + +// .animation-duration + +.animation-duration(...){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + @processing: ~`(function(){ var arg = "@{arguments}" || "0"; arg = arg.replace("[","").replace("]",""); return arg; }())`; + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-animation-duration: @processing;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-animation-duration: @processing;} + .inception (@signal, @arguments) when (@signal = 3) { -o-animation-duration: @processing;} + .inception (@signal, @arguments) when (@signal = 4) { -ms-animation-duration: @processing;} + .inception (@signal, @arguments) when (@signal = 5) { animation-duration: @processing;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .animation-duration(2s); } + + +// .animation-fill-mode + +.animation-fill-mode(...){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + @processing: ~`(function(){ var arg = "@{arguments}" || "none"; arg = arg.replace("[","").replace("]",""); return arg; }())`; + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-animation-fill-mode: @processing;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-animation-fill-mode: @processing;} + .inception (@signal, @arguments) when (@signal = 3) { -o-animation-fill-mode: @processing;} + .inception (@signal, @arguments) when (@signal = 5) { animation-fill-mode: @processing;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .animation-fill-mode(forwards); } + + +// .animation-timing-function + +.animation-timing-function(...){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + @processing: ~`(function(){ var arg = "@{arguments}" || "ease"; arg = arg.replace("[","").replace("]",""); return arg; }())`; + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-animation-timing-function: @processing;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-animation-timing-function: @processing;} + .inception (@signal, @arguments) when (@signal = 3) { -o-animation-timing-function: @processing;} + .inception (@signal, @arguments) when (@signal = 4) { -ms-animation-timing-function: @processing;} + .inception (@signal, @arguments) when (@signal = 5) { animation-timing-function: @processing;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .animation-timing-function(ease-in-out); } + + +// .animation-iteration-count + +.animation-iteration-count(...){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + @processing: ~`(function(){ var arg = "@{arguments}" || "0"; arg = arg.replace("[","").replace("]",""); return arg; }())`; + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-animation-iteration-count: @processing;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-animation-iteration-count: @processing;} + .inception (@signal, @arguments) when (@signal = 3) { -o-animation-iteration-count: @processing;} + .inception (@signal, @arguments) when (@signal = 4) { -ms-animation-iteration-count: @processing;} + .inception (@signal, @arguments) when (@signal = 5) { animation-iteration-count: @processing;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .animation-iteration-count(3); } + + +// .animation-name + +.animation-name(...){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + @processing: ~`(function(){ var arg = "@{arguments}" || "none"; arg = arg.replace("[","").replace("]",""); return arg; }())`; + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-animation-name: @processing;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-animation-name: @processing;} + .inception (@signal, @arguments) when (@signal = 3) { -o-animation-name: @processing;} + .inception (@signal, @arguments) when (@signal = 4) { -ms-animation-name: @processing;} + .inception (@signal, @arguments) when (@signal = 5) { animation-name: @processing;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .animation-name(myReallyCoolAnimationName); } + + +// .animation-play-state + +.animation-play-state(...){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + @processing: ~`(function(){ var arg = "@{arguments}" || "running"; arg = arg.replace("[","").replace("]",""); return arg; }())`; + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-animation-play-state: @processing;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-animation-play-state: @processing;} + .inception (@signal, @arguments) when (@signal = 3) { -o-animation-play-state: @processing;} + .inception (@signal, @arguments) when (@signal = 4) { -ms-animation-play-state: @processing;} + .inception (@signal, @arguments) when (@signal = 5) { animation-play-state: @processing;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .animation-play-state(paused); } + + +// .appearance + +.appearance(@argument:none){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @argument) when (@signal = 1) { -webkit-appearance: @argument;} + .inception (@signal, @argument) when (@signal = 2) { -moz-appearance: @argument;} + .inception (@signal, @argument) when (@signal = 5) { appearance: @argument;} + .inception (@signal, @argument) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @argument); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .appearance(button); } + + +// .backface-visibility + +.backface-visibility(@argument:visible){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @argument) when (@signal = 1) { -webkit-backface-visibility: @argument;} + .inception (@signal, @argument) when (@signal = 2) { -moz-backface-visibility: @argument;} + .inception (@signal, @argument) when (@signal = 5) { backface-visibility: @argument;} + .inception (@signal, @argument) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @argument); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .backface-visibility(hidden); } + + +// .background-clip + +.background-clip(@arguments:border-box){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-background-clip: @arguments;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-background-clip: @arguments;} + .inception (@signal, @arguments) when (@signal = 5) { background-clip: @arguments;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .background-clip(padding-box); } + + +// .background-image + +.background-image(...){ + + // Local config for disabling properties + + @svg: true; // SVG gradient for IE9 + @mozLocal: true; // Firefox 4+ + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5+, Android + @operaLocal: true; // Opera 10.5+ + @w3cLocal: true; // Unprefixed W3C syntax + + @backgroundSVG: ~`(function(){function K(a){var b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",c,d,e,f,g,h,i,j,k=0,l=0,m="",n=[];if(!a)return a;do c=a.charCodeAt(k++),d=a.charCodeAt(k++),e=a.charCodeAt(k++),j=c<<16|d<<8|e,f=j>>18&63,g=j>>12&63,h=j>>6&63,i=j&63,n[l++]=b.charAt(f)+b.charAt(g)+b.charAt(h)+b.charAt(i);while(k');if(f.test(d[q])&&!j.test(d[q])||l.test(d[q])||/180deg/.test(d[q])){var r=null;l.test(d[q])?r=l:/180deg/.test(d[q])?r=/180deg/:r=f,d[q]=d[q].replace(r,'')}else if(g.test(d[q])&&!k.test(d[q])||m.test(d[q])||/270deg/.test(d[q])){var r=null;m.test(d[q])?r=m:/270deg/.test(d[q])?r=/270deg/:r=g,d[q]=d[q].replace(r,'')}else if(h.test(d[q])&&!l.test(d[q])||j.test(d[q])||/[^\d]0deg/.test(d[q])){var r=null;j.test(d[q])?r=j:/0deg/.test(d[q])?r=/0deg/:r=h,d[q]=d[q].replace(r,'')}else if(i.test(d[q])&&!m.test(d[q])||k.test(d[q])||/90deg/.test(d[q])){var r=null;k.test(d[q])?r=k:/90deg/.test(d[q])?r=/90deg/:r=i,d[q]=d[q].replace(r,'')}else n.test(d[q])&&!o.test(d[q])?d[q]=d[q].replace(n,''):o.test(d[q])?d[q]=d[q].replace(o,''):c=!1}try{"".trim(),b=!0}catch(s){b=!1}b&&(d[q]=d[q].trim());if(/linear/.test(d[q])||/radial/.test(d[q])){d[q]=d[q].slice(0,-1),d[q]="url(data:image/svg+xml;base64--"+d[q]+')';var t=d.join("@@@"),u=t.match(/rgba?\(\d+,\s*\d+,\s*\d+,\s*(?:0|1|\.\d+|0\.\d+)\)\s*\d*%*/g)||0,v=t.match(/hsla?\(\d+,\s*\d+%,\s*\d+%,\s*(?:0|1|\.\d+|0\.\d+)\)\s*\d*%*/g)||0,w=[],x=[];for(var y=0;y').replace(/(rgba?\(\d+--\s*\d+--\s*\d+--\s*(0|1|\.\d+|0\.\d+)\))\s*(\d*.?\d*%)*/g,'').replace(/rgba/g,"rgb").replace(/(hsla?\(\d+--\s*\d+%--\s*\d+%--\s*(0|1|\.\d+|0\.\d+)\))\s*(\d*.?\d*%)*/g,'').replace(/hsla/g,"hsl").replace(/((?:aqua|black|blue|fuchsia|gray|grey|green|lime|maroon|navy|olive|purple|red|silver|teal|white|yellow))\s*(\d*%)*/g,'').replace(/\*\*\*/,"#grad-ucgg-generated");try{"".trim(),b=!0}catch(s){b=!1}b&&(C[E]=C[E].trim());if(/offset=""/g.test(C[E])){var F=C.length-2,G=Math.round(100/F)*D;var H='offset="'+G+'%"';C[E]=C[E].replace(/offset=""/,H),D++}}C=C.toString().replace(/,/g,"").replace(/--/g,",").replace(/(rgb?\(\d+,\s*\d+,\s*\d+),\s*(?:0|1|\.\d+|0\.\d+)\)/g,"$1)").replace(/(hsl?\(\d+,\s*\d+%,\s*\d+%),\s*(?:0|1|\.\d+|0\.\d+)\)/g,"$1)")}}/radial/.test(C)&&(/((ellipse).*(center)|(circle).*(center))/g.test(C)?C=C.replace(/<\/linearGradient>/g,"").replace(/radial-gradient[^<]+/g,'').replace(//g,''):C=!1);var I=null;try{C=C.split("@@@");var J=0;for(J;J/),I=K(I.join("")),C[J]=C[J].replace(/(<\?xml.*<\/svg>)/,I)}catch(s){}return c?C:C=!1,C?C.toString():C})()`; + @backgroundMoz: ~`(function(){var a,b,c,d,e,f,g,h,i,j,k;a="@{arguments}",c=null,d=a.split(/,(?=\s*(?:linear|radial))/g),e=d.length,k=/to\s*top/,j=/to\s*right/,h=/to\s*bottom/,i=/to\s*left/,b=/\d*deg/,f=0;while(f 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .background-origin(content-box); } + + +// .background-size + +.background-size(...){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + @processing: ~`(function(){ var arg = "@{arguments}".replace("[","").replace("]","") || "none"; if( !/^\w*%?([ X])/.test(arg) ) { arg = arg.replace(/,/g,"") } return arg; })()`; + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-background-size: @processing;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-background-size: @processing;} + .inception (@signal, @arguments) when (@signal = 5) { background-size: @processing;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .background-size(50% auto); } + + +// .border-radius + +.border-radius(@arguments:0) { + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-border-radius: @arguments; -webkit-background-clip: padding-box;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-border-radius: @arguments; -moz-background-clip: padding;} + .inception (@signal, @arguments) when (@signal = 5) { border-radius: @arguments; background-clip: padding-box; } + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .border-radius(10px); } // all corner rounded +// element{ .border-radius(~"10px / 20px"); } // NEED TO BE ESCAPED OR LESS DEVIDE IT! Horizontal and vertical rounded differently +// element{ .border-radius(0 10px 0 0); } // only top right corner rounded + + +// .border-top-left-radius + +.border-top-left-radius(@arguments:0) { + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-border-top-left-radius: @arguments; -webkit-background-clip: padding-box;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-border-radius-topleft: @arguments; -moz-background-clip: padding;} + .inception (@signal, @arguments) when (@signal = 5) { border-top-left-radius: @arguments; background-clip: padding-box; } + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .border-top-left-radius(10px); } + + +// .border-top-right-radius + +.border-top-right-radius(@arguments:0) { + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-border-top-right-radius: @arguments; -webkit-background-clip: padding-box;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-border-radius-topright: @arguments; -moz-background-clip: padding;} + .inception (@signal, @arguments) when (@signal = 5) { border-top-right-radius: @arguments; background-clip: padding-box; } + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .border-top-right-radius(10px); } + + +// .border-bottom-left-radius + +.border-bottom-left-radius(@arguments:0) { + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-border-bottom-left-radius: @arguments; -webkit-background-clip: padding-box;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-border-radius-bottomleft: @arguments; -moz-background-clip: padding;} + .inception (@signal, @arguments) when (@signal = 5) { border-bottom-left-radius: @arguments; background-clip: padding-box; } + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .border-bottom-left-radius(10px); } + + +// .border-bottom-right-radius + +.border-bottom-right-radius(@arguments:0) { + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-border-bottom-right-radius: @arguments; -webkit-background-clip: padding-box;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-border-radius-bottomright: @arguments; -moz-background-clip: padding;} + .inception (@signal, @arguments) when (@signal = 5) { border-bottom-right-radius: @arguments; background-clip: padding-box; } + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .border-bottom-right-radius(10px); } + + +// .border-image + +.border-image(@arguments:none){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-border-image: @arguments;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-border-image: @arguments;} + .inception (@signal, @arguments) when (@signal = 3) { -o-border-image: @arguments;} + .inception (@signal, @arguments) when (@signal = 5) { border-image: @arguments; } + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .border-image(url(border.png) 30 30 round); } + + +// .box-shadow + +.box-shadow(...){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + @processing: ~`(function(){ var arg = "@{arguments}".replace("[","").replace("]","") || "none"; if( !/^#?\w*%?([ X])/.test(arg) ) { arg = arg.replace(/,(?=[^()]*\))/g,'--').replace(/,/g,"").replace(/--/g,','); } return arg; })()`; + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-box-shadow: @processing;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-box-shadow: @processing;} + .inception (@signal, @arguments) when (@signal = 5) { box-shadow: @processing;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .box-shadow(0 1px 10px rgba(20,20,20,0.5), 0 1px 10px rgba(20,20,20,0.5)); } + + +// .box-sizing + +.box-sizing(@arguments:content-box){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-box-sizing: @arguments;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-box-sizing: @arguments;} + .inception (@signal, @arguments) when (@signal = 5) { box-sizing: @arguments;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .box-sizing(border-box); } + + +// .columns + +.columns(@arguments:auto auto){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-columns: @arguments;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-columns: @arguments;} + .inception (@signal, @arguments) when (@signal = 5) { columns: @arguments;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .columns(100px 3); } + + +// .column-count + +.column-count(@arguments:auto){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-column-count: @arguments;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-column-count: @arguments;} + .inception (@signal, @arguments) when (@signal = 5) { column-count: @arguments;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .column-count(3); } + + +// .column-gap + +.column-gap(@arguments:normal){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-column-gap: @arguments;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-column-gap: @arguments;} + .inception (@signal, @arguments) when (@signal = 5) { column-gap: @arguments;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .column-gap(40px); } + + +// .column-rule + +.column-rule(@arguments:medium none black){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-column-rule: @arguments;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-column-rule: @arguments;} + .inception (@signal, @arguments) when (@signal = 5) { column-rule: @arguments;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .column-rule(3px outset #ff00ff); } + + +// .column-width + +.column-width(@arguments:auto){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-column-width: @arguments;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-column-width: @arguments;} + .inception (@signal, @arguments) when (@signal = 5) { column-width: @arguments;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .column-width(100px); } + + +// .font-face + +.font-face(@fontname, @fontfile) { + + font-family: "@{fontname}"; + src: url("@{fontfile}-webfont.eot"); + src: url("@{fontfile}-webfont.eot?#iefix") format("embedded-opentype"), + url("@{fontfile}-webfont.woff") format("woff"), + url("@{fontfile}-webfont.ttf") format("truetype"), + url("@{fontfile}-webfont.svg#@{fontname}") format("svg"); + font-weight: normal; + font-style: normal; +} + +// element{ .font-face(ZendaRegular, zenda-webfont); } + + +// .opacity + +.opacity(@arguments:1){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-opacity: @arguments;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-opacity: @arguments;} + .inception (@signal, @arguments) when (@signal = 5) { opacity: @arguments;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .opacity(.5); } + + +// .perspective + +.perspective(@arguments:none){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-perspective: @arguments;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-perspective: @arguments;} + .inception (@signal, @arguments) when (@signal = 5) { perspective: @arguments;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .perspective(350px); } + + +// .perspective-origin + +.perspective-origin(@arguments:50% 50%){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-perspective-origin: @arguments;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-perspective-origin: @arguments;} + .inception (@signal, @arguments) when (@signal = 5) { perspective-origin: @arguments;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .perspective-origin(top left); } + + +// .size + +.size(@square){ + width: @square; + height: @square; +} + +.size(@width, @height){ + width: @width; + height: @height; +} + +// element{ .size(10px); } // render width:10px; height:10px; +// element{ .size(10px, 20px); } // render width:10px; height: 20px; + + +// .transform + +.transform(@arguments:none, ...){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: @arguments;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: @arguments;} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: @arguments;} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: @arguments;} + .inception (@signal, @arguments) when (@signal = 5) { transform: @arguments;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .transform(scale(.5) translate(10px, 20px)); } + + +// .transform-origin + +.transform-origin(@arguments:50% 50% 0){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform-origin: @arguments;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform-origin: @arguments;} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform-origin: @arguments;} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform-origin: @arguments;} + .inception (@signal, @arguments) when (@signal = 5) { transform-origin: @arguments;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .transform-origin(20% 40%); } + + +// .transform-style + +.transform-style(@arguments:flat){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform-style: @arguments;} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform-style: @arguments;} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform-style: @arguments;} + .inception (@signal, @arguments) when (@signal = 5) { transform-style: @arguments;} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .transform-style(preserve-3d); } + + +// .translate + +.translate(@x:0, @y:0){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: translate(@x, @y);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: translate(@x, @y);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: translate(@x, @y);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: translate(@x, @y);} + .inception (@signal, @arguments) when (@signal = 5) { transform: translate(@x, @y);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .translate(100px); } +// element{ .translate(100px, 50px); } + + +// .translate3d + +.translate3d(@x:0, @y:0, @z:0){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: translate3d(@x, @y, @z);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: translate3d(@x, @y, @z);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: translate3d(@x, @y, @z);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: translate3d(@x, @y, @z);} + .inception (@signal, @arguments) when (@signal = 5) { transform: translate3d(@x, @y, @z);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .translate3d(10px, 20px, 30px); } + + +// .translateX + +.translateX(@x:0){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: translateX(@x);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: translateX(@x);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: translateX(@x);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: translateX(@x);} + .inception (@signal, @arguments) when (@signal = 5) { transform: translateX(@x);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .translateX(10px); } + + +// .translateY + +.translateY(@y:0){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: translateY(@y);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: translateY(@y);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: translateY(@y);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: translateY(@y);} + .inception (@signal, @arguments) when (@signal = 5) { transform: translateY(@y);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .translateY(15px); } + + +// .translateZ + +.translateZ(@z:0){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: translateZ(@z);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: translateZ(@z);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: translateZ(@z);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: translateZ(@z);} + .inception (@signal, @arguments) when (@signal = 5) { transform: translateZ(@z);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .translateZ(32px); } + + +// .scale + +.scale(@x:1){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: scale(@x);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: scale(@x);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: scale(@x);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: scale(@x);} + .inception (@signal, @arguments) when (@signal = 5) { transform: scale(@x);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +.scale(@x, @y){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: scale(@x, @y);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: scale(@x, @y);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: scale(@x, @y);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: scale(@x, @y);} + .inception (@signal, @arguments) when (@signal = 5) { transform: scale(@x, @y);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .scale(2); } +// element{ .scale(2, 1); } + + +// .scale3d + +.scale3d(@x:1, @y:1, @z:1){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: scale3d(@x, @y, @z);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: scale3d(@x, @y, @z);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: scale3d(@x, @y, @z);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: scale3d(@x, @y, @z);} + .inception (@signal, @arguments) when (@signal = 5) { transform: scale3d(@x, @y, @z);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .scale3d(1, 2, 1); } + + +// .scaleX + +.scaleX(@x:1){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: scaleX(@x);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: scaleX(@x);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: scaleX(@x);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: scaleX(@x);} + .inception (@signal, @arguments) when (@signal = 5) { transform: scaleX(@x);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .scaleX(1.5); } + + +// .scaleY + +.scaleY(@y:1){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: scaleY(@y);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: scaleY(@y);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: scaleY(@y);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: scaleY(@y);} + .inception (@signal, @arguments) when (@signal = 5) { transform: scaleY(@y);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .scaleX(1.5); } + + +// .scaleZ + +.scaleZ(@z:1){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: scaleZ(@z);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: scaleZ(@z);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: scaleZ(@z);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: scaleZ(@z);} + .inception (@signal, @arguments) when (@signal = 5) { transform: scaleZ(@z);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .scaleZ(2.7); } + + +// .rotate + +.rotate(@angle:0){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: rotate(@angle);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: rotate(@angle);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: rotate(@angle);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: rotate(@angle);} + .inception (@signal, @arguments) when (@signal = 5) { transform: rotate(@angle);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .rotate(45deg); } + + +// .rotate3d + +.rotate3d(@x:0, @y:0, @z: 0, @angle:0){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: rotate3d(@x, @y, @z, @angle);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: rotate3d(@x, @y, @z, @angle);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: rotate3d(@x, @y, @z, @angle);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: rotate3d(@x, @y, @z, @angle);} + .inception (@signal, @arguments) when (@signal = 5) { transform: rotate3d(@x, @y, @z, @angle);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .rotate3d(1, 2.0, 3.0, 10deg); } + + +// .rotateX + +.rotateX(@angle:0){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: rotateX(@angle);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: rotateX(@angle);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: rotateX(@angle);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: rotateX(@angle);} + .inception (@signal, @arguments) when (@signal = 5) { transform: rotateX(@angle);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .rotateX(63deg); } + + +// .rotateY + +.rotateY(@angle:0){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: rotateY(@angle);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: rotateY(@angle);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: rotateY(@angle);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: rotateY(@angle);} + .inception (@signal, @arguments) when (@signal = 5) { transform: rotateY(@angle);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .rotateY(24deg); } + + +// .rotateZ + +.rotateZ(@angle:0){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: rotateZ(@angle);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: rotateZ(@angle);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: rotateZ(@angle);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: rotateZ(@angle);} + .inception (@signal, @arguments) when (@signal = 5) { transform: rotateZ(@angle);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .rotateZ(280deg); } + + +// .skew + +.skew(@angle:0){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: skew(@angle);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: skew(@angle);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: skew(@angle);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: skew(@angle);} + .inception (@signal, @arguments) when (@signal = 5) { transform: skew(@angle);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .skew(20deg); } + + +// .skewX + +.skewX(@angle:0){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: skewX(@angle);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: skewX(@angle);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: skewX(@angle);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: skewX(@angle);} + .inception (@signal, @arguments) when (@signal = 5) { transform: skewX(@angle);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .skewX(24deg); } + + +// .skewY + +.skewY(@angle:0){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transform: skewY(@angle);} + .inception (@signal, @arguments) when (@signal = 2) { -moz-transform: skewY(@angle);} + .inception (@signal, @arguments) when (@signal = 3) { -o-transform: skewY(@angle);} + .inception (@signal, @arguments) when (@signal = 4) { -ms-transform: skewY(@angle);} + .inception (@signal, @arguments) when (@signal = 5) { transform: skewY(@angle);} + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .skewY(36deg); } + + +// .transition + +.transition(...){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + @transitionWebkit: ~`(function(){var a,b,c,d,e,f,g;a="@{arguments}".split(","),c=["background-size","border-","box-shadow","column","transform"],d=c.length,e=a,f=!1,b=a.length;for(var h=0;h 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .transition(transform 3s linear); } + + +// .transition-property + +.transition-property(...){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + @transitionWebkit: ~`(function(){var a,b,c,d,e,f,g;a="@{arguments}".split(","),c=["background-size","border-","box-shadow","column","transform"],d=c.length,e=a,f=!1,b=a.length;for(var h=0;h 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .transition-property(width, height); } + + +// .transition-duration + +.transition-duration(...){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + @processing: ~`(function(){ var arg = "@{arguments}" || "0"; try{ var hasComma = arg.match(/,/g).length > 1 ? true : false; } catch (e) {} if (hasComma === true) arg = arg.replace(/,/g,""); arg = arg.replace("[","").replace("]",""); return arg; }())`; + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transition-duration: @processing; } + .inception (@signal, @arguments) when (@signal = 2) { -moz-transition-duration: @processing; } + .inception (@signal, @arguments) when (@signal = 3) { -o-transition-duration: @processing; } + .inception (@signal, @arguments) when (@signal = 5) { transition-duration: @processing; } + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .transition-duration(250ms); } + + +// .transition-timing-function + +.transition-timing-function(...){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + @processing: ~`(function(){ var arg = "@{arguments}" || "ease"; arg = arg.replace("[","").replace("]",""); return arg; }())`; + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transition-timing-function: @processing; } + .inception (@signal, @arguments) when (@signal = 2) { -moz-transition-timing-function: @processing; } + .inception (@signal, @arguments) when (@signal = 3) { -o-transition-timing-function: @processing; } + .inception (@signal, @arguments) when (@signal = 5) { transition-timing-function: @processing; } + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .transition-timing-function(cubic-bezier(0,0,1,1)); } + + +// .transition-delay + +.transition-delay(...){ + + // Local config for disabling properties + + @w3cLocal: true; // Unprefixed W3C syntax + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @operaLocal: true; // Opera 10.5+ + @msLocal: true; // IE 10+ + + @processing: ~`(function(){ var arg = "@{arguments}" || "0"; arg = arg.replace("[","").replace("]",""); return arg; }())`; + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-transition-delay: @processing; } + .inception (@signal, @arguments) when (@signal = 2) { -moz-transition-delay: @processing; } + .inception (@signal, @arguments) when (@signal = 3) { -o-transition-delay: @processing; } + .inception (@signal, @arguments) when (@signal = 5) { transition-delay: @processing; } + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @operaSignal, @opera, @operaLocal); + // -- + .result(@arguments, @w3cSignal, @w3c, @w3cLocal); +} + +// element{ .transition-delay(2s); } + + +// .user-select + +.user-select(@arguments:auto){ + + // Local config for disabling properties + + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @mozLocal: true; // Firefox 4+ + @msLocal: true; // IE 10+ + + .result (@arguments, @signal, @boolean, @localBoolean) when (@boolean = true) and (@localBoolean = true) { + .inception (@signal, @arguments) when (@signal = 1) { -webkit-user-select: @arguments; } + .inception (@signal, @arguments) when (@signal = 2) { -moz-user-select: @arguments; } + .inception (@signal, @arguments) when (@signal = 4) { -ms-user-select: @arguments; } + .inception (@signal, @arguments) when (@signal > 5),(@signal < 1) { error: "Signal is out of range"; } + .inception(@signal, @arguments); + } + .result (@arguments, @signal, @boolean, @localBoolean) when not (@boolean = true), not (@localBoolean = true) { } + + .result(@arguments, @webkitSignal, @webkit, @webkitLocal); + // -- this comment must be here because of LESS bug + .result(@arguments, @mozSignal, @moz, @mozLocal); + // -- + .result(@arguments, @msSignal, @ms, @msLocal); +} + +// element{ .user-select(text); } + + +// DEPRECATED mixins (must be supported because of old version of CSS Hat) + +// .gradient (renamed background-image) + +.gradient(...){ + + // Local config for disabling properties + + @svg: true; // SVG gradient for IE9 + @mozLocal: true; // Firefox 4+ + @webkitLocal: true; // Chrome 7+, Safari 5+, iOS5, Android + @operaLocal: true; // Opera 10.5+ + @w3cLocal: true; // Unprefixed W3C syntax + + @backgroundSVG: ~`(function(){function G(a){var b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",c,d,e,f,g,h,i,j,k=0,l=0,m="",n=[];if(!a)return a;do c=a.charCodeAt(k++),d=a.charCodeAt(k++),e=a.charCodeAt(k++),j=c<<16|d<<8|e,f=j>>18&63,g=j>>12&63,h=j>>6&63,i=j&63,n[l++]=b.charAt(f)+b.charAt(g)+b.charAt(h)+b.charAt(i);while(k');if(f.test(d[q])&&!j.test(d[q])||l.test(d[q])||/180deg/.test(d[q])){var r=null;l.test(d[q])?r=l:/180deg/.test(d[q])?r=/180deg/:r=f,d[q]=d[q].replace(r,'')}else if(g.test(d[q])&&!k.test(d[q])||m.test(d[q])||/270deg/.test(d[q])){var r=null;m.test(d[q])?r=m:/270deg/.test(d[q])?r=/270deg/:r=g,d[q]=d[q].replace(r,'')}else if(h.test(d[q])&&!l.test(d[q])||j.test(d[q])||/[^\d]0deg/.test(d[q])){var r=null;j.test(d[q])?r=j:/0deg/.test(d[q])?r=/0deg/:r=h,d[q]=d[q].replace(r,'')}else if(i.test(d[q])&&!m.test(d[q])||k.test(d[q])||/90deg/.test(d[q])){var r=null;k.test(d[q])?r=k:/90deg/.test(d[q])?r=/90deg/:r=i,d[q]=d[q].replace(r,'')}else n.test(d[q])&&!o.test(d[q])?d[q]=d[q].replace(n,''):o.test(d[q])?d[q]=d[q].replace(o,''):c=!1}try{"".trim(),b=!0}catch(s){b=!1}b&&(d[q]=d[q].trim());if(/linear/.test(d[q])||/radial/.test(d[q])){d[q]=d[q].slice(0,-1),d[q]="url(data:image/svg+xml;base64--"+d[q]+')';var t=d.join("@@@"),u=t.match(/rgba?\(\d+,\s*\d+,\s*\d+,\s*(?:0|1|\.\d+|0\.\d+)\)\s*\d*%*/g)||0,v=t.match(/hsla?\(\d+,\s*\d+%,\s*\d+%,\s*(?:0|1|\.\d+|0\.\d+)\)\s*\d*%*/g)||0,w=[],x=[];for(var y=0;y').replace(/(rgba?\(\d+--\s*\d+--\s*\d+--\s*(0|1|\.\d+|0\.\d+)\))\s*(\d*%)*/g,'').replace(/rgba/g,"rgb").replace(/(hsla?\(\d+--\s*\d+%--\s*\d+%--\s*(0|1|\.\d+|0\.\d+)\))\s*(\d*%)*/g,'').replace(/hsla/g,"hsl").replace(/((?:aqua|black|blue|fuchsia|gray|grey|green|lime|maroon|navy|olive|purple|red|silver|teal|white|yellow))\s*(\d*%)*/g,'').replace(/\*\*\*/,"#grad-ucgg-generated");try{"".trim(),b=!0}catch(s){b=!1}b&&(C[D]=C[D].trim())}C=C.toString().replace(/,/g,"").replace(/--/g,",").replace(/(rgb?\(\d+,\s*\d+,\s*\d+),\s*(?:0|1|\.\d+|0\.\d+)\)/g,"$1)").replace(/(hsl?\(\d+,\s*\d+%,\s*\d+%),\s*(?:0|1|\.\d+|0\.\d+)\)/g,"$1)")}}/radial/.test(C)&&(/((ellipse).*(center)|(circle).*(center))/g.test(C)?C=C.replace(/<\/linearGradient>/g,"").replace(/radial-gradient[^<]+/g,'').replace(//g,''):C=!1);var E=null;try{C=C.split("@@@");var F=0;for(F;F/),E=G(E.join("")),C[F]=C[F].replace(/(<\?xml.*<\/svg>)/,E)}catch(s){}return c?C:C=!1,C?C.toString().replace(/\[/g,"").replace(/\]/g,""):C}())`; + @backgroundMoz: ~`(function(){var a,b,c,d,e,f,g,h,i,j,k;a="@{arguments}",c=null,d=a.split(/,(?=\s*(?:linear|radial))/g),e=d.length,k=/to\s*top/,j=/to\s*right/,h=/to\s*bottom/,i=/to\s*left/,b=/\d*deg/,f=0;while(f + + +``` + +The full list of digests for every file can be found below. + +### Digests + +``` +sha384-uBlc/xEFeDxZmBU7K/YWwi3ryXQrLQCAY2K1Dl3OD2DaAQBZZTt6Ew3aeDP20ix0 /es/languages/bash.js +sha384-4qer4rJCVxZjkwD4YaJfOnT2NOOt0qdjKYJM2076C+djiJ4lgrP1LVsB/MCpJSET /es/languages/bash.min.js +sha384-Sp8E1Lb9fNhbvqBiogM60TCgpAIwYBi8WbHhIHcXO0bR5Z+9LeYwpDa1gkjzU99W /es/languages/csharp.js +sha384-huUb4Ol37G1WrtGV7bn1UArXcJSjD4tQswMGzgpNZYAPxR74MHTqW79z1dXWMvhk /es/languages/csharp.min.js +sha384-lZQp/EFiCoX1u9SeTlr5j1oULRhxSd9gBGl25v0bm17TTE/DXlbDtsFDdaQvFHiw /es/languages/haxe.js +sha384-SVFB5K3g6+IUca/JOVZ/3Xb6vzLQ+DEJMC3hxJjKTpbKPLdLhBcaZwL1RY9VaKbI /es/languages/haxe.min.js +sha384-OFoR8IZ+CFwcY8plx8HSDZNoCwLxc701CwdNGfoIEhSgwAbwhvInaxnEi3HYTt2Q /es/languages/xml.js +sha384-yFd3InBtG6WtAVgIl6iIdFKis8HmMC7GbbronB4lHJq3OLef3U8K9puak6MuVZqx /es/languages/xml.min.js +sha384-qbbaBGYYg7PdopdWOGj8KdkBosUDY5PAe3aTMJKTqWcriPBJJzCVu5BlwNEwqr9U /languages/bash.js +sha384-ByZsYVIHcE8sB12cYY+NUpM80NAWHoBs5SL8VVocIvqVLdXf1hmXNSBn/H9leT4c /languages/bash.min.js +sha384-8sbRwiU8Ar2M7+w//1u7YiI1e7KsmB4k3QbW/m1IW5FVH51HiOpR7g5QGE3RqTNi /languages/csharp.js +sha384-wWP4JQEhRVshehTP7lUMDn3yhDI2+398vN2QW5LBt1xIpK0Gfu4dPviO8tP9XRo5 /languages/csharp.min.js +sha384-lck/LqDqfpCkfVfsruoAIEm5i6D66TIBvliiD+iPwv0eE2m+8HqTtSXKBD02Uoxu /languages/haxe.js +sha384-uUmo8PWFx8gz1l7YQJJni6Enst2ZpJpYOnegvyrILp5YdqT9dwQuStgIob3F5few /languages/haxe.min.js +sha384-+PuZYFfVX2UQZU2yKt/FsJUZNUPzZWxW7auXltsaecr1xLvzBYF3c5gYoyOs1++x /languages/xml.js +sha384-jgkY4GMNWfQcLLIoP1vg3FWXflDrRhcSXGBW6ONIWC2SOIv5H1Pa57sXs+aomCuZ /languages/xml.min.js +sha384-ij2WfLBTKKcJScltXOyF8d+/3P27gwlh1LYLeVmGfQO96RygJWNCK1lJ1G3/M3OO /highlight.js +sha384-ur0+iDdWIupb0K/oyZXwLunOIqRI3Ug60G0YAS5LjT5WrBr+jGsmMUomu0KZY/ak /highlight.min.js +``` + diff --git a/vendor/highlightjs/LICENSE b/vendor/highlightjs/LICENSE new file mode 100644 index 000000000..2250cc7ec --- /dev/null +++ b/vendor/highlightjs/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2006, Ivan Sagalaev. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/highlightjs/README.md b/vendor/highlightjs/README.md new file mode 100644 index 000000000..30d84b95f --- /dev/null +++ b/vendor/highlightjs/README.md @@ -0,0 +1,45 @@ +# Highlight.js CDN Assets + +[![install size](https://packagephobia.now.sh/badge?p=highlight.js)](https://packagephobia.now.sh/result?p=highlight.js) + +**This package contains only the CDN build assets of highlight.js.** + +This may be what you want if you'd like to install the pre-built distributable highlight.js client-side assets via NPM. If you're wanting to use highlight.js mainly on the server-side you likely want the [highlight.js][1] package instead. + +To access these files via CDN:
+https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@latest/build/ + +**If you just want a single .js file with the common languages built-in: +** + +--- + +## Highlight.js + +Highlight.js is a syntax highlighter written in JavaScript. It works in +the browser as well as on the server. It works with pretty much any +markup, doesn’t depend on any framework, and has automatic language +detection. + +If you'd like to read the full README:
+ + +## License + +Highlight.js is released under the BSD License. See [LICENSE][7] file +for details. + +## Links + +The official site for the library is at . + +The Github project may be found at: + +Further in-depth documentation for the API and other topics is at +. + +A list of the Core Team and contributors can be found in the [CONTRIBUTORS.md][8] file. + +[1]: https://www.npmjs.com/package/highlight.js +[7]: https://github.com/highlightjs/highlight.js/blob/main/LICENSE +[8]: https://github.com/highlightjs/highlight.js/blob/main/CONTRIBUTORS.md diff --git a/vendor/highlightjs/es/core.js b/vendor/highlightjs/es/core.js new file mode 100644 index 000000000..7294b81df --- /dev/null +++ b/vendor/highlightjs/es/core.js @@ -0,0 +1,2600 @@ +/*! + Highlight.js v11.9.0 (git: b7ec4bfafc) + (c) 2006-2023 undefined and other contributors + License: BSD-3-Clause + */ +/* eslint-disable no-multi-assign */ + +function deepFreeze(obj) { + if (obj instanceof Map) { + obj.clear = + obj.delete = + obj.set = + function () { + throw new Error('map is read-only'); + }; + } else if (obj instanceof Set) { + obj.add = + obj.clear = + obj.delete = + function () { + throw new Error('set is read-only'); + }; + } + + // Freeze self + Object.freeze(obj); + + Object.getOwnPropertyNames(obj).forEach((name) => { + const prop = obj[name]; + const type = typeof prop; + + // Freeze prop if it is an object or function and also not already frozen + if ((type === 'object' || type === 'function') && !Object.isFrozen(prop)) { + deepFreeze(prop); + } + }); + + return obj; +} + +/** @typedef {import('highlight.js').CallbackResponse} CallbackResponse */ +/** @typedef {import('highlight.js').CompiledMode} CompiledMode */ +/** @implements CallbackResponse */ + +class Response { + /** + * @param {CompiledMode} mode + */ + constructor(mode) { + // eslint-disable-next-line no-undefined + if (mode.data === undefined) mode.data = {}; + + this.data = mode.data; + this.isMatchIgnored = false; + } + + ignoreMatch() { + this.isMatchIgnored = true; + } +} + +/** + * @param {string} value + * @returns {string} + */ +function escapeHTML(value) { + return value + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +/** + * performs a shallow merge of multiple objects into one + * + * @template T + * @param {T} original + * @param {Record[]} objects + * @returns {T} a single new object + */ +function inherit$1(original, ...objects) { + /** @type Record */ + const result = Object.create(null); + + for (const key in original) { + result[key] = original[key]; + } + objects.forEach(function(obj) { + for (const key in obj) { + result[key] = obj[key]; + } + }); + return /** @type {T} */ (result); +} + +/** + * @typedef {object} Renderer + * @property {(text: string) => void} addText + * @property {(node: Node) => void} openNode + * @property {(node: Node) => void} closeNode + * @property {() => string} value + */ + +/** @typedef {{scope?: string, language?: string, sublanguage?: boolean}} Node */ +/** @typedef {{walk: (r: Renderer) => void}} Tree */ +/** */ + +const SPAN_CLOSE = ''; + +/** + * Determines if a node needs to be wrapped in + * + * @param {Node} node */ +const emitsWrappingTags = (node) => { + // rarely we can have a sublanguage where language is undefined + // TODO: track down why + return !!node.scope; +}; + +/** + * + * @param {string} name + * @param {{prefix:string}} options + */ +const scopeToCSSClass = (name, { prefix }) => { + // sub-language + if (name.startsWith("language:")) { + return name.replace("language:", "language-"); + } + // tiered scope: comment.line + if (name.includes(".")) { + const pieces = name.split("."); + return [ + `${prefix}${pieces.shift()}`, + ...(pieces.map((x, i) => `${x}${"_".repeat(i + 1)}`)) + ].join(" "); + } + // simple scope + return `${prefix}${name}`; +}; + +/** @type {Renderer} */ +class HTMLRenderer { + /** + * Creates a new HTMLRenderer + * + * @param {Tree} parseTree - the parse tree (must support `walk` API) + * @param {{classPrefix: string}} options + */ + constructor(parseTree, options) { + this.buffer = ""; + this.classPrefix = options.classPrefix; + parseTree.walk(this); + } + + /** + * Adds texts to the output stream + * + * @param {string} text */ + addText(text) { + this.buffer += escapeHTML(text); + } + + /** + * Adds a node open to the output stream (if needed) + * + * @param {Node} node */ + openNode(node) { + if (!emitsWrappingTags(node)) return; + + const className = scopeToCSSClass(node.scope, + { prefix: this.classPrefix }); + this.span(className); + } + + /** + * Adds a node close to the output stream (if needed) + * + * @param {Node} node */ + closeNode(node) { + if (!emitsWrappingTags(node)) return; + + this.buffer += SPAN_CLOSE; + } + + /** + * returns the accumulated buffer + */ + value() { + return this.buffer; + } + + // helpers + + /** + * Builds a span element + * + * @param {string} className */ + span(className) { + this.buffer += ``; + } +} + +/** @typedef {{scope?: string, language?: string, children: Node[]} | string} Node */ +/** @typedef {{scope?: string, language?: string, children: Node[]} } DataNode */ +/** @typedef {import('highlight.js').Emitter} Emitter */ +/** */ + +/** @returns {DataNode} */ +const newNode = (opts = {}) => { + /** @type DataNode */ + const result = { children: [] }; + Object.assign(result, opts); + return result; +}; + +class TokenTree { + constructor() { + /** @type DataNode */ + this.rootNode = newNode(); + this.stack = [this.rootNode]; + } + + get top() { + return this.stack[this.stack.length - 1]; + } + + get root() { return this.rootNode; } + + /** @param {Node} node */ + add(node) { + this.top.children.push(node); + } + + /** @param {string} scope */ + openNode(scope) { + /** @type Node */ + const node = newNode({ scope }); + this.add(node); + this.stack.push(node); + } + + closeNode() { + if (this.stack.length > 1) { + return this.stack.pop(); + } + // eslint-disable-next-line no-undefined + return undefined; + } + + closeAllNodes() { + while (this.closeNode()); + } + + toJSON() { + return JSON.stringify(this.rootNode, null, 4); + } + + /** + * @typedef { import("./html_renderer").Renderer } Renderer + * @param {Renderer} builder + */ + walk(builder) { + // this does not + return this.constructor._walk(builder, this.rootNode); + // this works + // return TokenTree._walk(builder, this.rootNode); + } + + /** + * @param {Renderer} builder + * @param {Node} node + */ + static _walk(builder, node) { + if (typeof node === "string") { + builder.addText(node); + } else if (node.children) { + builder.openNode(node); + node.children.forEach((child) => this._walk(builder, child)); + builder.closeNode(node); + } + return builder; + } + + /** + * @param {Node} node + */ + static _collapse(node) { + if (typeof node === "string") return; + if (!node.children) return; + + if (node.children.every(el => typeof el === "string")) { + // node.text = node.children.join(""); + // delete node.children; + node.children = [node.children.join("")]; + } else { + node.children.forEach((child) => { + TokenTree._collapse(child); + }); + } + } +} + +/** + Currently this is all private API, but this is the minimal API necessary + that an Emitter must implement to fully support the parser. + + Minimal interface: + + - addText(text) + - __addSublanguage(emitter, subLanguageName) + - startScope(scope) + - endScope() + - finalize() + - toHTML() + +*/ + +/** + * @implements {Emitter} + */ +class TokenTreeEmitter extends TokenTree { + /** + * @param {*} options + */ + constructor(options) { + super(); + this.options = options; + } + + /** + * @param {string} text + */ + addText(text) { + if (text === "") { return; } + + this.add(text); + } + + /** @param {string} scope */ + startScope(scope) { + this.openNode(scope); + } + + endScope() { + this.closeNode(); + } + + /** + * @param {Emitter & {root: DataNode}} emitter + * @param {string} name + */ + __addSublanguage(emitter, name) { + /** @type DataNode */ + const node = emitter.root; + if (name) node.scope = `language:${name}`; + + this.add(node); + } + + toHTML() { + const renderer = new HTMLRenderer(this, this.options); + return renderer.value(); + } + + finalize() { + this.closeAllNodes(); + return true; + } +} + +/** + * @param {string} value + * @returns {RegExp} + * */ + +/** + * @param {RegExp | string } re + * @returns {string} + */ +function source(re) { + if (!re) return null; + if (typeof re === "string") return re; + + return re.source; +} + +/** + * @param {RegExp | string } re + * @returns {string} + */ +function lookahead(re) { + return concat('(?=', re, ')'); +} + +/** + * @param {RegExp | string } re + * @returns {string} + */ +function anyNumberOfTimes(re) { + return concat('(?:', re, ')*'); +} + +/** + * @param {RegExp | string } re + * @returns {string} + */ +function optional(re) { + return concat('(?:', re, ')?'); +} + +/** + * @param {...(RegExp | string) } args + * @returns {string} + */ +function concat(...args) { + const joined = args.map((x) => source(x)).join(""); + return joined; +} + +/** + * @param { Array } args + * @returns {object} + */ +function stripOptionsFromArgs(args) { + const opts = args[args.length - 1]; + + if (typeof opts === 'object' && opts.constructor === Object) { + args.splice(args.length - 1, 1); + return opts; + } else { + return {}; + } +} + +/** @typedef { {capture?: boolean} } RegexEitherOptions */ + +/** + * Any of the passed expresssions may match + * + * Creates a huge this | this | that | that match + * @param {(RegExp | string)[] | [...(RegExp | string)[], RegexEitherOptions]} args + * @returns {string} + */ +function either(...args) { + /** @type { object & {capture?: boolean} } */ + const opts = stripOptionsFromArgs(args); + const joined = '(' + + (opts.capture ? "" : "?:") + + args.map((x) => source(x)).join("|") + ")"; + return joined; +} + +/** + * @param {RegExp | string} re + * @returns {number} + */ +function countMatchGroups(re) { + return (new RegExp(re.toString() + '|')).exec('').length - 1; +} + +/** + * Does lexeme start with a regular expression match at the beginning + * @param {RegExp} re + * @param {string} lexeme + */ +function startsWith(re, lexeme) { + const match = re && re.exec(lexeme); + return match && match.index === 0; +} + +// BACKREF_RE matches an open parenthesis or backreference. To avoid +// an incorrect parse, it additionally matches the following: +// - [...] elements, where the meaning of parentheses and escapes change +// - other escape sequences, so we do not misparse escape sequences as +// interesting elements +// - non-matching or lookahead parentheses, which do not capture. These +// follow the '(' with a '?'. +const BACKREF_RE = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./; + +// **INTERNAL** Not intended for outside usage +// join logically computes regexps.join(separator), but fixes the +// backreferences so they continue to match. +// it also places each individual regular expression into it's own +// match group, keeping track of the sequencing of those match groups +// is currently an exercise for the caller. :-) +/** + * @param {(string | RegExp)[]} regexps + * @param {{joinWith: string}} opts + * @returns {string} + */ +function _rewriteBackreferences(regexps, { joinWith }) { + let numCaptures = 0; + + return regexps.map((regex) => { + numCaptures += 1; + const offset = numCaptures; + let re = source(regex); + let out = ''; + + while (re.length > 0) { + const match = BACKREF_RE.exec(re); + if (!match) { + out += re; + break; + } + out += re.substring(0, match.index); + re = re.substring(match.index + match[0].length); + if (match[0][0] === '\\' && match[1]) { + // Adjust the backreference. + out += '\\' + String(Number(match[1]) + offset); + } else { + out += match[0]; + if (match[0] === '(') { + numCaptures++; + } + } + } + return out; + }).map(re => `(${re})`).join(joinWith); +} + +/** @typedef {import('highlight.js').Mode} Mode */ +/** @typedef {import('highlight.js').ModeCallback} ModeCallback */ + +// Common regexps +const MATCH_NOTHING_RE = /\b\B/; +const IDENT_RE = '[a-zA-Z]\\w*'; +const UNDERSCORE_IDENT_RE = '[a-zA-Z_]\\w*'; +const NUMBER_RE = '\\b\\d+(\\.\\d+)?'; +const C_NUMBER_RE = '(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)'; // 0x..., 0..., decimal, float +const BINARY_NUMBER_RE = '\\b(0b[01]+)'; // 0b... +const RE_STARTERS_RE = '!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~'; + +/** +* @param { Partial & {binary?: string | RegExp} } opts +*/ +const SHEBANG = (opts = {}) => { + const beginShebang = /^#![ ]*\//; + if (opts.binary) { + opts.begin = concat( + beginShebang, + /.*\b/, + opts.binary, + /\b.*/); + } + return inherit$1({ + scope: 'meta', + begin: beginShebang, + end: /$/, + relevance: 0, + /** @type {ModeCallback} */ + "on:begin": (m, resp) => { + if (m.index !== 0) resp.ignoreMatch(); + } + }, opts); +}; + +// Common modes +const BACKSLASH_ESCAPE = { + begin: '\\\\[\\s\\S]', relevance: 0 +}; +const APOS_STRING_MODE = { + scope: 'string', + begin: '\'', + end: '\'', + illegal: '\\n', + contains: [BACKSLASH_ESCAPE] +}; +const QUOTE_STRING_MODE = { + scope: 'string', + begin: '"', + end: '"', + illegal: '\\n', + contains: [BACKSLASH_ESCAPE] +}; +const PHRASAL_WORDS_MODE = { + begin: /\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ +}; +/** + * Creates a comment mode + * + * @param {string | RegExp} begin + * @param {string | RegExp} end + * @param {Mode | {}} [modeOptions] + * @returns {Partial} + */ +const COMMENT = function(begin, end, modeOptions = {}) { + const mode = inherit$1( + { + scope: 'comment', + begin, + end, + contains: [] + }, + modeOptions + ); + mode.contains.push({ + scope: 'doctag', + // hack to avoid the space from being included. the space is necessary to + // match here to prevent the plain text rule below from gobbling up doctags + begin: '[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)', + end: /(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/, + excludeBegin: true, + relevance: 0 + }); + const ENGLISH_WORD = either( + // list of common 1 and 2 letter words in English + "I", + "a", + "is", + "so", + "us", + "to", + "at", + "if", + "in", + "it", + "on", + // note: this is not an exhaustive list of contractions, just popular ones + /[A-Za-z]+['](d|ve|re|ll|t|s|n)/, // contractions - can't we'd they're let's, etc + /[A-Za-z]+[-][a-z]+/, // `no-way`, etc. + /[A-Za-z][a-z]{2,}/ // allow capitalized words at beginning of sentences + ); + // looking like plain text, more likely to be a comment + mode.contains.push( + { + // TODO: how to include ", (, ) without breaking grammars that use these for + // comment delimiters? + // begin: /[ ]+([()"]?([A-Za-z'-]{3,}|is|a|I|so|us|[tT][oO]|at|if|in|it|on)[.]?[()":]?([.][ ]|[ ]|\))){3}/ + // --- + + // this tries to find sequences of 3 english words in a row (without any + // "programming" type syntax) this gives us a strong signal that we've + // TRULY found a comment - vs perhaps scanning with the wrong language. + // It's possible to find something that LOOKS like the start of the + // comment - but then if there is no readable text - good chance it is a + // false match and not a comment. + // + // for a visual example please see: + // https://github.com/highlightjs/highlight.js/issues/2827 + + begin: concat( + /[ ]+/, // necessary to prevent us gobbling up doctags like /* @author Bob Mcgill */ + '(', + ENGLISH_WORD, + /[.]?[:]?([.][ ]|[ ])/, + '){3}') // look for 3 words in a row + } + ); + return mode; +}; +const C_LINE_COMMENT_MODE = COMMENT('//', '$'); +const C_BLOCK_COMMENT_MODE = COMMENT('/\\*', '\\*/'); +const HASH_COMMENT_MODE = COMMENT('#', '$'); +const NUMBER_MODE = { + scope: 'number', + begin: NUMBER_RE, + relevance: 0 +}; +const C_NUMBER_MODE = { + scope: 'number', + begin: C_NUMBER_RE, + relevance: 0 +}; +const BINARY_NUMBER_MODE = { + scope: 'number', + begin: BINARY_NUMBER_RE, + relevance: 0 +}; +const REGEXP_MODE = { + scope: "regexp", + begin: /\/(?=[^/\n]*\/)/, + end: /\/[gimuy]*/, + contains: [ + BACKSLASH_ESCAPE, + { + begin: /\[/, + end: /\]/, + relevance: 0, + contains: [BACKSLASH_ESCAPE] + } + ] +}; +const TITLE_MODE = { + scope: 'title', + begin: IDENT_RE, + relevance: 0 +}; +const UNDERSCORE_TITLE_MODE = { + scope: 'title', + begin: UNDERSCORE_IDENT_RE, + relevance: 0 +}; +const METHOD_GUARD = { + // excludes method names from keyword processing + begin: '\\.\\s*' + UNDERSCORE_IDENT_RE, + relevance: 0 +}; + +/** + * Adds end same as begin mechanics to a mode + * + * Your mode must include at least a single () match group as that first match + * group is what is used for comparison + * @param {Partial} mode + */ +const END_SAME_AS_BEGIN = function(mode) { + return Object.assign(mode, + { + /** @type {ModeCallback} */ + 'on:begin': (m, resp) => { resp.data._beginMatch = m[1]; }, + /** @type {ModeCallback} */ + 'on:end': (m, resp) => { if (resp.data._beginMatch !== m[1]) resp.ignoreMatch(); } + }); +}; + +var MODES = /*#__PURE__*/Object.freeze({ + __proto__: null, + APOS_STRING_MODE: APOS_STRING_MODE, + BACKSLASH_ESCAPE: BACKSLASH_ESCAPE, + BINARY_NUMBER_MODE: BINARY_NUMBER_MODE, + BINARY_NUMBER_RE: BINARY_NUMBER_RE, + COMMENT: COMMENT, + C_BLOCK_COMMENT_MODE: C_BLOCK_COMMENT_MODE, + C_LINE_COMMENT_MODE: C_LINE_COMMENT_MODE, + C_NUMBER_MODE: C_NUMBER_MODE, + C_NUMBER_RE: C_NUMBER_RE, + END_SAME_AS_BEGIN: END_SAME_AS_BEGIN, + HASH_COMMENT_MODE: HASH_COMMENT_MODE, + IDENT_RE: IDENT_RE, + MATCH_NOTHING_RE: MATCH_NOTHING_RE, + METHOD_GUARD: METHOD_GUARD, + NUMBER_MODE: NUMBER_MODE, + NUMBER_RE: NUMBER_RE, + PHRASAL_WORDS_MODE: PHRASAL_WORDS_MODE, + QUOTE_STRING_MODE: QUOTE_STRING_MODE, + REGEXP_MODE: REGEXP_MODE, + RE_STARTERS_RE: RE_STARTERS_RE, + SHEBANG: SHEBANG, + TITLE_MODE: TITLE_MODE, + UNDERSCORE_IDENT_RE: UNDERSCORE_IDENT_RE, + UNDERSCORE_TITLE_MODE: UNDERSCORE_TITLE_MODE +}); + +/** +@typedef {import('highlight.js').CallbackResponse} CallbackResponse +@typedef {import('highlight.js').CompilerExt} CompilerExt +*/ + +// Grammar extensions / plugins +// See: https://github.com/highlightjs/highlight.js/issues/2833 + +// Grammar extensions allow "syntactic sugar" to be added to the grammar modes +// without requiring any underlying changes to the compiler internals. + +// `compileMatch` being the perfect small example of now allowing a grammar +// author to write `match` when they desire to match a single expression rather +// than being forced to use `begin`. The extension then just moves `match` into +// `begin` when it runs. Ie, no features have been added, but we've just made +// the experience of writing (and reading grammars) a little bit nicer. + +// ------ + +// TODO: We need negative look-behind support to do this properly +/** + * Skip a match if it has a preceding dot + * + * This is used for `beginKeywords` to prevent matching expressions such as + * `bob.keyword.do()`. The mode compiler automatically wires this up as a + * special _internal_ 'on:begin' callback for modes with `beginKeywords` + * @param {RegExpMatchArray} match + * @param {CallbackResponse} response + */ +function skipIfHasPrecedingDot(match, response) { + const before = match.input[match.index - 1]; + if (before === ".") { + response.ignoreMatch(); + } +} + +/** + * + * @type {CompilerExt} + */ +function scopeClassName(mode, _parent) { + // eslint-disable-next-line no-undefined + if (mode.className !== undefined) { + mode.scope = mode.className; + delete mode.className; + } +} + +/** + * `beginKeywords` syntactic sugar + * @type {CompilerExt} + */ +function beginKeywords(mode, parent) { + if (!parent) return; + if (!mode.beginKeywords) return; + + // for languages with keywords that include non-word characters checking for + // a word boundary is not sufficient, so instead we check for a word boundary + // or whitespace - this does no harm in any case since our keyword engine + // doesn't allow spaces in keywords anyways and we still check for the boundary + // first + mode.begin = '\\b(' + mode.beginKeywords.split(' ').join('|') + ')(?!\\.)(?=\\b|\\s)'; + mode.__beforeBegin = skipIfHasPrecedingDot; + mode.keywords = mode.keywords || mode.beginKeywords; + delete mode.beginKeywords; + + // prevents double relevance, the keywords themselves provide + // relevance, the mode doesn't need to double it + // eslint-disable-next-line no-undefined + if (mode.relevance === undefined) mode.relevance = 0; +} + +/** + * Allow `illegal` to contain an array of illegal values + * @type {CompilerExt} + */ +function compileIllegal(mode, _parent) { + if (!Array.isArray(mode.illegal)) return; + + mode.illegal = either(...mode.illegal); +} + +/** + * `match` to match a single expression for readability + * @type {CompilerExt} + */ +function compileMatch(mode, _parent) { + if (!mode.match) return; + if (mode.begin || mode.end) throw new Error("begin & end are not supported with match"); + + mode.begin = mode.match; + delete mode.match; +} + +/** + * provides the default 1 relevance to all modes + * @type {CompilerExt} + */ +function compileRelevance(mode, _parent) { + // eslint-disable-next-line no-undefined + if (mode.relevance === undefined) mode.relevance = 1; +} + +// allow beforeMatch to act as a "qualifier" for the match +// the full match begin must be [beforeMatch][begin] +const beforeMatchExt = (mode, parent) => { + if (!mode.beforeMatch) return; + // starts conflicts with endsParent which we need to make sure the child + // rule is not matched multiple times + if (mode.starts) throw new Error("beforeMatch cannot be used with starts"); + + const originalMode = Object.assign({}, mode); + Object.keys(mode).forEach((key) => { delete mode[key]; }); + + mode.keywords = originalMode.keywords; + mode.begin = concat(originalMode.beforeMatch, lookahead(originalMode.begin)); + mode.starts = { + relevance: 0, + contains: [ + Object.assign(originalMode, { endsParent: true }) + ] + }; + mode.relevance = 0; + + delete originalMode.beforeMatch; +}; + +// keywords that should have no default relevance value +const COMMON_KEYWORDS = [ + 'of', + 'and', + 'for', + 'in', + 'not', + 'or', + 'if', + 'then', + 'parent', // common variable name + 'list', // common variable name + 'value' // common variable name +]; + +const DEFAULT_KEYWORD_SCOPE = "keyword"; + +/** + * Given raw keywords from a language definition, compile them. + * + * @param {string | Record | Array} rawKeywords + * @param {boolean} caseInsensitive + */ +function compileKeywords(rawKeywords, caseInsensitive, scopeName = DEFAULT_KEYWORD_SCOPE) { + /** @type {import("highlight.js/private").KeywordDict} */ + const compiledKeywords = Object.create(null); + + // input can be a string of keywords, an array of keywords, or a object with + // named keys representing scopeName (which can then point to a string or array) + if (typeof rawKeywords === 'string') { + compileList(scopeName, rawKeywords.split(" ")); + } else if (Array.isArray(rawKeywords)) { + compileList(scopeName, rawKeywords); + } else { + Object.keys(rawKeywords).forEach(function(scopeName) { + // collapse all our objects back into the parent object + Object.assign( + compiledKeywords, + compileKeywords(rawKeywords[scopeName], caseInsensitive, scopeName) + ); + }); + } + return compiledKeywords; + + // --- + + /** + * Compiles an individual list of keywords + * + * Ex: "for if when while|5" + * + * @param {string} scopeName + * @param {Array} keywordList + */ + function compileList(scopeName, keywordList) { + if (caseInsensitive) { + keywordList = keywordList.map(x => x.toLowerCase()); + } + keywordList.forEach(function(keyword) { + const pair = keyword.split('|'); + compiledKeywords[pair[0]] = [scopeName, scoreForKeyword(pair[0], pair[1])]; + }); + } +} + +/** + * Returns the proper score for a given keyword + * + * Also takes into account comment keywords, which will be scored 0 UNLESS + * another score has been manually assigned. + * @param {string} keyword + * @param {string} [providedScore] + */ +function scoreForKeyword(keyword, providedScore) { + // manual scores always win over common keywords + // so you can force a score of 1 if you really insist + if (providedScore) { + return Number(providedScore); + } + + return commonKeyword(keyword) ? 0 : 1; +} + +/** + * Determines if a given keyword is common or not + * + * @param {string} keyword */ +function commonKeyword(keyword) { + return COMMON_KEYWORDS.includes(keyword.toLowerCase()); +} + +/* + +For the reasoning behind this please see: +https://github.com/highlightjs/highlight.js/issues/2880#issuecomment-747275419 + +*/ + +/** + * @type {Record} + */ +const seenDeprecations = {}; + +/** + * @param {string} message + */ +const error = (message) => { + console.error(message); +}; + +/** + * @param {string} message + * @param {any} args + */ +const warn = (message, ...args) => { + console.log(`WARN: ${message}`, ...args); +}; + +/** + * @param {string} version + * @param {string} message + */ +const deprecated = (version, message) => { + if (seenDeprecations[`${version}/${message}`]) return; + + console.log(`Deprecated as of ${version}. ${message}`); + seenDeprecations[`${version}/${message}`] = true; +}; + +/* eslint-disable no-throw-literal */ + +/** +@typedef {import('highlight.js').CompiledMode} CompiledMode +*/ + +const MultiClassError = new Error(); + +/** + * Renumbers labeled scope names to account for additional inner match + * groups that otherwise would break everything. + * + * Lets say we 3 match scopes: + * + * { 1 => ..., 2 => ..., 3 => ... } + * + * So what we need is a clean match like this: + * + * (a)(b)(c) => [ "a", "b", "c" ] + * + * But this falls apart with inner match groups: + * + * (a)(((b)))(c) => ["a", "b", "b", "b", "c" ] + * + * Our scopes are now "out of alignment" and we're repeating `b` 3 times. + * What needs to happen is the numbers are remapped: + * + * { 1 => ..., 2 => ..., 5 => ... } + * + * We also need to know that the ONLY groups that should be output + * are 1, 2, and 5. This function handles this behavior. + * + * @param {CompiledMode} mode + * @param {Array} regexes + * @param {{key: "beginScope"|"endScope"}} opts + */ +function remapScopeNames(mode, regexes, { key }) { + let offset = 0; + const scopeNames = mode[key]; + /** @type Record */ + const emit = {}; + /** @type Record */ + const positions = {}; + + for (let i = 1; i <= regexes.length; i++) { + positions[i + offset] = scopeNames[i]; + emit[i + offset] = true; + offset += countMatchGroups(regexes[i - 1]); + } + // we use _emit to keep track of which match groups are "top-level" to avoid double + // output from inside match groups + mode[key] = positions; + mode[key]._emit = emit; + mode[key]._multi = true; +} + +/** + * @param {CompiledMode} mode + */ +function beginMultiClass(mode) { + if (!Array.isArray(mode.begin)) return; + + if (mode.skip || mode.excludeBegin || mode.returnBegin) { + error("skip, excludeBegin, returnBegin not compatible with beginScope: {}"); + throw MultiClassError; + } + + if (typeof mode.beginScope !== "object" || mode.beginScope === null) { + error("beginScope must be object"); + throw MultiClassError; + } + + remapScopeNames(mode, mode.begin, { key: "beginScope" }); + mode.begin = _rewriteBackreferences(mode.begin, { joinWith: "" }); +} + +/** + * @param {CompiledMode} mode + */ +function endMultiClass(mode) { + if (!Array.isArray(mode.end)) return; + + if (mode.skip || mode.excludeEnd || mode.returnEnd) { + error("skip, excludeEnd, returnEnd not compatible with endScope: {}"); + throw MultiClassError; + } + + if (typeof mode.endScope !== "object" || mode.endScope === null) { + error("endScope must be object"); + throw MultiClassError; + } + + remapScopeNames(mode, mode.end, { key: "endScope" }); + mode.end = _rewriteBackreferences(mode.end, { joinWith: "" }); +} + +/** + * this exists only to allow `scope: {}` to be used beside `match:` + * Otherwise `beginScope` would necessary and that would look weird + + { + match: [ /def/, /\w+/ ] + scope: { 1: "keyword" , 2: "title" } + } + + * @param {CompiledMode} mode + */ +function scopeSugar(mode) { + if (mode.scope && typeof mode.scope === "object" && mode.scope !== null) { + mode.beginScope = mode.scope; + delete mode.scope; + } +} + +/** + * @param {CompiledMode} mode + */ +function MultiClass(mode) { + scopeSugar(mode); + + if (typeof mode.beginScope === "string") { + mode.beginScope = { _wrap: mode.beginScope }; + } + if (typeof mode.endScope === "string") { + mode.endScope = { _wrap: mode.endScope }; + } + + beginMultiClass(mode); + endMultiClass(mode); +} + +/** +@typedef {import('highlight.js').Mode} Mode +@typedef {import('highlight.js').CompiledMode} CompiledMode +@typedef {import('highlight.js').Language} Language +@typedef {import('highlight.js').HLJSPlugin} HLJSPlugin +@typedef {import('highlight.js').CompiledLanguage} CompiledLanguage +*/ + +// compilation + +/** + * Compiles a language definition result + * + * Given the raw result of a language definition (Language), compiles this so + * that it is ready for highlighting code. + * @param {Language} language + * @returns {CompiledLanguage} + */ +function compileLanguage(language) { + /** + * Builds a regex with the case sensitivity of the current language + * + * @param {RegExp | string} value + * @param {boolean} [global] + */ + function langRe(value, global) { + return new RegExp( + source(value), + 'm' + + (language.case_insensitive ? 'i' : '') + + (language.unicodeRegex ? 'u' : '') + + (global ? 'g' : '') + ); + } + + /** + Stores multiple regular expressions and allows you to quickly search for + them all in a string simultaneously - returning the first match. It does + this by creating a huge (a|b|c) regex - each individual item wrapped with () + and joined by `|` - using match groups to track position. When a match is + found checking which position in the array has content allows us to figure + out which of the original regexes / match groups triggered the match. + + The match object itself (the result of `Regex.exec`) is returned but also + enhanced by merging in any meta-data that was registered with the regex. + This is how we keep track of which mode matched, and what type of rule + (`illegal`, `begin`, end, etc). + */ + class MultiRegex { + constructor() { + this.matchIndexes = {}; + // @ts-ignore + this.regexes = []; + this.matchAt = 1; + this.position = 0; + } + + // @ts-ignore + addRule(re, opts) { + opts.position = this.position++; + // @ts-ignore + this.matchIndexes[this.matchAt] = opts; + this.regexes.push([opts, re]); + this.matchAt += countMatchGroups(re) + 1; + } + + compile() { + if (this.regexes.length === 0) { + // avoids the need to check length every time exec is called + // @ts-ignore + this.exec = () => null; + } + const terminators = this.regexes.map(el => el[1]); + this.matcherRe = langRe(_rewriteBackreferences(terminators, { joinWith: '|' }), true); + this.lastIndex = 0; + } + + /** @param {string} s */ + exec(s) { + this.matcherRe.lastIndex = this.lastIndex; + const match = this.matcherRe.exec(s); + if (!match) { return null; } + + // eslint-disable-next-line no-undefined + const i = match.findIndex((el, i) => i > 0 && el !== undefined); + // @ts-ignore + const matchData = this.matchIndexes[i]; + // trim off any earlier non-relevant match groups (ie, the other regex + // match groups that make up the multi-matcher) + match.splice(0, i); + + return Object.assign(match, matchData); + } + } + + /* + Created to solve the key deficiently with MultiRegex - there is no way to + test for multiple matches at a single location. Why would we need to do + that? In the future a more dynamic engine will allow certain matches to be + ignored. An example: if we matched say the 3rd regex in a large group but + decided to ignore it - we'd need to started testing again at the 4th + regex... but MultiRegex itself gives us no real way to do that. + + So what this class creates MultiRegexs on the fly for whatever search + position they are needed. + + NOTE: These additional MultiRegex objects are created dynamically. For most + grammars most of the time we will never actually need anything more than the + first MultiRegex - so this shouldn't have too much overhead. + + Say this is our search group, and we match regex3, but wish to ignore it. + + regex1 | regex2 | regex3 | regex4 | regex5 ' ie, startAt = 0 + + What we need is a new MultiRegex that only includes the remaining + possibilities: + + regex4 | regex5 ' ie, startAt = 3 + + This class wraps all that complexity up in a simple API... `startAt` decides + where in the array of expressions to start doing the matching. It + auto-increments, so if a match is found at position 2, then startAt will be + set to 3. If the end is reached startAt will return to 0. + + MOST of the time the parser will be setting startAt manually to 0. + */ + class ResumableMultiRegex { + constructor() { + // @ts-ignore + this.rules = []; + // @ts-ignore + this.multiRegexes = []; + this.count = 0; + + this.lastIndex = 0; + this.regexIndex = 0; + } + + // @ts-ignore + getMatcher(index) { + if (this.multiRegexes[index]) return this.multiRegexes[index]; + + const matcher = new MultiRegex(); + this.rules.slice(index).forEach(([re, opts]) => matcher.addRule(re, opts)); + matcher.compile(); + this.multiRegexes[index] = matcher; + return matcher; + } + + resumingScanAtSamePosition() { + return this.regexIndex !== 0; + } + + considerAll() { + this.regexIndex = 0; + } + + // @ts-ignore + addRule(re, opts) { + this.rules.push([re, opts]); + if (opts.type === "begin") this.count++; + } + + /** @param {string} s */ + exec(s) { + const m = this.getMatcher(this.regexIndex); + m.lastIndex = this.lastIndex; + let result = m.exec(s); + + // The following is because we have no easy way to say "resume scanning at the + // existing position but also skip the current rule ONLY". What happens is + // all prior rules are also skipped which can result in matching the wrong + // thing. Example of matching "booger": + + // our matcher is [string, "booger", number] + // + // ....booger.... + + // if "booger" is ignored then we'd really need a regex to scan from the + // SAME position for only: [string, number] but ignoring "booger" (if it + // was the first match), a simple resume would scan ahead who knows how + // far looking only for "number", ignoring potential string matches (or + // future "booger" matches that might be valid.) + + // So what we do: We execute two matchers, one resuming at the same + // position, but the second full matcher starting at the position after: + + // /--- resume first regex match here (for [number]) + // |/---- full match here for [string, "booger", number] + // vv + // ....booger.... + + // Which ever results in a match first is then used. So this 3-4 step + // process essentially allows us to say "match at this position, excluding + // a prior rule that was ignored". + // + // 1. Match "booger" first, ignore. Also proves that [string] does non match. + // 2. Resume matching for [number] + // 3. Match at index + 1 for [string, "booger", number] + // 4. If #2 and #3 result in matches, which came first? + if (this.resumingScanAtSamePosition()) { + if (result && result.index === this.lastIndex) ; else { // use the second matcher result + const m2 = this.getMatcher(0); + m2.lastIndex = this.lastIndex + 1; + result = m2.exec(s); + } + } + + if (result) { + this.regexIndex += result.position + 1; + if (this.regexIndex === this.count) { + // wrap-around to considering all matches again + this.considerAll(); + } + } + + return result; + } + } + + /** + * Given a mode, builds a huge ResumableMultiRegex that can be used to walk + * the content and find matches. + * + * @param {CompiledMode} mode + * @returns {ResumableMultiRegex} + */ + function buildModeRegex(mode) { + const mm = new ResumableMultiRegex(); + + mode.contains.forEach(term => mm.addRule(term.begin, { rule: term, type: "begin" })); + + if (mode.terminatorEnd) { + mm.addRule(mode.terminatorEnd, { type: "end" }); + } + if (mode.illegal) { + mm.addRule(mode.illegal, { type: "illegal" }); + } + + return mm; + } + + /** skip vs abort vs ignore + * + * @skip - The mode is still entered and exited normally (and contains rules apply), + * but all content is held and added to the parent buffer rather than being + * output when the mode ends. Mostly used with `sublanguage` to build up + * a single large buffer than can be parsed by sublanguage. + * + * - The mode begin ands ends normally. + * - Content matched is added to the parent mode buffer. + * - The parser cursor is moved forward normally. + * + * @abort - A hack placeholder until we have ignore. Aborts the mode (as if it + * never matched) but DOES NOT continue to match subsequent `contains` + * modes. Abort is bad/suboptimal because it can result in modes + * farther down not getting applied because an earlier rule eats the + * content but then aborts. + * + * - The mode does not begin. + * - Content matched by `begin` is added to the mode buffer. + * - The parser cursor is moved forward accordingly. + * + * @ignore - Ignores the mode (as if it never matched) and continues to match any + * subsequent `contains` modes. Ignore isn't technically possible with + * the current parser implementation. + * + * - The mode does not begin. + * - Content matched by `begin` is ignored. + * - The parser cursor is not moved forward. + */ + + /** + * Compiles an individual mode + * + * This can raise an error if the mode contains certain detectable known logic + * issues. + * @param {Mode} mode + * @param {CompiledMode | null} [parent] + * @returns {CompiledMode | never} + */ + function compileMode(mode, parent) { + const cmode = /** @type CompiledMode */ (mode); + if (mode.isCompiled) return cmode; + + [ + scopeClassName, + // do this early so compiler extensions generally don't have to worry about + // the distinction between match/begin + compileMatch, + MultiClass, + beforeMatchExt + ].forEach(ext => ext(mode, parent)); + + language.compilerExtensions.forEach(ext => ext(mode, parent)); + + // __beforeBegin is considered private API, internal use only + mode.__beforeBegin = null; + + [ + beginKeywords, + // do this later so compiler extensions that come earlier have access to the + // raw array if they wanted to perhaps manipulate it, etc. + compileIllegal, + // default to 1 relevance if not specified + compileRelevance + ].forEach(ext => ext(mode, parent)); + + mode.isCompiled = true; + + let keywordPattern = null; + if (typeof mode.keywords === "object" && mode.keywords.$pattern) { + // we need a copy because keywords might be compiled multiple times + // so we can't go deleting $pattern from the original on the first + // pass + mode.keywords = Object.assign({}, mode.keywords); + keywordPattern = mode.keywords.$pattern; + delete mode.keywords.$pattern; + } + keywordPattern = keywordPattern || /\w+/; + + if (mode.keywords) { + mode.keywords = compileKeywords(mode.keywords, language.case_insensitive); + } + + cmode.keywordPatternRe = langRe(keywordPattern, true); + + if (parent) { + if (!mode.begin) mode.begin = /\B|\b/; + cmode.beginRe = langRe(cmode.begin); + if (!mode.end && !mode.endsWithParent) mode.end = /\B|\b/; + if (mode.end) cmode.endRe = langRe(cmode.end); + cmode.terminatorEnd = source(cmode.end) || ''; + if (mode.endsWithParent && parent.terminatorEnd) { + cmode.terminatorEnd += (mode.end ? '|' : '') + parent.terminatorEnd; + } + } + if (mode.illegal) cmode.illegalRe = langRe(/** @type {RegExp | string} */ (mode.illegal)); + if (!mode.contains) mode.contains = []; + + mode.contains = [].concat(...mode.contains.map(function(c) { + return expandOrCloneMode(c === 'self' ? mode : c); + })); + mode.contains.forEach(function(c) { compileMode(/** @type Mode */ (c), cmode); }); + + if (mode.starts) { + compileMode(mode.starts, parent); + } + + cmode.matcher = buildModeRegex(cmode); + return cmode; + } + + if (!language.compilerExtensions) language.compilerExtensions = []; + + // self is not valid at the top-level + if (language.contains && language.contains.includes('self')) { + throw new Error("ERR: contains `self` is not supported at the top-level of a language. See documentation."); + } + + // we need a null object, which inherit will guarantee + language.classNameAliases = inherit$1(language.classNameAliases || {}); + + return compileMode(/** @type Mode */ (language)); +} + +/** + * Determines if a mode has a dependency on it's parent or not + * + * If a mode does have a parent dependency then often we need to clone it if + * it's used in multiple places so that each copy points to the correct parent, + * where-as modes without a parent can often safely be re-used at the bottom of + * a mode chain. + * + * @param {Mode | null} mode + * @returns {boolean} - is there a dependency on the parent? + * */ +function dependencyOnParent(mode) { + if (!mode) return false; + + return mode.endsWithParent || dependencyOnParent(mode.starts); +} + +/** + * Expands a mode or clones it if necessary + * + * This is necessary for modes with parental dependenceis (see notes on + * `dependencyOnParent`) and for nodes that have `variants` - which must then be + * exploded into their own individual modes at compile time. + * + * @param {Mode} mode + * @returns {Mode | Mode[]} + * */ +function expandOrCloneMode(mode) { + if (mode.variants && !mode.cachedVariants) { + mode.cachedVariants = mode.variants.map(function(variant) { + return inherit$1(mode, { variants: null }, variant); + }); + } + + // EXPAND + // if we have variants then essentially "replace" the mode with the variants + // this happens in compileMode, where this function is called from + if (mode.cachedVariants) { + return mode.cachedVariants; + } + + // CLONE + // if we have dependencies on parents then we need a unique + // instance of ourselves, so we can be reused with many + // different parents without issue + if (dependencyOnParent(mode)) { + return inherit$1(mode, { starts: mode.starts ? inherit$1(mode.starts) : null }); + } + + if (Object.isFrozen(mode)) { + return inherit$1(mode); + } + + // no special dependency issues, just return ourselves + return mode; +} + +var version = "11.9.0"; + +class HTMLInjectionError extends Error { + constructor(reason, html) { + super(reason); + this.name = "HTMLInjectionError"; + this.html = html; + } +} + +/* +Syntax highlighting with language autodetection. +https://highlightjs.org/ +*/ + + + +/** +@typedef {import('highlight.js').Mode} Mode +@typedef {import('highlight.js').CompiledMode} CompiledMode +@typedef {import('highlight.js').CompiledScope} CompiledScope +@typedef {import('highlight.js').Language} Language +@typedef {import('highlight.js').HLJSApi} HLJSApi +@typedef {import('highlight.js').HLJSPlugin} HLJSPlugin +@typedef {import('highlight.js').PluginEvent} PluginEvent +@typedef {import('highlight.js').HLJSOptions} HLJSOptions +@typedef {import('highlight.js').LanguageFn} LanguageFn +@typedef {import('highlight.js').HighlightedHTMLElement} HighlightedHTMLElement +@typedef {import('highlight.js').BeforeHighlightContext} BeforeHighlightContext +@typedef {import('highlight.js/private').MatchType} MatchType +@typedef {import('highlight.js/private').KeywordData} KeywordData +@typedef {import('highlight.js/private').EnhancedMatch} EnhancedMatch +@typedef {import('highlight.js/private').AnnotatedError} AnnotatedError +@typedef {import('highlight.js').AutoHighlightResult} AutoHighlightResult +@typedef {import('highlight.js').HighlightOptions} HighlightOptions +@typedef {import('highlight.js').HighlightResult} HighlightResult +*/ + + +const escape = escapeHTML; +const inherit = inherit$1; +const NO_MATCH = Symbol("nomatch"); +const MAX_KEYWORD_HITS = 7; + +/** + * @param {any} hljs - object that is extended (legacy) + * @returns {HLJSApi} + */ +const HLJS = function(hljs) { + // Global internal variables used within the highlight.js library. + /** @type {Record} */ + const languages = Object.create(null); + /** @type {Record} */ + const aliases = Object.create(null); + /** @type {HLJSPlugin[]} */ + const plugins = []; + + // safe/production mode - swallows more errors, tries to keep running + // even if a single syntax or parse hits a fatal error + let SAFE_MODE = true; + const LANGUAGE_NOT_FOUND = "Could not find the language '{}', did you forget to load/include a language module?"; + /** @type {Language} */ + const PLAINTEXT_LANGUAGE = { disableAutodetect: true, name: 'Plain text', contains: [] }; + + // Global options used when within external APIs. This is modified when + // calling the `hljs.configure` function. + /** @type HLJSOptions */ + let options = { + ignoreUnescapedHTML: false, + throwUnescapedHTML: false, + noHighlightRe: /^(no-?highlight)$/i, + languageDetectRe: /\blang(?:uage)?-([\w-]+)\b/i, + classPrefix: 'hljs-', + cssSelector: 'pre code', + languages: null, + // beta configuration options, subject to change, welcome to discuss + // https://github.com/highlightjs/highlight.js/issues/1086 + __emitter: TokenTreeEmitter + }; + + /* Utility functions */ + + /** + * Tests a language name to see if highlighting should be skipped + * @param {string} languageName + */ + function shouldNotHighlight(languageName) { + return options.noHighlightRe.test(languageName); + } + + /** + * @param {HighlightedHTMLElement} block - the HTML element to determine language for + */ + function blockLanguage(block) { + let classes = block.className + ' '; + + classes += block.parentNode ? block.parentNode.className : ''; + + // language-* takes precedence over non-prefixed class names. + const match = options.languageDetectRe.exec(classes); + if (match) { + const language = getLanguage(match[1]); + if (!language) { + warn(LANGUAGE_NOT_FOUND.replace("{}", match[1])); + warn("Falling back to no-highlight mode for this block.", block); + } + return language ? match[1] : 'no-highlight'; + } + + return classes + .split(/\s+/) + .find((_class) => shouldNotHighlight(_class) || getLanguage(_class)); + } + + /** + * Core highlighting function. + * + * OLD API + * highlight(lang, code, ignoreIllegals, continuation) + * + * NEW API + * highlight(code, {lang, ignoreIllegals}) + * + * @param {string} codeOrLanguageName - the language to use for highlighting + * @param {string | HighlightOptions} optionsOrCode - the code to highlight + * @param {boolean} [ignoreIllegals] - whether to ignore illegal matches, default is to bail + * + * @returns {HighlightResult} Result - an object that represents the result + * @property {string} language - the language name + * @property {number} relevance - the relevance score + * @property {string} value - the highlighted HTML code + * @property {string} code - the original raw code + * @property {CompiledMode} top - top of the current mode stack + * @property {boolean} illegal - indicates whether any illegal matches were found + */ + function highlight(codeOrLanguageName, optionsOrCode, ignoreIllegals) { + let code = ""; + let languageName = ""; + if (typeof optionsOrCode === "object") { + code = codeOrLanguageName; + ignoreIllegals = optionsOrCode.ignoreIllegals; + languageName = optionsOrCode.language; + } else { + // old API + deprecated("10.7.0", "highlight(lang, code, ...args) has been deprecated."); + deprecated("10.7.0", "Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"); + languageName = codeOrLanguageName; + code = optionsOrCode; + } + + // https://github.com/highlightjs/highlight.js/issues/3149 + // eslint-disable-next-line no-undefined + if (ignoreIllegals === undefined) { ignoreIllegals = true; } + + /** @type {BeforeHighlightContext} */ + const context = { + code, + language: languageName + }; + // the plugin can change the desired language or the code to be highlighted + // just be changing the object it was passed + fire("before:highlight", context); + + // a before plugin can usurp the result completely by providing it's own + // in which case we don't even need to call highlight + const result = context.result + ? context.result + : _highlight(context.language, context.code, ignoreIllegals); + + result.code = context.code; + // the plugin can change anything in result to suite it + fire("after:highlight", result); + + return result; + } + + /** + * private highlight that's used internally and does not fire callbacks + * + * @param {string} languageName - the language to use for highlighting + * @param {string} codeToHighlight - the code to highlight + * @param {boolean?} [ignoreIllegals] - whether to ignore illegal matches, default is to bail + * @param {CompiledMode?} [continuation] - current continuation mode, if any + * @returns {HighlightResult} - result of the highlight operation + */ + function _highlight(languageName, codeToHighlight, ignoreIllegals, continuation) { + const keywordHits = Object.create(null); + + /** + * Return keyword data if a match is a keyword + * @param {CompiledMode} mode - current mode + * @param {string} matchText - the textual match + * @returns {KeywordData | false} + */ + function keywordData(mode, matchText) { + return mode.keywords[matchText]; + } + + function processKeywords() { + if (!top.keywords) { + emitter.addText(modeBuffer); + return; + } + + let lastIndex = 0; + top.keywordPatternRe.lastIndex = 0; + let match = top.keywordPatternRe.exec(modeBuffer); + let buf = ""; + + while (match) { + buf += modeBuffer.substring(lastIndex, match.index); + const word = language.case_insensitive ? match[0].toLowerCase() : match[0]; + const data = keywordData(top, word); + if (data) { + const [kind, keywordRelevance] = data; + emitter.addText(buf); + buf = ""; + + keywordHits[word] = (keywordHits[word] || 0) + 1; + if (keywordHits[word] <= MAX_KEYWORD_HITS) relevance += keywordRelevance; + if (kind.startsWith("_")) { + // _ implied for relevance only, do not highlight + // by applying a class name + buf += match[0]; + } else { + const cssClass = language.classNameAliases[kind] || kind; + emitKeyword(match[0], cssClass); + } + } else { + buf += match[0]; + } + lastIndex = top.keywordPatternRe.lastIndex; + match = top.keywordPatternRe.exec(modeBuffer); + } + buf += modeBuffer.substring(lastIndex); + emitter.addText(buf); + } + + function processSubLanguage() { + if (modeBuffer === "") return; + /** @type HighlightResult */ + let result = null; + + if (typeof top.subLanguage === 'string') { + if (!languages[top.subLanguage]) { + emitter.addText(modeBuffer); + return; + } + result = _highlight(top.subLanguage, modeBuffer, true, continuations[top.subLanguage]); + continuations[top.subLanguage] = /** @type {CompiledMode} */ (result._top); + } else { + result = highlightAuto(modeBuffer, top.subLanguage.length ? top.subLanguage : null); + } + + // Counting embedded language score towards the host language may be disabled + // with zeroing the containing mode relevance. Use case in point is Markdown that + // allows XML everywhere and makes every XML snippet to have a much larger Markdown + // score. + if (top.relevance > 0) { + relevance += result.relevance; + } + emitter.__addSublanguage(result._emitter, result.language); + } + + function processBuffer() { + if (top.subLanguage != null) { + processSubLanguage(); + } else { + processKeywords(); + } + modeBuffer = ''; + } + + /** + * @param {string} text + * @param {string} scope + */ + function emitKeyword(keyword, scope) { + if (keyword === "") return; + + emitter.startScope(scope); + emitter.addText(keyword); + emitter.endScope(); + } + + /** + * @param {CompiledScope} scope + * @param {RegExpMatchArray} match + */ + function emitMultiClass(scope, match) { + let i = 1; + const max = match.length - 1; + while (i <= max) { + if (!scope._emit[i]) { i++; continue; } + const klass = language.classNameAliases[scope[i]] || scope[i]; + const text = match[i]; + if (klass) { + emitKeyword(text, klass); + } else { + modeBuffer = text; + processKeywords(); + modeBuffer = ""; + } + i++; + } + } + + /** + * @param {CompiledMode} mode - new mode to start + * @param {RegExpMatchArray} match + */ + function startNewMode(mode, match) { + if (mode.scope && typeof mode.scope === "string") { + emitter.openNode(language.classNameAliases[mode.scope] || mode.scope); + } + if (mode.beginScope) { + // beginScope just wraps the begin match itself in a scope + if (mode.beginScope._wrap) { + emitKeyword(modeBuffer, language.classNameAliases[mode.beginScope._wrap] || mode.beginScope._wrap); + modeBuffer = ""; + } else if (mode.beginScope._multi) { + // at this point modeBuffer should just be the match + emitMultiClass(mode.beginScope, match); + modeBuffer = ""; + } + } + + top = Object.create(mode, { parent: { value: top } }); + return top; + } + + /** + * @param {CompiledMode } mode - the mode to potentially end + * @param {RegExpMatchArray} match - the latest match + * @param {string} matchPlusRemainder - match plus remainder of content + * @returns {CompiledMode | void} - the next mode, or if void continue on in current mode + */ + function endOfMode(mode, match, matchPlusRemainder) { + let matched = startsWith(mode.endRe, matchPlusRemainder); + + if (matched) { + if (mode["on:end"]) { + const resp = new Response(mode); + mode["on:end"](match, resp); + if (resp.isMatchIgnored) matched = false; + } + + if (matched) { + while (mode.endsParent && mode.parent) { + mode = mode.parent; + } + return mode; + } + } + // even if on:end fires an `ignore` it's still possible + // that we might trigger the end node because of a parent mode + if (mode.endsWithParent) { + return endOfMode(mode.parent, match, matchPlusRemainder); + } + } + + /** + * Handle matching but then ignoring a sequence of text + * + * @param {string} lexeme - string containing full match text + */ + function doIgnore(lexeme) { + if (top.matcher.regexIndex === 0) { + // no more regexes to potentially match here, so we move the cursor forward one + // space + modeBuffer += lexeme[0]; + return 1; + } else { + // no need to move the cursor, we still have additional regexes to try and + // match at this very spot + resumeScanAtSamePosition = true; + return 0; + } + } + + /** + * Handle the start of a new potential mode match + * + * @param {EnhancedMatch} match - the current match + * @returns {number} how far to advance the parse cursor + */ + function doBeginMatch(match) { + const lexeme = match[0]; + const newMode = match.rule; + + const resp = new Response(newMode); + // first internal before callbacks, then the public ones + const beforeCallbacks = [newMode.__beforeBegin, newMode["on:begin"]]; + for (const cb of beforeCallbacks) { + if (!cb) continue; + cb(match, resp); + if (resp.isMatchIgnored) return doIgnore(lexeme); + } + + if (newMode.skip) { + modeBuffer += lexeme; + } else { + if (newMode.excludeBegin) { + modeBuffer += lexeme; + } + processBuffer(); + if (!newMode.returnBegin && !newMode.excludeBegin) { + modeBuffer = lexeme; + } + } + startNewMode(newMode, match); + return newMode.returnBegin ? 0 : lexeme.length; + } + + /** + * Handle the potential end of mode + * + * @param {RegExpMatchArray} match - the current match + */ + function doEndMatch(match) { + const lexeme = match[0]; + const matchPlusRemainder = codeToHighlight.substring(match.index); + + const endMode = endOfMode(top, match, matchPlusRemainder); + if (!endMode) { return NO_MATCH; } + + const origin = top; + if (top.endScope && top.endScope._wrap) { + processBuffer(); + emitKeyword(lexeme, top.endScope._wrap); + } else if (top.endScope && top.endScope._multi) { + processBuffer(); + emitMultiClass(top.endScope, match); + } else if (origin.skip) { + modeBuffer += lexeme; + } else { + if (!(origin.returnEnd || origin.excludeEnd)) { + modeBuffer += lexeme; + } + processBuffer(); + if (origin.excludeEnd) { + modeBuffer = lexeme; + } + } + do { + if (top.scope) { + emitter.closeNode(); + } + if (!top.skip && !top.subLanguage) { + relevance += top.relevance; + } + top = top.parent; + } while (top !== endMode.parent); + if (endMode.starts) { + startNewMode(endMode.starts, match); + } + return origin.returnEnd ? 0 : lexeme.length; + } + + function processContinuations() { + const list = []; + for (let current = top; current !== language; current = current.parent) { + if (current.scope) { + list.unshift(current.scope); + } + } + list.forEach(item => emitter.openNode(item)); + } + + /** @type {{type?: MatchType, index?: number, rule?: Mode}}} */ + let lastMatch = {}; + + /** + * Process an individual match + * + * @param {string} textBeforeMatch - text preceding the match (since the last match) + * @param {EnhancedMatch} [match] - the match itself + */ + function processLexeme(textBeforeMatch, match) { + const lexeme = match && match[0]; + + // add non-matched text to the current mode buffer + modeBuffer += textBeforeMatch; + + if (lexeme == null) { + processBuffer(); + return 0; + } + + // we've found a 0 width match and we're stuck, so we need to advance + // this happens when we have badly behaved rules that have optional matchers to the degree that + // sometimes they can end up matching nothing at all + // Ref: https://github.com/highlightjs/highlight.js/issues/2140 + if (lastMatch.type === "begin" && match.type === "end" && lastMatch.index === match.index && lexeme === "") { + // spit the "skipped" character that our regex choked on back into the output sequence + modeBuffer += codeToHighlight.slice(match.index, match.index + 1); + if (!SAFE_MODE) { + /** @type {AnnotatedError} */ + const err = new Error(`0 width match regex (${languageName})`); + err.languageName = languageName; + err.badRule = lastMatch.rule; + throw err; + } + return 1; + } + lastMatch = match; + + if (match.type === "begin") { + return doBeginMatch(match); + } else if (match.type === "illegal" && !ignoreIllegals) { + // illegal match, we do not continue processing + /** @type {AnnotatedError} */ + const err = new Error('Illegal lexeme "' + lexeme + '" for mode "' + (top.scope || '') + '"'); + err.mode = top; + throw err; + } else if (match.type === "end") { + const processed = doEndMatch(match); + if (processed !== NO_MATCH) { + return processed; + } + } + + // edge case for when illegal matches $ (end of line) which is technically + // a 0 width match but not a begin/end match so it's not caught by the + // first handler (when ignoreIllegals is true) + if (match.type === "illegal" && lexeme === "") { + // advance so we aren't stuck in an infinite loop + return 1; + } + + // infinite loops are BAD, this is a last ditch catch all. if we have a + // decent number of iterations yet our index (cursor position in our + // parsing) still 3x behind our index then something is very wrong + // so we bail + if (iterations > 100000 && iterations > match.index * 3) { + const err = new Error('potential infinite loop, way more iterations than matches'); + throw err; + } + + /* + Why might be find ourselves here? An potential end match that was + triggered but could not be completed. IE, `doEndMatch` returned NO_MATCH. + (this could be because a callback requests the match be ignored, etc) + + This causes no real harm other than stopping a few times too many. + */ + + modeBuffer += lexeme; + return lexeme.length; + } + + const language = getLanguage(languageName); + if (!language) { + error(LANGUAGE_NOT_FOUND.replace("{}", languageName)); + throw new Error('Unknown language: "' + languageName + '"'); + } + + const md = compileLanguage(language); + let result = ''; + /** @type {CompiledMode} */ + let top = continuation || md; + /** @type Record */ + const continuations = {}; // keep continuations for sub-languages + const emitter = new options.__emitter(options); + processContinuations(); + let modeBuffer = ''; + let relevance = 0; + let index = 0; + let iterations = 0; + let resumeScanAtSamePosition = false; + + try { + if (!language.__emitTokens) { + top.matcher.considerAll(); + + for (;;) { + iterations++; + if (resumeScanAtSamePosition) { + // only regexes not matched previously will now be + // considered for a potential match + resumeScanAtSamePosition = false; + } else { + top.matcher.considerAll(); + } + top.matcher.lastIndex = index; + + const match = top.matcher.exec(codeToHighlight); + // console.log("match", match[0], match.rule && match.rule.begin) + + if (!match) break; + + const beforeMatch = codeToHighlight.substring(index, match.index); + const processedCount = processLexeme(beforeMatch, match); + index = match.index + processedCount; + } + processLexeme(codeToHighlight.substring(index)); + } else { + language.__emitTokens(codeToHighlight, emitter); + } + + emitter.finalize(); + result = emitter.toHTML(); + + return { + language: languageName, + value: result, + relevance, + illegal: false, + _emitter: emitter, + _top: top + }; + } catch (err) { + if (err.message && err.message.includes('Illegal')) { + return { + language: languageName, + value: escape(codeToHighlight), + illegal: true, + relevance: 0, + _illegalBy: { + message: err.message, + index, + context: codeToHighlight.slice(index - 100, index + 100), + mode: err.mode, + resultSoFar: result + }, + _emitter: emitter + }; + } else if (SAFE_MODE) { + return { + language: languageName, + value: escape(codeToHighlight), + illegal: false, + relevance: 0, + errorRaised: err, + _emitter: emitter, + _top: top + }; + } else { + throw err; + } + } + } + + /** + * returns a valid highlight result, without actually doing any actual work, + * auto highlight starts with this and it's possible for small snippets that + * auto-detection may not find a better match + * @param {string} code + * @returns {HighlightResult} + */ + function justTextHighlightResult(code) { + const result = { + value: escape(code), + illegal: false, + relevance: 0, + _top: PLAINTEXT_LANGUAGE, + _emitter: new options.__emitter(options) + }; + result._emitter.addText(code); + return result; + } + + /** + Highlighting with language detection. Accepts a string with the code to + highlight. Returns an object with the following properties: + + - language (detected language) + - relevance (int) + - value (an HTML string with highlighting markup) + - secondBest (object with the same structure for second-best heuristically + detected language, may be absent) + + @param {string} code + @param {Array} [languageSubset] + @returns {AutoHighlightResult} + */ + function highlightAuto(code, languageSubset) { + languageSubset = languageSubset || options.languages || Object.keys(languages); + const plaintext = justTextHighlightResult(code); + + const results = languageSubset.filter(getLanguage).filter(autoDetection).map(name => + _highlight(name, code, false) + ); + results.unshift(plaintext); // plaintext is always an option + + const sorted = results.sort((a, b) => { + // sort base on relevance + if (a.relevance !== b.relevance) return b.relevance - a.relevance; + + // always award the tie to the base language + // ie if C++ and Arduino are tied, it's more likely to be C++ + if (a.language && b.language) { + if (getLanguage(a.language).supersetOf === b.language) { + return 1; + } else if (getLanguage(b.language).supersetOf === a.language) { + return -1; + } + } + + // otherwise say they are equal, which has the effect of sorting on + // relevance while preserving the original ordering - which is how ties + // have historically been settled, ie the language that comes first always + // wins in the case of a tie + return 0; + }); + + const [best, secondBest] = sorted; + + /** @type {AutoHighlightResult} */ + const result = best; + result.secondBest = secondBest; + + return result; + } + + /** + * Builds new class name for block given the language name + * + * @param {HTMLElement} element + * @param {string} [currentLang] + * @param {string} [resultLang] + */ + function updateClassName(element, currentLang, resultLang) { + const language = (currentLang && aliases[currentLang]) || resultLang; + + element.classList.add("hljs"); + element.classList.add(`language-${language}`); + } + + /** + * Applies highlighting to a DOM node containing code. + * + * @param {HighlightedHTMLElement} element - the HTML element to highlight + */ + function highlightElement(element) { + /** @type HTMLElement */ + let node = null; + const language = blockLanguage(element); + + if (shouldNotHighlight(language)) return; + + fire("before:highlightElement", + { el: element, language }); + + if (element.dataset.highlighted) { + console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.", element); + return; + } + + // we should be all text, no child nodes (unescaped HTML) - this is possibly + // an HTML injection attack - it's likely too late if this is already in + // production (the code has likely already done its damage by the time + // we're seeing it)... but we yell loudly about this so that hopefully it's + // more likely to be caught in development before making it to production + if (element.children.length > 0) { + if (!options.ignoreUnescapedHTML) { + console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."); + console.warn("https://github.com/highlightjs/highlight.js/wiki/security"); + console.warn("The element with unescaped HTML:"); + console.warn(element); + } + if (options.throwUnescapedHTML) { + const err = new HTMLInjectionError( + "One of your code blocks includes unescaped HTML.", + element.innerHTML + ); + throw err; + } + } + + node = element; + const text = node.textContent; + const result = language ? highlight(text, { language, ignoreIllegals: true }) : highlightAuto(text); + + element.innerHTML = result.value; + element.dataset.highlighted = "yes"; + updateClassName(element, language, result.language); + element.result = { + language: result.language, + // TODO: remove with version 11.0 + re: result.relevance, + relevance: result.relevance + }; + if (result.secondBest) { + element.secondBest = { + language: result.secondBest.language, + relevance: result.secondBest.relevance + }; + } + + fire("after:highlightElement", { el: element, result, text }); + } + + /** + * Updates highlight.js global options with the passed options + * + * @param {Partial} userOptions + */ + function configure(userOptions) { + options = inherit(options, userOptions); + } + + // TODO: remove v12, deprecated + const initHighlighting = () => { + highlightAll(); + deprecated("10.6.0", "initHighlighting() deprecated. Use highlightAll() now."); + }; + + // TODO: remove v12, deprecated + function initHighlightingOnLoad() { + highlightAll(); + deprecated("10.6.0", "initHighlightingOnLoad() deprecated. Use highlightAll() now."); + } + + let wantsHighlight = false; + + /** + * auto-highlights all pre>code elements on the page + */ + function highlightAll() { + // if we are called too early in the loading process + if (document.readyState === "loading") { + wantsHighlight = true; + return; + } + + const blocks = document.querySelectorAll(options.cssSelector); + blocks.forEach(highlightElement); + } + + function boot() { + // if a highlight was requested before DOM was loaded, do now + if (wantsHighlight) highlightAll(); + } + + // make sure we are in the browser environment + if (typeof window !== 'undefined' && window.addEventListener) { + window.addEventListener('DOMContentLoaded', boot, false); + } + + /** + * Register a language grammar module + * + * @param {string} languageName + * @param {LanguageFn} languageDefinition + */ + function registerLanguage(languageName, languageDefinition) { + let lang = null; + try { + lang = languageDefinition(hljs); + } catch (error$1) { + error("Language definition for '{}' could not be registered.".replace("{}", languageName)); + // hard or soft error + if (!SAFE_MODE) { throw error$1; } else { error(error$1); } + // languages that have serious errors are replaced with essentially a + // "plaintext" stand-in so that the code blocks will still get normal + // css classes applied to them - and one bad language won't break the + // entire highlighter + lang = PLAINTEXT_LANGUAGE; + } + // give it a temporary name if it doesn't have one in the meta-data + if (!lang.name) lang.name = languageName; + languages[languageName] = lang; + lang.rawDefinition = languageDefinition.bind(null, hljs); + + if (lang.aliases) { + registerAliases(lang.aliases, { languageName }); + } + } + + /** + * Remove a language grammar module + * + * @param {string} languageName + */ + function unregisterLanguage(languageName) { + delete languages[languageName]; + for (const alias of Object.keys(aliases)) { + if (aliases[alias] === languageName) { + delete aliases[alias]; + } + } + } + + /** + * @returns {string[]} List of language internal names + */ + function listLanguages() { + return Object.keys(languages); + } + + /** + * @param {string} name - name of the language to retrieve + * @returns {Language | undefined} + */ + function getLanguage(name) { + name = (name || '').toLowerCase(); + return languages[name] || languages[aliases[name]]; + } + + /** + * + * @param {string|string[]} aliasList - single alias or list of aliases + * @param {{languageName: string}} opts + */ + function registerAliases(aliasList, { languageName }) { + if (typeof aliasList === 'string') { + aliasList = [aliasList]; + } + aliasList.forEach(alias => { aliases[alias.toLowerCase()] = languageName; }); + } + + /** + * Determines if a given language has auto-detection enabled + * @param {string} name - name of the language + */ + function autoDetection(name) { + const lang = getLanguage(name); + return lang && !lang.disableAutodetect; + } + + /** + * Upgrades the old highlightBlock plugins to the new + * highlightElement API + * @param {HLJSPlugin} plugin + */ + function upgradePluginAPI(plugin) { + // TODO: remove with v12 + if (plugin["before:highlightBlock"] && !plugin["before:highlightElement"]) { + plugin["before:highlightElement"] = (data) => { + plugin["before:highlightBlock"]( + Object.assign({ block: data.el }, data) + ); + }; + } + if (plugin["after:highlightBlock"] && !plugin["after:highlightElement"]) { + plugin["after:highlightElement"] = (data) => { + plugin["after:highlightBlock"]( + Object.assign({ block: data.el }, data) + ); + }; + } + } + + /** + * @param {HLJSPlugin} plugin + */ + function addPlugin(plugin) { + upgradePluginAPI(plugin); + plugins.push(plugin); + } + + /** + * @param {HLJSPlugin} plugin + */ + function removePlugin(plugin) { + const index = plugins.indexOf(plugin); + if (index !== -1) { + plugins.splice(index, 1); + } + } + + /** + * + * @param {PluginEvent} event + * @param {any} args + */ + function fire(event, args) { + const cb = event; + plugins.forEach(function(plugin) { + if (plugin[cb]) { + plugin[cb](args); + } + }); + } + + /** + * DEPRECATED + * @param {HighlightedHTMLElement} el + */ + function deprecateHighlightBlock(el) { + deprecated("10.7.0", "highlightBlock will be removed entirely in v12.0"); + deprecated("10.7.0", "Please use highlightElement now."); + + return highlightElement(el); + } + + /* Interface definition */ + Object.assign(hljs, { + highlight, + highlightAuto, + highlightAll, + highlightElement, + // TODO: Remove with v12 API + highlightBlock: deprecateHighlightBlock, + configure, + initHighlighting, + initHighlightingOnLoad, + registerLanguage, + unregisterLanguage, + listLanguages, + getLanguage, + registerAliases, + autoDetection, + inherit, + addPlugin, + removePlugin + }); + + hljs.debugMode = function() { SAFE_MODE = false; }; + hljs.safeMode = function() { SAFE_MODE = true; }; + hljs.versionString = version; + + hljs.regex = { + concat: concat, + lookahead: lookahead, + either: either, + optional: optional, + anyNumberOfTimes: anyNumberOfTimes + }; + + for (const key in MODES) { + // @ts-ignore + if (typeof MODES[key] === "object") { + // @ts-ignore + deepFreeze(MODES[key]); + } + } + + // merge all the modes/regexes into our main object + Object.assign(hljs, MODES); + + return hljs; +}; + +// Other names for the variable may break build script +const highlight = HLJS({}); + +// returns a new instance of the highlighter to be used for extensions +// check https://github.com/wooorm/lowlight/issues/47 +highlight.newInstance = () => HLJS({}); + +export { highlight as default }; diff --git a/vendor/highlightjs/es/core.min.js b/vendor/highlightjs/es/core.min.js new file mode 100644 index 000000000..c6d4ae5cb --- /dev/null +++ b/vendor/highlightjs/es/core.min.js @@ -0,0 +1,307 @@ +/*! + Highlight.js v11.9.0 (git: b7ec4bfafc) + (c) 2006-2023 undefined and other contributors + License: BSD-3-Clause + */ +function e(t){return t instanceof Map?t.clear=t.delete=t.set=()=>{ +throw Error("map is read-only")}:t instanceof Set&&(t.add=t.clear=t.delete=()=>{ +throw Error("set is read-only") +}),Object.freeze(t),Object.getOwnPropertyNames(t).forEach((n=>{ +const i=t[n],s=typeof i;"object"!==s&&"function"!==s||Object.isFrozen(i)||e(i) +})),t}class t{constructor(e){ +void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1} +ignoreMatch(){this.isMatchIgnored=!0}}function n(e){ +return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'") +}function i(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t] +;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n}const s=e=>!!e.scope +;class r{constructor(e,t){ +this.buffer="",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){ +this.buffer+=n(e)}openNode(e){if(!s(e))return;const t=((e,{prefix:t})=>{ +if(e.startsWith("language:"))return e.replace("language:","language-") +;if(e.includes(".")){const n=e.split(".") +;return[`${t}${n.shift()}`,...n.map(((e,t)=>`${e}${"_".repeat(t+1)}`))].join(" ") +}return`${t}${e}`})(e.scope,{prefix:this.classPrefix});this.span(t)} +closeNode(e){s(e)&&(this.buffer+="")}value(){return this.buffer}span(e){ +this.buffer+=``}}const o=(e={})=>{const t={children:[]} +;return Object.assign(t,e),t};class a{constructor(){ +this.rootNode=o(),this.stack=[this.rootNode]}get top(){ +return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){ +this.top.children.push(e)}openNode(e){const t=o({scope:e}) +;this.add(t),this.stack.push(t)}closeNode(){ +if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){ +for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)} +walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){ +return"string"==typeof t?e.addText(t):t.children&&(e.openNode(t), +t.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){ +"string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{ +a._collapse(e)})))}}class c extends a{constructor(e){super(),this.options=e} +addText(e){""!==e&&this.add(e)}startScope(e){this.openNode(e)}endScope(){ +this.closeNode()}__addSublanguage(e,t){const n=e.root +;t&&(n.scope="language:"+t),this.add(n)}toHTML(){ +return new r(this,this.options).value()}finalize(){ +return this.closeAllNodes(),!0}}function l(e){ +return e?"string"==typeof e?e:e.source:null}function g(e){return h("(?=",e,")")} +function u(e){return h("(?:",e,")*")}function d(e){return h("(?:",e,")?")} +function h(...e){return e.map((e=>l(e))).join("")}function f(...e){const t=(e=>{ +const t=e[e.length-1] +;return"object"==typeof t&&t.constructor===Object?(e.splice(e.length-1,1),t):{} +})(e);return"("+(t.capture?"":"?:")+e.map((e=>l(e))).join("|")+")"} +function p(e){return RegExp(e.toString()+"|").exec("").length-1} +const b=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./ +;function m(e,{joinWith:t}){let n=0;return e.map((e=>{n+=1;const t=n +;let i=l(e),s="";for(;i.length>0;){const e=b.exec(i);if(!e){s+=i;break} +s+=i.substring(0,e.index), +i=i.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?s+="\\"+(Number(e[1])+t):(s+=e[0], +"("===e[0]&&n++)}return s})).map((e=>`(${e})`)).join(t)} +const E="[a-zA-Z]\\w*",x="[a-zA-Z_]\\w*",w="\\b\\d+(\\.\\d+)?",y="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",_="\\b(0b[01]+)",O={ +begin:"\\\\[\\s\\S]",relevance:0},k={scope:"string",begin:"'",end:"'", +illegal:"\\n",contains:[O]},v={scope:"string",begin:'"',end:'"',illegal:"\\n", +contains:[O]},N=(e,t,n={})=>{const s=i({scope:"comment",begin:e,end:t, +contains:[]},n);s.contains.push({scope:"doctag", +begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)", +end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0}) +;const r=f("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/) +;return s.contains.push({begin:h(/[ ]+/,"(",r,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),s +},S=N("//","$"),M=N("/\\*","\\*/"),R=N("#","$");var A=Object.freeze({ +__proto__:null,APOS_STRING_MODE:k,BACKSLASH_ESCAPE:O,BINARY_NUMBER_MODE:{ +scope:"number",begin:_,relevance:0},BINARY_NUMBER_RE:_,COMMENT:N, +C_BLOCK_COMMENT_MODE:M,C_LINE_COMMENT_MODE:S,C_NUMBER_MODE:{scope:"number", +begin:y,relevance:0},C_NUMBER_RE:y,END_SAME_AS_BEGIN:e=>Object.assign(e,{ +"on:begin":(e,t)=>{t.data._beginMatch=e[1]},"on:end":(e,t)=>{ +t.data._beginMatch!==e[1]&&t.ignoreMatch()}}),HASH_COMMENT_MODE:R,IDENT_RE:E, +MATCH_NOTHING_RE:/\b\B/,METHOD_GUARD:{begin:"\\.\\s*"+x,relevance:0}, +NUMBER_MODE:{scope:"number",begin:w,relevance:0},NUMBER_RE:w, +PHRASAL_WORDS_MODE:{ +begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ +},QUOTE_STRING_MODE:v,REGEXP_MODE:{scope:"regexp",begin:/\/(?=[^/\n]*\/)/, +end:/\/[gimuy]*/,contains:[O,{begin:/\[/,end:/\]/,relevance:0,contains:[O]}]}, +RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~", +SHEBANG:(e={})=>{const t=/^#![ ]*\// +;return e.binary&&(e.begin=h(t,/.*\b/,e.binary,/\b.*/)),i({scope:"meta",begin:t, +end:/$/,relevance:0,"on:begin":(e,t)=>{0!==e.index&&t.ignoreMatch()}},e)}, +TITLE_MODE:{scope:"title",begin:E,relevance:0},UNDERSCORE_IDENT_RE:x, +UNDERSCORE_TITLE_MODE:{scope:"title",begin:x,relevance:0}});function j(e,t){ +"."===e.input[e.index-1]&&t.ignoreMatch()}function I(e,t){ +void 0!==e.className&&(e.scope=e.className,delete e.className)}function T(e,t){ +t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)", +e.__beforeBegin=j,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords, +void 0===e.relevance&&(e.relevance=0))}function L(e,t){ +Array.isArray(e.illegal)&&(e.illegal=f(...e.illegal))}function B(e,t){ +if(e.match){ +if(e.begin||e.end)throw Error("begin & end are not supported with match") +;e.begin=e.match,delete e.match}}function P(e,t){ +void 0===e.relevance&&(e.relevance=1)}const D=(e,t)=>{if(!e.beforeMatch)return +;if(e.starts)throw Error("beforeMatch cannot be used with starts") +;const n=Object.assign({},e);Object.keys(e).forEach((t=>{delete e[t] +})),e.keywords=n.keywords,e.begin=h(n.beforeMatch,g(n.begin)),e.starts={ +relevance:0,contains:[Object.assign(n,{endsParent:!0})] +},e.relevance=0,delete n.beforeMatch +},H=["of","and","for","in","not","or","if","then","parent","list","value"],C="keyword" +;function $(e,t,n=C){const i=Object.create(null) +;return"string"==typeof e?s(n,e.split(" ")):Array.isArray(e)?s(n,e):Object.keys(e).forEach((n=>{ +Object.assign(i,$(e[n],t,n))})),i;function s(e,n){ +t&&(n=n.map((e=>e.toLowerCase()))),n.forEach((t=>{const n=t.split("|") +;i[n[0]]=[e,U(n[0],n[1])]}))}}function U(e,t){ +return t?Number(t):(e=>H.includes(e.toLowerCase()))(e)?0:1}const z={},W=e=>{ +console.error(e)},X=(e,...t)=>{console.log("WARN: "+e,...t)},G=(e,t)=>{ +z[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),z[`${e}/${t}`]=!0) +},K=Error();function F(e,t,{key:n}){let i=0;const s=e[n],r={},o={} +;for(let e=1;e<=t.length;e++)o[e+i]=s[e],r[e+i]=!0,i+=p(t[e-1]) +;e[n]=o,e[n]._emit=r,e[n]._multi=!0}function Z(e){(e=>{ +e.scope&&"object"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope, +delete e.scope)})(e),"string"==typeof e.beginScope&&(e.beginScope={ +_wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope +}),(e=>{if(Array.isArray(e.begin)){ +if(e.skip||e.excludeBegin||e.returnBegin)throw W("skip, excludeBegin, returnBegin not compatible with beginScope: {}"), +K +;if("object"!=typeof e.beginScope||null===e.beginScope)throw W("beginScope must be object"), +K;F(e,e.begin,{key:"beginScope"}),e.begin=m(e.begin,{joinWith:""})}})(e),(e=>{ +if(Array.isArray(e.end)){ +if(e.skip||e.excludeEnd||e.returnEnd)throw W("skip, excludeEnd, returnEnd not compatible with endScope: {}"), +K +;if("object"!=typeof e.endScope||null===e.endScope)throw W("endScope must be object"), +K;F(e,e.end,{key:"endScope"}),e.end=m(e.end,{joinWith:""})}})(e)}function V(e){ +function t(t,n){ +return RegExp(l(t),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(n?"g":"")) +}class n{constructor(){ +this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0} +addRule(e,t){ +t.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]), +this.matchAt+=p(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null) +;const e=this.regexes.map((e=>e[1]));this.matcherRe=t(m(e,{joinWith:"|" +}),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex +;const t=this.matcherRe.exec(e);if(!t)return null +;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),i=this.matchIndexes[n] +;return t.splice(0,n),Object.assign(t,i)}}class s{constructor(){ +this.rules=[],this.multiRegexes=[], +this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){ +if(this.multiRegexes[e])return this.multiRegexes[e];const t=new n +;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))), +t.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){ +return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){ +this.rules.push([e,t]),"begin"===t.type&&this.count++}exec(e){ +const t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex +;let n=t.exec(e) +;if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{ +const t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)} +return n&&(this.regexIndex+=n.position+1, +this.regexIndex===this.count&&this.considerAll()),n}} +if(e.compilerExtensions||(e.compilerExtensions=[]), +e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.") +;return e.classNameAliases=i(e.classNameAliases||{}),function n(r,o){const a=r +;if(r.isCompiled)return a +;[I,B,Z,D].forEach((e=>e(r,o))),e.compilerExtensions.forEach((e=>e(r,o))), +r.__beforeBegin=null,[T,L,P].forEach((e=>e(r,o))),r.isCompiled=!0;let c=null +;return"object"==typeof r.keywords&&r.keywords.$pattern&&(r.keywords=Object.assign({},r.keywords), +c=r.keywords.$pattern, +delete r.keywords.$pattern),c=c||/\w+/,r.keywords&&(r.keywords=$(r.keywords,e.case_insensitive)), +a.keywordPatternRe=t(c,!0), +o&&(r.begin||(r.begin=/\B|\b/),a.beginRe=t(a.begin),r.end||r.endsWithParent||(r.end=/\B|\b/), +r.end&&(a.endRe=t(a.end)), +a.terminatorEnd=l(a.end)||"",r.endsWithParent&&o.terminatorEnd&&(a.terminatorEnd+=(r.end?"|":"")+o.terminatorEnd)), +r.illegal&&(a.illegalRe=t(r.illegal)), +r.contains||(r.contains=[]),r.contains=[].concat(...r.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((t=>i(e,{ +variants:null},t)))),e.cachedVariants?e.cachedVariants:q(e)?i(e,{ +starts:e.starts?i(e.starts):null +}):Object.isFrozen(e)?i(e):e))("self"===e?r:e)))),r.contains.forEach((e=>{n(e,a) +})),r.starts&&n(r.starts,o),a.matcher=(e=>{const t=new s +;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:"begin" +}))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:"end" +}),e.illegal&&t.addRule(e.illegal,{type:"illegal"}),t})(a),a}(e)}function q(e){ +return!!e&&(e.endsWithParent||q(e.starts))}class J extends Error{ +constructor(e,t){super(e),this.name="HTMLInjectionError",this.html=t}} +const Y=n,Q=i,ee=Symbol("nomatch"),te=n=>{ +const i=Object.create(null),s=Object.create(null),r=[];let o=!0 +;const a="Could not find the language '{}', did you forget to load/include a language module?",l={ +disableAutodetect:!0,name:"Plain text",contains:[]};let p={ +ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i, +languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-", +cssSelector:"pre code",languages:null,__emitter:c};function b(e){ +return p.noHighlightRe.test(e)}function m(e,t,n){let i="",s="" +;"object"==typeof t?(i=e, +n=t.ignoreIllegals,s=t.language):(G("10.7.0","highlight(lang, code, ...args) has been deprecated."), +G("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"), +s=e,i=t),void 0===n&&(n=!0);const r={code:i,language:s};N("before:highlight",r) +;const o=r.result?r.result:E(r.language,r.code,n) +;return o.code=r.code,N("after:highlight",o),o}function E(e,n,s,r){ +const c=Object.create(null);function l(){if(!N.keywords)return void M.addText(R) +;let e=0;N.keywordPatternRe.lastIndex=0;let t=N.keywordPatternRe.exec(R),n="" +;for(;t;){n+=R.substring(e,t.index) +;const s=_.case_insensitive?t[0].toLowerCase():t[0],r=(i=s,N.keywords[i]);if(r){ +const[e,i]=r +;if(M.addText(n),n="",c[s]=(c[s]||0)+1,c[s]<=7&&(A+=i),e.startsWith("_"))n+=t[0];else{ +const n=_.classNameAliases[e]||e;u(t[0],n)}}else n+=t[0] +;e=N.keywordPatternRe.lastIndex,t=N.keywordPatternRe.exec(R)}var i +;n+=R.substring(e),M.addText(n)}function g(){null!=N.subLanguage?(()=>{ +if(""===R)return;let e=null;if("string"==typeof N.subLanguage){ +if(!i[N.subLanguage])return void M.addText(R) +;e=E(N.subLanguage,R,!0,S[N.subLanguage]),S[N.subLanguage]=e._top +}else e=x(R,N.subLanguage.length?N.subLanguage:null) +;N.relevance>0&&(A+=e.relevance),M.__addSublanguage(e._emitter,e.language) +})():l(),R=""}function u(e,t){ +""!==e&&(M.startScope(t),M.addText(e),M.endScope())}function d(e,t){let n=1 +;const i=t.length-1;for(;n<=i;){if(!e._emit[n]){n++;continue} +const i=_.classNameAliases[e[n]]||e[n],s=t[n];i?u(s,i):(R=s,l(),R=""),n++}} +function h(e,t){ +return e.scope&&"string"==typeof e.scope&&M.openNode(_.classNameAliases[e.scope]||e.scope), +e.beginScope&&(e.beginScope._wrap?(u(R,_.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap), +R=""):e.beginScope._multi&&(d(e.beginScope,t),R="")),N=Object.create(e,{parent:{ +value:N}}),N}function f(e,n,i){let s=((e,t)=>{const n=e&&e.exec(t) +;return n&&0===n.index})(e.endRe,i);if(s){if(e["on:end"]){const i=new t(e) +;e["on:end"](n,i),i.isMatchIgnored&&(s=!1)}if(s){ +for(;e.endsParent&&e.parent;)e=e.parent;return e}} +if(e.endsWithParent)return f(e.parent,n,i)}function b(e){ +return 0===N.matcher.regexIndex?(R+=e[0],1):(T=!0,0)}function m(e){ +const t=e[0],i=n.substring(e.index),s=f(N,e,i);if(!s)return ee;const r=N +;N.endScope&&N.endScope._wrap?(g(), +u(t,N.endScope._wrap)):N.endScope&&N.endScope._multi?(g(), +d(N.endScope,e)):r.skip?R+=t:(r.returnEnd||r.excludeEnd||(R+=t), +g(),r.excludeEnd&&(R=t));do{ +N.scope&&M.closeNode(),N.skip||N.subLanguage||(A+=N.relevance),N=N.parent +}while(N!==s.parent);return s.starts&&h(s.starts,e),r.returnEnd?0:t.length} +let w={};function y(i,r){const a=r&&r[0];if(R+=i,null==a)return g(),0 +;if("begin"===w.type&&"end"===r.type&&w.index===r.index&&""===a){ +if(R+=n.slice(r.index,r.index+1),!o){const t=Error(`0 width match regex (${e})`) +;throw t.languageName=e,t.badRule=w.rule,t}return 1} +if(w=r,"begin"===r.type)return(e=>{ +const n=e[0],i=e.rule,s=new t(i),r=[i.__beforeBegin,i["on:begin"]] +;for(const t of r)if(t&&(t(e,s),s.isMatchIgnored))return b(n) +;return i.skip?R+=n:(i.excludeBegin&&(R+=n), +g(),i.returnBegin||i.excludeBegin||(R=n)),h(i,e),i.returnBegin?0:n.length})(r) +;if("illegal"===r.type&&!s){ +const e=Error('Illegal lexeme "'+a+'" for mode "'+(N.scope||"")+'"') +;throw e.mode=N,e}if("end"===r.type){const e=m(r);if(e!==ee)return e} +if("illegal"===r.type&&""===a)return 1 +;if(I>1e5&&I>3*r.index)throw Error("potential infinite loop, way more iterations than matches") +;return R+=a,a.length}const _=O(e) +;if(!_)throw W(a.replace("{}",e)),Error('Unknown language: "'+e+'"') +;const k=V(_);let v="",N=r||k;const S={},M=new p.__emitter(p);(()=>{const e=[] +;for(let t=N;t!==_;t=t.parent)t.scope&&e.unshift(t.scope) +;e.forEach((e=>M.openNode(e)))})();let R="",A=0,j=0,I=0,T=!1;try{ +if(_.__emitTokens)_.__emitTokens(n,M);else{for(N.matcher.considerAll();;){ +I++,T?T=!1:N.matcher.considerAll(),N.matcher.lastIndex=j +;const e=N.matcher.exec(n);if(!e)break;const t=y(n.substring(j,e.index),e) +;j=e.index+t}y(n.substring(j))}return M.finalize(),v=M.toHTML(),{language:e, +value:v,relevance:A,illegal:!1,_emitter:M,_top:N}}catch(t){ +if(t.message&&t.message.includes("Illegal"))return{language:e,value:Y(n), +illegal:!0,relevance:0,_illegalBy:{message:t.message,index:j, +context:n.slice(j-100,j+100),mode:t.mode,resultSoFar:v},_emitter:M};if(o)return{ +language:e,value:Y(n),illegal:!1,relevance:0,errorRaised:t,_emitter:M,_top:N} +;throw t}}function x(e,t){t=t||p.languages||Object.keys(i);const n=(e=>{ +const t={value:Y(e),illegal:!1,relevance:0,_top:l,_emitter:new p.__emitter(p)} +;return t._emitter.addText(e),t})(e),s=t.filter(O).filter(v).map((t=>E(t,e,!1))) +;s.unshift(n);const r=s.sort(((e,t)=>{ +if(e.relevance!==t.relevance)return t.relevance-e.relevance +;if(e.language&&t.language){if(O(e.language).supersetOf===t.language)return 1 +;if(O(t.language).supersetOf===e.language)return-1}return 0})),[o,a]=r,c=o +;return c.secondBest=a,c}function w(e){let t=null;const n=(e=>{ +let t=e.className+" ";t+=e.parentNode?e.parentNode.className:"" +;const n=p.languageDetectRe.exec(t);if(n){const t=O(n[1]) +;return t||(X(a.replace("{}",n[1])), +X("Falling back to no-highlight mode for this block.",e)),t?n[1]:"no-highlight"} +return t.split(/\s+/).find((e=>b(e)||O(e)))})(e);if(b(n))return +;if(N("before:highlightElement",{el:e,language:n +}),e.dataset.highlighted)return void console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.",e) +;if(e.children.length>0&&(p.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."), +console.warn("https://github.com/highlightjs/highlight.js/wiki/security"), +console.warn("The element with unescaped HTML:"), +console.warn(e)),p.throwUnescapedHTML))throw new J("One of your code blocks includes unescaped HTML.",e.innerHTML) +;t=e;const i=t.textContent,r=n?m(i,{language:n,ignoreIllegals:!0}):x(i) +;e.innerHTML=r.value,e.dataset.highlighted="yes",((e,t,n)=>{const i=t&&s[t]||n +;e.classList.add("hljs"),e.classList.add("language-"+i) +})(e,n,r.language),e.result={language:r.language,re:r.relevance, +relevance:r.relevance},r.secondBest&&(e.secondBest={ +language:r.secondBest.language,relevance:r.secondBest.relevance +}),N("after:highlightElement",{el:e,result:r,text:i})}let y=!1;function _(){ +"loading"!==document.readyState?document.querySelectorAll(p.cssSelector).forEach(w):y=!0 +}function O(e){return e=(e||"").toLowerCase(),i[e]||i[s[e]]} +function k(e,{languageName:t}){"string"==typeof e&&(e=[e]),e.forEach((e=>{ +s[e.toLowerCase()]=t}))}function v(e){const t=O(e) +;return t&&!t.disableAutodetect}function N(e,t){const n=e;r.forEach((e=>{ +e[n]&&e[n](t)}))} +"undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(()=>{ +y&&_()}),!1),Object.assign(n,{highlight:m,highlightAuto:x,highlightAll:_, +highlightElement:w, +highlightBlock:e=>(G("10.7.0","highlightBlock will be removed entirely in v12.0"), +G("10.7.0","Please use highlightElement now."),w(e)),configure:e=>{p=Q(p,e)}, +initHighlighting:()=>{ +_(),G("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")}, +initHighlightingOnLoad:()=>{ +_(),G("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.") +},registerLanguage:(e,t)=>{let s=null;try{s=t(n)}catch(t){ +if(W("Language definition for '{}' could not be registered.".replace("{}",e)), +!o)throw t;W(t),s=l} +s.name||(s.name=e),i[e]=s,s.rawDefinition=t.bind(null,n),s.aliases&&k(s.aliases,{ +languageName:e})},unregisterLanguage:e=>{delete i[e] +;for(const t of Object.keys(s))s[t]===e&&delete s[t]}, +listLanguages:()=>Object.keys(i),getLanguage:O,registerAliases:k, +autoDetection:v,inherit:Q,addPlugin:e=>{(e=>{ +e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=t=>{ +e["before:highlightBlock"](Object.assign({block:t.el},t)) +}),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=t=>{ +e["after:highlightBlock"](Object.assign({block:t.el},t))})})(e),r.push(e)}, +removePlugin:e=>{const t=r.indexOf(e);-1!==t&&r.splice(t,1)}}),n.debugMode=()=>{ +o=!1},n.safeMode=()=>{o=!0},n.versionString="11.9.0",n.regex={concat:h, +lookahead:g,either:f,optional:d,anyNumberOfTimes:u} +;for(const t in A)"object"==typeof A[t]&&e(A[t]);return Object.assign(n,A),n +},ne=te({});ne.newInstance=()=>te({});export{ne as default}; \ No newline at end of file diff --git a/vendor/highlightjs/es/highlight.js b/vendor/highlightjs/es/highlight.js new file mode 100644 index 000000000..7294b81df --- /dev/null +++ b/vendor/highlightjs/es/highlight.js @@ -0,0 +1,2600 @@ +/*! + Highlight.js v11.9.0 (git: b7ec4bfafc) + (c) 2006-2023 undefined and other contributors + License: BSD-3-Clause + */ +/* eslint-disable no-multi-assign */ + +function deepFreeze(obj) { + if (obj instanceof Map) { + obj.clear = + obj.delete = + obj.set = + function () { + throw new Error('map is read-only'); + }; + } else if (obj instanceof Set) { + obj.add = + obj.clear = + obj.delete = + function () { + throw new Error('set is read-only'); + }; + } + + // Freeze self + Object.freeze(obj); + + Object.getOwnPropertyNames(obj).forEach((name) => { + const prop = obj[name]; + const type = typeof prop; + + // Freeze prop if it is an object or function and also not already frozen + if ((type === 'object' || type === 'function') && !Object.isFrozen(prop)) { + deepFreeze(prop); + } + }); + + return obj; +} + +/** @typedef {import('highlight.js').CallbackResponse} CallbackResponse */ +/** @typedef {import('highlight.js').CompiledMode} CompiledMode */ +/** @implements CallbackResponse */ + +class Response { + /** + * @param {CompiledMode} mode + */ + constructor(mode) { + // eslint-disable-next-line no-undefined + if (mode.data === undefined) mode.data = {}; + + this.data = mode.data; + this.isMatchIgnored = false; + } + + ignoreMatch() { + this.isMatchIgnored = true; + } +} + +/** + * @param {string} value + * @returns {string} + */ +function escapeHTML(value) { + return value + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +/** + * performs a shallow merge of multiple objects into one + * + * @template T + * @param {T} original + * @param {Record[]} objects + * @returns {T} a single new object + */ +function inherit$1(original, ...objects) { + /** @type Record */ + const result = Object.create(null); + + for (const key in original) { + result[key] = original[key]; + } + objects.forEach(function(obj) { + for (const key in obj) { + result[key] = obj[key]; + } + }); + return /** @type {T} */ (result); +} + +/** + * @typedef {object} Renderer + * @property {(text: string) => void} addText + * @property {(node: Node) => void} openNode + * @property {(node: Node) => void} closeNode + * @property {() => string} value + */ + +/** @typedef {{scope?: string, language?: string, sublanguage?: boolean}} Node */ +/** @typedef {{walk: (r: Renderer) => void}} Tree */ +/** */ + +const SPAN_CLOSE = ''; + +/** + * Determines if a node needs to be wrapped in + * + * @param {Node} node */ +const emitsWrappingTags = (node) => { + // rarely we can have a sublanguage where language is undefined + // TODO: track down why + return !!node.scope; +}; + +/** + * + * @param {string} name + * @param {{prefix:string}} options + */ +const scopeToCSSClass = (name, { prefix }) => { + // sub-language + if (name.startsWith("language:")) { + return name.replace("language:", "language-"); + } + // tiered scope: comment.line + if (name.includes(".")) { + const pieces = name.split("."); + return [ + `${prefix}${pieces.shift()}`, + ...(pieces.map((x, i) => `${x}${"_".repeat(i + 1)}`)) + ].join(" "); + } + // simple scope + return `${prefix}${name}`; +}; + +/** @type {Renderer} */ +class HTMLRenderer { + /** + * Creates a new HTMLRenderer + * + * @param {Tree} parseTree - the parse tree (must support `walk` API) + * @param {{classPrefix: string}} options + */ + constructor(parseTree, options) { + this.buffer = ""; + this.classPrefix = options.classPrefix; + parseTree.walk(this); + } + + /** + * Adds texts to the output stream + * + * @param {string} text */ + addText(text) { + this.buffer += escapeHTML(text); + } + + /** + * Adds a node open to the output stream (if needed) + * + * @param {Node} node */ + openNode(node) { + if (!emitsWrappingTags(node)) return; + + const className = scopeToCSSClass(node.scope, + { prefix: this.classPrefix }); + this.span(className); + } + + /** + * Adds a node close to the output stream (if needed) + * + * @param {Node} node */ + closeNode(node) { + if (!emitsWrappingTags(node)) return; + + this.buffer += SPAN_CLOSE; + } + + /** + * returns the accumulated buffer + */ + value() { + return this.buffer; + } + + // helpers + + /** + * Builds a span element + * + * @param {string} className */ + span(className) { + this.buffer += ``; + } +} + +/** @typedef {{scope?: string, language?: string, children: Node[]} | string} Node */ +/** @typedef {{scope?: string, language?: string, children: Node[]} } DataNode */ +/** @typedef {import('highlight.js').Emitter} Emitter */ +/** */ + +/** @returns {DataNode} */ +const newNode = (opts = {}) => { + /** @type DataNode */ + const result = { children: [] }; + Object.assign(result, opts); + return result; +}; + +class TokenTree { + constructor() { + /** @type DataNode */ + this.rootNode = newNode(); + this.stack = [this.rootNode]; + } + + get top() { + return this.stack[this.stack.length - 1]; + } + + get root() { return this.rootNode; } + + /** @param {Node} node */ + add(node) { + this.top.children.push(node); + } + + /** @param {string} scope */ + openNode(scope) { + /** @type Node */ + const node = newNode({ scope }); + this.add(node); + this.stack.push(node); + } + + closeNode() { + if (this.stack.length > 1) { + return this.stack.pop(); + } + // eslint-disable-next-line no-undefined + return undefined; + } + + closeAllNodes() { + while (this.closeNode()); + } + + toJSON() { + return JSON.stringify(this.rootNode, null, 4); + } + + /** + * @typedef { import("./html_renderer").Renderer } Renderer + * @param {Renderer} builder + */ + walk(builder) { + // this does not + return this.constructor._walk(builder, this.rootNode); + // this works + // return TokenTree._walk(builder, this.rootNode); + } + + /** + * @param {Renderer} builder + * @param {Node} node + */ + static _walk(builder, node) { + if (typeof node === "string") { + builder.addText(node); + } else if (node.children) { + builder.openNode(node); + node.children.forEach((child) => this._walk(builder, child)); + builder.closeNode(node); + } + return builder; + } + + /** + * @param {Node} node + */ + static _collapse(node) { + if (typeof node === "string") return; + if (!node.children) return; + + if (node.children.every(el => typeof el === "string")) { + // node.text = node.children.join(""); + // delete node.children; + node.children = [node.children.join("")]; + } else { + node.children.forEach((child) => { + TokenTree._collapse(child); + }); + } + } +} + +/** + Currently this is all private API, but this is the minimal API necessary + that an Emitter must implement to fully support the parser. + + Minimal interface: + + - addText(text) + - __addSublanguage(emitter, subLanguageName) + - startScope(scope) + - endScope() + - finalize() + - toHTML() + +*/ + +/** + * @implements {Emitter} + */ +class TokenTreeEmitter extends TokenTree { + /** + * @param {*} options + */ + constructor(options) { + super(); + this.options = options; + } + + /** + * @param {string} text + */ + addText(text) { + if (text === "") { return; } + + this.add(text); + } + + /** @param {string} scope */ + startScope(scope) { + this.openNode(scope); + } + + endScope() { + this.closeNode(); + } + + /** + * @param {Emitter & {root: DataNode}} emitter + * @param {string} name + */ + __addSublanguage(emitter, name) { + /** @type DataNode */ + const node = emitter.root; + if (name) node.scope = `language:${name}`; + + this.add(node); + } + + toHTML() { + const renderer = new HTMLRenderer(this, this.options); + return renderer.value(); + } + + finalize() { + this.closeAllNodes(); + return true; + } +} + +/** + * @param {string} value + * @returns {RegExp} + * */ + +/** + * @param {RegExp | string } re + * @returns {string} + */ +function source(re) { + if (!re) return null; + if (typeof re === "string") return re; + + return re.source; +} + +/** + * @param {RegExp | string } re + * @returns {string} + */ +function lookahead(re) { + return concat('(?=', re, ')'); +} + +/** + * @param {RegExp | string } re + * @returns {string} + */ +function anyNumberOfTimes(re) { + return concat('(?:', re, ')*'); +} + +/** + * @param {RegExp | string } re + * @returns {string} + */ +function optional(re) { + return concat('(?:', re, ')?'); +} + +/** + * @param {...(RegExp | string) } args + * @returns {string} + */ +function concat(...args) { + const joined = args.map((x) => source(x)).join(""); + return joined; +} + +/** + * @param { Array } args + * @returns {object} + */ +function stripOptionsFromArgs(args) { + const opts = args[args.length - 1]; + + if (typeof opts === 'object' && opts.constructor === Object) { + args.splice(args.length - 1, 1); + return opts; + } else { + return {}; + } +} + +/** @typedef { {capture?: boolean} } RegexEitherOptions */ + +/** + * Any of the passed expresssions may match + * + * Creates a huge this | this | that | that match + * @param {(RegExp | string)[] | [...(RegExp | string)[], RegexEitherOptions]} args + * @returns {string} + */ +function either(...args) { + /** @type { object & {capture?: boolean} } */ + const opts = stripOptionsFromArgs(args); + const joined = '(' + + (opts.capture ? "" : "?:") + + args.map((x) => source(x)).join("|") + ")"; + return joined; +} + +/** + * @param {RegExp | string} re + * @returns {number} + */ +function countMatchGroups(re) { + return (new RegExp(re.toString() + '|')).exec('').length - 1; +} + +/** + * Does lexeme start with a regular expression match at the beginning + * @param {RegExp} re + * @param {string} lexeme + */ +function startsWith(re, lexeme) { + const match = re && re.exec(lexeme); + return match && match.index === 0; +} + +// BACKREF_RE matches an open parenthesis or backreference. To avoid +// an incorrect parse, it additionally matches the following: +// - [...] elements, where the meaning of parentheses and escapes change +// - other escape sequences, so we do not misparse escape sequences as +// interesting elements +// - non-matching or lookahead parentheses, which do not capture. These +// follow the '(' with a '?'. +const BACKREF_RE = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./; + +// **INTERNAL** Not intended for outside usage +// join logically computes regexps.join(separator), but fixes the +// backreferences so they continue to match. +// it also places each individual regular expression into it's own +// match group, keeping track of the sequencing of those match groups +// is currently an exercise for the caller. :-) +/** + * @param {(string | RegExp)[]} regexps + * @param {{joinWith: string}} opts + * @returns {string} + */ +function _rewriteBackreferences(regexps, { joinWith }) { + let numCaptures = 0; + + return regexps.map((regex) => { + numCaptures += 1; + const offset = numCaptures; + let re = source(regex); + let out = ''; + + while (re.length > 0) { + const match = BACKREF_RE.exec(re); + if (!match) { + out += re; + break; + } + out += re.substring(0, match.index); + re = re.substring(match.index + match[0].length); + if (match[0][0] === '\\' && match[1]) { + // Adjust the backreference. + out += '\\' + String(Number(match[1]) + offset); + } else { + out += match[0]; + if (match[0] === '(') { + numCaptures++; + } + } + } + return out; + }).map(re => `(${re})`).join(joinWith); +} + +/** @typedef {import('highlight.js').Mode} Mode */ +/** @typedef {import('highlight.js').ModeCallback} ModeCallback */ + +// Common regexps +const MATCH_NOTHING_RE = /\b\B/; +const IDENT_RE = '[a-zA-Z]\\w*'; +const UNDERSCORE_IDENT_RE = '[a-zA-Z_]\\w*'; +const NUMBER_RE = '\\b\\d+(\\.\\d+)?'; +const C_NUMBER_RE = '(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)'; // 0x..., 0..., decimal, float +const BINARY_NUMBER_RE = '\\b(0b[01]+)'; // 0b... +const RE_STARTERS_RE = '!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~'; + +/** +* @param { Partial & {binary?: string | RegExp} } opts +*/ +const SHEBANG = (opts = {}) => { + const beginShebang = /^#![ ]*\//; + if (opts.binary) { + opts.begin = concat( + beginShebang, + /.*\b/, + opts.binary, + /\b.*/); + } + return inherit$1({ + scope: 'meta', + begin: beginShebang, + end: /$/, + relevance: 0, + /** @type {ModeCallback} */ + "on:begin": (m, resp) => { + if (m.index !== 0) resp.ignoreMatch(); + } + }, opts); +}; + +// Common modes +const BACKSLASH_ESCAPE = { + begin: '\\\\[\\s\\S]', relevance: 0 +}; +const APOS_STRING_MODE = { + scope: 'string', + begin: '\'', + end: '\'', + illegal: '\\n', + contains: [BACKSLASH_ESCAPE] +}; +const QUOTE_STRING_MODE = { + scope: 'string', + begin: '"', + end: '"', + illegal: '\\n', + contains: [BACKSLASH_ESCAPE] +}; +const PHRASAL_WORDS_MODE = { + begin: /\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ +}; +/** + * Creates a comment mode + * + * @param {string | RegExp} begin + * @param {string | RegExp} end + * @param {Mode | {}} [modeOptions] + * @returns {Partial} + */ +const COMMENT = function(begin, end, modeOptions = {}) { + const mode = inherit$1( + { + scope: 'comment', + begin, + end, + contains: [] + }, + modeOptions + ); + mode.contains.push({ + scope: 'doctag', + // hack to avoid the space from being included. the space is necessary to + // match here to prevent the plain text rule below from gobbling up doctags + begin: '[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)', + end: /(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/, + excludeBegin: true, + relevance: 0 + }); + const ENGLISH_WORD = either( + // list of common 1 and 2 letter words in English + "I", + "a", + "is", + "so", + "us", + "to", + "at", + "if", + "in", + "it", + "on", + // note: this is not an exhaustive list of contractions, just popular ones + /[A-Za-z]+['](d|ve|re|ll|t|s|n)/, // contractions - can't we'd they're let's, etc + /[A-Za-z]+[-][a-z]+/, // `no-way`, etc. + /[A-Za-z][a-z]{2,}/ // allow capitalized words at beginning of sentences + ); + // looking like plain text, more likely to be a comment + mode.contains.push( + { + // TODO: how to include ", (, ) without breaking grammars that use these for + // comment delimiters? + // begin: /[ ]+([()"]?([A-Za-z'-]{3,}|is|a|I|so|us|[tT][oO]|at|if|in|it|on)[.]?[()":]?([.][ ]|[ ]|\))){3}/ + // --- + + // this tries to find sequences of 3 english words in a row (without any + // "programming" type syntax) this gives us a strong signal that we've + // TRULY found a comment - vs perhaps scanning with the wrong language. + // It's possible to find something that LOOKS like the start of the + // comment - but then if there is no readable text - good chance it is a + // false match and not a comment. + // + // for a visual example please see: + // https://github.com/highlightjs/highlight.js/issues/2827 + + begin: concat( + /[ ]+/, // necessary to prevent us gobbling up doctags like /* @author Bob Mcgill */ + '(', + ENGLISH_WORD, + /[.]?[:]?([.][ ]|[ ])/, + '){3}') // look for 3 words in a row + } + ); + return mode; +}; +const C_LINE_COMMENT_MODE = COMMENT('//', '$'); +const C_BLOCK_COMMENT_MODE = COMMENT('/\\*', '\\*/'); +const HASH_COMMENT_MODE = COMMENT('#', '$'); +const NUMBER_MODE = { + scope: 'number', + begin: NUMBER_RE, + relevance: 0 +}; +const C_NUMBER_MODE = { + scope: 'number', + begin: C_NUMBER_RE, + relevance: 0 +}; +const BINARY_NUMBER_MODE = { + scope: 'number', + begin: BINARY_NUMBER_RE, + relevance: 0 +}; +const REGEXP_MODE = { + scope: "regexp", + begin: /\/(?=[^/\n]*\/)/, + end: /\/[gimuy]*/, + contains: [ + BACKSLASH_ESCAPE, + { + begin: /\[/, + end: /\]/, + relevance: 0, + contains: [BACKSLASH_ESCAPE] + } + ] +}; +const TITLE_MODE = { + scope: 'title', + begin: IDENT_RE, + relevance: 0 +}; +const UNDERSCORE_TITLE_MODE = { + scope: 'title', + begin: UNDERSCORE_IDENT_RE, + relevance: 0 +}; +const METHOD_GUARD = { + // excludes method names from keyword processing + begin: '\\.\\s*' + UNDERSCORE_IDENT_RE, + relevance: 0 +}; + +/** + * Adds end same as begin mechanics to a mode + * + * Your mode must include at least a single () match group as that first match + * group is what is used for comparison + * @param {Partial} mode + */ +const END_SAME_AS_BEGIN = function(mode) { + return Object.assign(mode, + { + /** @type {ModeCallback} */ + 'on:begin': (m, resp) => { resp.data._beginMatch = m[1]; }, + /** @type {ModeCallback} */ + 'on:end': (m, resp) => { if (resp.data._beginMatch !== m[1]) resp.ignoreMatch(); } + }); +}; + +var MODES = /*#__PURE__*/Object.freeze({ + __proto__: null, + APOS_STRING_MODE: APOS_STRING_MODE, + BACKSLASH_ESCAPE: BACKSLASH_ESCAPE, + BINARY_NUMBER_MODE: BINARY_NUMBER_MODE, + BINARY_NUMBER_RE: BINARY_NUMBER_RE, + COMMENT: COMMENT, + C_BLOCK_COMMENT_MODE: C_BLOCK_COMMENT_MODE, + C_LINE_COMMENT_MODE: C_LINE_COMMENT_MODE, + C_NUMBER_MODE: C_NUMBER_MODE, + C_NUMBER_RE: C_NUMBER_RE, + END_SAME_AS_BEGIN: END_SAME_AS_BEGIN, + HASH_COMMENT_MODE: HASH_COMMENT_MODE, + IDENT_RE: IDENT_RE, + MATCH_NOTHING_RE: MATCH_NOTHING_RE, + METHOD_GUARD: METHOD_GUARD, + NUMBER_MODE: NUMBER_MODE, + NUMBER_RE: NUMBER_RE, + PHRASAL_WORDS_MODE: PHRASAL_WORDS_MODE, + QUOTE_STRING_MODE: QUOTE_STRING_MODE, + REGEXP_MODE: REGEXP_MODE, + RE_STARTERS_RE: RE_STARTERS_RE, + SHEBANG: SHEBANG, + TITLE_MODE: TITLE_MODE, + UNDERSCORE_IDENT_RE: UNDERSCORE_IDENT_RE, + UNDERSCORE_TITLE_MODE: UNDERSCORE_TITLE_MODE +}); + +/** +@typedef {import('highlight.js').CallbackResponse} CallbackResponse +@typedef {import('highlight.js').CompilerExt} CompilerExt +*/ + +// Grammar extensions / plugins +// See: https://github.com/highlightjs/highlight.js/issues/2833 + +// Grammar extensions allow "syntactic sugar" to be added to the grammar modes +// without requiring any underlying changes to the compiler internals. + +// `compileMatch` being the perfect small example of now allowing a grammar +// author to write `match` when they desire to match a single expression rather +// than being forced to use `begin`. The extension then just moves `match` into +// `begin` when it runs. Ie, no features have been added, but we've just made +// the experience of writing (and reading grammars) a little bit nicer. + +// ------ + +// TODO: We need negative look-behind support to do this properly +/** + * Skip a match if it has a preceding dot + * + * This is used for `beginKeywords` to prevent matching expressions such as + * `bob.keyword.do()`. The mode compiler automatically wires this up as a + * special _internal_ 'on:begin' callback for modes with `beginKeywords` + * @param {RegExpMatchArray} match + * @param {CallbackResponse} response + */ +function skipIfHasPrecedingDot(match, response) { + const before = match.input[match.index - 1]; + if (before === ".") { + response.ignoreMatch(); + } +} + +/** + * + * @type {CompilerExt} + */ +function scopeClassName(mode, _parent) { + // eslint-disable-next-line no-undefined + if (mode.className !== undefined) { + mode.scope = mode.className; + delete mode.className; + } +} + +/** + * `beginKeywords` syntactic sugar + * @type {CompilerExt} + */ +function beginKeywords(mode, parent) { + if (!parent) return; + if (!mode.beginKeywords) return; + + // for languages with keywords that include non-word characters checking for + // a word boundary is not sufficient, so instead we check for a word boundary + // or whitespace - this does no harm in any case since our keyword engine + // doesn't allow spaces in keywords anyways and we still check for the boundary + // first + mode.begin = '\\b(' + mode.beginKeywords.split(' ').join('|') + ')(?!\\.)(?=\\b|\\s)'; + mode.__beforeBegin = skipIfHasPrecedingDot; + mode.keywords = mode.keywords || mode.beginKeywords; + delete mode.beginKeywords; + + // prevents double relevance, the keywords themselves provide + // relevance, the mode doesn't need to double it + // eslint-disable-next-line no-undefined + if (mode.relevance === undefined) mode.relevance = 0; +} + +/** + * Allow `illegal` to contain an array of illegal values + * @type {CompilerExt} + */ +function compileIllegal(mode, _parent) { + if (!Array.isArray(mode.illegal)) return; + + mode.illegal = either(...mode.illegal); +} + +/** + * `match` to match a single expression for readability + * @type {CompilerExt} + */ +function compileMatch(mode, _parent) { + if (!mode.match) return; + if (mode.begin || mode.end) throw new Error("begin & end are not supported with match"); + + mode.begin = mode.match; + delete mode.match; +} + +/** + * provides the default 1 relevance to all modes + * @type {CompilerExt} + */ +function compileRelevance(mode, _parent) { + // eslint-disable-next-line no-undefined + if (mode.relevance === undefined) mode.relevance = 1; +} + +// allow beforeMatch to act as a "qualifier" for the match +// the full match begin must be [beforeMatch][begin] +const beforeMatchExt = (mode, parent) => { + if (!mode.beforeMatch) return; + // starts conflicts with endsParent which we need to make sure the child + // rule is not matched multiple times + if (mode.starts) throw new Error("beforeMatch cannot be used with starts"); + + const originalMode = Object.assign({}, mode); + Object.keys(mode).forEach((key) => { delete mode[key]; }); + + mode.keywords = originalMode.keywords; + mode.begin = concat(originalMode.beforeMatch, lookahead(originalMode.begin)); + mode.starts = { + relevance: 0, + contains: [ + Object.assign(originalMode, { endsParent: true }) + ] + }; + mode.relevance = 0; + + delete originalMode.beforeMatch; +}; + +// keywords that should have no default relevance value +const COMMON_KEYWORDS = [ + 'of', + 'and', + 'for', + 'in', + 'not', + 'or', + 'if', + 'then', + 'parent', // common variable name + 'list', // common variable name + 'value' // common variable name +]; + +const DEFAULT_KEYWORD_SCOPE = "keyword"; + +/** + * Given raw keywords from a language definition, compile them. + * + * @param {string | Record | Array} rawKeywords + * @param {boolean} caseInsensitive + */ +function compileKeywords(rawKeywords, caseInsensitive, scopeName = DEFAULT_KEYWORD_SCOPE) { + /** @type {import("highlight.js/private").KeywordDict} */ + const compiledKeywords = Object.create(null); + + // input can be a string of keywords, an array of keywords, or a object with + // named keys representing scopeName (which can then point to a string or array) + if (typeof rawKeywords === 'string') { + compileList(scopeName, rawKeywords.split(" ")); + } else if (Array.isArray(rawKeywords)) { + compileList(scopeName, rawKeywords); + } else { + Object.keys(rawKeywords).forEach(function(scopeName) { + // collapse all our objects back into the parent object + Object.assign( + compiledKeywords, + compileKeywords(rawKeywords[scopeName], caseInsensitive, scopeName) + ); + }); + } + return compiledKeywords; + + // --- + + /** + * Compiles an individual list of keywords + * + * Ex: "for if when while|5" + * + * @param {string} scopeName + * @param {Array} keywordList + */ + function compileList(scopeName, keywordList) { + if (caseInsensitive) { + keywordList = keywordList.map(x => x.toLowerCase()); + } + keywordList.forEach(function(keyword) { + const pair = keyword.split('|'); + compiledKeywords[pair[0]] = [scopeName, scoreForKeyword(pair[0], pair[1])]; + }); + } +} + +/** + * Returns the proper score for a given keyword + * + * Also takes into account comment keywords, which will be scored 0 UNLESS + * another score has been manually assigned. + * @param {string} keyword + * @param {string} [providedScore] + */ +function scoreForKeyword(keyword, providedScore) { + // manual scores always win over common keywords + // so you can force a score of 1 if you really insist + if (providedScore) { + return Number(providedScore); + } + + return commonKeyword(keyword) ? 0 : 1; +} + +/** + * Determines if a given keyword is common or not + * + * @param {string} keyword */ +function commonKeyword(keyword) { + return COMMON_KEYWORDS.includes(keyword.toLowerCase()); +} + +/* + +For the reasoning behind this please see: +https://github.com/highlightjs/highlight.js/issues/2880#issuecomment-747275419 + +*/ + +/** + * @type {Record} + */ +const seenDeprecations = {}; + +/** + * @param {string} message + */ +const error = (message) => { + console.error(message); +}; + +/** + * @param {string} message + * @param {any} args + */ +const warn = (message, ...args) => { + console.log(`WARN: ${message}`, ...args); +}; + +/** + * @param {string} version + * @param {string} message + */ +const deprecated = (version, message) => { + if (seenDeprecations[`${version}/${message}`]) return; + + console.log(`Deprecated as of ${version}. ${message}`); + seenDeprecations[`${version}/${message}`] = true; +}; + +/* eslint-disable no-throw-literal */ + +/** +@typedef {import('highlight.js').CompiledMode} CompiledMode +*/ + +const MultiClassError = new Error(); + +/** + * Renumbers labeled scope names to account for additional inner match + * groups that otherwise would break everything. + * + * Lets say we 3 match scopes: + * + * { 1 => ..., 2 => ..., 3 => ... } + * + * So what we need is a clean match like this: + * + * (a)(b)(c) => [ "a", "b", "c" ] + * + * But this falls apart with inner match groups: + * + * (a)(((b)))(c) => ["a", "b", "b", "b", "c" ] + * + * Our scopes are now "out of alignment" and we're repeating `b` 3 times. + * What needs to happen is the numbers are remapped: + * + * { 1 => ..., 2 => ..., 5 => ... } + * + * We also need to know that the ONLY groups that should be output + * are 1, 2, and 5. This function handles this behavior. + * + * @param {CompiledMode} mode + * @param {Array} regexes + * @param {{key: "beginScope"|"endScope"}} opts + */ +function remapScopeNames(mode, regexes, { key }) { + let offset = 0; + const scopeNames = mode[key]; + /** @type Record */ + const emit = {}; + /** @type Record */ + const positions = {}; + + for (let i = 1; i <= regexes.length; i++) { + positions[i + offset] = scopeNames[i]; + emit[i + offset] = true; + offset += countMatchGroups(regexes[i - 1]); + } + // we use _emit to keep track of which match groups are "top-level" to avoid double + // output from inside match groups + mode[key] = positions; + mode[key]._emit = emit; + mode[key]._multi = true; +} + +/** + * @param {CompiledMode} mode + */ +function beginMultiClass(mode) { + if (!Array.isArray(mode.begin)) return; + + if (mode.skip || mode.excludeBegin || mode.returnBegin) { + error("skip, excludeBegin, returnBegin not compatible with beginScope: {}"); + throw MultiClassError; + } + + if (typeof mode.beginScope !== "object" || mode.beginScope === null) { + error("beginScope must be object"); + throw MultiClassError; + } + + remapScopeNames(mode, mode.begin, { key: "beginScope" }); + mode.begin = _rewriteBackreferences(mode.begin, { joinWith: "" }); +} + +/** + * @param {CompiledMode} mode + */ +function endMultiClass(mode) { + if (!Array.isArray(mode.end)) return; + + if (mode.skip || mode.excludeEnd || mode.returnEnd) { + error("skip, excludeEnd, returnEnd not compatible with endScope: {}"); + throw MultiClassError; + } + + if (typeof mode.endScope !== "object" || mode.endScope === null) { + error("endScope must be object"); + throw MultiClassError; + } + + remapScopeNames(mode, mode.end, { key: "endScope" }); + mode.end = _rewriteBackreferences(mode.end, { joinWith: "" }); +} + +/** + * this exists only to allow `scope: {}` to be used beside `match:` + * Otherwise `beginScope` would necessary and that would look weird + + { + match: [ /def/, /\w+/ ] + scope: { 1: "keyword" , 2: "title" } + } + + * @param {CompiledMode} mode + */ +function scopeSugar(mode) { + if (mode.scope && typeof mode.scope === "object" && mode.scope !== null) { + mode.beginScope = mode.scope; + delete mode.scope; + } +} + +/** + * @param {CompiledMode} mode + */ +function MultiClass(mode) { + scopeSugar(mode); + + if (typeof mode.beginScope === "string") { + mode.beginScope = { _wrap: mode.beginScope }; + } + if (typeof mode.endScope === "string") { + mode.endScope = { _wrap: mode.endScope }; + } + + beginMultiClass(mode); + endMultiClass(mode); +} + +/** +@typedef {import('highlight.js').Mode} Mode +@typedef {import('highlight.js').CompiledMode} CompiledMode +@typedef {import('highlight.js').Language} Language +@typedef {import('highlight.js').HLJSPlugin} HLJSPlugin +@typedef {import('highlight.js').CompiledLanguage} CompiledLanguage +*/ + +// compilation + +/** + * Compiles a language definition result + * + * Given the raw result of a language definition (Language), compiles this so + * that it is ready for highlighting code. + * @param {Language} language + * @returns {CompiledLanguage} + */ +function compileLanguage(language) { + /** + * Builds a regex with the case sensitivity of the current language + * + * @param {RegExp | string} value + * @param {boolean} [global] + */ + function langRe(value, global) { + return new RegExp( + source(value), + 'm' + + (language.case_insensitive ? 'i' : '') + + (language.unicodeRegex ? 'u' : '') + + (global ? 'g' : '') + ); + } + + /** + Stores multiple regular expressions and allows you to quickly search for + them all in a string simultaneously - returning the first match. It does + this by creating a huge (a|b|c) regex - each individual item wrapped with () + and joined by `|` - using match groups to track position. When a match is + found checking which position in the array has content allows us to figure + out which of the original regexes / match groups triggered the match. + + The match object itself (the result of `Regex.exec`) is returned but also + enhanced by merging in any meta-data that was registered with the regex. + This is how we keep track of which mode matched, and what type of rule + (`illegal`, `begin`, end, etc). + */ + class MultiRegex { + constructor() { + this.matchIndexes = {}; + // @ts-ignore + this.regexes = []; + this.matchAt = 1; + this.position = 0; + } + + // @ts-ignore + addRule(re, opts) { + opts.position = this.position++; + // @ts-ignore + this.matchIndexes[this.matchAt] = opts; + this.regexes.push([opts, re]); + this.matchAt += countMatchGroups(re) + 1; + } + + compile() { + if (this.regexes.length === 0) { + // avoids the need to check length every time exec is called + // @ts-ignore + this.exec = () => null; + } + const terminators = this.regexes.map(el => el[1]); + this.matcherRe = langRe(_rewriteBackreferences(terminators, { joinWith: '|' }), true); + this.lastIndex = 0; + } + + /** @param {string} s */ + exec(s) { + this.matcherRe.lastIndex = this.lastIndex; + const match = this.matcherRe.exec(s); + if (!match) { return null; } + + // eslint-disable-next-line no-undefined + const i = match.findIndex((el, i) => i > 0 && el !== undefined); + // @ts-ignore + const matchData = this.matchIndexes[i]; + // trim off any earlier non-relevant match groups (ie, the other regex + // match groups that make up the multi-matcher) + match.splice(0, i); + + return Object.assign(match, matchData); + } + } + + /* + Created to solve the key deficiently with MultiRegex - there is no way to + test for multiple matches at a single location. Why would we need to do + that? In the future a more dynamic engine will allow certain matches to be + ignored. An example: if we matched say the 3rd regex in a large group but + decided to ignore it - we'd need to started testing again at the 4th + regex... but MultiRegex itself gives us no real way to do that. + + So what this class creates MultiRegexs on the fly for whatever search + position they are needed. + + NOTE: These additional MultiRegex objects are created dynamically. For most + grammars most of the time we will never actually need anything more than the + first MultiRegex - so this shouldn't have too much overhead. + + Say this is our search group, and we match regex3, but wish to ignore it. + + regex1 | regex2 | regex3 | regex4 | regex5 ' ie, startAt = 0 + + What we need is a new MultiRegex that only includes the remaining + possibilities: + + regex4 | regex5 ' ie, startAt = 3 + + This class wraps all that complexity up in a simple API... `startAt` decides + where in the array of expressions to start doing the matching. It + auto-increments, so if a match is found at position 2, then startAt will be + set to 3. If the end is reached startAt will return to 0. + + MOST of the time the parser will be setting startAt manually to 0. + */ + class ResumableMultiRegex { + constructor() { + // @ts-ignore + this.rules = []; + // @ts-ignore + this.multiRegexes = []; + this.count = 0; + + this.lastIndex = 0; + this.regexIndex = 0; + } + + // @ts-ignore + getMatcher(index) { + if (this.multiRegexes[index]) return this.multiRegexes[index]; + + const matcher = new MultiRegex(); + this.rules.slice(index).forEach(([re, opts]) => matcher.addRule(re, opts)); + matcher.compile(); + this.multiRegexes[index] = matcher; + return matcher; + } + + resumingScanAtSamePosition() { + return this.regexIndex !== 0; + } + + considerAll() { + this.regexIndex = 0; + } + + // @ts-ignore + addRule(re, opts) { + this.rules.push([re, opts]); + if (opts.type === "begin") this.count++; + } + + /** @param {string} s */ + exec(s) { + const m = this.getMatcher(this.regexIndex); + m.lastIndex = this.lastIndex; + let result = m.exec(s); + + // The following is because we have no easy way to say "resume scanning at the + // existing position but also skip the current rule ONLY". What happens is + // all prior rules are also skipped which can result in matching the wrong + // thing. Example of matching "booger": + + // our matcher is [string, "booger", number] + // + // ....booger.... + + // if "booger" is ignored then we'd really need a regex to scan from the + // SAME position for only: [string, number] but ignoring "booger" (if it + // was the first match), a simple resume would scan ahead who knows how + // far looking only for "number", ignoring potential string matches (or + // future "booger" matches that might be valid.) + + // So what we do: We execute two matchers, one resuming at the same + // position, but the second full matcher starting at the position after: + + // /--- resume first regex match here (for [number]) + // |/---- full match here for [string, "booger", number] + // vv + // ....booger.... + + // Which ever results in a match first is then used. So this 3-4 step + // process essentially allows us to say "match at this position, excluding + // a prior rule that was ignored". + // + // 1. Match "booger" first, ignore. Also proves that [string] does non match. + // 2. Resume matching for [number] + // 3. Match at index + 1 for [string, "booger", number] + // 4. If #2 and #3 result in matches, which came first? + if (this.resumingScanAtSamePosition()) { + if (result && result.index === this.lastIndex) ; else { // use the second matcher result + const m2 = this.getMatcher(0); + m2.lastIndex = this.lastIndex + 1; + result = m2.exec(s); + } + } + + if (result) { + this.regexIndex += result.position + 1; + if (this.regexIndex === this.count) { + // wrap-around to considering all matches again + this.considerAll(); + } + } + + return result; + } + } + + /** + * Given a mode, builds a huge ResumableMultiRegex that can be used to walk + * the content and find matches. + * + * @param {CompiledMode} mode + * @returns {ResumableMultiRegex} + */ + function buildModeRegex(mode) { + const mm = new ResumableMultiRegex(); + + mode.contains.forEach(term => mm.addRule(term.begin, { rule: term, type: "begin" })); + + if (mode.terminatorEnd) { + mm.addRule(mode.terminatorEnd, { type: "end" }); + } + if (mode.illegal) { + mm.addRule(mode.illegal, { type: "illegal" }); + } + + return mm; + } + + /** skip vs abort vs ignore + * + * @skip - The mode is still entered and exited normally (and contains rules apply), + * but all content is held and added to the parent buffer rather than being + * output when the mode ends. Mostly used with `sublanguage` to build up + * a single large buffer than can be parsed by sublanguage. + * + * - The mode begin ands ends normally. + * - Content matched is added to the parent mode buffer. + * - The parser cursor is moved forward normally. + * + * @abort - A hack placeholder until we have ignore. Aborts the mode (as if it + * never matched) but DOES NOT continue to match subsequent `contains` + * modes. Abort is bad/suboptimal because it can result in modes + * farther down not getting applied because an earlier rule eats the + * content but then aborts. + * + * - The mode does not begin. + * - Content matched by `begin` is added to the mode buffer. + * - The parser cursor is moved forward accordingly. + * + * @ignore - Ignores the mode (as if it never matched) and continues to match any + * subsequent `contains` modes. Ignore isn't technically possible with + * the current parser implementation. + * + * - The mode does not begin. + * - Content matched by `begin` is ignored. + * - The parser cursor is not moved forward. + */ + + /** + * Compiles an individual mode + * + * This can raise an error if the mode contains certain detectable known logic + * issues. + * @param {Mode} mode + * @param {CompiledMode | null} [parent] + * @returns {CompiledMode | never} + */ + function compileMode(mode, parent) { + const cmode = /** @type CompiledMode */ (mode); + if (mode.isCompiled) return cmode; + + [ + scopeClassName, + // do this early so compiler extensions generally don't have to worry about + // the distinction between match/begin + compileMatch, + MultiClass, + beforeMatchExt + ].forEach(ext => ext(mode, parent)); + + language.compilerExtensions.forEach(ext => ext(mode, parent)); + + // __beforeBegin is considered private API, internal use only + mode.__beforeBegin = null; + + [ + beginKeywords, + // do this later so compiler extensions that come earlier have access to the + // raw array if they wanted to perhaps manipulate it, etc. + compileIllegal, + // default to 1 relevance if not specified + compileRelevance + ].forEach(ext => ext(mode, parent)); + + mode.isCompiled = true; + + let keywordPattern = null; + if (typeof mode.keywords === "object" && mode.keywords.$pattern) { + // we need a copy because keywords might be compiled multiple times + // so we can't go deleting $pattern from the original on the first + // pass + mode.keywords = Object.assign({}, mode.keywords); + keywordPattern = mode.keywords.$pattern; + delete mode.keywords.$pattern; + } + keywordPattern = keywordPattern || /\w+/; + + if (mode.keywords) { + mode.keywords = compileKeywords(mode.keywords, language.case_insensitive); + } + + cmode.keywordPatternRe = langRe(keywordPattern, true); + + if (parent) { + if (!mode.begin) mode.begin = /\B|\b/; + cmode.beginRe = langRe(cmode.begin); + if (!mode.end && !mode.endsWithParent) mode.end = /\B|\b/; + if (mode.end) cmode.endRe = langRe(cmode.end); + cmode.terminatorEnd = source(cmode.end) || ''; + if (mode.endsWithParent && parent.terminatorEnd) { + cmode.terminatorEnd += (mode.end ? '|' : '') + parent.terminatorEnd; + } + } + if (mode.illegal) cmode.illegalRe = langRe(/** @type {RegExp | string} */ (mode.illegal)); + if (!mode.contains) mode.contains = []; + + mode.contains = [].concat(...mode.contains.map(function(c) { + return expandOrCloneMode(c === 'self' ? mode : c); + })); + mode.contains.forEach(function(c) { compileMode(/** @type Mode */ (c), cmode); }); + + if (mode.starts) { + compileMode(mode.starts, parent); + } + + cmode.matcher = buildModeRegex(cmode); + return cmode; + } + + if (!language.compilerExtensions) language.compilerExtensions = []; + + // self is not valid at the top-level + if (language.contains && language.contains.includes('self')) { + throw new Error("ERR: contains `self` is not supported at the top-level of a language. See documentation."); + } + + // we need a null object, which inherit will guarantee + language.classNameAliases = inherit$1(language.classNameAliases || {}); + + return compileMode(/** @type Mode */ (language)); +} + +/** + * Determines if a mode has a dependency on it's parent or not + * + * If a mode does have a parent dependency then often we need to clone it if + * it's used in multiple places so that each copy points to the correct parent, + * where-as modes without a parent can often safely be re-used at the bottom of + * a mode chain. + * + * @param {Mode | null} mode + * @returns {boolean} - is there a dependency on the parent? + * */ +function dependencyOnParent(mode) { + if (!mode) return false; + + return mode.endsWithParent || dependencyOnParent(mode.starts); +} + +/** + * Expands a mode or clones it if necessary + * + * This is necessary for modes with parental dependenceis (see notes on + * `dependencyOnParent`) and for nodes that have `variants` - which must then be + * exploded into their own individual modes at compile time. + * + * @param {Mode} mode + * @returns {Mode | Mode[]} + * */ +function expandOrCloneMode(mode) { + if (mode.variants && !mode.cachedVariants) { + mode.cachedVariants = mode.variants.map(function(variant) { + return inherit$1(mode, { variants: null }, variant); + }); + } + + // EXPAND + // if we have variants then essentially "replace" the mode with the variants + // this happens in compileMode, where this function is called from + if (mode.cachedVariants) { + return mode.cachedVariants; + } + + // CLONE + // if we have dependencies on parents then we need a unique + // instance of ourselves, so we can be reused with many + // different parents without issue + if (dependencyOnParent(mode)) { + return inherit$1(mode, { starts: mode.starts ? inherit$1(mode.starts) : null }); + } + + if (Object.isFrozen(mode)) { + return inherit$1(mode); + } + + // no special dependency issues, just return ourselves + return mode; +} + +var version = "11.9.0"; + +class HTMLInjectionError extends Error { + constructor(reason, html) { + super(reason); + this.name = "HTMLInjectionError"; + this.html = html; + } +} + +/* +Syntax highlighting with language autodetection. +https://highlightjs.org/ +*/ + + + +/** +@typedef {import('highlight.js').Mode} Mode +@typedef {import('highlight.js').CompiledMode} CompiledMode +@typedef {import('highlight.js').CompiledScope} CompiledScope +@typedef {import('highlight.js').Language} Language +@typedef {import('highlight.js').HLJSApi} HLJSApi +@typedef {import('highlight.js').HLJSPlugin} HLJSPlugin +@typedef {import('highlight.js').PluginEvent} PluginEvent +@typedef {import('highlight.js').HLJSOptions} HLJSOptions +@typedef {import('highlight.js').LanguageFn} LanguageFn +@typedef {import('highlight.js').HighlightedHTMLElement} HighlightedHTMLElement +@typedef {import('highlight.js').BeforeHighlightContext} BeforeHighlightContext +@typedef {import('highlight.js/private').MatchType} MatchType +@typedef {import('highlight.js/private').KeywordData} KeywordData +@typedef {import('highlight.js/private').EnhancedMatch} EnhancedMatch +@typedef {import('highlight.js/private').AnnotatedError} AnnotatedError +@typedef {import('highlight.js').AutoHighlightResult} AutoHighlightResult +@typedef {import('highlight.js').HighlightOptions} HighlightOptions +@typedef {import('highlight.js').HighlightResult} HighlightResult +*/ + + +const escape = escapeHTML; +const inherit = inherit$1; +const NO_MATCH = Symbol("nomatch"); +const MAX_KEYWORD_HITS = 7; + +/** + * @param {any} hljs - object that is extended (legacy) + * @returns {HLJSApi} + */ +const HLJS = function(hljs) { + // Global internal variables used within the highlight.js library. + /** @type {Record} */ + const languages = Object.create(null); + /** @type {Record} */ + const aliases = Object.create(null); + /** @type {HLJSPlugin[]} */ + const plugins = []; + + // safe/production mode - swallows more errors, tries to keep running + // even if a single syntax or parse hits a fatal error + let SAFE_MODE = true; + const LANGUAGE_NOT_FOUND = "Could not find the language '{}', did you forget to load/include a language module?"; + /** @type {Language} */ + const PLAINTEXT_LANGUAGE = { disableAutodetect: true, name: 'Plain text', contains: [] }; + + // Global options used when within external APIs. This is modified when + // calling the `hljs.configure` function. + /** @type HLJSOptions */ + let options = { + ignoreUnescapedHTML: false, + throwUnescapedHTML: false, + noHighlightRe: /^(no-?highlight)$/i, + languageDetectRe: /\blang(?:uage)?-([\w-]+)\b/i, + classPrefix: 'hljs-', + cssSelector: 'pre code', + languages: null, + // beta configuration options, subject to change, welcome to discuss + // https://github.com/highlightjs/highlight.js/issues/1086 + __emitter: TokenTreeEmitter + }; + + /* Utility functions */ + + /** + * Tests a language name to see if highlighting should be skipped + * @param {string} languageName + */ + function shouldNotHighlight(languageName) { + return options.noHighlightRe.test(languageName); + } + + /** + * @param {HighlightedHTMLElement} block - the HTML element to determine language for + */ + function blockLanguage(block) { + let classes = block.className + ' '; + + classes += block.parentNode ? block.parentNode.className : ''; + + // language-* takes precedence over non-prefixed class names. + const match = options.languageDetectRe.exec(classes); + if (match) { + const language = getLanguage(match[1]); + if (!language) { + warn(LANGUAGE_NOT_FOUND.replace("{}", match[1])); + warn("Falling back to no-highlight mode for this block.", block); + } + return language ? match[1] : 'no-highlight'; + } + + return classes + .split(/\s+/) + .find((_class) => shouldNotHighlight(_class) || getLanguage(_class)); + } + + /** + * Core highlighting function. + * + * OLD API + * highlight(lang, code, ignoreIllegals, continuation) + * + * NEW API + * highlight(code, {lang, ignoreIllegals}) + * + * @param {string} codeOrLanguageName - the language to use for highlighting + * @param {string | HighlightOptions} optionsOrCode - the code to highlight + * @param {boolean} [ignoreIllegals] - whether to ignore illegal matches, default is to bail + * + * @returns {HighlightResult} Result - an object that represents the result + * @property {string} language - the language name + * @property {number} relevance - the relevance score + * @property {string} value - the highlighted HTML code + * @property {string} code - the original raw code + * @property {CompiledMode} top - top of the current mode stack + * @property {boolean} illegal - indicates whether any illegal matches were found + */ + function highlight(codeOrLanguageName, optionsOrCode, ignoreIllegals) { + let code = ""; + let languageName = ""; + if (typeof optionsOrCode === "object") { + code = codeOrLanguageName; + ignoreIllegals = optionsOrCode.ignoreIllegals; + languageName = optionsOrCode.language; + } else { + // old API + deprecated("10.7.0", "highlight(lang, code, ...args) has been deprecated."); + deprecated("10.7.0", "Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"); + languageName = codeOrLanguageName; + code = optionsOrCode; + } + + // https://github.com/highlightjs/highlight.js/issues/3149 + // eslint-disable-next-line no-undefined + if (ignoreIllegals === undefined) { ignoreIllegals = true; } + + /** @type {BeforeHighlightContext} */ + const context = { + code, + language: languageName + }; + // the plugin can change the desired language or the code to be highlighted + // just be changing the object it was passed + fire("before:highlight", context); + + // a before plugin can usurp the result completely by providing it's own + // in which case we don't even need to call highlight + const result = context.result + ? context.result + : _highlight(context.language, context.code, ignoreIllegals); + + result.code = context.code; + // the plugin can change anything in result to suite it + fire("after:highlight", result); + + return result; + } + + /** + * private highlight that's used internally and does not fire callbacks + * + * @param {string} languageName - the language to use for highlighting + * @param {string} codeToHighlight - the code to highlight + * @param {boolean?} [ignoreIllegals] - whether to ignore illegal matches, default is to bail + * @param {CompiledMode?} [continuation] - current continuation mode, if any + * @returns {HighlightResult} - result of the highlight operation + */ + function _highlight(languageName, codeToHighlight, ignoreIllegals, continuation) { + const keywordHits = Object.create(null); + + /** + * Return keyword data if a match is a keyword + * @param {CompiledMode} mode - current mode + * @param {string} matchText - the textual match + * @returns {KeywordData | false} + */ + function keywordData(mode, matchText) { + return mode.keywords[matchText]; + } + + function processKeywords() { + if (!top.keywords) { + emitter.addText(modeBuffer); + return; + } + + let lastIndex = 0; + top.keywordPatternRe.lastIndex = 0; + let match = top.keywordPatternRe.exec(modeBuffer); + let buf = ""; + + while (match) { + buf += modeBuffer.substring(lastIndex, match.index); + const word = language.case_insensitive ? match[0].toLowerCase() : match[0]; + const data = keywordData(top, word); + if (data) { + const [kind, keywordRelevance] = data; + emitter.addText(buf); + buf = ""; + + keywordHits[word] = (keywordHits[word] || 0) + 1; + if (keywordHits[word] <= MAX_KEYWORD_HITS) relevance += keywordRelevance; + if (kind.startsWith("_")) { + // _ implied for relevance only, do not highlight + // by applying a class name + buf += match[0]; + } else { + const cssClass = language.classNameAliases[kind] || kind; + emitKeyword(match[0], cssClass); + } + } else { + buf += match[0]; + } + lastIndex = top.keywordPatternRe.lastIndex; + match = top.keywordPatternRe.exec(modeBuffer); + } + buf += modeBuffer.substring(lastIndex); + emitter.addText(buf); + } + + function processSubLanguage() { + if (modeBuffer === "") return; + /** @type HighlightResult */ + let result = null; + + if (typeof top.subLanguage === 'string') { + if (!languages[top.subLanguage]) { + emitter.addText(modeBuffer); + return; + } + result = _highlight(top.subLanguage, modeBuffer, true, continuations[top.subLanguage]); + continuations[top.subLanguage] = /** @type {CompiledMode} */ (result._top); + } else { + result = highlightAuto(modeBuffer, top.subLanguage.length ? top.subLanguage : null); + } + + // Counting embedded language score towards the host language may be disabled + // with zeroing the containing mode relevance. Use case in point is Markdown that + // allows XML everywhere and makes every XML snippet to have a much larger Markdown + // score. + if (top.relevance > 0) { + relevance += result.relevance; + } + emitter.__addSublanguage(result._emitter, result.language); + } + + function processBuffer() { + if (top.subLanguage != null) { + processSubLanguage(); + } else { + processKeywords(); + } + modeBuffer = ''; + } + + /** + * @param {string} text + * @param {string} scope + */ + function emitKeyword(keyword, scope) { + if (keyword === "") return; + + emitter.startScope(scope); + emitter.addText(keyword); + emitter.endScope(); + } + + /** + * @param {CompiledScope} scope + * @param {RegExpMatchArray} match + */ + function emitMultiClass(scope, match) { + let i = 1; + const max = match.length - 1; + while (i <= max) { + if (!scope._emit[i]) { i++; continue; } + const klass = language.classNameAliases[scope[i]] || scope[i]; + const text = match[i]; + if (klass) { + emitKeyword(text, klass); + } else { + modeBuffer = text; + processKeywords(); + modeBuffer = ""; + } + i++; + } + } + + /** + * @param {CompiledMode} mode - new mode to start + * @param {RegExpMatchArray} match + */ + function startNewMode(mode, match) { + if (mode.scope && typeof mode.scope === "string") { + emitter.openNode(language.classNameAliases[mode.scope] || mode.scope); + } + if (mode.beginScope) { + // beginScope just wraps the begin match itself in a scope + if (mode.beginScope._wrap) { + emitKeyword(modeBuffer, language.classNameAliases[mode.beginScope._wrap] || mode.beginScope._wrap); + modeBuffer = ""; + } else if (mode.beginScope._multi) { + // at this point modeBuffer should just be the match + emitMultiClass(mode.beginScope, match); + modeBuffer = ""; + } + } + + top = Object.create(mode, { parent: { value: top } }); + return top; + } + + /** + * @param {CompiledMode } mode - the mode to potentially end + * @param {RegExpMatchArray} match - the latest match + * @param {string} matchPlusRemainder - match plus remainder of content + * @returns {CompiledMode | void} - the next mode, or if void continue on in current mode + */ + function endOfMode(mode, match, matchPlusRemainder) { + let matched = startsWith(mode.endRe, matchPlusRemainder); + + if (matched) { + if (mode["on:end"]) { + const resp = new Response(mode); + mode["on:end"](match, resp); + if (resp.isMatchIgnored) matched = false; + } + + if (matched) { + while (mode.endsParent && mode.parent) { + mode = mode.parent; + } + return mode; + } + } + // even if on:end fires an `ignore` it's still possible + // that we might trigger the end node because of a parent mode + if (mode.endsWithParent) { + return endOfMode(mode.parent, match, matchPlusRemainder); + } + } + + /** + * Handle matching but then ignoring a sequence of text + * + * @param {string} lexeme - string containing full match text + */ + function doIgnore(lexeme) { + if (top.matcher.regexIndex === 0) { + // no more regexes to potentially match here, so we move the cursor forward one + // space + modeBuffer += lexeme[0]; + return 1; + } else { + // no need to move the cursor, we still have additional regexes to try and + // match at this very spot + resumeScanAtSamePosition = true; + return 0; + } + } + + /** + * Handle the start of a new potential mode match + * + * @param {EnhancedMatch} match - the current match + * @returns {number} how far to advance the parse cursor + */ + function doBeginMatch(match) { + const lexeme = match[0]; + const newMode = match.rule; + + const resp = new Response(newMode); + // first internal before callbacks, then the public ones + const beforeCallbacks = [newMode.__beforeBegin, newMode["on:begin"]]; + for (const cb of beforeCallbacks) { + if (!cb) continue; + cb(match, resp); + if (resp.isMatchIgnored) return doIgnore(lexeme); + } + + if (newMode.skip) { + modeBuffer += lexeme; + } else { + if (newMode.excludeBegin) { + modeBuffer += lexeme; + } + processBuffer(); + if (!newMode.returnBegin && !newMode.excludeBegin) { + modeBuffer = lexeme; + } + } + startNewMode(newMode, match); + return newMode.returnBegin ? 0 : lexeme.length; + } + + /** + * Handle the potential end of mode + * + * @param {RegExpMatchArray} match - the current match + */ + function doEndMatch(match) { + const lexeme = match[0]; + const matchPlusRemainder = codeToHighlight.substring(match.index); + + const endMode = endOfMode(top, match, matchPlusRemainder); + if (!endMode) { return NO_MATCH; } + + const origin = top; + if (top.endScope && top.endScope._wrap) { + processBuffer(); + emitKeyword(lexeme, top.endScope._wrap); + } else if (top.endScope && top.endScope._multi) { + processBuffer(); + emitMultiClass(top.endScope, match); + } else if (origin.skip) { + modeBuffer += lexeme; + } else { + if (!(origin.returnEnd || origin.excludeEnd)) { + modeBuffer += lexeme; + } + processBuffer(); + if (origin.excludeEnd) { + modeBuffer = lexeme; + } + } + do { + if (top.scope) { + emitter.closeNode(); + } + if (!top.skip && !top.subLanguage) { + relevance += top.relevance; + } + top = top.parent; + } while (top !== endMode.parent); + if (endMode.starts) { + startNewMode(endMode.starts, match); + } + return origin.returnEnd ? 0 : lexeme.length; + } + + function processContinuations() { + const list = []; + for (let current = top; current !== language; current = current.parent) { + if (current.scope) { + list.unshift(current.scope); + } + } + list.forEach(item => emitter.openNode(item)); + } + + /** @type {{type?: MatchType, index?: number, rule?: Mode}}} */ + let lastMatch = {}; + + /** + * Process an individual match + * + * @param {string} textBeforeMatch - text preceding the match (since the last match) + * @param {EnhancedMatch} [match] - the match itself + */ + function processLexeme(textBeforeMatch, match) { + const lexeme = match && match[0]; + + // add non-matched text to the current mode buffer + modeBuffer += textBeforeMatch; + + if (lexeme == null) { + processBuffer(); + return 0; + } + + // we've found a 0 width match and we're stuck, so we need to advance + // this happens when we have badly behaved rules that have optional matchers to the degree that + // sometimes they can end up matching nothing at all + // Ref: https://github.com/highlightjs/highlight.js/issues/2140 + if (lastMatch.type === "begin" && match.type === "end" && lastMatch.index === match.index && lexeme === "") { + // spit the "skipped" character that our regex choked on back into the output sequence + modeBuffer += codeToHighlight.slice(match.index, match.index + 1); + if (!SAFE_MODE) { + /** @type {AnnotatedError} */ + const err = new Error(`0 width match regex (${languageName})`); + err.languageName = languageName; + err.badRule = lastMatch.rule; + throw err; + } + return 1; + } + lastMatch = match; + + if (match.type === "begin") { + return doBeginMatch(match); + } else if (match.type === "illegal" && !ignoreIllegals) { + // illegal match, we do not continue processing + /** @type {AnnotatedError} */ + const err = new Error('Illegal lexeme "' + lexeme + '" for mode "' + (top.scope || '') + '"'); + err.mode = top; + throw err; + } else if (match.type === "end") { + const processed = doEndMatch(match); + if (processed !== NO_MATCH) { + return processed; + } + } + + // edge case for when illegal matches $ (end of line) which is technically + // a 0 width match but not a begin/end match so it's not caught by the + // first handler (when ignoreIllegals is true) + if (match.type === "illegal" && lexeme === "") { + // advance so we aren't stuck in an infinite loop + return 1; + } + + // infinite loops are BAD, this is a last ditch catch all. if we have a + // decent number of iterations yet our index (cursor position in our + // parsing) still 3x behind our index then something is very wrong + // so we bail + if (iterations > 100000 && iterations > match.index * 3) { + const err = new Error('potential infinite loop, way more iterations than matches'); + throw err; + } + + /* + Why might be find ourselves here? An potential end match that was + triggered but could not be completed. IE, `doEndMatch` returned NO_MATCH. + (this could be because a callback requests the match be ignored, etc) + + This causes no real harm other than stopping a few times too many. + */ + + modeBuffer += lexeme; + return lexeme.length; + } + + const language = getLanguage(languageName); + if (!language) { + error(LANGUAGE_NOT_FOUND.replace("{}", languageName)); + throw new Error('Unknown language: "' + languageName + '"'); + } + + const md = compileLanguage(language); + let result = ''; + /** @type {CompiledMode} */ + let top = continuation || md; + /** @type Record */ + const continuations = {}; // keep continuations for sub-languages + const emitter = new options.__emitter(options); + processContinuations(); + let modeBuffer = ''; + let relevance = 0; + let index = 0; + let iterations = 0; + let resumeScanAtSamePosition = false; + + try { + if (!language.__emitTokens) { + top.matcher.considerAll(); + + for (;;) { + iterations++; + if (resumeScanAtSamePosition) { + // only regexes not matched previously will now be + // considered for a potential match + resumeScanAtSamePosition = false; + } else { + top.matcher.considerAll(); + } + top.matcher.lastIndex = index; + + const match = top.matcher.exec(codeToHighlight); + // console.log("match", match[0], match.rule && match.rule.begin) + + if (!match) break; + + const beforeMatch = codeToHighlight.substring(index, match.index); + const processedCount = processLexeme(beforeMatch, match); + index = match.index + processedCount; + } + processLexeme(codeToHighlight.substring(index)); + } else { + language.__emitTokens(codeToHighlight, emitter); + } + + emitter.finalize(); + result = emitter.toHTML(); + + return { + language: languageName, + value: result, + relevance, + illegal: false, + _emitter: emitter, + _top: top + }; + } catch (err) { + if (err.message && err.message.includes('Illegal')) { + return { + language: languageName, + value: escape(codeToHighlight), + illegal: true, + relevance: 0, + _illegalBy: { + message: err.message, + index, + context: codeToHighlight.slice(index - 100, index + 100), + mode: err.mode, + resultSoFar: result + }, + _emitter: emitter + }; + } else if (SAFE_MODE) { + return { + language: languageName, + value: escape(codeToHighlight), + illegal: false, + relevance: 0, + errorRaised: err, + _emitter: emitter, + _top: top + }; + } else { + throw err; + } + } + } + + /** + * returns a valid highlight result, without actually doing any actual work, + * auto highlight starts with this and it's possible for small snippets that + * auto-detection may not find a better match + * @param {string} code + * @returns {HighlightResult} + */ + function justTextHighlightResult(code) { + const result = { + value: escape(code), + illegal: false, + relevance: 0, + _top: PLAINTEXT_LANGUAGE, + _emitter: new options.__emitter(options) + }; + result._emitter.addText(code); + return result; + } + + /** + Highlighting with language detection. Accepts a string with the code to + highlight. Returns an object with the following properties: + + - language (detected language) + - relevance (int) + - value (an HTML string with highlighting markup) + - secondBest (object with the same structure for second-best heuristically + detected language, may be absent) + + @param {string} code + @param {Array} [languageSubset] + @returns {AutoHighlightResult} + */ + function highlightAuto(code, languageSubset) { + languageSubset = languageSubset || options.languages || Object.keys(languages); + const plaintext = justTextHighlightResult(code); + + const results = languageSubset.filter(getLanguage).filter(autoDetection).map(name => + _highlight(name, code, false) + ); + results.unshift(plaintext); // plaintext is always an option + + const sorted = results.sort((a, b) => { + // sort base on relevance + if (a.relevance !== b.relevance) return b.relevance - a.relevance; + + // always award the tie to the base language + // ie if C++ and Arduino are tied, it's more likely to be C++ + if (a.language && b.language) { + if (getLanguage(a.language).supersetOf === b.language) { + return 1; + } else if (getLanguage(b.language).supersetOf === a.language) { + return -1; + } + } + + // otherwise say they are equal, which has the effect of sorting on + // relevance while preserving the original ordering - which is how ties + // have historically been settled, ie the language that comes first always + // wins in the case of a tie + return 0; + }); + + const [best, secondBest] = sorted; + + /** @type {AutoHighlightResult} */ + const result = best; + result.secondBest = secondBest; + + return result; + } + + /** + * Builds new class name for block given the language name + * + * @param {HTMLElement} element + * @param {string} [currentLang] + * @param {string} [resultLang] + */ + function updateClassName(element, currentLang, resultLang) { + const language = (currentLang && aliases[currentLang]) || resultLang; + + element.classList.add("hljs"); + element.classList.add(`language-${language}`); + } + + /** + * Applies highlighting to a DOM node containing code. + * + * @param {HighlightedHTMLElement} element - the HTML element to highlight + */ + function highlightElement(element) { + /** @type HTMLElement */ + let node = null; + const language = blockLanguage(element); + + if (shouldNotHighlight(language)) return; + + fire("before:highlightElement", + { el: element, language }); + + if (element.dataset.highlighted) { + console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.", element); + return; + } + + // we should be all text, no child nodes (unescaped HTML) - this is possibly + // an HTML injection attack - it's likely too late if this is already in + // production (the code has likely already done its damage by the time + // we're seeing it)... but we yell loudly about this so that hopefully it's + // more likely to be caught in development before making it to production + if (element.children.length > 0) { + if (!options.ignoreUnescapedHTML) { + console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."); + console.warn("https://github.com/highlightjs/highlight.js/wiki/security"); + console.warn("The element with unescaped HTML:"); + console.warn(element); + } + if (options.throwUnescapedHTML) { + const err = new HTMLInjectionError( + "One of your code blocks includes unescaped HTML.", + element.innerHTML + ); + throw err; + } + } + + node = element; + const text = node.textContent; + const result = language ? highlight(text, { language, ignoreIllegals: true }) : highlightAuto(text); + + element.innerHTML = result.value; + element.dataset.highlighted = "yes"; + updateClassName(element, language, result.language); + element.result = { + language: result.language, + // TODO: remove with version 11.0 + re: result.relevance, + relevance: result.relevance + }; + if (result.secondBest) { + element.secondBest = { + language: result.secondBest.language, + relevance: result.secondBest.relevance + }; + } + + fire("after:highlightElement", { el: element, result, text }); + } + + /** + * Updates highlight.js global options with the passed options + * + * @param {Partial} userOptions + */ + function configure(userOptions) { + options = inherit(options, userOptions); + } + + // TODO: remove v12, deprecated + const initHighlighting = () => { + highlightAll(); + deprecated("10.6.0", "initHighlighting() deprecated. Use highlightAll() now."); + }; + + // TODO: remove v12, deprecated + function initHighlightingOnLoad() { + highlightAll(); + deprecated("10.6.0", "initHighlightingOnLoad() deprecated. Use highlightAll() now."); + } + + let wantsHighlight = false; + + /** + * auto-highlights all pre>code elements on the page + */ + function highlightAll() { + // if we are called too early in the loading process + if (document.readyState === "loading") { + wantsHighlight = true; + return; + } + + const blocks = document.querySelectorAll(options.cssSelector); + blocks.forEach(highlightElement); + } + + function boot() { + // if a highlight was requested before DOM was loaded, do now + if (wantsHighlight) highlightAll(); + } + + // make sure we are in the browser environment + if (typeof window !== 'undefined' && window.addEventListener) { + window.addEventListener('DOMContentLoaded', boot, false); + } + + /** + * Register a language grammar module + * + * @param {string} languageName + * @param {LanguageFn} languageDefinition + */ + function registerLanguage(languageName, languageDefinition) { + let lang = null; + try { + lang = languageDefinition(hljs); + } catch (error$1) { + error("Language definition for '{}' could not be registered.".replace("{}", languageName)); + // hard or soft error + if (!SAFE_MODE) { throw error$1; } else { error(error$1); } + // languages that have serious errors are replaced with essentially a + // "plaintext" stand-in so that the code blocks will still get normal + // css classes applied to them - and one bad language won't break the + // entire highlighter + lang = PLAINTEXT_LANGUAGE; + } + // give it a temporary name if it doesn't have one in the meta-data + if (!lang.name) lang.name = languageName; + languages[languageName] = lang; + lang.rawDefinition = languageDefinition.bind(null, hljs); + + if (lang.aliases) { + registerAliases(lang.aliases, { languageName }); + } + } + + /** + * Remove a language grammar module + * + * @param {string} languageName + */ + function unregisterLanguage(languageName) { + delete languages[languageName]; + for (const alias of Object.keys(aliases)) { + if (aliases[alias] === languageName) { + delete aliases[alias]; + } + } + } + + /** + * @returns {string[]} List of language internal names + */ + function listLanguages() { + return Object.keys(languages); + } + + /** + * @param {string} name - name of the language to retrieve + * @returns {Language | undefined} + */ + function getLanguage(name) { + name = (name || '').toLowerCase(); + return languages[name] || languages[aliases[name]]; + } + + /** + * + * @param {string|string[]} aliasList - single alias or list of aliases + * @param {{languageName: string}} opts + */ + function registerAliases(aliasList, { languageName }) { + if (typeof aliasList === 'string') { + aliasList = [aliasList]; + } + aliasList.forEach(alias => { aliases[alias.toLowerCase()] = languageName; }); + } + + /** + * Determines if a given language has auto-detection enabled + * @param {string} name - name of the language + */ + function autoDetection(name) { + const lang = getLanguage(name); + return lang && !lang.disableAutodetect; + } + + /** + * Upgrades the old highlightBlock plugins to the new + * highlightElement API + * @param {HLJSPlugin} plugin + */ + function upgradePluginAPI(plugin) { + // TODO: remove with v12 + if (plugin["before:highlightBlock"] && !plugin["before:highlightElement"]) { + plugin["before:highlightElement"] = (data) => { + plugin["before:highlightBlock"]( + Object.assign({ block: data.el }, data) + ); + }; + } + if (plugin["after:highlightBlock"] && !plugin["after:highlightElement"]) { + plugin["after:highlightElement"] = (data) => { + plugin["after:highlightBlock"]( + Object.assign({ block: data.el }, data) + ); + }; + } + } + + /** + * @param {HLJSPlugin} plugin + */ + function addPlugin(plugin) { + upgradePluginAPI(plugin); + plugins.push(plugin); + } + + /** + * @param {HLJSPlugin} plugin + */ + function removePlugin(plugin) { + const index = plugins.indexOf(plugin); + if (index !== -1) { + plugins.splice(index, 1); + } + } + + /** + * + * @param {PluginEvent} event + * @param {any} args + */ + function fire(event, args) { + const cb = event; + plugins.forEach(function(plugin) { + if (plugin[cb]) { + plugin[cb](args); + } + }); + } + + /** + * DEPRECATED + * @param {HighlightedHTMLElement} el + */ + function deprecateHighlightBlock(el) { + deprecated("10.7.0", "highlightBlock will be removed entirely in v12.0"); + deprecated("10.7.0", "Please use highlightElement now."); + + return highlightElement(el); + } + + /* Interface definition */ + Object.assign(hljs, { + highlight, + highlightAuto, + highlightAll, + highlightElement, + // TODO: Remove with v12 API + highlightBlock: deprecateHighlightBlock, + configure, + initHighlighting, + initHighlightingOnLoad, + registerLanguage, + unregisterLanguage, + listLanguages, + getLanguage, + registerAliases, + autoDetection, + inherit, + addPlugin, + removePlugin + }); + + hljs.debugMode = function() { SAFE_MODE = false; }; + hljs.safeMode = function() { SAFE_MODE = true; }; + hljs.versionString = version; + + hljs.regex = { + concat: concat, + lookahead: lookahead, + either: either, + optional: optional, + anyNumberOfTimes: anyNumberOfTimes + }; + + for (const key in MODES) { + // @ts-ignore + if (typeof MODES[key] === "object") { + // @ts-ignore + deepFreeze(MODES[key]); + } + } + + // merge all the modes/regexes into our main object + Object.assign(hljs, MODES); + + return hljs; +}; + +// Other names for the variable may break build script +const highlight = HLJS({}); + +// returns a new instance of the highlighter to be used for extensions +// check https://github.com/wooorm/lowlight/issues/47 +highlight.newInstance = () => HLJS({}); + +export { highlight as default }; diff --git a/vendor/highlightjs/es/highlight.min.js b/vendor/highlightjs/es/highlight.min.js new file mode 100644 index 000000000..c6d4ae5cb --- /dev/null +++ b/vendor/highlightjs/es/highlight.min.js @@ -0,0 +1,307 @@ +/*! + Highlight.js v11.9.0 (git: b7ec4bfafc) + (c) 2006-2023 undefined and other contributors + License: BSD-3-Clause + */ +function e(t){return t instanceof Map?t.clear=t.delete=t.set=()=>{ +throw Error("map is read-only")}:t instanceof Set&&(t.add=t.clear=t.delete=()=>{ +throw Error("set is read-only") +}),Object.freeze(t),Object.getOwnPropertyNames(t).forEach((n=>{ +const i=t[n],s=typeof i;"object"!==s&&"function"!==s||Object.isFrozen(i)||e(i) +})),t}class t{constructor(e){ +void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1} +ignoreMatch(){this.isMatchIgnored=!0}}function n(e){ +return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'") +}function i(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t] +;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n}const s=e=>!!e.scope +;class r{constructor(e,t){ +this.buffer="",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){ +this.buffer+=n(e)}openNode(e){if(!s(e))return;const t=((e,{prefix:t})=>{ +if(e.startsWith("language:"))return e.replace("language:","language-") +;if(e.includes(".")){const n=e.split(".") +;return[`${t}${n.shift()}`,...n.map(((e,t)=>`${e}${"_".repeat(t+1)}`))].join(" ") +}return`${t}${e}`})(e.scope,{prefix:this.classPrefix});this.span(t)} +closeNode(e){s(e)&&(this.buffer+="")}value(){return this.buffer}span(e){ +this.buffer+=``}}const o=(e={})=>{const t={children:[]} +;return Object.assign(t,e),t};class a{constructor(){ +this.rootNode=o(),this.stack=[this.rootNode]}get top(){ +return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){ +this.top.children.push(e)}openNode(e){const t=o({scope:e}) +;this.add(t),this.stack.push(t)}closeNode(){ +if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){ +for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)} +walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){ +return"string"==typeof t?e.addText(t):t.children&&(e.openNode(t), +t.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){ +"string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{ +a._collapse(e)})))}}class c extends a{constructor(e){super(),this.options=e} +addText(e){""!==e&&this.add(e)}startScope(e){this.openNode(e)}endScope(){ +this.closeNode()}__addSublanguage(e,t){const n=e.root +;t&&(n.scope="language:"+t),this.add(n)}toHTML(){ +return new r(this,this.options).value()}finalize(){ +return this.closeAllNodes(),!0}}function l(e){ +return e?"string"==typeof e?e:e.source:null}function g(e){return h("(?=",e,")")} +function u(e){return h("(?:",e,")*")}function d(e){return h("(?:",e,")?")} +function h(...e){return e.map((e=>l(e))).join("")}function f(...e){const t=(e=>{ +const t=e[e.length-1] +;return"object"==typeof t&&t.constructor===Object?(e.splice(e.length-1,1),t):{} +})(e);return"("+(t.capture?"":"?:")+e.map((e=>l(e))).join("|")+")"} +function p(e){return RegExp(e.toString()+"|").exec("").length-1} +const b=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./ +;function m(e,{joinWith:t}){let n=0;return e.map((e=>{n+=1;const t=n +;let i=l(e),s="";for(;i.length>0;){const e=b.exec(i);if(!e){s+=i;break} +s+=i.substring(0,e.index), +i=i.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?s+="\\"+(Number(e[1])+t):(s+=e[0], +"("===e[0]&&n++)}return s})).map((e=>`(${e})`)).join(t)} +const E="[a-zA-Z]\\w*",x="[a-zA-Z_]\\w*",w="\\b\\d+(\\.\\d+)?",y="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",_="\\b(0b[01]+)",O={ +begin:"\\\\[\\s\\S]",relevance:0},k={scope:"string",begin:"'",end:"'", +illegal:"\\n",contains:[O]},v={scope:"string",begin:'"',end:'"',illegal:"\\n", +contains:[O]},N=(e,t,n={})=>{const s=i({scope:"comment",begin:e,end:t, +contains:[]},n);s.contains.push({scope:"doctag", +begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)", +end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0}) +;const r=f("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/) +;return s.contains.push({begin:h(/[ ]+/,"(",r,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),s +},S=N("//","$"),M=N("/\\*","\\*/"),R=N("#","$");var A=Object.freeze({ +__proto__:null,APOS_STRING_MODE:k,BACKSLASH_ESCAPE:O,BINARY_NUMBER_MODE:{ +scope:"number",begin:_,relevance:0},BINARY_NUMBER_RE:_,COMMENT:N, +C_BLOCK_COMMENT_MODE:M,C_LINE_COMMENT_MODE:S,C_NUMBER_MODE:{scope:"number", +begin:y,relevance:0},C_NUMBER_RE:y,END_SAME_AS_BEGIN:e=>Object.assign(e,{ +"on:begin":(e,t)=>{t.data._beginMatch=e[1]},"on:end":(e,t)=>{ +t.data._beginMatch!==e[1]&&t.ignoreMatch()}}),HASH_COMMENT_MODE:R,IDENT_RE:E, +MATCH_NOTHING_RE:/\b\B/,METHOD_GUARD:{begin:"\\.\\s*"+x,relevance:0}, +NUMBER_MODE:{scope:"number",begin:w,relevance:0},NUMBER_RE:w, +PHRASAL_WORDS_MODE:{ +begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ +},QUOTE_STRING_MODE:v,REGEXP_MODE:{scope:"regexp",begin:/\/(?=[^/\n]*\/)/, +end:/\/[gimuy]*/,contains:[O,{begin:/\[/,end:/\]/,relevance:0,contains:[O]}]}, +RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~", +SHEBANG:(e={})=>{const t=/^#![ ]*\// +;return e.binary&&(e.begin=h(t,/.*\b/,e.binary,/\b.*/)),i({scope:"meta",begin:t, +end:/$/,relevance:0,"on:begin":(e,t)=>{0!==e.index&&t.ignoreMatch()}},e)}, +TITLE_MODE:{scope:"title",begin:E,relevance:0},UNDERSCORE_IDENT_RE:x, +UNDERSCORE_TITLE_MODE:{scope:"title",begin:x,relevance:0}});function j(e,t){ +"."===e.input[e.index-1]&&t.ignoreMatch()}function I(e,t){ +void 0!==e.className&&(e.scope=e.className,delete e.className)}function T(e,t){ +t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)", +e.__beforeBegin=j,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords, +void 0===e.relevance&&(e.relevance=0))}function L(e,t){ +Array.isArray(e.illegal)&&(e.illegal=f(...e.illegal))}function B(e,t){ +if(e.match){ +if(e.begin||e.end)throw Error("begin & end are not supported with match") +;e.begin=e.match,delete e.match}}function P(e,t){ +void 0===e.relevance&&(e.relevance=1)}const D=(e,t)=>{if(!e.beforeMatch)return +;if(e.starts)throw Error("beforeMatch cannot be used with starts") +;const n=Object.assign({},e);Object.keys(e).forEach((t=>{delete e[t] +})),e.keywords=n.keywords,e.begin=h(n.beforeMatch,g(n.begin)),e.starts={ +relevance:0,contains:[Object.assign(n,{endsParent:!0})] +},e.relevance=0,delete n.beforeMatch +},H=["of","and","for","in","not","or","if","then","parent","list","value"],C="keyword" +;function $(e,t,n=C){const i=Object.create(null) +;return"string"==typeof e?s(n,e.split(" ")):Array.isArray(e)?s(n,e):Object.keys(e).forEach((n=>{ +Object.assign(i,$(e[n],t,n))})),i;function s(e,n){ +t&&(n=n.map((e=>e.toLowerCase()))),n.forEach((t=>{const n=t.split("|") +;i[n[0]]=[e,U(n[0],n[1])]}))}}function U(e,t){ +return t?Number(t):(e=>H.includes(e.toLowerCase()))(e)?0:1}const z={},W=e=>{ +console.error(e)},X=(e,...t)=>{console.log("WARN: "+e,...t)},G=(e,t)=>{ +z[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),z[`${e}/${t}`]=!0) +},K=Error();function F(e,t,{key:n}){let i=0;const s=e[n],r={},o={} +;for(let e=1;e<=t.length;e++)o[e+i]=s[e],r[e+i]=!0,i+=p(t[e-1]) +;e[n]=o,e[n]._emit=r,e[n]._multi=!0}function Z(e){(e=>{ +e.scope&&"object"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope, +delete e.scope)})(e),"string"==typeof e.beginScope&&(e.beginScope={ +_wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope +}),(e=>{if(Array.isArray(e.begin)){ +if(e.skip||e.excludeBegin||e.returnBegin)throw W("skip, excludeBegin, returnBegin not compatible with beginScope: {}"), +K +;if("object"!=typeof e.beginScope||null===e.beginScope)throw W("beginScope must be object"), +K;F(e,e.begin,{key:"beginScope"}),e.begin=m(e.begin,{joinWith:""})}})(e),(e=>{ +if(Array.isArray(e.end)){ +if(e.skip||e.excludeEnd||e.returnEnd)throw W("skip, excludeEnd, returnEnd not compatible with endScope: {}"), +K +;if("object"!=typeof e.endScope||null===e.endScope)throw W("endScope must be object"), +K;F(e,e.end,{key:"endScope"}),e.end=m(e.end,{joinWith:""})}})(e)}function V(e){ +function t(t,n){ +return RegExp(l(t),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(n?"g":"")) +}class n{constructor(){ +this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0} +addRule(e,t){ +t.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]), +this.matchAt+=p(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null) +;const e=this.regexes.map((e=>e[1]));this.matcherRe=t(m(e,{joinWith:"|" +}),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex +;const t=this.matcherRe.exec(e);if(!t)return null +;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),i=this.matchIndexes[n] +;return t.splice(0,n),Object.assign(t,i)}}class s{constructor(){ +this.rules=[],this.multiRegexes=[], +this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){ +if(this.multiRegexes[e])return this.multiRegexes[e];const t=new n +;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))), +t.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){ +return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){ +this.rules.push([e,t]),"begin"===t.type&&this.count++}exec(e){ +const t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex +;let n=t.exec(e) +;if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{ +const t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)} +return n&&(this.regexIndex+=n.position+1, +this.regexIndex===this.count&&this.considerAll()),n}} +if(e.compilerExtensions||(e.compilerExtensions=[]), +e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.") +;return e.classNameAliases=i(e.classNameAliases||{}),function n(r,o){const a=r +;if(r.isCompiled)return a +;[I,B,Z,D].forEach((e=>e(r,o))),e.compilerExtensions.forEach((e=>e(r,o))), +r.__beforeBegin=null,[T,L,P].forEach((e=>e(r,o))),r.isCompiled=!0;let c=null +;return"object"==typeof r.keywords&&r.keywords.$pattern&&(r.keywords=Object.assign({},r.keywords), +c=r.keywords.$pattern, +delete r.keywords.$pattern),c=c||/\w+/,r.keywords&&(r.keywords=$(r.keywords,e.case_insensitive)), +a.keywordPatternRe=t(c,!0), +o&&(r.begin||(r.begin=/\B|\b/),a.beginRe=t(a.begin),r.end||r.endsWithParent||(r.end=/\B|\b/), +r.end&&(a.endRe=t(a.end)), +a.terminatorEnd=l(a.end)||"",r.endsWithParent&&o.terminatorEnd&&(a.terminatorEnd+=(r.end?"|":"")+o.terminatorEnd)), +r.illegal&&(a.illegalRe=t(r.illegal)), +r.contains||(r.contains=[]),r.contains=[].concat(...r.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((t=>i(e,{ +variants:null},t)))),e.cachedVariants?e.cachedVariants:q(e)?i(e,{ +starts:e.starts?i(e.starts):null +}):Object.isFrozen(e)?i(e):e))("self"===e?r:e)))),r.contains.forEach((e=>{n(e,a) +})),r.starts&&n(r.starts,o),a.matcher=(e=>{const t=new s +;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:"begin" +}))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:"end" +}),e.illegal&&t.addRule(e.illegal,{type:"illegal"}),t})(a),a}(e)}function q(e){ +return!!e&&(e.endsWithParent||q(e.starts))}class J extends Error{ +constructor(e,t){super(e),this.name="HTMLInjectionError",this.html=t}} +const Y=n,Q=i,ee=Symbol("nomatch"),te=n=>{ +const i=Object.create(null),s=Object.create(null),r=[];let o=!0 +;const a="Could not find the language '{}', did you forget to load/include a language module?",l={ +disableAutodetect:!0,name:"Plain text",contains:[]};let p={ +ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i, +languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-", +cssSelector:"pre code",languages:null,__emitter:c};function b(e){ +return p.noHighlightRe.test(e)}function m(e,t,n){let i="",s="" +;"object"==typeof t?(i=e, +n=t.ignoreIllegals,s=t.language):(G("10.7.0","highlight(lang, code, ...args) has been deprecated."), +G("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"), +s=e,i=t),void 0===n&&(n=!0);const r={code:i,language:s};N("before:highlight",r) +;const o=r.result?r.result:E(r.language,r.code,n) +;return o.code=r.code,N("after:highlight",o),o}function E(e,n,s,r){ +const c=Object.create(null);function l(){if(!N.keywords)return void M.addText(R) +;let e=0;N.keywordPatternRe.lastIndex=0;let t=N.keywordPatternRe.exec(R),n="" +;for(;t;){n+=R.substring(e,t.index) +;const s=_.case_insensitive?t[0].toLowerCase():t[0],r=(i=s,N.keywords[i]);if(r){ +const[e,i]=r +;if(M.addText(n),n="",c[s]=(c[s]||0)+1,c[s]<=7&&(A+=i),e.startsWith("_"))n+=t[0];else{ +const n=_.classNameAliases[e]||e;u(t[0],n)}}else n+=t[0] +;e=N.keywordPatternRe.lastIndex,t=N.keywordPatternRe.exec(R)}var i +;n+=R.substring(e),M.addText(n)}function g(){null!=N.subLanguage?(()=>{ +if(""===R)return;let e=null;if("string"==typeof N.subLanguage){ +if(!i[N.subLanguage])return void M.addText(R) +;e=E(N.subLanguage,R,!0,S[N.subLanguage]),S[N.subLanguage]=e._top +}else e=x(R,N.subLanguage.length?N.subLanguage:null) +;N.relevance>0&&(A+=e.relevance),M.__addSublanguage(e._emitter,e.language) +})():l(),R=""}function u(e,t){ +""!==e&&(M.startScope(t),M.addText(e),M.endScope())}function d(e,t){let n=1 +;const i=t.length-1;for(;n<=i;){if(!e._emit[n]){n++;continue} +const i=_.classNameAliases[e[n]]||e[n],s=t[n];i?u(s,i):(R=s,l(),R=""),n++}} +function h(e,t){ +return e.scope&&"string"==typeof e.scope&&M.openNode(_.classNameAliases[e.scope]||e.scope), +e.beginScope&&(e.beginScope._wrap?(u(R,_.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap), +R=""):e.beginScope._multi&&(d(e.beginScope,t),R="")),N=Object.create(e,{parent:{ +value:N}}),N}function f(e,n,i){let s=((e,t)=>{const n=e&&e.exec(t) +;return n&&0===n.index})(e.endRe,i);if(s){if(e["on:end"]){const i=new t(e) +;e["on:end"](n,i),i.isMatchIgnored&&(s=!1)}if(s){ +for(;e.endsParent&&e.parent;)e=e.parent;return e}} +if(e.endsWithParent)return f(e.parent,n,i)}function b(e){ +return 0===N.matcher.regexIndex?(R+=e[0],1):(T=!0,0)}function m(e){ +const t=e[0],i=n.substring(e.index),s=f(N,e,i);if(!s)return ee;const r=N +;N.endScope&&N.endScope._wrap?(g(), +u(t,N.endScope._wrap)):N.endScope&&N.endScope._multi?(g(), +d(N.endScope,e)):r.skip?R+=t:(r.returnEnd||r.excludeEnd||(R+=t), +g(),r.excludeEnd&&(R=t));do{ +N.scope&&M.closeNode(),N.skip||N.subLanguage||(A+=N.relevance),N=N.parent +}while(N!==s.parent);return s.starts&&h(s.starts,e),r.returnEnd?0:t.length} +let w={};function y(i,r){const a=r&&r[0];if(R+=i,null==a)return g(),0 +;if("begin"===w.type&&"end"===r.type&&w.index===r.index&&""===a){ +if(R+=n.slice(r.index,r.index+1),!o){const t=Error(`0 width match regex (${e})`) +;throw t.languageName=e,t.badRule=w.rule,t}return 1} +if(w=r,"begin"===r.type)return(e=>{ +const n=e[0],i=e.rule,s=new t(i),r=[i.__beforeBegin,i["on:begin"]] +;for(const t of r)if(t&&(t(e,s),s.isMatchIgnored))return b(n) +;return i.skip?R+=n:(i.excludeBegin&&(R+=n), +g(),i.returnBegin||i.excludeBegin||(R=n)),h(i,e),i.returnBegin?0:n.length})(r) +;if("illegal"===r.type&&!s){ +const e=Error('Illegal lexeme "'+a+'" for mode "'+(N.scope||"")+'"') +;throw e.mode=N,e}if("end"===r.type){const e=m(r);if(e!==ee)return e} +if("illegal"===r.type&&""===a)return 1 +;if(I>1e5&&I>3*r.index)throw Error("potential infinite loop, way more iterations than matches") +;return R+=a,a.length}const _=O(e) +;if(!_)throw W(a.replace("{}",e)),Error('Unknown language: "'+e+'"') +;const k=V(_);let v="",N=r||k;const S={},M=new p.__emitter(p);(()=>{const e=[] +;for(let t=N;t!==_;t=t.parent)t.scope&&e.unshift(t.scope) +;e.forEach((e=>M.openNode(e)))})();let R="",A=0,j=0,I=0,T=!1;try{ +if(_.__emitTokens)_.__emitTokens(n,M);else{for(N.matcher.considerAll();;){ +I++,T?T=!1:N.matcher.considerAll(),N.matcher.lastIndex=j +;const e=N.matcher.exec(n);if(!e)break;const t=y(n.substring(j,e.index),e) +;j=e.index+t}y(n.substring(j))}return M.finalize(),v=M.toHTML(),{language:e, +value:v,relevance:A,illegal:!1,_emitter:M,_top:N}}catch(t){ +if(t.message&&t.message.includes("Illegal"))return{language:e,value:Y(n), +illegal:!0,relevance:0,_illegalBy:{message:t.message,index:j, +context:n.slice(j-100,j+100),mode:t.mode,resultSoFar:v},_emitter:M};if(o)return{ +language:e,value:Y(n),illegal:!1,relevance:0,errorRaised:t,_emitter:M,_top:N} +;throw t}}function x(e,t){t=t||p.languages||Object.keys(i);const n=(e=>{ +const t={value:Y(e),illegal:!1,relevance:0,_top:l,_emitter:new p.__emitter(p)} +;return t._emitter.addText(e),t})(e),s=t.filter(O).filter(v).map((t=>E(t,e,!1))) +;s.unshift(n);const r=s.sort(((e,t)=>{ +if(e.relevance!==t.relevance)return t.relevance-e.relevance +;if(e.language&&t.language){if(O(e.language).supersetOf===t.language)return 1 +;if(O(t.language).supersetOf===e.language)return-1}return 0})),[o,a]=r,c=o +;return c.secondBest=a,c}function w(e){let t=null;const n=(e=>{ +let t=e.className+" ";t+=e.parentNode?e.parentNode.className:"" +;const n=p.languageDetectRe.exec(t);if(n){const t=O(n[1]) +;return t||(X(a.replace("{}",n[1])), +X("Falling back to no-highlight mode for this block.",e)),t?n[1]:"no-highlight"} +return t.split(/\s+/).find((e=>b(e)||O(e)))})(e);if(b(n))return +;if(N("before:highlightElement",{el:e,language:n +}),e.dataset.highlighted)return void console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.",e) +;if(e.children.length>0&&(p.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."), +console.warn("https://github.com/highlightjs/highlight.js/wiki/security"), +console.warn("The element with unescaped HTML:"), +console.warn(e)),p.throwUnescapedHTML))throw new J("One of your code blocks includes unescaped HTML.",e.innerHTML) +;t=e;const i=t.textContent,r=n?m(i,{language:n,ignoreIllegals:!0}):x(i) +;e.innerHTML=r.value,e.dataset.highlighted="yes",((e,t,n)=>{const i=t&&s[t]||n +;e.classList.add("hljs"),e.classList.add("language-"+i) +})(e,n,r.language),e.result={language:r.language,re:r.relevance, +relevance:r.relevance},r.secondBest&&(e.secondBest={ +language:r.secondBest.language,relevance:r.secondBest.relevance +}),N("after:highlightElement",{el:e,result:r,text:i})}let y=!1;function _(){ +"loading"!==document.readyState?document.querySelectorAll(p.cssSelector).forEach(w):y=!0 +}function O(e){return e=(e||"").toLowerCase(),i[e]||i[s[e]]} +function k(e,{languageName:t}){"string"==typeof e&&(e=[e]),e.forEach((e=>{ +s[e.toLowerCase()]=t}))}function v(e){const t=O(e) +;return t&&!t.disableAutodetect}function N(e,t){const n=e;r.forEach((e=>{ +e[n]&&e[n](t)}))} +"undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(()=>{ +y&&_()}),!1),Object.assign(n,{highlight:m,highlightAuto:x,highlightAll:_, +highlightElement:w, +highlightBlock:e=>(G("10.7.0","highlightBlock will be removed entirely in v12.0"), +G("10.7.0","Please use highlightElement now."),w(e)),configure:e=>{p=Q(p,e)}, +initHighlighting:()=>{ +_(),G("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")}, +initHighlightingOnLoad:()=>{ +_(),G("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.") +},registerLanguage:(e,t)=>{let s=null;try{s=t(n)}catch(t){ +if(W("Language definition for '{}' could not be registered.".replace("{}",e)), +!o)throw t;W(t),s=l} +s.name||(s.name=e),i[e]=s,s.rawDefinition=t.bind(null,n),s.aliases&&k(s.aliases,{ +languageName:e})},unregisterLanguage:e=>{delete i[e] +;for(const t of Object.keys(s))s[t]===e&&delete s[t]}, +listLanguages:()=>Object.keys(i),getLanguage:O,registerAliases:k, +autoDetection:v,inherit:Q,addPlugin:e=>{(e=>{ +e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=t=>{ +e["before:highlightBlock"](Object.assign({block:t.el},t)) +}),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=t=>{ +e["after:highlightBlock"](Object.assign({block:t.el},t))})})(e),r.push(e)}, +removePlugin:e=>{const t=r.indexOf(e);-1!==t&&r.splice(t,1)}}),n.debugMode=()=>{ +o=!1},n.safeMode=()=>{o=!0},n.versionString="11.9.0",n.regex={concat:h, +lookahead:g,either:f,optional:d,anyNumberOfTimes:u} +;for(const t in A)"object"==typeof A[t]&&e(A[t]);return Object.assign(n,A),n +},ne=te({});ne.newInstance=()=>te({});export{ne as default}; \ No newline at end of file diff --git a/vendor/highlightjs/es/languages/bash.js b/vendor/highlightjs/es/languages/bash.js new file mode 100644 index 000000000..8ac30da30 --- /dev/null +++ b/vendor/highlightjs/es/languages/bash.js @@ -0,0 +1,411 @@ +/*! `bash` grammar compiled for Highlight.js 11.9.0 */ +var hljsGrammar = (function () { + 'use strict'; + + /* + Language: Bash + Author: vah + Contributrors: Benjamin Pannell + Website: https://www.gnu.org/software/bash/ + Category: common, scripting + */ + + /** @type LanguageFn */ + function bash(hljs) { + const regex = hljs.regex; + const VAR = {}; + const BRACED_VAR = { + begin: /\$\{/, + end: /\}/, + contains: [ + "self", + { + begin: /:-/, + contains: [ VAR ] + } // default values + ] + }; + Object.assign(VAR, { + className: 'variable', + variants: [ + { begin: regex.concat(/\$[\w\d#@][\w\d_]*/, + // negative look-ahead tries to avoid matching patterns that are not + // Perl at all like $ident$, @ident@, etc. + `(?![\\w\\d])(?![$])`) }, + BRACED_VAR + ] + }); + + const SUBST = { + className: 'subst', + begin: /\$\(/, + end: /\)/, + contains: [ hljs.BACKSLASH_ESCAPE ] + }; + const COMMENT = hljs.inherit( + hljs.COMMENT(), + { + match: [ + /(^|\s)/, + /#.*$/ + ], + scope: { + 2: 'comment' + } + } + ); + const HERE_DOC = { + begin: /<<-?\s*(?=\w+)/, + starts: { contains: [ + hljs.END_SAME_AS_BEGIN({ + begin: /(\w+)/, + end: /(\w+)/, + className: 'string' + }) + ] } + }; + const QUOTE_STRING = { + className: 'string', + begin: /"/, + end: /"/, + contains: [ + hljs.BACKSLASH_ESCAPE, + VAR, + SUBST + ] + }; + SUBST.contains.push(QUOTE_STRING); + const ESCAPED_QUOTE = { + match: /\\"/ + }; + const APOS_STRING = { + className: 'string', + begin: /'/, + end: /'/ + }; + const ESCAPED_APOS = { + match: /\\'/ + }; + const ARITHMETIC = { + begin: /\$?\(\(/, + end: /\)\)/, + contains: [ + { + begin: /\d+#[0-9a-f]+/, + className: "number" + }, + hljs.NUMBER_MODE, + VAR + ] + }; + const SH_LIKE_SHELLS = [ + "fish", + "bash", + "zsh", + "sh", + "csh", + "ksh", + "tcsh", + "dash", + "scsh", + ]; + const KNOWN_SHEBANG = hljs.SHEBANG({ + binary: `(${SH_LIKE_SHELLS.join("|")})`, + relevance: 10 + }); + const FUNCTION = { + className: 'function', + begin: /\w[\w\d_]*\s*\(\s*\)\s*\{/, + returnBegin: true, + contains: [ hljs.inherit(hljs.TITLE_MODE, { begin: /\w[\w\d_]*/ }) ], + relevance: 0 + }; + + const KEYWORDS = [ + "if", + "then", + "else", + "elif", + "fi", + "for", + "while", + "until", + "in", + "do", + "done", + "case", + "esac", + "function", + "select" + ]; + + const LITERALS = [ + "true", + "false" + ]; + + // to consume paths to prevent keyword matches inside them + const PATH_MODE = { match: /(\/[a-z._-]+)+/ }; + + // http://www.gnu.org/software/bash/manual/html_node/Shell-Builtin-Commands.html + const SHELL_BUILT_INS = [ + "break", + "cd", + "continue", + "eval", + "exec", + "exit", + "export", + "getopts", + "hash", + "pwd", + "readonly", + "return", + "shift", + "test", + "times", + "trap", + "umask", + "unset" + ]; + + const BASH_BUILT_INS = [ + "alias", + "bind", + "builtin", + "caller", + "command", + "declare", + "echo", + "enable", + "help", + "let", + "local", + "logout", + "mapfile", + "printf", + "read", + "readarray", + "source", + "type", + "typeset", + "ulimit", + "unalias" + ]; + + const ZSH_BUILT_INS = [ + "autoload", + "bg", + "bindkey", + "bye", + "cap", + "chdir", + "clone", + "comparguments", + "compcall", + "compctl", + "compdescribe", + "compfiles", + "compgroups", + "compquote", + "comptags", + "comptry", + "compvalues", + "dirs", + "disable", + "disown", + "echotc", + "echoti", + "emulate", + "fc", + "fg", + "float", + "functions", + "getcap", + "getln", + "history", + "integer", + "jobs", + "kill", + "limit", + "log", + "noglob", + "popd", + "print", + "pushd", + "pushln", + "rehash", + "sched", + "setcap", + "setopt", + "stat", + "suspend", + "ttyctl", + "unfunction", + "unhash", + "unlimit", + "unsetopt", + "vared", + "wait", + "whence", + "where", + "which", + "zcompile", + "zformat", + "zftp", + "zle", + "zmodload", + "zparseopts", + "zprof", + "zpty", + "zregexparse", + "zsocket", + "zstyle", + "ztcp" + ]; + + const GNU_CORE_UTILS = [ + "chcon", + "chgrp", + "chown", + "chmod", + "cp", + "dd", + "df", + "dir", + "dircolors", + "ln", + "ls", + "mkdir", + "mkfifo", + "mknod", + "mktemp", + "mv", + "realpath", + "rm", + "rmdir", + "shred", + "sync", + "touch", + "truncate", + "vdir", + "b2sum", + "base32", + "base64", + "cat", + "cksum", + "comm", + "csplit", + "cut", + "expand", + "fmt", + "fold", + "head", + "join", + "md5sum", + "nl", + "numfmt", + "od", + "paste", + "ptx", + "pr", + "sha1sum", + "sha224sum", + "sha256sum", + "sha384sum", + "sha512sum", + "shuf", + "sort", + "split", + "sum", + "tac", + "tail", + "tr", + "tsort", + "unexpand", + "uniq", + "wc", + "arch", + "basename", + "chroot", + "date", + "dirname", + "du", + "echo", + "env", + "expr", + "factor", + // "false", // keyword literal already + "groups", + "hostid", + "id", + "link", + "logname", + "nice", + "nohup", + "nproc", + "pathchk", + "pinky", + "printenv", + "printf", + "pwd", + "readlink", + "runcon", + "seq", + "sleep", + "stat", + "stdbuf", + "stty", + "tee", + "test", + "timeout", + // "true", // keyword literal already + "tty", + "uname", + "unlink", + "uptime", + "users", + "who", + "whoami", + "yes" + ]; + + return { + name: 'Bash', + aliases: [ 'sh' ], + keywords: { + $pattern: /\b[a-z][a-z0-9._-]+\b/, + keyword: KEYWORDS, + literal: LITERALS, + built_in: [ + ...SHELL_BUILT_INS, + ...BASH_BUILT_INS, + // Shell modifiers + "set", + "shopt", + ...ZSH_BUILT_INS, + ...GNU_CORE_UTILS + ] + }, + contains: [ + KNOWN_SHEBANG, // to catch known shells and boost relevancy + hljs.SHEBANG(), // to catch unknown shells but still highlight the shebang + FUNCTION, + ARITHMETIC, + COMMENT, + HERE_DOC, + PATH_MODE, + QUOTE_STRING, + ESCAPED_QUOTE, + APOS_STRING, + ESCAPED_APOS, + VAR + ] + }; + } + + return bash; + +})(); +; +export default hljsGrammar; \ No newline at end of file diff --git a/vendor/highlightjs/es/languages/bash.min.js b/vendor/highlightjs/es/languages/bash.min.js new file mode 100644 index 000000000..eb16de166 --- /dev/null +++ b/vendor/highlightjs/es/languages/bash.min.js @@ -0,0 +1,21 @@ +/*! `bash` grammar compiled for Highlight.js 11.9.0 */ +var hljsGrammar=(()=>{"use strict";return e=>{const s=e.regex,t={},a={ +begin:/\$\{/,end:/\}/,contains:["self",{begin:/:-/,contains:[t]}]} +;Object.assign(t,{className:"variable",variants:[{ +begin:s.concat(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},a]});const n={ +className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE] +},i=e.inherit(e.COMMENT(),{match:[/(^|\s)/,/#.*$/],scope:{2:"comment"}}),c={ +begin:/<<-?\s*(?=\w+)/,starts:{contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/, +end:/(\w+)/,className:"string"})]}},o={className:"string",begin:/"/,end:/"/, +contains:[e.BACKSLASH_ESCAPE,t,n]};n.contains.push(o);const r={begin:/\$?\(\(/, +end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,t] +},l=e.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10 +}),m={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0, +contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{ +name:"Bash",aliases:["sh"],keywords:{$pattern:/\b[a-z][a-z0-9._-]+\b/, +keyword:["if","then","else","elif","fi","for","while","until","in","do","done","case","esac","function","select"], +literal:["true","false"], +built_in:["break","cd","continue","eval","exec","exit","export","getopts","hash","pwd","readonly","return","shift","test","times","trap","umask","unset","alias","bind","builtin","caller","command","declare","echo","enable","help","let","local","logout","mapfile","printf","read","readarray","source","type","typeset","ulimit","unalias","set","shopt","autoload","bg","bindkey","bye","cap","chdir","clone","comparguments","compcall","compctl","compdescribe","compfiles","compgroups","compquote","comptags","comptry","compvalues","dirs","disable","disown","echotc","echoti","emulate","fc","fg","float","functions","getcap","getln","history","integer","jobs","kill","limit","log","noglob","popd","print","pushd","pushln","rehash","sched","setcap","setopt","stat","suspend","ttyctl","unfunction","unhash","unlimit","unsetopt","vared","wait","whence","where","which","zcompile","zformat","zftp","zle","zmodload","zparseopts","zprof","zpty","zregexparse","zsocket","zstyle","ztcp","chcon","chgrp","chown","chmod","cp","dd","df","dir","dircolors","ln","ls","mkdir","mkfifo","mknod","mktemp","mv","realpath","rm","rmdir","shred","sync","touch","truncate","vdir","b2sum","base32","base64","cat","cksum","comm","csplit","cut","expand","fmt","fold","head","join","md5sum","nl","numfmt","od","paste","ptx","pr","sha1sum","sha224sum","sha256sum","sha384sum","sha512sum","shuf","sort","split","sum","tac","tail","tr","tsort","unexpand","uniq","wc","arch","basename","chroot","date","dirname","du","echo","env","expr","factor","groups","hostid","id","link","logname","nice","nohup","nproc","pathchk","pinky","printenv","printf","pwd","readlink","runcon","seq","sleep","stat","stdbuf","stty","tee","test","timeout","tty","uname","unlink","uptime","users","who","whoami","yes"] +},contains:[l,e.SHEBANG(),m,r,i,c,{match:/(\/[a-z._-]+)+/},o,{match:/\\"/},{ +className:"string",begin:/'/,end:/'/},{match:/\\'/},t]}}})() +;export default hljsGrammar; \ No newline at end of file diff --git a/vendor/highlightjs/es/languages/csharp.js b/vendor/highlightjs/es/languages/csharp.js new file mode 100644 index 000000000..64e2b8f12 --- /dev/null +++ b/vendor/highlightjs/es/languages/csharp.js @@ -0,0 +1,408 @@ +/*! `csharp` grammar compiled for Highlight.js 11.9.0 */ +var hljsGrammar = (function () { + 'use strict'; + + /* + Language: C# + Author: Jason Diamond + Contributor: Nicolas LLOBERA , Pieter Vantorre , David Pine + Website: https://docs.microsoft.com/dotnet/csharp/ + Category: common + */ + + /** @type LanguageFn */ + function csharp(hljs) { + const BUILT_IN_KEYWORDS = [ + 'bool', + 'byte', + 'char', + 'decimal', + 'delegate', + 'double', + 'dynamic', + 'enum', + 'float', + 'int', + 'long', + 'nint', + 'nuint', + 'object', + 'sbyte', + 'short', + 'string', + 'ulong', + 'uint', + 'ushort' + ]; + const FUNCTION_MODIFIERS = [ + 'public', + 'private', + 'protected', + 'static', + 'internal', + 'protected', + 'abstract', + 'async', + 'extern', + 'override', + 'unsafe', + 'virtual', + 'new', + 'sealed', + 'partial' + ]; + const LITERAL_KEYWORDS = [ + 'default', + 'false', + 'null', + 'true' + ]; + const NORMAL_KEYWORDS = [ + 'abstract', + 'as', + 'base', + 'break', + 'case', + 'catch', + 'class', + 'const', + 'continue', + 'do', + 'else', + 'event', + 'explicit', + 'extern', + 'finally', + 'fixed', + 'for', + 'foreach', + 'goto', + 'if', + 'implicit', + 'in', + 'interface', + 'internal', + 'is', + 'lock', + 'namespace', + 'new', + 'operator', + 'out', + 'override', + 'params', + 'private', + 'protected', + 'public', + 'readonly', + 'record', + 'ref', + 'return', + 'scoped', + 'sealed', + 'sizeof', + 'stackalloc', + 'static', + 'struct', + 'switch', + 'this', + 'throw', + 'try', + 'typeof', + 'unchecked', + 'unsafe', + 'using', + 'virtual', + 'void', + 'volatile', + 'while' + ]; + const CONTEXTUAL_KEYWORDS = [ + 'add', + 'alias', + 'and', + 'ascending', + 'async', + 'await', + 'by', + 'descending', + 'equals', + 'from', + 'get', + 'global', + 'group', + 'init', + 'into', + 'join', + 'let', + 'nameof', + 'not', + 'notnull', + 'on', + 'or', + 'orderby', + 'partial', + 'remove', + 'select', + 'set', + 'unmanaged', + 'value|0', + 'var', + 'when', + 'where', + 'with', + 'yield' + ]; + + const KEYWORDS = { + keyword: NORMAL_KEYWORDS.concat(CONTEXTUAL_KEYWORDS), + built_in: BUILT_IN_KEYWORDS, + literal: LITERAL_KEYWORDS + }; + const TITLE_MODE = hljs.inherit(hljs.TITLE_MODE, { begin: '[a-zA-Z](\\.?\\w)*' }); + const NUMBERS = { + className: 'number', + variants: [ + { begin: '\\b(0b[01\']+)' }, + { begin: '(-?)\\b([\\d\']+(\\.[\\d\']*)?|\\.[\\d\']+)(u|U|l|L|ul|UL|f|F|b|B)' }, + { begin: '(-?)(\\b0[xX][a-fA-F0-9\']+|(\\b[\\d\']+(\\.[\\d\']*)?|\\.[\\d\']+)([eE][-+]?[\\d\']+)?)' } + ], + relevance: 0 + }; + const VERBATIM_STRING = { + className: 'string', + begin: '@"', + end: '"', + contains: [ { begin: '""' } ] + }; + const VERBATIM_STRING_NO_LF = hljs.inherit(VERBATIM_STRING, { illegal: /\n/ }); + const SUBST = { + className: 'subst', + begin: /\{/, + end: /\}/, + keywords: KEYWORDS + }; + const SUBST_NO_LF = hljs.inherit(SUBST, { illegal: /\n/ }); + const INTERPOLATED_STRING = { + className: 'string', + begin: /\$"/, + end: '"', + illegal: /\n/, + contains: [ + { begin: /\{\{/ }, + { begin: /\}\}/ }, + hljs.BACKSLASH_ESCAPE, + SUBST_NO_LF + ] + }; + const INTERPOLATED_VERBATIM_STRING = { + className: 'string', + begin: /\$@"/, + end: '"', + contains: [ + { begin: /\{\{/ }, + { begin: /\}\}/ }, + { begin: '""' }, + SUBST + ] + }; + const INTERPOLATED_VERBATIM_STRING_NO_LF = hljs.inherit(INTERPOLATED_VERBATIM_STRING, { + illegal: /\n/, + contains: [ + { begin: /\{\{/ }, + { begin: /\}\}/ }, + { begin: '""' }, + SUBST_NO_LF + ] + }); + SUBST.contains = [ + INTERPOLATED_VERBATIM_STRING, + INTERPOLATED_STRING, + VERBATIM_STRING, + hljs.APOS_STRING_MODE, + hljs.QUOTE_STRING_MODE, + NUMBERS, + hljs.C_BLOCK_COMMENT_MODE + ]; + SUBST_NO_LF.contains = [ + INTERPOLATED_VERBATIM_STRING_NO_LF, + INTERPOLATED_STRING, + VERBATIM_STRING_NO_LF, + hljs.APOS_STRING_MODE, + hljs.QUOTE_STRING_MODE, + NUMBERS, + hljs.inherit(hljs.C_BLOCK_COMMENT_MODE, { illegal: /\n/ }) + ]; + const STRING = { variants: [ + INTERPOLATED_VERBATIM_STRING, + INTERPOLATED_STRING, + VERBATIM_STRING, + hljs.APOS_STRING_MODE, + hljs.QUOTE_STRING_MODE + ] }; + + const GENERIC_MODIFIER = { + begin: "<", + end: ">", + contains: [ + { beginKeywords: "in out" }, + TITLE_MODE + ] + }; + const TYPE_IDENT_RE = hljs.IDENT_RE + '(<' + hljs.IDENT_RE + '(\\s*,\\s*' + hljs.IDENT_RE + ')*>)?(\\[\\])?'; + const AT_IDENTIFIER = { + // prevents expressions like `@class` from incorrect flagging + // `class` as a keyword + begin: "@" + hljs.IDENT_RE, + relevance: 0 + }; + + return { + name: 'C#', + aliases: [ + 'cs', + 'c#' + ], + keywords: KEYWORDS, + illegal: /::/, + contains: [ + hljs.COMMENT( + '///', + '$', + { + returnBegin: true, + contains: [ + { + className: 'doctag', + variants: [ + { + begin: '///', + relevance: 0 + }, + { begin: '' }, + { + begin: '' + } + ] + } + ] + } + ), + hljs.C_LINE_COMMENT_MODE, + hljs.C_BLOCK_COMMENT_MODE, + { + className: 'meta', + begin: '#', + end: '$', + keywords: { keyword: 'if else elif endif define undef warning error line region endregion pragma checksum' } + }, + STRING, + NUMBERS, + { + beginKeywords: 'class interface', + relevance: 0, + end: /[{;=]/, + illegal: /[^\s:,]/, + contains: [ + { beginKeywords: "where class" }, + TITLE_MODE, + GENERIC_MODIFIER, + hljs.C_LINE_COMMENT_MODE, + hljs.C_BLOCK_COMMENT_MODE + ] + }, + { + beginKeywords: 'namespace', + relevance: 0, + end: /[{;=]/, + illegal: /[^\s:]/, + contains: [ + TITLE_MODE, + hljs.C_LINE_COMMENT_MODE, + hljs.C_BLOCK_COMMENT_MODE + ] + }, + { + beginKeywords: 'record', + relevance: 0, + end: /[{;=]/, + illegal: /[^\s:]/, + contains: [ + TITLE_MODE, + GENERIC_MODIFIER, + hljs.C_LINE_COMMENT_MODE, + hljs.C_BLOCK_COMMENT_MODE + ] + }, + { + // [Attributes("")] + className: 'meta', + begin: '^\\s*\\[(?=[\\w])', + excludeBegin: true, + end: '\\]', + excludeEnd: true, + contains: [ + { + className: 'string', + begin: /"/, + end: /"/ + } + ] + }, + { + // Expression keywords prevent 'keyword Name(...)' from being + // recognized as a function definition + beginKeywords: 'new return throw await else', + relevance: 0 + }, + { + className: 'function', + begin: '(' + TYPE_IDENT_RE + '\\s+)+' + hljs.IDENT_RE + '\\s*(<[^=]+>\\s*)?\\(', + returnBegin: true, + end: /\s*[{;=]/, + excludeEnd: true, + keywords: KEYWORDS, + contains: [ + // prevents these from being highlighted `title` + { + beginKeywords: FUNCTION_MODIFIERS.join(" "), + relevance: 0 + }, + { + begin: hljs.IDENT_RE + '\\s*(<[^=]+>\\s*)?\\(', + returnBegin: true, + contains: [ + hljs.TITLE_MODE, + GENERIC_MODIFIER + ], + relevance: 0 + }, + { match: /\(\)/ }, + { + className: 'params', + begin: /\(/, + end: /\)/, + excludeBegin: true, + excludeEnd: true, + keywords: KEYWORDS, + relevance: 0, + contains: [ + STRING, + NUMBERS, + hljs.C_BLOCK_COMMENT_MODE + ] + }, + hljs.C_LINE_COMMENT_MODE, + hljs.C_BLOCK_COMMENT_MODE + ] + }, + AT_IDENTIFIER + ] + }; + } + + return csharp; + +})(); +; +export default hljsGrammar; \ No newline at end of file diff --git a/vendor/highlightjs/es/languages/csharp.min.js b/vendor/highlightjs/es/languages/csharp.min.js new file mode 100644 index 000000000..dec26afcc --- /dev/null +++ b/vendor/highlightjs/es/languages/csharp.min.js @@ -0,0 +1,47 @@ +/*! `csharp` grammar compiled for Highlight.js 11.9.0 */ +var hljsGrammar=(()=>{"use strict";return e=>{const n={ +keyword:["abstract","as","base","break","case","catch","class","const","continue","do","else","event","explicit","extern","finally","fixed","for","foreach","goto","if","implicit","in","interface","internal","is","lock","namespace","new","operator","out","override","params","private","protected","public","readonly","record","ref","return","scoped","sealed","sizeof","stackalloc","static","struct","switch","this","throw","try","typeof","unchecked","unsafe","using","virtual","void","volatile","while"].concat(["add","alias","and","ascending","async","await","by","descending","equals","from","get","global","group","init","into","join","let","nameof","not","notnull","on","or","orderby","partial","remove","select","set","unmanaged","value|0","var","when","where","with","yield"]), +built_in:["bool","byte","char","decimal","delegate","double","dynamic","enum","float","int","long","nint","nuint","object","sbyte","short","string","ulong","uint","ushort"], +literal:["default","false","null","true"]},a=e.inherit(e.TITLE_MODE,{ +begin:"[a-zA-Z](\\.?\\w)*"}),i={className:"number",variants:[{ +begin:"\\b(0b[01']+)"},{ +begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{ +begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" +}],relevance:0},s={className:"string",begin:'@"',end:'"',contains:[{begin:'""'}] +},t=e.inherit(s,{illegal:/\n/}),r={className:"subst",begin:/\{/,end:/\}/, +keywords:n},l=e.inherit(r,{illegal:/\n/}),c={className:"string",begin:/\$"/, +end:'"',illegal:/\n/,contains:[{begin:/\{\{/},{begin:/\}\}/ +},e.BACKSLASH_ESCAPE,l]},o={className:"string",begin:/\$@"/,end:'"',contains:[{ +begin:/\{\{/},{begin:/\}\}/},{begin:'""'},r]},d=e.inherit(o,{illegal:/\n/, +contains:[{begin:/\{\{/},{begin:/\}\}/},{begin:'""'},l]}) +;r.contains=[o,c,s,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,i,e.C_BLOCK_COMMENT_MODE], +l.contains=[d,c,t,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,i,e.inherit(e.C_BLOCK_COMMENT_MODE,{ +illegal:/\n/})];const g={variants:[o,c,s,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE] +},E={begin:"<",end:">",contains:[{beginKeywords:"in out"},a] +},_=e.IDENT_RE+"(<"+e.IDENT_RE+"(\\s*,\\s*"+e.IDENT_RE+")*>)?(\\[\\])?",b={ +begin:"@"+e.IDENT_RE,relevance:0};return{name:"C#",aliases:["cs","c#"], +keywords:n,illegal:/::/,contains:[e.COMMENT("///","$",{returnBegin:!0, +contains:[{className:"doctag",variants:[{begin:"///",relevance:0},{ +begin:"\x3c!--|--\x3e"},{begin:""}]}] +}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"meta",begin:"#", +end:"$",keywords:{ +keyword:"if else elif endif define undef warning error line region endregion pragma checksum" +}},g,i,{beginKeywords:"class interface",relevance:0,end:/[{;=]/, +illegal:/[^\s:,]/,contains:[{beginKeywords:"where class" +},a,E,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"namespace", +relevance:0,end:/[{;=]/,illegal:/[^\s:]/, +contains:[a,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{ +beginKeywords:"record",relevance:0,end:/[{;=]/,illegal:/[^\s:]/, +contains:[a,E,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"meta", +begin:"^\\s*\\[(?=[\\w])",excludeBegin:!0,end:"\\]",excludeEnd:!0,contains:[{ +className:"string",begin:/"/,end:/"/}]},{ +beginKeywords:"new return throw await else",relevance:0},{className:"function", +begin:"("+_+"\\s+)+"+e.IDENT_RE+"\\s*(<[^=]+>\\s*)?\\(",returnBegin:!0, +end:/\s*[{;=]/,excludeEnd:!0,keywords:n,contains:[{ +beginKeywords:"public private protected static internal protected abstract async extern override unsafe virtual new sealed partial", +relevance:0},{begin:e.IDENT_RE+"\\s*(<[^=]+>\\s*)?\\(",returnBegin:!0, +contains:[e.TITLE_MODE,E],relevance:0},{match:/\(\)/},{className:"params", +begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:n,relevance:0, +contains:[g,i,e.C_BLOCK_COMMENT_MODE] +},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},b]}}})() +;export default hljsGrammar; \ No newline at end of file diff --git a/vendor/highlightjs/es/languages/haxe.js b/vendor/highlightjs/es/languages/haxe.js new file mode 100644 index 000000000..89505039f --- /dev/null +++ b/vendor/highlightjs/es/languages/haxe.js @@ -0,0 +1,175 @@ +/*! `haxe` grammar compiled for Highlight.js 11.9.0 */ +var hljsGrammar = (function () { + 'use strict'; + + /* + Language: Haxe + Description: Haxe is an open source toolkit based on a modern, high level, strictly typed programming language. + Author: Christopher Kaster (Based on the actionscript.js language file by Alexander Myadzel) + Contributors: Kenton Hamaluik + Website: https://haxe.org + Category: system + */ + + function haxe(hljs) { + const IDENT_RE = '[a-zA-Z_$][a-zA-Z0-9_$]*'; + + // C_NUMBER_RE with underscores and literal suffixes + const HAXE_NUMBER_RE = /(-?)(\b0[xX][a-fA-F0-9_]+|(\b\d+(\.[\d_]*)?|\.[\d_]+)(([eE][-+]?\d+)|i32|u32|i64|f64)?)/; + + const HAXE_BASIC_TYPES = 'Int Float String Bool Dynamic Void Array '; + + return { + name: 'Haxe', + aliases: [ 'hx' ], + keywords: { + keyword: 'abstract break case cast catch continue default do dynamic else enum extern ' + + 'final for function here if import in inline is macro never new override package private get set ' + + 'public return static super switch this throw trace try typedef untyped using var while ' + + HAXE_BASIC_TYPES, + built_in: + 'trace this', + literal: + 'true false null _' + }, + contains: [ + { + className: 'string', // interpolate-able strings + begin: '\'', + end: '\'', + contains: [ + hljs.BACKSLASH_ESCAPE, + { + className: 'subst', // interpolation + begin: /\$\{/, + end: /\}/ + }, + { + className: 'subst', // interpolation + begin: /\$/, + end: /\W\}/ + } + ] + }, + hljs.QUOTE_STRING_MODE, + hljs.C_LINE_COMMENT_MODE, + hljs.C_BLOCK_COMMENT_MODE, + { + className: 'number', + begin: HAXE_NUMBER_RE, + relevance: 0 + }, + { + className: 'variable', + begin: "\\$" + IDENT_RE, + }, + { + className: 'meta', // compiler meta + begin: /@:?/, + end: /\(|$/, + excludeEnd: true, + }, + { + className: 'meta', // compiler conditionals + begin: '#', + end: '$', + keywords: { keyword: 'if else elseif end error' } + }, + { + className: 'type', // function types + begin: /:[ \t]*/, + end: /[^A-Za-z0-9_ \t\->]/, + excludeBegin: true, + excludeEnd: true, + relevance: 0 + }, + { + className: 'type', // types + begin: /:[ \t]*/, + end: /\W/, + excludeBegin: true, + excludeEnd: true + }, + { + className: 'type', // instantiation + begin: /new */, + end: /\W/, + excludeBegin: true, + excludeEnd: true + }, + { + className: 'title.class', // enums + beginKeywords: 'enum', + end: /\{/, + contains: [ hljs.TITLE_MODE ] + }, + { + className: 'title.class', // abstracts + begin: '\\babstract\\b(?=\\s*' + hljs.IDENT_RE + '\\s*\\()', + end: /[\{$]/, + contains: [ + { + className: 'type', + begin: /\(/, + end: /\)/, + excludeBegin: true, + excludeEnd: true + }, + { + className: 'type', + begin: /from +/, + end: /\W/, + excludeBegin: true, + excludeEnd: true + }, + { + className: 'type', + begin: /to +/, + end: /\W/, + excludeBegin: true, + excludeEnd: true + }, + hljs.TITLE_MODE + ], + keywords: { keyword: 'abstract from to' } + }, + { + className: 'title.class', // classes + begin: /\b(class|interface) +/, + end: /[\{$]/, + excludeEnd: true, + keywords: 'class interface', + contains: [ + { + className: 'keyword', + begin: /\b(extends|implements) +/, + keywords: 'extends implements', + contains: [ + { + className: 'type', + begin: hljs.IDENT_RE, + relevance: 0 + } + ] + }, + hljs.TITLE_MODE + ] + }, + { + className: 'title.function', + beginKeywords: 'function', + end: /\(/, + excludeEnd: true, + illegal: /\S/, + contains: [ hljs.TITLE_MODE ] + } + ], + illegal: /<\// + }; + } + + return haxe; + +})(); +; +export default hljsGrammar; \ No newline at end of file diff --git a/vendor/highlightjs/es/languages/haxe.min.js b/vendor/highlightjs/es/languages/haxe.min.js new file mode 100644 index 000000000..0ced7072a --- /dev/null +++ b/vendor/highlightjs/es/languages/haxe.min.js @@ -0,0 +1,30 @@ +/*! `haxe` grammar compiled for Highlight.js 11.9.0 */ +var hljsGrammar=(()=>{"use strict";return e=>({name:"Haxe",aliases:["hx"], +keywords:{ +keyword:"abstract break case cast catch continue default do dynamic else enum extern final for function here if import in inline is macro never new override package private get set public return static super switch this throw trace try typedef untyped using var while Int Float String Bool Dynamic Void Array ", +built_in:"trace this",literal:"true false null _"},contains:[{ +className:"string",begin:"'",end:"'",contains:[e.BACKSLASH_ESCAPE,{ +className:"subst",begin:/\$\{/,end:/\}/},{className:"subst",begin:/\$/, +end:/\W\}/}]},e.QUOTE_STRING_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{ +className:"number", +begin:/(-?)(\b0[xX][a-fA-F0-9_]+|(\b\d+(\.[\d_]*)?|\.[\d_]+)(([eE][-+]?\d+)|i32|u32|i64|f64)?)/, +relevance:0},{className:"variable",begin:"\\$[a-zA-Z_$][a-zA-Z0-9_$]*"},{ +className:"meta",begin:/@:?/,end:/\(|$/,excludeEnd:!0},{className:"meta", +begin:"#",end:"$",keywords:{keyword:"if else elseif end error"}},{ +className:"type",begin:/:[ \t]*/,end:/[^A-Za-z0-9_ \t\->]/,excludeBegin:!0, +excludeEnd:!0,relevance:0},{className:"type",begin:/:[ \t]*/,end:/\W/, +excludeBegin:!0,excludeEnd:!0},{className:"type",begin:/new */,end:/\W/, +excludeBegin:!0,excludeEnd:!0},{className:"title.class",beginKeywords:"enum", +end:/\{/,contains:[e.TITLE_MODE]},{className:"title.class", +begin:"\\babstract\\b(?=\\s*"+e.IDENT_RE+"\\s*\\()",end:/[\{$]/,contains:[{ +className:"type",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0},{ +className:"type",begin:/from +/,end:/\W/,excludeBegin:!0,excludeEnd:!0},{ +className:"type",begin:/to +/,end:/\W/,excludeBegin:!0,excludeEnd:!0 +},e.TITLE_MODE],keywords:{keyword:"abstract from to"}},{className:"title.class", +begin:/\b(class|interface) +/,end:/[\{$]/,excludeEnd:!0, +keywords:"class interface",contains:[{className:"keyword", +begin:/\b(extends|implements) +/,keywords:"extends implements",contains:[{ +className:"type",begin:e.IDENT_RE,relevance:0}]},e.TITLE_MODE]},{ +className:"title.function",beginKeywords:"function",end:/\(/,excludeEnd:!0, +illegal:/\S/,contains:[e.TITLE_MODE]}],illegal:/<\//})})() +;export default hljsGrammar; \ No newline at end of file diff --git a/vendor/highlightjs/es/languages/xml.js b/vendor/highlightjs/es/languages/xml.js new file mode 100644 index 000000000..c4e13537e --- /dev/null +++ b/vendor/highlightjs/es/languages/xml.js @@ -0,0 +1,249 @@ +/*! `xml` grammar compiled for Highlight.js 11.9.0 */ +var hljsGrammar = (function () { + 'use strict'; + + /* + Language: HTML, XML + Website: https://www.w3.org/XML/ + Category: common, web + Audit: 2020 + */ + + /** @type LanguageFn */ + function xml(hljs) { + const regex = hljs.regex; + // XML names can have the following additional letters: https://www.w3.org/TR/xml/#NT-NameChar + // OTHER_NAME_CHARS = /[:\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]/; + // Element names start with NAME_START_CHAR followed by optional other Unicode letters, ASCII digits, hyphens, underscores, and periods + // const TAG_NAME_RE = regex.concat(/[A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/, regex.optional(/[A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*:/), /[A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*/);; + // const XML_IDENT_RE = /[A-Z_a-z:\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]+/; + // const TAG_NAME_RE = regex.concat(/[A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/, regex.optional(/[A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*:/), /[A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*/); + // however, to cater for performance and more Unicode support rely simply on the Unicode letter class + const TAG_NAME_RE = regex.concat(/[\p{L}_]/u, regex.optional(/[\p{L}0-9_.-]*:/u), /[\p{L}0-9_.-]*/u); + const XML_IDENT_RE = /[\p{L}0-9._:-]+/u; + const XML_ENTITIES = { + className: 'symbol', + begin: /&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/ + }; + const XML_META_KEYWORDS = { + begin: /\s/, + contains: [ + { + className: 'keyword', + begin: /#?[a-z_][a-z1-9_-]+/, + illegal: /\n/ + } + ] + }; + const XML_META_PAR_KEYWORDS = hljs.inherit(XML_META_KEYWORDS, { + begin: /\(/, + end: /\)/ + }); + const APOS_META_STRING_MODE = hljs.inherit(hljs.APOS_STRING_MODE, { className: 'string' }); + const QUOTE_META_STRING_MODE = hljs.inherit(hljs.QUOTE_STRING_MODE, { className: 'string' }); + const TAG_INTERNALS = { + endsWithParent: true, + illegal: /`]+/ } + ] + } + ] + } + ] + }; + return { + name: 'HTML, XML', + aliases: [ + 'html', + 'xhtml', + 'rss', + 'atom', + 'xjb', + 'xsd', + 'xsl', + 'plist', + 'wsf', + 'svg' + ], + case_insensitive: true, + unicodeRegex: true, + contains: [ + { + className: 'meta', + begin: //, + relevance: 10, + contains: [ + XML_META_KEYWORDS, + QUOTE_META_STRING_MODE, + APOS_META_STRING_MODE, + XML_META_PAR_KEYWORDS, + { + begin: /\[/, + end: /\]/, + contains: [ + { + className: 'meta', + begin: //, + contains: [ + XML_META_KEYWORDS, + XML_META_PAR_KEYWORDS, + QUOTE_META_STRING_MODE, + APOS_META_STRING_MODE + ] + } + ] + } + ] + }, + hljs.COMMENT( + //, + { relevance: 10 } + ), + { + begin: //, + relevance: 10 + }, + XML_ENTITIES, + // xml processing instructions + { + className: 'meta', + end: /\?>/, + variants: [ + { + begin: /<\?xml/, + relevance: 10, + contains: [ + QUOTE_META_STRING_MODE + ] + }, + { + begin: /<\?[a-z][a-z0-9]+/, + } + ] + + }, + { + className: 'tag', + /* + The lookahead pattern (?=...) ensures that 'begin' only matches + ')/, + end: />/, + keywords: { name: 'style' }, + contains: [ TAG_INTERNALS ], + starts: { + end: /<\/style>/, + returnEnd: true, + subLanguage: [ + 'css', + 'xml' + ] + } + }, + { + className: 'tag', + // See the comment in the + + + + + +

SWFObject 2 HTML and JavaScript generator v1.2

+ +
Asterisk (*) indicates required field
+
+ SWFObject configuration [ - ] +
+
+ * +
+
+ +
+
 
+
+ * +
+
+ + what is this? +
+
 
+
+

Static publishing

+ +

Description

+ +

Embed Flash content and alternative content using standards compliant markup, and use unobtrusive + JavaScript to resolve the issues that markup alone cannot solve.

+ +

Pros

+ +

The embedding of Flash content does not rely on JavaScript and the actual authoring of standards + compliant markup is promoted.

+ +

Cons

+ +

Does not solve 'click-to-activate' mechanisms in Internet Explorer 6+ and Opera 9+ and is harder to + author (without using this generator).

+ +

Dynamic publishing

+ +

Description

+ +

Create alternative content using standards compliant markup and embed Flash content with unobtrusive + JavaScript.

+ +

Pros

+ +

Avoids 'click-to-activate' mechanisms in Internet Explorer 6+ and Opera 9+ and is easy to author (even + without using this generator).

+ +

Cons

+ +

The embedding of Flash content relies on JavaScript, so if you have the Flash plug-in installed, but have + JavaScript disabled or use a browser that doesn't support JavaScript, you will not be able to see your + Flash content, however you will see alternative content instead. Flash content will also not be shown on + a device like Sony PSP, which has very poor JavaScript support, and automated tools like RSS readers are + not able to pick up Flash content.

+
+
+ * +
+
+ + . + + . + +
+
 
+
+ +
+
+ + +
+
 
+
+
+ * +
+ +
+

Specifies the id attribute of the HTML container element that will be replaced with Flash content if + enough JavaScript and Flash support is available.

+ +

This HTML container will be generated automatically and will embed your alternative HTML content as + defined in the HTML section.

+
+
 
+
+
+
+
+SWF definition [ - ] +
+
+ * +
+
+ +
+
 
+
+ * +
+
+ + x + + +
+
 
+
+ * +
+
+ +
+
 
+
+
+
+ +
+
+ +
+
 
+
 
+
+ +
+
+ +
+
 
+
 
+
+ +
+
+ +
+
 
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
 
+
 
+
+ +
+
+ +
+
+ +
+
+ +
+
 
+
 
+
+ +
+
+ +
+
+ +
+
+ +
+
 
+
 
+
+ +
+
+ +
+
+ +
+
+ +
+
 
+
 
+
+ +
+
+ +
+
+ +
+
+ +
+
 
+
 
+
+ +
+
+ +
+
+ +
+
+ +
+
 
+
 
+
+ +
+
+ +
+
+ +
+
+ +
+
 
+
 
+
+ +
+
+ +
+
 
+
+ add +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
 
+ +
 
+
+
+
+ HTML definition [ - ] +
+
+ +
+
+ +
+
 
+
+ +
+
+ +
+
 
+
+ +
+ +
+

The object element allows you to nest alternative content inside of it, which will be displayed if Flash + is not installed or supported. + This content will also be picked up by search engines, making it a great tool for creating + search-engine-friendly content.

+ +

Summarized, you should use alternative content for the following:

+
    +
  • When you like to create content that is accessible for people who browse the Web without plugins +
  • +
  • When you like to create search-engine-friendly content
  • +
  • To tell visitors that they can have a richer user experience by downloading the Flash plugin
  • +
+
+
 
+
+ +
+
 
+
+
+
+ + + + + +
+
 
+
+ Generated output [ - ] +
+
+ +
+
 
+
+
+ + diff --git a/vendor/swfobject/swfobject_generator/html/index.html b/vendor/swfobject/swfobject_generator/html/index.html new file mode 100644 index 000000000..fb9bb2798 --- /dev/null +++ b/vendor/swfobject/swfobject_generator/html/index.html @@ -0,0 +1,1142 @@ + + + +SWFObject 2 HTML and JavaScript generator v1.2 + + + + + + +

SWFObject 2 HTML and JavaScript generator v1.2

+ +
Asterisk (*) indicates required field
+
+ SWFObject configuration [ - ] +
+
+ * +
+
+ +
+
 
+
+ * +
+
+ + what is this? +
+
 
+
+

Static publishing

+ +

Description

+ +

Embed Flash content and alternative content using standards compliant markup, and use unobtrusive + JavaScript to resolve the issues that markup alone cannot solve.

+ +

Pros

+ +

The embedding of Flash content does not rely on JavaScript and the actual authoring of standards + compliant markup is promoted.

+ +

Cons

+ +

Does not solve 'click-to-activate' mechanisms in Internet Explorer 6+ and Opera 9+ and is harder to + author (without using this generator).

+ +

Dynamic publishing

+ +

Description

+ +

Create alternative content using standards compliant markup and embed Flash content with unobtrusive + JavaScript.

+ +

Pros

+ +

Avoids 'click-to-activate' mechanisms in Internet Explorer 6+ and Opera 9+ and is easy to author (even + without using this generator).

+ +

Cons

+ +

The embedding of Flash content relies on JavaScript, so if you have the Flash plug-in installed, but have + JavaScript disabled or use a browser that doesn't support JavaScript, you will not be able to see your + Flash content, however you will see alternative content instead. Flash content will also not be shown on + a device like Sony PSP, which has very poor JavaScript support, and automated tools like RSS readers are + not able to pick up Flash content.

+
+
+ * +
+
+ + . + + . + +
+
 
+
+ +
+
+ + +
+
 
+
+
+ * +
+ +
+

Specifies the id attribute of the HTML container element that will be replaced with Flash content if + enough JavaScript and Flash support is available.

+ +

This HTML container will be generated automatically and will embed your alternative HTML content as + defined in the HTML section.

+
+
 
+
+
+
+
+SWF definition [ - ] +
+
+ * +
+
+ +
+
 
+
+ * +
+
+ + x + + +
+
 
+
+ * +
+
+ +
+
 
+
+
+
+ +
+
+ +
+
 
+
 
+
+ +
+
+ +
+
 
+
 
+
+ +
+
+ +
+
 
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
 
+
 
+
+ +
+
+ +
+
+ +
+
+ +
+
 
+
 
+
+ +
+
+ +
+
+ +
+
+ +
+
 
+
 
+
+ +
+
+ +
+
+ +
+
+ +
+
 
+
 
+
+ +
+
+ +
+
+ +
+
+ +
+
 
+
 
+
+ +
+
+ +
+
+ +
+
+ +
+
 
+
 
+
+ +
+
+ +
+
+ +
+
+ +
+
 
+
 
+
+ +
+
+ +
+
 
+
+ add +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
 
+ +
 
+
+
+
+ HTML definition [ - ] +
+
+ +
+
+ +
+
 
+
+ +
+
+ +
+
 
+
+ +
+ +
+

The object element allows you to nest alternative content inside of it, which will be displayed if Flash + is not installed or supported. + This content will also be picked up by search engines, making it a great tool for creating + search-engine-friendly content.

+ +

Summarized, you should use alternative content for the following:

+
    +
  • When you like to create content that is accessible for people who browse the Web without plugins +
  • +
  • When you like to create search-engine-friendly content
  • +
  • To tell visitors that they can have a richer user experience by downloading the Flash plugin
  • +
+
+
 
+
+ +
+
 
+
+
+
+ + +
+
 
+
+ Generated output [ - ] +
+
+ +
+
 
+
+
+ + diff --git a/vendor/twitter-bootstrap-3/.editorconfig b/vendor/twitter-bootstrap-3/.editorconfig new file mode 100644 index 000000000..cf8d7fa6e --- /dev/null +++ b/vendor/twitter-bootstrap-3/.editorconfig @@ -0,0 +1,11 @@ +# editorconfig.org + +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/vendor/twitter-bootstrap-3/.gitignore b/vendor/twitter-bootstrap-3/.gitignore new file mode 100644 index 000000000..392fc3927 --- /dev/null +++ b/vendor/twitter-bootstrap-3/.gitignore @@ -0,0 +1,45 @@ +# Ignore compiled docs +_gh_pages +_site + +# Numerous always-ignore extensions +*.diff +*.err +*.orig +*.log +*.rej +*.swo +*.swp +*.zip +*.vi +*~ +*.sass-cache +*.ruby-version + +# OS or Editor folders +.DS_Store +._* +Thumbs.db +.cache +.project +.settings +.tmproj +*.esproj +nbproject +*.sublime-project +*.sublime-workspace + +# Komodo +*.komodoproject +.komodotools + +# grunt-html-validation +validation-status.json +validation-report.json + +# Folders to ignore +.hg +.svn +.CVS +.idea +node_modules diff --git a/vendor/twitter-bootstrap-3/.travis.travis.yml b/vendor/twitter-bootstrap-3/.travis.travis.yml new file mode 100644 index 000000000..9f2371887 --- /dev/null +++ b/vendor/twitter-bootstrap-3/.travis.travis.yml @@ -0,0 +1,11 @@ +language: node_js +node_js: + - 0.8 +before_script: + - gem install jekyll + - npm install -g grunt-cli +env: + global: + - secure: Besg41eyU+2mfxrywQ4ydOShMdc34ImaO0S0ENP+aCOBuyNBIgP59wy5tBMmyai2/8eInYeVps4Td96mWInMMxzTe3Bar7eTLG5tWVKRSr/wc4NBPZ/ppoPAmCEsz9Y+VptRH9/FO8n7hsL9EFZ+xBKbG+C0SccGoyBDpA5j7/w= + - secure: Ptiv7phCImFP3ALIz+sMQzrZg8k7C1gLZbFBhWxjnQr3g06wIfX3Ls5y9OHvxid+lOZZjISui3wzBVgpVHqwHUYf96+r0mo6/mJ+F4ffUmShZANVaIMD/JRTnXhUQJbvntGLvxn1EYWPdNM+2IHJrMipnjHxU9tkgAnlel4Zdew= + - TWBS_HAVE_OWN_BROWSERSTACK_KEY: "" diff --git a/vendor/twitter-bootstrap-3/CNAME b/vendor/twitter-bootstrap-3/CNAME new file mode 100644 index 000000000..52c853392 --- /dev/null +++ b/vendor/twitter-bootstrap-3/CNAME @@ -0,0 +1 @@ +getbootstrap.com diff --git a/vendor/twitter-bootstrap-3/CONTRIBUTING.md b/vendor/twitter-bootstrap-3/CONTRIBUTING.md new file mode 100644 index 000000000..2cbd6e32c --- /dev/null +++ b/vendor/twitter-bootstrap-3/CONTRIBUTING.md @@ -0,0 +1,58 @@ +# Contributing to Bootstrap + +Looking to contribute something to Bootstrap? **Here's how you can help.** + + + +## Reporting issues + +We only accept issues that are bug reports or feature requests. Bugs must be isolated and reproducible problems that we can fix within the Bootstrap core. Please read the following guidelines before opening any issue. + +1. **Search for existing issues.** We get a lot of duplicate issues, and you'd help us out a lot by first checking if someone else has reported the same issue. Moreover, the issue may have already been resolved with a fix available. +2. **Create an isolated and reproducible test case.** Be sure the problem exists in Bootstrap's code with a [reduced test case](http://css-tricks.com/reduced-test-cases/) that should be included in each bug report. +3. **Include a live example.** Make use of jsFiddle or jsBin to share your isolated test cases. +4. **Share as much information as possible.** Include operating system and version, browser and version, version of Bootstrap, customized or vanilla build, etc. where appropriate. Also include steps to reproduce the bug. + + + +## Pull requests + +- CSS changes must be done in `.less` files first, never just the compiled `.css` files +- If modifying the `.less` files, always recompile and commit the compiled files `bootstrap.css` and `bootstrap.min.css` +- Try not to pollute your pull request with unintended changes--keep them simple and small +- Try to share which browsers your code has been tested in before submitting a pull request +- Pull requests should always be against the `master` branch, never against `gh-pages`. + + + +## Coding standards + +### HTML + +- Two spaces for indentation, never tabs +- Double quotes only, never single quotes +- Always use proper indentation +- Use tags and elements appropriate for an HTML5 doctype (e.g., self-closing tags) + +### CSS + +- Adhere to the [Recess CSS property order](http://markdotto.com/2011/11/29/css-property-order/) +- Multiple-line approach (one property and value per line) +- Always a space after a property's colon (.e.g, `display: block;` and not `display:block;`) +- End all lines with a semi-colon +- For multiple, comma-separated selectors, place each selector on its own line +- Attribute selectors, like `input[type="text"]` should always wrap the attribute's value in double quotes, for consistency and safety (see this [blog post on unquoted attribute values](http://mathiasbynens.be/notes/unquoted-attribute-values) that can lead to XSS attacks). + +### JS + +- No semicolons +- Comma first +- 2 spaces (no tabs) +- strict mode +- "Attractive" + + + +## License + +By contributing your code, you agree to license your contribution under the terms of the APLv2: https://github.com/twbs/bootstrap/blob/master/LICENSE diff --git a/vendor/twitter-bootstrap-3/Gruntfile.js b/vendor/twitter-bootstrap-3/Gruntfile.js new file mode 100644 index 000000000..8a4e2fd53 --- /dev/null +++ b/vendor/twitter-bootstrap-3/Gruntfile.js @@ -0,0 +1,226 @@ +/* jshint node: true */ + +module.exports = function (grunt) +{ + "use strict"; + + // Project configuration. + grunt.initConfig ({ + + // Metadata. + pkg: grunt.file.readJSON ('package.json'), + banner: '/**\n' + + '* Bootstrap v<%= pkg.version %> by @fat and @mdo\n' + + '* Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' + + '* Licensed under <%= _.pluck(pkg.licenses, "url").join(", ") %>.\n' + + '*\n' + + '* Designed and built with all the love in the world by @mdo and @fat.\n' + + '*/\n', + jqueryCheck: 'if (!jQuery) { throw new Error(\"Bootstrap requires jQuery\") }\n\n', + + // Task configuration. + clean: { + dist: ['dist'] + }, + + jshint: { + options: { + jshintrc: 'js/.jshintrc' + }, + gruntfile: { + src: 'Gruntfile.js' + }, + src: { + src: ['js/*.js'] + }, + test: { + src: ['js/tests/unit/*.js'] + } + }, + + concat: { + options: { + banner: '<%= banner %><%= jqueryCheck %>', + stripBanners: false + }, + bootstrap: { + src: [ + 'js/transition.js', + 'js/alert.js', + 'js/button.js', + 'js/carousel.js', + 'js/collapse.js', + 'js/dropdown.js', + 'js/modal.js', + 'js/tooltip.js', + 'js/popover.js', + 'js/scrollspy.js', + 'js/tab.js', + 'js/affix.js' + ], + dest: 'dist/js/<%= pkg.name %>.js' + } + }, + + uglify: { + options: { + banner: '<%= banner %>' + }, + bootstrap: { + src: ['<%= concat.bootstrap.dest %>'], + dest: 'dist/js/<%= pkg.name %>.min.js' + } + }, + + recess: { + options: { + compile: true + }, + bootstrap: { + src: ['less/bootstrap.less'], + dest: 'dist/css/<%= pkg.name %>.css' + }, + min: { + options: { + compress: true + }, + src: ['less/bootstrap.less'], + dest: 'dist/css/<%= pkg.name %>.min.css' + }, + theme: { + src: ['less/theme.less'], + dest: 'dist/css/<%= pkg.name %>-theme.css' + }, + theme_min: { + options: { + compress: true + }, + src: ['less/theme.less'], + dest: 'dist/css/<%= pkg.name %>-theme.min.css' + } + }, + + copy: { + fonts: { + expand: true, + src: ["fonts/*"], + dest: 'dist/' + } + }, + + qunit: { + options: { + inject: 'js/tests/unit/phantom.js' + }, + files: ['js/tests/*.html'] + }, + + connect: { + server: { + options: { + port: 3000, + base: '.' + } + } + }, + + jekyll: { + docs: {} + }, + + validation: { + options: { + reset: true + }, + files: { + src: ["_gh_pages/**/*.html"] + } + }, + + watch: { + src: { + files: '<%= jshint.src.src %>', + tasks: ['jshint:src', 'qunit'] + }, + test: { + files: '<%= jshint.test.src %>', + tasks: ['jshint:test', 'qunit'] + }, + recess: { + files: 'less/*.less', + tasks: ['recess'] + } + } + }); + + + // These plugins provide necessary tasks. + grunt.loadNpmTasks ('grunt-contrib-clean'); + grunt.loadNpmTasks ('grunt-contrib-concat'); + grunt.loadNpmTasks ('grunt-contrib-connect'); + grunt.loadNpmTasks ('grunt-contrib-copy'); + grunt.loadNpmTasks ('grunt-contrib-jshint'); + grunt.loadNpmTasks ('grunt-contrib-qunit'); + grunt.loadNpmTasks ('grunt-contrib-uglify'); + grunt.loadNpmTasks ('grunt-contrib-watch'); + grunt.loadNpmTasks ('grunt-html-validation'); + grunt.loadNpmTasks ('grunt-jekyll'); + grunt.loadNpmTasks ('grunt-recess'); + grunt.loadNpmTasks ('browserstack-runner'); + + // Docs HTML validation task + grunt.registerTask ('validate-html', ['jekyll', 'validation']); + + // Test task. + var testSubtasks = ['dist-css', 'jshint', 'qunit', 'validate-html']; + // Only run BrowserStack tests under Travis + if (process.env.TRAVIS) + { + // Only run BrowserStack tests if this is a mainline commit in twbs/bootstrap, or you have your own BrowserStack key + if ((process.env.TRAVIS_REPO_SLUG === 'twbs/bootstrap' && process.env.TRAVIS_PULL_REQUEST === 'false') || process.env.TWBS_HAVE_OWN_BROWSERSTACK_KEY) + { + testSubtasks.push ('browserstack_runner'); + } + } + grunt.registerTask ('test', testSubtasks); + + // JS distribution task. + grunt.registerTask ('dist-js', ['concat', 'uglify']); + + // CSS distribution task. + grunt.registerTask ('dist-css', ['recess']); + + // Fonts distribution task. + grunt.registerTask ('dist-fonts', ['copy']); + + // Full distribution task. + grunt.registerTask ('dist', ['clean', 'dist-css', 'dist-fonts', 'dist-js']); + + // Default task. + grunt.registerTask ('default', ['test', 'dist', 'build-customizer']); + + // task for building customizer + grunt.registerTask ('build-customizer', 'Add scripts/less files to customizer.', function () + { + var fs = require ('fs') + + function getFiles (type) + { + var files = {} + fs.readdirSync (type) + .filter (function (path) + { + return type == 'fonts' ? true : new RegExp ('\\.' + type + '$').test (path) + }) + .forEach (function (path) + { + return files[path] = fs.readFileSync (type + '/' + path, 'utf8') + }) + return 'var __' + type + ' = ' + JSON.stringify (files) + '\n' + } + + var customize = fs.readFileSync ('customize.html', 'utf-8') + var files = getFiles ('js') + getFiles ('less') + getFiles ('fonts') + fs.writeFileSync ('assets/js/raw-files.js', files) + }); +}; \ No newline at end of file diff --git a/vendor/twitter-bootstrap-3/LICENSE b/vendor/twitter-bootstrap-3/LICENSE new file mode 100644 index 000000000..d9a10c0d8 --- /dev/null +++ b/vendor/twitter-bootstrap-3/LICENSE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/vendor/twitter-bootstrap-3/README.md b/vendor/twitter-bootstrap-3/README.md new file mode 100644 index 000000000..0ef9c6a43 --- /dev/null +++ b/vendor/twitter-bootstrap-3/README.md @@ -0,0 +1,141 @@ +# [Bootstrap](http://getbootstrap.com) [![Build Status](https://secure.travis-ci.org/twbs/bootstrap.png)](http://travis-ci.org/twbs/bootstrap) [![devDependency Status](https://david-dm.org/twbs/bootstrap/dev-status.png)](https://david-dm.org/twbs/bootstrap#info=devDependencies) + +Bootstrap is a sleek, intuitive, and powerful front-end framework for faster and easier web development, created and maintained by [Mark Otto](http://twitter.com/mdo) and [Jacob Thornton](http://twitter.com/fat). + +To get started, check out [http://getbootstrap.com](http://getbootstrap.com)! + + + +## Quick start + +Three quick start options are available: + +* [Download the latest release](https://github.com/twbs/bootstrap/releases/tag/v3.0.0). +* Clone the repo: `git clone git://github.com/twbs/bootstrap.git`. +* Install with [Bower](http://bower.io): `bower install bootstrap`. + +Read the [Getting Started page](http://getbootstrap.com/getting-started/) for information on the framework contents, templates and examples, and more. + + + +## Bugs and feature requests + +Have a bug or a feature request? [Please open a new issue](https://github.com/twbs/bootstrap/issues). Before opening any issue, please search for existing issues and read the [Issue Guidelines](https://github.com/necolas/issue-guidelines), written by [Nicolas Gallagher](https://github.com/necolas/). + +You may use [this JS Bin](http://jsbin.com/aKiCIDO/1/edit) as a template for your bug reports. + + + +## Documentation + +Bootstrap's documentation, included in this repo in the root directory, is built with [Jekyll](http://jekyllrb.com) and publicly hosted on GitHub Pages at [http://getbootstrap.com](http://getbootstrap.com). The docs may also be run locally. + +### Running documentation locally + +1. If necessary, [install Jekyll](http://jekyllrb.com/docs/installation) (requires v1.x). +2. From the root `/bootstrap` directory, run `jekyll serve` in the command line. + - **Windows users:** run `chcp 65001` first to change the command prompt's character encoding ([code page](http://en.wikipedia.org/wiki/Windows_code_page)) to UTF-8 so Jekyll runs without errors. +3. Open [http://localhost:9001](http://localhost:9001) in your browser, and voilà. + +Learn more about using Jekyll by reading their [documentation](http://jekyllrb.com/docs/home/). + +### Documentation for previous releases + +Documentation for v2.3.2 has been made available for the time being at [http://getbootstrap.com/2.3.2/](http://getbootstrap.com/2.3.2/) while folks transition to Bootstrap 3. + +[Previous releases](https://github.com/twbs/bootstrap/releases) and their documentation are also available for download. + + + +## Compiling CSS and JavaScript + +Bootstrap uses [Grunt](http://gruntjs.com/) with convenient methods for working with the framework. It's how we compile our code, run tests, and more. To use it, install the required dependencies as directed and then run some Grunt commands. + +### Install Grunt + +From the command line: + +1. Install `grunt-cli` globally with `npm install -g grunt-cli`. +2. Install the [necessary local dependencies](package.json) via `npm install` + +When completed, you'll be able to run the various Grunt commands provided from the command line. + +**Unfamiliar with `npm`? Don't have node installed?** That's a-okay. npm stands for [node packaged modules](http://npmjs.org/) and is a way to manage development dependencies through node.js. [Download and install node.js](http://nodejs.org/download/) before proceeding. + +### Available Grunt commands + +#### Build - `grunt` +Run `grunt` to run tests locally and compile the CSS and JavaScript into `/dist`. **Uses [recess](http://twitter.github.io/recess/) and [UglifyJS](http://lisperator.net/uglifyjs/).** + +#### Only compile CSS and JavaScript - `grunt dist` +`grunt dist` creates the `/dist` directory with compiled files. **Uses [recess](http://twitter.github.io/recess/) and [UglifyJS](http://lisperator.net/uglifyjs/).** + +#### Tests - `grunt test` +Runs [JSHint](http://jshint.com) and [QUnit](http://qunitjs.com/) tests headlessly in [PhantomJS](http://phantomjs.org/) (used for CI). + +#### Watch - `grunt watch` +This is a convenience method for watching just Less files and automatically building them whenever you save. + +### Troubleshooting dependencies + +Should you encounter problems with installing dependencies or running Grunt commands, uninstall all previous dependency versions (global and local). Then, rerun `npm install`. + + + +## Contributing + +Please read through our [contributing guidelines](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md). Included are directions for opening issues, coding standards, and notes on development. + +More over, if your pull request contains JavaScript patches or features, you must include relevant unit tests. All HTML and CSS should conform to the [Code Guide](http://github.com/mdo/code-guide), maintained by [Mark Otto](http://github.com/mdo). + +Editor preferences are available in the [editor config](.editorconfig) for easy use in common text editors. Read more and download plugins at [http://editorconfig.org](http://editorconfig.org). + + + +## Community + +Keep track of development and community news. + +* Follow [@twbootstrap on Twitter](http://twitter.com/twbootstrap). +* Read and subscribe to the [The Official Bootstrap Blog](http://blog.getbootstrap.com). +* Have a question that's not a feature request or bug report? [Ask on the mailing list.](http://groups.google.com/group/twitter-bootstrap) +* Chat with fellow Bootstrappers in IRC. On the `irc.freenode.net` server, in the `##twitter-bootstrap` channel. + + + + +## Versioning + +For transparency and insight into our release cycle, and for striving to maintain backward compatibility, Bootstrap will be maintained under the Semantic Versioning guidelines as much as possible. + +Releases will be numbered with the following format: + +`..` + +And constructed with the following guidelines: + +* Breaking backward compatibility bumps the major (and resets the minor and patch) +* New additions without breaking backward compatibility bumps the minor (and resets the patch) +* Bug fixes and misc changes bumps the patch + +For more information on SemVer, please visit [http://semver.org/](http://semver.org/). + + + +## Authors + +**Mark Otto** + ++ [http://twitter.com/mdo](http://twitter.com/mdo) ++ [http://github.com/mdo](http://github.com/mdo) + +**Jacob Thornton** + ++ [http://twitter.com/fat](http://twitter.com/fat) ++ [http://github.com/fat](http://github.com/fat) + + + +## Copyright and license + +Copyright 2013 Twitter, Inc under [the Apache 2.0 license](LICENSE). diff --git a/vendor/twitter-bootstrap-3/_config.yml b/vendor/twitter-bootstrap-3/_config.yml new file mode 100644 index 000000000..b93496ae0 --- /dev/null +++ b/vendor/twitter-bootstrap-3/_config.yml @@ -0,0 +1,24 @@ +# Dependencies +markdown: rdiscount +pygments: true + +# Permalinks +permalink: pretty + +# Server +destination: ./_gh_pages +exclude: [".editorconfig", ".gitignore", ".ruby-version", "bower.json", "composer.json", "CONTRIBUTING.md", "CNAME", "LICENSE", "Gruntfile.js", "package.json", "node_modules", "README.md", "less"] +port: 9001 + +# Custom vars +current_version: 3.0.0 +repo: https://github.com/twbs/bootstrap +download: https://github.com/twbs/bootstrap/archive/v3.0.0.zip +download_dist: https://github.com/twbs/bootstrap/releases/download/v3.0.0/bootstrap-3.0.0-dist.zip + +blog: http://blog.getbootstrap.com +expo: http://expo.getbootstrap.com + +cdn_css: //netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css +cdn_theme_css: //netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-theme.min.css +cdn_js: //netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js diff --git a/vendor/twitter-bootstrap-3/_includes/ads.html b/vendor/twitter-bootstrap-3/_includes/ads.html new file mode 100644 index 000000000..c3b920252 --- /dev/null +++ b/vendor/twitter-bootstrap-3/_includes/ads.html @@ -0,0 +1,10 @@ +
+
+
+ +
+
diff --git a/vendor/twitter-bootstrap-3/_includes/footer.html b/vendor/twitter-bootstrap-3/_includes/footer.html new file mode 100644 index 000000000..018032fd3 --- /dev/null +++ b/vendor/twitter-bootstrap-3/_includes/footer.html @@ -0,0 +1,35 @@ + + + + + + + + + + +{% if page.slug == "customize" %} + + + + + + +{% endif %} + + + diff --git a/vendor/twitter-bootstrap-3/_includes/header.html b/vendor/twitter-bootstrap-3/_includes/header.html new file mode 100644 index 000000000..f3e67d670 --- /dev/null +++ b/vendor/twitter-bootstrap-3/_includes/header.html @@ -0,0 +1,49 @@ + + + + + + + {% if page.title == "Bootstrap" %} + {{ page.title }} + {% else %} + {{ page.title }} · Bootstrap + {% endif %} + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/twitter-bootstrap-3/_includes/nav-components.html b/vendor/twitter-bootstrap-3/_includes/nav-components.html new file mode 100644 index 000000000..c5678bbb7 --- /dev/null +++ b/vendor/twitter-bootstrap-3/_includes/nav-components.html @@ -0,0 +1,137 @@ +
  • + Glyphicons + +
  • +
  • + Dropdowns + +
  • +
  • + Button groups + +
  • +
  • + Button dropdowns + +
  • +
  • + Input groups + +
  • +
  • + Navs + +
  • +
  • + Navbar + +
  • +
  • Breadcrumbs
  • +
  • + Pagination + +
  • +
  • Labels
  • +
  • Badges
  • +
  • Jumbotron
  • +
  • Page header
  • +
  • + Thumbnails + +
  • +
  • + Alerts + +
  • +
  • + Progress bars + +
  • +
  • + Media object + +
  • +
  • + List group + +
  • +
  • + Panels + +
  • +
  • Wells
  • diff --git a/vendor/twitter-bootstrap-3/_includes/nav-css.html b/vendor/twitter-bootstrap-3/_includes/nav-css.html new file mode 100644 index 000000000..c11a0578c --- /dev/null +++ b/vendor/twitter-bootstrap-3/_includes/nav-css.html @@ -0,0 +1,95 @@ +
  • + Overview + +
  • +
  • + Grid system + +
  • +
  • + Typography + +
  • +
  • Code
  • +
  • + Tables + +
  • +
  • + Forms + +
  • +
  • + Buttons + +
  • +
  • + Images +
  • +
  • + Helper classes + +
  • +
  • + Responsive utilities + +
  • diff --git a/vendor/twitter-bootstrap-3/_includes/nav-customize.html b/vendor/twitter-bootstrap-3/_includes/nav-customize.html new file mode 100644 index 000000000..e41878d20 --- /dev/null +++ b/vendor/twitter-bootstrap-3/_includes/nav-customize.html @@ -0,0 +1,40 @@ +
  • + LESS components +
  • +
  • + jQuery plugins +
  • +
  • + LESS variables + +
  • +
  • + Download +
  • diff --git a/vendor/twitter-bootstrap-3/_includes/nav-getting-started.html b/vendor/twitter-bootstrap-3/_includes/nav-getting-started.html new file mode 100644 index 000000000..88236bc6f --- /dev/null +++ b/vendor/twitter-bootstrap-3/_includes/nav-getting-started.html @@ -0,0 +1,44 @@ +
  • + Download Bootstrap + +
  • +
  • + What's included +
  • +
  • + Basic template +
  • +
  • + Examples +
  • +
  • + Disabling responsiveness +
  • +
  • + Migrating from 2.x to 3.0 + +
  • +
  • + Browser support +
  • +
  • + Third party support +
  • +
  • + Accessibility +
  • +
  • + License FAQs +
  • +
  • + Customizing Bootstrap +
  • diff --git a/vendor/twitter-bootstrap-3/_includes/nav-javascript.html b/vendor/twitter-bootstrap-3/_includes/nav-javascript.html new file mode 100644 index 000000000..2ec6e7d60 --- /dev/null +++ b/vendor/twitter-bootstrap-3/_includes/nav-javascript.html @@ -0,0 +1,88 @@ +
  • + Overview + +
  • +
  • Transitions
  • +
  • + Modal + +
  • +
  • + Dropdown + +
  • +
  • + Scrollspy + +
  • +
  • + Tab + +
  • +
  • + Tooltip + +
  • +
  • + Popover + +
  • +
  • + Alert + +
  • +
  • + Button + +
  • +
  • + Collapse + +
  • +
  • + Carousel + +
  • +
  • + Affix + +
  • diff --git a/vendor/twitter-bootstrap-3/_includes/nav-main.html b/vendor/twitter-bootstrap-3/_includes/nav-main.html new file mode 100644 index 000000000..3785d0381 --- /dev/null +++ b/vendor/twitter-bootstrap-3/_includes/nav-main.html @@ -0,0 +1,37 @@ + diff --git a/vendor/twitter-bootstrap-3/_includes/old-bs-docs.html b/vendor/twitter-bootstrap-3/_includes/old-bs-docs.html new file mode 100644 index 000000000..1643d0813 --- /dev/null +++ b/vendor/twitter-bootstrap-3/_includes/old-bs-docs.html @@ -0,0 +1,9 @@ +
    +
    + + Looking for Bootstrap 2.3.2 docs? + + We've moved it to a new home while we push forward with Bootstrap 3. Read + the blog for details. +
    +
    diff --git a/vendor/twitter-bootstrap-3/_includes/social-buttons.html b/vendor/twitter-bootstrap-3/_includes/social-buttons.html new file mode 100644 index 000000000..48c4f0b3d --- /dev/null +++ b/vendor/twitter-bootstrap-3/_includes/social-buttons.html @@ -0,0 +1,22 @@ +
    + +
    diff --git a/vendor/twitter-bootstrap-3/_layouts/default.html b/vendor/twitter-bootstrap-3/_layouts/default.html new file mode 100644 index 000000000..9b212fa49 --- /dev/null +++ b/vendor/twitter-bootstrap-3/_layouts/default.html @@ -0,0 +1,83 @@ + + + + + {% include header.html %} + + + +Skip navigation + + +{% include nav-main.html %} + + +
    +
    +

    {{ page.title }}

    + +

    {{ page.lead }}

    + {% include ads.html %} +
    +
    + + +{% include old-bs-docs.html %} + +
    +
    +
    + +
    +
    + {{ content }} +
    +
    + +
    + + + + + +{% include footer.html %} + + + diff --git a/vendor/twitter-bootstrap-3/_layouts/home.html b/vendor/twitter-bootstrap-3/_layouts/home.html new file mode 100644 index 000000000..ed4116070 --- /dev/null +++ b/vendor/twitter-bootstrap-3/_layouts/home.html @@ -0,0 +1,55 @@ + + + + + {% include header.html %} + + + +Skip navigation + + +{% include nav-main.html %} + + +{{ content }} + + + + +{% include footer.html %} + + + diff --git a/vendor/twitter-bootstrap-3/assets/css/docs.css b/vendor/twitter-bootstrap-3/assets/css/docs.css new file mode 100644 index 000000000..fd4f8c4f9 --- /dev/null +++ b/vendor/twitter-bootstrap-3/assets/css/docs.css @@ -0,0 +1,1164 @@ +/* + * Bootstrap Documentation + * Special styles for presenting Bootstrap's documentation and code examples. + * + * Table of contents: + * + * Scaffolding + * Main navigation + * Footer + * Social buttons + * Homepage + * Page headers + * Old docs callout + * Ads + * Side navigation + * Docs sections + * Callouts + * Grid styles + * Examples + * Code snippets (highlight) + * Responsive tests + * Glyphicons + * Customizer + * Miscellaneous + */ + +/* + * Scaffolding + * + * Update the basics of our documents to prep for docs content. + */ + +body { + position: relative; /* For scrollyspy */ + padding-top: 50px; /* Account for fixed navbar */ +} + +/* Keep code small in tables on account of limited space */ +.table code { + font-size: 13px; + font-weight: normal; +} + +/* Outline button for use within the docs */ +.btn-outline { + color: #563d7c; + background-color: #fff; + border-color: #e5e5e5; +} + +.btn-outline:hover, +.btn-outline:focus, +.btn-outline:active { + color: #fff; + background-color: #563d7c; + border-color: #563d7c; +} + +/* Inverted outline button (white on dark) */ +.btn-outline-inverse { + color: #fff; + background-color: transparent; + border-color: #cdbfe3; +} + +.btn-outline-inverse:hover, +.btn-outline-inverse:focus, +.btn-outline-inverse:active { + color: #563d7c; + text-shadow: none; + background-color: #fff; + border-color: #fff; +} + +/* + * Main navigation + * + * Turn the `.navbar` at the top of the docs purple. + */ + +.bs-docs-nav { + text-shadow: 0 -1px 0 rgba(0, 0, 0, .15); + background-color: #563d7c; + border-color: #463265; + box-shadow: 0 1px 0 rgba(255, 255, 255, .1); +} + +.bs-docs-nav .navbar-collapse { + border-color: #463265; +} + +.bs-docs-nav .navbar-brand { + color: #fff; +} + +.bs-docs-nav .navbar-nav > li > a { + color: #cdbfe3; +} + +.bs-docs-nav .navbar-nav > li > a:hover { + color: #fff; +} + +.bs-docs-nav .navbar-nav > .active > a, +.bs-docs-nav .navbar-nav > .active > a:hover { + color: #fff; + background-color: #463265; +} + +.bs-docs-nav .navbar-toggle { + border-color: #563d7c; +} + +.bs-docs-nav .navbar-toggle:hover { + background-color: #463265; + border-color: #463265; +} + +/* + * Footer + * + * Separated section of content at the bottom of all pages, save the homepage. + */ + +.bs-footer { + padding-top: 40px; + padding-bottom: 30px; + margin-top: 100px; + color: #777; + text-align: center; + border-top: 1px solid #e5e5e5; +} + +.footer-links { + margin: 10px 0; + padding-left: 0; +} + +.footer-links li { + display: inline; + padding: 0 2px; +} + +.footer-links li:first-child { + padding-left: 0; +} + +@media (min-width: 768px) { + .bs-footer { + text-align: left; + } + + .bs-footer p { + margin-bottom: 0; + } +} + +/* + * Social buttons + * + * Twitter and GitHub social action buttons (for homepage and footer). + */ + +.bs-social { + margin-top: 20px; + margin-bottom: 20px; + text-align: center; +} + +.bs-social-buttons { + display: inline-block; + margin-bottom: 0; + padding-left: 0; + list-style: none; +} + +.bs-social-buttons li { + display: inline-block; + line-height: 1; + padding: 5px 8px; +} + +.bs-social-buttons .twitter-follow-button { + width: 225px !important; +} + +.bs-social-buttons .twitter-share-button { + width: 98px !important; +} + +/* Style the GitHub buttons via CSS instead of inline attributes */ +.github-btn { + border: 0; + overflow: hidden; +} + +@media screen and (min-width: 768px) { + .bs-social { + text-align: left; + } + + .bs-social-buttons li:first-child { + padding-left: 0; + } +} + +/* + * Topography, yo! + * + * Apply the map background via base64 and relevant colors where we need 'em. + */ + +.bs-docs-home, +.bs-header { + color: #cdbfe3; + background-color: #563d7c; + background-image: url(data:image/png;base64,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); +} + +/* + * Homepage + * + * Tweaks to the custom homepage and the masthead (main jumbotron). + */ + +/* Masthead (headings and download button) */ +.bs-masthead { + position: relative; + padding: 30px 15px; + text-align: center; + text-shadow: 0 1px 0 rgba(0, 0, 0, .15); +} + +.bs-masthead h1 { + font-size: 50px; + line-height: 1; + color: #fff; +} + +.bs-masthead .btn-outline { + margin-top: 20px; + margin-bottom: 20px; + padding: 18px 24px; + font-size: 21px; +} + +/* Links to project-level content like the repo, Expo, etc */ +.bs-masthead-links { + margin-top: 20px; + margin-bottom: 20px; + padding: 0 15px; + list-style: none; + text-align: center; +} + +.bs-masthead-links li { + display: inline; +} + +.bs-masthead-links li + li { + margin-left: 20px; +} + +.bs-masthead-links a { + color: #fff; +} + +@media screen and (min-width: 768px) { + .bs-masthead { + text-align: left; + padding-top: 140px; + padding-bottom: 140px; + } + + .bs-masthead h1 { + font-size: 100px; + } + + .bs-masthead .lead { + margin-right: 25%; + font-size: 30px; + } + + .bs-masthead-links { + padding: 0; + text-align: left; + } +} + +/* + * Page headers + * + * Jumbotron-esque headers at the top of every page that's not the homepage. + */ + +/* Page headers */ +.bs-header { + padding: 30px 15px 40px; /* side padding builds on .container 15px, so 30px */ + font-size: 16px; + text-align: center; + text-shadow: 0 1px 0 rgba(0, 0, 0, .15); +} + +.bs-header h1 { + color: #fff; +} + +.bs-header p { + font-weight: 300; + line-height: 1.5; +} + +.bs-header .container { + position: relative; +} + +@media screen and (min-width: 768px) { + .bs-header { + font-size: 21px; + text-align: left; + } + + .bs-header h1 { + font-size: 60px; + line-height: 1; + } +} + +@media screen and (min-width: 992px) { + .bs-header h1, + .bs-header p { + margin-right: 380px; + } +} + +/* + * Carbon ads + * + * Single display ad that shows on all pages (except homepage) in page headers. + * The hella `!important` is required for any pre-set property. + */ + +.carbonad { + width: auto !important; + margin: 50px -30px -40px !important; + padding: 20px !important; + overflow: hidden; /* clearfix */ + height: auto !important; + font-size: 13px !important; + line-height: 16px !important; + text-align: left; + background: #463265 !important; + border: 0 !important; + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .075); +} + +.carbonad-img { + margin: 0 !important; +} + +.carbonad-text, +.carbonad-tag { + float: none !important; + display: block !important; + width: auto !important; + height: auto !important; + margin-left: 145px !important; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif !important; +} + +.carbonad-text { + padding-top: 0 !important; +} + +.carbonad-tag { + color: #cdbfe3 !important; + text-align: left !important; +} + +.carbonad-text a, +.carbonad-tag a { + color: #fff !important; +} + +.carbonad #azcarbon > img { + display: none; /* hide what I assume are tracking images */ +} + +@media screen and (min-width: 768px) { + .carbonad { + margin: 0 !important; + border-radius: 4px; + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .075), 0 1px 0 rgba(255, 255, 255, .1); + } +} + +@media screen and (min-width: 992px) { + .carbonad { + position: absolute; + top: 20px; + right: 0; + padding: 15px !important; + width: 330px !important; + min-height: 132px; + } +} + +/* + * Callout for 2.3.2 docs + * + * Only appears below page headers (not on the homepage). The homepage gets its + * own link with the masthead links. + */ + +.bs-old-docs { + padding: 15px 20px; + color: #777; + background-color: #fafafa; + border-top: 1px solid #fff; + border-bottom: 1px solid #e5e5e5; +} + +.bs-old-docs strong { + color: #555; +} + +/* + * Side navigation + * + * Scrollspy and affixed enhanced navigation to highlight sections and secondary + * sections of docs content. + */ + +/* By default it's not affixed in mobile views, so undo that */ +.bs-sidebar.affix { + position: static; +} + +/* First level of nav */ +.bs-sidenav { + margin-top: 30px; + margin-bottom: 30px; + padding-top: 10px; + padding-bottom: 10px; + text-shadow: 0 1px 0 #fff; + background-color: #f7f5fa; + border-radius: 5px; +} + +/* All levels of nav */ +.bs-sidebar .nav > li > a { + display: block; + color: #716b7a; + padding: 5px 20px; +} + +.bs-sidebar .nav > li > a:hover, +.bs-sidebar .nav > li > a:focus { + text-decoration: none; + background-color: #e5e3e9; + border-right: 1px solid #dbd8e0; +} + +.bs-sidebar .nav > .active > a, +.bs-sidebar .nav > .active:hover > a, +.bs-sidebar .nav > .active:focus > a { + font-weight: bold; + color: #563d7c; + background-color: transparent; + border-right: 1px solid #563d7c; +} + +/* Nav: second level (shown on .active) */ +.bs-sidebar .nav .nav { + display: none; /* Hide by default, but at >768px, show it */ + margin-bottom: 8px; +} + +.bs-sidebar .nav .nav > li > a { + padding-top: 3px; + padding-bottom: 3px; + padding-left: 30px; + font-size: 90%; +} + +/* Show and affix the side nav when space allows it */ +@media screen and (min-width: 992px) { + .bs-sidebar .nav > .active > ul { + display: block; + } + + /* Widen the fixed sidebar */ + .bs-sidebar.affix, + .bs-sidebar.affix-bottom { + width: 213px; + } + + .bs-sidebar.affix { + position: fixed; /* Undo the static from mobile first approach */ + top: 80px; + } + + .bs-sidebar.affix-bottom { + position: absolute; /* Undo the static from mobile first approach */ + } + + .bs-sidebar.affix-bottom .bs-sidenav, + .bs-sidebar.affix .bs-sidenav { + margin-top: 0; + margin-bottom: 0; + } +} + +@media screen and (min-width: 1200px) { + /* Widen the fixed sidebar again */ + .bs-sidebar.affix-bottom, + .bs-sidebar.affix { + width: 263px; + } +} + +/* + * Docs sections + * + * Content blocks for each component or feature. + */ + +/* Space things out */ +.bs-docs-section + .bs-docs-section { + padding-top: 40px; +} + +/* Janky fix for preventing navbar from overlapping */ +h1[id] { + padding-top: 80px; + margin-top: -45px; +} + +/* + * Callouts + * + * Not quite alerts, but custom and helpful notes for folks reading the docs. + * Requires a base and modifier class. + */ + +/* Common styles for all types */ +.bs-callout { + margin: 20px 0; + padding: 15px 30px 15px 15px; + border-left: 5px solid #eee; +} + +.bs-callout h4 { + margin-top: 0; +} + +.bs-callout p:last-child { + margin-bottom: 0; +} + +.bs-callout code, +.bs-callout .highlight { + background-color: #fff; +} + +/* Variations */ +.bs-callout-danger { + background-color: #fcf2f2; + border-color: #dFb5b4; +} + +.bs-callout-warning { + background-color: #fefbed; + border-color: #f1e7bc; +} + +.bs-callout-info { + background-color: #f0f7fd; + border-color: #d0e3f0; +} + +/* + * Grid examples + * + * Highlight the grid columns within the docs so folks can see their padding, + * alignment, sizing, etc. + */ + +.show-grid { + margin-bottom: 15px; +} + +.show-grid [class^="col-"] { + padding-top: 10px; + padding-bottom: 10px; + background-color: #eee; + border: 1px solid #ddd; + background-color: rgba(86, 61, 124, .15); + border: 1px solid rgba(86, 61, 124, .2); +} + +/* + * Examples + * + * Isolated sections of example content for each component or feature. Usually + * followed by a code snippet. + */ + +.bs-example { + position: relative; + padding: 45px 15px 15px; + margin: 0 -15px 15px; + background-color: #fafafa; + box-shadow: inset 0 3px 6px rgba(0, 0, 0, .05); + border-color: #e5e5e5 #eee #eee; + border-style: solid; + border-width: 1px 0; +} + +/* Echo out a label for the example */ +.bs-example:after { + content: "Example"; + position: absolute; + top: 15px; + left: 15px; + font-size: 12px; + font-weight: bold; + color: #bbb; + text-transform: uppercase; + letter-spacing: 1px; +} + +/* Tweak display of the code snippets when following an example */ +.bs-example + .highlight { + margin: -15px -15px 15px; + border-radius: 0; + border-width: 0 0 1px; +} + +/* Make the examples and snippets not full-width */ +@media screen and (min-width: 768px) { + .bs-example { + margin-left: 0; + margin-right: 0; + background-color: #fff; + border-width: 1px; + border-color: #ddd; + border-radius: 4px 4px 0 0; + box-shadow: none; + } + + .bs-example + .highlight { + margin-top: -16px; + margin-left: 0; + margin-right: 0; + border-width: 1px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + } +} + +/* Tweak content of examples for optimum awesome */ +.bs-example > p:last-child, +.bs-example > ul:last-child, +.bs-example > ol:last-child, +.bs-example > blockquote:last-child, +.bs-example > .form-control:last-child, +.bs-example > .table:last-child, +.bs-example > .navbar:last-child, +.bs-example > .jumbotron:last-child, +.bs-example > .alert:last-child, +.bs-example > .panel:last-child, +.bs-example > .list-group:last-child, +.bs-example > .well:last-child, +.bs-example > .progress:last-child, +.bs-example > .table-responsive:last-child > .table { + margin-bottom: 0; +} + +.bs-example > p > .close { + float: none; +} + +/* Typography */ +.bs-example-type .table .info { + color: #999; + vertical-align: middle; +} + +.bs-example-type .table td { + padding: 15px 0; + border-color: #eee; +} + +.bs-example-type .table tr:first-child td { + border-top: 0; +} + +.bs-example-type h1, +.bs-example-type h2, +.bs-example-type h3, +.bs-example-type h4, +.bs-example-type h5, +.bs-example-type h6 { + margin: 0; +} + +/* Images */ +.bs-example > .img-circle, +.bs-example > .img-rounded, +.bs-example > .img-thumbnail { + margin: 5px; +} + +/* Buttons */ +.bs-example > .btn, +.bs-example > .btn-group { + margin-top: 5px; + margin-bottom: 5px; +} + +.bs-example > .btn-toolbar + .btn-toolbar { + margin-top: 10px; +} + +/* Forms */ +.bs-example-control-sizing select, +.bs-example-control-sizing input[type="text"] + input[type="text"] { + margin-top: 10px; +} + +.bs-example-form .input-group { + margin-bottom: 10px; +} + +.bs-example > textarea.form-control { + resize: vertical; +} + +/* List groups */ +.bs-example > .list-group { + max-width: 400px; +} + +/* Navbars */ +.bs-example .navbar:last-child { + margin-bottom: 0; +} + +.bs-navbar-top-example, +.bs-navbar-bottom-example { + z-index: 1; + padding: 0; + overflow: hidden; /* cut the drop shadows off */ +} + +.bs-navbar-top-example .navbar-header, +.bs-navbar-bottom-example .navbar-header { + margin-left: 0; +} + +.bs-navbar-top-example .navbar-fixed-top, +.bs-navbar-bottom-example .navbar-fixed-bottom { + position: relative; + margin-left: 0; + margin-right: 0; +} + +.bs-navbar-top-example { + padding-bottom: 45px; +} + +.bs-navbar-top-example:after { + top: auto; + bottom: 15px; +} + +.bs-navbar-top-example .navbar-fixed-top { + top: -1px; +} + +.bs-navbar-bottom-example { + padding-top: 45px; +} + +.bs-navbar-bottom-example .navbar-fixed-bottom { + bottom: -1px; +} + +.bs-navbar-bottom-example .navbar { + margin-bottom: 0; +} + +@media (min-width: 768px) { + .bs-navbar-top-example .navbar-fixed-top, + .bs-navbar-bottom-example .navbar-fixed-bottom { + position: absolute; + } + + .bs-navbar-top-example { + border-radius: 0 0 4px 4px; + } + + .bs-navbar-bottom-example { + border-radius: 4px 4px 0 0; + } +} + +/* Pagination */ +.bs-example .pagination { + margin-top: 10px; + margin-bottom: 10px; +} + +/* Pager */ +.bs-example > .pager { + margin-top: 0; +} + +/* Example modals */ +.bs-example-modal { + background-color: #f5f5f5; +} + +.bs-example-modal .modal { + position: relative; + top: auto; + right: auto; + left: auto; + bottom: auto; + z-index: 1; + display: block; +} + +.bs-example-modal .modal-dialog { + left: auto; + margin-left: auto; + margin-right: auto; +} + +/* Example dropdowns */ +.bs-example > .dropdown > .dropdown-menu { + position: static; + display: block; + margin-bottom: 5px; +} + +/* Example tabbable tabs */ +.bs-example-tabs .nav-tabs { + margin-bottom: 15px; +} + +/* Tooltips */ +.bs-example-tooltips { + text-align: center; +} + +.bs-example-tooltips > .btn { + margin-top: 5px; + margin-bottom: 5px; +} + +/* Popovers */ +.bs-example-popover { + padding-bottom: 24px; + background-color: #f9f9f9; +} + +.bs-example-popover .popover { + position: relative; + display: block; + float: left; + width: 260px; + margin: 20px; +} + +/* Scrollspy demo on fixed height div */ +.scrollspy-example { + position: relative; + height: 200px; + margin-top: 10px; + overflow: auto; +} + +/* + * Code snippets + * + * Generated via Pygments and Jekyll, these are snippets of HTML, CSS, and JS. + */ + +.highlight { + display: none; /* hidden by default, until >480px */ + padding: 9px 14px; + margin-bottom: 14px; + background-color: #f7f7f9; + border: 1px solid #e1e1e8; + border-radius: 4px; +} + +.highlight pre { + padding: 0; + margin-top: 0; + margin-bottom: 0; + background-color: transparent; + border: 0; + white-space: nowrap; +} + +.highlight pre code { + font-size: inherit; + color: #333; /* Effectively the base text color */ +} + +.highlight pre .lineno { + display: inline-block; + width: 22px; + padding-right: 5px; + margin-right: 10px; + text-align: right; + color: #bebec5; +} + +/* Show code snippets when we have the space */ +@media screen and (min-width: 481px) { + .highlight { + display: block; + } +} + +/* + * Responsive tests + * + * Generate a set of tests to show the responsive utilities in action. + */ + +/* Responsive (scrollable) doc tables */ +.table-responsive .highlight pre { + white-space: normal; +} + +/* Utility classes table */ +.bs-table th small, +.responsive-utilities th small { + display: block; + font-weight: normal; + color: #999; +} + +.responsive-utilities tbody th { + font-weight: normal; +} + +.responsive-utilities td { + text-align: center; +} + +.responsive-utilities td.is-visible { + color: #468847; + background-color: #dff0d8 !important; +} + +.responsive-utilities td.is-hidden { + color: #ccc; + background-color: #f9f9f9 !important; +} + +/* Responsive tests */ +.responsive-utilities-test { + margin-top: 5px; +} + +.responsive-utilities-test .col-xs-6 { + margin-bottom: 10px; +} + +.responsive-utilities-test span { + padding: 15px 10px; + font-size: 14px; + font-weight: bold; + line-height: 1.1; + text-align: center; + border-radius: 4px; +} + +.visible-on .col-xs-6 .hidden-xs, +.visible-on .col-xs-6 .hidden-sm, +.visible-on .col-xs-6 .hidden-md, +.visible-on .col-xs-6 .hidden-lg, +.hidden-on .col-xs-6 .visible-xs, +.hidden-on .col-xs-6 .visible-sm, +.hidden-on .col-xs-6 .visible-md, +.hidden-on .col-xs-6 .visible-lg { + color: #999; + border: 1px solid #ddd; +} + +.visible-on .col-xs-6 .visible-xs, +.visible-on .col-xs-6 .visible-sm, +.visible-on .col-xs-6 .visible-md, +.visible-on .col-xs-6 .visible-lg, +.hidden-on .col-xs-6 .hidden-xs, +.hidden-on .col-xs-6 .hidden-sm, +.hidden-on .col-xs-6 .hidden-md, +.hidden-on .col-xs-6 .hidden-lg { + color: #468847; + background-color: #dff0d8; + border: 1px solid #d6e9c6; +} + +/* + * Glyphicons + * + * Special styles for displaying the icons and their classes in the docs. + */ + +.bs-glyphicons { + padding-left: 0; + padding-bottom: 1px; + margin-bottom: 20px; + list-style: none; + overflow: hidden; +} + +.bs-glyphicons li { + float: left; + width: 25%; + height: 115px; + padding: 10px; + margin: 0 -1px -1px 0; + font-size: 12px; + line-height: 1.4; + text-align: center; + border: 1px solid #ddd; +} + +.bs-glyphicons .glyphicon { + display: block; + margin: 5px auto 10px; + font-size: 24px; +} + +.bs-glyphicons li:hover { + background-color: rgba(86, 61, 124, .1); +} + +@media (min-width: 768px) { + .bs-glyphicons li { + width: 12.5%; + } +} + +/* + * Customizer + * + * Since this is so form control heavy, we have quite a few styles to customize + * the display of inputs, headings, and more. Also included are all the download + * buttons and actions. + */ + +.bs-customizer .toggle { + float: right; + margin-top: 85px; /* On account of ghetto navbar fix */ +} + +/* Headings and form contrls */ +.bs-customizer label { + margin-top: 10px; + font-weight: 500; + color: #444; +} + +.bs-customizer h2 { + margin-top: 0; + margin-bottom: 5px; + padding-top: 30px; +} + +.bs-customizer h4 { + margin-top: 15px; +} + +.bs-customizer input[type="text"] { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + background-color: #fafafa; +} + +.bs-customizer .help-block { + font-size: 12px; +} + +/* For the variables, use regular weight */ +#less-section label { + font-weight: normal; +} + +/* Downloads */ +.bs-customize-download .btn-outline { + padding: 20px; +} + +/* Error handling */ +.bs-customizer-alert { + position: fixed; + top: 51px; + left: 0; + right: 0; + z-index: 1030; + padding: 15px 0; + color: #fff; + background-color: #d9534f; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25); + border-bottom: 1px solid #b94441; +} + +.bs-customizer-alert .close { + margin-top: -4px; + font-size: 24px; +} + +.bs-customizer-alert p { + margin-bottom: 0; +} + +.bs-customizer-alert .glyphicon { + margin-right: 5px; +} + +.bs-customizer-alert pre { + margin: 10px 0 0; + color: #fff; + background-color: #a83c3a; + border-color: #973634; + box-shadow: inset 0 2px 4px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); +} + +/* + * Miscellaneous + * + * Odds and ends for optimum docs display. + */ + +/* Examples gallery: space out content better */ +.bs-examples h4 { + margin-bottom: 5px; +} + +.bs-examples p { + margin-bottom: 20px; +} + +/* Pseudo :focus state for showing how it looks in the docs */ +#focusedInput { + border-color: rgba(82, 168, 236, .8); + outline: 0; + outline: thin dotted \9; /* IE6-9 */ + -moz-box-shadow: 0 0 8px rgba(82, 168, 236, .6); + box-shadow: 0 0 8px rgba(82, 168, 236, .6); +} + +/* Better spacing on download options in getting started */ +.bs-docs-dl-options h4 { + margin-top: 15px; + margin-bottom: 5px; +} diff --git a/vendor/twitter-bootstrap-3/assets/css/pygments-manni.css b/vendor/twitter-bootstrap-3/assets/css/pygments-manni.css new file mode 100644 index 000000000..7867c1cc4 --- /dev/null +++ b/vendor/twitter-bootstrap-3/assets/css/pygments-manni.css @@ -0,0 +1,315 @@ +.hll { + background-color: #ffffcc +} + +/*{ background: #f0f3f3; }*/ +.c { + color: #999; +} + +/* Comment */ +.err { + color: #AA0000; + background-color: #FFAAAA +} + +/* Error */ +.k { + color: #006699; +} + +/* Keyword */ +.o { + color: #555555 +} + +/* Operator */ +.cm { + color: #0099FF; + font-style: italic +} + +/* Comment.Multiline */ +.cp { + color: #009999 +} + +/* Comment.Preproc */ +.c1 { + color: #999; +} + +/* Comment.Single */ +.cs { + color: #999; +} + +/* Comment.Special */ +.gd { + background-color: #FFCCCC; + border: 1px solid #CC0000 +} + +/* Generic.Deleted */ +.ge { + font-style: italic +} + +/* Generic.Emph */ +.gr { + color: #FF0000 +} + +/* Generic.Error */ +.gh { + color: #003300; +} + +/* Generic.Heading */ +.gi { + background-color: #CCFFCC; + border: 1px solid #00CC00 +} + +/* Generic.Inserted */ +.go { + color: #AAAAAA +} + +/* Generic.Output */ +.gp { + color: #000099; +} + +/* Generic.Prompt */ +.gs { +} + +/* Generic.Strong */ +.gu { + color: #003300; +} + +/* Generic.Subheading */ +.gt { + color: #99CC66 +} + +/* Generic.Traceback */ +.kc { + color: #006699; +} + +/* Keyword.Constant */ +.kd { + color: #006699; +} + +/* Keyword.Declaration */ +.kn { + color: #006699; +} + +/* Keyword.Namespace */ +.kp { + color: #006699 +} + +/* Keyword.Pseudo */ +.kr { + color: #006699; +} + +/* Keyword.Reserved */ +.kt { + color: #007788; +} + +/* Keyword.Type */ +.m { + color: #FF6600 +} + +/* Literal.Number */ +.s { + color: #d44950 +} + +/* Literal.String */ +.na { + color: #4f9fcf +} + +/* Name.Attribute */ +.nb { + color: #336666 +} + +/* Name.Builtin */ +.nc { + color: #00AA88; +} + +/* Name.Class */ +.no { + color: #336600 +} + +/* Name.Constant */ +.nd { + color: #9999FF +} + +/* Name.Decorator */ +.ni { + color: #999999; +} + +/* Name.Entity */ +.ne { + color: #CC0000; +} + +/* Name.Exception */ +.nf { + color: #CC00FF +} + +/* Name.Function */ +.nl { + color: #9999FF +} + +/* Name.Label */ +.nn { + color: #00CCFF; +} + +/* Name.Namespace */ +.nt { + color: #2f6f9f; +} + +/* Name.Tag */ +.nv { + color: #003333 +} + +/* Name.Variable */ +.ow { + color: #000000; +} + +/* Operator.Word */ +.w { + color: #bbbbbb +} + +/* Text.Whitespace */ +.mf { + color: #FF6600 +} + +/* Literal.Number.Float */ +.mh { + color: #FF6600 +} + +/* Literal.Number.Hex */ +.mi { + color: #FF6600 +} + +/* Literal.Number.Integer */ +.mo { + color: #FF6600 +} + +/* Literal.Number.Oct */ +.sb { + color: #CC3300 +} + +/* Literal.String.Backtick */ +.sc { + color: #CC3300 +} + +/* Literal.String.Char */ +.sd { + color: #CC3300; + font-style: italic +} + +/* Literal.String.Doc */ +.s2 { + color: #CC3300 +} + +/* Literal.String.Double */ +.se { + color: #CC3300; +} + +/* Literal.String.Escape */ +.sh { + color: #CC3300 +} + +/* Literal.String.Heredoc */ +.si { + color: #AA0000 +} + +/* Literal.String.Interpol */ +.sx { + color: #CC3300 +} + +/* Literal.String.Other */ +.sr { + color: #33AAAA +} + +/* Literal.String.Regex */ +.s1 { + color: #CC3300 +} + +/* Literal.String.Single */ +.ss { + color: #FFCC33 +} + +/* Literal.String.Symbol */ +.bp { + color: #336666 +} + +/* Name.Builtin.Pseudo */ +.vc { + color: #003333 +} + +/* Name.Variable.Class */ +.vg { + color: #003333 +} + +/* Name.Variable.Global */ +.vi { + color: #003333 +} + +/* Name.Variable.Instance */ +.il { + color: #FF6600 +} + +/* Literal.Number.Integer.Long */ + +.css .o, +.css .o + .nt, +.css .nt + .nt { + color: #999; +} diff --git a/vendor/twitter-bootstrap-3/assets/ico/apple-touch-icon-114-precomposed.png b/vendor/twitter-bootstrap-3/assets/ico/apple-touch-icon-114-precomposed.png new file mode 100644 index 000000000..d8597a12b Binary files /dev/null and b/vendor/twitter-bootstrap-3/assets/ico/apple-touch-icon-114-precomposed.png differ diff --git a/vendor/twitter-bootstrap-3/assets/ico/apple-touch-icon-144-precomposed.png b/vendor/twitter-bootstrap-3/assets/ico/apple-touch-icon-144-precomposed.png new file mode 100644 index 000000000..22ef08a43 Binary files /dev/null and b/vendor/twitter-bootstrap-3/assets/ico/apple-touch-icon-144-precomposed.png differ diff --git a/vendor/twitter-bootstrap-3/assets/ico/apple-touch-icon-57-precomposed.png b/vendor/twitter-bootstrap-3/assets/ico/apple-touch-icon-57-precomposed.png new file mode 100644 index 000000000..8e139fdf0 Binary files /dev/null and b/vendor/twitter-bootstrap-3/assets/ico/apple-touch-icon-57-precomposed.png differ diff --git a/vendor/twitter-bootstrap-3/assets/ico/apple-touch-icon-72-precomposed.png b/vendor/twitter-bootstrap-3/assets/ico/apple-touch-icon-72-precomposed.png new file mode 100644 index 000000000..e262c24af Binary files /dev/null and b/vendor/twitter-bootstrap-3/assets/ico/apple-touch-icon-72-precomposed.png differ diff --git a/vendor/twitter-bootstrap-3/assets/ico/favicon.png b/vendor/twitter-bootstrap-3/assets/ico/favicon.png new file mode 100644 index 000000000..56aa877f2 Binary files /dev/null and b/vendor/twitter-bootstrap-3/assets/ico/favicon.png differ diff --git a/vendor/twitter-bootstrap-3/assets/js/application.js b/vendor/twitter-bootstrap-3/assets/js/application.js new file mode 100644 index 000000000..45b101a75 --- /dev/null +++ b/vendor/twitter-bootstrap-3/assets/js/application.js @@ -0,0 +1,92 @@ +// NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT +// IT'S ALL JUST JUNK FOR OUR DOCS! +// ++++++++++++++++++++++++++++++++++++++++++ + +!function ($) +{ + + $ (function () + { + + var $window = $ (window) + var $body = $ (document.body) + + var navHeight = $ ('.navbar').outerHeight (true) + 10 + + $body.scrollspy ({ + target: '.bs-sidebar', + offset: navHeight + }) + + $window.on ('load', function () + { + $body.scrollspy ('refresh') + }) + + $ ('.bs-docs-container [href=#]').click (function (e) + { + e.preventDefault () + }) + + // back to top + setTimeout (function () + { + var $sideBar = $ ('.bs-sidebar') + + $sideBar.affix ({ + offset: { + top: function () + { + var offsetTop = $sideBar.offset ().top + var sideBarMargin = parseInt ($sideBar.children (0).css ('margin-top'), 10) + var navOuterHeight = $ ('.bs-docs-nav').height () + + return (this.top = offsetTop - navOuterHeight - sideBarMargin) + }, bottom: function () + { + return (this.bottom = $ ('.bs-footer').outerHeight (true)) + } + } + }) + }, 100) + + setTimeout (function () + { + $ ('.bs-top').affix () + }, 100) + + // tooltip demo + $ ('.tooltip-demo').tooltip ({ + selector: "[data-toggle=tooltip]", + container: "body" + }) + + $ ('.tooltip-test').tooltip () + $ ('.popover-test').popover () + + $ ('.bs-docs-navbar').tooltip ({ + selector: "a[data-toggle=tooltip]", + container: ".bs-docs-navbar .nav" + }) + + // popover demo + $ ("[data-toggle=popover]") + .popover () + + // button state demo + $ ('#fat-btn') + .click (function () + { + var btn = $ (this) + btn.button ('loading') + setTimeout (function () + { + btn.button ('reset') + }, 3000) + }) + + // carousel demo + $ ('.bs-docs-carousel-example').carousel () + }) + +} (window.jQuery) diff --git a/vendor/twitter-bootstrap-3/assets/js/customizer.js b/vendor/twitter-bootstrap-3/assets/js/customizer.js new file mode 100644 index 000000000..d2f540a16 --- /dev/null +++ b/vendor/twitter-bootstrap-3/assets/js/customizer.js @@ -0,0 +1,349 @@ +window.onload = function () +{ // wait for load in a dumb way because B-0 + var cw = '/*!\n * Bootstrap v3.0.0\n *\n * Copyright 2013 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\n' + + function showError (msg, err) + { + $ ('
    \ +
    \ + ×\ +

    ' + msg + '

    ' + + (err.extract ? '
    ' + err.extract.join ('\n') + '
    ' : '') + '\ +
    \ +
    ').appendTo ('body').alert () + throw err + } + + function showCallout (msg, showUpTop) + { + var callout = $ ('
    \ +

    Attention!

    \ +

    ' + msg + '

    \ +
    ') + + if (showUpTop) + { + callout.appendTo ('.bs-docs-container') + } else + { + callout.insertAfter ('.bs-customize-download') + } + } + + function getQueryParam (key) + { + key = key.replace (/[*+?^$.\[\]{}()|\\\/]/g, "\\$&"); // escape RegEx meta chars + var match = location.search.match (new RegExp ("[?&]" + key + "=([^&]+)(&|$)")); + return match && decodeURIComponent (match[1].replace (/\+/g, " ")); + } + + function createGist (configData) + { + var data = { + "description": "Bootstrap Customizer Config", + "public": true, + "files": { + "config.json": { + "content": JSON.stringify (configData, null, 2) + } + } + } + $.ajax ({ + url: 'https://api.github.com/gists', + type: 'POST', + dataType: 'json', + data: JSON.stringify (data) + }) + .success (function (result) + { + history.replaceState (false, document.title, window.location.origin + window.location.pathname + '?id=' + result.id) + }) + .error (function (err) + { + showError ('Ruh roh! Could not save gist file, configuration not saved.', err) + }) + } + + function getCustomizerData () + { + var vars = {} + + $ ('#less-variables-section input') + .each (function () + { + $ (this).val () && (vars[ $ (this).prev ().text () ] = $ (this).val ()) + }) + + var data = { + vars: vars, + css: $ ('#less-section input:checked').map (function () + { + return this.value + }).toArray (), + js: $ ('#plugin-section input:checked').map (function () + { + return this.value + }).toArray () + } + + if ($.isEmptyObject (data.vars) && !data.css.length && !data.js.length) return + + return data + } + + function parseUrl () + { + var id = getQueryParam ('id') + + if (!id) return + + $.ajax ({ + url: 'https://api.github.com/gists/' + id, + type: 'GET', + dataType: 'json' + }) + .success (function (result) + { + var data = JSON.parse (result.files['config.json'].content) + if (data.js) + { + $ ('#plugin-section input').each (function () + { + $ (this).prop ('checked', ~$.inArray (this.value, data.js)) + }) + } + if (data.css) + { + $ ('#less-section input').each (function () + { + $ (this).prop ('checked', ~$.inArray (this.value, data.css)) + }) + } + if (data.vars) + { + for (var i in data.vars) + { + $ ('input[data-var="' + i + '"]').val (data.vars[i]) + } + } + }) + .error (function (err) + { + showError ('Error fetching bootstrap config file', err) + }) + } + + function generateZip (css, js, fonts, complete) + { + if (!css && !js) return showError ('Ruh roh! No Bootstrap files selected.', new Error ('no Bootstrap')) + + var zip = new JSZip () + + if (css) + { + var cssFolder = zip.folder ('css') + for (var fileName in css) + { + cssFolder.file (fileName, css[fileName]) + } + } + + if (js) + { + var jsFolder = zip.folder ('js') + for (var fileName in js) + { + jsFolder.file (fileName, js[fileName]) + } + } + + if (fonts) + { + var fontsFolder = zip.folder ('fonts') + for (var fileName in fonts) + { + fontsFolder.file (fileName, fonts[fileName]) + } + } + + var content = zip.generate ({type: "blob"}) + + complete (content) + } + + function generateCustomCSS (vars) + { + var result = '' + + for (var key in vars) + { + result += key + ': ' + vars[key] + ';\n' + } + + return result + '\n\n' + } + + function generateFonts () + { + var glyphicons = $ ('#less-section [value="glyphicons.less"]:checked') + if (glyphicons.length) + { + return __fonts + } + } + + function generateCSS () + { + var $checked = $ ('#less-section input:checked') + + if (!$checked.length) return false + + var result = {} + var vars = {} + var css = '' + + $ ('#less-variables-section input') + .each (function () + { + $ (this).val () && (vars[ $ (this).prev ().text () ] = $ (this).val ()) + }) + + css += __less['variables.less'] + if (vars) css += generateCustomCSS (vars) + css += __less['mixins.less'] + css += __less['normalize.less'] + css += __less['scaffolding.less'] + css += $checked + .map (function () + { + return __less[this.value] + }) + .toArray () + .join ('\n') + + css = css.replace (/@import[^\n]*/gi, '') //strip any imports + + try + { + var parser = new less.Parser ({ + paths: ['variables.less', 'mixins.less'], optimization: 0, filename: 'bootstrap.css' + }).parse (css, function (err, tree) + { + if (err) + { + return showError ('Ruh roh! Could not parse less files.', err) + } + result = { + 'bootstrap.css': cw + tree.toCSS (), + 'bootstrap.min.css': cw + tree.toCSS ({ compress: true }) + } + }) + } catch (err) + { + return showError ('Ruh roh! Could not parse less files.', err) + } + + return result + } + + function generateJavascript () + { + var $checked = $ ('#plugin-section input:checked') + if (!$checked.length) return false + + var js = $checked + .map (function () + { + return __js[this.value] + }) + .toArray () + .join ('\n') + + return { + 'bootstrap.js': js, + 'bootstrap.min.js': cw + uglify (js) + } + } + + var inputsComponent = $ ('#less-section input') + var inputsPlugin = $ ('#plugin-section input') + var inputsVariables = $ ('#less-variables-section input') + + $ ('#less-section .toggle').on ('click', function (e) + { + e.preventDefault () + inputsComponent.prop ('checked', !inputsComponent.is (':checked')) + }) + + $ ('#plugin-section .toggle').on ('click', function (e) + { + e.preventDefault () + inputsPlugin.prop ('checked', !inputsPlugin.is (':checked')) + }) + + $ ('#less-variables-section .toggle').on ('click', function (e) + { + e.preventDefault () + inputsVariables.val ('') + }) + + $ ('[data-dependencies]').on ('click', function () + { + if (!$ (this).is (':checked')) return + var dependencies = this.getAttribute ('data-dependencies') + if (!dependencies) return + dependencies = dependencies.split (',') + for (var i = 0; i < dependencies.length; i++) + { + var dependency = $ ('[value="' + dependencies[i] + '"]') + dependency && dependency.prop ('checked', true) + } + }) + + $ ('[data-dependents]').on ('click', function () + { + if ($ (this).is (':checked')) return + var dependents = this.getAttribute ('data-dependents') + if (!dependents) return + dependents = dependents.split (',') + for (var i = 0; i < dependents.length; i++) + { + var dependent = $ ('[value="' + dependents[i] + '"]') + dependent && dependent.prop ('checked', false) + } + }) + + var $compileBtn = $ ('#btn-compile') + var $downloadBtn = $ ('#btn-download') + + $compileBtn.on ('click', function (e) + { + e.preventDefault () + + $compileBtn.attr ('disabled', 'disabled') + + generateZip (generateCSS (), generateJavascript (), generateFonts (), function (blob) + { + $compileBtn.removeAttr ('disabled') + saveAs (blob, "bootstrap.zip") + createGist (getCustomizerData ()) + }) + }) + + // browser support alerts + if (!window.URL && navigator.userAgent.toLowerCase ().indexOf ('safari') != -1) + { + showCallout ("Looks like you're using safari, which sadly doesn't have the best support\ + for HTML5 blobs. Because of this your file will be downloaded with the name \"untitled\".\ + However, if you check your downloads folder, just rename this \"untitled\" file\ + to \"bootstrap.zip\" and you should be good to go!") + } else if (!window.URL && !window.webkitURL) + { + $ ('.bs-docs-section, .bs-sidebar').css ('display', 'none') + + showCallout ("Looks like your current browser doesn't support the Bootstrap Customizer. Please take a second\ + to upgrade to a more modern browser.", true) + } + + parseUrl () +} diff --git a/vendor/twitter-bootstrap-3/assets/js/filesaver.js b/vendor/twitter-bootstrap-3/assets/js/filesaver.js new file mode 100644 index 000000000..8f0ab8c67 --- /dev/null +++ b/vendor/twitter-bootstrap-3/assets/js/filesaver.js @@ -0,0 +1,400 @@ +/* Blob.js + * A Blob implementation. + * 2013-06-20 + * + * By Eli Grey, http://eligrey.com + * By Devin Samarin, https://github.com/eboyjr + * License: X11/MIT + * See LICENSE.md + */ + +/*global self, unescape */ +/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, + plusplus: true */ + +/*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */ + +if (typeof Blob !== "function" || typeof URL === "undefined") + if (typeof Blob === "function" && typeof webkitURL !== "undefined") self.URL = webkitURL; + else var Blob = (function (view) + { + "use strict"; + + var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || view.MSBlobBuilder || (function (view) + { + var + get_class = function (object) + { + return Object.prototype.toString.call (object).match (/^\[object\s(.*)\]$/)[1]; + } + , FakeBlobBuilder = function BlobBuilder () + { + this.data = []; + } + , FakeBlob = function Blob (data, type, encoding) + { + this.data = data; + this.size = data.length; + this.type = type; + this.encoding = encoding; + } + , FBB_proto = FakeBlobBuilder.prototype + , FB_proto = FakeBlob.prototype + , FileReaderSync = view.FileReaderSync + , FileException = function (type) + { + this.code = this[this.name = type]; + } + , file_ex_codes = ( + "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " + + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR" + ).split (" ") + , file_ex_code = file_ex_codes.length + , real_URL = view.URL || view.webkitURL || view + , real_create_object_URL = real_URL.createObjectURL + , real_revoke_object_URL = real_URL.revokeObjectURL + , URL = real_URL + , btoa = view.btoa + , atob = view.atob + + , ArrayBuffer = view.ArrayBuffer + , Uint8Array = view.Uint8Array + ; + FakeBlob.fake = FB_proto.fake = true; + while (file_ex_code--) + { + FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1; + } + if (!real_URL.createObjectURL) + { + URL = view.URL = {}; + } + URL.createObjectURL = function (blob) + { + var + type = blob.type + , data_URI_header + ; + if (type === null) + { + type = "application/octet-stream"; + } + if (blob instanceof FakeBlob) + { + data_URI_header = "data:" + type; + if (blob.encoding === "base64") + { + return data_URI_header + ";base64," + blob.data; + } else if (blob.encoding === "URI") + { + return data_URI_header + "," + decodeURIComponent (blob.data); + } + if (btoa) + { + return data_URI_header + ";base64," + btoa (blob.data); + } else + { + return data_URI_header + "," + encodeURIComponent (blob.data); + } + } else if (real_create_object_URL) + { + return real_create_object_URL.call (real_URL, blob); + } + }; + URL.revokeObjectURL = function (object_URL) + { + if (object_URL.substring (0, 5) !== "data:" && real_revoke_object_URL) + { + real_revoke_object_URL.call (real_URL, object_URL); + } + }; + FBB_proto.append = function (data/*, endings*/) + { + var bb = this.data; + // decode data to a binary string + if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) + { + var + str = "" + , buf = new Uint8Array (data) + , i = 0 + , buf_len = buf.length + ; + for (; i < buf_len; i++) + { + str += String.fromCharCode (buf[i]); + } + bb.push (str); + } else if (get_class (data) === "Blob" || get_class (data) === "File") + { + if (FileReaderSync) + { + var fr = new FileReaderSync; + bb.push (fr.readAsBinaryString (data)); + } else + { + // async FileReader won't work as BlobBuilder is sync + throw new FileException ("NOT_READABLE_ERR"); + } + } else if (data instanceof FakeBlob) + { + if (data.encoding === "base64" && atob) + { + bb.push (atob (data.data)); + } else if (data.encoding === "URI") + { + bb.push (decodeURIComponent (data.data)); + } else if (data.encoding === "raw") + { + bb.push (data.data); + } + } else + { + if (typeof data !== "string") + { + data += ""; // convert unsupported types to strings + } + // decode UTF-16 to binary string + bb.push (unescape (encodeURIComponent (data))); + } + }; + FBB_proto.getBlob = function (type) + { + if (!arguments.length) + { + type = null; + } + return new FakeBlob (this.data.join (""), type, "raw"); + }; + FBB_proto.toString = function () + { + return "[object BlobBuilder]"; + }; + FB_proto.slice = function (start, end, type) + { + var args = arguments.length; + if (args < 3) + { + type = null; + } + return new FakeBlob ( + this.data.slice (start, args > 1 ? end : this.data.length) + , type + , this.encoding + ); + }; + FB_proto.toString = function () + { + return "[object Blob]"; + }; + return FakeBlobBuilder; + } (view)); + + return function Blob (blobParts, options) + { + var type = options ? (options.type || "") : ""; + var builder = new BlobBuilder (); + if (blobParts) + { + for (var i = 0, len = blobParts.length; i < len; i++) + { + builder.append (blobParts[i]); + } + } + return builder.getBlob (type); + }; + } (self)); + +/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ +var saveAs = saveAs || (navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind (navigator)) || (function (h) +{ + "use strict"; + var r = h.document, l = function () + { + return h.URL || h.webkitURL || h + }, e = h.URL || h.webkitURL || h, n = r.createElementNS ("http://www.w3.org/1999/xhtml", "a"), g = !h.externalHost && "download" in n, j = function (t) + { + var s = r.createEvent ("MouseEvents"); + s.initMouseEvent ("click", true, false, h, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + t.dispatchEvent (s) + }, o = h.webkitRequestFileSystem, p = h.requestFileSystem || o || h.mozRequestFileSystem, m = function (s) + { + (h.setImmediate || h.setTimeout) (function () + { + throw s + }, 0) + }, c = "application/octet-stream", k = 0, b = [], i = function () + { + var t = b.length; + while (t--) + { + var s = b[t]; + if (typeof s === "string") + { + e.revokeObjectURL (s) + } else + { + s.remove () + } + } + b.length = 0 + }, q = function (t, s, w) + { + s = [].concat (s); + var v = s.length; + while (v--) + { + var x = t["on" + s[v]]; + if (typeof x === "function") + { + try + { + x.call (t, w || t) + } catch (u) + { + m (u) + } + } + } + }, f = function (t, u) + { + var v = this, B = t.type, E = false, x, w, s = function () + { + var F = l ().createObjectURL (t); + b.push (F); + return F + }, A = function () + { + q (v, "writestart progress write writeend".split (" ")) + }, D = function () + { + if (E || !x) + { + x = s (t) + } + if (w) + { + w.location.href = x + } else + { + window.open (x, "_blank") + } + v.readyState = v.DONE; + A () + }, z = function (F) + { + return function () + { + if (v.readyState !== v.DONE) + { + return F.apply (this, arguments) + } + } + }, y = {create: true, exclusive: false}, C; + v.readyState = v.INIT; + if (!u) + { + u = "download" + } + if (g) + { + x = s (t); + n.href = x; + n.download = u; + j (n); + v.readyState = v.DONE; + A (); + return + } + if (h.chrome && B && B !== c) + { + C = t.slice || t.webkitSlice; + t = C.call (t, 0, t.size, c); + E = true + } + if (o && u !== "download") + { + u += ".download" + } + if (B === c || o) + { + w = h + } + if (!p) + { + D (); + return + } + k += t.size; + p (h.TEMPORARY, k, z (function (F) + { + F.root.getDirectory ("saved", y, z (function (G) + { + var H = function () + { + G.getFile (u, y, z (function (I) + { + I.createWriter (z (function (J) + { + J.onwriteend = function (K) + { + w.location.href = I.toURL (); + b.push (I); + v.readyState = v.DONE; + q (v, "writeend", K) + }; + J.onerror = function () + { + var K = J.error; + if (K.code !== K.ABORT_ERR) + { + D () + } + }; + "writestart progress write abort".split (" ").forEach (function (K) + { + J["on" + K] = v["on" + K] + }); + J.write (t); + v.abort = function () + { + J.abort (); + v.readyState = v.DONE + }; + v.readyState = v.WRITING + }), D) + }), D) + }; + G.getFile (u, {create: false}, z (function (I) + { + I.remove (); + H () + }), z (function (I) + { + if (I.code === I.NOT_FOUND_ERR) + { + H () + } else + { + D () + } + })) + }), D) + }), D) + }, d = f.prototype, a = function (s, t) + { + return new f (s, t) + }; + d.abort = function () + { + var s = this; + s.readyState = s.DONE; + q (s, "abort") + }; + d.readyState = d.INIT = 0; + d.WRITING = 1; + d.DONE = 2; + d.error = d.onwritestart = d.onprogress = d.onwrite = d.onabort = d.onerror = d.onwriteend = null; + h.addEventListener ("unload", i, false); + return a +} (self)); \ No newline at end of file diff --git a/vendor/twitter-bootstrap-3/assets/js/holder.js b/vendor/twitter-bootstrap-3/assets/js/holder.js new file mode 100644 index 000000000..16ca037a1 --- /dev/null +++ b/vendor/twitter-bootstrap-3/assets/js/holder.js @@ -0,0 +1,564 @@ +/* + + Holder - 2.0 - client side image placeholders + (c) 2012-2013 Ivan Malopinsky / http://imsky.co + + Provided under the Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0 + Commercial use requires attribution. + + */ + +var Holder = Holder || {}; +(function (app, win) +{ + + var preempted = false, + fallback = false, + canvas = document.createElement ('canvas'); + + //getElementsByClassName polyfill + document.getElementsByClassName || (document.getElementsByClassName = function (e) + { + var t = document, n, r, i, s = []; + if (t.querySelectorAll)return t.querySelectorAll ("." + e); + if (t.evaluate) + { + r = ".//*[contains(concat(' ', @class, ' '), ' " + e + " ')]", n = t.evaluate (r, t, null, 0, null); + while (i = n.iterateNext ())s.push (i) + } else + { + n = t.getElementsByTagName ("*"), r = new RegExp ("(^|\\s)" + e + "(\\s|$)"); + for (i = 0; i < n.length; i++)r.test (n[i].className) && s.push (n[i]) + } + return s + }) + + //getComputedStyle polyfill + window.getComputedStyle || (window.getComputedStyle = function (e, t) + { + return this.el = e, this.getPropertyValue = function (t) + { + var n = /(\-([a-z]){1})/g; + return t == "float" && (t = "styleFloat"), n.test (t) && (t = t.replace (n, function () + { + return arguments[2].toUpperCase () + })), e.currentStyle[t] ? e.currentStyle[t] : null + }, this + }) + + //http://javascript.nwbox.com/ContentLoaded by Diego Perini with modifications + function contentLoaded (n, t) + { + var l = "complete", s = "readystatechange", u = !1, h = u, c = !0, i = n.document, a = i.documentElement, e = i.addEventListener ? "addEventListener" : "attachEvent", v = i.addEventListener ? "removeEventListener" : "detachEvent", f = i.addEventListener ? "" : "on", r = function (e) + { + (e.type != s || i.readyState == l) && ((e.type == "load" ? n : i)[v] (f + e.type, r, u), !h && (h = !0) && t.call (n, null)) + }, o = function () + { + try + { + a.doScroll ("left") + } catch (n) + { + setTimeout (o, 50); + return + } + r ("poll") + }; + if (i.readyState == l)t.call (n, "lazy"); else + { + if (i.createEventObject && a.doScroll) + { + try + { + c = !n.frameElement + } catch (y) + { + } + c && o () + } + i[e] (f + "DOMContentLoaded", r, u), i[e] (f + s, r, u), n[e] (f + "load", r, u) + } + }; + + //https://gist.github.com/991057 by Jed Schmidt with modifications + function selector (a) + { + a = a.match (/^(\W)?(.*)/); + var b = document["getElement" + (a[1] ? a[1] == "#" ? "ById" : "sByClassName" : "sByTagName")] (a[2]); + var ret = []; + b != null && (b.length ? ret = b : b.length == 0 ? ret = b : ret = [b]); + return ret; + } + + //shallow object property extend + function extend (a, b) + { + var c = {}; + for (var d in a)c[d] = a[d]; + for (var e in b)c[e] = b[e]; + return c + } + + //hasOwnProperty polyfill + if (!Object.prototype.hasOwnProperty) + Object.prototype.hasOwnProperty = function (prop) + { + var proto = this.__proto__ || this.constructor.prototype; + return (prop in this) && (!(prop in proto) || proto[prop] !== this[prop]); + } + + function text_size (width, height, template) + { + height = parseInt (height, 10); + width = parseInt (width, 10); + var bigSide = Math.max (height, width) + var smallSide = Math.min (height, width) + var scale = 1 / 12; + var newHeight = Math.min (smallSide * 0.75, 0.75 * bigSide * scale); + return { + height: Math.round (Math.max (template.size, newHeight)) + } + } + + function draw (ctx, dimensions, template, ratio) + { + var ts = text_size (dimensions.width, dimensions.height, template); + var text_height = ts.height; + var width = dimensions.width * ratio, + height = dimensions.height * ratio; + var font = template.font ? template.font : "sans-serif"; + canvas.width = width; + canvas.height = height; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + ctx.fillStyle = template.background; + ctx.fillRect (0, 0, width, height); + ctx.fillStyle = template.foreground; + ctx.font = "bold " + text_height + "px " + font; + var text = template.text ? template.text : (Math.floor (dimensions.width) + "x" + Math.floor (dimensions.height)); + var text_width = ctx.measureText (text).width; + if (text_width / width >= 0.75) + { + text_height = Math.floor (text_height * 0.75 * (width / text_width)); + } + //Resetting font size if necessary + ctx.font = "bold " + (text_height * ratio) + "px " + font; + ctx.fillText (text, (width / 2), (height / 2), width); + return canvas.toDataURL ("image/png"); + } + + function render (mode, el, holder, src) + { + var dimensions = holder.dimensions, + theme = holder.theme, + text = holder.text ? decodeURIComponent (holder.text) : holder.text; + var dimensions_caption = dimensions.width + "x" + dimensions.height; + theme = (text ? extend (theme, { + text: text + }) : theme); + theme = (holder.font ? extend (theme, { + font: holder.font + }) : theme); + if (mode == "image") + { + el.setAttribute ("data-src", src); + el.setAttribute ("alt", text ? text : theme.text ? theme.text + " [" + dimensions_caption + "]" : dimensions_caption); + if (fallback || !holder.auto) + { + el.style.width = dimensions.width + "px"; + el.style.height = dimensions.height + "px"; + } + if (fallback) + { + el.style.backgroundColor = theme.background; + } else + { + el.setAttribute ("src", draw (ctx, dimensions, theme, ratio)); + } + } else if (mode == "background") + { + if (!fallback) + { + el.style.backgroundImage = "url(" + draw (ctx, dimensions, theme, ratio) + ")"; + el.style.backgroundSize = dimensions.width + "px " + dimensions.height + "px"; + } + } else if (mode == "fluid") + { + el.setAttribute ("data-src", src); + el.setAttribute ("alt", text ? text : theme.text ? theme.text + " [" + dimensions_caption + "]" : dimensions_caption); + if (dimensions.height.substr (-1) == "%") + { + el.style.height = dimensions.height + } else + { + el.style.height = dimensions.height + "px" + } + if (dimensions.width.substr (-1) == "%") + { + el.style.width = dimensions.width + } else + { + el.style.width = dimensions.width + "px" + } + if (el.style.display == "inline" || el.style.display == "") + { + el.style.display = "block"; + } + if (fallback) + { + el.style.backgroundColor = theme.background; + } else + { + el.holderData = holder; + fluid_images.push (el); + fluid_update (el); + } + } + }; + + function fluid_update (element) + { + var images; + if (element.nodeType == null) + { + images = fluid_images; + } else + { + images = [element] + } + for (i in images) + { + var el = images[i] + if (el.holderData) + { + var holder = el.holderData; + el.setAttribute ("src", draw (ctx, { + height: el.clientHeight, + width: el.clientWidth + }, holder.theme, ratio)); + } + } + } + + function parse_flags (flags, options) + { + + var ret = { + theme: settings.themes.gray + }, render = false; + + for (sl = flags.length, j = 0; j < sl; j++) + { + var flag = flags[j]; + if (app.flags.dimensions.match (flag)) + { + render = true; + ret.dimensions = app.flags.dimensions.output (flag); + } else if (app.flags.fluid.match (flag)) + { + render = true; + ret.dimensions = app.flags.fluid.output (flag); + ret.fluid = true; + } else if (app.flags.colors.match (flag)) + { + ret.theme = app.flags.colors.output (flag); + } else if (options.themes[flag]) + { + //If a theme is specified, it will override custom colors + ret.theme = options.themes[flag]; + } else if (app.flags.text.match (flag)) + { + ret.text = app.flags.text.output (flag); + } else if (app.flags.font.match (flag)) + { + ret.font = app.flags.font.output (flag); + } else if (app.flags.auto.match (flag)) + { + ret.auto = true; + } + } + + return render ? ret : false; + + }; + + + if (!canvas.getContext) + { + fallback = true; + } else + { + if (canvas.toDataURL ("image/png") + .indexOf ("data:image/png") < 0) + { + //Android doesn't support data URI + fallback = true; + } else + { + var ctx = canvas.getContext ("2d"); + } + } + + var dpr = 1, bsr = 1; + + if (!fallback) + { + dpr = window.devicePixelRatio || 1, + bsr = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1; + } + + var ratio = dpr / bsr; + + var fluid_images = []; + + var settings = { + domain: "holder.js", + images: "img", + bgnodes: ".holderjs", + themes: { + "gray": { + background: "#eee", + foreground: "#aaa", + size: 12 + }, + "social": { + background: "#3a5a97", + foreground: "#fff", + size: 12 + }, + "industrial": { + background: "#434A52", + foreground: "#C2F200", + size: 12 + } + }, + stylesheet: ".holderjs-fluid {font-size:16px;font-weight:bold;text-align:center;font-family:sans-serif;margin:0}" + }; + + + app.flags = { + dimensions: { + regex: /^(\d+)x(\d+)$/, + output: function (val) + { + var exec = this.regex.exec (val); + return { + width: +exec[1], + height: +exec[2] + } + } + }, + fluid: { + regex: /^([0-9%]+)x([0-9%]+)$/, + output: function (val) + { + var exec = this.regex.exec (val); + return { + width: exec[1], + height: exec[2] + } + } + }, + colors: { + regex: /#([0-9a-f]{3,})\:#([0-9a-f]{3,})/i, + output: function (val) + { + var exec = this.regex.exec (val); + return { + size: settings.themes.gray.size, + foreground: "#" + exec[2], + background: "#" + exec[1] + } + } + }, + text: { + regex: /text\:(.*)/, + output: function (val) + { + return this.regex.exec (val)[1]; + } + }, + font: { + regex: /font\:(.*)/, + output: function (val) + { + return this.regex.exec (val)[1]; + } + }, + auto: { + regex: /^auto$/ + } + } + + for (var flag in app.flags) + { + if (!app.flags.hasOwnProperty (flag)) continue; + app.flags[flag].match = function (val) + { + return val.match (this.regex) + } + } + + app.add_theme = function (name, theme) + { + name != null && theme != null && (settings.themes[name] = theme); + return app; + }; + + app.add_image = function (src, el) + { + var node = selector (el); + if (node.length) + { + for (var i = 0, l = node.length; i < l; i++) + { + var img = document.createElement ("img") + img.setAttribute ("data-src", src); + node[i].appendChild (img); + } + } + return app; + }; + + app.run = function (o) + { + var options = extend (settings, o), + images = [], imageNodes = [], bgnodes = []; + + if (typeof(options.images) == "string") + { + imageNodes = selector (options.images); + } + else if (window.NodeList && options.images instanceof window.NodeList) + { + imageNodes = options.images; + } else if (window.Node && options.images instanceof window.Node) + { + imageNodes = [options.images]; + } + + if (typeof(options.bgnodes) == "string") + { + bgnodes = selector (options.bgnodes); + } else if (window.NodeList && options.elements instanceof window.NodeList) + { + bgnodes = options.bgnodes; + } else if (window.Node && options.bgnodes instanceof window.Node) + { + bgnodes = [options.bgnodes]; + } + + preempted = true; + + for (i = 0, l = imageNodes.length; i < l; i++) images.push (imageNodes[i]); + + var holdercss = document.getElementById ("holderjs-style"); + if (!holdercss) + { + holdercss = document.createElement ("style"); + holdercss.setAttribute ("id", "holderjs-style"); + holdercss.type = "text/css"; + document.getElementsByTagName ("head")[0].appendChild (holdercss); + } + + if (!options.nocss) + { + if (holdercss.styleSheet) + { + holdercss.styleSheet.cssText += options.stylesheet; + } else + { + holdercss.appendChild (document.createTextNode (options.stylesheet)); + } + } + + var cssregex = new RegExp (options.domain + "\/(.*?)\"?\\)"); + + for (var l = bgnodes.length, i = 0; i < l; i++) + { + var src = window.getComputedStyle (bgnodes[i], null) + .getPropertyValue ("background-image"); + var flags = src.match (cssregex); + var bgsrc = bgnodes[i].getAttribute ("data-background-src"); + + if (flags) + { + var holder = parse_flags (flags[1].split ("/"), options); + if (holder) + { + render ("background", bgnodes[i], holder, src); + } + } + else if (bgsrc != null) + { + var holder = parse_flags (bgsrc.substr (bgsrc.lastIndexOf (options.domain) + options.domain.length + 1) + .split ("/"), options); + if (holder) + { + render ("background", bgnodes[i], holder, src); + } + } + } + + for (l = images.length, i = 0; i < l; i++) + { + + var attr_src = attr_data_src = src = null; + + try + { + attr_src = images[i].getAttribute ("src"); + attr_datasrc = images[i].getAttribute ("data-src"); + } catch (e) + { + } + + if (attr_datasrc == null && !!attr_src && attr_src.indexOf (options.domain) >= 0) + { + src = attr_src; + } else if (!!attr_datasrc && attr_datasrc.indexOf (options.domain) >= 0) + { + src = attr_datasrc; + } + + if (src) + { + var holder = parse_flags (src.substr (src.lastIndexOf (options.domain) + options.domain.length + 1) + .split ("/"), options); + if (holder) + { + if (holder.fluid) + { + render ("fluid", images[i], holder, src) + } else + { + render ("image", images[i], holder, src); + } + } + } + } + return app; + }; + + contentLoaded (win, function () + { + if (window.addEventListener) + { + window.addEventListener ("resize", fluid_update, false); + window.addEventListener ("orientationchange", fluid_update, false); + } else + { + window.attachEvent ("onresize", fluid_update) + } + preempted || app.run (); + }); + + if (typeof define === "function" && define.amd) + { + define ("Holder", [], function () + { + return app; + }); + } + +}) (Holder, window); diff --git a/vendor/twitter-bootstrap-3/assets/js/html5shiv.js b/vendor/twitter-bootstrap-3/assets/js/html5shiv.js new file mode 100644 index 000000000..464994870 --- /dev/null +++ b/vendor/twitter-bootstrap-3/assets/js/html5shiv.js @@ -0,0 +1,91 @@ +/* + HTML5 Shiv v3.6.2pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed + */ +(function (l, f) +{ + function m () + { + var a = e.elements; + return"string" == typeof a ? a.split (" ") : a + } + + function i (a) + { + var b = n[a[o]]; + b || (b = {}, h++, a[o] = h, n[h] = b); + return b + } + + function p (a, b, c) + { + b || (b = f); + if (g)return b.createElement (a); + c || (c = i (b)); + b = c.cache[a] ? c.cache[a].cloneNode () : r.test (a) ? (c.cache[a] = c.createElem (a)).cloneNode () : c.createElem (a); + return b.canHaveChildren && !s.test (a) ? c.frag.appendChild (b) : b + } + + function t (a, b) + { + if (!b.cache)b.cache = {}, b.createElem = a.createElement, b.createFrag = a.createDocumentFragment, b.frag = b.createFrag (); + a.createElement = function (c) + { + return!e.shivMethods ? b.createElem (c) : p (c, a, b) + }; + a.createDocumentFragment = Function ("h,f", "return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&(" + m ().join ().replace (/\w+/g, function (a) + { + b.createElem (a); + b.frag.createElement (a); + return'c("' + a + '")' + }) + ");return n}") (e, b.frag) + } + + function q (a) + { + a || (a = f); + var b = i (a); + if (e.shivCSS && !j && !b.hasCSS) + { + var c, d = a; + c = d.createElement ("p"); + d = d.getElementsByTagName ("head")[0] || d.documentElement; + c.innerHTML = "x"; + c = d.insertBefore (c.lastChild, d.firstChild); + b.hasCSS = !!c + } + g || t (a, b); + return a + } + + var k = l.html5 || {}, s = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i, r = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i, j, o = "_html5shiv", h = 0, n = {}, g; + (function () + { + try + { + var a = f.createElement ("a"); + a.innerHTML = ""; + j = "hidden"in a; + var b; + if (!(b = 1 == a.childNodes.length)) + { + f.createElement ("a"); + var c = f.createDocumentFragment (); + b = "undefined" == typeof c.cloneNode || + "undefined" == typeof c.createDocumentFragment || "undefined" == typeof c.createElement + } + g = b + } catch (d) + { + g = j = !0 + } + }) (); + var e = {elements: k.elements || "abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video", version: "3.6.2pre", shivCSS: !1 !== k.shivCSS, supportsUnknownElements: g, shivMethods: !1 !== k.shivMethods, type: "default", shivDocument: q, createElement: p, createDocumentFragment: function (a, b) + { + a || (a = f); + if (g)return a.createDocumentFragment (); + for (var b = b || i (a), c = b.frag.cloneNode (), d = 0, e = m (), h = e.length; d < h; d++)c.createElement (e[d]); + return c + }}; + l.html5 = e; + q (f) +}) (this, document); diff --git a/vendor/twitter-bootstrap-3/assets/js/jquery.js b/vendor/twitter-bootstrap-3/assets/js/jquery.js new file mode 100644 index 000000000..32e39c4d2 --- /dev/null +++ b/vendor/twitter-bootstrap-3/assets/js/jquery.js @@ -0,0 +1,2960 @@ +/*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license + //@ sourceMappingURL=jquery-1.10.2.min.map + */ +(function (e, t) +{ + var n, r, i = typeof t, o = e.location, a = e.document, s = a.documentElement, l = e.jQuery, u = e.$, c = {}, p = [], f = "1.10.2", d = p.concat, h = p.push, g = p.slice, m = p.indexOf, y = c.toString, v = c.hasOwnProperty, b = f.trim, x = function (e, t) + { + return new x.fn.init (e, t, r) + }, w = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, T = /\S+/g, C = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, N = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, k = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, E = /^[\],:{}\s]*$/, S = /(?:^|:|,)(?:\s*\[)+/g, A = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, j = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, D = /^-ms-/, L = /-([\da-z])/gi, H = function (e, t) + { + return t.toUpperCase () + }, q = function (e) + { + (a.addEventListener || "load" === e.type || "complete" === a.readyState) && (_ (), x.ready ()) + }, _ = function () + { + a.addEventListener ? (a.removeEventListener ("DOMContentLoaded", q, !1), e.removeEventListener ("load", q, !1)) : (a.detachEvent ("onreadystatechange", q), e.detachEvent ("onload", q)) + }; + x.fn = x.prototype = {jquery: f, constructor: x, init: function (e, n, r) + { + var i, o; + if (!e)return this; + if ("string" == typeof e) + { + if (i = "<" === e.charAt (0) && ">" === e.charAt (e.length - 1) && e.length >= 3 ? [null, e, null] : N.exec (e), !i || !i[1] && n)return!n || n.jquery ? (n || r).find (e) : this.constructor (n).find (e); + if (i[1]) + { + if (n = n instanceof x ? n[0] : n, x.merge (this, x.parseHTML (i[1], n && n.nodeType ? n.ownerDocument || n : a, !0)), k.test (i[1]) && x.isPlainObject (n))for (i in n)x.isFunction (this[i]) ? this[i] (n[i]) : this.attr (i, n[i]); + return this + } + if (o = a.getElementById (i[2]), o && o.parentNode) + { + if (o.id !== i[2])return r.find (e); + this.length = 1, this[0] = o + } + return this.context = a, this.selector = e, this + } + return e.nodeType ? (this.context = this[0] = e, this.length = 1, this) : x.isFunction (e) ? r.ready (e) : (e.selector !== t && (this.selector = e.selector, this.context = e.context), x.makeArray (e, this)) + }, selector: "", length: 0, toArray: function () + { + return g.call (this) + }, get: function (e) + { + return null == e ? this.toArray () : 0 > e ? this[this.length + e] : this[e] + }, pushStack: function (e) + { + var t = x.merge (this.constructor (), e); + return t.prevObject = this, t.context = this.context, t + }, each: function (e, t) + { + return x.each (this, e, t) + }, ready: function (e) + { + return x.ready.promise ().done (e), this + }, slice: function () + { + return this.pushStack (g.apply (this, arguments)) + }, first: function () + { + return this.eq (0) + }, last: function () + { + return this.eq (-1) + }, eq: function (e) + { + var t = this.length, n = +e + (0 > e ? t : 0); + return this.pushStack (n >= 0 && t > n ? [this[n]] : []) + }, map: function (e) + { + return this.pushStack (x.map (this, function (t, n) + { + return e.call (t, n, t) + })) + }, end: function () + { + return this.prevObject || this.constructor (null) + }, push: h, sort: [].sort, splice: [].splice}, x.fn.init.prototype = x.fn, x.extend = x.fn.extend = function () + { + var e, n, r, i, o, a, s = arguments[0] || {}, l = 1, u = arguments.length, c = !1; + for ("boolean" == typeof s && (c = s, s = arguments[1] || {}, l = 2), "object" == typeof s || x.isFunction (s) || (s = {}), u === l && (s = this, --l); u > l; l++)if (null != (o = arguments[l]))for (i in o)e = s[i], r = o[i], s !== r && (c && r && (x.isPlainObject (r) || (n = x.isArray (r))) ? (n ? (n = !1, a = e && x.isArray (e) ? e : []) : a = e && x.isPlainObject (e) ? e : {}, s[i] = x.extend (c, a, r)) : r !== t && (s[i] = r)); + return s + }, x.extend ({expando: "jQuery" + (f + Math.random ()).replace (/\D/g, ""), noConflict: function (t) + { + return e.$ === x && (e.$ = u), t && e.jQuery === x && (e.jQuery = l), x + }, isReady: !1, readyWait: 1, holdReady: function (e) + { + e ? x.readyWait++ : x.ready (!0) + }, ready: function (e) + { + if (e === !0 ? !--x.readyWait : !x.isReady) + { + if (!a.body)return setTimeout (x.ready); + x.isReady = !0, e !== !0 && --x.readyWait > 0 || (n.resolveWith (a, [x]), x.fn.trigger && x (a).trigger ("ready").off ("ready")) + } + }, isFunction: function (e) + { + return"function" === x.type (e) + }, isArray: Array.isArray || function (e) + { + return"array" === x.type (e) + }, isWindow: function (e) + { + return null != e && e == e.window + }, isNumeric: function (e) + { + return!isNaN (parseFloat (e)) && isFinite (e) + }, type: function (e) + { + return null == e ? e + "" : "object" == typeof e || "function" == typeof e ? c[y.call (e)] || "object" : typeof e + }, isPlainObject: function (e) + { + var n; + if (!e || "object" !== x.type (e) || e.nodeType || x.isWindow (e))return!1; + try + { + if (e.constructor && !v.call (e, "constructor") && !v.call (e.constructor.prototype, "isPrototypeOf"))return!1 + } catch (r) + { + return!1 + } + if (x.support.ownLast)for (n in e)return v.call (e, n); + for (n in e); + return n === t || v.call (e, n) + }, isEmptyObject: function (e) + { + var t; + for (t in e)return!1; + return!0 + }, error: function (e) + { + throw Error (e) + }, parseHTML: function (e, t, n) + { + if (!e || "string" != typeof e)return null; + "boolean" == typeof t && (n = t, t = !1), t = t || a; + var r = k.exec (e), i = !n && []; + return r ? [t.createElement (r[1])] : (r = x.buildFragment ([e], t, i), i && x (i).remove (), x.merge ([], r.childNodes)) + }, parseJSON: function (n) + { + return e.JSON && e.JSON.parse ? e.JSON.parse (n) : null === n ? n : "string" == typeof n && (n = x.trim (n), n && E.test (n.replace (A, "@").replace (j, "]").replace (S, ""))) ? Function ("return " + n) () : (x.error ("Invalid JSON: " + n), t) + }, parseXML: function (n) + { + var r, i; + if (!n || "string" != typeof n)return null; + try + { + e.DOMParser ? (i = new DOMParser, r = i.parseFromString (n, "text/xml")) : (r = new ActiveXObject ("Microsoft.XMLDOM"), r.async = "false", r.loadXML (n)) + } catch (o) + { + r = t + } + return r && r.documentElement && !r.getElementsByTagName ("parsererror").length || x.error ("Invalid XML: " + n), r + }, noop: function () + { + }, globalEval: function (t) + { + t && x.trim (t) && (e.execScript || function (t) + { + e.eval.call (e, t) + }) (t) + }, camelCase: function (e) + { + return e.replace (D, "ms-").replace (L, H) + }, nodeName: function (e, t) + { + return e.nodeName && e.nodeName.toLowerCase () === t.toLowerCase () + }, each: function (e, t, n) + { + var r, i = 0, o = e.length, a = M (e); + if (n) + { + if (a) + { + for (; o > i; i++)if (r = t.apply (e[i], n), r === !1)break + } else for (i in e)if (r = t.apply (e[i], n), r === !1)break + } else if (a) + { + for (; o > i; i++)if (r = t.call (e[i], i, e[i]), r === !1)break + } else for (i in e)if (r = t.call (e[i], i, e[i]), r === !1)break; + return e + }, trim: b && !b.call ("\ufeff\u00a0") ? function (e) + { + return null == e ? "" : b.call (e) + } : function (e) + { + return null == e ? "" : (e + "").replace (C, "") + }, makeArray: function (e, t) + { + var n = t || []; + return null != e && (M (Object (e)) ? x.merge (n, "string" == typeof e ? [e] : e) : h.call (n, e)), n + }, inArray: function (e, t, n) + { + var r; + if (t) + { + if (m)return m.call (t, e, n); + for (r = t.length, n = n ? 0 > n ? Math.max (0, r + n) : n : 0; r > n; n++)if (n in t && t[n] === e)return n + } + return-1 + }, merge: function (e, n) + { + var r = n.length, i = e.length, o = 0; + if ("number" == typeof r)for (; r > o; o++)e[i++] = n[o]; else while (n[o] !== t)e[i++] = n[o++]; + return e.length = i, e + }, grep: function (e, t, n) + { + var r, i = [], o = 0, a = e.length; + for (n = !!n; a > o; o++)r = !!t (e[o], o), n !== r && i.push (e[o]); + return i + }, map: function (e, t, n) + { + var r, i = 0, o = e.length, a = M (e), s = []; + if (a)for (; o > i; i++)r = t (e[i], i, n), null != r && (s[s.length] = r); else for (i in e)r = t (e[i], i, n), null != r && (s[s.length] = r); + return d.apply ([], s) + }, guid: 1, proxy: function (e, n) + { + var r, i, o; + return"string" == typeof n && (o = e[n], n = e, e = o), x.isFunction (e) ? (r = g.call (arguments, 2), i = function () + { + return e.apply (n || this, r.concat (g.call (arguments))) + }, i.guid = e.guid = e.guid || x.guid++, i) : t + }, access: function (e, n, r, i, o, a, s) + { + var l = 0, u = e.length, c = null == r; + if ("object" === x.type (r)) + { + o = !0; + for (l in r)x.access (e, n, l, r[l], !0, a, s) + } else if (i !== t && (o = !0, x.isFunction (i) || (s = !0), c && (s ? (n.call (e, i), n = null) : (c = n, n = function (e, t, n) + { + return c.call (x (e), n) + })), n))for (; u > l; l++)n (e[l], r, s ? i : i.call (e[l], l, n (e[l], r))); + return o ? e : c ? n.call (e) : u ? n (e[0], r) : a + }, now: function () + { + return(new Date).getTime () + }, swap: function (e, t, n, r) + { + var i, o, a = {}; + for (o in t)a[o] = e.style[o], e.style[o] = t[o]; + i = n.apply (e, r || []); + for (o in t)e.style[o] = a[o]; + return i + }}), x.ready.promise = function (t) + { + if (!n)if (n = x.Deferred (), "complete" === a.readyState)setTimeout (x.ready); else if (a.addEventListener)a.addEventListener ("DOMContentLoaded", q, !1), e.addEventListener ("load", q, !1); else + { + a.attachEvent ("onreadystatechange", q), e.attachEvent ("onload", q); + var r = !1; + try + { + r = null == e.frameElement && a.documentElement + } catch (i) + { + } + r && r.doScroll && function o () + { + if (!x.isReady) + { + try + { + r.doScroll ("left") + } catch (e) + { + return setTimeout (o, 50) + } + _ (), x.ready () + } + } () + } + return n.promise (t) + }, x.each ("Boolean Number String Function Array Date RegExp Object Error".split (" "), function (e, t) + { + c["[object " + t + "]"] = t.toLowerCase () + }); + function M (e) + { + var t = e.length, n = x.type (e); + return x.isWindow (e) ? !1 : 1 === e.nodeType && t ? !0 : "array" === n || "function" !== n && (0 === t || "number" == typeof t && t > 0 && t - 1 in e) + } + + r = x (a), function (e, t) + { + var n, r, i, o, a, s, l, u, c, p, f, d, h, g, m, y, v, b = "sizzle" + -new Date, w = e.document, T = 0, C = 0, N = st (), k = st (), E = st (), S = !1, A = function (e, t) + { + return e === t ? (S = !0, 0) : 0 + }, j = typeof t, D = 1 << 31, L = {}.hasOwnProperty, H = [], q = H.pop, _ = H.push, M = H.push, O = H.slice, F = H.indexOf || function (e) + { + var t = 0, n = this.length; + for (; n > t; t++)if (this[t] === e)return t; + return-1 + }, B = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", P = "[\\x20\\t\\r\\n\\f]", R = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", W = R.replace ("w", "w#"), $ = "\\[" + P + "*(" + R + ")" + P + "*(?:([*^$|!~]?=)" + P + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + W + ")|)|)" + P + "*\\]", I = ":(" + R + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + $.replace (3, 8) + ")*)|.*)\\)|)", z = RegExp ("^" + P + "+|((?:^|[^\\\\])(?:\\\\.)*)" + P + "+$", "g"), X = RegExp ("^" + P + "*," + P + "*"), U = RegExp ("^" + P + "*([>+~]|" + P + ")" + P + "*"), V = RegExp (P + "*[+~]"), Y = RegExp ("=" + P + "*([^\\]'\"]*)" + P + "*\\]", "g"), J = RegExp (I), G = RegExp ("^" + W + "$"), Q = {ID: RegExp ("^#(" + R + ")"), CLASS: RegExp ("^\\.(" + R + ")"), TAG: RegExp ("^(" + R.replace ("w", "w*") + ")"), ATTR: RegExp ("^" + $), PSEUDO: RegExp ("^" + I), CHILD: RegExp ("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + P + "*(even|odd|(([+-]|)(\\d*)n|)" + P + "*(?:([+-]|)" + P + "*(\\d+)|))" + P + "*\\)|)", "i"), bool: RegExp ("^(?:" + B + ")$", "i"), needsContext: RegExp ("^" + P + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + P + "*((?:-\\d)?\\d*)" + P + "*\\)|)(?=[^-]|$)", "i")}, K = /^[^{]+\{\s*\[native \w/, Z = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, et = /^(?:input|select|textarea|button)$/i, tt = /^h\d$/i, nt = /'|\\/g, rt = RegExp ("\\\\([\\da-f]{1,6}" + P + "?|(" + P + ")|.)", "ig"), it = function (e, t, n) + { + var r = "0x" + t - 65536; + return r !== r || n ? t : 0 > r ? String.fromCharCode (r + 65536) : String.fromCharCode (55296 | r >> 10, 56320 | 1023 & r) + }; + try + { + M.apply (H = O.call (w.childNodes), w.childNodes), H[w.childNodes.length].nodeType + } catch (ot) + { + M = {apply: H.length ? function (e, t) + { + _.apply (e, O.call (t)) + } : function (e, t) + { + var n = e.length, r = 0; + while (e[n++] = t[r++]); + e.length = n - 1 + }} + } + function at (e, t, n, i) + { + var o, a, s, l, u, c, d, m, y, x; + if ((t ? t.ownerDocument || t : w) !== f && p (t), t = t || f, n = n || [], !e || "string" != typeof e)return n; + if (1 !== (l = t.nodeType) && 9 !== l)return[]; + if (h && !i) + { + if (o = Z.exec (e))if (s = o[1]) + { + if (9 === l) + { + if (a = t.getElementById (s), !a || !a.parentNode)return n; + if (a.id === s)return n.push (a), n + } else if (t.ownerDocument && (a = t.ownerDocument.getElementById (s)) && v (t, a) && a.id === s)return n.push (a), n + } else + { + if (o[2])return M.apply (n, t.getElementsByTagName (e)), n; + if ((s = o[3]) && r.getElementsByClassName && t.getElementsByClassName)return M.apply (n, t.getElementsByClassName (s)), n + } + if (r.qsa && (!g || !g.test (e))) + { + if (m = d = b, y = t, x = 9 === l && e, 1 === l && "object" !== t.nodeName.toLowerCase ()) + { + c = mt (e), (d = t.getAttribute ("id")) ? m = d.replace (nt, "\\$&") : t.setAttribute ("id", m), m = "[id='" + m + "'] ", u = c.length; + while (u--)c[u] = m + yt (c[u]); + y = V.test (e) && t.parentNode || t, x = c.join (",") + } + if (x)try + { + return M.apply (n, y.querySelectorAll (x)), n + } catch (T) + { + } finally + { + d || t.removeAttribute ("id") + } + } + } + return kt (e.replace (z, "$1"), t, n, i) + } + + function st () + { + var e = []; + + function t (n, r) + { + return e.push (n += " ") > o.cacheLength && delete t[e.shift ()], t[n] = r + } + + return t + } + + function lt (e) + { + return e[b] = !0, e + } + + function ut (e) + { + var t = f.createElement ("div"); + try + { + return!!e (t) + } catch (n) + { + return!1 + } finally + { + t.parentNode && t.parentNode.removeChild (t), t = null + } + } + + function ct (e, t) + { + var n = e.split ("|"), r = e.length; + while (r--)o.attrHandle[n[r]] = t + } + + function pt (e, t) + { + var n = t && e, r = n && 1 === e.nodeType && 1 === t.nodeType && (~t.sourceIndex || D) - (~e.sourceIndex || D); + if (r)return r; + if (n)while (n = n.nextSibling)if (n === t)return-1; + return e ? 1 : -1 + } + + function ft (e) + { + return function (t) + { + var n = t.nodeName.toLowerCase (); + return"input" === n && t.type === e + } + } + + function dt (e) + { + return function (t) + { + var n = t.nodeName.toLowerCase (); + return("input" === n || "button" === n) && t.type === e + } + } + + function ht (e) + { + return lt (function (t) + { + return t = +t, lt (function (n, r) + { + var i, o = e ([], n.length, t), a = o.length; + while (a--)n[i = o[a]] && (n[i] = !(r[i] = n[i])) + }) + }) + } + + s = at.isXML = function (e) + { + var t = e && (e.ownerDocument || e).documentElement; + return t ? "HTML" !== t.nodeName : !1 + }, r = at.support = {}, p = at.setDocument = function (e) + { + var n = e ? e.ownerDocument || e : w, i = n.defaultView; + return n !== f && 9 === n.nodeType && n.documentElement ? (f = n, d = n.documentElement, h = !s (n), i && i.attachEvent && i !== i.top && i.attachEvent ("onbeforeunload", function () + { + p () + }), r.attributes = ut (function (e) + { + return e.className = "i", !e.getAttribute ("className") + }), r.getElementsByTagName = ut (function (e) + { + return e.appendChild (n.createComment ("")), !e.getElementsByTagName ("*").length + }), r.getElementsByClassName = ut (function (e) + { + return e.innerHTML = "
    ", e.firstChild.className = "i", 2 === e.getElementsByClassName ("i").length + }), r.getById = ut (function (e) + { + return d.appendChild (e).id = b, !n.getElementsByName || !n.getElementsByName (b).length + }), r.getById ? (o.find.ID = function (e, t) + { + if (typeof t.getElementById !== j && h) + { + var n = t.getElementById (e); + return n && n.parentNode ? [n] : [] + } + }, o.filter.ID = function (e) + { + var t = e.replace (rt, it); + return function (e) + { + return e.getAttribute ("id") === t + } + }) : (delete o.find.ID, o.filter.ID = function (e) + { + var t = e.replace (rt, it); + return function (e) + { + var n = typeof e.getAttributeNode !== j && e.getAttributeNode ("id"); + return n && n.value === t + } + }), o.find.TAG = r.getElementsByTagName ? function (e, n) + { + return typeof n.getElementsByTagName !== j ? n.getElementsByTagName (e) : t + } : function (e, t) + { + var n, r = [], i = 0, o = t.getElementsByTagName (e); + if ("*" === e) + { + while (n = o[i++])1 === n.nodeType && r.push (n); + return r + } + return o + }, o.find.CLASS = r.getElementsByClassName && function (e, n) + { + return typeof n.getElementsByClassName !== j && h ? n.getElementsByClassName (e) : t + }, m = [], g = [], (r.qsa = K.test (n.querySelectorAll)) && (ut (function (e) + { + e.innerHTML = "", e.querySelectorAll ("[selected]").length || g.push ("\\[" + P + "*(?:value|" + B + ")"), e.querySelectorAll (":checked").length || g.push (":checked") + }), ut (function (e) + { + var t = n.createElement ("input"); + t.setAttribute ("type", "hidden"), e.appendChild (t).setAttribute ("t", ""), e.querySelectorAll ("[t^='']").length && g.push ("[*^$]=" + P + "*(?:''|\"\")"), e.querySelectorAll (":enabled").length || g.push (":enabled", ":disabled"), e.querySelectorAll ("*,:x"), g.push (",.*:") + })), (r.matchesSelector = K.test (y = d.webkitMatchesSelector || d.mozMatchesSelector || d.oMatchesSelector || d.msMatchesSelector)) && ut (function (e) + { + r.disconnectedMatch = y.call (e, "div"), y.call (e, "[s!='']:x"), m.push ("!=", I) + }), g = g.length && RegExp (g.join ("|")), m = m.length && RegExp (m.join ("|")), v = K.test (d.contains) || d.compareDocumentPosition ? function (e, t) + { + var n = 9 === e.nodeType ? e.documentElement : e, r = t && t.parentNode; + return e === r || !(!r || 1 !== r.nodeType || !(n.contains ? n.contains (r) : e.compareDocumentPosition && 16 & e.compareDocumentPosition (r))) + } : function (e, t) + { + if (t)while (t = t.parentNode)if (t === e)return!0; + return!1 + }, A = d.compareDocumentPosition ? function (e, t) + { + if (e === t)return S = !0, 0; + var i = t.compareDocumentPosition && e.compareDocumentPosition && e.compareDocumentPosition (t); + return i ? 1 & i || !r.sortDetached && t.compareDocumentPosition (e) === i ? e === n || v (w, e) ? -1 : t === n || v (w, t) ? 1 : c ? F.call (c, e) - F.call (c, t) : 0 : 4 & i ? -1 : 1 : e.compareDocumentPosition ? -1 : 1 + } : function (e, t) + { + var r, i = 0, o = e.parentNode, a = t.parentNode, s = [e], l = [t]; + if (e === t)return S = !0, 0; + if (!o || !a)return e === n ? -1 : t === n ? 1 : o ? -1 : a ? 1 : c ? F.call (c, e) - F.call (c, t) : 0; + if (o === a)return pt (e, t); + r = e; + while (r = r.parentNode)s.unshift (r); + r = t; + while (r = r.parentNode)l.unshift (r); + while (s[i] === l[i])i++; + return i ? pt (s[i], l[i]) : s[i] === w ? -1 : l[i] === w ? 1 : 0 + }, n) : f + }, at.matches = function (e, t) + { + return at (e, null, null, t) + }, at.matchesSelector = function (e, t) + { + if ((e.ownerDocument || e) !== f && p (e), t = t.replace (Y, "='$1']"), !(!r.matchesSelector || !h || m && m.test (t) || g && g.test (t)))try + { + var n = y.call (e, t); + if (n || r.disconnectedMatch || e.document && 11 !== e.document.nodeType)return n + } catch (i) + { + } + return at (t, f, null, [e]).length > 0 + }, at.contains = function (e, t) + { + return(e.ownerDocument || e) !== f && p (e), v (e, t) + }, at.attr = function (e, n) + { + (e.ownerDocument || e) !== f && p (e); + var i = o.attrHandle[n.toLowerCase ()], a = i && L.call (o.attrHandle, n.toLowerCase ()) ? i (e, n, !h) : t; + return a === t ? r.attributes || !h ? e.getAttribute (n) : (a = e.getAttributeNode (n)) && a.specified ? a.value : null : a + }, at.error = function (e) + { + throw Error ("Syntax error, unrecognized expression: " + e) + }, at.uniqueSort = function (e) + { + var t, n = [], i = 0, o = 0; + if (S = !r.detectDuplicates, c = !r.sortStable && e.slice (0), e.sort (A), S) + { + while (t = e[o++])t === e[o] && (i = n.push (o)); + while (i--)e.splice (n[i], 1) + } + return e + }, a = at.getText = function (e) + { + var t, n = "", r = 0, i = e.nodeType; + if (i) + { + if (1 === i || 9 === i || 11 === i) + { + if ("string" == typeof e.textContent)return e.textContent; + for (e = e.firstChild; e; e = e.nextSibling)n += a (e) + } else if (3 === i || 4 === i)return e.nodeValue + } else for (; t = e[r]; r++)n += a (t); + return n + }, o = at.selectors = {cacheLength: 50, createPseudo: lt, match: Q, attrHandle: {}, find: {}, relative: {">": {dir: "parentNode", first: !0}, " ": {dir: "parentNode"}, "+": {dir: "previousSibling", first: !0}, "~": {dir: "previousSibling"}}, preFilter: {ATTR: function (e) + { + return e[1] = e[1].replace (rt, it), e[3] = (e[4] || e[5] || "").replace (rt, it), "~=" === e[2] && (e[3] = " " + e[3] + " "), e.slice (0, 4) + }, CHILD: function (e) + { + return e[1] = e[1].toLowerCase (), "nth" === e[1].slice (0, 3) ? (e[3] || at.error (e[0]), e[4] = +(e[4] ? e[5] + (e[6] || 1) : 2 * ("even" === e[3] || "odd" === e[3])), e[5] = +(e[7] + e[8] || "odd" === e[3])) : e[3] && at.error (e[0]), e + }, PSEUDO: function (e) + { + var n, r = !e[5] && e[2]; + return Q.CHILD.test (e[0]) ? null : (e[3] && e[4] !== t ? e[2] = e[4] : r && J.test (r) && (n = mt (r, !0)) && (n = r.indexOf (")", r.length - n) - r.length) && (e[0] = e[0].slice (0, n), e[2] = r.slice (0, n)), e.slice (0, 3)) + }}, filter: {TAG: function (e) + { + var t = e.replace (rt, it).toLowerCase (); + return"*" === e ? function () + { + return!0 + } : function (e) + { + return e.nodeName && e.nodeName.toLowerCase () === t + } + }, CLASS: function (e) + { + var t = N[e + " "]; + return t || (t = RegExp ("(^|" + P + ")" + e + "(" + P + "|$)")) && N (e, function (e) + { + return t.test ("string" == typeof e.className && e.className || typeof e.getAttribute !== j && e.getAttribute ("class") || "") + }) + }, ATTR: function (e, t, n) + { + return function (r) + { + var i = at.attr (r, e); + return null == i ? "!=" === t : t ? (i += "", "=" === t ? i === n : "!=" === t ? i !== n : "^=" === t ? n && 0 === i.indexOf (n) : "*=" === t ? n && i.indexOf (n) > -1 : "$=" === t ? n && i.slice (-n.length) === n : "~=" === t ? (" " + i + " ").indexOf (n) > -1 : "|=" === t ? i === n || i.slice (0, n.length + 1) === n + "-" : !1) : !0 + } + }, CHILD: function (e, t, n, r, i) + { + var o = "nth" !== e.slice (0, 3), a = "last" !== e.slice (-4), s = "of-type" === t; + return 1 === r && 0 === i ? function (e) + { + return!!e.parentNode + } : function (t, n, l) + { + var u, c, p, f, d, h, g = o !== a ? "nextSibling" : "previousSibling", m = t.parentNode, y = s && t.nodeName.toLowerCase (), v = !l && !s; + if (m) + { + if (o) + { + while (g) + { + p = t; + while (p = p[g])if (s ? p.nodeName.toLowerCase () === y : 1 === p.nodeType)return!1; + h = g = "only" === e && !h && "nextSibling" + } + return!0 + } + if (h = [a ? m.firstChild : m.lastChild], a && v) + { + c = m[b] || (m[b] = {}), u = c[e] || [], d = u[0] === T && u[1], f = u[0] === T && u[2], p = d && m.childNodes[d]; + while (p = ++d && p && p[g] || (f = d = 0) || h.pop ())if (1 === p.nodeType && ++f && p === t) + { + c[e] = [T, d, f]; + break + } + } else if (v && (u = (t[b] || (t[b] = {}))[e]) && u[0] === T)f = u[1]; else while (p = ++d && p && p[g] || (f = d = 0) || h.pop ())if ((s ? p.nodeName.toLowerCase () === y : 1 === p.nodeType) && ++f && (v && ((p[b] || (p[b] = {}))[e] = [T, f]), p === t))break; + return f -= i, f === r || 0 === f % r && f / r >= 0 + } + } + }, PSEUDO: function (e, t) + { + var n, r = o.pseudos[e] || o.setFilters[e.toLowerCase ()] || at.error ("unsupported pseudo: " + e); + return r[b] ? r (t) : r.length > 1 ? (n = [e, e, "", t], o.setFilters.hasOwnProperty (e.toLowerCase ()) ? lt (function (e, n) + { + var i, o = r (e, t), a = o.length; + while (a--)i = F.call (e, o[a]), e[i] = !(n[i] = o[a]) + }) : function (e) + { + return r (e, 0, n) + }) : r + }}, pseudos: {not: lt (function (e) + { + var t = [], n = [], r = l (e.replace (z, "$1")); + return r[b] ? lt (function (e, t, n, i) + { + var o, a = r (e, null, i, []), s = e.length; + while (s--)(o = a[s]) && (e[s] = !(t[s] = o)) + }) : function (e, i, o) + { + return t[0] = e, r (t, null, o, n), !n.pop () + } + }), has: lt (function (e) + { + return function (t) + { + return at (e, t).length > 0 + } + }), contains: lt (function (e) + { + return function (t) + { + return(t.textContent || t.innerText || a (t)).indexOf (e) > -1 + } + }), lang: lt (function (e) + { + return G.test (e || "") || at.error ("unsupported lang: " + e), e = e.replace (rt, it).toLowerCase (), function (t) + { + var n; + do if (n = h ? t.lang : t.getAttribute ("xml:lang") || t.getAttribute ("lang"))return n = n.toLowerCase (), n === e || 0 === n.indexOf (e + "-"); while ((t = t.parentNode) && 1 === t.nodeType); + return!1 + } + }), target: function (t) + { + var n = e.location && e.location.hash; + return n && n.slice (1) === t.id + }, root: function (e) + { + return e === d + }, focus: function (e) + { + return e === f.activeElement && (!f.hasFocus || f.hasFocus ()) && !!(e.type || e.href || ~e.tabIndex) + }, enabled: function (e) + { + return e.disabled === !1 + }, disabled: function (e) + { + return e.disabled === !0 + }, checked: function (e) + { + var t = e.nodeName.toLowerCase (); + return"input" === t && !!e.checked || "option" === t && !!e.selected + }, selected: function (e) + { + return e.parentNode && e.parentNode.selectedIndex, e.selected === !0 + }, empty: function (e) + { + for (e = e.firstChild; e; e = e.nextSibling)if (e.nodeName > "@" || 3 === e.nodeType || 4 === e.nodeType)return!1; + return!0 + }, parent: function (e) + { + return!o.pseudos.empty (e) + }, header: function (e) + { + return tt.test (e.nodeName) + }, input: function (e) + { + return et.test (e.nodeName) + }, button: function (e) + { + var t = e.nodeName.toLowerCase (); + return"input" === t && "button" === e.type || "button" === t + }, text: function (e) + { + var t; + return"input" === e.nodeName.toLowerCase () && "text" === e.type && (null == (t = e.getAttribute ("type")) || t.toLowerCase () === e.type) + }, first: ht (function () + { + return[0] + }), last: ht (function (e, t) + { + return[t - 1] + }), eq: ht (function (e, t, n) + { + return[0 > n ? n + t : n] + }), even: ht (function (e, t) + { + var n = 0; + for (; t > n; n += 2)e.push (n); + return e + }), odd: ht (function (e, t) + { + var n = 1; + for (; t > n; n += 2)e.push (n); + return e + }), lt: ht (function (e, t, n) + { + var r = 0 > n ? n + t : n; + for (; --r >= 0;)e.push (r); + return e + }), gt: ht (function (e, t, n) + { + var r = 0 > n ? n + t : n; + for (; t > ++r;)e.push (r); + return e + })}}, o.pseudos.nth = o.pseudos.eq; + for (n in{radio: !0, checkbox: !0, file: !0, password: !0, image: !0})o.pseudos[n] = ft (n); + for (n in{submit: !0, reset: !0})o.pseudos[n] = dt (n); + function gt () + { + } + + gt.prototype = o.filters = o.pseudos, o.setFilters = new gt; + function mt (e, t) + { + var n, r, i, a, s, l, u, c = k[e + " "]; + if (c)return t ? 0 : c.slice (0); + s = e, l = [], u = o.preFilter; + while (s) + { + (!n || (r = X.exec (s))) && (r && (s = s.slice (r[0].length) || s), l.push (i = [])), n = !1, (r = U.exec (s)) && (n = r.shift (), i.push ({value: n, type: r[0].replace (z, " ")}), s = s.slice (n.length)); + for (a in o.filter)!(r = Q[a].exec (s)) || u[a] && !(r = u[a] (r)) || (n = r.shift (), i.push ({value: n, type: a, matches: r}), s = s.slice (n.length)); + if (!n)break + } + return t ? s.length : s ? at.error (e) : k (e, l).slice (0) + } + + function yt (e) + { + var t = 0, n = e.length, r = ""; + for (; n > t; t++)r += e[t].value; + return r + } + + function vt (e, t, n) + { + var r = t.dir, o = n && "parentNode" === r, a = C++; + return t.first ? function (t, n, i) + { + while (t = t[r])if (1 === t.nodeType || o)return e (t, n, i) + } : function (t, n, s) + { + var l, u, c, p = T + " " + a; + if (s) + { + while (t = t[r])if ((1 === t.nodeType || o) && e (t, n, s))return!0 + } else while (t = t[r])if (1 === t.nodeType || o)if (c = t[b] || (t[b] = {}), (u = c[r]) && u[0] === p) + { + if ((l = u[1]) === !0 || l === i)return l === !0 + } else if (u = c[r] = [p], u[1] = e (t, n, s) || i, u[1] === !0)return!0 + } + } + + function bt (e) + { + return e.length > 1 ? function (t, n, r) + { + var i = e.length; + while (i--)if (!e[i] (t, n, r))return!1; + return!0 + } : e[0] + } + + function xt (e, t, n, r, i) + { + var o, a = [], s = 0, l = e.length, u = null != t; + for (; l > s; s++)(o = e[s]) && (!n || n (o, r, i)) && (a.push (o), u && t.push (s)); + return a + } + + function wt (e, t, n, r, i, o) + { + return r && !r[b] && (r = wt (r)), i && !i[b] && (i = wt (i, o)), lt (function (o, a, s, l) + { + var u, c, p, f = [], d = [], h = a.length, g = o || Nt (t || "*", s.nodeType ? [s] : s, []), m = !e || !o && t ? g : xt (g, f, e, s, l), y = n ? i || (o ? e : h || r) ? [] : a : m; + if (n && n (m, y, s, l), r) + { + u = xt (y, d), r (u, [], s, l), c = u.length; + while (c--)(p = u[c]) && (y[d[c]] = !(m[d[c]] = p)) + } + if (o) + { + if (i || e) + { + if (i) + { + u = [], c = y.length; + while (c--)(p = y[c]) && u.push (m[c] = p); + i (null, y = [], u, l) + } + c = y.length; + while (c--)(p = y[c]) && (u = i ? F.call (o, p) : f[c]) > -1 && (o[u] = !(a[u] = p)) + } + } else y = xt (y === a ? y.splice (h, y.length) : y), i ? i (null, a, y, l) : M.apply (a, y) + }) + } + + function Tt (e) + { + var t, n, r, i = e.length, a = o.relative[e[0].type], s = a || o.relative[" "], l = a ? 1 : 0, c = vt (function (e) + { + return e === t + }, s, !0), p = vt (function (e) + { + return F.call (t, e) > -1 + }, s, !0), f = [function (e, n, r) + { + return!a && (r || n !== u) || ((t = n).nodeType ? c (e, n, r) : p (e, n, r)) + }]; + for (; i > l; l++)if (n = o.relative[e[l].type])f = [vt (bt (f), n)]; else + { + if (n = o.filter[e[l].type].apply (null, e[l].matches), n[b]) + { + for (r = ++l; i > r; r++)if (o.relative[e[r].type])break; + return wt (l > 1 && bt (f), l > 1 && yt (e.slice (0, l - 1).concat ({value: " " === e[l - 2].type ? "*" : ""})).replace (z, "$1"), n, r > l && Tt (e.slice (l, r)), i > r && Tt (e = e.slice (r)), i > r && yt (e)) + } + f.push (n) + } + return bt (f) + } + + function Ct (e, t) + { + var n = 0, r = t.length > 0, a = e.length > 0, s = function (s, l, c, p, d) + { + var h, g, m, y = [], v = 0, b = "0", x = s && [], w = null != d, C = u, N = s || a && o.find.TAG ("*", d && l.parentNode || l), k = T += null == C ? 1 : Math.random () || .1; + for (w && (u = l !== f && l, i = n); null != (h = N[b]); b++) + { + if (a && h) + { + g = 0; + while (m = e[g++])if (m (h, l, c)) + { + p.push (h); + break + } + w && (T = k, i = ++n) + } + r && ((h = !m && h) && v--, s && x.push (h)) + } + if (v += b, r && b !== v) + { + g = 0; + while (m = t[g++])m (x, y, l, c); + if (s) + { + if (v > 0)while (b--)x[b] || y[b] || (y[b] = q.call (p)); + y = xt (y) + } + M.apply (p, y), w && !s && y.length > 0 && v + t.length > 1 && at.uniqueSort (p) + } + return w && (T = k, u = C), x + }; + return r ? lt (s) : s + } + + l = at.compile = function (e, t) + { + var n, r = [], i = [], o = E[e + " "]; + if (!o) + { + t || (t = mt (e)), n = t.length; + while (n--)o = Tt (t[n]), o[b] ? r.push (o) : i.push (o); + o = E (e, Ct (i, r)) + } + return o + }; + function Nt (e, t, n) + { + var r = 0, i = t.length; + for (; i > r; r++)at (e, t[r], n); + return n + } + + function kt (e, t, n, i) + { + var a, s, u, c, p, f = mt (e); + if (!i && 1 === f.length) + { + if (s = f[0] = f[0].slice (0), s.length > 2 && "ID" === (u = s[0]).type && r.getById && 9 === t.nodeType && h && o.relative[s[1].type]) + { + if (t = (o.find.ID (u.matches[0].replace (rt, it), t) || [])[0], !t)return n; + e = e.slice (s.shift ().value.length) + } + a = Q.needsContext.test (e) ? 0 : s.length; + while (a--) + { + if (u = s[a], o.relative[c = u.type])break; + if ((p = o.find[c]) && (i = p (u.matches[0].replace (rt, it), V.test (s[0].type) && t.parentNode || t))) + { + if (s.splice (a, 1), e = i.length && yt (s), !e)return M.apply (n, i), n; + break + } + } + } + return l (e, f) (i, t, !h, n, V.test (e)), n + } + + r.sortStable = b.split ("").sort (A).join ("") === b, r.detectDuplicates = S, p (), r.sortDetached = ut (function (e) + { + return 1 & e.compareDocumentPosition (f.createElement ("div")) + }), ut (function (e) + { + return e.innerHTML = "", "#" === e.firstChild.getAttribute ("href") + }) || ct ("type|href|height|width", function (e, n, r) + { + return r ? t : e.getAttribute (n, "type" === n.toLowerCase () ? 1 : 2) + }), r.attributes && ut (function (e) + { + return e.innerHTML = "", e.firstChild.setAttribute ("value", ""), "" === e.firstChild.getAttribute ("value") + }) || ct ("value", function (e, n, r) + { + return r || "input" !== e.nodeName.toLowerCase () ? t : e.defaultValue + }), ut (function (e) + { + return null == e.getAttribute ("disabled") + }) || ct (B, function (e, n, r) + { + var i; + return r ? t : (i = e.getAttributeNode (n)) && i.specified ? i.value : e[n] === !0 ? n.toLowerCase () : null + }), x.find = at, x.expr = at.selectors, x.expr[":"] = x.expr.pseudos, x.unique = at.uniqueSort, x.text = at.getText, x.isXMLDoc = at.isXML, x.contains = at.contains + } (e); + var O = {}; + + function F (e) + { + var t = O[e] = {}; + return x.each (e.match (T) || [], function (e, n) + { + t[n] = !0 + }), t + } + + x.Callbacks = function (e) + { + e = "string" == typeof e ? O[e] || F (e) : x.extend ({}, e); + var n, r, i, o, a, s, l = [], u = !e.once && [], c = function (t) + { + for (r = e.memory && t, i = !0, a = s || 0, s = 0, o = l.length, n = !0; l && o > a; a++)if (l[a].apply (t[0], t[1]) === !1 && e.stopOnFalse) + { + r = !1; + break + } + n = !1, l && (u ? u.length && c (u.shift ()) : r ? l = [] : p.disable ()) + }, p = {add: function () + { + if (l) + { + var t = l.length; + (function i (t) + { + x.each (t, function (t, n) + { + var r = x.type (n); + "function" === r ? e.unique && p.has (n) || l.push (n) : n && n.length && "string" !== r && i (n) + }) + }) (arguments), n ? o = l.length : r && (s = t, c (r)) + } + return this + }, remove: function () + { + return l && x.each (arguments, function (e, t) + { + var r; + while ((r = x.inArray (t, l, r)) > -1)l.splice (r, 1), n && (o >= r && o--, a >= r && a--) + }), this + }, has: function (e) + { + return e ? x.inArray (e, l) > -1 : !(!l || !l.length) + }, empty: function () + { + return l = [], o = 0, this + }, disable: function () + { + return l = u = r = t, this + }, disabled: function () + { + return!l + }, lock: function () + { + return u = t, r || p.disable (), this + }, locked: function () + { + return!u + }, fireWith: function (e, t) + { + return!l || i && !u || (t = t || [], t = [e, t.slice ? t.slice () : t], n ? u.push (t) : c (t)), this + }, fire: function () + { + return p.fireWith (this, arguments), this + }, fired: function () + { + return!!i + }}; + return p + }, x.extend ({Deferred: function (e) + { + var t = [ + ["resolve", "done", x.Callbacks ("once memory"), "resolved"], + ["reject", "fail", x.Callbacks ("once memory"), "rejected"], + ["notify", "progress", x.Callbacks ("memory")] + ], n = "pending", r = {state: function () + { + return n + }, always: function () + { + return i.done (arguments).fail (arguments), this + }, then: function () + { + var e = arguments; + return x.Deferred (function (n) + { + x.each (t, function (t, o) + { + var a = o[0], s = x.isFunction (e[t]) && e[t]; + i[o[1]] (function () + { + var e = s && s.apply (this, arguments); + e && x.isFunction (e.promise) ? e.promise ().done (n.resolve).fail (n.reject).progress (n.notify) : n[a + "With"] (this === r ? n.promise () : this, s ? [e] : arguments) + }) + }), e = null + }).promise () + }, promise: function (e) + { + return null != e ? x.extend (e, r) : r + }}, i = {}; + return r.pipe = r.then, x.each (t, function (e, o) + { + var a = o[2], s = o[3]; + r[o[1]] = a.add, s && a.add (function () + { + n = s + }, t[1 ^ e][2].disable, t[2][2].lock), i[o[0]] = function () + { + return i[o[0] + "With"] (this === i ? r : this, arguments), this + }, i[o[0] + "With"] = a.fireWith + }), r.promise (i), e && e.call (i, i), i + }, when: function (e) + { + var t = 0, n = g.call (arguments), r = n.length, i = 1 !== r || e && x.isFunction (e.promise) ? r : 0, o = 1 === i ? e : x.Deferred (), a = function (e, t, n) + { + return function (r) + { + t[e] = this, n[e] = arguments.length > 1 ? g.call (arguments) : r, n === s ? o.notifyWith (t, n) : --i || o.resolveWith (t, n) + } + }, s, l, u; + if (r > 1)for (s = Array (r), l = Array (r), u = Array (r); r > t; t++)n[t] && x.isFunction (n[t].promise) ? n[t].promise ().done (a (t, u, n)).fail (o.reject).progress (a (t, l, s)) : --i; + return i || o.resolveWith (u, n), o.promise () + }}), x.support = function (t) + { + var n, r, o, s, l, u, c, p, f, d = a.createElement ("div"); + if (d.setAttribute ("className", "t"), d.innerHTML = "
    a", n = d.getElementsByTagName ("*") || [], r = d.getElementsByTagName ("a")[0], !r || !r.style || !n.length)return t; + s = a.createElement ("select"), u = s.appendChild (a.createElement ("option")), o = d.getElementsByTagName ("input")[0], r.style.cssText = "top:1px;float:left;opacity:.5", t.getSetAttribute = "t" !== d.className, t.leadingWhitespace = 3 === d.firstChild.nodeType, t.tbody = !d.getElementsByTagName ("tbody").length, t.htmlSerialize = !!d.getElementsByTagName ("link").length, t.style = /top/.test (r.getAttribute ("style")), t.hrefNormalized = "/a" === r.getAttribute ("href"), t.opacity = /^0.5/.test (r.style.opacity), t.cssFloat = !!r.style.cssFloat, t.checkOn = !!o.value, t.optSelected = u.selected, t.enctype = !!a.createElement ("form").enctype, t.html5Clone = "<:nav>" !== a.createElement ("nav").cloneNode (!0).outerHTML, t.inlineBlockNeedsLayout = !1, t.shrinkWrapBlocks = !1, t.pixelPosition = !1, t.deleteExpando = !0, t.noCloneEvent = !0, t.reliableMarginRight = !0, t.boxSizingReliable = !0, o.checked = !0, t.noCloneChecked = o.cloneNode (!0).checked, s.disabled = !0, t.optDisabled = !u.disabled; + try + { + delete d.test + } catch (h) + { + t.deleteExpando = !1 + } + o = a.createElement ("input"), o.setAttribute ("value", ""), t.input = "" === o.getAttribute ("value"), o.value = "t", o.setAttribute ("type", "radio"), t.radioValue = "t" === o.value, o.setAttribute ("checked", "t"), o.setAttribute ("name", "t"), l = a.createDocumentFragment (), l.appendChild (o), t.appendChecked = o.checked, t.checkClone = l.cloneNode (!0).cloneNode (!0).lastChild.checked, d.attachEvent && (d.attachEvent ("onclick", function () + { + t.noCloneEvent = !1 + }), d.cloneNode (!0).click ()); + for (f in{submit: !0, change: !0, focusin: !0})d.setAttribute (c = "on" + f, "t"), t[f + "Bubbles"] = c in e || d.attributes[c].expando === !1; + d.style.backgroundClip = "content-box", d.cloneNode (!0).style.backgroundClip = "", t.clearCloneStyle = "content-box" === d.style.backgroundClip; + for (f in x (t))break; + return t.ownLast = "0" !== f, x (function () + { + var n, r, o, s = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;", l = a.getElementsByTagName ("body")[0]; + l && (n = a.createElement ("div"), n.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px", l.appendChild (n).appendChild (d), d.innerHTML = "
    t
    ", o = d.getElementsByTagName ("td"), o[0].style.cssText = "padding:0;margin:0;border:0;display:none", p = 0 === o[0].offsetHeight, o[0].style.display = "", o[1].style.display = "none", t.reliableHiddenOffsets = p && 0 === o[0].offsetHeight, d.innerHTML = "", d.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;", x.swap (l, null != l.style.zoom ? {zoom: 1} : {}, function () + { + t.boxSizing = 4 === d.offsetWidth + }), e.getComputedStyle && (t.pixelPosition = "1%" !== (e.getComputedStyle (d, null) || {}).top, t.boxSizingReliable = "4px" === (e.getComputedStyle (d, null) || {width: "4px"}).width, r = d.appendChild (a.createElement ("div")), r.style.cssText = d.style.cssText = s, r.style.marginRight = r.style.width = "0", d.style.width = "1px", t.reliableMarginRight = !parseFloat ((e.getComputedStyle (r, null) || {}).marginRight)), typeof d.style.zoom !== i && (d.innerHTML = "", d.style.cssText = s + "width:1px;padding:1px;display:inline;zoom:1", t.inlineBlockNeedsLayout = 3 === d.offsetWidth, d.style.display = "block", d.innerHTML = "
    ", d.firstChild.style.width = "5px", t.shrinkWrapBlocks = 3 !== d.offsetWidth, t.inlineBlockNeedsLayout && (l.style.zoom = 1)), l.removeChild (n), n = d = o = r = null) + }), n = s = l = u = r = o = null, t + } ({}); + var B = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, P = /([A-Z])/g; + + function R (e, n, r, i) + { + if (x.acceptData (e)) + { + var o, a, s = x.expando, l = e.nodeType, u = l ? x.cache : e, c = l ? e[s] : e[s] && s; + if (c && u[c] && (i || u[c].data) || r !== t || "string" != typeof n)return c || (c = l ? e[s] = p.pop () || x.guid++ : s), u[c] || (u[c] = l ? {} : {toJSON: x.noop}), ("object" == typeof n || "function" == typeof n) && (i ? u[c] = x.extend (u[c], n) : u[c].data = x.extend (u[c].data, n)), a = u[c], i || (a.data || (a.data = {}), a = a.data), r !== t && (a[x.camelCase (n)] = r), "string" == typeof n ? (o = a[n], null == o && (o = a[x.camelCase (n)])) : o = a, o + } + } + + function W (e, t, n) + { + if (x.acceptData (e)) + { + var r, i, o = e.nodeType, a = o ? x.cache : e, s = o ? e[x.expando] : x.expando; + if (a[s]) + { + if (t && (r = n ? a[s] : a[s].data)) + { + x.isArray (t) ? t = t.concat (x.map (t, x.camelCase)) : t in r ? t = [t] : (t = x.camelCase (t), t = t in r ? [t] : t.split (" ")), i = t.length; + while (i--)delete r[t[i]]; + if (n ? !I (r) : !x.isEmptyObject (r))return + } + (n || (delete a[s].data, I (a[s]))) && (o ? x.cleanData ([e], !0) : x.support.deleteExpando || a != a.window ? delete a[s] : a[s] = null) + } + } + } + + x.extend ({cache: {}, noData: {applet: !0, embed: !0, object: "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"}, hasData: function (e) + { + return e = e.nodeType ? x.cache[e[x.expando]] : e[x.expando], !!e && !I (e) + }, data: function (e, t, n) + { + return R (e, t, n) + }, removeData: function (e, t) + { + return W (e, t) + }, _data: function (e, t, n) + { + return R (e, t, n, !0) + }, _removeData: function (e, t) + { + return W (e, t, !0) + }, acceptData: function (e) + { + if (e.nodeType && 1 !== e.nodeType && 9 !== e.nodeType)return!1; + var t = e.nodeName && x.noData[e.nodeName.toLowerCase ()]; + return!t || t !== !0 && e.getAttribute ("classid") === t + }}), x.fn.extend ({data: function (e, n) + { + var r, i, o = null, a = 0, s = this[0]; + if (e === t) + { + if (this.length && (o = x.data (s), 1 === s.nodeType && !x._data (s, "parsedAttrs"))) + { + for (r = s.attributes; r.length > a; a++)i = r[a].name, 0 === i.indexOf ("data-") && (i = x.camelCase (i.slice (5)), $ (s, i, o[i])); + x._data (s, "parsedAttrs", !0) + } + return o + } + return"object" == typeof e ? this.each (function () + { + x.data (this, e) + }) : arguments.length > 1 ? this.each (function () + { + x.data (this, e, n) + }) : s ? $ (s, e, x.data (s, e)) : null + }, removeData: function (e) + { + return this.each (function () + { + x.removeData (this, e) + }) + }}); + function $ (e, n, r) + { + if (r === t && 1 === e.nodeType) + { + var i = "data-" + n.replace (P, "-$1").toLowerCase (); + if (r = e.getAttribute (i), "string" == typeof r) + { + try + { + r = "true" === r ? !0 : "false" === r ? !1 : "null" === r ? null : +r + "" === r ? +r : B.test (r) ? x.parseJSON (r) : r + } catch (o) + { + } + x.data (e, n, r) + } else r = t + } + return r + } + + function I (e) + { + var t; + for (t in e)if (("data" !== t || !x.isEmptyObject (e[t])) && "toJSON" !== t)return!1; + return!0 + } + + x.extend ({queue: function (e, n, r) + { + var i; + return e ? (n = (n || "fx") + "queue", i = x._data (e, n), r && (!i || x.isArray (r) ? i = x._data (e, n, x.makeArray (r)) : i.push (r)), i || []) : t + }, dequeue: function (e, t) + { + t = t || "fx"; + var n = x.queue (e, t), r = n.length, i = n.shift (), o = x._queueHooks (e, t), a = function () + { + x.dequeue (e, t) + }; + "inprogress" === i && (i = n.shift (), r--), i && ("fx" === t && n.unshift ("inprogress"), delete o.stop, i.call (e, a, o)), !r && o && o.empty.fire () + }, _queueHooks: function (e, t) + { + var n = t + "queueHooks"; + return x._data (e, n) || x._data (e, n, {empty: x.Callbacks ("once memory").add (function () + { + x._removeData (e, t + "queue"), x._removeData (e, n) + })}) + }}), x.fn.extend ({queue: function (e, n) + { + var r = 2; + return"string" != typeof e && (n = e, e = "fx", r--), r > arguments.length ? x.queue (this[0], e) : n === t ? this : this.each (function () + { + var t = x.queue (this, e, n); + x._queueHooks (this, e), "fx" === e && "inprogress" !== t[0] && x.dequeue (this, e) + }) + }, dequeue: function (e) + { + return this.each (function () + { + x.dequeue (this, e) + }) + }, delay: function (e, t) + { + return e = x.fx ? x.fx.speeds[e] || e : e, t = t || "fx", this.queue (t, function (t, n) + { + var r = setTimeout (t, e); + n.stop = function () + { + clearTimeout (r) + } + }) + }, clearQueue: function (e) + { + return this.queue (e || "fx", []) + }, promise: function (e, n) + { + var r, i = 1, o = x.Deferred (), a = this, s = this.length, l = function () + { + --i || o.resolveWith (a, [a]) + }; + "string" != typeof e && (n = e, e = t), e = e || "fx"; + while (s--)r = x._data (a[s], e + "queueHooks"), r && r.empty && (i++, r.empty.add (l)); + return l (), o.promise (n) + }}); + var z, X, U = /[\t\r\n\f]/g, V = /\r/g, Y = /^(?:input|select|textarea|button|object)$/i, J = /^(?:a|area)$/i, G = /^(?:checked|selected)$/i, Q = x.support.getSetAttribute, K = x.support.input; + x.fn.extend ({attr: function (e, t) + { + return x.access (this, x.attr, e, t, arguments.length > 1) + }, removeAttr: function (e) + { + return this.each (function () + { + x.removeAttr (this, e) + }) + }, prop: function (e, t) + { + return x.access (this, x.prop, e, t, arguments.length > 1) + }, removeProp: function (e) + { + return e = x.propFix[e] || e, this.each (function () + { + try + { + this[e] = t, delete this[e] + } catch (n) + { + } + }) + }, addClass: function (e) + { + var t, n, r, i, o, a = 0, s = this.length, l = "string" == typeof e && e; + if (x.isFunction (e))return this.each (function (t) + { + x (this).addClass (e.call (this, t, this.className)) + }); + if (l)for (t = (e || "").match (T) || []; s > a; a++)if (n = this[a], r = 1 === n.nodeType && (n.className ? (" " + n.className + " ").replace (U, " ") : " ")) + { + o = 0; + while (i = t[o++])0 > r.indexOf (" " + i + " ") && (r += i + " "); + n.className = x.trim (r) + } + return this + }, removeClass: function (e) + { + var t, n, r, i, o, a = 0, s = this.length, l = 0 === arguments.length || "string" == typeof e && e; + if (x.isFunction (e))return this.each (function (t) + { + x (this).removeClass (e.call (this, t, this.className)) + }); + if (l)for (t = (e || "").match (T) || []; s > a; a++)if (n = this[a], r = 1 === n.nodeType && (n.className ? (" " + n.className + " ").replace (U, " ") : "")) + { + o = 0; + while (i = t[o++])while (r.indexOf (" " + i + " ") >= 0)r = r.replace (" " + i + " ", " "); + n.className = e ? x.trim (r) : "" + } + return this + }, toggleClass: function (e, t) + { + var n = typeof e; + return"boolean" == typeof t && "string" === n ? t ? this.addClass (e) : this.removeClass (e) : x.isFunction (e) ? this.each (function (n) + { + x (this).toggleClass (e.call (this, n, this.className, t), t) + }) : this.each (function () + { + if ("string" === n) + { + var t, r = 0, o = x (this), a = e.match (T) || []; + while (t = a[r++])o.hasClass (t) ? o.removeClass (t) : o.addClass (t) + } else(n === i || "boolean" === n) && (this.className && x._data (this, "__className__", this.className), this.className = this.className || e === !1 ? "" : x._data (this, "__className__") || "") + }) + }, hasClass: function (e) + { + var t = " " + e + " ", n = 0, r = this.length; + for (; r > n; n++)if (1 === this[n].nodeType && (" " + this[n].className + " ").replace (U, " ").indexOf (t) >= 0)return!0; + return!1 + }, val: function (e) + { + var n, r, i, o = this[0]; + { + if (arguments.length)return i = x.isFunction (e), this.each (function (n) + { + var o; + 1 === this.nodeType && (o = i ? e.call (this, n, x (this).val ()) : e, null == o ? o = "" : "number" == typeof o ? o += "" : x.isArray (o) && (o = x.map (o, function (e) + { + return null == e ? "" : e + "" + })), r = x.valHooks[this.type] || x.valHooks[this.nodeName.toLowerCase ()], r && "set"in r && r.set (this, o, "value") !== t || (this.value = o)) + }); + if (o)return r = x.valHooks[o.type] || x.valHooks[o.nodeName.toLowerCase ()], r && "get"in r && (n = r.get (o, "value")) !== t ? n : (n = o.value, "string" == typeof n ? n.replace (V, "") : null == n ? "" : n) + } + }}), x.extend ({valHooks: {option: {get: function (e) + { + var t = x.find.attr (e, "value"); + return null != t ? t : e.text + }}, select: {get: function (e) + { + var t, n, r = e.options, i = e.selectedIndex, o = "select-one" === e.type || 0 > i, a = o ? null : [], s = o ? i + 1 : r.length, l = 0 > i ? s : o ? i : 0; + for (; s > l; l++)if (n = r[l], !(!n.selected && l !== i || (x.support.optDisabled ? n.disabled : null !== n.getAttribute ("disabled")) || n.parentNode.disabled && x.nodeName (n.parentNode, "optgroup"))) + { + if (t = x (n).val (), o)return t; + a.push (t) + } + return a + }, set: function (e, t) + { + var n, r, i = e.options, o = x.makeArray (t), a = i.length; + while (a--)r = i[a], (r.selected = x.inArray (x (r).val (), o) >= 0) && (n = !0); + return n || (e.selectedIndex = -1), o + }}}, attr: function (e, n, r) + { + var o, a, s = e.nodeType; + if (e && 3 !== s && 8 !== s && 2 !== s)return typeof e.getAttribute === i ? x.prop (e, n, r) : (1 === s && x.isXMLDoc (e) || (n = n.toLowerCase (), o = x.attrHooks[n] || (x.expr.match.bool.test (n) ? X : z)), r === t ? o && "get"in o && null !== (a = o.get (e, n)) ? a : (a = x.find.attr (e, n), null == a ? t : a) : null !== r ? o && "set"in o && (a = o.set (e, r, n)) !== t ? a : (e.setAttribute (n, r + ""), r) : (x.removeAttr (e, n), t)) + }, removeAttr: function (e, t) + { + var n, r, i = 0, o = t && t.match (T); + if (o && 1 === e.nodeType)while (n = o[i++])r = x.propFix[n] || n, x.expr.match.bool.test (n) ? K && Q || !G.test (n) ? e[r] = !1 : e[x.camelCase ("default-" + n)] = e[r] = !1 : x.attr (e, n, ""), e.removeAttribute (Q ? n : r) + }, attrHooks: {type: {set: function (e, t) + { + if (!x.support.radioValue && "radio" === t && x.nodeName (e, "input")) + { + var n = e.value; + return e.setAttribute ("type", t), n && (e.value = n), t + } + }}}, propFix: {"for": "htmlFor", "class": "className"}, prop: function (e, n, r) + { + var i, o, a, s = e.nodeType; + if (e && 3 !== s && 8 !== s && 2 !== s)return a = 1 !== s || !x.isXMLDoc (e), a && (n = x.propFix[n] || n, o = x.propHooks[n]), r !== t ? o && "set"in o && (i = o.set (e, r, n)) !== t ? i : e[n] = r : o && "get"in o && null !== (i = o.get (e, n)) ? i : e[n] + }, propHooks: {tabIndex: {get: function (e) + { + var t = x.find.attr (e, "tabindex"); + return t ? parseInt (t, 10) : Y.test (e.nodeName) || J.test (e.nodeName) && e.href ? 0 : -1 + }}}}), X = {set: function (e, t, n) + { + return t === !1 ? x.removeAttr (e, n) : K && Q || !G.test (n) ? e.setAttribute (!Q && x.propFix[n] || n, n) : e[x.camelCase ("default-" + n)] = e[n] = !0, n + }}, x.each (x.expr.match.bool.source.match (/\w+/g), function (e, n) + { + var r = x.expr.attrHandle[n] || x.find.attr; + x.expr.attrHandle[n] = K && Q || !G.test (n) ? function (e, n, i) + { + var o = x.expr.attrHandle[n], a = i ? t : (x.expr.attrHandle[n] = t) != r (e, n, i) ? n.toLowerCase () : null; + return x.expr.attrHandle[n] = o, a + } : function (e, n, r) + { + return r ? t : e[x.camelCase ("default-" + n)] ? n.toLowerCase () : null + } + }), K && Q || (x.attrHooks.value = {set: function (e, n, r) + { + return x.nodeName (e, "input") ? (e.defaultValue = n, t) : z && z.set (e, n, r) + }}), Q || (z = {set: function (e, n, r) + { + var i = e.getAttributeNode (r); + return i || e.setAttributeNode (i = e.ownerDocument.createAttribute (r)), i.value = n += "", "value" === r || n === e.getAttribute (r) ? n : t + }}, x.expr.attrHandle.id = x.expr.attrHandle.name = x.expr.attrHandle.coords = function (e, n, r) + { + var i; + return r ? t : (i = e.getAttributeNode (n)) && "" !== i.value ? i.value : null + }, x.valHooks.button = {get: function (e, n) + { + var r = e.getAttributeNode (n); + return r && r.specified ? r.value : t + }, set: z.set}, x.attrHooks.contenteditable = {set: function (e, t, n) + { + z.set (e, "" === t ? !1 : t, n) + }}, x.each (["width", "height"], function (e, n) + { + x.attrHooks[n] = {set: function (e, r) + { + return"" === r ? (e.setAttribute (n, "auto"), r) : t + }} + })), x.support.hrefNormalized || x.each (["href", "src"], function (e, t) + { + x.propHooks[t] = {get: function (e) + { + return e.getAttribute (t, 4) + }} + }), x.support.style || (x.attrHooks.style = {get: function (e) + { + return e.style.cssText || t + }, set: function (e, t) + { + return e.style.cssText = t + "" + }}), x.support.optSelected || (x.propHooks.selected = {get: function (e) + { + var t = e.parentNode; + return t && (t.selectedIndex, t.parentNode && t.parentNode.selectedIndex), null + }}), x.each (["tabIndex", "readOnly", "maxLength", "cellSpacing", "cellPadding", "rowSpan", "colSpan", "useMap", "frameBorder", "contentEditable"], function () + { + x.propFix[this.toLowerCase ()] = this + }), x.support.enctype || (x.propFix.enctype = "encoding"), x.each (["radio", "checkbox"], function () + { + x.valHooks[this] = {set: function (e, n) + { + return x.isArray (n) ? e.checked = x.inArray (x (e).val (), n) >= 0 : t + }}, x.support.checkOn || (x.valHooks[this].get = function (e) + { + return null === e.getAttribute ("value") ? "on" : e.value + }) + }); + var Z = /^(?:input|select|textarea)$/i, et = /^key/, tt = /^(?:mouse|contextmenu)|click/, nt = /^(?:focusinfocus|focusoutblur)$/, rt = /^([^.]*)(?:\.(.+)|)$/; + + function it () + { + return!0 + } + + function ot () + { + return!1 + } + + function at () + { + try + { + return a.activeElement + } catch (e) + { + } + } + + x.event = {global: {}, add: function (e, n, r, o, a) + { + var s, l, u, c, p, f, d, h, g, m, y, v = x._data (e); + if (v) + { + r.handler && (c = r, r = c.handler, a = c.selector), r.guid || (r.guid = x.guid++), (l = v.events) || (l = v.events = {}), (f = v.handle) || (f = v.handle = function (e) + { + return typeof x === i || e && x.event.triggered === e.type ? t : x.event.dispatch.apply (f.elem, arguments) + }, f.elem = e), n = (n || "").match (T) || [""], u = n.length; + while (u--)s = rt.exec (n[u]) || [], g = y = s[1], m = (s[2] || "").split (".").sort (), g && (p = x.event.special[g] || {}, g = (a ? p.delegateType : p.bindType) || g, p = x.event.special[g] || {}, d = x.extend ({type: g, origType: y, data: o, handler: r, guid: r.guid, selector: a, needsContext: a && x.expr.match.needsContext.test (a), namespace: m.join (".")}, c), (h = l[g]) || (h = l[g] = [], h.delegateCount = 0, p.setup && p.setup.call (e, o, m, f) !== !1 || (e.addEventListener ? e.addEventListener (g, f, !1) : e.attachEvent && e.attachEvent ("on" + g, f))), p.add && (p.add.call (e, d), d.handler.guid || (d.handler.guid = r.guid)), a ? h.splice (h.delegateCount++, 0, d) : h.push (d), x.event.global[g] = !0); + e = null + } + }, remove: function (e, t, n, r, i) + { + var o, a, s, l, u, c, p, f, d, h, g, m = x.hasData (e) && x._data (e); + if (m && (c = m.events)) + { + t = (t || "").match (T) || [""], u = t.length; + while (u--)if (s = rt.exec (t[u]) || [], d = g = s[1], h = (s[2] || "").split (".").sort (), d) + { + p = x.event.special[d] || {}, d = (r ? p.delegateType : p.bindType) || d, f = c[d] || [], s = s[2] && RegExp ("(^|\\.)" + h.join ("\\.(?:.*\\.|)") + "(\\.|$)"), l = o = f.length; + while (o--)a = f[o], !i && g !== a.origType || n && n.guid !== a.guid || s && !s.test (a.namespace) || r && r !== a.selector && ("**" !== r || !a.selector) || (f.splice (o, 1), a.selector && f.delegateCount--, p.remove && p.remove.call (e, a)); + l && !f.length && (p.teardown && p.teardown.call (e, h, m.handle) !== !1 || x.removeEvent (e, d, m.handle), delete c[d]) + } else for (d in c)x.event.remove (e, d + t[u], n, r, !0); + x.isEmptyObject (c) && (delete m.handle, x._removeData (e, "events")) + } + }, trigger: function (n, r, i, o) + { + var s, l, u, c, p, f, d, h = [i || a], g = v.call (n, "type") ? n.type : n, m = v.call (n, "namespace") ? n.namespace.split (".") : []; + if (u = f = i = i || a, 3 !== i.nodeType && 8 !== i.nodeType && !nt.test (g + x.event.triggered) && (g.indexOf (".") >= 0 && (m = g.split ("."), g = m.shift (), m.sort ()), l = 0 > g.indexOf (":") && "on" + g, n = n[x.expando] ? n : new x.Event (g, "object" == typeof n && n), n.isTrigger = o ? 2 : 3, n.namespace = m.join ("."), n.namespace_re = n.namespace ? RegExp ("(^|\\.)" + m.join ("\\.(?:.*\\.|)") + "(\\.|$)") : null, n.result = t, n.target || (n.target = i), r = null == r ? [n] : x.makeArray (r, [n]), p = x.event.special[g] || {}, o || !p.trigger || p.trigger.apply (i, r) !== !1)) + { + if (!o && !p.noBubble && !x.isWindow (i)) + { + for (c = p.delegateType || g, nt.test (c + g) || (u = u.parentNode); u; u = u.parentNode)h.push (u), f = u; + f === (i.ownerDocument || a) && h.push (f.defaultView || f.parentWindow || e) + } + d = 0; + while ((u = h[d++]) && !n.isPropagationStopped ())n.type = d > 1 ? c : p.bindType || g, s = (x._data (u, "events") || {})[n.type] && x._data (u, "handle"), s && s.apply (u, r), s = l && u[l], s && x.acceptData (u) && s.apply && s.apply (u, r) === !1 && n.preventDefault (); + if (n.type = g, !o && !n.isDefaultPrevented () && (!p._default || p._default.apply (h.pop (), r) === !1) && x.acceptData (i) && l && i[g] && !x.isWindow (i)) + { + f = i[l], f && (i[l] = null), x.event.triggered = g; + try + { + i[g] () + } catch (y) + { + } + x.event.triggered = t, f && (i[l] = f) + } + return n.result + } + }, dispatch: function (e) + { + e = x.event.fix (e); + var n, r, i, o, a, s = [], l = g.call (arguments), u = (x._data (this, "events") || {})[e.type] || [], c = x.event.special[e.type] || {}; + if (l[0] = e, e.delegateTarget = this, !c.preDispatch || c.preDispatch.call (this, e) !== !1) + { + s = x.event.handlers.call (this, e, u), n = 0; + while ((o = s[n++]) && !e.isPropagationStopped ()) + { + e.currentTarget = o.elem, a = 0; + while ((i = o.handlers[a++]) && !e.isImmediatePropagationStopped ())(!e.namespace_re || e.namespace_re.test (i.namespace)) && (e.handleObj = i, e.data = i.data, r = ((x.event.special[i.origType] || {}).handle || i.handler).apply (o.elem, l), r !== t && (e.result = r) === !1 && (e.preventDefault (), e.stopPropagation ())) + } + return c.postDispatch && c.postDispatch.call (this, e), e.result + } + }, handlers: function (e, n) + { + var r, i, o, a, s = [], l = n.delegateCount, u = e.target; + if (l && u.nodeType && (!e.button || "click" !== e.type))for (; u != this; u = u.parentNode || this)if (1 === u.nodeType && (u.disabled !== !0 || "click" !== e.type)) + { + for (o = [], a = 0; l > a; a++)i = n[a], r = i.selector + " ", o[r] === t && (o[r] = i.needsContext ? x (r, this).index (u) >= 0 : x.find (r, this, null, [u]).length), o[r] && o.push (i); + o.length && s.push ({elem: u, handlers: o}) + } + return n.length > l && s.push ({elem: this, handlers: n.slice (l)}), s + }, fix: function (e) + { + if (e[x.expando])return e; + var t, n, r, i = e.type, o = e, s = this.fixHooks[i]; + s || (this.fixHooks[i] = s = tt.test (i) ? this.mouseHooks : et.test (i) ? this.keyHooks : {}), r = s.props ? this.props.concat (s.props) : this.props, e = new x.Event (o), t = r.length; + while (t--)n = r[t], e[n] = o[n]; + return e.target || (e.target = o.srcElement || a), 3 === e.target.nodeType && (e.target = e.target.parentNode), e.metaKey = !!e.metaKey, s.filter ? s.filter (e, o) : e + }, props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split (" "), fixHooks: {}, keyHooks: {props: "char charCode key keyCode".split (" "), filter: function (e, t) + { + return null == e.which && (e.which = null != t.charCode ? t.charCode : t.keyCode), e + }}, mouseHooks: {props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split (" "), filter: function (e, n) + { + var r, i, o, s = n.button, l = n.fromElement; + return null == e.pageX && null != n.clientX && (i = e.target.ownerDocument || a, o = i.documentElement, r = i.body, e.pageX = n.clientX + (o && o.scrollLeft || r && r.scrollLeft || 0) - (o && o.clientLeft || r && r.clientLeft || 0), e.pageY = n.clientY + (o && o.scrollTop || r && r.scrollTop || 0) - (o && o.clientTop || r && r.clientTop || 0)), !e.relatedTarget && l && (e.relatedTarget = l === e.target ? n.toElement : l), e.which || s === t || (e.which = 1 & s ? 1 : 2 & s ? 3 : 4 & s ? 2 : 0), e + }}, special: {load: {noBubble: !0}, focus: {trigger: function () + { + if (this !== at () && this.focus)try + { + return this.focus (), !1 + } catch (e) + { + } + }, delegateType: "focusin"}, blur: {trigger: function () + { + return this === at () && this.blur ? (this.blur (), !1) : t + }, delegateType: "focusout"}, click: {trigger: function () + { + return x.nodeName (this, "input") && "checkbox" === this.type && this.click ? (this.click (), !1) : t + }, _default: function (e) + { + return x.nodeName (e.target, "a") + }}, beforeunload: {postDispatch: function (e) + { + e.result !== t && (e.originalEvent.returnValue = e.result) + }}}, simulate: function (e, t, n, r) + { + var i = x.extend (new x.Event, n, {type: e, isSimulated: !0, originalEvent: {}}); + r ? x.event.trigger (i, null, t) : x.event.dispatch.call (t, i), i.isDefaultPrevented () && n.preventDefault () + }}, x.removeEvent = a.removeEventListener ? function (e, t, n) + { + e.removeEventListener && e.removeEventListener (t, n, !1) + } : function (e, t, n) + { + var r = "on" + t; + e.detachEvent && (typeof e[r] === i && (e[r] = null), e.detachEvent (r, n)) + }, x.Event = function (e, n) + { + return this instanceof x.Event ? (e && e.type ? (this.originalEvent = e, this.type = e.type, this.isDefaultPrevented = e.defaultPrevented || e.returnValue === !1 || e.getPreventDefault && e.getPreventDefault () ? it : ot) : this.type = e, n && x.extend (this, n), this.timeStamp = e && e.timeStamp || x.now (), this[x.expando] = !0, t) : new x.Event (e, n) + }, x.Event.prototype = {isDefaultPrevented: ot, isPropagationStopped: ot, isImmediatePropagationStopped: ot, preventDefault: function () + { + var e = this.originalEvent; + this.isDefaultPrevented = it, e && (e.preventDefault ? e.preventDefault () : e.returnValue = !1) + }, stopPropagation: function () + { + var e = this.originalEvent; + this.isPropagationStopped = it, e && (e.stopPropagation && e.stopPropagation (), e.cancelBubble = !0) + }, stopImmediatePropagation: function () + { + this.isImmediatePropagationStopped = it, this.stopPropagation () + }}, x.each ({mouseenter: "mouseover", mouseleave: "mouseout"}, function (e, t) + { + x.event.special[e] = {delegateType: t, bindType: t, handle: function (e) + { + var n, r = this, i = e.relatedTarget, o = e.handleObj; + return(!i || i !== r && !x.contains (r, i)) && (e.type = o.origType, n = o.handler.apply (this, arguments), e.type = t), n + }} + }), x.support.submitBubbles || (x.event.special.submit = {setup: function () + { + return x.nodeName (this, "form") ? !1 : (x.event.add (this, "click._submit keypress._submit", function (e) + { + var n = e.target, r = x.nodeName (n, "input") || x.nodeName (n, "button") ? n.form : t; + r && !x._data (r, "submitBubbles") && (x.event.add (r, "submit._submit", function (e) + { + e._submit_bubble = !0 + }), x._data (r, "submitBubbles", !0)) + }), t) + }, postDispatch: function (e) + { + e._submit_bubble && (delete e._submit_bubble, this.parentNode && !e.isTrigger && x.event.simulate ("submit", this.parentNode, e, !0)) + }, teardown: function () + { + return x.nodeName (this, "form") ? !1 : (x.event.remove (this, "._submit"), t) + }}), x.support.changeBubbles || (x.event.special.change = {setup: function () + { + return Z.test (this.nodeName) ? (("checkbox" === this.type || "radio" === this.type) && (x.event.add (this, "propertychange._change", function (e) + { + "checked" === e.originalEvent.propertyName && (this._just_changed = !0) + }), x.event.add (this, "click._change", function (e) + { + this._just_changed && !e.isTrigger && (this._just_changed = !1), x.event.simulate ("change", this, e, !0) + })), !1) : (x.event.add (this, "beforeactivate._change", function (e) + { + var t = e.target; + Z.test (t.nodeName) && !x._data (t, "changeBubbles") && (x.event.add (t, "change._change", function (e) + { + !this.parentNode || e.isSimulated || e.isTrigger || x.event.simulate ("change", this.parentNode, e, !0) + }), x._data (t, "changeBubbles", !0)) + }), t) + }, handle: function (e) + { + var n = e.target; + return this !== n || e.isSimulated || e.isTrigger || "radio" !== n.type && "checkbox" !== n.type ? e.handleObj.handler.apply (this, arguments) : t + }, teardown: function () + { + return x.event.remove (this, "._change"), !Z.test (this.nodeName) + }}), x.support.focusinBubbles || x.each ({focus: "focusin", blur: "focusout"}, function (e, t) + { + var n = 0, r = function (e) + { + x.event.simulate (t, e.target, x.event.fix (e), !0) + }; + x.event.special[t] = {setup: function () + { + 0 === n++ && a.addEventListener (e, r, !0) + }, teardown: function () + { + 0 === --n && a.removeEventListener (e, r, !0) + }} + }), x.fn.extend ({on: function (e, n, r, i, o) + { + var a, s; + if ("object" == typeof e) + { + "string" != typeof n && (r = r || n, n = t); + for (a in e)this.on (a, n, r, e[a], o); + return this + } + if (null == r && null == i ? (i = n, r = n = t) : null == i && ("string" == typeof n ? (i = r, r = t) : (i = r, r = n, n = t)), i === !1)i = ot; else if (!i)return this; + return 1 === o && (s = i, i = function (e) + { + return x ().off (e), s.apply (this, arguments) + }, i.guid = s.guid || (s.guid = x.guid++)), this.each (function () + { + x.event.add (this, e, i, r, n) + }) + }, one: function (e, t, n, r) + { + return this.on (e, t, n, r, 1) + }, off: function (e, n, r) + { + var i, o; + if (e && e.preventDefault && e.handleObj)return i = e.handleObj, x (e.delegateTarget).off (i.namespace ? i.origType + "." + i.namespace : i.origType, i.selector, i.handler), this; + if ("object" == typeof e) + { + for (o in e)this.off (o, n, e[o]); + return this + } + return(n === !1 || "function" == typeof n) && (r = n, n = t), r === !1 && (r = ot), this.each (function () + { + x.event.remove (this, e, r, n) + }) + }, trigger: function (e, t) + { + return this.each (function () + { + x.event.trigger (e, t, this) + }) + }, triggerHandler: function (e, n) + { + var r = this[0]; + return r ? x.event.trigger (e, n, r, !0) : t + }}); + var st = /^.[^:#\[\.,]*$/, lt = /^(?:parents|prev(?:Until|All))/, ut = x.expr.match.needsContext, ct = {children: !0, contents: !0, next: !0, prev: !0}; + x.fn.extend ({find: function (e) + { + var t, n = [], r = this, i = r.length; + if ("string" != typeof e)return this.pushStack (x (e).filter (function () + { + for (t = 0; i > t; t++)if (x.contains (r[t], this))return!0 + })); + for (t = 0; i > t; t++)x.find (e, r[t], n); + return n = this.pushStack (i > 1 ? x.unique (n) : n), n.selector = this.selector ? this.selector + " " + e : e, n + }, has: function (e) + { + var t, n = x (e, this), r = n.length; + return this.filter (function () + { + for (t = 0; r > t; t++)if (x.contains (this, n[t]))return!0 + }) + }, not: function (e) + { + return this.pushStack (ft (this, e || [], !0)) + }, filter: function (e) + { + return this.pushStack (ft (this, e || [], !1)) + }, is: function (e) + { + return!!ft (this, "string" == typeof e && ut.test (e) ? x (e) : e || [], !1).length + }, closest: function (e, t) + { + var n, r = 0, i = this.length, o = [], a = ut.test (e) || "string" != typeof e ? x (e, t || this.context) : 0; + for (; i > r; r++)for (n = this[r]; n && n !== t; n = n.parentNode)if (11 > n.nodeType && (a ? a.index (n) > -1 : 1 === n.nodeType && x.find.matchesSelector (n, e))) + { + n = o.push (n); + break + } + return this.pushStack (o.length > 1 ? x.unique (o) : o) + }, index: function (e) + { + return e ? "string" == typeof e ? x.inArray (this[0], x (e)) : x.inArray (e.jquery ? e[0] : e, this) : this[0] && this[0].parentNode ? this.first ().prevAll ().length : -1 + }, add: function (e, t) + { + var n = "string" == typeof e ? x (e, t) : x.makeArray (e && e.nodeType ? [e] : e), r = x.merge (this.get (), n); + return this.pushStack (x.unique (r)) + }, addBack: function (e) + { + return this.add (null == e ? this.prevObject : this.prevObject.filter (e)) + }}); + function pt (e, t) + { + do e = e[t]; while (e && 1 !== e.nodeType); + return e + } + + x.each ({parent: function (e) + { + var t = e.parentNode; + return t && 11 !== t.nodeType ? t : null + }, parents: function (e) + { + return x.dir (e, "parentNode") + }, parentsUntil: function (e, t, n) + { + return x.dir (e, "parentNode", n) + }, next: function (e) + { + return pt (e, "nextSibling") + }, prev: function (e) + { + return pt (e, "previousSibling") + }, nextAll: function (e) + { + return x.dir (e, "nextSibling") + }, prevAll: function (e) + { + return x.dir (e, "previousSibling") + }, nextUntil: function (e, t, n) + { + return x.dir (e, "nextSibling", n) + }, prevUntil: function (e, t, n) + { + return x.dir (e, "previousSibling", n) + }, siblings: function (e) + { + return x.sibling ((e.parentNode || {}).firstChild, e) + }, children: function (e) + { + return x.sibling (e.firstChild) + }, contents: function (e) + { + return x.nodeName (e, "iframe") ? e.contentDocument || e.contentWindow.document : x.merge ([], e.childNodes) + }}, function (e, t) + { + x.fn[e] = function (n, r) + { + var i = x.map (this, t, n); + return"Until" !== e.slice (-5) && (r = n), r && "string" == typeof r && (i = x.filter (r, i)), this.length > 1 && (ct[e] || (i = x.unique (i)), lt.test (e) && (i = i.reverse ())), this.pushStack (i) + } + }), x.extend ({filter: function (e, t, n) + { + var r = t[0]; + return n && (e = ":not(" + e + ")"), 1 === t.length && 1 === r.nodeType ? x.find.matchesSelector (r, e) ? [r] : [] : x.find.matches (e, x.grep (t, function (e) + { + return 1 === e.nodeType + })) + }, dir: function (e, n, r) + { + var i = [], o = e[n]; + while (o && 9 !== o.nodeType && (r === t || 1 !== o.nodeType || !x (o).is (r)))1 === o.nodeType && i.push (o), o = o[n]; + return i + }, sibling: function (e, t) + { + var n = []; + for (; e; e = e.nextSibling)1 === e.nodeType && e !== t && n.push (e); + return n + }}); + function ft (e, t, n) + { + if (x.isFunction (t))return x.grep (e, function (e, r) + { + return!!t.call (e, r, e) !== n + }); + if (t.nodeType)return x.grep (e, function (e) + { + return e === t !== n + }); + if ("string" == typeof t) + { + if (st.test (t))return x.filter (t, e, n); + t = x.filter (t, e) + } + return x.grep (e, function (e) + { + return x.inArray (e, t) >= 0 !== n + }) + } + + function dt (e) + { + var t = ht.split ("|"), n = e.createDocumentFragment (); + if (n.createElement)while (t.length)n.createElement (t.pop ()); + return n + } + + var ht = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", gt = / jQuery\d+="(?:null|\d+)"/g, mt = RegExp ("<(?:" + ht + ")[\\s/>]", "i"), yt = /^\s+/, vt = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, bt = /<([\w:]+)/, xt = /\s*$/g, At = {option: [1, ""], legend: [1, "
    ", "
    "], area: [1, "", ""], param: [1, "", ""], thead: [1, "", "
    "], tr: [2, "", "
    "], col: [2, "", "
    "], td: [3, "", "
    "], _default: x.support.htmlSerialize ? [0, "", ""] : [1, "X
    ", "
    "]}, jt = dt (a), Dt = jt.appendChild (a.createElement ("div")); + At.optgroup = At.option, At.tbody = At.tfoot = At.colgroup = At.caption = At.thead, At.th = At.td, x.fn.extend ({text: function (e) + { + return x.access (this, function (e) + { + return e === t ? x.text (this) : this.empty ().append ((this[0] && this[0].ownerDocument || a).createTextNode (e)) + }, null, e, arguments.length) + }, append: function () + { + return this.domManip (arguments, function (e) + { + if (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) + { + var t = Lt (this, e); + t.appendChild (e) + } + }) + }, prepend: function () + { + return this.domManip (arguments, function (e) + { + if (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) + { + var t = Lt (this, e); + t.insertBefore (e, t.firstChild) + } + }) + }, before: function () + { + return this.domManip (arguments, function (e) + { + this.parentNode && this.parentNode.insertBefore (e, this) + }) + }, after: function () + { + return this.domManip (arguments, function (e) + { + this.parentNode && this.parentNode.insertBefore (e, this.nextSibling) + }) + }, remove: function (e, t) + { + var n, r = e ? x.filter (e, this) : this, i = 0; + for (; null != (n = r[i]); i++)t || 1 !== n.nodeType || x.cleanData (Ft (n)), n.parentNode && (t && x.contains (n.ownerDocument, n) && _t (Ft (n, "script")), n.parentNode.removeChild (n)); + return this + }, empty: function () + { + var e, t = 0; + for (; null != (e = this[t]); t++) + { + 1 === e.nodeType && x.cleanData (Ft (e, !1)); + while (e.firstChild)e.removeChild (e.firstChild); + e.options && x.nodeName (e, "select") && (e.options.length = 0) + } + return this + }, clone: function (e, t) + { + return e = null == e ? !1 : e, t = null == t ? e : t, this.map (function () + { + return x.clone (this, e, t) + }) + }, html: function (e) + { + return x.access (this, function (e) + { + var n = this[0] || {}, r = 0, i = this.length; + if (e === t)return 1 === n.nodeType ? n.innerHTML.replace (gt, "") : t; + if (!("string" != typeof e || Tt.test (e) || !x.support.htmlSerialize && mt.test (e) || !x.support.leadingWhitespace && yt.test (e) || At[(bt.exec (e) || ["", ""])[1].toLowerCase ()])) + { + e = e.replace (vt, "<$1>"); + try + { + for (; i > r; r++)n = this[r] || {}, 1 === n.nodeType && (x.cleanData (Ft (n, !1)), n.innerHTML = e); + n = 0 + } catch (o) + { + } + } + n && this.empty ().append (e) + }, null, e, arguments.length) + }, replaceWith: function () + { + var e = x.map (this, function (e) + { + return[e.nextSibling, e.parentNode] + }), t = 0; + return this.domManip (arguments, function (n) + { + var r = e[t++], i = e[t++]; + i && (r && r.parentNode !== i && (r = this.nextSibling), x (this).remove (), i.insertBefore (n, r)) + }, !0), t ? this : this.remove () + }, detach: function (e) + { + return this.remove (e, !0) + }, domManip: function (e, t, n) + { + e = d.apply ([], e); + var r, i, o, a, s, l, u = 0, c = this.length, p = this, f = c - 1, h = e[0], g = x.isFunction (h); + if (g || !(1 >= c || "string" != typeof h || x.support.checkClone) && Nt.test (h))return this.each (function (r) + { + var i = p.eq (r); + g && (e[0] = h.call (this, r, i.html ())), i.domManip (e, t, n) + }); + if (c && (l = x.buildFragment (e, this[0].ownerDocument, !1, !n && this), r = l.firstChild, 1 === l.childNodes.length && (l = r), r)) + { + for (a = x.map (Ft (l, "script"), Ht), o = a.length; c > u; u++)i = l, u !== f && (i = x.clone (i, !0, !0), o && x.merge (a, Ft (i, "script"))), t.call (this[u], i, u); + if (o)for (s = a[a.length - 1].ownerDocument, x.map (a, qt), u = 0; o > u; u++)i = a[u], kt.test (i.type || "") && !x._data (i, "globalEval") && x.contains (s, i) && (i.src ? x._evalUrl (i.src) : x.globalEval ((i.text || i.textContent || i.innerHTML || "").replace (St, ""))); + l = r = null + } + return this + }}); + function Lt (e, t) + { + return x.nodeName (e, "table") && x.nodeName (1 === t.nodeType ? t : t.firstChild, "tr") ? e.getElementsByTagName ("tbody")[0] || e.appendChild (e.ownerDocument.createElement ("tbody")) : e + } + + function Ht (e) + { + return e.type = (null !== x.find.attr (e, "type")) + "/" + e.type, e + } + + function qt (e) + { + var t = Et.exec (e.type); + return t ? e.type = t[1] : e.removeAttribute ("type"), e + } + + function _t (e, t) + { + var n, r = 0; + for (; null != (n = e[r]); r++)x._data (n, "globalEval", !t || x._data (t[r], "globalEval")) + } + + function Mt (e, t) + { + if (1 === t.nodeType && x.hasData (e)) + { + var n, r, i, o = x._data (e), a = x._data (t, o), s = o.events; + if (s) + { + delete a.handle, a.events = {}; + for (n in s)for (r = 0, i = s[n].length; i > r; r++)x.event.add (t, n, s[n][r]) + } + a.data && (a.data = x.extend ({}, a.data)) + } + } + + function Ot (e, t) + { + var n, r, i; + if (1 === t.nodeType) + { + if (n = t.nodeName.toLowerCase (), !x.support.noCloneEvent && t[x.expando]) + { + i = x._data (t); + for (r in i.events)x.removeEvent (t, r, i.handle); + t.removeAttribute (x.expando) + } + "script" === n && t.text !== e.text ? (Ht (t).text = e.text, qt (t)) : "object" === n ? (t.parentNode && (t.outerHTML = e.outerHTML), x.support.html5Clone && e.innerHTML && !x.trim (t.innerHTML) && (t.innerHTML = e.innerHTML)) : "input" === n && Ct.test (e.type) ? (t.defaultChecked = t.checked = e.checked, t.value !== e.value && (t.value = e.value)) : "option" === n ? t.defaultSelected = t.selected = e.defaultSelected : ("input" === n || "textarea" === n) && (t.defaultValue = e.defaultValue) + } + } + + x.each ({appendTo: "append", prependTo: "prepend", insertBefore: "before", insertAfter: "after", replaceAll: "replaceWith"}, function (e, t) + { + x.fn[e] = function (e) + { + var n, r = 0, i = [], o = x (e), a = o.length - 1; + for (; a >= r; r++)n = r === a ? this : this.clone (!0), x (o[r])[t] (n), h.apply (i, n.get ()); + return this.pushStack (i) + } + }); + function Ft (e, n) + { + var r, o, a = 0, s = typeof e.getElementsByTagName !== i ? e.getElementsByTagName (n || "*") : typeof e.querySelectorAll !== i ? e.querySelectorAll (n || "*") : t; + if (!s)for (s = [], r = e.childNodes || e; null != (o = r[a]); a++)!n || x.nodeName (o, n) ? s.push (o) : x.merge (s, Ft (o, n)); + return n === t || n && x.nodeName (e, n) ? x.merge ([e], s) : s + } + + function Bt (e) + { + Ct.test (e.type) && (e.defaultChecked = e.checked) + } + + x.extend ({clone: function (e, t, n) + { + var r, i, o, a, s, l = x.contains (e.ownerDocument, e); + if (x.support.html5Clone || x.isXMLDoc (e) || !mt.test ("<" + e.nodeName + ">") ? o = e.cloneNode (!0) : (Dt.innerHTML = e.outerHTML, Dt.removeChild (o = Dt.firstChild)), !(x.support.noCloneEvent && x.support.noCloneChecked || 1 !== e.nodeType && 11 !== e.nodeType || x.isXMLDoc (e)))for (r = Ft (o), s = Ft (e), a = 0; null != (i = s[a]); ++a)r[a] && Ot (i, r[a]); + if (t)if (n)for (s = s || Ft (e), r = r || Ft (o), a = 0; null != (i = s[a]); a++)Mt (i, r[a]); else Mt (e, o); + return r = Ft (o, "script"), r.length > 0 && _t (r, !l && Ft (e, "script")), r = s = i = null, o + }, buildFragment: function (e, t, n, r) + { + var i, o, a, s, l, u, c, p = e.length, f = dt (t), d = [], h = 0; + for (; p > h; h++)if (o = e[h], o || 0 === o)if ("object" === x.type (o))x.merge (d, o.nodeType ? [o] : o); else if (wt.test (o)) + { + s = s || f.appendChild (t.createElement ("div")), l = (bt.exec (o) || ["", ""])[1].toLowerCase (), c = At[l] || At._default, s.innerHTML = c[1] + o.replace (vt, "<$1>") + c[2], i = c[0]; + while (i--)s = s.lastChild; + if (!x.support.leadingWhitespace && yt.test (o) && d.push (t.createTextNode (yt.exec (o)[0])), !x.support.tbody) + { + o = "table" !== l || xt.test (o) ? "" !== c[1] || xt.test (o) ? 0 : s : s.firstChild, i = o && o.childNodes.length; + while (i--)x.nodeName (u = o.childNodes[i], "tbody") && !u.childNodes.length && o.removeChild (u) + } + x.merge (d, s.childNodes), s.textContent = ""; + while (s.firstChild)s.removeChild (s.firstChild); + s = f.lastChild + } else d.push (t.createTextNode (o)); + s && f.removeChild (s), x.support.appendChecked || x.grep (Ft (d, "input"), Bt), h = 0; + while (o = d[h++])if ((!r || -1 === x.inArray (o, r)) && (a = x.contains (o.ownerDocument, o), s = Ft (f.appendChild (o), "script"), a && _t (s), n)) + { + i = 0; + while (o = s[i++])kt.test (o.type || "") && n.push (o) + } + return s = null, f + }, cleanData: function (e, t) + { + var n, r, o, a, s = 0, l = x.expando, u = x.cache, c = x.support.deleteExpando, f = x.event.special; + for (; null != (n = e[s]); s++)if ((t || x.acceptData (n)) && (o = n[l], a = o && u[o])) + { + if (a.events)for (r in a.events)f[r] ? x.event.remove (n, r) : x.removeEvent (n, r, a.handle); + u[o] && (delete u[o], c ? delete n[l] : typeof n.removeAttribute !== i ? n.removeAttribute (l) : n[l] = null, p.push (o)) + } + }, _evalUrl: function (e) + { + return x.ajax ({url: e, type: "GET", dataType: "script", async: !1, global: !1, "throws": !0}) + }}), x.fn.extend ({wrapAll: function (e) + { + if (x.isFunction (e))return this.each (function (t) + { + x (this).wrapAll (e.call (this, t)) + }); + if (this[0]) + { + var t = x (e, this[0].ownerDocument).eq (0).clone (!0); + this[0].parentNode && t.insertBefore (this[0]), t.map (function () + { + var e = this; + while (e.firstChild && 1 === e.firstChild.nodeType)e = e.firstChild; + return e + }).append (this) + } + return this + }, wrapInner: function (e) + { + return x.isFunction (e) ? this.each (function (t) + { + x (this).wrapInner (e.call (this, t)) + }) : this.each (function () + { + var t = x (this), n = t.contents (); + n.length ? n.wrapAll (e) : t.append (e) + }) + }, wrap: function (e) + { + var t = x.isFunction (e); + return this.each (function (n) + { + x (this).wrapAll (t ? e.call (this, n) : e) + }) + }, unwrap: function () + { + return this.parent ().each (function () + { + x.nodeName (this, "body") || x (this).replaceWith (this.childNodes) + }).end () + }}); + var Pt, Rt, Wt, $t = /alpha\([^)]*\)/i, It = /opacity\s*=\s*([^)]*)/, zt = /^(top|right|bottom|left)$/, Xt = /^(none|table(?!-c[ea]).+)/, Ut = /^margin/, Vt = RegExp ("^(" + w + ")(.*)$", "i"), Yt = RegExp ("^(" + w + ")(?!px)[a-z%]+$", "i"), Jt = RegExp ("^([+-])=(" + w + ")", "i"), Gt = {BODY: "block"}, Qt = {position: "absolute", visibility: "hidden", display: "block"}, Kt = {letterSpacing: 0, fontWeight: 400}, Zt = ["Top", "Right", "Bottom", "Left"], en = ["Webkit", "O", "Moz", "ms"]; + + function tn (e, t) + { + if (t in e)return t; + var n = t.charAt (0).toUpperCase () + t.slice (1), r = t, i = en.length; + while (i--)if (t = en[i] + n, t in e)return t; + return r + } + + function nn (e, t) + { + return e = t || e, "none" === x.css (e, "display") || !x.contains (e.ownerDocument, e) + } + + function rn (e, t) + { + var n, r, i, o = [], a = 0, s = e.length; + for (; s > a; a++)r = e[a], r.style && (o[a] = x._data (r, "olddisplay"), n = r.style.display, t ? (o[a] || "none" !== n || (r.style.display = ""), "" === r.style.display && nn (r) && (o[a] = x._data (r, "olddisplay", ln (r.nodeName)))) : o[a] || (i = nn (r), (n && "none" !== n || !i) && x._data (r, "olddisplay", i ? n : x.css (r, "display")))); + for (a = 0; s > a; a++)r = e[a], r.style && (t && "none" !== r.style.display && "" !== r.style.display || (r.style.display = t ? o[a] || "" : "none")); + return e + } + + x.fn.extend ({css: function (e, n) + { + return x.access (this, function (e, n, r) + { + var i, o, a = {}, s = 0; + if (x.isArray (n)) + { + for (o = Rt (e), i = n.length; i > s; s++)a[n[s]] = x.css (e, n[s], !1, o); + return a + } + return r !== t ? x.style (e, n, r) : x.css (e, n) + }, e, n, arguments.length > 1) + }, show: function () + { + return rn (this, !0) + }, hide: function () + { + return rn (this) + }, toggle: function (e) + { + return"boolean" == typeof e ? e ? this.show () : this.hide () : this.each (function () + { + nn (this) ? x (this).show () : x (this).hide () + }) + }}), x.extend ({cssHooks: {opacity: {get: function (e, t) + { + if (t) + { + var n = Wt (e, "opacity"); + return"" === n ? "1" : n + } + }}}, cssNumber: {columnCount: !0, fillOpacity: !0, fontWeight: !0, lineHeight: !0, opacity: !0, order: !0, orphans: !0, widows: !0, zIndex: !0, zoom: !0}, cssProps: {"float": x.support.cssFloat ? "cssFloat" : "styleFloat"}, style: function (e, n, r, i) + { + if (e && 3 !== e.nodeType && 8 !== e.nodeType && e.style) + { + var o, a, s, l = x.camelCase (n), u = e.style; + if (n = x.cssProps[l] || (x.cssProps[l] = tn (u, l)), s = x.cssHooks[n] || x.cssHooks[l], r === t)return s && "get"in s && (o = s.get (e, !1, i)) !== t ? o : u[n]; + if (a = typeof r, "string" === a && (o = Jt.exec (r)) && (r = (o[1] + 1) * o[2] + parseFloat (x.css (e, n)), a = "number"), !(null == r || "number" === a && isNaN (r) || ("number" !== a || x.cssNumber[l] || (r += "px"), x.support.clearCloneStyle || "" !== r || 0 !== n.indexOf ("background") || (u[n] = "inherit"), s && "set"in s && (r = s.set (e, r, i)) === t)))try + { + u[n] = r + } catch (c) + { + } + } + }, css: function (e, n, r, i) + { + var o, a, s, l = x.camelCase (n); + return n = x.cssProps[l] || (x.cssProps[l] = tn (e.style, l)), s = x.cssHooks[n] || x.cssHooks[l], s && "get"in s && (a = s.get (e, !0, r)), a === t && (a = Wt (e, n, i)), "normal" === a && n in Kt && (a = Kt[n]), "" === r || r ? (o = parseFloat (a), r === !0 || x.isNumeric (o) ? o || 0 : a) : a + }}), e.getComputedStyle ? (Rt = function (t) + { + return e.getComputedStyle (t, null) + }, Wt = function (e, n, r) + { + var i, o, a, s = r || Rt (e), l = s ? s.getPropertyValue (n) || s[n] : t, u = e.style; + return s && ("" !== l || x.contains (e.ownerDocument, e) || (l = x.style (e, n)), Yt.test (l) && Ut.test (n) && (i = u.width, o = u.minWidth, a = u.maxWidth, u.minWidth = u.maxWidth = u.width = l, l = s.width, u.width = i, u.minWidth = o, u.maxWidth = a)), l + }) : a.documentElement.currentStyle && (Rt = function (e) + { + return e.currentStyle + }, Wt = function (e, n, r) + { + var i, o, a, s = r || Rt (e), l = s ? s[n] : t, u = e.style; + return null == l && u && u[n] && (l = u[n]), Yt.test (l) && !zt.test (n) && (i = u.left, o = e.runtimeStyle, a = o && o.left, a && (o.left = e.currentStyle.left), u.left = "fontSize" === n ? "1em" : l, l = u.pixelLeft + "px", u.left = i, a && (o.left = a)), "" === l ? "auto" : l + }); + function on (e, t, n) + { + var r = Vt.exec (t); + return r ? Math.max (0, r[1] - (n || 0)) + (r[2] || "px") : t + } + + function an (e, t, n, r, i) + { + var o = n === (r ? "border" : "content") ? 4 : "width" === t ? 1 : 0, a = 0; + for (; 4 > o; o += 2)"margin" === n && (a += x.css (e, n + Zt[o], !0, i)), r ? ("content" === n && (a -= x.css (e, "padding" + Zt[o], !0, i)), "margin" !== n && (a -= x.css (e, "border" + Zt[o] + "Width", !0, i))) : (a += x.css (e, "padding" + Zt[o], !0, i), "padding" !== n && (a += x.css (e, "border" + Zt[o] + "Width", !0, i))); + return a + } + + function sn (e, t, n) + { + var r = !0, i = "width" === t ? e.offsetWidth : e.offsetHeight, o = Rt (e), a = x.support.boxSizing && "border-box" === x.css (e, "boxSizing", !1, o); + if (0 >= i || null == i) + { + if (i = Wt (e, t, o), (0 > i || null == i) && (i = e.style[t]), Yt.test (i))return i; + r = a && (x.support.boxSizingReliable || i === e.style[t]), i = parseFloat (i) || 0 + } + return i + an (e, t, n || (a ? "border" : "content"), r, o) + "px" + } + + function ln (e) + { + var t = a, n = Gt[e]; + return n || (n = un (e, t), "none" !== n && n || (Pt = (Pt || x ("