All Projects → hhvm → Xhp Lib

hhvm / Xhp Lib

Licence: mit
Class libraries for XHP. XHP is a Hack feature that augments the syntax of the language such that XML document fragments become valid Hack expressions.

Programming Languages

hack
652 projects

Labels

Projects that are alternatives of or similar to Xhp Lib

Network Avatar Picker
A npm module that returns user's social network avatar. Supported providers: facebook, instagram, twitter, tumblr, vimeo, github, youtube and gmail
Stars: ✭ 74 (-94.29%)
Mutual labels:  facebook
Laravel Facebook Ads
Facebook & Instagram Ads API for Laravel
Stars: ✭ 87 (-93.29%)
Mutual labels:  facebook
Facebook Timeline Compose Android
Facebook Timeline UI with Pure Kotlin Jetpack Compose
Stars: ✭ 90 (-93.06%)
Mutual labels:  facebook
Spam Bot 3000
Social media research and promotion, semi-autonomous CLI bot
Stars: ✭ 79 (-93.91%)
Mutual labels:  facebook
Svelte Social Auth
Social Auth for Svelte v3
Stars: ✭ 86 (-93.37%)
Mutual labels:  facebook
Androidoauth
A simple way to authenticate with Google and Facebook using OAuth 2.0 in Android
Stars: ✭ 88 (-93.22%)
Mutual labels:  facebook
Facebook Data Analyzer
📊Python script to analyze the contents of your Facebook data export
Stars: ✭ 71 (-94.53%)
Mutual labels:  facebook
Docker Multistreamer
Dockerized multistreamer
Stars: ✭ 90 (-93.06%)
Mutual labels:  facebook
Fnreactionsview
FNReactionsView is a customizable control (based on UIView) to give people a way to show floating emoji like facebook does during live stream, easy way.
Stars: ✭ 87 (-93.29%)
Mutual labels:  facebook
React Share Button
📱 React share button component with web-share api and fallback modal with native intent urls
Stars: ✭ 89 (-93.14%)
Mutual labels:  facebook
Facebook Tunnel
Tunneling Internet traffic over Facebook chat.
Stars: ✭ 1,234 (-4.86%)
Mutual labels:  facebook
Social Login Helper Deprecated
A simple android library to easily implement social login into your android project
Stars: ✭ 81 (-93.75%)
Mutual labels:  facebook
Facebookclientplugin
Facebook Client Plugin for Xamarin iOS and Android
Stars: ✭ 89 (-93.14%)
Mutual labels:  facebook
Facegrab
A tool to collect public images from Facebook and create an image dataset for training computer vision applications like gender recognition, and face detection
Stars: ✭ 76 (-94.14%)
Mutual labels:  facebook
Daily Coding Problem
Series of the problem 💯 and solution ✅ asked by Daily Coding problem👨‍🎓 website.
Stars: ✭ 90 (-93.06%)
Mutual labels:  facebook
Skraper
Kotlin/Java library and cli tool for scraping posts and media from various sources with neither authorization nor full page rendering (Facebook, Instagram, Twitter, Youtube, Tiktok, Telegram, Twitch, Reddit, 9GAG, Pinterest, Flickr, Tumblr, IFunny, VK, Pikabu)
Stars: ✭ 72 (-94.45%)
Mutual labels:  facebook
Devil
Devil is a tool that is basically made for facebook to Hack target accounts , BruteForce Attack , grab friendlist accounts , yahoo chacker , Facbook Friend information gathering tool , auto likes reactions & much more i hope you enjoy this tool i'm not responsible if you use this tool for any illegal purpose
Stars: ✭ 88 (-93.22%)
Mutual labels:  facebook
Easylogin
Login effortlessly with different social networks like Facebook, Twitter or Google Plus
Stars: ✭ 90 (-93.06%)
Mutual labels:  facebook
Django Graphql Social Auth
Python Social Auth support for Graphene Django
Stars: ✭ 90 (-93.06%)
Mutual labels:  facebook
Fb Android Crash
How to crash the integrated browser in FB for Android? Let's open that URL!
Stars: ✭ 89 (-93.14%)
Mutual labels:  facebook

XHP Logo

Build Status

Introduction

