Coder Social home page Coder Social logo

eea / volto-slate Goto Github PK

View Code? Open in Web Editor NEW
31.0 40.0 11.0 27.3 MB

DEPRECATED: Moved to Volto Core since 16.0.0.alpha.15

License: MIT License

JavaScript 97.07% CSS 0.13% Less 1.37% Makefile 1.41% Shell 0.02%
volto volto-slate slatejs plone addons volto-addon eea-volto-addon hacktoberfest

volto-slate's Introduction

volto-slate

Releases

Pipeline Lines of Code Coverage Bugs Duplicated Lines (%)

Pipeline Lines of Code Coverage Bugs Duplicated Lines (%)

Watch a 5 minutes "elevator pitch" for volto-slate

An alternative text editor for Volto, capable of completely replacing the default richtext editor while offering enhanced functionality and behavior. We believe that, in order to succeed, Volto's richtext form editor (the Volto Composite Page editor) needs strong integration between the rich text capabilities and the rest of the Volto blocks. Some examples of the kind of strong integration we have in mind:

  • Pasting complex documents inside a volto-slate text block will create multiple Volto blocks: images will be converted to Volto Image blocks, tables will be converted to Volto Table blocks, etc.
  • The text block accepts drag&drop images and it will upload them as Volto Image blocks.
  • volto-slate has a Table button with the familiar size input, but it create a Table block

While this addon is still in an early alpha stage, we've solved most of the big issues, the API starts to stabilize and we've already started several addons based on it: https://github.com/eea/volto-slate-metadata-mentions/ and https://github.com/eea/volto-slate-zotero

Why

Some of the main reasons that drove us to create volto-slate instead of enhancing Volto's draftjs implementation:

  • Volto's draftjs implementation depends on draft-js-plugins, a third-party project that introduces its own set of bugs and maintanance issues

  • Slate has a modern, developer-friendly api that makes developing plugins something easy to do. Getting the editor in a plugin is as easy as const editor = useSlate(), overriding core functionality is something that's built in as pluggable, directly in Slate.

  • Volto's draft based implementation depends on Redraft for its final output, which comes with its own bugs and issues. While it is nice to have view-mode components, this is something that volto-slate implements just as well.

  • Because Slate's internal storage uses a tree modeled on the DOM pattern, its final rendered output is very clean. Note: The Slate editor value is a JSON object, similar to the Draftjs based implementation.

Upgrades

Upgrade to 4.x.x

  • Namespace the plugins #156:
    • Make sure you upgrade your slate plugins to use the new slate namespaced plugin ids. See for example volto-slate-footnote #23
  • asDefault profile makes the volto-slate as the default Editor for blocks and richtext.
    • If you're not ready for this, yet, switch to volto-slate:asDefaultBlock

Upgrade to 3.x.x

  • Removed all deprecated, already in Volto Core, futurevolto components:
    • SidebarPopup
    • ObjectWidget
    • ObjectBrowserWidget
    • helpers/Blocks
  • Table inline button and copy&paste support is not installed by default anymore. You'll need to explicitly import the tableButton profile like:
    • volto:asDefault,tableButton
    • volto-slate:minimalDefault,simpleLink,tableButton

Available profiles.

volto-slate provides several optional configuration:

  • asDefault - makes the volto-slate as the default Editor for blocks and richtext
  • asDefaultBlock - makes volto-slate the default Editor for blocks
  • asDefaultRichText - makes volto-slate the default Editor for richtext widget
  • minimalDefault, same as the above, but uses a set of toolbar buttons similar to Volto
  • simpleLink reuses Volto's link plugin and makes for a better replacement of Volto's rich text editor.
  • tableButton adds table button to Slate toolbar in order to easily insert Table block after.

Features

1. Hovering (floating) toolbar that shows up on selection

Screen Recording

2. Optional expanded (fixed) toolbar

Screen Recording

3. Working with links (internal, external, email)

Screen Recording

4. Removing links

Screen Recording

5. Editing links

Screen Recording

6. Block-quotes

