GithubHelp home page GithubHelp logo

marmelab / sedy Goto Github PK

View Code? Open in Web Editor NEW
268.0 18.0 26.0 1.46 MB

A GitHub bot bringing the sed command to code reviews

Home Page: https://marmelab.com/sedy/

License: MIT License

Makefile 1.32% JavaScript 98.68%
looking-for-contributors

sedy's Introduction

inviting new maintainers Archived Repository
This code is no longer maintained. If you're interested in taking over the code and its maintenance, please contact marmelab.

Build Status

What's Sedy

Sedy is a GitHub webhook which allows pull-request reviewers to fix typos themselves by typing sed-like commands on review comments.

commit example

How it works

After installing Sedy on your repository, just type a sed-like command (s/[old text]/[new text]/) in a single comment or in a code review, and Sedy will quickly commit the fix.

Installation

Go to https://github.com/apps/sedy and follow the instructions.

That's it.

Contributing

Whether it's for a bug or a suggestion, your feedback is precious. Feel free to fill an issue. Be sure that it will be considered.

If you want to open a PR, all you need to know is written on the CONTRIBUTING.md.

License

sedy is licensed under the MIT License, and sponsored by marmelab.

sedy's People

Contributors

alexisjanvier avatar djhi avatar fzaninotto avatar jpetitcolas avatar kmaschta avatar luwangel avatar marmelab-bot avatar pborreli avatar sedy-bot avatar timgrossmann 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

sedy's Issues

Remove octonode

Remove useless dependency octonode in favor of request.
It would be a good way to clean github client.

My organization repositories don't show up

Description

My organisation repositories don't show up

Steps to Reproduce

  1. Go to https://marmelab.com/sedy
  2. Click on "Authorize on Private & Public Repositories"
  3. Grant access to organization repositories
  4. Back on https://marmelab.com/sedy it shows only my personal repositories

Expected behavior: That I could select the organization repositories where I'm the owner

Actual behavior: Could only select my personal repositories

Add push on :+1: from submitter

Description

Shamelessly pinched from @unholiness here: https://news.ycombinator.com/item?id=13753987

Rather than triggering Sedy immediately on a reviewer comment, I'd like the trigger to be the original requester reacting to the comment with a thumbs-up. The requester knows what they're trying to say, and they should decide if the changes get made.

A commit has replaced all accent to a weid char `C)`

See this commit https://github.com/marmelab/marmelab.github.io/pull/156/commits/1887f6219cd0629552ce4eea01d80410f9513917

Webhook payload

