Git Product home page Git Product logo

essence's Introduction

Essence

Build status Scrutinizer Code Quality Code Coverage Total downloads

Essence is a simple PHP library to extract media information from websites, like youtube videos, twitter statuses or blog articles.

If you were already using Essence 2.x.x, you should take a look at the migration guide.

Installation

composer require essence/essence

Example

Essence is designed to be really easy to use. Using the main class of the library, you can retrieve information in just those few lines:

$Essence = new Essence\Essence();
$Media = $Essence->extract('http://www.youtube.com/watch?v=39e3KYAmXK4');

if ($Media) {
	// That's all, you're good to go !
}

Then, just do anything you want with the data:

<article>
	<header>
		<h1><?php echo $Media->title; ?></h1>
		<p>By <?php echo $Media->authorName; ?></p>
	</header>

	<div class="player">
		<?php echo $Media->html; ?>
	</div>
</article>

What you get

Using Essence, you will mainly interact with Media objects. Media is a simple container for all the information that are fetched from an URL.

Here are the default properties it provides:

  • type
  • version
  • url
  • title
  • description
  • authorName
  • authorUrl
  • providerName
  • providerUrl
  • cacheAge
  • thumbnailUrl
  • thumbnailWidth
  • thumbnailHeight
  • html
  • width
  • height

These properties were gathered from the OEmbed and OpenGraph specifications, and merged together in a united interface. Based on such standards, these properties should be a solid starting point.

However, "non-standard" properties can and will also be setted.

Here is how you can manipulate the Media properties:

// through dedicated methods
if (!$Media->has('foo')) {
	$Media->set('foo', 'bar');
}

$value = $Media->get('foo');

// or directly like a class attribute
$Media->customValue = 12;

Note that Essence will always try to fill the html property when it is not available.

Advanced usage

The Essence class provides some useful utility functions to ensure you will get some information.

Extracting URLs

The crawl() and crawlUrl() methods let you crawl extractable URLs from a web page, either directly from its source, or from its URL (in which case Essence will take care of fetching the source).

For example, here is how you could get the URL of all videos in a blog post:

$urls = $Essence->crawlUrl('http://www.blog.com/article');
array(2) {
	[0] => 'http://www.youtube.com/watch?v=123456',
	[1] => 'http://www.dailymotion.com/video/a1b2c_lolcat-fun'
}

You can then get information from all the extracted URLs:

$medias = $Essence->extractAll($urls);
array(2) {
	['http://www.youtube.com/watch?v=123456'] => object(Media) {}
	['http://www.dailymotion.com/video/a1b2c_lolcat-fun'] => object(Media) {}
}

Replacing URLs in text

Essence can replace any extractable URL in a text by information about it. By default, any URL will be replaced by the html property of the found Media.

echo $Essence->replace('Look at this: http://www.youtube.com/watch?v=123456');
Look at this: <iframe src="http://www.youtube.com/embed/123456"></iframe>

But you can do more by passing a callback to control which information will replace the URL:

echo $Essence->replace($text, function($Media) {
	return <<<HTML
		<p class="title">$Media->title</p>
		<div class="player">$Media->html</div>
HTML;
});
Look at this:
<p class="title">Video title</p>
<div class="player">
	<iframe src="http://www.youtube.com/embed/123456"></iframe>
<div>

This makes it easy to build rich templates or even to integrate a templating engine:

echo $Essence->replace($text, function($Media) use ($TwigTemplate) {
	return $TwigTemplate->render($Media->properties());
});

Configuring providers

It is possible to pass some options to the providers.

For example, OEmbed providers accepts the maxwidth and maxheight parameters, as specified in the OEmbed spec.

$options = [
	'maxwidth' => 800,
	'maxheight' => 600
];

$Media = $Essence->extract($url, $options);
$medias = $Essence->extractAll($urls, $options);
$text = $Essence->replace($text, null, $options);

