Giter VIP home page Giter VIP logo

metalsmith-pagination's Introduction

Metalsmith Pagination

NPM version NPM downloads Build status Test coverage

A Metalsmith plugin for paginating arrays and collections.

Installation

npm install metalsmith-pagination --save

Usage

To paginate an array of files, you need to have a property that points to the location of the collection you want to paginate. The value should be an options object that will be used to initialize the plugin.

P.S. Make sure the pagination middleware is defined after the files array exists, but before the template middleware renders.

CLI

Install via npm and then add metalsmith-pagination to your metalsmith.json:

{
  "plugins": {
    "metalsmith-pagination": {
      "collections.articles": {
        "perPage": 5,
        "template": "index.jade",
        "first": "index.html",
        "path": "page/:num/index.html",
        "filter": "private !== true",
        "pageMetadata": {
          "title": "Archive"
        }
      }
    }
  }
}

JavaScript

Install via npm, require the module and .use the result of the function.

var pagination = require('metalsmith-pagination')

metalsmith.use(pagination({
  'collections.articles': {
    perPage: 5,
    template: 'index.jade',
    first: 'index.html',
    path: 'page/:num/index.html',
    filter: function (page) {
      return !page.private
    },
    pageMetadata: {
      title: 'Archive'
    }
  }
}))

Options

  • perPage The number of files per page (default: 10).
  • first An optional path to use in place of the page one (E.g. Render as the homepage index.html, instead of page/1/index.html).
  • path The path to render every page under. Interpolated with the pagination object, so you can use :name, :num or :index.
  • filter A string or function used to filter files in pagination.
  • pageMetadata The metadata to merge with every page.
  • noPageOne Set to true to disable rendering of page one, useful in conjunction with first (default: false).
  • groupBy Set the grouping algorithm manually (default: paginated by perPage). Useful for paginating by other factors, like year published (E.g. date.getFullYear()).
  • empty Allows empty pages for collections. This will also be used as the file passed to groupBy to get the page name.
  • template The template metadata for metalsmith-templates.
  • layout The layout metadata for metalsmith-layouts.
  • pageContents Set the contents of generated pages (default: Buffer.from('')). Useful for metalsmith-in-place (especially with pageMetadata).

Page Metadata

The pageMetadata option is optional. The object passed as pageMetadata is merged with the metadata of every page generated. This allows you to add arbitrary metadata to every page, such as a title variable.

Template Usage

Within the template you specified, you will have access to pagination specific helpers:

  • pagination.num The current page number.
  • pagination.index The current page index (num - 1).
  • pagination.getPages(num) Get an array of num pages with the current page as centered as possible
  • pagination.name The page name from groupBy. If no groupBy was used, it is the current page number as a string.
  • pagination.files All the files to render in the current page (E.g. array of x articles).
  • pagination.pages References to every page in the collection (E.g. used to render pagination numbers).
  • pagination.next The next page, if it exists.
  • pagination.previous The previous page, if it exists.
  • pagination.first The first page, equal to pagination.pages[0].
  • pagination.last The last page, equal to pagination.pages[pagination.pages.length - 1].

For example, in Jade:

block content
  each file in pagination.files
    article.content
      header.header
        small.header-metadata
          time.timestamp(datetime=file.date)= moment(file.date).format('MMMM D, YYYY')
        h2.content-title
          a(href='/' + file.path)= file.title
      section.content-article!= file.snippet
  nav.navigation.cf
    if pagination.previous
      a.btn.pull-right(href='/' + pagination.previous.path)
        | Newer  
        i.icon-right-dir
    if pagination.next
      a.btn.pull-left(href='/' + pagination.next.path)
        i.icon-left-dir
        |   Older

License

MIT

metalsmith-pagination's People

Contributors

alexey-detr avatar blakeembrey avatar dependabot[bot] avatar greenkeeper[bot] 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

Watchers

 avatar  avatar  avatar  avatar

metalsmith-pagination's Issues

Cannot output perPage limited article list using Handlebars templates

I must be doing something wrong, but can't see what. I'm following the instructions from your article on building a blog with Metalsmith, but using Handlebars over Jade: http://blakeembrey.com/articles/2014/09/building-a-blog-with-metalsmith/