Screen Recording

7. Split paragraph block in two with Enter key and join them back with Backspace key

Screen Recording

8. Breaking and joining list items

Screen Recording

9. Breaking (with expanded selection) and joining list items

Screen Recording

10. Inserting a new list item at the end

Screen Recording

11. Two Enter key presses in the last empty list item creates a new list

Screen Recording

12. Using Up and Down keys to go through the blocks in both directions

Screen Recording

13. Changing indent level of list items using Tab and Shift-Tab keys

Screen Recording

14. Splitting a list block with Enter into two list blocks

Screen Recording

15. Support for markdown bulleted lists with *, - and +

Screen Recording

16. Support for markdown numbered lists with 1. - 9.

Screen Recording

17. Backspace with cursor on first position inside a list with just one item converts the list to a paragraph

Screen Recording

18. Creating a new text block with Enter at the end of a text block and removing it with Backspace

Screen Recording

19. Switching the list type (numbered list to/from bulleted list)

Screen Recording

Getting started

Try volto-slate with Docker

  1. Get the latest Docker images

    docker pull plone
    docker pull plone/volto
    
  2. Start Plone backend

    docker run -d --name plone -p 8080:8080 -e SITE=Plone -e PROFILES="profile-plone.restapi:blocks" plone
    
  3. Start Volto frontend

    docker run -it --rm -p 3000:3000 --link plone -e ADDONS="volto-slate:asDefault" plone/volto
    
  4. Go to http://localhost:3000

  5. Login with admin:admin

  6. Create a new Page and add a new Text block.

Add volto-slate to your Volto project

  1. Make sure you have a Plone backend up-and-running at http://localhost:8080/Plone

  2. Start Volto frontend

  • If you already have a Volto project, just update package.json:

    "addons": [
        "volto-slate:asDefault"
    ],
    
    "dependencies": {
        "volto-slate": "*"
    }
  • If not, create one:

    npm install -g yo @plone/generator-volto
    yo @plone/volto my-volto-project --addon volto-slate:asDefault
    cd my-volto-project
    
  • Install new add-ons and restart Volto:

    yarn install
    yarn start
    
  1. Go to http://localhost:3000

  2. Happy editing!

Plugins

To write a new plugin, please refer plugins

Cypress

We aim to achieve a good coverage for cypress. Please refer to commands listed here to ease the process of writing new tests.

Release

Automatic release using Jenkins

  • The automatic release is started by creating a Pull Request from develop to master. The pull request status checks correlated to the branch and PR Jenkins jobs need to be processed successfully. 1 review from a github user with rights is mandatory.
  • It runs on every commit on master branch, which is protected from direct commits, only allowing pull request merge commits.
  • The automatic release is done by Jenkins. The status of the release job can be seen both in the Readme.md badges and the green check/red cross/yellow circle near the last commit information. If you click on the icon, you will have the list of checks that were run. The continuous-integration/jenkins/branch link goes to the Jenkins job execution webpage.
  • Automated release scripts are located in the eeacms/gitflow docker image, specifically js-release.sh script. It uses the release-it tool.
  • As long as a PR request is open from develop to master, the PR Jenkins job will automatically re-create the CHANGELOG.md and package.json files to be production-ready.
  • The version format must be MAJOR.MINOR.PATCH. By default, next release is set to next minor version (with patch 0).
  • You can manually change the version in package.json. The new version must not be already present in the tags/releases of the repository, otherwise it will be automatically increased by the script. Any changes to the version will trigger a CHANGELOG.md re-generation.
  • Automated commits and commits with [JENKINS] or [YARN] in the commit log are excluded from CHANGELOG.md file.

Manual release from the develop branch ( beta release )

Installation and configuration of release-it

You need to first install the release-it client.

npm install -g release-it

Release-it uses the configuration written in the .release-it.json file located in the root of the repository.