Other providers will just ignore the options they don't handle.

Configuration

Essence currently supports 68 specialized providers:

23hq                Deviantart          Kickstarter         Sketchfab
Animoto             Dipity              Meetup              SlideShare
Aol                 Dotsub              Mixcloud            SoundCloud
App.net             Edocr               Mobypicture         SpeakerDeck
Bambuser            Flickr              Nfb                 Spotify
Bandcamp            FunnyOrDie          Official.fm         Ted
Blip.tv             Gist                Polldaddy           Twitter
Cacoo               Gmep                PollEverywhere      Ustream
CanalPlus           HowCast             Prezi               Vhx
Chirb.it            Huffduffer          Qik                 Viddler
CircuitLab          Hulu                Rdio                Videojug
Clikthrough         Ifixit              Revision3           Vimeo
CollegeHumor        Ifttt               Roomshare           Vine
Coub                Imgur               Sapo                Wistia
CrowdRanking        Instagram           Screenr             WordPress
DailyMile           Jest                Scribd              Yfrog
Dailymotion         Justin.tv           Shoudio             Youtube

Plus the OEmbed and OpenGraph providers, which can be used to extract any URL.

You can configure these providers on instanciation:

$Essence = new Essence\Essence([
	// the SoundCloud provider is an OEmbed provider with a specific endpoint
	'SoundCloud' => Essence\Di\Container::unique(function($C) {
		return $C->get('OEmbedProvider')->setEndpoint(
			'http://soundcloud.com/oembed?format=json&url=:url'
		);
	}),

	'filters' => [
		// the SoundCloud provider will be used for URLs that matches this pattern
		'SoundCloud' => '~soundcloud\.com/[a-zA-Z0-9-_]+/[a-zA-Z0-9-]+~i'
	]
]);

You can also disable the default ones:

$Essence = new Essence\Essence([
	'filters' => [
		'SoundCloud' => false
	]
]);

You will find the default configuration in the standard DI container of Essence (see the following part).

Customization

Almost everything in Essence can be configured through dependency injection. Under the hoods, the constructor uses a dependency injection container to return a fully configured instance of Essence.

To customize the Essence behavior, the easiest way is to configure injection settings when building Essence:

$Essence = new Essence\Essence([
	// the container will return a unique instance of CustomHttpClient
	// each time an HTTP client is needed
	'Http' => Essence\Di\Container::unique(function() {
		return new CustomHttpClient();
	})
]);

The default injection settings are defined in the Standard container class.

Try it out

Once you've installed essence, you should try to run ./cli/essence.php in a terminal. This script allows you to test Essence quickly:

# will fetch and print information about the video
./cli/essence.php extract http://www.youtube.com/watch?v=4S_NHY9c8uM

# will fetch and print all extractable URLs found at the given HTML page
./cli/essence.php crawl http://www.youtube.com/watch?v=4S_NHY9c8uM

Third-party libraries

If you're interested in embedding videos, you should take a look at the Multiplayer lib. It allows you to build customizable embed codes painlessly:

$Multiplayer = new Multiplayer\Multiplayer();

if ($Media->type === 'video') {
	echo $Multiplayer->html($Media->url, [
		'autoPlay' => true,
		'highlightColor' => 'BADA55'
	]);
}

essence's People

Contributors

bes avatar fastnloud avatar felixgirault avatar gargamol avatar gargron avatar h4cc avatar herewithme avatar hhirsch avatar laughingwithu avatar maartendekeizer avatar manuhabitela avatar nightmora avatar norikt avatar phordijk avatar scrutinizer-auto-fixer avatar shevabam avatar somethingideally avatar theluckyone avatar zyuhel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

essence's Issues

thumbnailUrl on Youtube urls

Hi,

Thank you for your amazing work!
Can you please provide me any guidelines to achieve my wish:

When I use ->thumbnailUrl it returns something like "http://i1.ytimg.com/vi/youtube-video-id/hqdefault.jpg"
As you can see, the default format of the thumbnail is "hqdefault.jpg".
I don't know if you are aware of this but you can ask other format for exemple to get rid of the black borders "mqdefault.jpg"

How can I ask ->thumbnailUrl to return such format?

With best regards,

J.

Add fallbacks for oEmbed providers

Some providers like Youtube seem to block requests to their API when too many of them are issued.
Adding fallback configurations using OpenGraph or Twitter cards would solve this problem easily.

Provider: Wistia

Would be great to add Wistia to the providers.

'Wistia' => array(
    'class' => 'OEmbed',
    'filter' => '/https?:\/\/(.+)?(wistia.com|wi.st)\/.*/',
    'endpoint' => 'http://fast.wistia.com/oembed?format=json&url=%s',
),

Regex filter taken from their docs.

Great project BTW. Thanks! 😉

Warning: curl_setopt_array(): CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set

Hello, i don't understant why i have this error when i launch a page who use Esscence i have this error :

Warning: curl_setopt_array(): CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set in in /var/www/html/elab/vendor/fg/essence/lib/Essence/Http/Client/Curl.php line 60

with my symfony 2.3 project.

This error occur at this line of my controller

$manager = \Essence\Essence::instance();

Thank's

Html generation

Hey Felix

Just wanted to note that the html functionality seems to have taken a backwards step and just generates html for images or a simple default html link, with no specific handling for the video type as was part of the code I originally contributed back in version 1.

Was there a reason for this decision and if not do you mind if reimplement it?

The code I am referring to is located in essence/lib/Essence/provider.php. (Also would be great If I could get an acknowledgement for the providers I worked on)

 public static function completeMedia( Media $Media ) {

                if ( !$Media->has( 'html' )) {
                        $title = htmlspecialchars( $Media->get( 'title', $Media->url ));

                        switch ( $Media->type ) {
                                // builds an <img> tag pointing to the photo
                                case 'photo':
                                        $Media->set( 'html', sprintf(
                                                '<img src="%s" alt="%s" width="%d" height="%d" />',
                                                $Media->url,
                                                $title,
                                                $Media->get( 'width', 500 ),
                                                $Media->get( 'height', 375 )
                                        ));
                                        break;

                                // builds an <a> tag pointing to the original resource
                                default:
                                        $Media->set( 'html', sprintf(
                                                '<a href="%s" alt="%s">%s</a>',
                                                $Media->url,
                                                $Media->has( 'description' )
                                                        ? htmlspecialchars( $Media->description )
                                                        : $title,
                                                $title
                                        ));
                                        break;
                        }
                }

                return $Media;
        }

I have also managed to integrate the wikipedia api in with Essence and will hopefully be able to merge this along with a few more providers in the next few weeks.

cheers

thumbnailFormat=maxres

Would be great to add also the option "maxres" for thumbnailFormat:

$oEmbed = $Essence->embed($text, [
'thumbnailFormat' => 'maxres'
]);

and

case 'maxres':
$url = str_replace( 'hqdefault', 'maxresdefault', $url );
break;

Tag Cascade

Require a tagged version of Cascade in composer.json.

Code review

Hi,

While reviewing and digging into code, I'm wondering the following:
https://github.com/felixgirault/essence/blob/master/lib/Essence/Media.php

namespace Essence;

use ArrayIterator;
use IteratorAggregate;
use JsonSerializable;
use Essence\Configurable;
...

Then within the class:

class Media implements IteratorAggregate, JsonSerializable {
    use Configurable;

What is the purpose of this "use Configurable" statement? You already declared a "use Essence\Configurable;".

With best regards.

API Branch

Hi Felix

I have been working on integrating wikipedia and Github via their API's and was wondering if you could create a branch specifically for the API's to be sent too rather than the multiple providers branch.

BTW like the changes you made to my last pull request, learning a lot from your style of coding.

Cheers

shortcodes

Not sure if this is currently possible, but could you define a url "wrapper" so that essence doesn't automatically embed all url's?

eg.

$text = 'http://www.youtube.com/embed/JwlgC-jSPTk'; # doesn't get transformed

$text .= '[embed http://www.youtube.com/embed/JwlgC-jSPTk]'; # does get transformed

$essence->replace($text, $wrapper = '[embed %s]');

The converse could actually work better, defining a way to not embed a specific url.

$text = 'http://www.youtube.com/embed/JwlgC-jSPTk'; # does get transformed

$text .= '!http://www.youtube.com/embed/JwlgC-jSPTk'; # doesn't get transformed

$essence->replace($text, $antiwrapper = '!');

Part of my motivation is that if I'm passing html to essence things can go haywire.

$text = '<a href="http://www.youtube.com/embed/JwlgC-jSPTk">Video</a>';

$essence->replace($text); # oh dear :(

Html property not always populated

This is kind of a request which I am going to work on myself and pull a request when I can, as from what I can see it it is just a matter of setting up a template for OG providers.

Also just want to run an idea past you with regard to websites that don't support oembed or OG. Basically use their existing API to get the information and then parse it through JSON in accordance with the Oembed spec for Essence to work with. I realise this may be outside the scope of your project and again I will try to implement this myself.

Let me know whether this is where you see Essence going or if wish to keep it clean and not quite so hacky.

Cheers again

Problem parsing YouTube url

Hey

When trying to parse a YouTube url

$essence = Essence\Essence::instance();
$media   = $essence->embed('http://www.youtube.com/watch?v=Cgoqrgc_0cM');

I get an error on this line in providers.php (line 239)

$url = OEmbed::prepare( $url );

It seems the prepare method has been replaced with prepareUrl? So I changed the function to OEmbed::prepareUrl( $url ) which then compiles OK but the video isn't parsed.

I then looked into the OEmbed::prepareUrl() function and it seems that this is trimming any querystrings from the url, so my url above becomes http://www.youtube.com/watch - which is clearly incorrect.

If I comment out the whole call to OEmbed::prepareUrl() it works.

Bug with _parseXML

Hello Felix,

J'ai un petit problème avec ta lib, parfois elle me retourne ce tableau au lieu de me retourner NULL ou dans le cas les balises Facebook (présentes dans le code).

J'ai un peu inspecté ton code et fait des tests, et je suppose que cela vient de ta méthode _parseXML ...

As tu déjà eu ce problème ?

class fg\Essence\Media#950 (1) {
  protected $_properties =>
  array(2) {
    'channel' =>
    string(40) "\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t"
    'url' =>
    string(28) "http://blog.nicolas-juen.fr/"
  }
}

Merci d'avance

embed.ly and other providers

Firstly this is awesome and I love the way you code.

Was wondering whether it would be possible to have embed.ly as a oembed provider. I have already done a few other oembed providers and will create a fork and then make a pull request.

Also a heads up that I am integrating essence into Concrete5 as part of a package that I am developing.

Cheers

Parse text for embeddable urls

Hi,

it would be cool to have a function that gets a text as param and will search for embeddable urls (like youtube).

It may returns:

  • the list of embeddable urls (like Essence::extract() does)
    or (maybe base on a flag as second param)
  • the text with embeddable urls replaced by Media::html()

Thank you for your good work. ;)

Rework OEmbed/Multiple provider

This provider is not the better way of handling a huge number of providers as it adds another layer under the ProviderCollection.

Maybe an OEmbed/Simple provider could be created. It would be instanciated for each service, keeping a reasonable number of classes while allowing to set an infinite list of services.

The list of services could then be defined in a configuration file.

wmode on videos

An old problem with a known solution. basically because flash and the like is redendered differently to html, it does not respect z-index values and always appears over html elements.