Here's the relevant code, first from build.js:

Metalsmith(__dirname)
    .source('src')
    .use(collections({
        articles: {
            pattern: 'articles/**/*.md',
            sortBy: 'date',
            reverse: true
        },
        pages: {
            pattern: 'pages/**/*.md',
        }
    }))
    .use(pagination({
        'collections.articles': {
            'perPage': 2,
            'template': 'partials/blogNavigation.hbt',
            'path': 'page/:num/index.html'
        }
    }))
    .use(markdown({
        'smartypants': true,
        'gfm': true,
        'tables': true
    }))
    .use(permalinks())
    .use(templates('handlebars'))
    .destination('build')
    .build(function(err) {
        if (err) console.log(err);
    });

and the Handlebars template:

<h2 id="blogHeading">Top Blog Posts</h2>
<ul class="articleList">
    {{#each collections.articles}}
        <li class="articleList__item">
            <h3 class="articleList__itemName">
                <a href="{{ this.path }}">{{ this.title }}</a>
            </h3>
        </li>
    {{/each}}
</ul>

I've split the iterator for blog post headers into its own template, that rolls into the home.hbt that renders the index.html page, but cannot get the list to generate unless I use collections.articles. I'm not sure what to replace that with in Handlebars, and thus can't get my pagination or per page limiting in place.

Switching to metalsmith-layouts

I recently upgraded a bunch of outdated packages on my site, and have run into a bit of a problem.

I was previously using metalsmith-templates, but with it being deprecated figured it was about time to upgrade. Everything else is working fine for me at the moment switching to metalsmith-layouts with the sole exception of metalsmith-pagination... :(

The relevant sections of my index.js show what everything mostly looked like when it was working fine with metalsmith-templates:

...
paginate    = require('metalsmith-pagination'),
...

.use(paginate({
        'collections.blogposts':{
            perPage: 10,
            //template: 'test.hbt'
            //template: 'blog-list-pages.hbt',
            layout: 'blog-list-pages.hbt',
            first: '/blog/index.html',
            path: '/blog/page-:num.html',
            pageMetadata: {
                title: 'Blog'
            }
        }
    }))

The only difference between it previously working and now is the change from metalsmith-templates to metalsmith-layouts, and the requisite change of the template: key to layouts: - which seemed to be straightforward. The problem is that I am not getting any of my generated output as expected previously. Any ideas on moving forward to troubleshoot?

Limiting the amount of pages shown in the pagination

Is there a way to limit the amount of pages shown in the pagination?

For example my blog has 10 pages at the moment, and so the pagination looks something like this:

< 1 2 3 4 5 6 7 8 9 10 >

I want to limit this to only displaying 3 results at a time, i.e.:

< 4 5 6 >

And by extension, I think this would be great if it included a way of getting the first and last page.

Contents writing fully templated data?

I've run into an odd problem here.
I've got a very simple project setup, using only (in this order):

  • metalsmith-collections
  • metalsmith-markdown
  • metalsmith-permalinks
  • metalsmith-pagination
Metalsmith(__dirname)

    .metadata({
        sitename: "Site Name",
        siteurl: "siteurl"
    })
    .source('./src')
    .destination('./build')
    .clean(true)
    .use(collections({
        posts: 'posts/**/*.md',
        sortBy: 'date',
        reverse: true
    }))
    .use(markdown())
    .use(permalinks({
        pattern: ':date/:title',
        date: 'YYYY/MM',
        relative: false
    }))
    .use( paginate({
        'collections.posts': {
            perPage: 10,
            layout: 'main.hbt',
            first: 'index.html',
            path: ':num.html'
        }
    }))
    .use( layouts({
        engine: 'handlebars',
        directory: 'templates'
    }))
    .build( function(err) {
        if (err) throw err;
    });

The template for paginated files looks like this:

<!DOCTYPE html>
<html lang='en'>
    <head>
        <title>{{{ sitename }}}</title>
    </head>
    <body>
        {{#each pagination.files}}
        <article>
            <h1 class='post.title'><a href="/{{path}}">{{title}}</a></h1>
            <!-- CONTENTS -->
            {{{ contents }}}
            <!-- /CONTENTS -->
        </article>
        <hr>
        {{/each}}

    </body>
</html>

I am expecting that {{{ contents }}} writes only the contents of each post, but it appears to be writing the fully templated version of each post.

In the html output, I expected:

<!DOCTYPE html>
<html lang='en'>
    <head>
        <title>Site Name</title> 
    </head>
    <body>
        <article>
            <h1 class='post.title'><a href="/2015/01/test-deux-2015">Test Deux (2015)</a></h1>
            <!-- CONTENTS -->
                    <h2>Test Deux (2015)</h2>
                    <div>
                        <h2 id="second-heading-2015-">SEcond heading (2015)</h2>
                        <p>some paragraph stuff</p>
                    </div>
            <!-- /CONTENTS -->
        </article>
    </body>
</html>

Instead I am seeing what appears to be the fully templated contents (notice the extra html elements):

<!DOCTYPE html>
<html lang='en'>
    <head>
        <title>Site Name</title> 
    </head>
    <body>
        <article>
            <h1 class='post.title'><a href="/2015/01/test-deux-2015">Test Deux (2015)</a></h1>
            <!-- CONTENTS -->
            <html lang='en'>
            <body class='postpage-from-post-layouts'>
                    <h2>Test Deux (2015)</h2>
                    <div>
                        <h2 id="second-heading-2015-">SEcond heading (2015)</h2>
                        <p>some paragraph stuff</p>
                    </div>
            </body>
            </html>
            <!-- /CONTENTS -->
        </article>
    </body>
</html>

Why is page 1 generated twice when options.first is set?

As can be seen in the tests, when the first option is set, a firstPage and a pageOne are created:

        var firstPage = files['articles/index.html']
        var pageOne = files['articles/page/1/index.html']
        (...)
        expect(firstPage).to.exist
        expect(firstPage).to.not.equal(pageOne)
        expect(firstPage.pagination.next).to.equal(pageTwo)
        expect(firstPage.pagination.previous).to.not.exist

        expect(pageOne).to.exist
        expect(pageOne.pagination.next).to.equal(pageTwo)
        expect(pageOne.pagination.previous).to.not.exist

The contents of firstPage and pageOne are the same, so I'm wondering: why is pageOne created?

Plugin creates index.html files, but there is no content in them

Hello, i have a little issue here....

So i have 4 posts and plugin created 4 folders for me, but the index.html files in them are empty by some reason, Could you please tell me what the problem can be, i just need to get output in the generated index files. Let me know if you need anything else to determine the issue. Thank you!

1) I installed the plugin
2) Added plugin to my plugin list :

"metalsmith-pagination": {
      "collections.posts": {
        "perPage": 1,
        "layout": "blog.hbt",
        "path": "page:num/index.html"
      }
    }

3) These are my collections:

"metalsmith-collections": {
        "page": {
            "pattern": "**/index.*",
            "sortBy": "priority",
            "reverse": true,
            "refer": false,
            "metadata": {
                "layout": "page.hbt"
            }
        },
        "posts": {
            "sortBy": "publishDate",
            "reverse": true
        }
    }

4) Here is the posts files' metadata:


---
title: First Post
publishDate: 2014-04-18
layout: post.hbt
collection: posts

---

5) Here is my blog.hbt layout:

{{> header}}

<h2> This heading should be copied in every paginated page </h2>

{{> footer}}

6) Here are the layouts and partials registered:

"metalsmith-layouts": {
        "engine": "handlebars",
        "directory": "src/website/layouts",
        "partials": "src/website/layouts/partials"
    },
    "metalsmith-in-place": {
      "engine": "handlebars",
      "partials": "src/website/layouts/partials"
    }

Path fields is not populated correctly with [email protected]

When you upgrade metalsmith-collections from 0.7.0 to 0.9.0 then the path field in the file object listed in pagination.files become a string
"articles/le-theatre-entreprise.md"

instead of being the usual object :

{ 
  root: '',
  dir: 'articles',
  base: 'le-theatre-entreprise.md',
  ext: '.md',
  name: 'lexique-satisfaction-client-W',
  href: '/articles/le-theatre-entreprise.md,
  dhref: '/articles/' 
}

My setup is :

"metalsmith": "2.3.0",
"metalsmith-collections": "0.7.0",
"metalsmith-copy": "0.3.0",
"metalsmith-layouts": "1.8.1",
"metalsmith-markdown": "0.2.1",
"metalsmith-pagination": "1.4.0",
"metalsmith-paths": "3.0.1",
"metalsmith-publish": "0.1.5",
"metalsmith-tags": "2.0.0",
"metalsmith-text-replace": "1.0.1"