{
  "action": "created",
  "comment": {
    "url": "https://api.github.com/repos/marmelab/marmelab.github.io/pulls/comments/77782663",
    "id": 77782663,
    "diff_hunk": "@@ -0,0 +1,214 @@\n+---\n+layout: post\n+title: \"Puissance 4 multi-joueur : retour d'expérience\"\n+excerpt: \"Première semaine parmi les équipes marmelab, premier challenge de la période d'intégration, 4 jours pour mettre au point un serveur de jeu puissance 4.\"\n+image: /images/blog/connect-four-small.png\n+author: <a href=\"https://github.com/floo51\">Florian</a>\n+tags:\n+- PHP\n+- symfony\n+- doctrine\n+---\n+\n+Première semaine parmi les équipes marmelab, premier challenge de la période d'intégration, 4 jours pour mettre au point un serveur de jeu puissance 4.\n+\n+Le sujet : 2 joueurs se connectent sur un site web et se rejoignent pour une partie de puissance 4. A tour de rôle, ils déposent un pion jusqu'à ce que l'un des deux gagne ou que le plateau soit rempli. Les technos : PHP7, Symfony 3.\n+\n+<img src=\"/images/blog/connect-four-big.png\" class=\"responsive\" />\n+\n+Les objectifs ? Se familiariser avec les méthodes et les technologies marmelab en soumettant son travail à l'avis de ses pairs.\n+\n+Qu'en ai-je retenu...\n+\n+## L'art de la sémantique\n+\n+> _[Définition](https://fr.wikipedia.org/wiki/S%C3%A9mantique):\n+La sémantique est une branche de la linguistique qui étudie les signifiés, ce dont on parle, ce que l'on veut énoncer. Sa branche symétrique, la syntaxe, concerne pour sa part le signifiant, sa forme, sa langue, sa graphie, sa grammaire, etc ; c'est la forme de l'énoncé._\n+\n+Ou pour faire plus simple et remettre en contexte, la sémantique est le fait de trouver le meilleur mot permettant de décrire un concept avec aussi peu d'ambiguïté que possible.\n+\n+Utiliser le langage le plus naturel possible et des termes au plus proche du réel permet de comprendre les liens entres nos objets et les concepts fonctionnels qu'ils nous servent à manipuler. Les commentaires deviennent alors superflux et le code se documente par lui-même.\n+\n+```diff\n+class Board\n+{\n+    const COLUMNS = 7;\n+    const ROWS = 6;\n+\n++   private $cells;\n+-   private $discs;\n+\n+    public function __construct()\n+    {\n+        $this->initializeCells();\n+    }\n+```\n+\n+Dans le modèle initial, le plateau de jeu contenait un tableau de pions (`discs`) puis, suite à un refactoring, une matrice de cellule; chaque cellule pouvant contenir un pion ou être vide.\n+\n+Lors d'un tel refactoring remettant en cause la signification d'un modèle de données, il est essentiel d'également considérer un refactoring sémantique.\n+Le nom `discs` n'est plus du tout adapté à ce que le concept représente, il pourrait donc être mal interprété par un futur développeur et amener à compromettre la maintenabilité générale du projet.\n+\n+## Best practices\n+\n+### Conventions & consistence",
    "path": "blog/_posts/2016-09-02-puissance-4-retour-experience.md",
    "position": 54,
    "original_position": 54,
    "commit_id": "44480e191b2f8fea904a17021f204a87323b3552",
    "original_commit_id": "44480e191b2f8fea904a17021f204a87323b3552",
    "user": {
      "login": "fzaninotto",
      "id": 99944,
      "avatar_url": "https://avatars.githubusercontent.com/u/99944?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/fzaninotto",
      "html_url": "https://github.com/fzaninotto",
      "followers_url": "https://api.github.com/users/fzaninotto/followers",
      "following_url": "https://api.github.com/users/fzaninotto/following{/other_user}",
      "gists_url": "https://api.github.com/users/fzaninotto/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/fzaninotto/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/fzaninotto/subscriptions",
      "organizations_url": "https://api.github.com/users/fzaninotto/orgs",
      "repos_url": "https://api.github.com/users/fzaninotto/repos",
      "events_url": "https://api.github.com/users/fzaninotto/events{/privacy}",
      "received_events_url": "https://api.github.com/users/fzaninotto/received_events",
      "type": "User",
      "site_admin": false
    },
    "body": "s/consistence/cohérence/",
    "created_at": "2016-09-07T08:50:56Z",
    "updated_at": "2016-09-07T08:50:56Z",
    "html_url": "https://github.com/marmelab/marmelab.github.io/pull/156#discussion_r77782663",
    "pull_request_url": "https://api.github.com/repos/marmelab/marmelab.github.io/pulls/156",
    "_links": {
      "self": {
        "href": "https://api.github.com/repos/marmelab/marmelab.github.io/pulls/comments/77782663"
      },
      "html": {
        "href": "https://github.com/marmelab/marmelab.github.io/pull/156#discussion_r77782663"
      },
      "pull_request": {
        "href": "https://api.github.com/repos/marmelab/marmelab.github.io/pulls/156"
      }
    }
  },
  "pull_request": {
    "url": "https://api.github.com/repos/marmelab/marmelab.github.io/pulls/156",
    "id": 83807210,
    "html_url": "https://github.com/marmelab/marmelab.github.io/pull/156",
    "diff_url": "https://github.com/marmelab/marmelab.github.io/pull/156.diff",
    "patch_url": "https://github.com/marmelab/marmelab.github.io/pull/156.patch",
    "issue_url": "https://api.github.com/repos/marmelab/marmelab.github.io/issues/156",
    "number": 156,
    "state": "open",
    "locked": false,
    "title": "[RFR] Add connect four article",
    "user": {
      "login": "floo51",
      "id": 2562270,
      "avatar_url": "https://avatars.githubusercontent.com/u/2562270?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/floo51",
      "html_url": "https://github.com/floo51",
      "followers_url": "https://api.github.com/users/floo51/followers",
      "following_url": "https://api.github.com/users/floo51/following{/other_user}",
      "gists_url": "https://api.github.com/users/floo51/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/floo51/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/floo51/subscriptions",
      "organizations_url": "https://api.github.com/users/floo51/orgs",
      "repos_url": "https://api.github.com/users/floo51/repos",
      "events_url": "https://api.github.com/users/floo51/events{/privacy}",
      "received_events_url": "https://api.github.com/users/floo51/received_events",
      "type": "User",
      "site_admin": false
    },
    "body": "- [x] Header\r\n- [x] Outline\r\n- [x] §1 : L'art du nommage\r\n- [x] §2 : Best practices\r\n- [x] §3 : Temps réel\r\n- [x] §4 : Conclusion",
    "created_at": "2016-09-02T14:05:16Z",
    "updated_at": "2016-09-07T08:50:56Z",
    "closed_at": null,
    "merged_at": null,
    "merge_commit_sha": "af4433e7169f9ba68de2354ce4450990bd4ed91e",
    "assignee": null,
    "assignees": [

    ],
    "milestone": null,
    "commits_url": "https://api.github.com/repos/marmelab/marmelab.github.io/pulls/156/commits",
    "review_comments_url": "https://api.github.com/repos/marmelab/marmelab.github.io/pulls/156/comments",
    "review_comment_url": "https://api.github.com/repos/marmelab/marmelab.github.io/pulls/comments{/number}",
    "comments_url": "https://api.github.com/repos/marmelab/marmelab.github.io/issues/156/comments",
    "statuses_url": "https://api.github.com/repos/marmelab/marmelab.github.io/statuses/44480e191b2f8fea904a17021f204a87323b3552",
    "head": {
      "label": "marmelab:connect_four",
      "ref": "connect_four",
      "sha": "44480e191b2f8fea904a17021f204a87323b3552",
      "user": {
        "login": "marmelab",
        "id": 3116319,
        "avatar_url": "https://avatars.githubusercontent.com/u/3116319?v=3",
        "gravatar_id": "",
        "url": "https://api.github.com/users/marmelab",
        "html_url": "https://github.com/marmelab",
        "followers_url": "https://api.github.com/users/marmelab/followers",
        "following_url": "https://api.github.com/users/marmelab/following{/other_user}",
        "gists_url": "https://api.github.com/users/marmelab/gists{/gist_id}",
        "starred_url": "https://api.github.com/users/marmelab/starred{/owner}{/repo}",
        "subscriptions_url": "https://api.github.com/users/marmelab/subscriptions",
        "organizations_url": "https://api.github.com/users/marmelab/orgs",
        "repos_url": "https://api.github.com/users/marmelab/repos",
        "events_url": "https://api.github.com/users/marmelab/events{/privacy}",
        "received_events_url": "https://api.github.com/users/marmelab/received_events",
        "type": "Organization",
        "site_admin": false
      },
      "repo": {
        "id": 13563896,
        "name": "marmelab.github.io",
        "full_name": "marmelab/marmelab.github.io",
        "owner": {
          "login": "marmelab",
          "id": 3116319,
          "avatar_url": "https://avatars.githubusercontent.com/u/3116319?v=3",
          "gravatar_id": "",
          "url": "https://api.github.com/users/marmelab",
          "html_url": "https://github.com/marmelab",
          "followers_url": "https://api.github.com/users/marmelab/followers",
          "following_url": "https://api.github.com/users/marmelab/following{/other_user}",
          "gists_url": "https://api.github.com/users/marmelab/gists{/gist_id}",
          "starred_url": "https://api.github.com/users/marmelab/starred{/owner}{/repo}",
          "subscriptions_url": "https://api.github.com/users/marmelab/subscriptions",
          "organizations_url": "https://api.github.com/users/marmelab/orgs",
          "repos_url": "https://api.github.com/users/marmelab/repos",
          "events_url": "https://api.github.com/users/marmelab/events{/privacy}",
          "received_events_url": "https://api.github.com/users/marmelab/received_events",
          "type": "Organization",
          "site_admin": false
        },
        "private": true,
        "html_url": "https://github.com/marmelab/marmelab.github.io",
        "description": "marmelab.com website",
        "fork": false,
        "url": "https://api.github.com/repos/marmelab/marmelab.github.io",
        "forks_url": "https://api.github.com/repos/marmelab/marmelab.github.io/forks",
        "keys_url": "https://api.github.com/repos/marmelab/marmelab.github.io/keys{/key_id}",
        "collaborators_url": "https://api.github.com/repos/marmelab/marmelab.github.io/collaborators{/collaborator}",
        "teams_url": "https://api.github.com/repos/marmelab/marmelab.github.io/teams",
        "hooks_url": "https://api.github.com/repos/marmelab/marmelab.github.io/hooks",
        "issue_events_url": "https://api.github.com/repos/marmelab/marmelab.github.io/issues/events{/number}",
        "events_url": "https://api.github.com/repos/marmelab/marmelab.github.io/events",
        "assignees_url": "https://api.github.com/repos/marmelab/marmelab.github.io/assignees{/user}",
        "branches_url": "https://api.github.com/repos/marmelab/marmelab.github.io/branches{/branch}",
        "tags_url": "https://api.github.com/repos/marmelab/marmelab.github.io/tags",
        "blobs_url": "https://api.github.com/repos/marmelab/marmelab.github.io/git/blobs{/sha}",
        "git_tags_url": "https://api.github.com/repos/marmelab/marmelab.github.io/git/tags{/sha}",
        "git_refs_url": "https://api.github.com/repos/marmelab/marmelab.github.io/git/refs{/sha}",
        "trees_url": "https://api.github.com/repos/marmelab/marmelab.github.io/git/trees{/sha}",
        "statuses_url": "https://api.github.com/repos/marmelab/marmelab.github.io/statuses/{sha}",
        "languages_url": "https://api.github.com/repos/marmelab/marmelab.github.io/languages",
        "stargazers_url": "https://api.github.com/repos/marmelab/marmelab.github.io/stargazers",
        "contributors_url": "https://api.github.com/repos/marmelab/marmelab.github.io/contributors",
        "subscribers_url": "https://api.github.com/repos/marmelab/marmelab.github.io/subscribers",
        "subscription_url": "https://api.github.com/repos/marmelab/marmelab.github.io/subscription",
        "commits_url": "https://api.github.com/repos/marmelab/marmelab.github.io/commits{/sha}",
        "git_commits_url": "https://api.github.com/repos/marmelab/marmelab.github.io/git/commits{/sha}",
        "comments_url": "https://api.github.com/repos/marmelab/marmelab.github.io/comments{/number}",
        "issue_comment_url": "https://api.github.com/repos/marmelab/marmelab.github.io/issues/comments{/number}",
        "contents_url": "https://api.github.com/repos/marmelab/marmelab.github.io/contents/{+path}",
        "compare_url": "https://api.github.com/repos/marmelab/marmelab.github.io/compare/{base}...{head}",
        "merges_url": "https://api.github.com/repos/marmelab/marmelab.github.io/merges",
        "archive_url": "https://api.github.com/repos/marmelab/marmelab.github.io/{archive_format}{/ref}",
        "downloads_url": "https://api.github.com/repos/marmelab/marmelab.github.io/downloads",
        "issues_url": "https://api.github.com/repos/marmelab/marmelab.github.io/issues{/number}",
        "pulls_url": "https://api.github.com/repos/marmelab/marmelab.github.io/pulls{/number}",
        "milestones_url": "https://api.github.com/repos/marmelab/marmelab.github.io/milestones{/number}",
        "notifications_url": "https://api.github.com/repos/marmelab/marmelab.github.io/notifications{?since,all,participating}",
        "labels_url": "https://api.github.com/repos/marmelab/marmelab.github.io/labels{/name}",
        "releases_url": "https://api.github.com/repos/marmelab/marmelab.github.io/releases{/id}",
        "deployments_url": "https://api.github.com/repos/marmelab/marmelab.github.io/deployments",
        "created_at": "2013-10-14T14:41:40Z",
        "updated_at": "2016-03-09T08:16:34Z",
        "pushed_at": "2016-09-07T08:45:28Z",
        "git_url": "git://github.com/marmelab/marmelab.github.io.git",
        "ssh_url": "[email protected]:marmelab/marmelab.github.io.git",
        "clone_url": "https://github.com/marmelab/marmelab.github.io.git",
        "svn_url": "https://github.com/marmelab/marmelab.github.io",
        "homepage": "marmelab.com",
        "size": 63165,
        "stargazers_count": 2,
        "watchers_count": 2,
        "language": "HTML",
        "has_issues": true,
        "has_downloads": true,
        "has_wiki": true,
        "has_pages": true,
        "forks_count": 0,
        "mirror_url": null,
        "open_issues_count": 8,
        "forks": 0,
        "open_issues": 8,
        "watchers": 2,
        "default_branch": "master"
      }
    },
    "base": {
      "label": "marmelab:master",
      "ref": "master",
      "sha": "a381505e838eece479fb149dc09860d7d9a1e527",
      "user": {
        "login": "marmelab",
        "id": 3116319,
        "avatar_url": "https://avatars.githubusercontent.com/u/3116319?v=3",
        "gravatar_id": "",
        "url": "https://api.github.com/users/marmelab",
        "html_url": "https://github.com/marmelab",
        "followers_url": "https://api.github.com/users/marmelab/followers",
        "following_url": "https://api.github.com/users/marmelab/following{/other_user}",
        "gists_url": "https://api.github.com/users/marmelab/gists{/gist_id}",
        "starred_url": "https://api.github.com/users/marmelab/starred{/owner}{/repo}",
        "subscriptions_url": "https://api.github.com/users/marmelab/subscriptions",
        "organizations_url": "https://api.github.com/users/marmelab/orgs",
        "repos_url": "https://api.github.com/users/marmelab/repos",
        "events_url": "https://api.github.com/users/marmelab/events{/privacy}",
        "received_events_url": "https://api.github.com/users/marmelab/received_events",
        "type": "Organization",
        "site_admin": false
      },
      "repo": {
        "id": 13563896,
        "name": "marmelab.github.io",
        "full_name": "marmelab/marmelab.github.io",
        "owner": {
          "login": "marmelab",
          "id": 3116319,
          "avatar_url": "https://avatars.githubusercontent.com/u/3116319?v=3",
          "gravatar_id": "",
          "url": "https://api.github.com/users/marmelab",
          "html_url": "https://github.com/marmelab",
          "followers_url": "https://api.github.com/users/marmelab/followers",
          "following_url": "https://api.github.com/users/marmelab/following{/other_user}",
          "gists_url": "https://api.github.com/users/marmelab/gists{/gist_id}",
          "starred_url": "https://api.github.com/users/marmelab/starred{/owner}{/repo}",
          "subscriptions_url": "https://api.github.com/users/marmelab/subscriptions",
          "organizations_url": "https://api.github.com/users/marmelab/orgs",
          "repos_url": "https://api.github.com/users/marmelab/repos",
          "events_url": "https://api.github.com/users/marmelab/events{/privacy}",
          "received_events_url": "https://api.github.com/users/marmelab/received_events",
          "type": "Organization",
          "site_admin": false
        },
        "private": true,
        "html_url": "https://github.com/marmelab/marmelab.github.io",
        "description": "marmelab.com website",
        "fork": false,
        "url": "https://api.github.com/repos/marmelab/marmelab.github.io",
        "forks_url": "https://api.github.com/repos/marmelab/marmelab.github.io/forks",
        "keys_url": "https://api.github.com/repos/marmelab/marmelab.github.io/keys{/key_id}",
        "collaborators_url": "https://api.github.com/repos/marmelab/marmelab.github.io/collaborators{/collaborator}",
        "teams_url": "https://api.github.com/repos/marmelab/marmelab.github.io/teams",
        "hooks_url": "https://api.github.com/repos/marmelab/marmelab.github.io/hooks",
        "issue_events_url": "https://api.github.com/repos/marmelab/marmelab.github.io/issues/events{/number}",
        "events_url": "https://api.github.com/repos/marmelab/marmelab.github.io/events",
        "assignees_url": "https://api.github.com/repos/marmelab/marmelab.github.io/assignees{/user}",
        "branches_url": "https://api.github.com/repos/marmelab/marmelab.github.io/branches{/branch}",
        "tags_url": "https://api.github.com/repos/marmelab/marmelab.github.io/tags",
        "blobs_url": "https://api.github.com/repos/marmelab/marmelab.github.io/git/blobs{/sha}",
        "git_tags_url": "https://api.github.com/repos/marmelab/marmelab.github.io/git/tags{/sha}",
        "git_refs_url": "https://api.github.com/repos/marmelab/marmelab.github.io/git/refs{/sha}",
        "trees_url": "https://api.github.com/repos/marmelab/marmelab.github.io/git/trees{/sha}",
        "statuses_url": "https://api.github.com/repos/marmelab/marmelab.github.io/statuses/{sha}",
        "languages_url": "https://api.github.com/repos/marmelab/marmelab.github.io/languages",
        "stargazers_url": "https://api.github.com/repos/marmelab/marmelab.github.io/stargazers",
        "contributors_url": "https://api.github.com/repos/marmelab/marmelab.github.io/contributors",
        "subscribers_url": "https://api.github.com/repos/marmelab/marmelab.github.io/subscribers",
        "subscription_url": "https://api.github.com/repos/marmelab/marmelab.github.io/subscription",
        "commits_url": "https://api.github.com/repos/marmelab/marmelab.github.io/commits{/sha}",
        "git_commits_url": "https://api.github.com/repos/marmelab/marmelab.github.io/git/commits{/sha}",
        "comments_url": "https://api.github.com/repos/marmelab/marmelab.github.io/comments{/number}",
        "issue_comment_url": "https://api.github.com/repos/marmelab/marmelab.github.io/issues/comments{/number}",
        "contents_url": "https://api.github.com/repos/marmelab/marmelab.github.io/contents/{+path}",
        "compare_url": "https://api.github.com/repos/marmelab/marmelab.github.io/compare/{base}...{head}",
        "merges_url": "https://api.github.com/repos/marmelab/marmelab.github.io/merges",
        "archive_url": "https://api.github.com/repos/marmelab/marmelab.github.io/{archive_format}{/ref}",
        "downloads_url": "https://api.github.com/repos/marmelab/marmelab.github.io/downloads",
        "issues_url": "https://api.github.com/repos/marmelab/marmelab.github.io/issues{/number}",
        "pulls_url": "https://api.github.com/repos/marmelab/marmelab.github.io/pulls{/number}",
        "milestones_url": "https://api.github.com/repos/marmelab/marmelab.github.io/milestones{/number}",
        "notifications_url": "https://api.github.com/repos/marmelab/marmelab.github.io/notifications{?since,all,participating}",
        "labels_url": "https://api.github.com/repos/marmelab/marmelab.github.io/labels{/name}",
        "releases_url": "https://api.github.com/repos/marmelab/marmelab.github.io/releases{/id}",
        "deployments_url": "https://api.github.com/repos/marmelab/marmelab.github.io/deployments",
        "created_at": "2013-10-14T14:41:40Z",
        "updated_at": "2016-03-09T08:16:34Z",
        "pushed_at": "2016-09-07T08:45:28Z",
        "git_url": "git://github.com/marmelab/marmelab.github.io.git",
        "ssh_url": "[email protected]:marmelab/marmelab.github.io.git",
        "clone_url": "https://github.com/marmelab/marmelab.github.io.git",
        "svn_url": "https://github.com/marmelab/marmelab.github.io",
        "homepage": "marmelab.com",
        "size": 63165,
        "stargazers_count": 2,
        "watchers_count": 2,
        "language": "HTML",
        "has_issues": true,
        "has_downloads": true,
        "has_wiki": true,
        "has_pages": true,
        "forks_count": 0,
        "mirror_url": null,
        "open_issues_count": 8,
        "forks": 0,
        "open_issues": 8,
        "watchers": 2,
        "default_branch": "master"
      }
    },
    "_links": {
      "self": {
        "href": "https://api.github.com/repos/marmelab/marmelab.github.io/pulls/156"
      },
      "html": {
        "href": "https://github.com/marmelab/marmelab.github.io/pull/156"
      },
      "issue": {
        "href": "https://api.github.com/repos/marmelab/marmelab.github.io/issues/156"
      },
      "comments": {
        "href": "https://api.github.com/repos/marmelab/marmelab.github.io/issues/156/comments"
      },
      "review_comments": {
        "href": "https://api.github.com/repos/marmelab/marmelab.github.io/pulls/156/comments"
      },
      "review_comment": {
        "href": "https://api.github.com/repos/marmelab/marmelab.github.io/pulls/comments{/number}"
      },
      "commits": {
        "href": "https://api.github.com/repos/marmelab/marmelab.github.io/pulls/156/commits"
      },
      "statuses": {
        "href": "https://api.github.com/repos/marmelab/marmelab.github.io/statuses/44480e191b2f8fea904a17021f204a87323b3552"
      }
    }
  },
  "repository": {
    "id": 13563896,
    "name": "marmelab.github.io",
    "full_name": "marmelab/marmelab.github.io",
    "owner": {
      "login": "marmelab",
      "id": 3116319,
      "avatar_url": "https://avatars.githubusercontent.com/u/3116319?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/marmelab",
      "html_url": "https://github.com/marmelab",
      "followers_url": "https://api.github.com/users/marmelab/followers",
      "following_url": "https://api.github.com/users/marmelab/following{/other_user}",
      "gists_url": "https://api.github.com/users/marmelab/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/marmelab/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/marmelab/subscriptions",
      "organizations_url": "https://api.github.com/users/marmelab/orgs",
      "repos_url": "https://api.github.com/users/marmelab/repos",
      "events_url": "https://api.github.com/users/marmelab/events{/privacy}",
      "received_events_url": "https://api.github.com/users/marmelab/received_events",
      "type": "Organization",
      "site_admin": false
    },
    "private": true,
    "html_url": "https://github.com/marmelab/marmelab.github.io",
    "description": "marmelab.com website",
    "fork": false,
    "url": "https://api.github.com/repos/marmelab/marmelab.github.io",
    "forks_url": "https://api.github.com/repos/marmelab/marmelab.github.io/forks",
    "keys_url": "https://api.github.com/repos/marmelab/marmelab.github.io/keys{/key_id}",
    "collaborators_url": "https://api.github.com/repos/marmelab/marmelab.github.io/collaborators{/collaborator}",
    "teams_url": "https://api.github.com/repos/marmelab/marmelab.github.io/teams",
    "hooks_url": "https://api.github.com/repos/marmelab/marmelab.github.io/hooks",
    "issue_events_url": "https://api.github.com/repos/marmelab/marmelab.github.io/issues/events{/number}",
    "events_url": "https://api.github.com/repos/marmelab/marmelab.github.io/events",
    "assignees_url": "https://api.github.com/repos/marmelab/marmelab.github.io/assignees{/user}",
    "branches_url": "https://api.github.com/repos/marmelab/marmelab.github.io/branches{/branch}",
    "tags_url": "https://api.github.com/repos/marmelab/marmelab.github.io/tags",
    "blobs_url": "https://api.github.com/repos/marmelab/marmelab.github.io/git/blobs{/sha}",
    "git_tags_url": "https://api.github.com/repos/marmelab/marmelab.github.io/git/tags{/sha}",
    "git_refs_url": "https://api.github.com/repos/marmelab/marmelab.github.io/git/refs{/sha}",
    "trees_url": "https://api.github.com/repos/marmelab/marmelab.github.io/git/trees{/sha}",
    "statuses_url": "https://api.github.com/repos/marmelab/marmelab.github.io/statuses/{sha}",
    "languages_url": "https://api.github.com/repos/marmelab/marmelab.github.io/languages",
    "stargazers_url": "https://api.github.com/repos/marmelab/marmelab.github.io/stargazers",
    "contributors_url": "https://api.github.com/repos/marmelab/marmelab.github.io/contributors",
    "subscribers_url": "https://api.github.com/repos/marmelab/marmelab.github.io/subscribers",
    "subscription_url": "https://api.github.com/repos/marmelab/marmelab.github.io/subscription",
    "commits_url": "https://api.github.com/repos/marmelab/marmelab.github.io/commits{/sha}",
    "git_commits_url": "https://api.github.com/repos/marmelab/marmelab.github.io/git/commits{/sha}",
    "comments_url": "https://api.github.com/repos/marmelab/marmelab.github.io/comments{/number}",
    "issue_comment_url": "https://api.github.com/repos/marmelab/marmelab.github.io/issues/comments{/number}",
    "contents_url": "https://api.github.com/repos/marmelab/marmelab.github.io/contents/{+path}",
    "compare_url": "https://api.github.com/repos/marmelab/marmelab.github.io/compare/{base}...{head}",
    "merges_url": "https://api.github.com/repos/marmelab/marmelab.github.io/merges",
    "archive_url": "https://api.github.com/repos/marmelab/marmelab.github.io/{archive_format}{/ref}",
    "downloads_url": "https://api.github.com/repos/marmelab/marmelab.github.io/downloads",
    "issues_url": "https://api.github.com/repos/marmelab/marmelab.github.io/issues{/number}",
    "pulls_url": "https://api.github.com/repos/marmelab/marmelab.github.io/pulls{/number}",
    "milestones_url": "https://api.github.com/repos/marmelab/marmelab.github.io/milestones{/number}",
    "notifications_url": "https://api.github.com/repos/marmelab/marmelab.github.io/notifications{?since,all,participating}",
    "labels_url": "https://api.github.com/repos/marmelab/marmelab.github.io/labels{/name}",
    "releases_url": "https://api.github.com/repos/marmelab/marmelab.github.io/releases{/id}",
    "deployments_url": "https://api.github.com/repos/marmelab/marmelab.github.io/deployments",
    "created_at": "2013-10-14T14:41:40Z",
    "updated_at": "2016-03-09T08:16:34Z",
    "pushed_at": "2016-09-07T08:45:28Z",
    "git_url": "git://github.com/marmelab/marmelab.github.io.git",
    "ssh_url": "[email protected]:marmelab/marmelab.github.io.git",
    "clone_url": "https://github.com/marmelab/marmelab.github.io.git",
    "svn_url": "https://github.com/marmelab/marmelab.github.io",
    "homepage": "marmelab.com",
    "size": 63165,
    "stargazers_count": 2,
    "watchers_count": 2,
    "language": "HTML",
    "has_issues": true,
    "has_downloads": true,
    "has_wiki": true,
    "has_pages": true,
    "forks_count": 0,
    "mirror_url": null,
    "open_issues_count": 8,
    "forks": 0,
    "open_issues": 8,
    "watchers": 2,
    "default_branch": "master"
  },
  "organization": {
    "login": "marmelab",
    "id": 3116319,
    "url": "https://api.github.com/orgs/marmelab",
    "repos_url": "https://api.github.com/orgs/marmelab/repos",
    "events_url": "https://api.github.com/orgs/marmelab/events",
    "hooks_url": "https://api.github.com/orgs/marmelab/hooks",
    "issues_url": "https://api.github.com/orgs/marmelab/issues",
    "members_url": "https://api.github.com/orgs/marmelab/members{/member}",
    "public_members_url": "https://api.github.com/orgs/marmelab/public_members{/member}",
    "avatar_url": "https://avatars.githubusercontent.com/u/3116319?v=3",
    "description": null
  },
  "sender": {
    "login": "fzaninotto",
    "id": 99944,
    "avatar_url": "https://avatars.githubusercontent.com/u/99944?v=3",
    "gravatar_id": "",
    "url": "https://api.github.com/users/fzaninotto",
    "html_url": "https://github.com/fzaninotto",
    "followers_url": "https://api.github.com/users/fzaninotto/followers",
    "following_url": "https://api.github.com/users/fzaninotto/following{/other_user}",
    "gists_url": "https://api.github.com/users/fzaninotto/gists{/gist_id}",
    "starred_url": "https://api.github.com/users/fzaninotto/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/fzaninotto/subscriptions",
    "organizations_url": "https://api.github.com/users/fzaninotto/orgs",
    "repos_url": "https://api.github.com/users/fzaninotto/repos",
    "events_url": "https://api.github.com/users/fzaninotto/events{/privacy}",
    "received_events_url": "https://api.github.com/users/fzaninotto/received_events",
    "type": "User",
    "site_admin": false
  }
}

