epiclab / synectic Goto Github PK
View Code? Open in Web Editor NEWCards-based IDE for research into context-aware, heuristic problem-solving development tools.
Home Page: https://epiclab.github.io/synectic/
License: MIT License
Cards-based IDE for research into context-aware, heuristic problem-solving development tools.
Home Page: https://epiclab.github.io/synectic/
License: MIT License
Synectic (v0.8.0 and higher) uses the native file selector dialog provided through Electron.Dialog.showOpenDialog()
, which provides a dialog window for users to select a local file to opened within the IDE. On Mac OS High Sierra (10.13), the following error is thrown when calling to the native file selector dialog:
objc[38863]: Class FIFinderSyncExtensionHost is implemented in both
/System/Library/PrivateFrameworks/FinderKit.framework/Versions/A/FinderKit (0x7fffa4f30210)
and /System/Library/PrivateFrameworks/FileProvider.framework/OverrideBundles
/FinderSyncCollaborationFileProviderOverride.bundle/Contents/MacOS
/FinderSyncCollaborationFileProviderOverride (0x115114dc8). One of the two will be used.
Which one is undefined.
This issue has been reported for XCode (link), lionheart/openradar-mirror
project on GitHub (link), and through a Java Exception (link). The root cause appears to be that Apple included both of these duplicate implementations in the release of High Sierra, and as of Mac OS Mojave (10.14.2) a fix has not been provided.
The Canvas
within Synectic was originally developed with an architecture that allows multiple instances within a single instance of the Synectic IDE. Additionally, the following features should be developed and added to Synectic:
Canvas
instance creation and switching should be enabled through the App Menus.Canvas
class should have functionality to save and reload the state of a canvas (i.e. storing the type, content, and position of cards/stacks within the canvas).Webpack provides support for the import()
syntax that conforms to the ECMAScript proposal for dynamic imports. Implementing this feature in Synectic will allow us to use the following on-demand module importing:
function getComponent() {
return import(/* webpackChunkName: "lodash" */ 'lodash').then(({ default: _ }) => {
var element = document.createElement('div');
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
}).catch(error => 'An error occurred while loading the component');
}
In particular, this feature will increase performance by reducing the number of brace
mode packages that must be imported into the Synectic namespace during run-time to only those mode packages required for the files open in cards on the canvas at any given time.
Per the Webpack documentation:
import()
calls usepromises
internally. If you useimport()
with older browsers, remember to shimPromise
using a polyfill such as es6-promise or promise-polyfill.
Additional insights and examples are discussed on Marius Schulz's blog post, TypeScript 2.4: Dynamic import() Expressions, as well as the Webpack Lazy Loading documentation. The brace
project also includes issue thlorenz/brace#113, which discusses how to make use of either the import()
or require.ensure
syntax for dynamically loading the Ace mode files required for setting the syntax highlighting mode in an active Ace Editor window.
When dragging two cards on top of one another, they instantly disappear. The DOM elements are still there in the upper left corner, but they are invisible to the user and uninteractible.
It should be able to:
Good to have:
The Terminal
class should derive from the Card
class, and provide basic terminal interactions. The following interactions represent the basic functional set of interactions that should be supported in an initial version:
The terminal should behavior in the same native manner as the underlying terminal/command prompt of the host OS, i.e.:
CD
, DIR
, RD
, RENAME
, etc.).bash
, tcsh
, xterm
) and accept related commands (cd
, ls
, rmdir
, mv
, etc.).During merge conflicts and when developers examine version history, it is sometimes necessary to compare versions of the same file between branches (both local and remote) in order to understand what has changed. The git protocol (either in a command-line tool or a GUI interface) does not currently allow for easily switching between branch versions on a per-file basis. Changing branches is a project-wide change, which makes it difficult to maintain a current working position in a particular file of interest if you would like to examine the differences in that file in comparison to another branch. Therefore, the following features should be added to synectic
:
Card
.Composition
card that shows the lines of code added (shown as code highlighted in green) and removed (shown as code highlighted in red). Visually, these cards are similar to Editor
cards but represent the conflicting files involved in a merge conflict.Card
instances to see highlighted changes.Notes should allow for adding clickable hyperlinks within the text of the note. These hyperlinks should target:
Editor
card that is part of the annotation.WebBrowser
card that is part of the annotation.Editor
card on the canvas.WebBrowser
card on the canvas.WebBrowser
card on the canvas.For each of these cases, the following actions should occur when the associated hyperlink is clicked:
Editor
card should scroll to and highlight the specified line.WebBrowser
card should scroll to the specified position.Editor
card should scroll to and highlight the specified line, and the Editor
card should have highlight
enabled.WebBrowser
card should scroll to the specified position, and the WebBrowser
card should have highlight
enabled.WebBrowser
card should be opened and scroll to the specified position.Note: Hyperlinks targeting code files not currently open within the canvas will not be supported at this time. Synectic does not maintain a concept of code projects, and therefore any search for a specific unopened code file would require searching across all local directories and potentially requiring significant delays if a user's local file system has a lot of directories.
Files like .gitignore
or LICENSE
can't be opened because they don't have file extensions. (aren't recognized, so get a null handler from the filetypes)
The user should be able to active/deactivate annotations
Communicating status and requesting user input requires a uniform and consistent UI for notifications. Borrowing from Google's Material Design, the following features are required:
The Browser
component will provide web browser capabilities within a card, allowing users to view websites while working within Synectic. The initial set of features are:
Navigation
Browser
component should include an address that displays the currently loaded URL.Browser
component should allow users to load websites through manually entered URLs in adherence to the behavior of the URL API. This should be asynchronous (i.e. non-blocking of other UI interactions).Browser
component should allow users to reload the currently loaded website.Browser
component should allow users to click on links in a loaded website and:
History
Browser
component should allow users to navigate back in the browser session history in adherence to the behavior of the History.back
API.Browser
component should allow users to navigate forward in the browser session history in adherence to the behavior of the History.forward
API.Browser
component should allow users to use the go command in the browser session history in adherence to the behavior of the History.go
API.Bookmarks
Browser
component should allow users to set the currently loaded URL as a bookmark.Browser
component should visually indicate that the currently loaded URL has been bookmarked.Browser
component should allow users to remove the currently loaded URL from bookmarks.Browser
component should display a list of currently bookmarked URLs, and allow URLs to be directly removed from the list.Scroll Navigation
Browser
component should allow the scroll position within a website to be set externally (i.e. other elements within Synectic should be able to update the scroll position; see Ben Carp's response to the StackOverflow question ReactJS how to scroll to an element).Error Handling
Browser
should be able to validate URLs entered into the address bar and provide visual indicators until the entered URL has been corrected. The TypeScript base library includes a URL class that adheres to the WhatWG URL specification.Browser
should offer suggestions for adding/correcting bad URLs that cannot be validated (i.e. suggesting to add a .com
to the end of the URL https://github
).Browser
should provide visual indicators for HTTP status codes, especially errors such as 404 Not Found and 400 Bad Request.All of the following build scripts fail to complete: build
, build-all
, build-mac
, build-win
, build-linux
, and rebuild
. Each rule uses electron-packager to prepare and package Synectic IDE, which internally uses npm prune --production
unless the --no-prune
flag is set. Since all of the above listed build scripts do not set the --no-prune
flag, the following error appears:
Packaging app for platform darwin x64 using electron v1.6.11
Command failed: npm prune --production
npm ERR! May not delete: /private/var/folders/45/z27gvn2d30qfrkbjcbpm2nrc0000gn/T/electron-packager/darwin-x64/Synectic-darwin-x64/Electron.app/Contents/Resources/app/node_modules/.bin
This issue is caused by a recent change in [email protected], and will not be fixed until either [email protected] or a [email protected] bugfix release. Tracking resolution via the following issue on the npm/npm project: [email protected]: npm prune --production fails. We will update to the latest version of npm when it becomes available, in order to resolve this build issue.
The transition from one Canvas
instance to another Canvas
instance is not easily discernible and visually understandable to users. Therefore, a slide animation should be implemented to visually illustrate the switch between Canvas
instances. The tie-in point for implementation should be to the AppManager.updateCanvasSelected()
function (in lib/manager.js
).
Example animation for the sliding between elements on a canvas:
To alleviate the burden of asking users to navigate to a release page, download, and reinstall after each new synectic
release, we need to enable auto-updating within the application. However, per the documentation available on the autoUpdater
module there is the additional requirement that a multi-platform release server be setup and configured.
autoUpdater
module and associated code.autoUpdater
module and code that handles automatically checking for updates from the selected multi-platform release server.When adding Card
instances to a Stack
, especially when doing so via the selection and right-click menu, the order in which cards are cascaded in the stack is not visually represented by the cards being stacked according to that ordering.
The following screenshot illustrates this issue, where the OCR.ts
card is shown above the test2.js
card instead of adhering to the ordering. The expected result is that all cards are stacked one-above-the-other in the ordering that they are show in the stack, with the lowest card being in the upper left-hand corner and the highest card being in the lower right-hand corner.
The use of html-webpack-plugin
and html-loader
has previously had compatibility issues when attempting to inject custom chunks and fields into HTML using the HtmlWebpackPlugin
and the title
field.
In order to track and evaluate the effects of different interactions on context and problem-solving, the Synectic IDE needs to have an event logging system to aggregate time-series data regarding events (and as an initial step towards event replay).
The initial logging system needs to keep track of the following events:
Canvas
creation: timestamp
, canvasId
, height
, width
Canvas
resize: timestamp
, canvasId
, oldHeight
, oldWidth
, newHeight
, newWidth
Card
creation: timestamp
, cardId
, cardType
, createdBy
, createdOn
Card
movement: timestamp
, cardId
, beforeTop
, beforeLeft
, afterTop
, afterLeft
Stack
creation: timestamp
, bottomCardId
, topCardId
, createdOn
Stack
movement: timestamp
, stackId
, beforeTop
, beforeLeft
, afterTop
, afterLeft
Stack
card addition: timestamp
, cardId
, stackId
, stackSize
Stack
card removal: timestamp
, cardId
, stackId
, stackPos
Note: The id
field defined in the Card
, Stack
, and Canvas
classes is not guaranteed to be a unique ID and is instead used to manage the current workspace of the application. Therefore, this id
field should not be used for the cardId
, stackId
, canvasId
, createdOn
, bottomCardId
, or topCardId
fields listed above. The resolution of #10 will provide a valid uuid
field for use with both Card
and Stack
instances, and thus is a blocker for this issue.
The CodeEditor
class was previously developed in the Bonsai (nelsonni/bonsai) repository. With the following issue describing the process:
The following features require porting from Bonsai, extending, and integrating into Synectic:
CodeEditor
class needs to extend from the Card
class.CodeEditor
class needs to rely on the ace-code-editor npm package for language-specific syntax highlighting and support.CodeEditor
needs to implement content scaling for full-screen/half-screen expansion, which is stubbed out in the Card
class.CodeEditor
needs to accept copy & pasted code snippets for either integrating into an already open CodeEditor
card, or integrating into a newly instantiated CodeEditor
card.Card
instances.Link
) between two ends( card/stack), in middle of which there is a text box input( Note
)Note
s allow multi-line text to be input and displayed.Link
s between a Stack
and another Card
.Link
s between two Stack
instances.Provide loosely-coupled connections to git init
, git branch
, git remote
commands which can be activated from AppMenu
options which provide feedback via Dialog.notice
or Dialog.dialog
elements.
The results of running these commands from AppMenu
options should match the underlying git
command results that would be displayed from a terminal, including error messages (e.g. the message fatal: Not a git repository (or any of the parent directories): .git
when attempting to execute git status
from a directory that does not contain a .git
file).
During merge conflict resolutions that include multiple files or chunks, staging fixes for each can lead to situations in which some fixes negatively impact others. For example, imagine if two conflicting chunks occurred in the same method; one at the top of the method and one towards the bottom. The chunk at the top of the method is fixed by a simple refactoring of the algorithm on the lines comprising that chunk, whereas the chunk at the bottom of the method requires a major rewrite of the method and includes merging with another related method. If each conflicting chunk is dealt with separately, the resulting fixes will overlap and become additional conflicts. Therefore, the following features should be added to synectic
:
Card
instances contained within a Stack
.Stack
instances to show the branch or branches of the Card
instanced contained on the Stack
.Staging
card should allow for removing and reordering patches.Staging
card should allow individual patches to be split into separate smaller patches.Editor
card (if the particular file is open in the Canvas
).Staging
card should check each newly added patch for overlap with any other patches already on the list.Staging
card list.Provide a terminal-like representation of the output provided by all regular git
commands (Git Reference Documentation). This output should not be directly interactive (e.g. users should not be able to enter additional commands similar to a functioning terminal window). This assumes that issue #27 has not been completed, otherwise, this stage should simply provide tie-in for the underlying git
system (unless not installed) as provided on the host OS.
Cards require a location for displaying meta-information (e.g. created/modified timestamps, associated file path, Git repository status, etc.). The current UI for Card
instances already contains a header with a title and multiple buttons, along with the content region which can also contain complex UI elements. Therefore, providing a back face to each Card
instance will allow for card-specific information which is not directly part of the content of the card and is intermittently relevant to the user to be maintained with the card.
To allow for switching between the front and back faces of a Card
instance, a button should allow for a flip animation to transition forward and backward between the faces of the card. Example animation for the flip effect on a card:
The Stack
class was previously developed in the Bonsai (nelsonni/bonsai) repository. With the following issues describing the process:
The following features require porting from Bonsai, extending, and integrating into Synectic:
Stack
that allows an infinite number of cards to be included at instantiation.Stack
borders need to dynamically scale to contain an infinite number of cards contained within the Stack
instance.Card
instances added to a Stack
need to have the JQuery draggable functionality disabled, and automatically re-enabled upon either individually being removed from the Stack
or having the containing Stack
be closed.Card
instances contained within a Stack
needs to rely on HTML DOM containment instead of the cascadeCards()
method for maintaining correct positioning in comparison to the containing Stack
object.Card
instances contained within a Stack
need to be positioned closer together as more cards are added to the Stack
in order to prevent extremely large Stack
instances from taking up the entire viewable window.Per the reports of this error from @SoutiRini, the [email protected]
version appears to have an error that was previously masked but has appeared due to an update to the typescript
package which allowed make deeper type inferences for class inheritance that involves a super class declaring and managing instances of parent
. When attempting to compile, the tsc
compiler gives the following error messages:
webpack --config webpack.config.js --progress --colors
Version: webpack 3.11.0
ERROR in /Users/Rini/Documents/Synectic/synectic/src/core/Stack.ts
[tsl] ERROR in /Users/Rini/Documents/Synectic/synectic/src/core/Stack.ts(8,10)
TS2564: Property 'parent' has no initializer and is not definitely assigned in the constructor.
ERROR in /Users/Rini/Documents/Synectic/synectic/src/core/Stack.ts
[tsl] ERROR in /Users/Rini/Documents/Synectic/synectic/src/core/Stack.ts(9,10)
TS2564: Property 'children' has no initializer and is not definitely assigned in the constructor.
The following screenshots demonstrate these errors:
The GitHub_Tracker
card class should rely upon the GitHub REST API to provide a consistent, flexible, and integrated issue tracking experience. The GitHub website is optimized for both desktop and mobile browsers, however even though the WebBrowser
card can load these pages it does not provide a "native" and actionable viewing of the underlying information. Thus, the GitHub_Tracker
card should have the following features:
GitHub_Tracker
class should extend from the Card
class.GitHub_Tracker
class needs to accept and remember authentication tokens and information.GitHub_Tracker
class needs to allow for exploring both GitHub Issues and Pull Requests.GitHub_Tracker
class needs to check and maintain the same state of information as available directly on the GitHub website (i.e. presenting up-to-date information).GitHub_Tracker
class needs to allow for adding new comments to both GitHub Issues and Pull Requests.GitHub_Tracker
class needs to allow copy & pasted text to be both pulled from and pasted into the content in a GitHub_Issues
card.GitHub_Tracker
class needs to implement content scaling for full-screen/half-screen expansion, which is stubbed out in the Card
class.The electron/spectron
package provides a mock environment through the use of require('spectron').Application
, which pulls in and executes main.js
from the target project (e.g. synectic/main.js
for this project). This environment has access to all local files from the target project, but creates a new namespace for execution purposes (also pulling additional functionality for testing purposes).
However, this mock environment does not have access to the jquery-ui
package, since it is pulled in via <link>
and <script>
tags in lib/index.html
(through a dynamic link loader and lib/init.js
). This causes test/card-test.js
and test/canvas-test.js
to fail tests with the following messages:
1) cards interactions creates a Card instance:
TypeError: $(...).draggable is not a function
at Card.toggleDraggable (app/Card.js:42:20)
at new Card (app/Card.js:30:21)
at Context.<anonymous> (test/card-test.js:27:16)
The current work-around for this issue is that the Card
constructor includes a modal
parameter option which can be set to false
in order to disable the setting of $(card).toggleDraggable()
(which requires the jquery-ui
package). A better solution would be to pull in the jquery-ui
package into the mock environment during testing.
An annotation Link
is a line which connects two ends of an annotation ( Card
/ Stack
) in middle of which there is a text box input( Note
).
User starts drawing a Link
by clicking down the mouse on the boundary of one of the end elements ( Card
or Stack
),
User should be able to draw the line by dragging the mouse.
User end drawing the Link
by licking up the mouse on the boundary of the other end elements ( Card
or Stack
).
User can right click on the Link
and select to delete the Link
User can change the place of the Link
on the element
To allow organizational structures such as the Group
class to provide usable functionality, it is necessary to enable Card
instances to be selected based upon an area of the Canvas
that contains several relevant Card
instances. This selection will occur through the following path:
Canvas
, hold the click down, and drag away from the initial point to form a rectangular selection area.Card
instances that reside within the rectangle should be considered selected, and a right-click on one of the selected Card
instances (denoted by a highlighted border color on all selected Card
instances) should provide a context menu that includes Create Stack
and Create Group
options.Electron 2.0.0 includes new warnings regarding the security implications of using Electron and the underlying Chromium engine in local application settings. The run-time warning indicates:
Electron Security Warning (Insecure Content-Security-Policy) This renderer process has either no Content Security Policy set or a policy with "unsafe-eval" enabled. This exposes users of this app to unnecessary security risks.
To mitigate this issue, the ElectronJS developers have included links to https://electronjs.org/docs/tutorial/security. This website provides the following steps as part of evaluating the security of your own Electron application (we will need to do each step for synectic
):
In addition, where possible these security measures should be added either as unit tests in the test/
directory of the project, or as tslint
rules to validate that these security measures remain in place in the future.
The TextEditor
class should provide Markdown language support within the text content area. This support should include both of the following:
**bold**
should result in bold text).Note: A reasonable solution to this issue might be to investigate the use of the markdown
package on npm.
The FileExplorer
card should operate in a similar fashion to file explorers available in other IDEs and applications, except for certain key functionality alterations as indicated below. The following features should be developed and integrated into Synectic:
FileExplorer
card needs to be a React component that uses the Redux store for state.FileExploror
card needs to allow clicking on files to open a Card
component containing the specific handler type for that file (i.e. clicking on foo.js
should result in a new Editor
card added to Redux, and therefore loaded onto the canvas).FileExplorer
card should indicate the current git branch, and options for switching between available branches (which should result in any new files from that branch being loaded into the FileExplorer
).FileExplorer
card needs to implement content scaling for full-screen/half-screen expansion, which should result in the Card
being stretched to 20% of the available width of the Canvas
component.To allow organizational structures such as the Group
class to provide usable functionality, it is necessary to enable Card
instances to be individually selected and grouped together (in the sense that they are tracked as a group, not that they are pulled to a shared location on the Canvas
). This selection will occur by two different paths:
Cmd
(โ
) key down while selecting Card
instances from the Canvas
.Card
instance and selecting Initiate Group
, which will allow additional Card
instances to be selected from the same Canvas
in order to add them to the new Group
. This will also add a floating button element (labelled Create Group
) along the outer edge of the first Card
(which was used to initiate the grouping).The loading and saving of Card
content from local files allows for changes made in the cards to be preserved beyond the life cycle of an IDE execution.
The following features are required for allowing file I/O in Synectic:
Open...
dialogCard
instanceCard
instance to corresponding fileCard
for initiating a "save to file" actionCard
content when corresponding file is changedAlthough there are several different workflows based on the git protocol (i.e. Centralized Workflow, Feature Branch Workflow, Gitflow Workflow, Forking Workflow, etc.), the basic tenets are that changes must be staged, committed, and merged into a repository.
Merge conflicts can occur in multiple files, with multiple conflicting chunks in each file. Resolving the conflict requires dealing with each conflicting chunk individually and staging the fixes until all of them have been dealt with. The git protocol typically requires staging these fixes on a per-file basis (although git interactive staging provides for per-chunk staging).
For Synectic, our philosophy of allowing cards to represent files and data from any known git branches without regard to the current branch means that we have additional design considerations for this type of workflow:
The id
field defined in the Card
and Stack
classes is not guaranteed to be a unique ID and is instead used to manage the set of Card
or Stack
instances currently placed on a Canvas
. In order to provide a universally unique identifier (uuid), a new uuid
field (using the uuid package) must be added to the Card
and Stack
class definitions in order to have a truly unique ID to identify individual Card
and Stack
instances across multiple IDE sessions, multiple Canvas
instances, and aggregated logs from multiple systems.
Provide reasonable keyboard shortcuts for all options in the Control
menu on the Application Menu. The Control
menu currently requires shortcuts for:
New Canvas
New Card
Switch Canvas
, including automatic numbers for individual Canvas
instancesThe associated shortcut key sequences should be listed next to the corresponding option within the Control
menu once properly configured.
Card
or Stack
) and drag it on the canvas.Link
) connected to a dragging element(Card
or Stack
)it should stay connected to the element.Note
) should always be connected to the middle of the Link
.Provide a consolidation notification system that notifies users upon success/failure of git
commands. This should utilize or extend the Dialog
factory and/or use any additional notification enhancements provided (e.g. if a notification bar is added to the bottom of the IDE).
Provide the ability to compose a commit within Synectic IDE such that the system allows:
Previous solutions for loading the jquery
and jquery-ui
modules into the Electron renderer namespace required the use of:
externals: {
jquery: 'jQuery'
}
This solution required treating JQuery as an external module, which implies some enhanced security restrictions under Webpack 4.
A better solution under Webpack 4 involves using the ProvidePlugin
feature (StackOverflow ref):
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
"window.jQuery": "jquery",
})
]
Having a Note Box in which user typed their note related to an annotation.
user should be able to type in the Note box
Note Box should support multi-line texts
Size ob the Note Box change according to the text
It seems that if a card is placed on another card that has not been moved since being created, you lose the ability to remove the card from the stack without further issues.
Originally posted by @hcoffey1 in #56 (comment)
Similar to the Stack
class, a Group
class should provide for selecting and grouping cards together without forcing those underlying Card
objects to be pulled into a stack. The objects contained within a Group
will remain in their original location on the canvas and instead have a tag attached to them to indicate that they are grouped together.
Git integration is essential for modern software development projects, especially when multiple developers need to collaborate on the same codebase. The features of git should be supported throughout Synectic, and versioning should be supported in ways that translate directly to availablegit
commands (i.e. do not break the git
API in order to enhance it). The following features should be developed and integrated into Synectic:
CodeEditor
card containing a file currently under version control.git fetch
, git pull
, and git push
commands on demand by users.git
commands (e.g. if git fetch
times out, git pull
results in a merge conflict, etc.).The functionality provided inInteractions.ts
is imported into Card.ts
and Stack.ts
through statements such as:
import { OptionState, Draggable, Droppable, Selectable } from './interactions.'
The capitalization of the filename, and the lowercase import statements, are at odds with each other on case-sensitive OS (such as Linux) and cause a run-time error since they are treated as being different filenames for matching and import purposes.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.