Not overwriting files

I'm trying to run this plugin after metalsmith-permalinks renders a set of posts. It used to work, but I've changed some of the metadata and it's not overwriting the file. Any thoughts?

Error: Failed to write the file at: dist/blog/2016/07/18/how-to-set-smart-marketing-goals-and-forecast-revenue/index.html

EEXIST: file already exists, mkdir /dist/blog/2016/07/18/how-to-set-smart-marketing-goals-and-forecast-revenue'
    at Error (native)

Please add template examples.

Conceptually I like the idea of the plugin. But I'd really like to see an example of how it would be implemented in a jade template.

How to use pagination with full article contents and not snippets?

In page layout pagination.files[].contents inserts the whole rendered html file with its own layout. Where can I get the same contents that is at contents property in a single article layout? Or is there a way to paste whole contents in the snippet property somehow? I don't have them in my *.md files.

I noticed that I can get correct contents when using pagination before markdown, but in that case path is wrong. It points to the *.md file.

What am I doing wrong?

pagination object not being read from pug template

I'm trying to use the pagination object in my templates, but when I try to build out my site I get a "Cannot read property 'files' of Undefined. I'm assuming the undefined is in fact, the pagination object.

html(lang="en")
  head
    meta(charset="utf-8")
    meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1')
    meta(name="viewport", content="width=device-width")
    title= Home
  body
    h1 Home
    each article in pagination.files
      article.content-article
        header
          span.timestamp= article.date
            h2
              a(href=`/${article.path}/`)= article.title 

If this helps, I also have my build file.

const metalsmith = require('metalsmith');
const markdown = require('metalsmith-markdown');
const highligher = require('highlighter');
const layouts = require('metalsmith-layouts');
const permalinks = require('metalsmith-permalinks');
const collections = require('metalsmith-collections');
const pagination = require('metalsmith-pagination');

metalsmith(__dirname)
  .source('./src')
  .use(collections({
    articles: {
      pattern: 'articles/**/*.md',
      sortBy: 'date',
      reverse: true,
    }
  }))
  .use(pagination({
    'collections.articles': {
      perPage: 5,
      first: 'index.html',
      path: 'page/:num/index.html',
      layout: 'index.pug',
    }
  }))
  .use(markdown({
    gfm: true,
    tables: true,
    highlight: highligher(),
  }))
  .use(permalinks())
  .use(layouts({
    engine: 'pug',
    directory: 'layouts',
  }))

  .build((err) => {
    if (err) throw err;
  });

Thank you for your time.

Template var paginate vs pagination

It seems that paginate.next and paginate.previous are not available in the template, but pagination.next and pagination.previous are. This is not reflected in the readme

Plugin throws TypeError if collection doesn't exist

Hey

First, thanks for the great plugin!

Second, just wondering why the plugin is so strict about requiring the collection to be present in the build. If I have a null collection (i.e. nothing in my build matches the pattern set on metalsmith-collections) then the plugin throws a TypeError (L37).

I back most of my Metalsmith sites with Contentful, so I'm not in complete control of which items will be in the build. If an editor removes all items from a particular Content Type then it's possible that the collection will be empty.

Could default behaviour just be skipping over missing/empty collections?

Cheers
Sam

Does not allow omission of template and layout options