Improve/remove bot comment

image

No need to @-quote the author. I even wonder if there is a need to comment at all, since GitHub now notifies of commits. In an ideal world, the bot would comment to say that all demands were dealt with, but until then, I think you can remove the comments.

You'd better work on a better commit message:

image

I'd prefer something like

Typo fix s/previous/the previous/

As requested by @fzaninotto on #153 (comment)

Diff parser error

Description

@jpetitcolas really is the nemesis of Sedy.

Additional informations

Inefficient diff parser error
{
    hunk: '@@ -1,3 +1,13 @@\n+---\n+layout: post\n+title: "Les générateurs"\n+excerpt: "Les générateurs sont une fonctionnalité introduite dans es6 qui permet de créer des fonctions spéciales avec la capacité de mettre en pause leur éxécution en retournant un résultat intermédiaire."\n+author: <a href="https://github.com/ThieryMichel">Thiery Michel</a>\n+tags:\n+- es6\n+- generator\n+---\n+\n # Les générateurs\n \n ## Que sont les générateurs',
    position: null
}

TODO

  • Do not throw an error or try/catch the error to let other commits to be pushed
  • Log the related comment too
  • See why GitHub do not sent a position this time

Poorly parsed GitHub's diff

GitHub return a specific format for diff hunk application/vnd.github.v3.diff which is currently poorly parsed.
More info about GitHub's diff in the documentation: https://developer.github.com/v3/pulls/comments/#input