Adding ?wmode=opaque to the end of the url will fix this. Only problem with this solution is accessibility concerns.

The easiest solution would just add this to each of the providers that provide flash or other embeds, but this would only work with oembed providers.

Alternatively the solution I would prefer is create a function to string replace the url only when a video is provided but before I go ahead and implement this was wondering what you thought.

Extract generic classes

Extract all generic classes from essence to keep them in a separate repo:

  • lighter essence repo
  • independant and reusable framework

Extract from HTML (string)

Instead of fetching an entire page via cURL or file_get_contents(), parsing an entire HTML page or an HTML fragment from a string would be handy. On some pages, only certain parts of the HTML are worth parsing and I'd like to run Essence on just those by passing HTML as a string.

oEmbed: Allow additional parameters

Please can you allow additional parameters for oEmbed.

The OEmbed::_completeEndpoint method is currently reducing parameters to only maxwidth and maxheight, which is breaking functionality of certain providers (f.ex. Wistia).

From the oEmbed spec (2.2):

Providers are welcome to support custom additional parameters.

Suggested change

protected function _completeEndpoint( &$endpoint, $options ) {

    if ( ! empty( $options ) ) {
        $endpoint .= ( strrpos( $endpoint, '?' ) === false ) ? '?' : '&';
        $endpoint .= http_build_query( $options );
    }
}

Trying to get property of non-object

Hi,
Since few days, I have a very strange issue!

I use Laravel 4. Please note that everything was working very well.

  1. I fetch data from database returned as a collection of objects. (tested and working)
// fetch resources collection
$resources = $xxx->resources()->orderBy('created_at', 'DESC')->get();
  1. I instantiate the Essence object. (tested and working)
// Essence to work on resources
$essence = Essence\Essence::instance();
  1. I perform a foreach (->each) on the collection
// Fetch metadata from the resource
$resources->each(function ($resource) use ($essence)
{
    $media = $essence->embed($resource->url, ['thumbnailFormat' => 'medium']);
    var_dump($media); // A
    var_dump($media->title); // B
});

// A output

object(Essence\Media)[259]
  protected '_properties' => 
    array (size=23) ...

// B output

Trying to get property of non-object

Do you have any idea? It should be very simple! That drives me nuts!!

With best regards.

[probosal] - Flickr provider

Hi

Lova to hav a Flickr provider in the providers list, like this?

namespace fg\Essence\Provider\OEmbed;

class Flickr extends \fg\Essence\Provider\OEmbed {

public function __construct( ) {

    parent::__construct(
        '#flickr\.com|youtu\.be#i',
        'http://www.flickr.com/services/oembed?format=json&url=%s',
        self::json
    );
}

}

Youtube scripts will be blocked on HTTPS page

Issue:

  • When I embed a Youtube video on a HTTPS page, the latest Chrome and Firefox block their scripts with a "This page has insecure content" warning
  • This is caused by the iframe src being a HTTP resource

Solution:

Implementation:

References:

Error ir curl fail

Hi Felix, Sorry to bother you again!

If I by mistake use an url to media that is not correct (like two bb in youtube) I get a "Exception: HTTP error" that I can't catch?

like this url: http://www.youtubbe.com/watch?v=oHg5SJYRHA0

I think it happens when curl try to fetch media that does not exist?

/fg/Essence/Http/Curl.php line 88
at Curl->get('http://www.youtubbe.com/watch?v=oHg5SJYRHA0') fg/Essence/Provider/OEmbed/Generic.php line 89

Would be super nice to be able to catch it using the lastError or handle that in some way.

if (!$media){
$exception = $essence->lastError();
}

any ideas?

regard // Johannes

Trouble with Essence::replace and multiple sources of media

Assuming you have a text featuring two links:

  1. Link to a tweet (or any other textual source)
  2. Link to another media source

And assuming the content of the first link contains the second link, The Essence::replace method will very generously replace that link in the embedded content as well.