XHP augments the syntax of Hack such that XML document fragments become valid Hack expressions. This allows you to use Hack as a stricter templating engine and offers much more straightforward implementation of reusable components.

If you want a high-level XHP UI library, you might want to take a look at https://github.com/hhvm/xhp-bootstrap/

Announcements and articles are posted to the XHP-Lib blog

Installation

Composer is the recommended installation method. To add XHP to your project, run the following command :

$ composer require facebook/xhp-lib:^3.0

Simple Example

$href = 'http://www.facebook.com';
$link = <a href={$href}>Facebook</a>;

Take note of the syntax on line 4, this is not a string. This is the major new syntax that XHP introduces to Hack.

Anything that's in {}'s is interpreted as a full Hack expression. This differs from {}'s in double-quoted strings; double-quoted strings can only contain variables.

You can define arbitrary elements that can be instantiated in Hack. Under the covers each element you create is an instance of a class. To define new elements you just define a new class. XHP comes with a set of predefined elements which implement most of HTML for you.

Complex Structures

Note that XHP structures can be arbitrarily complex. This is a valid XHP program:

$post =
  <div class="post">
    <h2>{$post}</h2>
    <p><span>Hey there.</span></p>
    <a href={$like_link}>Like</a>
  </div>;

One advantage that XHP has over string construction is that it enforces correct markup structure at compile time. That is, the expression $foo = <h1>Header</h2>; is not a valid expression, because you can not close an h1 tag with a /h2. When building large chunks of markup it can be difficult to be totally correct. With XHP the compiler now checks your work and will refuse to run until the markup is correct.

Dynamic Structures

Sometimes it may be useful to create a bunch of elements and dynamically add them as children to an element. All XHP objects support the appendChild method which behaves similarly to the same Javascript method. For example:

$list = <ul />;
$items = ...;

foreach ($items as $item) {
  $list->appendChild(<li>{$item}</li>);
}

In the code, <ul /> creates a ul with no children. Then we dynamically append children to it for each item in the $items list.

Escaping

An interesting feature of XHP is the idea of automatic escaping. If you want to render input from the user without using XHP, you must manually escape it. This practice is error-prone and has been proven over time to be an untenable solution. It increases code complexity and still leads to security vulnerabilities by careless programming. However, since XHP has context-specific about the page structure it can automatically escape data. The following two examples are identical, and both are "safe".

$hello = '<div>Hello '.htmlspecialchars($name).'</div>';
$hello = <div>Hello {$name}</div>;

As you can see, using XHP makes safety the default rather than the exception.

Defining Elements

All elements in XHP are just Hack classes. Even the basic HTML elements like div and span are classes. You define an element just like you do a class, except you use a leading colon to specify that you're creating an XHP element:

class :fb:thing extends :x:element {
  ...
}

After we define fb:thing we can instantiate it with the expression <fb:thing />. ❌element is the core XHP class you should subclass from when defining an element. It will provide you all the methods you need like appendChild, and so on. As an ❌element you must define only render(). render() should always return more XHP elements. It's important to remember this rule: even elements you define yourself will return XHP elements. The only XHP elements that are allowed to return a string are elements which subclass from ❌primitive. The only elements which should subclass ❌primitive are base elements that make HTML building blocks. XHP with the core HTML library is a viable replacement for strings of markup.

You can also use the leading-colon syntax to use an XHP element where you would normally use a class name, for instance while referencing class constants or typehinting:

$constant = :fb:thing::someConstant;
function giveMeAThing(:fb:thing $thing) {
}

Defining Attributes

Most elements will take some number of attributes which affect its behavior. You define attributes in an element with the attribute keyword.

class :fb:thing extends :x:element {
  attribute
    string title = "No Title",
    enum { "cool", "lame" } type;
}

Here we define two attributes, title and type. title is of type string and the default value is "No Title". type is of type enum and has two valid values -- "cool" and "lame". Valid types are bool, int, array, string, and var. You can also specify a class or element name as a type. Finally, you can put @required after the name to specify that this attribute is required for the element to render.

Note that when you extend another element you will always inherit its attributes. However, any attributes you specify with the same name will override your parent's attributes.

You can also steal another element's attributes by specifying only a tag name in a definition. The declaration attribute :div says that this element may accept any attribute that a div element could accept.