I've just implemented pagination with this plugin (see here: https://github.com/ismay/ismaywolff.nl/commit/df879d291f27f198fa2bb757a79fe5c587c8b779), and it works really well. Only one thing that it does is a minor inconvenience: it requires me to pass a layout or template option, when in fact I'm using the pageContents option with in-place (so I don't need layouts or templates).

I've now set layout to a nonsense string ("none") to silence the error (see here: https://github.com/ismay/ismaywolff.nl/blob/master/metalsmith.js#L82), but it would be nice if it was allowed to omit both layout and template when pageContents has been set.

Automatically generate index.html pages when not specified in path property

Today, if you wanna have your pages paths set as page/2/, and not as page/2/index.html, setting the path option as page/:num/ will make the generation just to output files named like /page/2, but we want files to be named as /page/2/index.html.

metalsmith.use(pagination({
  "collections.posts": {
    "path": "page/:num/"
  }
}));

Current output:

root/
  page/
    1        <- file, not folder
    2        <- file, not folder
    3        <- file, not folder
    ...

Desired output:

root/
  page/
    1/
      index.html
    2/
      index.html
    3/
      index.html
    ...

That way, it works in accordance with metalsmith-permalinks as well.

Let me know what you think about this.
And thanks for this awesome plugin! =)

how to add next and previous button along with some page number in pagination using javaScript.

Hi have done some basic pagination and it is working fine now i need to add next and previous button.Please help me it would great appreciation.
PFB screenshot what i have developed.
image
After clicking page number 5, page number 6 and 7 appear.
image
Now I just want to add previous and next button.
PFB my code.

displayDetailsPage(success, index) {
    console.log(this);
    const mbmleaseArrList = JSON.parse(success);
    console.log(mbmleaseArrList.length);
    let htmlpagedisplay = '';
    let i;
    let htmlBuild = '';
    const start = Math.max(0, index - 2);
    const end = Math.min(start + 5, mbmleaseArrList.length - 1);
           if ((i + 1) !== 1) {
        htmlpagedisplay += (`<button value="${1}" id='pageshow' class="mb-lease-report__lilist" data-pageNo-show=${0}>First</button>`);
    }
    for (i = start; i < end; i += 1) {
        htmlpagedisplay += (`<button value="${i + 1}" id='pageshow' class="mb-lease-report__lilist" data-pageNo-show=${i}>${i + 1}</button>`);
    }
    if ((i + 1) !== mbmleaseArrList.length - 1) {
        htmlpagedisplay += (`<button value="${mbmleaseArrList.length - 1}" id='pageshow' class="mb-lease-report__lilist" data-pageNo-show=${mbmleaseArrList.length - 1}>Last</button>`);
    }
    resultDisplay.innerHTML = htmlBuild;
    resultDisplay1.innerHTML = htmlpagedisplay;}

    document.addEventListener(EVENTS.CLICK, (e) => {//here i have written the event listener when I was clicking on the page it gets triggered. 
        console.log(this);
        if (e.target && e.target.matches(`#${ID.PAGESHOW}`)) {
            e.preventDefault();
            const inputs = document.getElementById(`${ID.SHOW}`).value;
            const index = e.target.getAttribute('data-pageNo-show');
            const url = '/bin/microsites/mb-lease-report-pagination';
            const data = {
                formData: inputs,
            };

            this.Ajax.ajaxPostFn(url, data, (success) => {
                // console.log(success);
                this.displayDetailsPage(success, index);
            });
        }
 });

Now my requirement is that add next and previous button.

Docs, Using in-place templates

Are there docs anywhere for the params on this plugin? I'm not sure what the first parameter does.

Also, how does the template get rendered? I'm using metalsmith-in-place and I'd like to choose a template from the src dir instead of the root templates or layouts.

Thanks.

How can this plugin be used by other metalsmith plugins?

Hello! I'm currently working on adding pagination to the metalsmith-tags plugin. I'd love to use this plugin alongside my modifications in the tags plugin however I'm a little stuck as to how I can go about doing so.

Currently this plugin requires fixed knowledge of all collections and arrays so that it can create the pagination files.

However with the tags plugin I don't know what tags are going to exist until runtime. At the point when I know what tags I want to paginate I can no longer modify the pagination options object.