Here is a piece of text that triggers this bug:

https://twitter.com/Totalbiscuit/status/339129052889755650

The video being

http://www.youtube.com/watch?v=nU2y6ztlMAQ

Incorrect format used

Soundcloud is defined in the constructor like this:

            parent::__construct(
                    '#soundcloud\.com/[a-zA-Z0-9_]+/.+#i',
                    'http://soundcloud.com/oembed.json?url=%s',
                    self::json
            );

However it seems to download XML version instead:

http://soundcloud.com/oembed?url=http://soundcloud.com/forss/flickermood
vs
http://soundcloud.com/oembed?url=http://soundcloud.com/forss/flickermood&format=json

due to this problem thumbnail-url gets into properties instead of thumbnail_url and also iframe is wrapped inside CDATA:

thumbnail-url:
http://i1.sndcdn.com/artworks-000030703701-n5da7c-t500x500.jpg?ca77017
html:
]]>

SoundCloud should use json

p.s. this was working fine yesterday, but something was changed by SoundCloud in their XML format of OEmbed.

Customize HTML player

Is there any way customize the HTML output.

For example.

If I do this for Vine

    $Media = $Essence->embed( 'https://vine.co/v/M7MFlunmLJ5' );
    echo $Media->html;

Output is

<iframe class="vine-embed" src="https://vine.co/v/M7MFlunmLJ5/embed/postcard" width="320" height="320" frameborder="0"></iframe><script async src="//platform.vine.co/static/scripts/embed.js" charset="utf-8"></script>

But I want output to be like this

<iframe class="vine-embed" src="https://vine.co/v/M7MFlunmLJ5/embed/postcard" width="320" height="320" frameborder="0"></iframe>

By removing that script tags vine videos will not auto play. Same is their any way by which we can customize the soundcloud and youtube player.

Or is there any way by which can get embed url only like https://vine.co/v/M7MFlunmLJ5/embed/postcard

Thanks

Exposing other methods

I’m interested in interacting with providers programatically without rebuilding the entire Collection service.

A couple of things I’m trying to do:

  • List providers
  • Check URLs against providers

It doesn’t appear to be possible to access the providers service instance within the current API. If I’m missing something let me know but I can’t figure out how to interact with these at present.

What might be the approach for this?

Implement null object pattern for medias

Instead of returning null for non embeddable medias, returning a null object would be less error prone.

$Media = $Essence->embed( 'http://...' );

// old way
if ( $Media === null ) { }
if ( $Media !== null ) { }

// new way
if ( $Media->isNull( )) { }
if ( $Media->isOk( )) { }

Declaration of Essence\Provider\OEmbed::prepareUrl()

Hey,

I just did a quick composer require "fg/essense:dev-master" in my Laravel project.

Then added a simple render method with the following:

public function render()
{
  $essence = Essence\Essence::instance();

  $embedded = $essence->replace($this->text);

  return $embedded;
}

Got the following Exception:

Declaration of Essence\Provider\OEmbed::prepareUrl() should be compatible with Essence\Provider::prepareUrl($url, array $options = Array)

Add configuration options for providers

Allow the user to pass options to providers to customize their behavior.

This could be used to create multisites providers, which could be configured at initialisation to set which sites they would try to embed.

For example, all the simple OEmbed providers could be replaced by a single one, configured with the scheme and endpoint of each particular website, reducing the overall weight of the library.

Update Packagist

Packagist doesn’t seem to have updated to the most recent tagged release (v2.5.0).

Perhaps a Force Update may do the trick.

Oh, flicker provider is gone?

Hi

The Flicker provider is now gone in commit 'Removed useless providers'.

It wasn't useless to me :-(

all the best // johannes

Update doc

Hi,

there are some errors in the README.md that I have detected:

  1. The namespace is fg\Essence and not Essence

  2. In the configure method, you have forgotten to wrap the providers inside an array

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.