Also, the position should not be null. See the documentation too: https://developer.github.com/v3/pulls/comments/#list-comments-on-a-pull-request

Failure case

sed: s/convert canvas/convert the canvas/
position: null
diff hunk:

@@ -0,0 +1,202 @@\n+---\r\n+layout: post\r\n+title: Taking Picture From Webcam Using Canvas\r\n+excerpt: "Taking a picture from a browser using the webcam is not trivial as it may seem. It requires a low supported API and some canvas manipulation. Here is the missing how-to."\r\n+image: /images/blog/webcam.jpg\r\n+author: <a href="http://www.jonathan-petitcolas.com">Jonathan Petitcolas</a>\r\n+canonical: https://www.jonathan-petitcolas.com/2016/08/24/taking-picture-from-webcam-using-canvas.html\r\n+tags:\r\n+- canvas\r\n+- webcam\r\n+---\r\n+\r\n+**Notice:** this post may ask your authorization to use your webcam. This is due to\r\n+live samples embedded in this post.\r\n+\r\n+<figure>\r\n+\t<img class="responsive" src="/images/blog/webcam.jpg" alt="Webcam, by David Burillo" title="Webcam, by David Burillo" />\r\n+ <figcaption>\r\n+ <a href="https://www.flickr.com/photos/dgbury/5695679595/in/photolist-9FiR7k-98et2a-98etvR-98hBZ9-6Ed5wT-ohM1Ua-9AMe8t-99gMt-4EtoSE-91enR6-aCLhA-71vCP-93Mxqn-59WYvo-71vAt-3mwzw-7DapU-7NDuqJ-aceHr-6cGRyB-4QK9Ed-4SFKp-33532-R93tf-9AcPZV-6KuEf-o1NMBf-551kGR-oxedo5-ozefa5-ohLnLV-ohL95C-ohL96E-ohL94A-oxedno-ozg5uc-miKhC-4QK9DY-moxg4g-62xZ8c-8gpDB-TY7Ry-vRtD4-5QzXBV-8zNSb-5QEdXL-9muvC-4iLMqg-dtKJqc-e1gAy3">\r\n+ Webcam, by David Burillo\r\n+ </a>\r\n+ </figcaption>\r\n+</figure>\r\n+\r\n+I recently needed to take a picture from a web browser using my webcam. As this is\r\n+a basic need, I thought it would be quite easy. Yet, solution is not trivial, and\r\n+implies both using new user media HTML5 API and some canvas manipulation. Here is\r\n+a reminder which may be useful to everyone.\r\n+\r\n+## Displaying Webcam Stream in Browser\r\n+\r\n+First step is to display the webcam stream into the browser. It is easily done using\r\n+the `getUserMedia` HTML5 API. [Support is quite limited](http://caniuse.com/#search=getUserMedia)\r\n+(neither supported on Safari / iOS, nor on IE, but supported on Edge, Firefox and\r\n+Chrome). A solution for oldest browsers is to fallback on a Flash solution. However,\r\n+it won\'t be fixed on mobiles, and we would need to use an extra framework such\r\n+as [PhoneGap](http://phonegap.com/) in this case.\r\n+\r\n+As dealing with fallback would be quite cumbersome, and as we don\'t want to write\r\n+some ugly prefixed code such as:\r\n+\r\n+``` js\r\n+const getUserMedia = navigator.getUserMedia\r\n+ || navigator.webkitGetUserMedia\r\n+ || navigator.mozGetUserMedia\r\n+ || navigator.msGetUserMedia;\r\n+```\r\n+\r\n+We are going to use a polyfill written by [@addyosmani](https://www.twitter.com/addyosmani):\r\n+[getUserMedia.js](https://github.com/addyosmani/getUserMedia.js/). It uses either the\r\n+native implementation or Flash fallback depending of browser support. Exactly what\r\n+we need.\r\n+\r\n+First, let\'s install it (I\'m using Webpack, hence the `save-dev`):\r\n+\r\n+``` sh\r\n+npm install --save-dev getusermedia-js\r\n+```\r\n+\r\n+Let\'s now initialize a video stream and display it in the browser using the\r\n+freshly installed package:\r\n+\r\n+``` js\r\n+import { getUserMedia } from \'getusermedia-js\';\r\n+\r\n+getUserMedia({\r\n+ video: true,\r\n+ audio: false,\r\n+ width: 640,\r\n+ height: 480,\r\n+ el: \'stream\', // render live video in #stream\r\n+ swffile: require(\'getusermedia-js/dist/fallback/jscam_canvas_only.swf\'),\r\n+}, stream => {\r\n+ const video = document.querySelector(\'#stream video\');\r\n+ video.src = window.URL.createObjectURL(stream);\r\n+ video.play();\r\n+}, err => console.error(err));\r\n+```\r\n+\r\n+We start by calling the `getUserMedia` polyfill, specifying it we don\'t care about\r\n+audio, the preview video dimensions, and where to insert it (in the `#stream` element).\r\n+We also specify the path to our Flash fallback (included in the lib). I didn\'t test\r\n+it as all my installed browsers support this feature, but it should work this way.\r\n+\r\n+Note that if we don\'t use any module bundler, we need to replace the `require` call\r\n+by the path of the fallback.\r\n+\r\n+Second and third arguments are respectively success and error callbacks. Let\'s focus\r\n+on the success handler, as we just log errors in case of failure. Once we get the webcam\r\n+stream, we point the `video` tag to its URL, retrieved using the `URL.createObjectURL`\r\n+method. We should not forget to call the `play` method on our video to prevent\r\n+from being stuck at the first frame.\r\n+\r\n+At this step, we are able to display our webcam stream:\r\n+\r\n+<div class=\'embed-container\' style="padding-bottom: 35rem;">\r\n+ <iframe src="https://www.jonathan-petitcolas.com/labs/webcam-picture/webcam-stream/index.html" height="580" frameborder="0" allowfullscreen></iframe>\r\n+</div>\r\n+\r\n+## Taking a Picture using Canvas and Live Webcam Stream\r\n+\r\n+Now, we need to isolate a single frame into a picture. Principle is not trivial: we need\r\n+to add a `canvas` element to our page, set the canvas content to current video frame,\r\n+and then convert canvas content to data URL.\r