So this is more of a question and brainstorm of how I could use this plugin alongside the tags plugin. Can I do so as this plugin currently exists, or as I suspect, some modifications are required for this plugin.

Does not work with multi-language module

Pagination is not aware of the locale property in page metadata.

I'm not sure how to solve this without breaking the current api as we do not have access to anything then the pagination properties when defining options like first and path.

If pageContents is a string, you get undefined behavior.

TL;DR: When you set pageContents to a string, layouts do not get applied to the page.

Hello, I just solved an issue I was having with this plugin. It took me awhile and I had to dig through several plugins before I figured it out.

You have to pass a buffer object for the pageContents option. If you pass a string, the layout plugin fails, silently, it's utf8 check. When I ran my build, my generated pagination page only had the string I passed, no html from the layout.

I suggest doing a typeof check for strings on the pageContents option and either throw an error or create a new buffer using the string.

BTW, Thank you for creating and maintaining this plugin!

path option arguments don't work correctly

It looks like there is an issue in the interpolate method. For example, this path setting won't be replaced correctly:
path: 'blog/page:num_en.html'

After performing the interpolate method, it will return blog/pageundefined.html

Generate pagination from empty collection

Thank you for writing this great plugin. It is one of my core components in my build chain for a while.

Do you think it is worth to generate a pagination even when the collection is empty? Currently, this plugin does not add any new pages when there are no files inside the specified collection.

This is useful when the collection is generated dynamically. Suppose 3 collections (a, b, c) are prepared in advance, then we scan through all files and add them into one of them, We expect this plugin to generate 'a/page/1.html', 'b/page/1.html', 'c/page/1.html'. This plugin currently does not generate pages for empty collection, so the file existence becomes inconsistent.

I am currently modifying(add) your code like below in my project. I'm not sure about the potential demerits, but it would be nice if this feature is officially supported.

...
if (collection.length == 0 && pageOptions.emptyPage) {
  var params = {
    name: '0',
    index: 0,
    num: 1
  }

  // Generate the page data.
  var page = extend(pageOptions.pageMetadata, {
    template: pageOptions.emptyPage.template,
    layout: pageOptions.emptyPage.layout,
    contents: pageOptions.emptyPage.pageContents || Buffer.from(''),
    path: interpolate(pageOptions.path, params),
  })

  if (!pageOptions.noPageOne) {
    files[page.path] = page
  }

  if (pageOptions.first) {
    // Extend the "first page" over the top of "page one".
    page = extend(page, {
      path: interpolate(pageOptions.first, params)
    })

    files[page.path] = page
  }
}
...

In addition, solving issue #25 makes this feature even more useful, I guess.

Contentful Integration

Thanks for the awesome plugin. I'm new to Metalsmith so please forgive any ignorance, but I've been looking through your docs, the contentful-metalsmith docs, and the metalsmith-collections docs, trying to find a way to set up pagination on content that's coming from contentful. Is Metalsmith-collections a requirement for metalsmith-pagination? I know you don't explicitly say that, but each example I've found of metalsmith-pagination uses collections. I haven't found any evidence that collections and contentful are compatible.

I'm planning on using a javascript setup. I've forked the contentful-metalsmith-example (https://github.com/contentful-labs/contentful-metalsmith-example) and done some testing using our data and everything works fine, but I haven't had much luck with your plugin. Do you have any advice?

I won't get too into the detail of our setup and what I have and haven't tried unless you think it'll help answer the question.

Thanks again!

I can't get your plugin to work

I've tried everything, it's not working..

  "pagination": {
    "collections.posts": {
      "perPage": 2,
      "first": "blog/index.html",
      "path": "blog/:num/index.html",
      "pageMetadata": {
"title": "Blog"
},
      "layout": "blog.liquid"
    }
  },

add page metadata to pagination.files

I'm trying to render a paginated collection with metadata added to each file from another plugin (excerpts).. Currently, it's not being added to each pagination.files metadata. The problem is that I can't access metalsmith with my current project as it's being abstracted away from a config so I don't have access to the metadata() to assign to fileMetadata. Is there any way that you can simply extend the files with the current file metadata in the collection assigned? That way the metadata property wouldn't be needed for pagination.files?

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.