Release-it is a tool that automates 4 important steps in the release process:

  1. Version increase in package.json ( increased from the current version in package.json)
  2. CHANGELOG.md automatic generation from commit messages ( grouped by releases )
  3. GitHub release on the commit with the changelog and package.json modification on the develop branch
  4. NPM release ( by default it's disabled, but can be enabled in the configuration file )

To configure the authentification, you need to export GITHUB_TOKEN for GitHub

export GITHUB_TOKEN=XXX-XXXXXXXXXXXXXXXXXXXXXX

To configure npm, you can use the npm login command or use a configuration file with a TOKEN :

echo "//registry.npmjs.org/:_authToken=YYYYYYYYYYYYYYYYYYYYYYYYYYYYYY" > .npmrc

Using release-it tool

There are 3 yarn scripts that can be run to do the release

yarn release-beta

Automatically calculates and presents 3 beta versions - patch, minor and major for you to choose ( or Other for manual input).

? Select increment (next version):
❯ prepatch (0.1.1-beta.0)
  preminor (0.2.0-beta.0)
  premajor (1.0.0-beta.0)
  Other, please specify...
yarn release-major-beta

Same as yarn release-beta, but with premajor version pre-selected.

yarn release

Generic command, does not automatically add the beta to version, but you can still manually write it if you choose Other.

Important notes

Do not use release-it tool on master branch, the commit on CHANGELOG.md file and the version increase in the package.json file can't be done without a PULL REQUEST.

Do not keep Pull Requests from develop to master branches open when you are doing beta releases from the develop branch. As long as a PR to master is open, an automatic script will run on every commit and will update both the version and the changelog to a production-ready state - ( MAJOR.MINOR.PATCH mandatory format for version).

How to contribute

See DEVELOP.md.

Credit

A lot of inspiration from the great Slate Plugins repository, especially the autoformat handlers.

Copyright and license

The Initial Owner of the Original Code is European Environment Agency (EEA). All Rights Reserved.

See LICENSE.md for details.

Funding

European Environment Agency (EU)

volto-slate's People

Contributors

andreiggr avatar avoinea avatar eea-jenkins avatar ichim-david avatar iflameing avatar kreafox avatar ksuess avatar nileshgulia1 avatar razvanmiu avatar robgietema avatar silviubogan avatar sneridagh avatar tiberiuichim avatar valentinab25 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

Watchers

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

volto-slate's Issues

Fixed toolbar: text jumps on selection

Steps to reporduce

  • Fix the Slate toolbar (config.settings.slate.showExpandedToolbar = true;)
  • select text
  • deselect text by setting cursor somewhere else

Expected behavior
Toolbar is always visible while block is active.
That means toolbar does not vanish on deselecting text.

Slate_fixed_toolbar_jumping

eslint issues

volto-slate]$ ../../../node_modules/eslint/bin/eslint.js --max-warnings=0 'src/**/*.{js,jsx,json}'

/joint/volto/ims-develop/src/addons/volto-slate/src/components/ElementEditor/PluginEditor.jsx
  32:16  warning  Unexpected console statement  no-console

/joint/volto/ims-develop/src/addons/volto-slate/src/editor/extensions/insertData.js
  35:7  warning  Unexpected console statement  no-console
  36:7  warning  Unexpected console statement  no-console
  53:9  warning  Unexpected console statement  no-console
  60:5  warning  Unexpected console statement  no-console
  62:5  warning  Unexpected console statement  no-console

/joint/volto/ims-develop/src/addons/volto-slate/src/editor/plugins/Markdown/constants.js
  3:10  warning  'Editor' is defined but never used  no-unused-vars

/joint/volto/ims-develop/src/addons/volto-slate/src/editor/plugins/Markdown/index.js
  1:8  warning  'React' is defined but never used          no-unused-vars
  4:8  warning  'PluginSidebar' is defined but never used  no-unused-vars

/joint/volto/ims-develop/src/addons/volto-slate/src/editor/plugins/StyleMenu/StyleMenu.jsx
  29:7  warning  'brownColor' is assigned a value but never used  no-unused-vars

