Coder Social home page Coder Social logo

react-mde's Introduction

āš ļø Attention

This repository is undergoing a huge refactoring and react-mde will now be headless, starting from version 12. Meaning, it won't be opinionated about styles anymore. The master branch now contains the new version. No updates to the 11.5.0 will ever come.

You can check out the headless version (12.*) with the next tag. Here is a demo.

I will close all issues related to the 11.* version since that's no longer being maintained.

šŸ“ react-mde (11.5.0)

npm MinZipped twitter

A simple yet powerful and extensible React Markdown Editor that aims to have feature parity with the Github Markdown editor. React-mde has no 3rd party dependencies.

Demo

Installing

npm i react-mde

Using

React-mde is a completely controlled component.

Minimal example using Showdown. View live on CodeSandBox:

import * as React from "react";
import ReactMde from "react-mde";
import * as Showdown from "showdown";
import "react-mde/lib/styles/css/react-mde-all.css";

const converter = new Showdown.Converter({
  tables: true,
  simplifiedAutoLink: true,
  strikethrough: true,
  tasklists: true
});

export default function App() {
  const [value, setValue] = React.useState("**Hello world!!!**");
  const [selectedTab, setSelectedTab] = React.useState<"write" | "preview">("write");
  return (
    <div className="container">
      <ReactMde
        value={value}
        onChange={setValue}
        selectedTab={selectedTab}
        onTabChange={setSelectedTab}
        generateMarkdownPreview={markdown =>
          Promise.resolve(converter.makeHtml(markdown))
        }
      />
    </div>
  );
}

Markdown Preview

React-mde is agnostic regarding how to preview Markdown. The prop generateMarkdownPreview should return a Promise of either a string or a ReactElement.

Customizing Icons

React-mde comes with SVG icons extracted from FontAwesome.

You can customize the way icons are resolved by passing your own getIcon that will return a ReactNode given a command name.

<ReactMde
    getIcon={(commandName) => <MyCustomIcon name={commandName} />}
    onChange={this.handleValueChange}
    // ...
/>

React-mde Props

The types are described below

  • value: string: The Markdown value.
  • onChange: (value: string): Event handler for the onChange event.
  • selectedTab: "write" | "preview": The currently selected tab.
  • onTabChange: (tab) => void: Function called when the selected tab changes.
  • classes?: Object: An object containing the following optional properties: reactMde, toolbar, preview, textArea and suggestionsDropdown. This allows for passing class names to each of the inner components of React-mde. Classes defined in the classes prop follow the specification of Jed Watson's classNames project.
  • commands?: Record<string, Command>: An object with string properties representing keys, and a Command object as value for each key. These are custom commands. Commands are explained in more details below.
  • toolbarCommands?: string[][]: Array of array of strings, indicating which commands should be displayed. Each outer array is a group. Example: [["code", "bold"], ["italic"]]. The default list can be obtained with import { getDefaultToolbarCommands } from 'react-mde', getDefaultToolbarCommands()
  • generateMarkdownPreview: (markdown: string) => Promise<string | ReactElement>;: Function that should return a Promise to the generated HTML or a React element for the preview. If this prop is falsy, then no preview is going to be generated.
  • getIcon?: (commandName: string) => React.ReactNode } An optional set of button content options, including an iconProvider to allow custom icon rendering. options. It is recommended to inspect the layouts source code to see what options can be passed to each while the documentation is not complete.
  • loadingPreview: What to display in the preview while it is loading. Value can be string, React Element or anything React can render.
  • readOnly?: boolean: Flag to render the editor in read-only mode.
  • l18n?: A localization option. It contains the strings write, preview, uploadingImage and pasteDropSelect.
  • minEditorHeight?: number: The minimum height of the editor.
  • maxEditorHeight?: number: The max height of the editor (after that, it will scroll).
  • minPreviewHeight?: number: The minimum height of the preview.
  • heightUnits?: string: The height units, defaults to px.
  • loadSuggestions?: (text: string, triggeredBy: string) => Promise<Suggestion[]>: Function to load mention suggestions based on the given text and triggeredBy (character that triggered the suggestions). The result should be an array of {preview: React.ReactNode, value: string}. The preview is what is going to be displayed in the suggestions box. The value is what is going to be inserted in the textarea on click or enter.
  • suggestionTriggerCharacters (string[]): Characters that will trigger mention suggestions to be loaded. This property is useless without loadSuggestions.
  • suggestionsAutoplace?: boolean: Try to move the suggestions popover around so that it fits in the viewport, defaults to false
  • childProps?: Object: An object containing props to be passed to writeButton, previewButton, commandButtons and textArea.
  • paste: PasteOptions: Options for file upload.