sed: s/have been just/has just been/
position: null
diff hunk:

@@ -0,0 +1,202 @@\n+---\r\n+layout: post\r\n+title: Taking Picture From Webcam Using Canvas\r\n+excerpt: "Taking a picture from a browser using the webcam is not trivial as it may seem. It requires a low supported API and some canvas manipulation. Here is the missing how-to."\r\n+image: /images/blog/webcam.jpg\r\n+author: <a href="http://www.jonathan-petitcolas.com">Jonathan Petitcolas</a>\r\n+canonical: https://www.jonathan-petitcolas.com/2016/08/24/taking-picture-from-webcam-using-canvas.html\r\n+tags:\r\n+- canvas\r\n+- webcam\r\n+---\r\n+\r\n+**Notice:** this post may ask your authorization to use your webcam. This is due to\r\n+live samples embedded in this post.\r\n+\r\n+<figure>\r\n+\t<img class="responsive" src="/images/blog/webcam.jpg" alt="Webcam, by David Burillo" title="Webcam, by David Burillo" />\r\n+ <figcaption>\r\n+ <a href="https://www.flickr.com/photos/dgbury/5695679595/in/photolist-9FiR7k-98et2a-98etvR-98hBZ9-6Ed5wT-ohM1Ua-9AMe8t-99gMt-4EtoSE-91enR6-aCLhA-71vCP-93Mxqn-59WYvo-71vAt-3mwzw-7DapU-7NDuqJ-aceHr-6cGRyB-4QK9Ed-4SFKp-33532-R93tf-9AcPZV-6KuEf-o1NMBf-551kGR-oxedo5-ozefa5-ohLnLV-ohL95C-ohL96E-ohL94A-oxedno-ozg5uc-miKhC-4QK9DY-moxg4g-62xZ8c-8gpDB-TY7Ry-vRtD4-5QzXBV-8zNSb-5QEdXL-9muvC-4iLMqg-dtKJqc-e1gAy3">\r\n+ Webcam, by David Burillo\r\n+ </a>\r\n+ </figcaption>\r\n+</figure>\r\n+\r\n+I recently needed to take a picture from a web browser using my webcam. As this is\r\n+a basic need, I thought it would be quite easy. Yet, solution is not trivial, and\r\n+implies both using new user media HTML5 API and some canvas manipulation. Here is\r\n+a reminder which may be useful to everyone.\r\n+\r\n+## Displaying Webcam Stream in Browser\r\n+\r\n+First step is to display the webcam stream into the browser. It is easily done using\r\n+the `getUserMedia` HTML5 API. [Support is quite limited](http://caniuse.com/#search=getUserMedia)\r\n+(neither supported on Safari / iOS, nor on IE, but supported on Edge, Firefox and\r\n+Chrome). A solution for oldest browsers is to fallback on a Flash solution. However,\r\n+it won\'t be fixed on mobiles, and we would need to use an extra framework such\r\n+as [PhoneGap](http://phonegap.com/) in this case.\r\n+\r\n+As dealing with fallback would be quite cumbersome, and as we don\'t want to write\r\n+some ugly prefixed code such as:\r\n+\r\n+``` js\r\n+const getUserMedia = navigator.getUserMedia\r\n+ || navigator.webkitGetUserMedia\r\n+ || navigator.mozGetUserMedia\r\n+ || navigator.msGetUserMedia;\r\n+```\r\n+\r\n+We are going to use a polyfill written by [@addyosmani](https://www.twitter.com/addyosmani):\r\n+[getUserMedia.js](https://github.com/addyosmani/getUserMedia.js/). It uses either the\r\n+native implementation or Flash fallback depending of browser support. Exactly what\r\n+we need.\r\n+\r\n+First, let\'s install it (I\'m using Webpack, hence the `save-dev`):\r\n+\r\n+``` sh\r\n+npm install --save-dev getusermedia-js\r\n+```\r\n+\r\n+Let\'s now initialize a video stream and display it in the browser using the\r\n+freshly installed package:\r\n+\r\n+``` js\r\n+import { getUserMedia } from \'getusermedia-js\';\r\n+\r\n+getUserMedia({\r\n+ video: true,\r\n+ audio: false,\r\n+ width: 640,\r\n+ height: 480,\r\n+ el: \'stream\', // render live video in #stream\r\n+ swffile: require(\'getusermedia-js/dist/fallback/jscam_canvas_only.swf\'),\r\n+}, stream => {\r\n+ const video = document.querySelector(\'#stream video\');\r\n+ video.src = window.URL.createObjectURL(stream);\r\n+ video.play();\r\n+}, err => console.error(err));\r\n+```\r\n+\r\n+We start by calling the `getUserMedia` polyfill, specifying it we don\'t care about\r\n+audio, the preview video dimensions, and where to insert it (in the `#stream` element).\r\n+We also specify the path to our Flash fallback (included in the lib). I didn\'t test\r\n+it as all my installed browsers support this feature, but it should work this way.\r\n+\r\n+Note that if we don\'t use any module bundler, we need to replace the `require` call\r\n+by the path of the fallback.\r\n+\r\n+Second and third arguments are respectively success and error callbacks. Let\'s focus\r\n+on the success handler, as we just log errors in case of failure. Once we get the webcam\r\n+stream, we point the `video` tag to its URL, retrieved using the `URL.createObjectURL`\r\n+method. We should not forget to call the `play` method on our video to prevent\r\n+from being stuck at the first frame.\r\n+\r\n+At this step, we are able to display our webcam stream:\r\n+\r\n+<div class=\'embed-container\' style="padding-bottom: 35rem;">\r\n+ <iframe src="https://www.jonathan-petitcolas.com/labs/webcam-picture/webcam-stream/index.html" height="580" frameborder="0" allowfullscreen></iframe>\r\n+</div>\r\n+\r\n+## Taking a Picture using Canvas and Live Webcam Stream\r\n+\r\n+Now, we need to isolate a single frame into a picture. Principle is not trivial: we need\r\n+to add a `canvas` element to our page, set the canvas content to current video frame,\r\n+and then convert canvas content to data URL.\r\n+\r\n+We update our HTML code to add a `Capture` button:\r\n+\r\n+``` xml\r\n+<div class="wrapper">\r\n+ <div id="stream"></div>\r\n+ <img id="grid" src="#"/>\r\n+ <p class="actions"><button id="capture">Capture</button></p>\r\n+</div>\r\n+```\r\n+We added an image used to display our snapped view once user has pressed the\r\n+capture button. As we don\'t have any image at initialization, we set the `src`\r\n+attribute to `#`. There is a lot of discussion about [how to set an image with no\r\n+src attribute](http://stackoverflow.com/questions/5775469/whats-the-valid-way-to-include-an-image-with-no-src/28077004#28077004).\r\n+I opted for the anchor `#` which triggers an extra request to current page, which\r\n+have been just downloaded and is still in cache. A very little overhead.\r

