Monty  Boehm

Monty Boehm

1656597180

Soss.jl: Probabilistic Programming Via Source Rewriting

Soss   

Soss is a library for probabilistic programming.

Let's look at an example. First we'll load things:

using MeasureTheory
using Soss

MeasureTheory.jl is designed specifically with PPLs like Soss in mind, though you can also use Distributions.jl.

Now for a model. Here's a linear regression:

m = @model x begin
    α ~ Lebesgue(ℝ)
    β ~ Normal()
    σ ~ Exponential()
    y ~ For(x) do xj
        Normal(α + β * xj, σ)
    end
    return y
end

Next we'll generate some fake data to work with. For x-values, let's use

x = randn(20)

Now loosely speaking, Lebesgue(ℝ) is uniform over the real numbers, so we can't really sample from it. Instead, let's transform the model and make α an argument:

julia> predα = predictive(m, :α)
@model (x, α) begin
        σ ~ Exponential()
        β ~ Normal()
        y ~ For(x) do xj
                Normal(α + β * xj, σ)
            end
        return y
    end

Now we can do

julia> y = rand(predα(x=x,α=10.0))
20-element Vector{Float64}:
 10.554133456468438
  9.378065258831002
 12.873667041657287
  8.940799408080496
 10.737189595204965
  9.500536439014208
 11.327606120726893
 10.899892855024445
 10.18488773139243
 10.386969795947177
 10.382195272387214
  8.358407507910297
 10.727173015711768
 10.452311211064654
 11.076232496702387
 11.362009520020141
  9.539433052406448
 10.61851691333643
 11.586170856832645
  9.197496058151618

Now for inference! Let's use DynamicHMC, which we have wrapped in SampleChainsDynamicHMC.