Defining Element Structure

All elements have some kind of structure that they must follow. For instance, in HTML5 it is illegal for an <input /> to appear directly inside of a <body /> tag (it must be inside a form). XHP allows you to define a content model which documents must adhere to. This is done with the children keyword, which uses a syntax similar to regular expressions. Note, that unlike attribute, children may only appear once inside any class.

class :fb:thing_container extends :x:element {
  children (:fb:thing1 | :fb:thing2)*;
}

A children declaration supports the following postfix operators:

  • ? : Zero or one instance
  • * : Zero or more instances
  • + : One or more instances

If no operator is specified then the declaration must be matched exactly one time. You may also use the , or | operator to combine multiple declarations into one. The , operator specifies a list of declarations that must appear in order, and a | specifies a list of declarations, of which one must match. For instance if you are defining a page layout your children declaration may look like:

  children (:fb:left_column?, :fb:content, :fb:right_column?);

This specifies an optional left column followed by a required content and an optional right column.

You can also use the special declarations any or empty to specify that your element can accept any elements, or no elements. If you don't specify a children declaration your parent class's declaration will be inherited. ❌element's children declaration is children any;.

Note: The algorithm which checks adherence to a children declaration is greedy with no backtracking. For most children declarations this will make no difference, but if you're defining a complex children declaration, you should know how it works. Basically, this declaration is impossible to satisfy: children (:fb:thing*, :fb:thing);. The * postfix operator is greedy and will capture all fb:thing's. After that it's impossible to match another fb:thing.

Element Categories

A lot of times you may want to accept all children of a particular group, but enumerating the group starts to become unsustainable. When this happens you can define an element group and specify in your child declaration that your element is a member. Then you can reference that group in a children declaration using the % prefix.

class :fb:thing1 extends :x:element {
  category %fb:thing;
}

class :fb:thing2 extends :x:element {
  category %fb:thing;
}

class :fb:thing_container extends :x:element {
  children (%fb:thing)*;
}

Asynchronous data fetching

XHP supports Hack's 'async' functionality, allowing you to build components that efficiently fetch the data that they require:

class :async-thing extends :x:element {
  protected async function renderAsync(): Awaitable<XHPRoot> {
    $db = await AsyncMysqlClient::connect(...);
    $result = await $db->queryf(
      'SELECT id2 FROM %T WHERE id1 %=d',
      'friends',
      $this->getContext('viewer')->getUserID(),
    );

    $rows = $result->mapRowsTyped();
    $friend_ids = $rows->map($row ==> $row['id2']);
    $friend_data = await HH\Asio\mm(
      $friend_ids,
      $id ==> User::get($id),
    );

    $out = <ul />;
    foreach ($friend_ids as $id) {
      $out->appendChild(<li>.... </li>);
    }

    return $out;
  }
}

When an XHP tree is rendered, asyncRender() is called for all XHPAsync children, and data fetching happens in parallel. This allows the data dependencies of your components to efficiently be an implementation detail instead of having to have it as part of the API and passed by the user (eg in an attribute).

Whitespace

In XHP, text nodes that contain only whitespace are removed. The expressions <div> </div> and <div /> are identical. Text nodes that contain non-whitespace are trimmed on the left and right to at most 1 space. This is worth noting because you may want to do something like:

$node = <div><label>Title:</label> <span>{$title}</span></div>;

This will lead to non-desirable results as the space between the : and $title will be lost. In order to fix this try moving the space into the <label /> tag. If you can't do this then just use {' '} which will not be stripped.

Best Practices

There are certain conventions that you should comply with while using XHP.

  • Don't pollute the global XHP namespace with namespace-less elements. Most elements you define should use some namespace. Elements that use no namespace should not be "magic" at all. For instance,
class :fb:thing extends :x:element {
  protected async function renderAsync(): Awaitable<XHPRoot> {
    return <div class="thing">thing</div>;
  }
}

This element would be considered magic because when you print an <fb:thing /> it actually returns a div.

External Resources

Below are a list of external resources about XHP:

  • Code Before the Horse - Basic XHP introduction, examples, and lessons learned from Facebook written by one of their UI Engineers.

License

This software is MIT-licensed.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].