/joint/volto/ims-develop/src/addons/volto-slate/src/editor/plugins/StyleMenu/utils.js
  55:5  warning  Unexpected console statement  no-console
  81:5  warning  Unexpected console statement  no-console

/joint/volto/ims-develop/src/addons/volto-slate/src/utils/blocks.js
  157:5  warning  Unexpected console statement  no-console

/joint/volto/ims-develop/src/addons/volto-slate/src/utils/internals.js
  1:10  warning  'Point' is defined but never used  no-unused-vars
  1:17  warning  'Range' is defined but never used  no-unused-vars

/joint/volto/ims-develop/src/addons/volto-slate/src/utils/lists.js
  1:43  warning  'Text' is defined but never used  no-unused-vars
  1:49  warning  'Node' is defined but never used  no-unused-vars

/joint/volto/ims-develop/src/addons/volto-slate/src/utils/ops.js
  5:8  warning  '_' is defined but never used  no-unused-vars

/joint/volto/ims-develop/src/addons/volto-slate/src/utils/todo.js
    1:30  warning  'Range' is defined but never used                     no-unused-vars
    1:37  warning  'Node' is defined but never used                      no-unused-vars
    2:10  warning  'settings' is defined but never used                  no-unused-vars
    4:3   warning  'getBlocksFieldname' is defined but never used        no-unused-vars
    5:3   warning  'getBlocksLayoutFieldname' is defined but never used  no-unused-vars
   23:53  error    'createEmptyParagraph' is not defined                 no-undef
  179:3   error    'selectAll' is not defined                            no-undef
  189:5   error    'convertAllToParagraph' is not defined                no-undef
  192:5   error    'convertAllToParagraph' is not defined                no-undef
  197:5   error    'convertAllToParagraph' is not defined                no-undef
  202:5   error    'convertAllToParagraph' is not defined                no-undef
  206:3   error    'selectAll' is not defined                            no-undef
  209:3   error    'unwrapList' is not defined                           no-undef
  214:17  error    'getSelectionNodesArrayByType' is not defined         no-undef

✖ 32 problems (9 errors, 23 warnings)

Question: is lazy loading Slate and volto-slate possible?

@tiberiuichim I was wondering if it would be possible to lazy load volto-slate and slate itself?

We are checking out custom bundles regularly and volto-slate and slate are roughly 200k that might make a difference on loading times. Here is the lighthouse treemap report from one of our projects.

Lighthouse-Treemap

I'd just like to understand what's needed to accomplish lazy loading and how much effort it would cost. cc @sneridagh

slate crashed when we paste a bold content in Bullet list and ordered list

@tiberiuichim can you help me regarding this.

steps to reproduce.

  1. in edit mode enter short text in a normal text field
  2. mark the text as bullet list
  3. press enter to get the second bullet
  4. copy a text formatted in bold from a Word document or from a web page shown in your browser with CTRL-C
  5. try to paste this with CTRL-V behind the second bullet
  6. bold text will be pasted into a new text field
  7. position cursor before the bold text and press delete key in order to merge bold text with the bullet list.
  8. Error message occurs.

Screenshot
list-elements-bold-italic-error

Potential improvements to DEVELOP.md

The steps in DEVELOP.md miss one thing. At the end, before eventually running yarn test, for yarn test to work, one must put
this line over the scripts.test line in package.json:

"test": "razzle test --env=jsdom --passWithNoTests --watchAll",

This line previously was:

"test": "razzle test --env=jsdom --passWithNoTests",

The new thing is --watchAll, without which this error shows up when running yarn test:

Determining test suites to run...
--watch is not supported without git/hg, please use --watchAll 
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Installation: dependency 'volto-object-widget'

Hi! First of all: Slate is cool. And this, your Slate integration rocks.

  • pasting text by creating multiple blocks is magnificent
  • the play of Slate with ElasticSearch is a lot easier than that of DraftJS (thanks for the plaintext value!)
  • the widget for setting links is really comfortable
  • well, the response on selecting text is a bit sluggish

I switch to Slate.

This is what I think is also necessary to install eea/volto-slate:

"addons": [
  "@eeacms/volto-object-widget"
],

"dependencies": {
  "@eeacms/volto-object-widget": "^1.0.0"
}

It's not enough to follow this instruction of README.txt:

If you already have a volto project, just update package.json:

"addons": [
    "volto-slate:asDefault"
],

"dependencies": {
    "volto-slate": "^1.0.0"
}

Thank you for taking time for this!

Unmet peer dependencies

warning "workspace-aggregator-3fe56610-8427-4601-b1a6-ea30fd526ec7 > volto-slate > [email protected]" has unmet peer dependency "react@^15.0.0 || ^16.0.0 || ^17.0.0|| ^18.0.0".
warning "workspace-aggregator-3fe56610-8427-4601-b1a6-ea30fd526ec7 > volto-slate > [email protected]" has unmet peer dependency "react@>=16.0.0".
warning "workspace-aggregator-3fe56610-8427-4601-b1a6-ea30fd526ec7 > volto-slate > [email protected]" has unmet peer dependency "react-dom@>=16.0.0".
warning "workspace-aggregator-3fe56610-8427-4601-b1a6-ea30fd526ec7 > volto-slate > [email protected]" has unmet peer dependency "react@>=16.8.0".
warning "workspace-aggregator-3fe56610-8427-4601-b1a6-ea30fd526ec7 > volto-slate > [email protected]" has unmet peer dependency "react-dom@>=16.8.0".
warning "workspace-aggregator-3fe56610-8427-4601-b1a6-ea30fd526ec7 > volto-slate > @testing-library/[email protected]" has unmet peer dependency "react@*".
warning "workspace-aggregator-3fe56610-8427-4601-b1a6-ea30fd526ec7 > volto-slate > @testing-library/[email protected]" has unmet peer dependency "react-dom@*".
warning "workspace-aggregator-3fe56610-8427-4601-b1a6-ea30fd526ec7 > volto-slate > @cypress/[email protected]" has unmet peer dependency "cypress@*".

Tests are failing

Test suite failed to run



    Cannot find module 'volto-slate/editor' from 'Cell.jsx'



    However, Jest was able to find:

    	'./Cell.jsx'

    	'./Cell.test.js'



    You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'jsx', 'json', 'ts', 'tsx'].



    See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string

Some problem with jest setup, probably caused by volto 12.

Placeholder: "Enter some richtext..." -> "Type text..."

volto-slate currently uses "Enter some richtext..." as placeholder. We should make this placeholder consistent with Volto/Draft and use "Type text...". This message also needs to be translated into the different languages that Volto currently supports.

I did not find the string in the volto-slate repo. Does this come from Slate directly?

Improve focus mechanism in RichTextWidget

Unlike the usual slate editor ( the text block) if we directly use SlateRichTextWidget, we have problems with focus and text selection. The main problem being not able to place a 'cursor' between the texts.

External links with navigation path need to be opened in same window

Bug description: plone/volto#2434

UniversalLink expects a boolean for openLinkInNewTab, but slate provides _self. This leads to a link with target _blank.
So my question is, if _self, _parent, .. is really needed.

choices: [
['_self', 'Open in this window / frame'],
['_blank', 'Open in new window'],
['_parent', 'Open in parent window / frame'],
['_top', 'Open in top frame (replaces all frames)'],
],

or if this could be reduced to a boolean. Or even let the editor decide if the href is internal or external like draftjs does, and no choice for the user.

Module name mappings not good in Yeoman Volto generator for volto-slate

After overcoming #44 as I said in that issue, I get these sort of fails from unit tests (part of the output of $ yarn test and there is no script $ yarn test-addon in the generated package.json file that I can run):

image

volto-slate/editor cannot be imported because it is not seen as an existing file or directory.

I need this working because I would like to use the latest Jest version for unit tests in volto-slate but when I updated the version of Jest here, I came over this issue for which, to make it progress, I would need an isolated testcase and I thought to make it based on Yeoman.

Compress Slate values before saving

