readium / architecture Goto Github PK
View Code? Open in Web Editor NEWđ Documents the architecture of the Readium project
Home Page: https://readium.org/architecture
License: BSD 3-Clause "New" or "Revised" License
đ Documents the architecture of the Readium project
Home Page: https://readium.org/architecture
License: BSD 3-Clause "New" or "Revised" License
As a follow-up to our latest conference call (Oct. 26th 2016) we're going to explore how Readium 1 currently structures its main JSON document, and if we could leverage existing work on BFF & Web Publications: https://github.com/HadrienGardeur/webpub-manifest
This is a request to create repos for the project that aims at integration of
Readium 1 viewer with Readium 2 Streamer.
Here are some points on the way we approach this task:
Readium 2 streamer provides parse, fetch, serve functions effectively
replacing what is in readium-js epub-fetch directory.
Readium 2 Web Publication Manifest provides publication data model. This
corresponds to Readium 1 models from epub-model directory - package_document,
metadata, manifest.
Readium 1 PackageDocument is a principal data model that encompasses metadata,
manifest, spine, toc, media overlay etc. providing public interface for
readium-shared-js and readium-cfi-js. Here are some examples of this public
API functions:
generateTocListDOM, getSpineItem, getPageProgressionDirection.
Thus Readium 1 PackageDocument and Readium 2 Web Publication Manifest provide
the main data model for the publication, so if we can implement
PackageDocument interface based on the data in Web Publication Manifest we
should be able to cover a bulk of readium-shared-js and readium-cfi-js needs.
Based on the above the bulk of changes will be in readium-js and
readium-shared-js. As of now we have started the work by forking readium-js and
readium-shared-js into:
[email protected]:evidentpoint/readium-js.git
[email protected]:evidentpoint/readium-shared-js.git
In order to add visibility to this project we probably want to make them more
accessible to the team and have these repos officially under
https://github.com/readium
Since these repos will contain modified readium 1 code, we probably want to keep
this link in the naming, but also want to stress the fact that they are
integrating with r2 streamer.
My immediate thought would be readium-js-r2-streamer and
readium-shared-js-r2-streamer. Any other suggestions are welcome.
During our last conference call, I mentioned that several browser engines support rel="prerender": http://caniuse.com/#feat=link-rel-prerender
This is fairly widely implemented on the Web too, for instance Google includes rel="prerender" on the first result of a search if it's confident enough about it. In Chrome, this creates a separate process that prerenders the document and replaces the current tab once you follow the link.
This could be a good strategy on Android (Chomeview) and on desktop (Electron with Chromium or Edge), but won't work on iOS where we might instead rely on multiple webviews.
Has anyone tested rel="prerender" either with a prototype or with Readium-1? I'd like to figure out if this is an option for us, or if the audio/video/script issues that have been mentioned before would make this difficult to use.
Moving this from email to an issue:
rkwright wrote
Laurent reminded me earlier today that we still have a large number of open issues in R1. This is no surprise because many of them really ARE still problems, but most are relatively minor. The problem all along has been that developers are always happy to develop features but less enthusiastic about fixing bugs. Especially in open source projects and when their REAL boss is breathing down their neck. We will run into this same problem with R2 as well, I am sure so we need to think about that.
However, I am making another pass through the open issues in R1 and reading through them got me thinking. There is a HUGE amount of time and effort invested in those issues: investigating, fixing, experimenting, etc. An not only the remaining open issues but also all the issues that have been closed. Iâm trying to think of a way for us to troll through the issues and gather the info in a meaningful way. Even if R2 is better architected and designed, etc. many of the R1 issues arose not because of bad design or implementation (though that is true for some of them) but because the situation or problem was tricky.
As a follow-up to #36 we're moving away from using paths relative to the OPF in the streamer.
We'll now stictly use absolute paths based on the root of the container instead.
The following resource types that we parsed are affected:
While encryption.xml
parsing is not as directly affected by this change, we need to make sure that we still match resources correctly after this change.
In the streamer, we should now have absolute URIs in the following elements:
spine
resources
toc
, landmarks
, loi
, page-list
, ...)Let's say:
META-INF/container.xml
rootfile@href
=>
EPUB/package.opf
manifest>item@href
=>
chapter1.xhtml
A typical "fetcher" URL in the current implementations would look like:
https://r2.org/moby-dick.epub/chapter1.xhtml
Now, in my opinion, this is slightly "wrong", because the full path in the EPUB container is actually EPUB/chapter1.xhtml
(regardless of its zipped / unzipped status).
Furthermore (and more importantly), we have a problem with relative paths such as:
manifest>item@href
=> ../cover.jpg
...which would result in URLs such as:
https://r2.org/moby-dick.epub/../cover.jpg
(as you can see, the ..
notation interferes because it is not escaped)
So, wouldn't it be better to logically follow the EPUB container file structure?
i.e.:
https://r2.org/moby-dick.epub/cover.jpg
https://r2.org/moby-dick.epub/EPUB/chapter1.xhtml
Note that I implemented support for both syntaxes in the NodeJS streamer, as described here:
https://github.com/edrlab/r2-streamer-js/wiki/Demonstration#epub-resource-urls
OK, sorry if it feels like I'm bringing myself into at an early stage of discussion but it seems to me this is an important issue and it'd better be discussed at this point.
For the last four years, some people have been trying to improve UX in reflow using JavaScript. Historically, this has been painful since simple functions tend to grow into huge snippets of bloat made of conditional statements and pagination implementation workarounds. As a result, you often get poor performance, which actually deteriorate UXâand you can't necessarily afford to optimize those snippets because it costs the publisher money and time it is not willing to spend.
Problem is that even simple interactions might be painful. Letâs see some use cases.
Letâs say you want to use details
, which is a HTML5 tag.
Summary Goes Here
...this is hidden, collapsable content...
Every rendering engine but Trident/EdgeHTML now supports that (landed in Firefox 49) so it works in Reading Systems like iBooks, ADE on OS X, Readium, iOS apps using a web view, etc.
Problem is, it doesn't automatically trigger a pagination recalc. In other words, details
is expanded and contents at the end of your XHTML file may be pushed out of the âlast pageâ (overflow).
Obviously, this also apply to content you append/insert based on user interaction, content which is already in the DOM with display: none
and you show/hide, etc.
In this case, which is quite a standard pattern on the web, a public function to push pagination recalc would help. A lot. Or maybe something in the vein of regionOverset
.
asides
at first reading in order to focus on the primary content. But maybe he will expand some asides
at first reading because they explain concepts instead of extending them.details
extensively. The assumption is that a memento is a utility and should be designed as such (expanded details
would make it harder to parse when you're searching for something).display: none
was a no-go, he used visibility: hidden
. In order not to have whitespace everywhere in his book, he defined height
and overflow-y
for the answer container. But this is suboptimal since scroll might be buggy in some apps and each MCQ is not the same height on every device.Managing offset
and/or position
is tough when all RS don't implement pagination in the same manner. Some are using columns (in some conditions), others report negative values, others require a timeout, etc.
It might be debatable because a lot of people think you should not do that but custom methods could be useful.
Like, for instance, a method to get the page/spread on which the element is actually positioned. For the sake of simplification, something like:
var el = document.getElementById('where-is-waldo');
el.isOnPage();
Which could have properties like top, left, width, etc. but for the page/spread. Cf. getBoundingClientRect
And then you could theoretically position a modal hands down, even if you're not âa NASA engineerâ (quoted from people I actually train).
abbr
) in her essay. While she has used the title
attribute, it wonât work on touch devices (the tooltip only displays on mouse hover). She would like to use a popup/popover on mobile but pagination makes scripting much much more difficult than it should be (offset
, position
, viewport
etc.). As a result, her script works in some conditions but will fail spectacularly in others.To some extent, this is an extension of the two previous sections.
This is probably where a solid API could help authors improve eBooks spectacularly, by covering cases which aren't covered by default. Itâs not all about interactivity any longer, itâs about empowering usersâor at least helping them access books in the best conditions.
Sometimes you might want to override the RSâ settings (background-color, text color, etc.). Other times you might want to be in sync with those RSâ settings.
For instance, maybe you want to apply a different type scale when the font-size
user setting reaches a specific value (see Mabelâs use case). Or maybe you'd like to add a couple of settings depending on the existing RSâs settings.
letter-
and word-spacing
, and a reading rule based on the position of the mouse. This should probably be a plugin but for the time being, it is not an option so the script must be embedded in EPUB files.
background-color
can't necessarily be applied to the whole UI (but only the container, be it a div
or an iframe
);letter-
and word-spacing
needs pagination recalc as well;He doesn't have much time to deal with those issues, the project comes to a standstill.
I know an API with functions/methods isn't particularly easy to design and implement. It may well be debatable too.
However, it could remove a lot of the barriers limiting what we can do in reflow, the performance we can achieve and the frameworks/plugins we can build.
(Sorry for the inconvenience.)
[edit]
regionOverset
in âAdding/Removing Contentsâ;CodeBeat provides a free automated review of code in a wide variety of languages, including JavaScript, Swift, Go, TypeScript Java, and Kotlin. It is easy to use - just create a CodeBeat account and add your repository and branch. CodeBeat will then analyze the code on every checkin.
You can be notified in several ways:
Alexandre has been using it for his Swift work and has the results sent to his Slack channel. I use it myself for my "hobby" Javascript work (rkwright@github) and find it very useful. It is not a substitute for real code reviews, but it is very useful nonetheless.
Having it go directly into Slack for all of our projects might be a bit much, but might be useful.
I'll put an agenda item in next week's R2 meeting about this issue and we can discuss it.
As I mentioned before in another issue and on the latest weekly call, in an effort to be as transparent as possible, there's now a project board for Readium-2 at https://github.com/orgs/readium/projects/1
Project board are a relatively new feature on Github, and they can either be associated to:
When a board is associated to an organization, you can reference issues from any repo in there but you need to be a member of that organization to view the board (which limits its potential in terms of visibility and transparency).
When a board is associated to a repo, all you need is read access to the repo to see it.
I wasn't aware of the requirement regarding membership for organization-wide board, and being able to reference cross-repo issues sounded like a useful feature.
Should we revisit that decision and use a repo-level board instead? As long as we keep all epics on this repo, it should work too.
@HadrienGardeur
https://github.com/readium/r2-streamer-go/blob/master/parser/epub/smil.go#L7
type Body struct {
TextRef string `xml:"textref,attr"`
Seq []Seq `xml:"seq"`
Par []Par `xml:"par"`
}
type Seq struct {
TextRef string `xml:"textref,attr"`
Par []Par `xml:"par"`
Seq []Seq `xml:"seq"`
}
This breaks with SMIL files such as (the order of interspersed seq
and par
elements is important):
<smil>
<body>
<seq>
<par>
....
</par>
<seq>
....
</seq>
<par>
....
</par>
</seq>
<par>
....
</par>
</body>
</smil>
I addressed this in the NodeJS implementation by making sure body
extends seq
, and seq
has a sorted children
list, which items are either seq
(recursive) or par
:
https://github.com/edrlab/r2-streamer-js/blob/develop/src/parser/epub/smil-body.ts#L14
https://github.com/edrlab/r2-streamer-js/blob/develop/src/parser/epub/smil-seq.ts#L16
https://github.com/edrlab/r2-streamer-js/blob/develop/src/parser/epub/smil-par.ts#L18
Info given by D.Weck:
R1 in native "launchers" use HTTP server for all EPUB resources, although historically there was an attempt to only serve audio/video via HTTP (the rest was fed into the WebView using custom URL protocol handler). Since WKwebview, even the top-level reader.html + JS etc. are served via HTTP (used to be file:// app-bundle)
But R1 in Chrome app and Electron and Apache Cordova etc. do not use HTTP server.
Now that we are talking about developing more "per platform" native modules, in which case will we use a HTTP server and in which case will we use custom protocols?
In the Readium-2 engineering meeting on 9 November, the team discussed two big issues:
Previously, the contributors had agreed (at the behest of the Readium board) to generate three deliverables in Phase 1 of the Readum 2 project
where Phase 1 was to be completed in the November/December 2016 timeframe. As part of that process, the group reached a consensus that
However, one of the implications of this approach was that R2 would effectively be a complete rewrite of the existing codebase. Several members of the group were uncomfortable with this approach (see email thread here).
In the discussion on 9 November, however, the group came to the conclusion that trying to develop the code in an incremental fashion by developing pieces of Readium-2 separately then integrating them into a fork of Radium-1 was most likely an unworkable solution. The ripple of effect of changing APIs and the behavior of code modules would make that very difficult.
The group came to the conclusion that a more viable solution would be
To start with the most fundamental piece of an EPUB reading system, the parser
When the parser would be complete, move onto the next step (e.g. the model representing the parsed EPUB) and so on. Eventually, the completed and tested code would/could be âportedâ to native languages and libraries for iOS and Android. The TypeScript (transpiled to JavaScript) could be used as a replacement for the ReadiumJS stack as well.
Arguably, this represents a move from the original âwaterfall-likeâ design/implementation approach to a more agile approach.
Pros:
This allows the development to be done bottom-up in a more natural design process
There is little or no integration pain since the development is bottom up
The resulting code is cleanly developed (with typing) and associated tests
Cons:
The time from beginning to the process will very likely be much longer to reach native-code implementation since the TypeScript version must be developed first
Since the development would be agile, providing a scope and timeframe is infeasible, as is concrete interfaces win a specified timeframe
?
The 2 solutions we came up with, in chronological order, are:
The first solution is a custom Jekyll plugin called remote-include
.
It injects ressource which are outside of the local Jekyll repository (i.e. the repo where Jekyll is configured; vanilla include
/include_relative
can only access local ressources).
Pros :
Cons :
---
layout: post-using-remote-include
title: "Readium2 Streamer Roadmap"
date: 2017-03-23 11:36:00 +0100
categories: overview
permalink: /r2-streamer-roadmap/
---
{% remote_include https://raw.githubusercontent.com/readium/readium-2/master/streamer/roadmap.md %}
The code can be checked here on the develop branch of the readium site repo. You can also build it locally to see it live using bundler.
This is the second solution we came up with, trying to tackle the "auto regeneration" problem cited above.
This solution hasn't been fully implemented yet since it will change the architecture of the repo and the content of the files.
We create a gh-pages
branch on the readium-2
documentation repository.
Inside it we add the 'Jekyll conf+ressources' (/_includes/, /_layouts/,_config.yml, /assets/*).
We add a 'front matter' to each documentation file in order for Jekyll to process them (read convert .md
to .html
).
Pros :
Cons :
Here is the branch we made tests with.
Which solution would you like to see implemented?
Tree facts:
1/ Any project required a roadmap of some sort.
2/ Some Readium stakeholders are nervous about the Readium-2 roadmap and a possible clash between R1 and R2 adoption in 2017, therefore they'd like to know when R2 could constitute a proper replacement for R1.
3/ An open-source project which relies on the the dedication of community members cannot provide a propre timeframe for different versions of its software (even if part of the core team is paid for working on the project, as it is the case for EDRLab developers).
And a proposal:
What is the navigation pointer technology? CFI? Part of the EPUB standard, but has flaws
Something else? What?
This is a continuation of a conversation started in issue: #26 "Define a roadmap for Readium-2". The thrust is that some community members (myself included) feel that the Readium 2 label has become confusing and problematic due to the fact that it is not, strictly speaking, version increments of current projects, rather new projects that tackle similar functionality/use cases as those of existing projects, but with different technical architectures, goal sets, assumptions, development methodologies, and scope. e.g. apples and oranges vs the more traditional version upgrade/update conventions using numerical progression.
It seems to me that there are basic two sub-topics here:
There is currently no general consensus that the name should be changed. So this is a thread where various contributors can express their support of the change, and reasoning. Whereas others can express their opposition to the change and reasoning for that opposition. Ideally we will reach general consensus, however, if that is not possible to achieve it can be elevated to the Readium Board for consideration and vote.
If we are to adopt a new naming convention for communicating intent more clearly, and for organizing discreet modules into logical groupings, what should that new convention be?
Any and all input is much appreciated. I think this is an important issue and I will do my best to keep the conversation moving forward productively.
In EPUB 3.x, each spine item references a media overlay (SMIL) using an id/idref.
Since we plan on having our own syntax for media overlays (see #22), I don't think that we should necessarily adopt the same strategy as EPUB 3.x. Here's a first proposal:
links
to a service that can return media overlays for the complete publication, or for a specific HTML resourceI'm not sure yet how the spine item level should be handled:
Link
HTTP headerproperties
and a URI instead of an idcc @danielweck
The streamer is responsible for:
The Go version has started the implementation with the following ideas:
spine
/resources
using a single structureThis issue is meant to be an epic for all on-going development in Go/Swift/Java for this feature.
Over the years, metadata expression has changed quite a lot in the EPUB specs:
refines
and more complex terms in 3.xThe responsability of the streamer is to do all of the heavy lifting for app developers and provide them with a consistent output, no matter which version of EPUB is used.
How we express metadata in the Readium Web Publication Manifest is already heavily documented at https://github.com/readium/webpub-manifest/tree/master/contexts
For the most part, this is stable and only some very EPUB specific terms might be tweaked.
Documenting how each term should be parsed based on 2.0.1, 3.0, 3.0.1 and 3.1 is still a work in progress and will be documented at https://github.com/readium/readium-2/blob/master/streamer/parser/metadata.md
This is an epic for metadata parsing across all implementations of the streamer architecture.
The context is making EPUBs of historical fiction and non-fiction.
The problem is to combine traditional citing, by page and section, with structural references over multiple editions. Some of this is just a matter of setting up independent standards, but also having a reader that allows for this sort of use.
The secondary problem is not to overburden the original text with needless markup.
Imagine 15 different editions of the same book with different pagination and some changes in text.
Finding a specific reference, by choosing the edition and then the reference, should be external to the text source, but within the EPUB.
This means that the structural identity within the mark-up has to mediated visually and in substance. So that it can be found by the reader and copied from the reader retaining citing and containing the data fragment.
My conclusion is this can be elegantly achieved by using identifiable CSS fragments. For instance an âeditionâ fragment that simply suppresses (hides) some source material while revealing (visible) others. For instance the differences in editions of Darwinâs Origin of Species etc.,.
A pagination/section sheet which provides labels, or other indicators within elements.
An ACTIVE reader to use this it has to assemble CSS Fragments with the EPUB data into a JSON file that is copied. The reader would need a plugin support, for this should be indolently reviewed and also integrated into things like Zotero.
A PASSIVE EPUB with a default view and a selection system so that the user gets the reference visuals that suit their immediate need.
Perhaps there is an entirely different way of handling compounded publications and unambiguous referencing.
The questions is what is the approach to branching strategy overall for Readium-2. The two primary choices (though there might be others) are:
There are three basic branch/groups:
the master branch is created and labeled initially
the development branch is created by branching from the master. All development is done in the development branch, which is to say that developer's commits are pushed to the development branch when they are qualified. Ideally this "qualification" is done through pull-requests, but in any case, commits are made from the developer's local copies when the code is deemed clean.
When a feature branch is deemed ready, a pull-request is made targeting the develop branch (never the master)
periodically, the develop branch is judged ready to be merged into the master and a release is made. At this time:
There are two basic branch/groups:
the master branch is created and labeled initially
there is no development branch. Instead, commits from the developers are pushed to the master branch, but the head is neither tagged nor guaranteed to be 100% stable.
when it is time for a release,
Subsequent, commits by developers are to the master branch, but are ahead of the master's new tag so are not part of the release
In addition to providing the content of an OPF in a different serialization, the streamer will also be responsible for parsing SMIL files and providing them in a simplified JSON document.
What are the key principles and information that need to be preserved in SMIL? What can we simplify and streamline?
cc @danielweck
In the initial phase of this project, many different labels were created for issues here.
Since we now have a better idea of the purpose for this repo, I'd like to propose a simplification with the following labels:
I'll give a few examples:
Any thoughts?
There is much "agreement" that Readium-2 should have well-defined interfaces (APIs). What are those interfaces to? From? This clearly comes back to what is the overall architecture of Readium-2?
What language are they written in? JavaScript? TypeScript? IDL?
Should there be a pure âJavaScriptâ version, as there is in Readium-Now? I.e. a replacement for the Chrome Extension and/or the CloudReader?
Which of the modules that make up Readium-2 will be in a script language (e.g. JavaScript or TypeScript - as opposed to a native-language implementation. I.e. what modules will be the equivalent of readium-shared-js in Readium-1?
Should the goal be to be as cross-platform as possible or give up on that and write platform-specific implementations? E.g. Objective C/Swift on iOS, Java on Android, etc.
This is a meta issue to cover all TOC related issues in the streamer.
In EPUB 2.x and 3.x this means parsing:
Spec document for the Readium Web Publication Manifest is still a work in progress and will be referenced here.
Go version already supports a large chunk of this.
Weâre collecting feedback for Readium CSS and some requests may exceed the projectâs scope. This issue is intended to list those requests.
I assume youâll open specific issues for requests if needed so I may edit this first comment so that itâs easier to keep track. Iâll also include the source whenever possible so that you can require additional information.
mathml.css
and doesnât rely on webkitâs)background-color: red
on body
). Iâve just discovered that some Reading Systems actually do it.margin
in a chrome vs content waySome flavor of Ecmascript (e.g. 2016) or a fully-typed language such as TypeScript?
If so, which âtyped scriptâ language?
Most implementations of the streamer generate a pretty printed output of the Readium Web Publication Manifest.
To facilitate testing across implementations, we want to add a canonical output of that same manifest with the following rules:
links
http://localhost:3692
for example)We'll use the canonical
query parameter to determinate when we should generate this canonical form: http://www.example.com/manifest.json?canonical=true
.
What platforms should be supported?
iOS
Android
OSX
Windows
Linux
Chrome OS?
Chromebooks?
EPUB 2.x and 3.x metadata can be a little all over the place, we want to document how each metadata element should be treated when we parse them and populate our streamer's in memory model.
The end result should be a Markdown document in the streamer folder of the main repo.
This issue is for discussing code review strategy for readium 2 and the process for migrating existing projects from other organizations to the readium github org.
To start the discussion, I'd say that once a project is ready for production use all changes must be reviewed by another developer before being merged or released. Reviewers should check that the code is documented and tested as well. Ideally the reviewers should be other developers working on the same project, but if no one is available any readium developer may do a review.
For something that's still a prototype and not ready to be used by others, it's fine for developers to manage the project however they prefer. That said, it's nice to get early feedback from others who might use a project later - I'd have liked us to do more of that for the TypeScript projects particularly.
I'm not sure how this should relate to migrating projects into the readium github org.
In order to optimize performance between the streamer and other modules, we must make sure that the streamer implements proper HTTP caching.
A best practice document is available to summarize how the streamer should handle HTTP caching for the manifest, resources and APIs: https://github.com/readium/readium-2/blob/master/streamer/server/caching.md
I have to split and move the current NYPLNavigator + R2Navigator (demo app) to the Readium domain.
Both EPUB 2.x and EPUB 3.x support fallbacks for formats that are not core formats (XHTML + SVG in EPUB 3.x, but also DTBook in EPUB 2.x).
Since we're targeting browser engines with Readium 2, it seems very unnecessary to follow the same behavior.
Here's my proposal regarding fallbacks:
spine
should directly reference the fallback for all unknown media types, without any equivalent to the fallback
attributefallback
property in properties
This means that the streamer won't support DTBook-only EPUB 2.x, but I believe that's a reasonable enough compromise.
cc @danielweck @rkwright thoughts?
In the past, there have been several discussions of the relative security of using an internal HTTP server in Readium-1. The point was made (originally by @ryanackley - Ryan Ackley) that using common tools like WireShark, one can intercept the stream and grab its contents. This can happen whether the original content was encrypted or not. This is because the stream can be intercepted after the content has been decrypted by the DRM engine.
Before we try to determine the seriousness of this and/or try to determine ways to block such actions, it would be good if someone on the team would verify this exploit is possible. I am pretty sure Ryan is correct, but in any case, we need a way to verify if any proposed blocking action actually works.
With the current code, media overlays are not parsed when they're encrypted.
We need to add support for this feature by handling the following behavior:
links
or properties
) are present, even if we can't decrypt the SMIL files yetSource tree (no wiki pages, issues, PRs, gh-pages ... just Git develop branch):
https://github.com/edrlab/r2-streamer-js
Pre-compiled Javascript (ES5,6,7,8):
https://github.com/edrlab/r2-streamer-js-dist
TravisCI:
In addition to other similar services, the streamer will also expose a synthetic page list API.
The documentation is available at: https://github.com/readium/readium-2/blob/master/positions/README.md
In a previous conference call:
Aside from the issues of security related to the use of the an internal HTTP server in Readium (both 1, and now probably in 2), there are some more general issues related to the use of scripting with a browser engine. The attack vectors include:
@ryanackley wrote a document on these subjects some time ago. The doc is here
Synthetic page is an Adobe creation, cryptic.
We should find an alternative for
Page (the text fragment/segment between two synthetic breaks)
Page number (0 or 1 based?)
The current position, expressed as a percentage, in the publication.
Discussion started at:
#10 (comment)
See epic description.
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.