julia> using SampleChainsDynamicHMC
[ Info: Precompiling SampleChainsDynamicHMC [6d9fd711-e8b2-4778-9c70-c1dfb499d4c4]

julia> post = sample(m(x=x) | (y=y,), dynamichmc())
4000-element MultiChain with 4 chains and schema (σ = Float64, β = Float64, α = Float64)
(σ = 1.0±0.15, β = 0.503±0.26, α = 10.2±0.25)

How is Soss different from Turing?

First, a fine point: When people say "the Turing PPL" they usually mean what's technically called "DynamicPPL".

  • In Soss, models are first class, and can be composed or nested. For example, you can define a model and later nest it inside another model, and inference will handle both together. DynamicPPL can also handle nested models (see this PR) though I'm not aware of a way to combine independently-defined DynamicPPL models for a single inference pass.
  • Soss has been updated to use MeasureTheory.jl, though everything from Distributions.jl is still available.
  • Soss allows model transformations. This can be used, for example, to easily express predictive distributions or Markov blanket as a new model.
  • Most of the focus of Soss is at the syntactic level; inference works in terms of "primitives" that transform the model's abstract syntax tree (AST) to new code. This adds the same benefits as using Julia's macros and generated functions, as opposed to higher-order functions alone.
  • Soss can evaluate log-densities symbolically, which can then be used to produce optimized evaluations for much faster inference. This capability is in relatively early stages, and will be made more robust in our ongoing development.
  • The Soss team is much smaller than that of DynamicPPL. But I hope that will change (contributors welcome!)

Soss and DynamicPPL are both maturing and becoming more complete, so the above will change over time. It's also worth noting that we (the Turing team and I) hope to move toward a natural way of using these systems together to arrive at the best of both.

How can I get involved?

I'm glad you asked! Lots of things:

For more details, please see the documentation.

Stargazers over time

Stargazers over time

Author: cscherrer
Source Code: https://github.com/cscherrer/Soss.jl 
License: MIT license

#julia #library #programming 

Soss.jl: Probabilistic Programming Via Source Rewriting

Chronos: A Standalone DateTime Library Originally Based Off Of Carbon

CakePHP Chronos    

Chronos aims to be a drop-in replacement for nesbot/carbon. It focuses on providing immutable date/datetime objects. Immutable objects help ensure that datetime objects aren't accidentally modified keeping data more predictable.

Installation

Installing with composer:

$ composer require cakephp/chronos

You can then use Chronos:

<?php
require 'vendor/autoload.php';

use Cake\Chronos\Chronos;

printf("Now: %s", Chronos::now());

Differences with nesbot/carbon

The biggest and main difference is that Chronos extends DateTimeImmutable instead of DateTime. Immutability for date values has proven to be a great way of avoiding bugs and reduce the amount of code, since developers don't have to manually copy the instance every time they need a change.

Another important feature it offers is the Date class, which is used for representing dates without time (calendar dates). Any time method called on this type of object is basically a no-op.

There are other implementation changes, but one that users might not notice is Chronos considers Monday as the start of the week instead of Sunday. This follows the ISO-8601 and current versions of PHP 5.6 and PHP 7.

A minor but still noticeable difference is that Chronos has no external dependencies, it is completely standalone.

Finally, Chronos is faster than Carbon as it has been optimized for the creation of hundreds of instances with minimal overhead.

Migrating from Carbon

First add cakephp/chronos to your composer.json:

php composer.phar require cakephp/chronos

By default Chronos includes a compatibility script that creates aliases for the relevant Carbon classes. This will let most applications upgrade with very little effort. If you'd like to permanently update your code, you will need to update imports and typehints. Assuming src contains the files you want to migrate, we could use the following to update files:

# Replace imports
find ./src -type f -name '*.php' -exec sed -i '' 's/use Carbon\\CarbonInterval/use Cake\\Chronos\\ChronosInterval/g' {} \;
find ./src -type f -name '*.php' -exec sed -i '' 's/use Carbon\\CarbonImmutable/use Cake\\Chronos\\Chronos/g' {} \;
find ./src -type f -name '*.php' -exec sed -i '' 's/use Carbon\\Carbon/use Cake\\Chronos\\Chronos/g' {} \;

# Replace typehints and extensions
find ./src -type f -name '*.php' -exec sed -i '' 's/CarbonInterval/ChronosInterval/g' {} \;
find ./src -type f -name '*.php' -exec sed -i '' 's/CarbonImmutable/Chronos/g' {} \;
find ./src -type f -name '*.php' -exec sed -i '' 's/Carbon/Chronos/g' {} \;

At this point your code should mostly work as it did before. The biggest difference is that Chronos instances are immutable.

Immutable Object Changes

Immutable objects have a number of advantages:

  1. Using immutable objects is always free of side-effects.
  2. Dates and times don't accidentally change underneath other parts of your code.

With those benefits in mind, there are a few things you need to keep in mind when modifying immutable objects:

// This will lose modifications
$date = new Chronos('2015-10-21 16:29:00');
$date->modify('+2 hours');

// This will keep modifications
$date = new Chronos('2015-10-21 16:29:00');
$date = $date->modify('+2 hours');

Getting Mutable Objects

In the case that you need a mutable instance you can get one:

$time = new Chronos('2015-10-21 16:29:00');
$mutable = $time->toMutable();

$date = new Date('2015-10-21');
$mutable = $date->toMutable();

Converting Mutable Objects into Immutable ones.

If you have a mutable object and want an immutable variant you can do the following:

$time = new MutableDateTime('2015-10-21 16:29:00');
$fixed = $time->toImmutable();

$date = new MutableDate('2015-10-21');
$fixed = $date->toImmutable();

Calendar Dates

PHP only offers datetime objects as part of the native extensions. Chronos adds a number of conveniences to the traditional DateTime object and introduces a Date object. Date instances offer compatibility with the ChronosInterface, but have their time frozen to 00:00:00 and the timezone set to the server default timezone. This makes them ideal when working with calendar dates as the time components will always match.

use Cake\Chronos\Date;

$today = new Date();
echo $today;
// Outputs '2015-10-21'

echo $today->modify('+3 hours');
// Outputs '2015-10-21'

Like instances of Chronos, Date objects are also immutable. The MutableDate class provides a mutable variant of Date.

Documentation

A more descriptive documentation can be found at book.cakephp.org/chronos/2/en/.

API Documentation

API documentation can be found on api.cakephp.org/chronos.

Author: Cakephp
Source Code: https://github.com/cakephp/chronos 
License: MIT license

#php #cakephp #library #time 

Chronos: A Standalone DateTime Library Originally Based Off Of Carbon
Gordon  Taylor

Gordon Taylor

1656250740

NVD3: A Reusable Charting Library Written in D3.js

NVD3 - A reusable D3 charting library

Usage

Simply add the nv.d3 assets to your project and include them in your HTML.

<link href="nv.d3.min.css" rel="stylesheet">
<script src="nv.d3.min.js"></script>
  • nv.d3.js should appear after d3.js is included.
  • Prefer minified assets (.min) for production.

Dependencies

NVD3 is recommended to go with d3.js version 3.5.3 and later, but NOT d3 4.x yet. version 3.5.17 is the most recent d3 v3 release.

Minimum D3 version required: 3.4.4

For a D3v4 Version, see the work in progress at the nvd3 organization

Along with pieChart options padAngle and cornerRadius, the interactive guideline tooltip now requires these later versions of D3 (3.4.4+, specifically, to get interactive tooltips). The interactive guide lines rely on the more recent d3.bisector() method which treats accessors taking two parameters (the second being the element index) as comparators (see d3.bisector()).

Supported Browsers

NVD3 runs best on WebKit based browsers.

  • Google Chrome: latest version
  • Opera 15+ (i.e. webkit version)
  • Safari: latest version
  • Firefox: latest version
  • Internet Explorer: 10+

Do we support D3 v4.x?

No, we do not... we are very interested in taking this on but could use some help. Please let us know if you'd like to help make this a reality! :)

Changelog

1.8.6 Changes:

  • Community bugfixes

1.8.5 Changes:

  • Community bugfixes
  • New force-directed graph

1.8.4 Changes:

  • Community bugfixes including tooltip fixes.

1.8.3 Changes:

  • Lots of community bugfixes
  • Added force-directed chart

1.8.2 Changes:

  • Lots of community bugfixes and a few extra minor features

1.8.1 Changes:

  • Tooltips were refactored - If you have customized your tooltips, note that you may need to adjust your custom functions as the data passed has changed format. See the new tooltip options for more details.
  • Added boxplot charts | example
  • Added candlestick charts | example
  • Added extra donut chart abilities | examples
  • Added sunburst Charts | example
  • Time Series | example
  • Another legend format available | example
  • Lots of bug fixes (see closed issues)
  • (for all examples, see here)

1.7.1 Changes:

  • Fixed axis.staggerLabels bug.
  • Fixed Karma unit tests.
  • Fixed chart test pages.
  • Merged in nvd3-community changes and development branch.

1.7.0 Changes:

  • Fixes around 20 small bugs.
  • Fixed the notorious slowness of line charts and scatter plots on chrome
  • Combined the scatterChart and scatterChartWithLines models
  • Combined the linePlusBarChart and linePlusBarChartWithFocus models.
  • renamed some of the options (see the new documentation for what options are available for each chart)
  • Completed the migration of the option functions to an object format which allows the generation of the documentation in an automated way. Not everything has a description yet, but check it out!
  • Added extra options to the donut charts based on features that will be in d3 3.5. The donut example page loads the latest d3 from their 3.5 branch so keep that in mind.
  • Added an example of the parallelCoordinates chart.
  • Fixed up the half-done OHLC bar chart, and made an example for it as well.

1.6.0 Changes:

  • includes about a dozen bug fixes and pull requests I fixed and merged in from the issues/pulls from the original project.
  • It also standardized all indention

Current development focus

  • Review outstanding pull requests and issues.
  • Try to find an easy way to actually document usage and all chart options.
  • Improve the testing framework.
  • Setup continuous integration.

Bugs

Found a bug? Check out the latest from the master branch and make sure it's not already fixed first! If you don't see a related fix, please open an issue.


Optional dependencies

Including Fastdom in your project can greatly increase the performance of the line chart (particularly in Firefox and Internet Explorer) by batching DOM read and write operations to avoid layout thrashing. NVD3 will take advantage of Fastdom if present.


Contributing

If one of the existing models doesn't meet your needs, fork the project, implement the model and an example using it, send us a pull request, for consideration for inclusion in the project.

If you'd like to contribute consistently, show me what you've got with some good pull requests and you may get added to the nvd3-community org!

A few rules for pull requests

  1. Please commit to the master branch
  2. Do NOT check in anything under the build directory, it clutters up the commit and just gets overwritten later.
  3. All new features must come with unit test coverage
  4. Bug fixes should come with unit tests that prove their fix

If you want to test your changes using the example pages, you'll have to run grunt production to build the items into the build directory. You must do this before your changes show up in the examples, as they link to the build directory in order to properly show off the finished product. Please remember to NOT include the build files in your commit though, only include the source files you changed!

Tips for Testing

  • Unit tests were written in Karma and Mocha. Follow instructions in Building Latest to get npm packages setup. This may not work on Windows machines.
  • Run bower install to get bower dependencies.
  • Run grunt to start the unit tests.
  • Also visually inspect the HTML pages in the examples/ and test/ folders. Make sure there are no glaring errors.
  • Novus now uses Travis CI for continuous integration. Visit our travis build page to see the latest status.

Meteor Tinytests

  • Any Meteor-specific features can be tested from the command line using tinytest and Spacejam
  • spacejam can be installed by running npm install -g spacejam.
  • Tinytests can then be executed by running spacejam test-packages ./ from this project's root.

Building latest

  1. First clone the repository and checkout the master branch
  2. make sure nodejs is installed via your system's package manager.
  3. Install grunt, grunt-cli, and bower: npm install -g grunt grunt-cli bower

have node download nvd3's required modules with: npm install

build with: grunt production

You should now have a build directory with the js and css files within.


Inspired by the work of Mike Bostock's Towards Reusable Charts, and supported by a combined effort of Novus and the NVD3 community.

View Examples | NEW Documentation! | Development build status: Build Status


Author: novus
Source Code: https://github.com/novus/nvd3 
License: View license

#javascript #d3 #library 

NVD3: A Reusable Charting Library Written in D3.js
Rocio  O'Keefe

Rocio O'Keefe

1655886240

DynamicformFlutter: Flutter Widget to Build Forms with Easier Way

dynamicform 

create your form with easier way

Getting Started

  • Generate custom form
  • Form Controller to manage form
  • login Form
  • payment form
  • Pre-existing elements

Installing

Add the following to your pubspec.yaml file:

dependencies:
	dynamic_form: ^0.23.0

Simple Usage

Creating a basic SimpleDynamicForm:

        SimpleDynamicForm(
                  controller: controller,
                  groupElements: [
                          GroupElement(
                                        directionGroup: DirectionGroup.Vertical,
                                        textElements: [
                                        TextElement(
                                          id:"name",
                                          label: "name",
                                        ),
                                        TextElement(
                                            id:"password",
                                             label: "password", 
                                             typeInput: TypeInput.Password,
                                        )
                                    ],
                                )
                              ],
                          );

Properties in SimpleDynamicForm

PropertiesDescription
groupElementslist of element to build your form
paddingThe amount of space by which to inset the form
controllerThe FormController to get values and validate your form
submitButton(Widget) custom submit Widget that you want to add to the form

Declare FormController to get validation,list values of forms

 FormController controller = FormController();

you can access to controller from your submit button

 FormController controller = SimpleDynamicForm.of(context);

validate forms

controller.validate();

show error to forms fields after validation

  • error will be cleared automatically when form validate
 controller.addErrorToField(String idField,String errorMessage);

recuperate all values in form :

 controller.getAllValues();

if you are used ids in element, you can recuperate values with their ids

 Map values = controller.getByIds();

you recuperate by id

 controller.getValueById(id);

set input value in form :

you can change field value using id of that field

 controller.setFieldValueById(id,value);

clear all inputs in form :

 controller.clearValues();

LoginForm

pre-existing login form to make easy for you to build

Simple Usage

Creating a basic LoginForm :

  
    LoginForm(
          controller:controller
          submitLogin:RaisedButton(
           onPressed: () {
                final email = controller.email;
                final password = controller.password;
                print("$email,$password");
              },
          child: Text("Log In"),
         ),
          onlyEmail: false,
          textButton: Text("Log IN"),
          paddingFields: const EdgeInsets.all(0),
          decorationLoginForm: DecorationLoginForm(
            commonDecoration: decoration,
            decorationEmailElement: OutlineDecorationElement(
                contentPadding: EdgeInsets.only(
                left: 12.0,
              ),
            ),
            decorationPasswordElement: OutlinePasswordElementDecoration(
                contentPadding: EdgeInsets.only(left: 8),
                prefix: Padding(
                   padding: EdgeInsets.all(6.0),
                   child: Icon(
                      Icons.lock,
                      size: 20,
                  ),
            ),
            enableVisibilityPassword: false
      ),
    )

LoginFormController

  • validate login form
  • recuperate email/password
  • show error in specific input
  1. initialization
LoginFormController controller = LoginFormController();
  1. recuperate email/Username,password
final email = controller.email;
final password = controller.password;
  1. access to controller in submit button
 LoginFormController controller = LoginForm.of(context)
  1. show field error after validation (use case when auth failed)
 controller.addEmailError("invalid Email not found");
 controller.addPasswordError("invalid Email not found");
  1. Properties
PropertiesDescription
controllerLoginFormController to validate login form and get data
decorationLoginForm(DecorationLoginForm) contain configuration of the inputs decoration of email/password fields in form
directionGroupDirection of form (Vertical/Horizontal)
paddingFieldspadding between fields
onlyEmailenable only email type textField
passwordErrormessages errors to show when password field not validate
usernameEmailErrormessages errors to show when email/username not validate
submitLogin(Widget) Button of submit form

PaymentForm

  • pre-existing payment form to make easy for you to build
  1. Simple Usage

Creating a basic PaymentForm :

    PaymentForm(
          controller:controller,
          decorationElement: OutlineDecorationElement(),
          errorMessageCVV: "cvv is invalid",
          errorMessageDateExpiration: "date expiration is invalid",
          errorIsRequiredMessage: "This field  is required",
          labelCVV: "cvv",
          labelDateExpiration: "date expiration",
          labelCardNumber: "card number",
          submitButton: ElevatedButton(
            onPressed: () {
              controller.validate();
            },
            child: Text("pay"),
          ),
        )

PaymentController

  1. initialization
PaymentController controller = PaymentController();
  1. validation payment form
bool isValid = controller.validate();
  1. recuperate cardNumber,cvv,dateExpiration
final cardNumber = controller.cardNumber;
final cvv = controller.cvv;
final dateExpiration = controller.dateExpiration;
  1. access to payment controller inside payment submit button
 PaymentController controller = PaymentForm.of(context);
  1. show field error after validation (use case when card check failed)
 controller.addCardNumberError(errorMessage);
 controller.addCVVError(errorMessage);
 controller.addDateExpirationError(errorMessage);
  1. `Properties
PropertiesDescription
controller(PaymentController) controller to validate form,setError fields,clear values
entryModeDateExpiration(DateExpirationEntryMode) input type of card date expiration can be dropdown or input(textField)
decorationElementdecoration of all input field in form
buttonDecorationdecoration of button that contain radius,backgroundColor,width
errorMessageDateExpirationmessages errors to show when Date Expiration field not validate
errorMessageCVVmessages errors to show when cvv field is invalidate
errorMessageCardNumbermessages errors to show when credit card number is invalidate
errorIsRequiredMessagemessages errors to show when at least one field not filled
labelCardNumbertext label of credit card number field
labelDateExpirationtext label of date expiration field
labelCVVtext label of cvv field
submitButton(widget) submit button widget

API

How to sketch your form ?

textElement is small element in dynamicForm GroupElement is group of TextElement

GroupElement

PropertiesDescription
directionGroupDirection of form (Vertical/Horizontal)
sizeElementssize of each textElement of form When direction Horizontal,sum of values should be egal a 1
textElementsgroup of textElement.
paddingpadding of groups.
decorationdecoration of container groups.
backgroundColorcolor of the container groups.

textElement

PropertiesDescription
typeInputEnumerate to specifie type of TextField.
labeltext label of TextField.
DecorationElementinput decoration of TextField.
onTapcallback when you click on TextField .
hinttext hint of textField.
errorMsgmessage to show when TextField isn't validate.
labelStylestyle of label TextField
errorStylestyle of error message TextField
hintStylestyle of hint TextFieldcolor
readOnlyenable TextField uneditable
validatorcallback validation of TextField
paddingpadding of TextField
visibilityenable visibility of element

EmailElement

Pre-exsiting element

check validation of email

Pre-initialized values

extends from TextElement

PropertiesDescription
DecorationElementinput decoration of TextField.
labeltext label of TextField.
hinttext hint of textField.
isRequiredmake textField required in validation
errorEmailIsRequirederror message for textField when it's required
errorEmailPatternerror message for textField input when it's not email in validation
labelStylestyle of label TextField
errorStylestyle of error message TextField
hintStylestyle of hint TextFieldcolor
readOnlyenable TextField uneditable
paddingpadding of TextField

PasswordElement

Pre-exsiting element

check validation of password

Pre-initialized values

show/hide password

extends from TextElement

PropertiesDescription
DecorationElementinput decoration of TextField.
labeltext label of TextField.
hinttext hint of textField.
errorMsgmessage to show when TextField isn't validate.
labelStylestyle of label TextField
errorStylestyle of error message TextField
hintStylestyle of hint TextFieldcolor
readOnlyenable TextField uneditable
paddingpadding of TextField
enableShowPasswordenable eye icon,make password text visible
isRequiredmake passwordField required
minLengthminimun length accepted by password
hasUppercasemake password contains at least one upperCase character
hasSpecialCharactermake password contains at least one special character
hasDigitsmake password contains at least one digits
requiredErrorMsgmessage error to show when password is required
minLengthErrorMsgmessage error to show when password length is less then the specified
uppercaseErrorMsgmessage error to show when password doesn't contain any upperCase character
specialCharacterErrorMsgmessage error to show when password doesn't contain any special character

NumberElement

Pre-exsiting element for Number input

Pre-initialized values

enabled digitsOnly

extends from TextElement

PropertiesDescription
labeltext label of TextField.
hinttext hint of textField.
DecorationElementinput decoration of TextField.
errorMsgmessage to show when TextField isn't validate.
labelStylestyle of label TextField
errorStylestyle of error message TextField
hintStylestyle of hint TextFieldcolor
readOnlyenable TextField uneditable
paddingpadding of TextField
isDigitsenable only digit number

CountryElement

Pre-exsiting element for Country input

Pre-initialized values

pick country via BottomSheet

show flag of countries

PropertiesDescription
DecorationElementinput decoration of TextField.
labeltext label of TextField.
initValueInitiale Value to country input.
labelModalSheetTitle of modalSheet
labelSearchModalSheethint search textfield in BottomSheet
countryTextResultenumeration get result of selection countries
showFlagshow flag of countris in modalsheet
paddingpadding of TextField
readonlywhen enable TextField to be unmodified

PhoneNumberElement

Pre-exsiting element for phone number input

Pre-initialized values

To Do in PhoneNumberElement

[ ] pick calling phone via BottomSheet

[ ] show flag of countries for each calling code

Properties

PropertiesDescription
DecorationElementinput decoration of TextField.
labeltext label of TextField.
hinttext placeholder for phone number input.
initValueinitial Value to phone input.
errorMsgtext error message
validatorcallback validation of TextField
showPrefixFlagenable flag country to be visible at left of TextField
showSuffixFlagenable flag country to be visible at rigth of TextField
paddingpadding of TextField
showPrefixshow calling phone number(get current calling phone of user)
readOnlybool make TextField readOnly
initPrefix(String) initial calling code of the specific country
labelModalSheet(String) title of bottom sheet that shown list of calling code of countries

TextAreaElement

Pre-exsiting element for multiLine input (like commentField) Pre-initialized values

PropertiesDescription
maxLinesmaximum line to span in textField.
showCounterenable visibility of counterText.
maxCharacterThe limit on the number of characters that you can type in textField

DateElement

Pre-exsiting element for date field input Pre-initialized values

PropertiesDescription
idString,should be unique,
initDate(DateTime) initialize the input field
firstDate](DateTime) represent earliest allowable Date in date picker
lastDate(DateTime) represent latest allowable Date in date picker
format(DateFormat) for format the date that you pick (default :DateFormat.yMd())
selectableDayPredicate(SelectableDayPredicate) to enable dates to be selected
label(String) text label of TextField
decorationElementinput decoration of TextField
hint(String) hint text of textField
isRequired(bool) if true,make this field required
errorMsg(String) show error message when the field isn't validate
padding(EdgeInsets) padding of textField

RadioGroupElement

Pre-exsiting element for radioGroup field input Pre-initialized values

PropertiesDescription
idString,should be unique,
initValue(String) initialized select value of the radio group field
label(String) text label of the radio group field
labelAlignment(AlignmentGeometry) label text alignment
activeSelectedColor(Color) active select radio in the radio group field
decorationElementinput decoration of TextField
errorMsg(String) error message that will show when error
values(List
valuesLabel(List
padding(EdgeInsets) padding of textField

DecorationElement

abstract class

Pre-exsiting inputDecoration for TextFormField

Pre-initialized values

Typically one of UnderlineDecorationElement or OutlineDecorationElement or RoundedDecorationElement can be used.

UnderlineDecorationElement

PropertiesDescription
borderColorThe border Color to display when the InputDecorator does not have the focus.
errorBorderColorThe borwidthLineder Color to display when the InputDecorator does have the error.
focusBorderColorThe border Color to display when the InputDecorator does have the focus.
disabledBorderColorThe border Color to display when the InputDecorator is disabled.
radiusradius of the border.
widthSideThe width of this line of the border
filledColorbase fill color of the decoration
focusColorfocused fill color of the decoration

OutlineDecorationElement

PropertiesDescription
borderColorThe border Color to display when the InputDecorator does not have the focus.
errorBorderColorThe borwidthLineder Color to display when the InputDecorator does have the error.
focusBorderColorThe border Color to display when the InputDecorator does have the focus.
disabledBorderColorThe border Color to display when the InputDecorator is disabled.
radiusradius of the border.
widthSideThe width of this line of the border
filledColorbase fill color of the decoration
focusColorfocused fill color of the decoration

RoundedDecorationElement

without BorderSide

PropertiesDescription
radiusradius of the border.
filledColorbase fill color of the decoration
focusColorfocused fill color of the decoration

ButtonLoginDecorationElement

decoration for button login

PropertiesDescription
shapeButtonLoginshape of the login button.
backgroundColorButtonackground color of the login button
widthSubmitButtonwidth size of the login button
elevationelevation of the button
  • example
///decoration Element 
 final decoration = OutlineDecorationElement(
                     filledColor: Colors.white,
                     radius: BorderRadius.only(
                       topLeft: Radius.circular(5.0),
                       topRight: Radius.circular(5.0),
                     ),
                     widthSide: 0.6,
                   );

PasswordControls

define an validation rules for password input

PropertiesDescription
minLengthminimum length accepted by password
hasUppercasemake password contains at least one upperCase character
hasSpecialCharactermake password contains at least one special character
hasDigitsmake password contains at least one digits

Installing

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add dynamic_form

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  dynamic_form: ^0.23.0

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:dynamic_form/dynamic_form.dart';

example/lib/main.dart

import 'package:dynamic_form/dynamic_form.dart';
import 'package:flutter/material.dart';
import 'package:formdynamic/login_page.dart';

import 'payment_example.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _MyAppState();
// This widget is the root of your application.

}

class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
  TabController tabController;

  @override
  void initState() {
    super.initState();
    tabController = TabController(
      length: 3,
      initialIndex: 1,
      vsync: this,
    );
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Dynamic Form Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        backgroundColor: Colors.grey[300],
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text("Demo"),
          bottom: TabBar(
            controller: tabController,
            tabs: <Widget>[
              GestureDetector(
                onTap: () {
                  tabController.index = 0;
                },
                child: Text("Basic Example"),
              ),
              GestureDetector(
                onTap: () {
                  tabController.index = 1;
                },
                child: Text("Login form "),
              ),
              GestureDetector(
                onTap: () {
                  tabController.index = 2;
                },
                child: Text("payment form "),
              ),
            ],
          ),
          actions: [],
        ),
        body: TabBarView(
          controller: tabController,
          children: <Widget>[
            MyHomePage(),
            LoginPage(),
            PaymentExample(),
          ],
        ),
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  // controller.clearValues()
  @override
  Widget build(BuildContext context) {
    final controller = FormController();
    return Stack(
      children: [
        SingleChildScrollView(
          child: Column(
            children: <Widget>[
              SimpleDynamicForm(
                controller: controller,
                groupElements: [
                  GroupElement(
                    margin: EdgeInsets.only(bottom: 5.0),
                    directionGroup: DirectionGroup.Horizontal,
                    sizeElements: [0.3],
                    textElements: [
                      TextElement(
                          initValue: "",
                          label: "first name",
                          hint: "first name",
                          validator: (v) {
                            if (v.isEmpty) {
                              return "err";
                            }
                            return null;
                          }),
                      TextElement(
                          label: "last name",
                          isRequired: true,
                          initValue: "your name",
                          validator: (v) {
                            if (v != "your name") {
                              return "name not accepted";
                            }
                            return null;
                          }),
                    ],
                  ),
                  GroupElement(
                    directionGroup: DirectionGroup.Vertical,
                    textElements: [
                      SelectChoiceElement(
                        values: ["Male","Female"],
                        initValue: "Male",
                        label: "Gender",
                        id: "gender",
                        decorationElement: OutlineDecorationElement()
                      ),
                      RadioGroupElement(
                        id: "mode",
                        label: "Mode",
                        values: ["dark","light"],
                        valuesLabel: ["Dark Mode","Light Mode"],
                        initValue: "dark",
                        activeSelectedColor: Colors.red,
                        onSelected: (v){
                          print(v);
                        }
                      ),
                      PhoneNumberElement(
                        //label: "",
                        hint: "Phone Number",
                        errorMsg: "invalid phone number",
                        initValue: "1234567",
                        showPrefix: true,
                        showPrefixFlag: true,
                        readOnly: false,
                        visibility: false,
                        decorationElement: OutlineDecorationElement(
                          borderColor: Colors.grey,
                        ),
                      ),
                      DateElement(
                        id: "date",
                        hint: "date",
                        label: "date",
                        isRequired: true,
                        errorMsg: "this field is required",
                      ),
                      TextElement(
                        label: "last name",
                        isRequired: true,
                        initValue: "your name",
                        error: "this field is required",
                        validator: (v) {
                          if (v != "your name") {
                            return "name not accepted";
                          }
                          return null;
                        },
                      ),
                    ],
                  ),
                  GroupElement(
                    directionGroup: DirectionGroup.Vertical,
                    commonDecorationElements: OutlineDecorationElement(
                      contentPadding: EdgeInsets.only(left: 5, right: 3),
                      radius: BorderRadius.circular(4),
                    ),
                    padding: EdgeInsets.symmetric(vertical: 6, horizontal: 8),
                    textElements: [
                      CountryElement(
                        id: "countries",
                        label: "Pays",
                        labelModalSheet: "Pays",
                        labelSearchModalSheet: "search",
                        // decorationElement: OutlineDecorationElement(
                        //   radius: BorderRadius.circular(4),
                        // ),
                        initValue: "",
                        countryTextResult: CountryTextResult.countryCode,
                        showFlag: true,
                      ),
                      PhoneNumberElement(
                        label: "Phone",
                        showPrefix: true,
                        showSuffixFlag: true,
                        showPrefixFlag: false,
                        hint: "Phone",
                        initPrefix: "+216",
                      ),
                      TextAreaElement(
                        maxCharacter: 300,
                        maxLines: 4,
                        showCounter: false,
                      ),
                    ],
                  ),
                ],
                submitButton: SubmitForm(),
              ),
            ],
          ),
        ),
        Positioned(
          bottom: 16,
          right: 8,
          child: FloatingActionButton(
            heroTag: "clearForm",
            child: Icon(Icons.delete),
            onPressed: () => controller.clearValues(),
          ),
        ),
      ],
    );
  }
}

class SubmitForm extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final controller = SimpleDynamicForm.of(context);
    return ElevatedButton(
      onPressed: () {
        print(controller.validate());
        print(controller.getAllValues());
        print(controller.getAllValuesByIds());
        print(controller.getValueById("countries"));
      },
      child: Text("Validate"),
    );
  }
}

Author: liodali
Source Code: https://github.com/liodali/DynamicFormFlutter 
License: MIT license

#flutter #dart #library 

DynamicformFlutter: Flutter Widget to Build Forms with Easier Way
Elian  Harber

Elian Harber

1655655360

UIprogress: A Go Library to Render Progress Bars in Terminal Apps

uiprogress  

A Go library to render progress bars in terminal applications. It provides a set of flexible features with a customizable API.

example

Progress bars improve readability for terminal applications with long outputs by providing a concise feedback loop.

Features

  • Multiple Bars: uiprogress can render multiple progress bars that can be tracked concurrently
  • Dynamic Addition: Add additional progress bars any time, even after the progress tracking has started
  • Prepend and Append Functions: Append or prepend completion percent and time elapsed to the progress bars
  • Custom Decorator Functions: Add custom functions around the bar along with helper functions

Usage

To start listening for progress bars, call uiprogress.Start() and add a progress bar using uiprogress.AddBar(total int). Update the progress using bar.Incr() or bar.Set(n int). Full source code for the below example is available at example/simple/simple.go

uiprogress.Start()            // start rendering
bar := uiprogress.AddBar(100) // Add a new bar

// optionally, append and prepend completion and elapsed time
bar.AppendCompleted()
bar.PrependElapsed()

for bar.Incr() {
  time.Sleep(time.Millisecond * 20)
}

This will render the below in the terminal

example

Using Custom Decorators

You can also add a custom decorator function in addition to default bar.AppendCompleted() and bar.PrependElapsed() decorators. The below example tracks the current step for an application deploy progress. Source code for the below example is available at example/full/full.go

var steps = []string{"downloading source", "installing deps", "compiling", "packaging", "seeding database", "deploying", "staring servers"}
bar := uiprogress.AddBar(len(steps))

// prepend the current step to the bar
bar.PrependFunc(func(b *uiprogress.Bar) string {
  return "app: " + steps[b.Current()-1]
})

for bar.Incr() {
  time.Sleep(time.Millisecond * 10)
}

Rendering Multiple bars

You can add multiple bars using uiprogress.AddBar(n). The below example demonstrates updating multiple bars concurrently and adding a new bar later in the pipeline. Source for this example is available at example/multi/multi.go

waitTime := time.Millisecond * 100
uiprogress.Start()

// start the progress bars in go routines
var wg sync.WaitGroup

bar1 := uiprogress.AddBar(20).AppendCompleted().PrependElapsed()
wg.Add(1)
go func() {
  defer wg.Done()
  for bar1.Incr() {
    time.Sleep(waitTime)
  }
}()

bar2 := uiprogress.AddBar(40).AppendCompleted().PrependElapsed()
wg.Add(1)
go func() {
  defer wg.Done()
  for bar2.Incr() {
    time.Sleep(waitTime)
  }
}()

time.Sleep(time.Second)
bar3 := uiprogress.AddBar(20).PrependElapsed().AppendCompleted()
wg.Add(1)
go func() {
  defer wg.Done()
  for i := 1; i <= bar3.Total; i++ {
    bar3.Set(i)
    time.Sleep(waitTime)
  }
}()

// wait for all the go routines to finish
wg.Wait()

This will produce

example

Incr counter

Bar.Incr() is an atomic counter and can be used as a general tracker, making it ideal for tracking progress of work fanned out to a lots of go routines. The source code for the below example is available at example/incr/incr.go

runtime.GOMAXPROCS(runtime.NumCPU()) // use all available cpu cores

// create a new bar and prepend the task progress to the bar and fanout into 1k go routines
count := 1000
bar := uiprogress.AddBar(count).AppendCompleted().PrependElapsed()
bar.PrependFunc(func(b *uiprogress.Bar) string {
  return fmt.Sprintf("Task (%d/%d)", b.Current(), count)
})

uiprogress.Start()
var wg sync.WaitGroup

// fanout into go routines
for i := 0; i < count; i++ {
  wg.Add(1)
  go func() {
    defer wg.Done()
    time.Sleep(time.Millisecond * time.Duration(rand.Intn(500)))
    bar.Incr()
  }()
}
time.Sleep(time.Second) // wait for a second for all the go routines to finish
wg.Wait()
uiprogress.Stop()

Installation

$ go get -v github.com/gosuri/uiprogress

Todos

  •  Resize bars and decorators by auto detecting window's dimensions
  •  Handle more progress bars than vertical screen allows

Author: Gosuri
Source Code: https://github.com/gosuri/uiprogress 
License: MIT license

#go #golang #library 

UIprogress: A Go Library to Render Progress Bars in Terminal Apps
Elian  Harber

Elian Harber

1655640180

A Really Basic Thread-safe Progress Bar for Golang Applications

progressbar

A very simple thread-safe progress bar which should work on every OS without problems. I needed a progressbar for croc and everything I tried had problems, so I made another one. In order to be OS agnostic I do not plan to support multi-line outputs.

Install

go get -u github.com/schollz/progressbar/v3

Usage

Basic usage

bar := progressbar.Default(100)
for i := 0; i < 100; i++ {
    bar.Add(1)
    time.Sleep(40 * time.Millisecond)
}

which looks like:

Example of basic bar

I/O operations

The progressbar implements an io.Writer so it can automatically detect the number of bytes written to a stream, so you can use it as a progressbar for an io.Reader.

req, _ := http.NewRequest("GET", "https://dl.google.com/go/go1.14.2.src.tar.gz", nil)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()

f, _ := os.OpenFile("go1.14.2.src.tar.gz", os.O_CREATE|os.O_WRONLY, 0644)
defer f.Close()

bar := progressbar.DefaultBytes(
    resp.ContentLength,
    "downloading",
)
io.Copy(io.MultiWriter(f, bar), resp.Body)

which looks like:

Example of download bar

Progress bar with unknown length

A progressbar with unknown length is a spinner. Any bar with -1 length will automatically convert it to a spinner with a customizable spinner type. For example, the above code can be run and set the resp.ContentLength to -1.

which looks like:

Example of download bar with unknown length

Customization

There is a lot of customization that you can do - change the writer, the color, the width, description, theme, etc. See all the options.

bar := progressbar.NewOptions(1000,
    progressbar.OptionSetWriter(ansi.NewAnsiStdout()),
    progressbar.OptionEnableColorCodes(true),
    progressbar.OptionShowBytes(true),
    progressbar.OptionSetWidth(15),
    progressbar.OptionSetDescription("[cyan][1/3][reset] Writing moshable file..."),
    progressbar.OptionSetTheme(progressbar.Theme{
        Saucer:        "[green]=[reset]",
        SaucerHead:    "[green]>[reset]",
        SaucerPadding: " ",
        BarStart:      "[",
        BarEnd:        "]",
    }))
for i := 0; i < 1000; i++ {
    bar.Add(1)
    time.Sleep(5 * time.Millisecond)
}

which looks like:

Example of customized bar

Contributing

Pull requests are welcome. Feel free to...

  • Revise documentation
  • Add new features
  • Fix bugs
  • Suggest improvements

Thanks

Thanks @Dynom for massive improvements in version 2.0!

Thanks @CrushedPixel for adding descriptions and color code support!

Thanks @MrMe42 for adding some minor features!

Thanks @tehstun for some great PRs!

Thanks @Benzammour and @haseth for helping create v3!

Thanks @briandowns for compiling the list of spinners.

Author: Schollz
Source Code: https://github.com/schollz/progressbar 
License: MIT license

#go #golang #library #terminal 

A Really Basic Thread-safe Progress Bar for Golang Applications
Elian  Harber

Elian Harber

1655592960

An Elegant & Concurrent Library for The Telegram Bot API in Go

Echotron is a concurrent library for telegram bots written in pure Go.

Fetch with

go get github.com/NicoNex/echotron/v3

Design

Echotron is heavily based on concurrency: for example, every call to the Update method of each bot is executed on a different goroutine. This makes sure that, even if one instance of the bot is deadlocked, the other ones keep running just fine, making the bot work for other users without any issues and/or slowdowns.

Echotron is designed to be as similar to the official Telegram API as possible, but there are some things to take into account before starting to work with this library.

  • The methods have the exact same name, but with a capital first letter, since in Go methods have to start with a capital letter to be exported. Example: sendMessage becomes SendMessage
  • The order of the parameters in some methods is different than in the official Telegram API, so refer to the docs for the correct one.
  • The only chat_id (or, in this case, chatID) type supported is int64, instead of the "Integer or String" requirement of the official API. That's because numeric IDs can't change in any way, which isn't the case with text-based usernames.
  • In some methods, you might find a InputFile type parameter. InputFile is a struct with unexported fields, since only three combination of fields are valid, which can be obtained through the methods NewInputFileID, NewInputFilePath and NewInputFileBytes.
  • In some methods, you might find a MessageIDOptions type parameter. MessageIDOptions is another struct with unexported fields, since only two combination of field are valid, which can be obtained through the methods NewMessageID and NewInlineMessageID.
  • Optional parameters can be added by passing the correct struct to each method that might request optional parameters. If you don't want to pass any optional parameter, nil is more than enough. Refer to the docs to check for each method's optional parameters struct: it's the type of the opts parameter.
  • Some parameters are hardcoded to avoid putting random stuff which isn't recognized by the Telegram API. Some notable examples are ParseMode, ChatAction and InlineQueryType. For a full list of custom hardcoded parameters, refer to the docs for each custom type: by clicking on the type's name, you'll get the source which contains the possible values for that type.

Usage

Long Polling

A very simple implementation:

package main

import (
    "log"

    "github.com/NicoNex/echotron/v3"
)

// Struct useful for managing internal states in your bot, but it could be of
// any type such as `type bot int64` if you only need to store the chatID.
type bot struct {
    chatID int64
    echotron.API
}

const token = "YOUR TELEGRAM TOKEN"

// This function needs to be of type 'echotron.NewBotFn' and is called by
// the echotron dispatcher upon any new message from a chatID that has never
// interacted with the bot before.
// This means that echotron keeps one instance of the echotron.Bot implementation
// for each chat where the bot is used.
func newBot(chatID int64) echotron.Bot {
    return &bot{
        chatID,
        echotron.NewAPI(token),
    }
}

// This method is needed to implement the echotron.Bot interface.
func (b *bot) Update(update *echotron.Update) {
    if update.Message.Text == "/start" {
        b.SendMessage("Hello world", b.chatID, nil)
    }
}

func main() {
    // This is the entry point of echotron library.
    dsp := echotron.NewDispatcher(token, newBot)
    log.Println(dsp.Poll())
}

Functional example with bot internal states:

package main

import (
    "log"
    "strings"

    "github.com/NicoNex/echotron/v3"
)

// Recursive type definition of the bot state function.
type stateFn func(*echotron.Update) stateFn

type bot struct {
    chatID int64
    state  stateFn
    name   string
    echotron.API
}

const token = "YOUR TELEGRAM TOKEN"

func newBot(chatID int64) echotron.Bot {
    bot := &bot{
        chatID: chatID,
        API:    echotron.NewAPI(token),
    }
    // We set the default state to the bot.handleMessage method.
    bot.state = bot.handleMessage
    return bot
}

func (b *bot) Update(update *echotron.Update) {
    // Here we execute the current state and set the next one.
    b.state = b.state(update)
}

func (b *bot) handleMessage(update *echotron.Update) stateFn {
    if strings.HasPrefix(update.Message.Text, "/set_name") {
        b.SendMessage("Send me my new name!", b.chatID, nil)
        // Here we return b.handleName since next time we receive a message it
        // will be the new name.
        return b.handleName
    }
    return b.handleMessage
}

func (b *bot) handleName(update *echotron.Update) stateFn {
    b.name = update.Message.Text
    b.SendMessage(fmt.Sprintf("My new name is %q", b.name), b.chatID, nil)
    // Here we return b.handleMessage since the next time we receive a message
    // it will be handled in the default way.
    return b.handleMessage
}

func main() {
    dsp := echotron.NewDispatcher(token, newBot)
    log.Println(dsp.Poll())
}

Example with self destruction for lower RAM usage:

package main

import (
    "log"
    "time"

    "github.com/NicoNex/echotron/v3"
)

type bot struct {
    chatID int64
    echotron.API
}

const token = "YOUR TELEGRAM TOKEN"

var dsp echotron.Dispatcher

func newBot(chatID int64) echotron.Bot {
    bot := &bot{
        chatID,
        echotron.NewAPI(token),
    }
    go bot.selfDestruct(time.After(time.Hour))
    return bot
}

func (b *bot) selfDestruct(timech <- chan time.Time) {
    <-timech
    b.SendMessage("goodbye", b.chatID, nil)
    dsp.DelSession(b.chatID)
}

func (b *bot) Update(update *echotron.Update) {
    if update.Message.Text == "/start" {
        b.SendMessage("Hello world", b.chatId, nil)
    }
}

func main() {
    dsp = echotron.NewDispatcher(token, newBot)
    log.Println(dsp.Poll())
}

Webhook

package main

import "github.com/NicoNex/echotron/v3"

type bot struct {
    chatID int64
    echotron.API
}

const token = "YOUR TELEGRAM TOKEN"

func newBot(chatID int64) echotron.Bot {
    return &bot{
        chatID,
        echotron.NewAPI(token),
    }
}

func (b *bot) Update(update *echotron.Update) {
    if update.Message.Text == "/start" {
        b.SendMessage("Hello world", b.chatID, nil)
    }
}

func main() {
    dsp := echotron.NewDispatcher(token, newBot)
    dsp.ListenWebhook("https://example.com:443/my_bot_token")
}

Webhook with a custom http.Server

This is an example for a custom http.Server which handles your own specified routes and also the webhook route which is specified by ListenWebhook.

package main

import (
    "github.com/NicoNex/echotron/v3"

    "context"
    "log"
    "net/http"
)

type bot struct {
    chatID int64
    echotron.API
}

const token = "YOUR TELEGRAM TOKEN"

func newBot(chatID int64) echotron.Bot {
    return &bot{
        chatID,
        echotron.NewAPI(token),
    }
}

func (b *bot) Update(update *echotron.Update) {
    if update.Message.Text == "/start" {
        b.SendMessage("Hello world", b.chatID, nil)
    }
}

func main() {
    termChan := make(chan os.Signal, 1) // Channel for terminating the app via os.Interrupt signal
    signal.Notify(termChan, syscall.SIGINT, syscall.SIGTERM)

    mux := http.NewServeMux()
    mux.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
        // Handle user login
    })
    mux.HandleFunc("/logout", func(w http.ResponseWriter, r *http.Request) {
        // Handle user logout
    })
    mux.HandleFunc("/about", func(w http.ResponseWriter, r *http.Request) {
        // Tell something about your awesome telegram bot
    })

    // Set custom http.Server
    server := &http.Server{Addr: ":8080", Handler: mux}

    go func() {
        <-termChan
        // Perform some cleanup..
        if err := server.Shutdown(context.Background()); err != nil {
            log.Print(err)
        }
    }()

    // Capture the interrupt signal for app termination handling
    dsp := echotron.NewDispatcher(token, newBot)
    dsp.SetHTTPServer(server)
    // Start your custom http.Server with a registered /my_bot_token handler.
    log.Println(dsp.ListenWebhook("https://example.com/my_bot_token"))
}

Author: NicoNex
Source Code: https://github.com/NicoNex/echotron 
License: LGPL-3.0 license

#go #golang #bot #library #telegram 

An Elegant & Concurrent Library for The Telegram Bot API in Go
Sheldon  Grant

Sheldon Grant

1654932420

Plate.js -- A Template Library

Plate.js -- A Template Library

Plate is a Django Template Language implementation in Javascript. Super exciting!

Plate

  • Plays nicely with the event loop and async code. Plate makes it easy to parallelize your view code!
  • Aims to be compatible with the latest version of the Django Template Language. If you've got a template in Django, it should render just fine in Plate.
  • Thoroughly tested using tape.
  • Designed to work nicely in a Node.js environment
  • Extensible -- It makes use of plugins to provide capabilities (e.g., template loading).

How do I use it?

In node (or browserify):


    var plate = require('plate')

    var template = new plate.Template('hello {{ world }}')

    template.render({world:'everyone'}, function(err, data) {
      console.log(data)
    })

    // outputs "hello everyone"

Plate follows the Node.js style of taking callbacks that receive an error object and a data object. If there's no error, err will be null.

In browser (vanilla):

    <script type="text/javascript" src="plate.min.js">
    <script type="text/html" id="template">
        hello {{ world }}.
    </script>
    <script type="text/javascript">
        var source = $('#template').text()
          , template = new plate.Template(source)

        template.render({world: 'everyone'}, function(err, data) {
          console.log(data)
        })
    </script>

In browser (using require.js):


require(['plate.min'], function(plate) {
  var template = new plate.Template('hello {{ world }}')
})

Documentation

Plate is documented on its github wiki. There are "Getting Started" guides for both in-browser as well as in-node environments.

Contributing

Got a feature you'd like to add? I'd love to see it. The workflow is pretty standard Github fare:

  • Fork this repository.
  • Create a branch -- title it descriptively, please :)
  • Work, work, work.
  • Push your changes and submit a pull request.

The minimum requirements for a pull request to be merged are:

  • You've added (passing) tests for your new code.
  • The existing tests still pass.
  • You've added (or changed, as appropriate) documentation to the docs/ folder in Markdown format.

Run the tests

In node:


$ npm install plate
$ npm test plate

Can I use it in my browser?

Yes. Plate was designed to work well in the standard suite of browsers. Each minor point release will target compatibility with IE7+, FF3+, Chrome, and Safari 4+.

You can download a minified, precompiled version here.

If you're having trouble, try using the debug version, with source maps.

Author: Chrisdickinson
Source Code: https://github.com/chrisdickinson/plate 
License: MIT

#node #nodejs #javascript #library 

Plate.js -- A Template Library

Las 9 Mejores Bibliotecas De animación De JavaScript Y CSS

Hoy vamos a repasar 9 bibliotecas de animación gratuitas y bien codificadas que se adaptan mejor al trabajo de diseño de interfaz de usuario, cubriendo sus fortalezas y debilidades, y cuándo elegir cada una.

El diseño web front-end ha experimentado una revolución en la última década. A finales de los 2000, la mayoría de nosotros todavía estábamos diseñando diseños estáticos para revistas. Hoy en día, estamos construyendo “máquinas digitales” con miles de partes móviles, coordinadas y redimensionadas.

En pocas palabras, los grandes diseñadores de UI también deben ser grandes animadores , con una sólida comprensión de las técnicas y la tecnología de animación web.

Tenga en cuenta que estamos analizando cada biblioteca desde la perspectiva de un diseñador de interfaz de usuario experto en código, no como un desarrollador "gurú del código". Algunas de estas bibliotecas son CSS puro. Otros son JavaScript, pero ninguno requiere nada más que conocimientos básicos de HTML/CSS y/o JavaScript para ser útil.

Nuestra lista de las 9 mejores bibliotecas de animación

  1. Lottie.js : excelente para animaciones basadas en vectores a cualquier escala
  2. Animate.css : mejor para manipulaciones de interfaz de usuario pequeñas y específicas
  3. GreenSock (GSAP) : plataforma de animación gigante pero con todas las funciones capaz de cualquier cosa, desde juegos hasta desarrollo de aplicaciones.
  4. AnimeJS
  5. Animaciones Mágicas
  6. Zperro
  7. CSShake
  8. Hover.CSS
  9. AniJS

Lottie.js

Ejemplo de animación de Lottie (en GIF)

Seamos claros: Lottiejs es un tipo de biblioteca de animación muy diferente a los otros ocho en esta lista. Sin embargo, no creemos que los diseñadores de UI/UX puedan darse el lujo de ignorarlo.

Crear una animación de Lottie es más parecido a crear una producción de video. Necesitará una herramienta de animación de terceros que pueda exportar un archivo JSON 'listo para Lottie'. De hecho, el formato Lottie fue diseñado específicamente para hacer que las animaciones de Adobe After Effects funcionen de manera eficiente en la web y en dispositivos móviles. Esto hace que las animaciones de Lottie sean rápidas, eficientes, fáciles de escribir y, a menudo, bastante hermosas.

Aunque Lottie se concibió como una extensión de Adobe After Effects , hay muchas (posiblemente mejores) alternativas 'nativas de Lottie' para crear animaciones de Lottie. Éstos incluyen:

Lottie usa 'reproductores de animación' separados optimizados para Web, iOS y Android respectivamente. El código base de Lottie es desarrollado y mantenido por AirBnb y cuenta con una comunidad súper entusiasta y apasionada que crece detrás de él.

  • Creador : AirBnb
  • Lanzamiento : 2015
  • Popularidad :Estrellas en GitHub
  • Descripción: "Lottie es una biblioteca de iOS, Android y React Native que genera animaciones de After Effects en tiempo real".
  • GitHub : Lottie WebLottie iOSLottie Android
  • Licencia :Licencia

 

Animar.css

Animate.css es una de las bibliotecas de animación CSS más pequeñas y fáciles de usar. Es refinado, eficiente y bien mantenido desde su lanzamiento en 2013.

Aplicar la biblioteca de Animate a su proyecto es tan simple como vincular el CSS y agregar las clases de CSS requeridas a sus elementos HTML. Por supuesto, también puede usar jQuery o Vanilla JS para activar las animaciones en un evento en particular si lo prefiere.

Animar.CSS

  • Creador : Daniel Edén
  • Lanzamiento : 2013
  • Versión actual : v4.1.1
  • Popularidad :Estrellas en GitHub
  • Descripción: “Una biblioteca multinavegador de animaciones CSS. Tan fácil de usar como algo fácil.”
  • Tamaño de la biblioteca: 70 kB (minificado)
  • GitHub : https://github.com/daneden/animate.css
  • Licencia :

En el momento de escribir este artículo, sigue siendo una de las bibliotecas de animación CSS más populares y ampliamente utilizadas y su archivo minificado es lo suficientemente pequeño como para incluirlo también en sitios web móviles.

Animate.css todavía está en desarrollo activo. Tenga cuidado con la versión 4, que admitirá propiedades personalizadas de CSS (también conocidas como variables de CSS). Esta es una de las bibliotecas de animación más simples y robustas y no dudaríamos en usarla en cualquier proyecto.

Calcetín verde (GSAP)

GreenSock (o GSAP - GreenSock Animation Platform) es la navaja suiza de la animación web. Para animaciones elegantes y sofisticadas que funcionan sin problemas, GSAP es ideal. Puede animar cualquier cosa, desde elementos DOM hasta SVG, y su ecosistema incluye algunos complementos increíbles que le permiten hacer todo tipo de cosas divertidas, por ejemplo, transformar SVG, dibujar trazos SVG, funcionalidad de desplazamiento, codificar texto y mucho más. Es rápido, compatible con varios navegadores y su sintaxis es sencilla e intuitiva.

Calcetín verde (GSAP)

  • Versión actual : 3.10.4
  • Popularidad :Estrellas en GitHub
  • Descripción : “Animación de nivel profesional y ultra alto rendimiento para la web moderna”.
  • Tamaño de la biblioteca : 313 kB (carpeta minificada que contiene la descarga ligera de la biblioteca)
  • GitHub : https://github.com/greensock/GreenSock-JS/
  • Licencia : licencia estándar sin cargo, combinada con un modelo de pago para funciones y complementos específicos. Consulte la página de licencias para obtener más detalles.

GSAP es modular, por lo tanto, puede elegir qué partes de la biblioteca necesita para su proyecto, lo cual es excelente para mantener el tamaño del archivo bajo control.

Si está buscando algo poderoso pero intuitivo con una documentación increíble y soporte de la comunidad, definitivamente le recomendaría que pruebe esta biblioteca de animación en su próximo proyecto. Estarás entusiasmado.

 

AnimeJS

AnimeJS es la última incorporación a nuestra lista, pero ha ganado muchos adeptos desde su creación. Es increíblemente versátil y potente, y no estaría fuera de lugar para potenciar las animaciones de juegos HTML. La única pregunta real es " ¿es excesivo para aplicaciones web simples?"

Quizás. Pero como también es rápido, pequeño y relativamente fácil de aprender, es difícil encontrar fallas en él.

AnimeJS se describe como una “ biblioteca de animación de JavaScript ligera con una API simple pero potente. Funciona con propiedades CSS, SVG, atributos DOM y Objetos JavaScript ”. Bastante impresionante.

Este proyecto está disponible en GitHub .

  • Creador : Julián Garnier
  • Lanzamiento : 2016
  • Versión actual : v3.2.1
  • Popularidad :Estrellas en GitHub
  • Descripción : "Anime.js es una biblioteca de animación JavaScript liviana con una API simple pero poderosa".
  • Tamaño de la biblioteca : 16,8 kB (minificado)
  • GitHub : https://github.com/juliangarnier/anime
  • Licencia :

Lo más impresionante es que Anime.JS tiene una "documentación" impresionante que muestra HTML, código JavaScript y ejemplos de trabajo en un hermoso entorno de aplicación.

En resumen, si se siente cómodo con una solución de animación de JavaScript, es difícil encontrar razones para ignorar AnimeJS.

Animaciones Mágicas

Magic Animations ha sido una de las bibliotecas de animación más impresionantes disponibles. Tiene muchas animaciones diferentes, muchas de las cuales son bastante exclusivas de esta biblioteca. Al igual que con Animate.css, puede implementar Magic simplemente importando el archivo CSS. También puede implementar las animaciones usando jQuery. Este proyecto ofrece una aplicación de demostración particularmente interesante.

Sitio de animación mágica

  • Versión actual : 1.4.1
  • Popularidad :Estrellas en GitHub
  • Descripción : “Animaciones CSS3 con efectos especiales”
  • Tamaño de la biblioteca : 54,9 kB (minificado)
  • GitHub : https://github.com/miniMAC/magic
  • Licencia :

El tamaño de archivo de Magic Animation es moderado en comparación con Animate.css y es conocido por sus animaciones exclusivas, como los efectos mágicos, los efectos tontos y los efectos de bomba.

Si estás buscando algo un poco fuera de lo común, hazlo. No te decepcionará.

 

Zdog

Zdog es una biblioteca de JavaScript para crear diseños y animaciones en 3D de David DeSandro. Con su ayuda, puede dibujar sus diseños usando el <canvas>elemento o SVG y darles vida en animaciones fluidas con un elegante efecto 3D.

Zdog

  • Versión actual : 1.1.0
  • Popularidad :Estrellas en GitHub
  • Descripción : "Motor pseudo-3D redondo, plano y fácil
    de diseñar para lienzo y SVG"
  • Tamaño de la biblioteca : 28 kB (minificado)
  • GitHub : https://github.com/metafizzy/zdog
  • Licencia :

Si está familiarizado con JavaScript, aprenderá los conceptos básicos de Zdog con bastante rapidez: tiene una API declarativa sencilla, excelentes documentos y muchos recursos de aprendizaje. Consulte mi introducción a Zdog en SitePoint.

CSShake

CSShake ofrece exactamente lo que dice en la caja: una biblioteca de CSS diseñada específicamente para agitar elementos dentro de su página web. Como era de esperar, hay una serie de variaciones disponibles para agitar sus componentes web.

CSShake

Apple popularizó el tropo de la interfaz de usuario de sacudir vigorosamente un elemento de la interfaz de usuario (un cuadro de diálogo, modal o de texto) cuando un usuario ingresa una respuesta incorrecta, imitando a una persona que sacude la cabeza. CSShake proporciona una variedad de interesantes animaciones de "sacudidas" y no faltan variaciones en esta biblioteca.

 

Hover.css

Hover.css es una biblioteca de animación CSS diseñada para usarse con botones y otros elementos de la interfaz de usuario en su sitio web. Tiene transiciones 2D realmente agradables, junto con una gran cantidad de otras animaciones bien diseñadas.

Hover.css

  • Versión actual : 2.3.2
  • Popularidad :Estrellas en GitHub
  • Descripción : “Aplique fácilmente a sus propios elementos, modifíquelos o simplemente utilícelos como inspiración”.
  • Tamaño de la biblioteca : 93,0 kB (minificado)
  • GitHub : https://github.com/IanLunn/Hover
  • Licencia : licencia personal/de código abierto gratuita y licencia comercial de pago, según los requisitos. Para obtener más información, lea la sección de licencias en GitHub .

Hover.css es más adecuado para animar elementos de página discretos como botones, logotipos, componentes SVG o imágenes destacadas en lugar de animaciones de página más grandes y complejas. Podría decirse que sus efectos de animación más notables son sus burbujas de discurso y rizos distintivos.

AniJS

Nuestra biblioteca final es interesante por su enfoque único. AniJS es una biblioteca de animación que le permite agregar animaciones a elementos en una estructura simple 'similar a una oración'. Toma el siguiente formato:

Si hace clic, On Square, Do wobble animado a .container-box

<div data-anijs="if: click, do: flipInY, to: .container-box"></div>

Si no está muy familiarizado con JavaScript, esta puede ser una excelente manera de ingresar a los movimientos coreografiados por JS.

AniJS

  • Creador : Dariel Noel
  • Lanzamiento : 2014
  • Versión actual : 0.9.3
  • Popularidad :Estrellas en GitHub
  • Descripción : “Una Biblioteca para Levantar tu Diseño Web sin Codificar.”
  • Tamaño de la biblioteca : 10,5 kB
  • GitHub : https://github.com/anijs/anijs
  • Licencia :

AniJS es una biblioteca con un tamaño muy razonable teniendo en cuenta su funcionalidad. El formato que utiliza para la implementación es bastante original y diferente en comparación con otras bibliotecas de animación (que muchos otros pueden encontrar poco convencionales).

Sin embargo, vale la pena probar esta biblioteca, al menos una vez para sus proyectos.

 

¿Qué biblioteca debería elegir?

Hay muchas bibliotecas de animación listas y esperando para ser implementadas en su proyecto. Los enumerados anteriormente son algunos con la mejor combinación de sofisticación y estabilidad.

Si está buscando una solución CSS bien probada y fácil de implementar, Animate.css es probablemente la opción disponible más versátil y rentable.

Si está buscando una base de JavaScript más completa y potente para impulsar juegos, simuladores, modelos y otras aplicaciones sofisticadas en línea, GreenSock y AnimeJS son muy difíciles de dividir.

Si su estilo de arte está fuertemente basado en vectores y tiene una herramienta de animación compatible con Lottie, es difícil ignorar el movimiento suave y la eficiencia de Lottie.

Si bien el uso de una biblioteca de animación en su aplicación web sin duda puede mejorar la interactividad, exagerar anula el propósito y, a menudo, confunde al usuario. Tenga cuidado y use las animaciones con criterio.

¿Utiliza bibliotecas de animación para sus proyectos? ¿Cuáles son tus bibliotecas de animación favoritas?

 Esta historia se publicó originalmente en https://www.sitepoint.com/our-top-9-animation-libraries/

  #animation #library #anijs 

Las 9 Mejores Bibliotecas De animación De JavaScript Y CSS
坂本  健一

坂本 健一

1654893300

UIデザイナーのための9つの最高のJavaScriptとCSSアニメーションライブラリ

今日は、UIデザイン作業に最適な9つの無料の適切にコーディングされたアニメーションライブラリを実行します。それらの長所と短所、およびそれぞれをいつ選択するかについて説明します。

フロントエンドWebデザインは、過去10年間で革命を遂げてきました。後期の2000年代には、私たちのほとんどはまだ静的な雑誌のレイアウトを設計していました。今日、私たちは何千ものサイズ変更、調整、可動部品を備えた「デジタルマシン」を構築しています。

簡単に言うと、優れたUIデザイナーは、優れたアニメーターである必要があります。Webアニメーションの手法と技術をしっかりと理解している必要があります。

各ライブラリは、「コードの第一人者」の開発者としてではなく、コードに精通したUIデザイナーの観点から見ていることに注意してください。これらのライブラリのいくつかは純粋なCSSです。その他はJavaScriptですが、有用であるために基本的なHTML/CSSおよび/またはJavaScriptの理解以上のものを必要とするものはありません。

トップ9のアニメーションライブラリリスト

  1. Lottie.js:あらゆる規模のベクターベースのアニメーションに最適
  2. Animate.css:小規模でターゲットを絞ったUI操作に最適
  3. GreenSock(GSAP):ゲームからアプリケーション開発まで、あらゆる機能を備えた巨大なアニメーションプラットフォーム。
  4. AnimeJS
  5. 魔法のアニメーション
  6. ZDog
  7. CSShake
  8. Hover.CSS
  9. アニス

Lottie.js

ロッティアニメーションの例(GIF)

明確にしましょう。Lottiejsは、このリストの他の8つとは非常に異なるタイプのアニメーションライブラリです。それにもかかわらず、UI/UXデザイナーはそれを無視する余裕はないと思います。

Lottieアニメーションの作成は、ビデオ作品の作成に似ています。'Lottie-ready'JSONファイルをエクスポートできるサードパーティのアニメーションツールが必要になります。実際、Lottie形式は、AdobeAfterEffectsアニメーションがWebおよびモバイルで効率的に機能するように特別に設計されています。これにより、Lottieアニメーションは高速で効率的で、スクリプトが簡単になり、多くの場合非常に美しくなります。

LottieはAdobeAfterEffectsの拡張機能として考案されましたが、Lottieアニメーションを作成するための(おそらくより優れた)「Lottieネイティブ」の代替手段がたくさんあります。これらには以下が含まれます:

Lottieは、それぞれWeb、iOS、Android用に最適化された個別の「アニメーションプレーヤー」を使用しています。LottieコードベースはAirBnbによって開発および保守されており、その背後で非常に熱心で情熱的なコミュニティが成長しています。

  • 作成者AirBnb
  • リリース:2015
  • 人気GitHubのスター
  • 説明:「LottieはiOS、Android、およびReact Nativeライブラリであり、AfterEffectsアニメーションをリアルタイムでレンダリングします。」
  • GitHubLottie WebLottie iOSLottie Android
  • ライセンスライセンス

 

Animate.css

Animate.cssは、最小で最も使いやすいCSSアニメーションライブラリの1つです。2013年のリリース以来、洗練され、効率的で、手入れが行き届いています。

Animateライブラリをプロジェクトに適用するのは、CSSをリンクし、必要なCSSクラスをHTML要素に追加するのと同じくらい簡単です。もちろん、必要に応じて、jQueryまたはvanillaJSを使用して特定のイベントのアニメーションをトリガーすることもできます。

Animate.CSS

  • 作成者ダニエルエデン
  • リリース:2013
  • 現在のバージョン:v4.1.1
  • 人気GitHubのスター
  • 説明:「CSSアニメーションのクロスブラウザライブラリ。簡単なものと同じくらい使いやすいです。」
  • ライブラリサイズ: 70 kB(縮小)
  • GitHubhttps ://github.com/daneden/animate.css
  • ライセンス

これを書いている時点では、それは今でも最も人気があり広く使用されているCSSアニメーションライブラリの1つであり、その縮小されたファイルはモバイルWebサイトにも含めるのに十分小さいです。

Animate.cssはまだ活発に開発中です。CSSカスタムプロパティ(別名CSS変数)をサポートするバージョン4に注意してください。これは最もシンプルで堅牢なアニメーションライブラリの1つであり、どのプロジェクトでもこれを使用することを躊躇しません。

GreenSock(GSAP)

GreenSock(またはGSAP – GreenSock Animation Platform)は、Webアニメーションのスイスアーミーナイフです。スムーズに実行される洗練された洗練されたアニメーションには、GSAPが理想的です。DOM要素からSVGまで、あらゆるものをアニメーション化できます。そのエコシステムには、SVGのモーフィング、SVGストロークの描画、スクロール機能、テキストのスクランブルなど、あらゆる種類の楽しいことを実行できるすばらしいプラグインが含まれています。高速でクロスブラウザ互換であり、構文は単純で直感的です。

GreenSock(GSAP)

  • 現在のバージョン:3.10.4
  • 人気GitHubのスター
  • 説明:「最新のWeb向けの超高性能でプロフェッショナルグレードのアニメーション。」
  • ライブラリサイズ:313 kB(ライブラリの軽量ダウンロードを含む縮小フォルダー)
  • GitHubhttps ://github.com/greensock/GreenSock-JS/
  • ライセンス:標準の無料ライセンスで、特定の機能とプラグインの有料モデルと混合されています。詳細については、ライセンスページを参照してください。

GSAPはモジュール式であるため、プロジェクトに必要なライブラリの部分を選択できます。これは、ファイルサイズを制御するのに最適です。

優れたドキュメントとコミュニティサポートを備えた強力で直感的なものをお探しの場合は、次のプロジェクトでこのアニメーションライブラリを試してみることをお勧めします。あなたは熱狂的になります。

 

AnimeJS

AnimeJSは私たちのリストに新しく追加されたものですが、作成以来、非常に多くのコンバージョンを獲得しています。それは信じられないほど用途が広く強力であり、HTMLゲームアニメーションを強化するのに場違いではありません。唯一の本当の質問は、「単純なWebアプリにとってはやり過ぎですか?

多分。しかし、それはまた速く、小さく、そして比較的簡単に学ぶことができるので、それの欠点を見つけるのは難しいです。

AnimeJSは、「シンプルでありながら強力なAPIを備えた軽量のJavaScriptアニメーションライブラリ」と呼ばれています。これは、CSSプロパティ、SVG、DOM属性、およびJavaScriptオブジェクトで機能します。めっちゃすごい。

このプロジェクトはGitHubで入手できます。

  • 作成者Julian Garnier
  • リリース:2016
  • 現在のバージョン:v3.2.1
  • 人気GitHubのスター
  • 説明:「Anime.jsは、シンプルでありながら強力なAPIを備えた軽量のJavaScriptアニメーションライブラリです。」
  • ライブラリサイズ:16.8 kB(縮小)
  • GitHubhttps ://github.com/juliangarnier/anime
  • ライセンス

最も印象的なことに、Anime.JSには、美しいアプリ環境でHTML、JavaScriptコード、および実用的な例を示す見事な「ドキュメント」があります。

つまり、JavaScriptアニメーションソリューションに慣れている場合、AnimeJSを無視する理由を見つけるのは困難です。

魔法のアニメーション

Magic Animationsは、利用可能な最も印象的なアニメーションライブラリの1つです。さまざまなアニメーションがあり、その多くはこのライブラリに非常に固有のものです。Animate.cssと同様に、CSSファイルをインポートするだけでMagicを実装できます。jQueryを使用してアニメーションを実装することもできます。このプロジェクトは、特にクールなデモアプリケーションを提供します。

マジックアニメーションサイト

  • 現在のバージョン:1.4.1
  • 人気GitHubのスター
  • 説明:「特殊効果のあるCSS3アニメーション」
  • ライブラリサイズ:54.9 kB(縮小)
  • GitHubhttps ://github.com/miniMAC/magic
  • ライセンス

Magic AnimationのファイルサイズはAnimate.cssに比べて適度であり、魔法の効果、愚かな効果、爆弾の効果などの特徴的なアニメーションで知られています。

少し変わったものを探しているなら、それを探してください。がっかりすることはありません。

 

Zdog

Zdogは、DavidDeSandroによる3Dデザインとアニメーションを作成するためのJavaScriptライブラリです。その助けを借りて、<canvas>要素またはSVGを使用してデザインを描画し、滑らかな3D効果を備えた滑らかなアニメーションでそれらを生き生きとさせることができます。

Zdog

  • 現在のバージョン:1.1.0
  • 人気GitHubのスター
  • 説明:「キャンバスとSVG用のラウンドでフラットなデザイナーフレンドリーな
    疑似3Dエンジン」
  • ライブラリサイズ:28 kB(縮小)
  • GitHubhttps ://github.com/metafizzy/zdog
  • ライセンス

JavaScriptに精通している場合は、Zdogの基本をすぐに学ぶことができます。JavaScriptには、わかりやすい宣言型API、優れたドキュメント、および豊富な学習リソースがあります。SitePointでZdogの紹介をご覧ください。

CSShake

CSShakeは、ボックスに記載されている内容を正確に提供します。これは、Webページ内の要素をシェイクするために特別に設計されたCSSライブラリです。ご想像のとおり、Webコンポーネントを振るにはさまざまなバリエーションがあります。

CSShake

Appleは、ユーザーが誤った応答を入力したときにUI要素(ダイアログ、モーダル、またはテキストボックス)を激しく振るというUIの傾向を普及させました。これは、頭を振る人を模倣したものです。CSShakeは、さまざまな興味深い「シェイク」アニメーションを提供し、このライブラリにはバリエーションが不足していません。

 

Hover.css

Hover.cssは、Webサイトのボタンやその他のUI要素で使用するために設計されたCSSアニメーションライブラリです。他の多くの巧妙に作成されたアニメーションとともに、それは本当に素晴らしい2Dトランジションを持っています。

Hover.css

  • 現在のバージョン:2.3.2
  • 人気GitHubのスター
  • 説明:「自分の要素に簡単に適用したり、変更したり、インスピレーションを得るために使用したりできます。」
  • ライブラリサイズ:93.0 kB(縮小)
  • GitHubhttps ://github.com/IanLunn/Hover
  • ライセンス:要件に応じて、無料の個人/オープンソースライセンスと有料の商用ライセンス。詳細については、GitHubのライセンスセクションをご覧ください。

Hover.cssは、大きくて複雑なページアニメーションではなく、ボタン、ロゴ、SVGコンポーネント、注目の画像などの個別のページ要素をアニメーション化するのに最適です。間違いなく、その最も注目すべきアニメーション効果は、独特の吹き出しとカールです。

アニス

私たちの最終的なライブラリは、そのユニークなアプローチで興味深いものです。AniJSは、単純な「文のような」構造で要素にアニメーションを追加できるアニメーションライブラリです。次の形式を取ります。

クリックすると、正方形上で、.container -boxにアニメーション化されたウォブルを実行します

<div data-anijs="if: click, do: flipInY, to: .container-box"></div>

JavaScriptにあまり詳しくない場合は、JSで振り付けられた動きに足を踏み入れるのに最適な方法かもしれません。

アニス

  • 作成者ダリエルノエル
  • リリース:2014
  • 現在のバージョン:0.9.3
  • 人気GitHubのスター
  • 説明:「コーディングせずにWebデザインを向上させるためのライブラリ。」
  • ライブラリサイズ:10.5 kB
  • GitHubhttps ://github.com/anijs/anijs
  • ライセンス

AniJSは、機能を考慮した非常に妥当なサイズのライブラリです。実装に使用する形式は非常に独創的で、他のアニメーションライブラリ(他の多くの人が型にはまらないと感じるかもしれません)と比較して異なります。

それでも、このライブラリは、プロジェクトで少なくとも1回は試してみる価値があります。

 

どのライブラリを選択する必要がありますか?

プロジェクトに実装される準備ができて待機している多くのアニメーションライブラリがあります。上記にリストされているものは、洗練と安定性の最良の組み合わせを備えたいくつかです。

実装が簡単で、十分にテストされたCSSソリューションを探している場合、Animate.cssは、おそらく最も用途の広い「バングフォーバック」オプションです。

オンラインゲーム、シミュレーター、モデル、およびその他の高度なアプリケーションを強化するための、より完全で強力なJavaScriptベースを探している場合、GreenSockAnimeJSを分割するのは非常に困難です。

アートスタイルが強力なベクターベースであり、Lottie対応のアニメーションツールを使用している場合、Lottieのスムーズな動きと効率は無視できません。

Webアプリケーションでアニメーションライブラリを使用すると、対話性を確実に向上させることができますが、それをやりすぎると、目的が損なわれ、ユーザーを混乱させることがよくあります。注意して、アニメーションを慎重に使用してください。

プロジェクトにアニメーションライブラリを使用していますか?お気に入りのアニメーションライブラリは何ですか?

 このストーリーは、もともとhttps://www.sitepoint.com/our-top-9-animation-libraries/で公開されました 

 #animation #library #anijs 

UIデザイナーのための9つの最高のJavaScriptとCSSアニメーションライブラリ
Sheldon  Grant

Sheldon Grant

1654853760

Node.js interface to The Native Liblzma Compression Library

lzma-native   

Node.js interface to the native liblzma compression library (.xz file format, among others)

This package provides interfaces for compression and decompression of .xz (and legacy .lzma) files, both stream-based and string-based.

Example usage

Installation

Simply install lzma-native via npm:

$ npm install --save lzma-native

Note: As of version 1.0.0, this module provides pre-built binaries for multiple Node.js versions and all major OS using node-pre-gyp, so for 99 % of users no compiler toolchain is necessary. Please create an issue here if you have any trouble installing this module.

Note: lzma-native@2.x requires a Node version >= 4. If you want to support Node 0.10 or 0.12, you can feel free to use lzma-native@1.x.

For streams

If you don’t have any fancy requirements, using this library is quite simple: 

var lzma = require('lzma-native');

var compressor = lzma.createCompressor();
var input = fs.createReadStream('README.md');
var output = fs.createWriteStream('README.md.xz');

input.pipe(compressor).pipe(output);

For decompression, you can simply use lzma.createDecompressor().

Both functions return a stream where you can pipe your input in and read your (de)compressed output from.

For simple strings/Buffers

If you want your input/output to be Buffers (strings will be accepted as input), this even gets a little simpler:

lzma.compress('Banana', function(result) {
    console.log(result); // <Buffer fd 37 7a 58 5a 00 00 01 69 22 de 36 02 00 21 ...>
});

Again, replace lzma.compress with lzma.decompress and you’ll get the inverse transformation.

lzma.compress() and lzma.decompress() will return promises and you don’t need to provide any kind of callback (Example code).

API

Compatibility implementations

Apart from the API described here, lzma-native implements the APIs of the following other LZMA libraries so you can use it nearly as a drop-in replacement:

  • node-xz via lzma.Compressor and lzma.Decompressor
  • LZMA-JS via lzma.LZMA().compress and lzma.LZMA().decompress, though without actual support for progress functions and returning Buffer objects instead of integer arrays. (This produces output in the .lzma file format, not the .xz format!)

Multi-threaded encoding

Since version 1.5.0, lzma-native supports liblzma’s built-in multi-threading encoding capabilities. To make use of them, set the threads option to an integer value: lzma.createCompressor({ threads: n });. You can use value of 0 to use the number of processor cores. This option is only available for the easyEncoder (the default) and streamEncoder encoders.

Note that, by default, encoding will take place in Node’s libuv thread pool regardless of this option, and setting it when multiple encoders are running is likely to affect performance negatively.

Reference

Encoding strings and Buffer objects

Creating streams for encoding

.xz file metadata

Miscellaneous functions

Encoding strings and Buffer objects

lzma.compress(), lzma.decompress()

  • lzma.compress(string, [opt, ]on_finish)
  • lzma.decompress(string, [opt, ]on_finish)
ParamTypeDescription
stringBuffer / StringAny string or buffer to be (de)compressed (that can be passed to stream.end(…))
[opt]Options / intOptional. See options
on_finishCallbackWill be invoked with the resulting Buffer as the first parameter when encoding is finished, and as on_finish(null, err) in case of an error.

These methods will also return a promise that you can use directly.

Example code:

lzma.compress('Bananas', 6, function(result) {
    lzma.decompress(result, function(decompressedResult) {
        assert.equal(decompressedResult.toString(), 'Bananas');
    });
});

Example code for promises:

lzma.compress('Bananas', 6).then(function(result) {
    return lzma.decompress(result);
}).then(function(decompressedResult) {
    assert.equal(decompressedResult.toString(), 'Bananas');
}).catch(function(err) {
    // ...
});

lzma.LZMA().compress(), lzma.LZMA().decompress()

  • lzma.LZMA().compress(string, mode, on_finish[, on_progress])
  • lzma.LZMA().decompress(string, on_finish[, on_progress])

(Compatibility; See LZMA-JS for the original specs.)

Note that the result of compression is in the older LZMA1 format (.lzma files). This is different from the more universally used LZMA2 format (.xz files) and you will have to take care of possible compatibility issues with systems expecting .xz files.

ParamTypeDescription
stringBuffer / String / ArrayAny string, buffer, or array of integers or typed integers (e.g. Uint8Array)
modeintA number between 0 and 9, indicating compression level
on_finishCallbackWill be invoked with the resulting Buffer as the first parameter when encoding is finished, and as on_finish(null, err) in case of an error.
on_progressCallbackIndicates progress by passing a number in [0.0, 1.0]. Currently, this package only invokes the callback with 0.0 and 1.0.

These methods will also return a promise that you can use directly.

This does not work exactly as described in the original LZMA-JS specification:

  • The results are Buffer objects, not integer arrays. This just makes a lot more sense in a Node.js environment.
  • on_progress is currently only called with 0.0 and 1.0.

Example code:

lzma.LZMA().compress('Bananas', 4, function(result) {
    lzma.LZMA().decompress(result, function(decompressedResult) {
        assert.equal(decompressedResult.toString(), 'Bananas');
    });
});

For an example using promises, see compress().

Creating streams for encoding

lzma.createCompressor(), lzma.createDecompressor()

  • lzma.createCompressor([options])
  • lzma.createDecompressor([options])
ParamTypeDescription
[options]Options / intOptional. See options

Return a duplex stream, i.e. a both readable and writable stream. Input will be read, (de)compressed and written out. You can use this to pipe input through this stream, i.e. to mimick the xz command line util, you can write:

var compressor = lzma.createCompressor();

process.stdin.pipe(compressor).pipe(process.stdout);

The output of compression will be in LZMA2 format (.xz files), while decompression will accept either format via automatic detection.

lzma.Compressor(), lzma.Decompressor()

  • lzma.Compressor([preset], [options])
  • lzma.Decompressor([options])

(Compatibility; See node-xz for the original specs.)

These methods handle the .xz file format.

ParamTypeDescription
[preset]intOptional. See options.preset
[options]OptionsOptional. See options

Return a duplex stream, i.e. a both readable and writable stream. Input will be read, (de)compressed and written out. You can use this to pipe input through this stream, i.e. to mimick the xz command line util, you can write:

var compressor = lzma.Compressor();

process.stdin.pipe(compressor).pipe(process.stdout);

lzma.createStream()

  • lzma.createStream(coder, options)
ParamTypeDescription
[coder]stringAny of the supported coder names, e.g. "easyEncoder" (default) or "autoDecoder".
[options]Options / intOptional. See options

Return a duplex stream for (de-)compression. You can use this to pipe input through this stream.

The available coders are (the most interesting ones first):

Less likely to be of interest to you, but also available:

  • aloneDecoder Decoder which only uses the legacy .lzma format. Supports the options.memlimit option.
  • rawEncoder Custom encoder corresponding to lzma_raw_encoder (See the native library docs for details). Supports the options.filters option.
  • rawDecoder Custom decoder corresponding to lzma_raw_decoder (See the native library docs for details). Supports the options.filters option.
  • streamEncoder Custom encoder corresponding to lzma_stream_encoder (See the native library docs for details). Supports options.filters and options.check options.
  • streamDecoder Custom decoder corresponding to lzma_stream_decoder (See the native library docs for details). Supports options.memlimit and options.flags options.

Options

Option nameTypeDescription
checkcheckAny of lzma.CHECK_CRC32, lzma.CHECK_CRC64, lzma.CHECK_NONE, lzma.CHECK_SHA256
memlimitfloatA memory limit for (de-)compression in bytes
presetintA number from 0 to 9, 0 being the fastest and weakest compression, 9 the slowest and highest compression level. (Please also see the [xz(1) manpage][xz-manpage] for notes – don’t just blindly use 9!) You can also OR this with lzma.PRESET_EXTREME (the -e option to the xz command line utility).
flagsintA bitwise or of lzma.LZMA_TELL_NO_CHECK, lzma.LZMA_TELL_UNSUPPORTED_CHECK, lzma.LZMA_TELL_ANY_CHECK, lzma.LZMA_CONCATENATED
synchronousboolIf true, forces synchronous coding (i.e. no usage of threading)
bufsizeintThe default size for allocated buffers
threadsintSet to an integer to use liblzma’s multi-threading support. 0 will choose the number of CPU cores.
blockSizeintMaximum uncompressed size of a block in multi-threading mode
timeoutintTimeout for a single encoding operation in multi-threading mode

options.filters can, if the coder supports it, be an array of filter objects, each with the following properties:

  • .id Any of lzma.FILTERS_MAX, lzma.FILTER_ARM, lzma.FILTER_ARMTHUMB, lzma.FILTER_IA64, lzma.FILTER_POWERPC, lzma.FILTER_SPARC, lzma.FILTER_X86 or lzma.FILTER_DELTA, lzma.FILTER_LZMA1, lzma.FILTER_LZMA2

The delta filter supports the additional option .dist for a distance between bytes (see the xz(1) manpage).

The LZMA filter supports the additional options .dict_size, .lp, .lc, pb, .mode, nice_len, .mf, .depth and .preset. See the xz(1) manpage for meaning of these parameters and additional information.

Miscellaneous functions

lzma.crc32()

  • lzma.crc32(input[, encoding[, previous]])

Compute the CRC32 checksum of a Buffer or string.

ParamTypeDescription
inputstring / BufferAny string or Buffer.
[encoding]stringOptional. If input is a string, an encoding to use when converting into binary.
[previous]intThe result of a previous CRC32 calculation so that you can compute the checksum per each chunk

Example usage:

lzma.crc32('Banana') // => 69690105

lzma.checkSize()

  • lzma.checkSize(check)

Return the byte size of a check sum.

ParamTypeDescription
checkcheckAny supported check constant.

Example usage:

lzma.checkSize(lzma.CHECK_SHA256) // => 16
lzma.checkSize(lzma.CHECK_CRC32)  // => 4

lzma.easyDecoderMemusage()

  • lzma.easyDecoderMemusage(preset)

Returns the approximate memory usage when decoding using easyDecoder for a given preset.

ParamTypeDescription
presetpresetA compression level from 0 to 9

Example usage:

lzma.easyDecoderMemusage(6) // => 8454192

lzma.easyEncoderMemusage()

  • lzma.easyEncoderMemusage(preset)

Returns the approximate memory usage when encoding using easyEncoder for a given preset.

ParamTypeDescription
presetpresetA compression level from 0 to 9

Example usage:

lzma.easyEncoderMemusage(6) // => 97620499

lzma.rawDecoderMemusage()

  • lzma.rawDecoderMemusage(filters)

Returns the approximate memory usage when decoding using rawDecoder for a given filter list.

ParamTypeDescription
filtersarrayAn array of filters

 

lzma.rawEncoderMemusage()

  • lzma.rawEncoderMemusage(filters)

Returns the approximate memory usage when encoding using rawEncoder for a given filter list.

ParamTypeDescription
filtersarrayAn array of filters

 

lzma.versionString()

  • lzma.versionString()

Returns the version of the underlying C library.

Example usage:

lzma.versionString() // => '5.2.3'

lzma.versionNumber()

  • lzma.versionNumber()

Returns the version of the underlying C library.

Example usage:

lzma.versionNumber() // => 50020012

.xz file metadata

lzma.isXZ()

  • lzma.isXZ(input)

Tells whether an input buffer is an XZ file (.xz, LZMA2 format) using the file format’s magic number. This is not a complete test, i.e. the data following the file header may still be invalid in some way.

ParamTypeDescription
inputstring / BufferAny string or Buffer (integer arrays accepted).

Example usage:

lzma.isXZ(fs.readFileSync('test/hamlet.txt.xz')); // => true
lzma.isXZ(fs.readFileSync('test/hamlet.txt.lzma')); // => false
lzma.isXZ('Banana'); // => false

(The magic number of XZ files is hex fd 37 7a 58 5a 00 at position 0.)

lzma.parseFileIndex()

  • lzma.parseFileIndex(options[, callback])

Read .xz file metadata.

options.fileSize needs to be an integer indicating the size of the file being inspected, e.g. obtained by fs.stat().

options.read(count, offset, cb) must be a function that reads count bytes from the underlying file, starting at position offset. If that is not possible, e.g. because the file does not have enough bytes, the file should be considered corrupt. On success, cb should be called with a Buffer containing the read data. cb can be invoked as cb(err, buffer), in which case err will be passed along to the original callback argument when set.

callback will be called with err and info as its arguments.

If no callback is provided, options.read() must work synchronously and the file info will be returned from lzma.parseFileIndex().

Example usage:

fs.readFile('test/hamlet.txt.xz', function(err, content) {
  // handle error

  lzma.parseFileIndex({
    fileSize: content.length,
    read: function(count, offset, cb) {
      cb(content.slice(offset, offset + count));
    }
  }, function(err, info) {
    // handle error
    
    // do something with e.g. info.uncompressedSize
  });
});

lzma.parseFileIndexFD()

  • lzma.parseFileIndexFD(fd, callback)

Read .xz metadata from a file descriptor.

This is like parseFileIndex(), but lets you pass an file descriptor in fd. The file will be inspected using fs.stat() and fs.read(). The file descriptor will not be opened or closed by this call.

Example usage:

fs.open('test/hamlet.txt.xz', 'r', function(err, fd) {
  // handle error

  lzma.parseFileIndexFD(fd, function(err, info) {
    // handle error
    
    // do something with e.g. info.uncompressedSize
    
    fs.close(fd, function(err) { /* handle error */ });
  });
});

Installation

This package includes the native C library, so there is no need to install it separately.

Related projects

Other implementations of the LZMA algorithms for node.js and/or web clients include:

Note that LZMA has been designed to have much faster decompression than compression, which is something you may want to take into account when choosing an compression algorithm for large files. Almost always, LZMA achieves higher compression ratios than other algorithms, though.

Acknowledgements

Initial development of this project was financially supported by Tradity.

Author: Addaleax
Source Code: https://github.com/addaleax/lzma-native 
License: MIT license

#node #nodejs #library #javascript 

Node.js interface to The Native Liblzma Compression Library
Lawson  Wehner

Lawson Wehner

1654508220

Mcauthlib: Minecraft Authentication Library Made with Dart

Mojang's Yggdrasil authentication for Dart.

Getting started

Add this as dependency in your pubspec.yaml

...

dependencies:
  mcauthlib: (version goes here)
  
...

Use this package as a library

Depend on it

Run this command:

With Dart:

 $ dart pub add mcauthlib

With Flutter:

 $ flutter pub add mcauthlib

This will add a line like this to your package's pubspec.yaml (and run an implicit dart pub get):

dependencies:
  mcauthlib: ^1.0.0

Alternatively, your editor might support dart pub get or flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:mcauthlib/mcauthlib.dart';

example/mcauthlib_example.dart

import 'package:mcauthlib/mcauthlib.dart';

void main() async {
  //This example is how to authenticate with this library.

  //First create MojangAuth instance.
  final auth = MojangAuth();

  //Then, create User with authtype keyword.
  //The first parameter is email and the second one is password.
  var user = User.authType("lorem@ipsum.com", "dolorsitamet");

  //await until authentication return map with
  //Response type, clientToken, accessToken, player uuid.
  var result = await auth.authenticate(user);

  //If a request was successful the response type should be
  //ResponseType.success
  //if not, it will return ResponseType.failure with error Type.
  if(result['responseType'] == ResponseType.success){
    user.clientToken = result['clientToken'];
    user.accessToken = result['accessToken'];
  }
}

Usage

here

Features

https://wiki.vg/Authentication

Author: GiftShower
Source Code: https://github.com/GiftShower/mcauthlib 
License: GPL-3.0 license

#flutter #dart #library 

Mcauthlib: Minecraft Authentication Library Made with Dart
Lawson  Wehner

Lawson Wehner

1654459020

Console_bars: A Dart Library to Create Progress Bars in Console

A package for creating an awesome progress bar in the terminal. Handy while developing a CLI or a desktop utility in dart.

Usage

Options:

  • total : Total number of steps
  • desc : Simple text shown before the bar (optional)
  • space : Character denoting empty space (default : '.')
  • fill : Character denoting filled space (default : '█')
  • time : Toggle timing mode (default : false)
  • percentage : Toggle percentage display (default : false)
  • scale : Scale of the bar relative to width (between: 0 and 1, default: 0.5, Irrelavant if width is specified)
  • width : Width of the bar (If not specified, it will be automatically calculated using the terminal width and scale)

Code:

final p = FillingBar(desc: "Loading", total: 1000, time: true, percentage:true);
  for (var i = 0; i < 1000; i++) {
    p.increment();
    sleep(Duration(milliseconds: 10));
  }

Result:

Animation

Loading : ████████████████████████████████████████.................... 673/1000 67.3% [ 0:00:13.28 / 0:00:06.45 ]

Use this package as a library

Depend on it

Run this command:

With Dart:

 $ dart pub add console_bars

With Flutter:

 $ flutter pub add console_bars

This will add a line like this to your package's pubspec.yaml (and run an implicit dart pub get):

dependencies:
  console_bars: ^1.0.4

Alternatively, your editor might support dart pub get or flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:console_bars/console_bars.dart';

example/console_bars_example.dart

import 'dart:io';

import 'package:console_bars/console_bars.dart';

void main(List<String> args) {
  // A bar that looks like
  //
  // Loading : ████████████████████████████████████████.................... 673/1000 67.3% [ 0:00:13.28 / 0:00:06.45 ]
  //
  final p = FillingBar(
      desc: "Loading", total: 1000, time: true, percentage: true, scale: 0.2);
  for (var i = 0; i < 1000; i++) {
    p.increment();
    sleep(Duration(milliseconds: 10));
  }
  print("\nDone");
}

See in pub.dev

Author: RohitEdathil
Source Code: https://github.com/RohitEdathil/ConsoleBars 
License: GPL-3.0 license

#flutter #dart #library 

Console_bars: A Dart Library to Create Progress Bars in Console
Lawson  Wehner

Lawson Wehner

1654406640

Majority Judgment for Dart

Majority Judgment for Dart     

This Dart package helps to resolve polls using Majority Judgment.

Features

  • Efficient Majority Judgment algorithm, scales well to billions of participants
  • Configure whether to favor adhesion or contestation (default)
  • Balance proposal tallies using a static default grade or the median grade1
  • Room for Central Judgment and Usual Judgment
  • Unit-tested (run dart test)

Get started


import 'package:majority_judgment/majority_judgment.dart';

void main() {
    
      final pollTally = PollTally([
        [1, 2, 4, 2, 1], // Proposal A, from "worst" grade to "best" grade
        [1, 2, 4, 1, 2], // Proposal B
        [3, 1, 3, 1, 2], // Proposal C
        [1, 2, 4, 2, 1], // Proposal D (equal to A)
      ]);
      final mj = MajorityJudgmentResolver();
      final result = mj.resolve(pollTally);

      print(result.proposalsResults.map((ProposalResult p) => p.rank));
      //> (2, 1, 4, 2)

      print(result.sortedProposalsResults.map((ProposalResult p) => p.index));
      //> (1, 0, 3, 2)
    
}

Use this package as a library

Depend on it

Run this command:

With Dart:

 $ dart pub add majority_judgment

With Flutter:

 $ flutter pub add majority_judgment

This will add a line like this to your package's pubspec.yaml (and run an implicit dart pub get):

dependencies:
  majority_judgment: ^0.2.0

Alternatively, your editor might support dart pub get or flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:majority_judgment/majority_judgment.dart';

example/example.dart

// ignore_for_file: avoid_print

import 'package:majority_judgment/majority_judgment.dart';

void main() {
  final pollTally = PollTally([
    [1, 2, 4, 2, 1], // Proposal A, from "worst" grade to "best" grade
    [1, 2, 4, 1, 2], // Proposal B
    [3, 1, 3, 1, 2], // Proposal C
    [1, 2, 4, 2, 1], // Proposal D (equal to A)
  ]);
  //pollTally.balanceWithStaticDefault(); // use a balancer if necessary
  final mj = MajorityJudgmentResolver();
  final result = mj.resolve(pollTally);

  print(result.proposalsResults.map((ProposalResult p) => p.rank));
  //> (2, 1, 4, 2)

  print(result.sortedProposalsResults.map((ProposalResult p) => p.index));
  //> (1, 0, 3, 2)
}

Contribute

Usual git flow: clone, tinker, request a merge.

Author: MieuxVoter
Source Code: https://github.com/MieuxVoter/majority-judgment-library-dart 
License: MIT license

#flutter #dart #library 

Majority Judgment for Dart
Nigel  Uys

Nigel Uys

1654347180

Bellt: A Simple Go Router

Bellt

Simple Golang HTTP router

Bellt Package implements a request router with the aim of managing controller actions based on fixed and parameterized routes.

The project so far has the following functionalities:

  • Standard definition of route "/ health", in order to prepare the service developed with bellt to act as microservice.
  • Providing the creation of parameterized routes, simple or segmented (groups).
  • All requests can be made through fixed patterns, querystrings and parameters.
  • Obtaining the requisition parameters in the controller functions.

Install

To get Bellt

> Go CLI

go get -u github.com/GuilhermeCaruso/bellt

> Go DEP

dep ensure -add github.com/GuilhermeCaruso/bellt

> Govendor

govendor fetch github.com/GuilhermeCaruso/bellt

Guide

Router

To initialize our router

var router = bellt.NewRouter()
package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/GuilhermeCaruso/bellt"
)

func main() {
    router := bellt.NewRouter()

    log.Fatal(http.ListenAndServe(":8080", nil))
}

HandleFunc

HandleFunc function responsible for initializing a common route or built through the Router. All non-grouped routes must be initialized by this method.

/*
    [path] - Endpoint string
    [handlerFunc] - Function that will be called on the request
    [methods] - Slice for endpoint methods ("GET", "POST", "PUT", "DELETE")
*/

router.HandleFunc(path, handlerFunc, methods)
    
package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/GuilhermeCaruso/bellt"
)

func main() {
    router := bellt.NewRouter()

    router.HandleFunc("/bellt", belltHandler, "GET")

    log.Fatal(http.ListenAndServe(":8080", nil))
}

func belltHandle(w http.ResponseWriter, r *http.Request){
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("Simple Golang HTTP router")
}

HandleGroup

HandleGroup is responsible for creating a group of routes. The main path can be set for all other routes.

/*
    [mainPath] - Main route used in all subr-outes
    
    [subHandleFunc] - SubHandleFunc function responsiblefor initializing a common route or
    built through the Router. All grouped routes must be initialized by this method
*/

router.HandleGroup(mainPath, ...SubHandleFunc)
    

SubHandleFunc

SubHandleFunc is responsible for initializing a common or built route. Its use must be made within the scope of the HandleGroup method, where the main path will be declared.

/*
    [path] - Endpoint string
    [handlerFunc] - Function that will be called on the request
    [methods] - Slice for endpoint methods ("GET", "POST", "PUT", "DELETE")
*/

router.SubHandleFunc(path, handlerFunc, methods)
    
package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/GuilhermeCaruso/bellt"
)

func main() {
    router := bellt.NewRouter()

    router.HandleGroup("/api",
        router.SubHandleFunc("/bellt", belltHandle, "GET"),
        router.SubHandleFunc("/check", checkHandle, "GET"),
    )

    log.Fatal(http.ListenAndServe(":8080", nil))
}

func belltHandle(w http.ResponseWriter, r *http.Request){
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("Simple Golang HTTP router")
}

func checkHandle(w http.ResponseWriter, r *http.Request){
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("Ok!")
}

Middleware

The declaration of middlewares in HandleFunc or SubHandleFunc should be done using the Use method

Use

/*
    handlerFunc - Function that will be called on the request 
    middlewareList - Slice of middleware that will be used in the request (Middleware)
*/
bellt.Use(handlerFunc, ...middlewareList)

The middleware type has a following signature

type Middleware func(http.HandlerFunc) http.HandlerFunc

Applying middlewares to routes

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/GuilhermeCaruso/bellt"
)

func main() {

    router := bellt.NewRouter()

    router.HandleFunc("/hello", bellt.Use(
        exampleHandler,
        middlewareOne,
        middlewareTwo,
    ), "GET")

    router.HandleGroup("/api",
        router.SubHandleFunc("/hello", bellt.Use(
            exampleHandler,
            middlewareOne,
            middlewareTwo,
        ), "GET"),
    )

    log.Fatal(http.ListenAndServe(":8080", nil))
}

func exampleHandler(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
    w.Write([]byte(`Hello Middleware!`))
}

func middlewareOne(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("Step One")
        next.ServeHTTP(w, r)
    }
}

func middlewareTwo(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("Step Two")
        next.ServeHTTP(w, r)
    }
}

Parameterized Routes

Route parameters must be passed using {} as scope limiter

router.HandleFunc("/hello/{name}", handlerFunc, "GET")

router.HandleGroup("/api", 
    SubHandleFunc("/item/{id}", handlerFunc, "GET")
)

Route Variables

RouteVariables used to capture and store parameters passed to built routes.

Need to pass the *Request of the HandlerFunc used in the HandleFunc method.

/*
    r = *Request of the HandlerFunc
*/
rv := bellt.RouteVariables(r)

The declaration must be made within the HandlerFunc

func exampleHandler(w http.ResponseWriter, r *http.Request) {
    rv := bellt.RouteVariables(r)
    /*[...]*/
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("Hello!"))
}

GetVar

GetVar returns the parameter value of the route

/*
    r = *Request of the HandlerFunc
    param = Parameter name string
*/
rv := bellt.RouteVariables(r)

rv.GetVar(param)
func exampleHandler(w http.ResponseWriter, r *http.Request) {
    rv := bellt.RouteVariables(r)
    w.WriteHeader(http.StatusOK)
    w.Write([]byte(fmt.Sprintf(`Hello %v gopher!`, rv.GetVar("color")))))
}

The complete implementation of parameterized routes should look like this:

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/GuilhermeCaruso/bellt"
)

func main() {

    router := bellt.NewRouter()

    router.HandleFunc("/contact/{id}/{user}", exampleHandler, "GET")

    router.HandleGroup("/api",
        router.SubHandleFunc("/check/{id}/{user}", exampleHandler, "GET"),
    )

    log.Fatal(http.ListenAndServe(":8080", nil))
}

func exampleHandler(w http.ResponseWriter, r *http.Request) {
    rv := bellt.RouteVariables(r)

    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    w.Write([]byte(fmt.Sprintf(`{"id": %v, "user": %v}`, rv.GetVar("user"), rv.GetVar("id"))))
}

Full Example

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/GuilhermeCaruso/bellt"
)

func main() {

    router := bellt.NewRouter()

    router.HandleFunc("/contact/{id}/{user}", bellt.Use(
        exampleHandler,
        middlewareOne,
        middlewareTwo,
    ), "GET")

    router.HandleFunc("/contact", bellt.Use(
        exampleNewHandler,
        middlewareOne,
        middlewareTwo,
    ), "GET")

    router.HandleGroup("/api",
        router.SubHandleFunc("/check", bellt.Use(
            exampleNewHandler,
            middlewareOne,
            middlewareTwo,
        ), "GET"),
        router.SubHandleFunc("/check/{id}/{user}", bellt.Use(
            exampleHandler,
            middlewareOne,
            middlewareTwo,
        ), "GET"),
    )

    log.Fatal(http.ListenAndServe(":8080", nil))
}

func exampleHandler(w http.ResponseWriter, r *http.Request) {

    rv := bellt.RouteVariables(r)

    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    w.Write([]byte(fmt.Sprintf(`{"id": %v, "user": %v}`, rv.GetVar("user"), rv.GetVar("id"))))
}

func exampleNewHandler(w http.ResponseWriter, r *http.Request) {
    rv := bellt.RouteVariables(r)

    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    w.Write([]byte(`{"msg": "Works"}`))
}

func middlewareOne(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("Step One")

        next.ServeHTTP(w, r)
    }
}

func middlewareTwo(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("Step Two")

        next.ServeHTTP(w, r)
    }
}

Benchmark

Applying requisition performance tests, the following results were obtained, showing the initial potency of the Bellt package.

Presentation

Guilherme Caruso - Cabify- GolangSP Meetup 2 - 21/03/2019 - São Paulo /Brazil

Slides - Construindo Rotas Parametrizadas em GO

Video - GolangSP Meetup 2

Author: GuilhermeCaruso
Source Code: https://github.com/GuilhermeCaruso/bellt 
License: MIT license

#go #golang #http #library 

Bellt: A Simple Go Router