I propose that we do a denormalization on save and a normalization on "load" of values. The normalization algoritm is the one in this function:

const normalizeToSlate = (editor, nodes) => {

The denormalization algorithm would be the "reverse" algorithm, it would remove the empty {text: ''} placeholders so that the JSON value is compressed before save. These placeholder nodes only make sense for SlateJS internals, they shouldn't have been exposed "to the world".

Image plugin should not execute if there's an text/html payload in the data

Copy/pasting from Excel puts an image and also a table in the data. The image plugin should look for this and (maybe optional) not insert an image in the content, but leave the table to be inserted.
Alternatively, it could insert the image but also leave the table, so the editor gets a chance to choose which version s/he prefers.

After going through steps in DEVELOP.md I get an empty Volto home page

image

(note: My Page is an attempt to create a Volto Page that also failed in some way)

I think it is a bug in plone.docker since that is where the home page I am used to comes from.

When I try to create a page, I do not get the block editor form I am used to but a properties page without Volto Slate installed in it:

image

stylelint issues

volto-slate]$ ../../../node_modules/stylelint/bin/stylelint.js 'src/**/*.{css,less}'

src/editor/plugins/StyleMenu/style.css
 11:3  ✖  Expected "font-style" to come before "font-weight"   order/properties-order

src/editor/plugins/Table/less/public.less
  1:13  ✖  Replace "A6A" with "a6a"                                     prettier/prettier     
  7:3   ✖  Expected "width" to come before "margin-bottom"              order/properties-order
  9:3   ✖  Expected "border-collapse" to come before "border-spacing"   order/properties-order
 11:6   ✖  Insert "⏎·"                                                  prettier/prettier     
 14:5   ✖  Expected "padding" to come before "border"                   order/properties-order

src/editor/plugins/Table/less/table.less
  1:13  ✖  Replace "A6A" with "a6a"                           prettier/prettier     
  3:31  ✖  Delete "⏎"                                         prettier/prettier     
 10:5   ✖  Expected "margin-top" to come before "font-size"   order/properties-order
 22:7   ✖  Expected "cursor" to come before "opacity"         order/properties-order
 29:2   ✖  Insert "⏎"                                         prettier/prettier

Replace custom-build saved selection with HOC

From https://gist.github.com/heyitsaamir/6089165fe6789eee170b46809cb61fc6

import React, { useContext, useRef } from 'react';

import { isEqual } from 'lodash';
import { Range } from 'slate';
import { ReactEditor, useSlate } from 'slate-react';

export const CurrentSelectionContext = React.createContext<{
  current: Range | null;
}>({ current: null });

export function withCurrentSelection<OriginalProps>(WrappedComponent: React.ComponentType<OriginalProps>) {
  return React.forwardRef((props: OriginalProps, ref) => {
    const editor = useSlate();
    const currentSelection = useRef<Range | null>(editor.selection);
    if (ReactEditor.isFocused(editor)) {
      if (!isEqual(currentSelection.current, editor.selection)) {
        currentSelection.current = editor.selection;
      }
    }

    return (
      <CurrentSelectionContext.Provider
        value={{
          current: currentSelection.current,
        }}
      >
        <WrappedComponent {...props} ref={ref} />
      </CurrentSelectionContext.Provider>
    );
  });
}
export const useCurrentSelection = () => useContext(CurrentSelectionContext);

Editor toolbar inline menu: paragraph style

Will you remove the feature of editor toolbar inline menu?
An inline style selection does what expected. A paragraph style selection does not have an effect as the class is not set.

Seite_bearbeiten

This helps:

GitHub_Desktop

If editor toolbar inline menu will still be a feature, I would be happy and I would place a PR. What are your plans with Slate?

Remove awkward empty implementation of getBlockProps

Sometimes editor.getBlockProps is used to detect if the editor is "block text" flavour. I've introduced an editor.isNotTextBlock that's set in the richtext editor flavours.

I think this should be cleaned up, it's awkward. Too many ways of doing the same thing, plus an overload that does nothing.

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.