Styling

The following styles from React-mde should be added: (Both .scss and .css files are available. No need to use sass-loader if you don't want)

Easiest way: import react-mde-all.css:

import 'react-mde/lib/styles/css/react-mde-all.css';

If you want to have a more granular control over the styles, you can import each individual file.

If you're using SASS, you can override these variables: https://github.com/andrerpena/react-mde/blob/master/src/styles/variables.scss

XSS concerns

React-mde does not automatically sanitize the HTML preview. If your using Showdown, this has been taken from their documentation:

Cross-side scripting is a well known technique to gain access to private information of the users of a website. The attacker injects spurious HTML content (a script) on the web page which will read the userā€™s cookies and do something bad with it (like steal credentials). As a countermeasure, you should filter any suspicious content coming from user input. Showdown doesnā€™t include an XSS filter, so you must provide your own. But be careful in how you do itā€¦

You might want to take a look at showdown-xss-filter.

It is also possible to return a Promise to a React Element from generateMarkdownPreview, which makes it possible to use ReactMarkdown as a preview. View issue. ReactMarkdown has built-in XSS protection.

Please refer to the commands source code to understand how they should be implemented.

Change log / Migrating from older versions

Instructions here.

Licence

React-mde is MIT licensed.

Third party

In order to make React-mde zero deps, I've embedded two small libraries:

About the author

Made with ā¤ļø by AndrĆ© Pena and other awesome contributors.

twitter

react-mde's People

Contributors

andrerpena avatar bnbarak avatar darwintantuco avatar dependabot[bot] avatar errorname avatar greenkeeper[bot] avatar ivanbanov avatar jacargentina avatar kravaring avatar lsurma avatar meddy avatar michaelryancaputo avatar mikeappell avatar mmomtchev avatar n1ru4l avatar nes-si avatar pawlowskim avatar peterjmag avatar pwolaq avatar ralouphie avatar rej156 avatar rozman-michael avatar scott-silver avatar stephenharris avatar tbaut avatar thaichors3000 avatar urkass avatar ustacryptact avatar vitorqb avatar xdamman 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

react-mde's Issues

Implement the GitHub layout

After the multi-layout support was implemented #73, now it's time to implement the GitHub layout, with the preview being on the side, in tabs.

Removing event listeners

bind every time creates a new function, so removing event listeners like that won't work:

    componentDidMount() {
        document.addEventListener('click', this.handleGlobalClick.bind(this), false);
    }

    componentWillUnmount() {
        document.removeEventListener('click', this.handleGlobalClick.bind(this), false);
    }

Doesn't work with React 16

Had my project on React 15.6, but when I tried updating to 16, this package broke with

Uncaught TypeError: Cannot read property 'node' of undefined
    at Object../node_modules/react-mde/lib/components/HeaderGroup.js (HeaderGroup.js:14)
    at __webpack_require__ (bootstrap 492c0abd2a0e9b4d876f:678)
    at fn (bootstrap 492c0abd2a0e9b4d876f:88)
    at Object../node_modules/react-mde/lib/ReactMde.js (ReactMde.js:21)
    at __webpack_require__ (bootstrap 492c0abd2a0e9b4d876f:678)
    at fn (bootstrap 492c0abd2a0e9b4d876f:88)
    at Object../node_modules/react-mde/lib/index.js (index.js:8)
    at __webpack_require__ (bootstrap 492c0abd2a0e9b4d876f:678)
    at fn (bootstrap 492c0abd2a0e9b4d876f:88)
    at Object.<anonymous> (bundle.js:170102)

I believe it's because PropTypes have been moved into a separate package.
Any chance of fixing it any time soon?

Multiple copies of React loaded.

Hi,

Firstly, I can't wait to use this functionality - It looks much simpler and cleaner than the other solutions out there.

Unfortunately I'm currently receiving the following error message:

multiplereact

When I check the sources tab it looks like I'm loading React 16 and you've got React 15.6 (I think) included as a dependency.

Any clues on how to resolve this one?

Make commands to return Promise<Value> only

I'll be releasing a new 2.* version this Saturday that will allow commands to return Promises optionally (thanks @flexzuu). However, for the sake of consistency and simplicity, I'm deprecating commands that don't return a promise now. In 3.* they'll be gone.

This will have NO EFFECT on users that only use the default commands, and for those who created their own commands, all they have to do is to return Promise.resolve([whatever you returned before]).

#65 (comment)

Option to disallow raw HTML

Currently, a user can type something like this:

<div onmouseenter="alert('poop')">foo</div>

Which will cause all manner of chaos. It doesn't seem that there's a way to disable arbitrary HTML. Can this be made an option?

Stuck highlighting within textarea box

Weird issue going on, though it doesn't seem to be occurring in your demo but i figured maybe someone here would know how to go about fixing it...

Every time i highlight anything in the textarea box, I can't seem to un-highlight the selection after clicking within the textarea box again.

It does however get unhighlighted (text gets un-selected) once I click outside of the textarea box.

Any idea why?

Feature for adding markdown list item on Enter key press and a Tab feature in textbox area

Right now if you type markdown as followed :

  • asdlkfjasdlfk (and then press enter)
  •     <--- it would be awesome if it automatically added a  "-"   or 1. , 2. , etc automatically depending on if its a bullet or numbered list. 
    

Similar to how Microsoft word does it when pressing enter on Lists.

Also, a feature that when you are done writing the list items, a way to cancel out the last markdown "-" or 1. by clicking enter and or backspace; just like how Microsoft Words does it as well. Example:

  • This is
  • a test showing
  • example
  • // at this point pressing enter or backspace should remove the markdown "-"

Lastly, a feature that when you key press Tab, it will actually tab over in the textbox (or 4 spaces) and reflect as so in the HTML as a Tab instead of selecting another element on the page.

Find a recommended library to deal with XSS

As observed by @mattbasta in this thread: #74, React-mde is vulnerable to XSS and this is not as simple as described here. What we do have now is a prop called processHtml which is called before displaying the HTML in the preview panel, and this allows you to use your anti-XSS library of choice to mitigate it.

This thread is about finding a recommended one. Maybe I'll add it as an optional dependency, or possibly just suggest using it and updating the demo to include it.

Possibility for commands to return multiple times

Wishlist feature: make it possible for commands to update the text more than once, asynchronously.

Use case: image uploading. For example, when you first upload an image in the GitHub editor, it inserts ![Uploading IMG_20180214_172431_759.jpgā€¦](). Once the upload is finished, it replaces the Uploading... text with the image's URL.

It is possible to work around this by using the command to insert the Uploading, and then updating value with the final URL, but this is messy and requires several layers of indirection.

Docs don't match TS type definition for Command

The docs say that the icon member of a command may be a JSX element. However, the type definition only allows strings:

If this is a text, it will print a font-awesome <i/> element with the classes fa fa-${icon}. Passing bold will print <i className="fa fa-bold"></i>. If the passing value is a React element, it will print the react element.

https://github.com/andrerpena/react-mde/blob/master/src/types/Command.ts#L6

The icon member should conceivably be updated to string | JSX.Element

State and props should be assigned to const

There are few places where state or props parameters are assigned to let instead of const`, for example:

        let icon = this.props.icon;
        let open = this.state.open;
        let commands = this.props.commands;

Use Draft.js instead of a regular textarea

React-mde currently has the history problem #76. So basically Ctrl + Z doesn't work properly when the content of the textarea is altered through a command and not by typing. The solution to this problem seems to be a custom implementation of history.

Yesterday I stumbled upon Draft.js again and it seems to take care of this and other feature problems like mentions out of the box. The biggest problem with Draft.js is that it brings complexity.

What I want to investigate the bringing Draft.js into the ReactMdeTextArea component but abstracting its complexity so the React-mde APIs remain simple.

UL/OL commands set wrong selection, affects UX

Repro:

  • go to http://andrerpena.me/react-mde/
  • click any of the two list command buttons
  • the list bullet is properly inserted but it and the following space are selected

Why is it bad? Becuase the users expect that after clicking on the list icon they can start typing the list item content. But because of the selection they overwrite the bullet.

Action required: Greenkeeper could not be activated šŸšØ

šŸšØ You need to enable Continuous Integration on all branches of this repository. šŸšØ

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didnā€™t receive a CI status on the greenkeeper/initial branch, itā€™s possible that you donā€™t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how itā€™s configured. Make sure it is set to run on all new branches. If you donā€™t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, youā€™ll need to re-trigger Greenkeeperā€™s initial pull request. To do this, please delete the greenkeeper/initial branch in this repository, and then remove and re-add this repository to the Greenkeeper integrationā€™s white list on Github. You'll find this list on your repo or organizationā€™s settings page, under Installed GitHub Apps.

Support table?

Does react-mde support table?
I tried the following in the live demo, but no effect:

| 22   | 44   |
| ---- | ---- |
| 222  | 33   |

How to use react-mde with typescript

import React from 'react'
const ReactMde = require('react-mde')
const { ReactMdeCommands } = require('react-mde') 

interface ComponentProps {}

interface ComponentState {
	reactMdeValue: object
}

class WriteArticle extends React.Component<ComponentProps, ComponentState> {
	constructor(props: object) {
		super(props)
		this.state = {
			reactMdeValue: {
				text: '',
				selection: null
			}
		}
	}

	handleValueChange = (value: object) => {
		this.setState({reactMdeValue: value})
	}

	render() {
		return (
			<div className="container">
				<ReactMde
					textAreaProps={{
							id: 'ta1',
							name: 'ta1',
					}}
					value={this.state.reactMdeValue}
					onChange={this.handleValueChange}
					commands={ReactMdeCommands}
				/>
			</div>
		)
	}
}

export default WriteArticle

The above code runs with error as below:
warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.

react: 16.1.0
react-mde: 1.0.3

Demo toolbar doesn't work with Firefox

Neat project! The demo is a bit broken on Firefox unfortunately. The buttons on the toolbar simply do nothing whatsoever. The rest of the functionality seems to work fine.

Tested with Firefox 50.1.0 on Ubuntu without any extensions. No errors are reported on the console.

Cannot read property 'slice' of undefined

When I try to use some button to format text, I get this warning

Cannot read property 'slice' of undefined

It could be because I'm passing value as string to component?

This is my ReactMde component. It receives the props from his parent.

<ReactMde
        {...{ value, onChange }}
        textAreaProps={{
          id,
          style: { resize: 'none' },
          value,
        }}
        commands={ReactMdeCommands.getDefaultCommands()}
        visibility={{ preview: false }}
/>

And this's his parent:

<MarkDownEditor
  id="text"
  value={this.state.reactMdeValue.text}
  onChange={this.handleChange}
/>

This is the error:

Uncaught (in promise) TypeError: Cannot read property 'slice' of undefined
at Object.insertText (ReactMdeTextHelper.js:21)
at Object.makeACommandThatInsertsBeforeAndAfter (ReactMdeCommandHelper.js:55)
at Object.execute (ReactMdeCommands.js:34)
at ReactMde. (ReactMde.js:83)
at step (ReactMde.js:50)
at Object.next (ReactMde.js:31)
at ReactMde.js:25
at new Promise ()
at ./node_modules/react-mde/lib/js/ReactMde.js.__awaiter (ReactMde.js:21)
at ReactMde._this.handleCommand (ReactMde.js:77)
at onClick (ReactMdeToolbar.js:16)
at Object../node_modules/react-dom/lib/ReactErrorUtils.js.ReactErrorUtils.invokeGuardedCallback (ReactErrorUtils.js:69)
at executeDispatch (EventPluginUtils.js:85)
at Object.executeDispatchesInOrder (EventPluginUtils.js:108)
at executeDispatchesAndRelease (EventPluginHub.js:43)
at executeDispatchesAndReleaseTopLevel (EventPluginHub.js:54)
at Array.forEach ()
at forEachAccumulated (forEachAccumulated.js:24)
at Object.processEventQueue (EventPluginHub.js:254)
at runEventQueueInBatch (ReactEventEmitterMixin.js:17)
at Object.handleTopLevel [as _handleTopLevel] (ReactEventEmitterMixin.js:27)
at handleTopLevelImpl (ReactEventListener.js:72)
at ReactDefaultBatchingStrategyTransaction.perform (Transaction.js:143)
at Object.batchedUpdates (ReactDefaultBatchingStrategy.js:62)
at Object.batchedUpdates (ReactUpdates.js:97)
at dispatchEvent (ReactEventListener.js:147)

Thanks in advance.

Commands ... how to go about editing/creating them?

Everything works great with using the package, I'm just not sure how to go about editing the commands.

I really need to take out the typing in code command and possibly the insert picture command. No need for it in my app for our users.

Confused with the instructions of having to implement my own commands to do this (also not using typescript).

Seems like I would have create a file similar to that of ReactMdeCommands? That file looks like it needs imports from multiple different files.

Any example of how to take out some of the default commands would be great!

Confusion of how to get All 3 sub components working together.

On Version 2 of React-mde.

I have all 3 components showing. I'm just not sure how to go about connecting all 3 components to work together. Example : Clicking bold from ReactMdeToolbar component does not bold the text in ReactMdeTextArea component. And the text typed into ReactMdeTextArea component does not show up in the ReactMdePreview component. I'm sure there is something i'm missing here, like refs or something needed.

Example:


  handleValueChange = value => {

    this.setState({
      reactMdeValue: value,
    });
  };

return(
        <ReactMdeToolbar 
          commands={ReactMdeCommands.getDefaultCommands()}   
          />

        <ReactMdeTextArea          
            rows= {this.props.rows}
            title= {this.props.title}
            style= {textareaStyle}
            placeholder= {this.props.placeholder}
            className = "textarea-input"
            value={this.state.reactMdeValue}
            onChange={this.handleValueChange}      
        />

        <ReactMdePreview />

)

Header dropdown throws error

Noticed this when working locally, and tried it out on the demo:

bundle-prod.js:26260 Uncaught TypeError: Cannot read property 'openDropdown' of undefined
    at HeaderItemDropdown.handleOpenDropdown (bundle-prod.js:26260)
    at HTMLUnknownElement.callCallback (bundle-prod.js:4657)
    at Object.invokeGuardedCallbackDev (bundle-prod.js:4696)
    at Object.invokeGuardedCallback (bundle-prod.js:4553)
    at Object.invokeGuardedCallbackAndCatchFirstError (bundle-prod.js:4567)
    at executeDispatch (bundle-prod.js:4790)
    at Object.executeDispatchesInOrder (bundle-prod.js:4812)
    at executeDispatchesAndRelease (bundle-prod.js:5327)
    at executeDispatchesAndReleaseTopLevel (bundle-prod.js:5338)
    at Array.forEach (<anonymous>)

Avoid mutating function arguments

There are few places where function arguments are mutated. It's a good practice to avoid such behaviour by creating new variables instead of mutating existing ones.

Example:

export function makeHeader(text, selection, insertionBefore) {
    selection = selectCurrentWorkIfCarretIsInsideOne(text, selection); // mutating selection variable

Focus is forcingly moved to markdown editor

Hello,
Thank you for this great package

After applying this editor , I found a issue in it

** reproduction steps **

  1. add react-mde
  2. add other inputs
  3. render
  4. type something in react-mde
  5. type something in other inputs
  6. then focus is moved to react-mde forcingly

you can check it out with below code !
https://codesandbox.io/s/o4v4mqmrq6

ReactMdeDemo.js
render() {
    return (
      <div className="container">
        <ReactMde
          textAreaProps={{
            id: "ta1",
            name: "ta1"
          }}
          value={this.state.reactMdeValue}
          onChange={this.handleValueChange}
          showdownOptions={{ tables: true, simplifiedAutoLink: true }}
        />

        <input
          name="name"
          onChange={e => this.setState({ name: e.target.value })}
          value={this.state.name}
        />
      </div>
    );
  }

Clicking a command not selecting the highlighted portion.

I'm using react-mde through the 3 sub component approach. Once i click bold (or any command) for example, it selects the entire string instead of the portion that i have highlighted

Example:

Text value: This is the test.

I've highlighted the word 'the' and clicked bold command.

Which results in this

       **This is the test**

Where it really should result to

      This is **the** test.

(which showdown then bolds the entire string because of the markdown syntax)

On a side note, it works fine when react-mde is used as a single wrapper component instead of with sub-components.

Not sure if its a bug, or something on my end. Can you post an example of react-mde in JS that uses all 3 sub components with handleCommand().. Maybe i'm missing something in setting up the handleCommand. Made some comments below in my component to help understand the issue.


    let realCommands = [ 
      [ReactMdeCommands.makeHeaderCommand, ReactMdeCommands.makeBoldCommand, ReactMdeCommands.makeItalicCommand], 
    [ReactMdeCommands.makeUnorderedListCommand, ReactMdeCommands.makeOrderedListCommand],
    ]




  handleCommand = (command: Command) => {

    //const {value: {text}, onChange} = this.props;

    let text = this.state.reactMdeValue.text;          //debugger showing correct text = "This is the test"

    let textArea = this.textArea;                    //debugger showing correct textArea = textarea.textarea-input

    const newValue = command.execute(text, getSelection(textArea));

             //here newValue is equal to **This is the test** which makes me think something is up with the 
              execute command as it should be   This is **the** test



    this.handleValueChange(newValue);

  }




  handleValueChange = value => {

    this.setState({
      reactMdeValue: value,
    });

 };




   <div>
              <ReactMdeToolbar
                commands={realCommands}
                onCommand={this.handleCommand}
                />

              <ReactMdeTextArea
                  onChange={this.handleValueChange}
                  value={this.state.reactMdeValue}
                  textAreaProps={textAreaProps}
                  textAreaRef={(ref) => this.textArea = ref}
                  />      

              <label className="group-input inputs-module">Preview</label>

              <ReactMdePreview 
                  markdown={this.state.reactMdeValue.text}
                  />
   </div>

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.