sed: s/and add/and added/
position: null
diff hunk:

@@ -0,0 +1,202 @@\n+---\r\n+layout: post\r\n+title: Taking Picture From Webcam Using Canvas\r\n+excerpt: "Taking a picture from a browser using the webcam is not trivial as it may seem. It requires a low supported API and some canvas manipulation. Here is the missing how-to."\r\n+image: /images/blog/webcam.jpg\r\n+author: <a href="http://www.jonathan-petitcolas.com">Jonathan Petitcolas</a>\r\n+canonical: https://www.jonathan-petitcolas.com/2016/08/24/taking-picture-from-webcam-using-canvas.html\r\n+tags:\r\n+- canvas\r\n+- webcam\r\n+---\r\n+\r\n+**Notice:** this post may ask your authorization to use your webcam. This is due to\r\n+live samples embedded in this post.\r\n+\r\n+<figure>\r\n+\t<img class="responsive" src="/images/blog/webcam.jpg" alt="Webcam, by David Burillo" title="Webcam, by David Burillo" />\r\n+ <figcaption>\r\n+ <a href="https://www.flickr.com/photos/dgbury/5695679595/in/photolist-9FiR7k-98et2a-98etvR-98hBZ9-6Ed5wT-ohM1Ua-9AMe8t-99gMt-4EtoSE-91enR6-aCLhA-71vCP-93Mxqn-59WYvo-71vAt-3mwzw-7DapU-7NDuqJ-aceHr-6cGRyB-4QK9Ed-4SFKp-33532-R93tf-9AcPZV-6KuEf-o1NMBf-551kGR-oxedo5-ozefa5-ohLnLV-ohL95C-ohL96E-ohL94A-oxedno-ozg5uc-miKhC-4QK9DY-moxg4g-62xZ8c-8gpDB-TY7Ry-vRtD4-5QzXBV-8zNSb-5QEdXL-9muvC-4iLMqg-dtKJqc-e1gAy3">\r\n+ Webcam, by David Burillo\r\n+ </a>\r\n+ </figcaption>\r\n+</figure>\r\n+\r\n+I recently needed to take a picture from a web browser using my webcam. As this is\r\n+a basic need, I thought it would be quite easy. Yet, solution is not trivial, and\r\n+implies both using new user media HTML5 API and some canvas manipulation. Here is\r\n+a reminder which may be useful to everyone.\r\n+\r\n+## Displaying Webcam Stream in Browser\r\n+\r\n+First step is to display the webcam stream into the browser. It is easily done using\r\n+the `getUserMedia` HTML5 API. [Support is quite limited](http://caniuse.com/#search=getUserMedia)\r\n+(neither supported on Safari / iOS, nor on IE, but supported on Edge, Firefox and\r\n+Chrome). A solution for oldest browsers is to fallback on a Flash solution. However,\r\n+it won\'t be fixed on mobiles, and we would need to use an extra framework such\r\n+as [PhoneGap](http://phonegap.com/) in this case.\r\n+\r\n+As dealing with fallback would be quite cumbersome, and as we don\'t want to write\r\n+some ugly prefixed code such as:\r\n+\r\n+``` js\r\n+const getUserMedia = navigator.getUserMedia\r\n+ || navigator.webkitGetUserMedia\r\n+ || navigator.mozGetUserMedia\r\n+ || navigator.msGetUserMedia;\r\n+```\r\n+\r\n+We are going to use a polyfill written by [@addyosmani](https://www.twitter.com/addyosmani):\r\n+[getUserMedia.js](https://github.com/addyosmani/getUserMedia.js/). It uses either the\r\n+native implementation or Flash fallback depending of browser support. Exactly what\r\n+we need.\r\n+\r\n+First, let\'s install it (I\'m using Webpack, hence the `save-dev`):\r\n+\r\n+``` sh\r\n+npm install --save-dev getusermedia-js\r\n+```\r\n+\r\n+Let\'s now initialize a video stream and display it in the browser using the\r\n+freshly installed package:\r\n+\r\n+``` js\r\n+import { getUserMedia } from \'getusermedia-js\';\r\n+\r\n+getUserMedia({\r\n+ video: true,\r\n+ audio: false,\r\n+ width: 640,\r\n+ height: 480,\r\n+ el: \'stream\', // render live video in #stream\r\n+ swffile: require(\'getusermedia-js/dist/fallback/jscam_canvas_only.swf\'),\r\n+}, stream => {\r\n+ const video = document.querySelector(\'#stream video\');\r\n+ video.src = window.URL.createObjectURL(stream);\r\n+ video.play();\r\n+}, err => console.error(err));\r\n+```\r\n+\r\n+We start by calling the `getUserMedia` polyfill, specifying it we don\'t care about\r\n+audio, the preview video dimensions, and where to insert it (in the `#stream` element).\r\n+We also specify the path to our Flash fallback (included in the lib). I didn\'t test\r\n+it as all my installed browsers support this feature, but it should work this way.\r\n+\r\n+Note that if we don\'t use any module bundler, we need to replace the `require` call\r\n+by the path of the fallback.\r\n+\r\n+Second and third arguments are respectively success and error callbacks. Let\'s focus\r\n+on the success handler, as we just log errors in case of failure. Once we get the webcam\r\n+stream, we point the `video` tag to its URL, retrieved using the `URL.createObjectURL`\r\n+method. We should not forget to call the `play` method on our video to prevent\r\n+from being stuck at the first frame.\r\n+\r\n+At this step, we are able to display our webcam stream:\r\n+\r\n+<div class=\'embed-container\' style="padding-bottom: 35rem;">\r\n+ <iframe src="https://www.jonathan-petitcolas.com/labs/webcam-picture/webcam-stream/index.html" height="580" frameborder="0" allowfullscreen></iframe>\r\n+</div>\r\n+\r\n+## Taking a Picture using Canvas and Live Webcam Stream\r\n+\r\n+Now, we need to isolate a single frame into a picture. Principle is not trivial: we need\r\n+to add a `canvas` element to our page, set the canvas content to current video frame,\r\n+and then convert canvas content to data URL.\r\n+\r\n+We update our HTML code to add a `Capture` button:\r\n+\r\n+``` xml\r\n+<div class="wrapper">\r\n+ <div id="stream"></div>\r\n+ <img id="grid" src="#"/>\r\n+ <p class="actions"><button id="capture">Capture</button></p>\r\n+</div>\r\n+```\r\n+We added an image used to display our snapped view once user has pressed the\r\n+capture button. As we don\'t have any image at initialization, we set the `src`\r\n+attribute to `#`. There is a lot of discussion about [how to set an image with no\r\n+src attribute](http://stackoverflow.com/questions/5775469/whats-the-valid-way-to-include-an-image-with-no-src/28077004#28077004).\r\n+I opted for the anchor `#` which triggers an extra request to current page, which\r\n+have been just downloaded and is still in cache. A very little overhead.\r\n+\r\n+Browsers may display a broken image icon using `#`. To prevent this behavior, let\'s\r\n+use some CSS:\r\n+\r\n+``` css\r\n+img[src="#"] {\r\n+ display: none;\r\n+}\r\n+```\r\n+\r\n+Let\'s update our Javascript code to capture a single video frame:\r\n+\r\n+``` js\r\n+const startVideo = stream => {\r\n+ const video = document.querySelector(\'#stream video\');\r\n+ video.src = window.URL.createObjectURL(stream);\r\n+ video.play();\r\n+};\r\n+\r\n+const stopVideo = stream => {\r\n+ const video = document.querySelector(\'#stream video\');\r\n+ video.parentNode.removeChild(video);\r\n+\r\n+ // free memory before page unloading\r\n+ window.URL.revokeObjectURL(stream);\r\n+}\r\n+\r\n+const capture = () => {\r\n+ // add canvas element\r\n+ const canvas = document.createElement(\'canvas\');\r\n+ document.querySelector(\'body\').appendChild(canvas);\r\n+\r\n+ // set canvas dimensions to video ones to not truncate picture\r\n+ const videoElement = document.querySelector(\'#stream video\');\r\n+ canvas.width = videoElement.width;\r\n+ canvas.height = videoElement.height;\r\n+\r\n+ // copy full video frame into the canvas\r\n+ canvas.getContext(\'2d\').drawImage(videoElement, 0, 0, videoElement.width, videoElement.height);\r\n+\r\n+ // get image data URL and remove canvas\r\n+ const snapshot = canvas.toDataURL("image/png");\r\n+ canvas.parentNode.removeChild(canvas);\r\n+\r\n+ // update grid picture source\r\n+ document.querySelector(\'#grid\').setAttribute(\'src\', snapshot);\r\n+};\r\n+\r\n+getUserMedia({\r\n+ video: true,\r\n+ audio: false,\r\n+ width: 640,\r\n+ height: 480,\r\n+ el: \'stream\', // render live video in #stream\r\n+ swffile: require(\'getusermedia-js/dist/fallback/jscam_canvas_only.swf\'),\r\n+}, stream => {\r\n+ startVideo(stream);\r\n+ document.getElementById(\'capture\').addEventListener(\'click\', () => {\r\n+ capture();\r\n+ stopVideo(stream);\r\n+ });\r\n+}, err => console.error(err));\r\n+```\r\n+\r\n+We moved previous success callback content into a dedicated `startVideo` function,\r\n+and add an event listener on the `capture` button. All other code is either self\r

marmelab.com/sedy/setup/ just show up 30 repos

Description

On the setup page, only 30 repositories show up (until letter "C" to give a rough idea). I don't find a way to scroll past that point so I am unable to activate sedy for a repo past that limit.

Steps to Reproduce

  1. Activate sedy when you have more than 30 repos
  2. Reach sedy/setup/
  3. Try to activate the 35th repo for example – can't because it does not show up

Expected behavior: Being able to see all my repos/scroll through the list

Actual behavior: -

Additional informations

I have tried with and without ad blocker and result is the same.

Refactor fixer with strategies

The fixer should have multiple fix strategies which can be chosen in accordance with the origin of the trigger (PR comment, issue, etc).

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.