liblouis / liblouis Goto Github PK
View Code? Open in Web Editor NEWOpen-source braille translator and back-translator.
Home Page: http://liblouis.io
License: GNU Lesser General Public License v2.1
Open-source braille translator and back-translator.
Home Page: http://liblouis.io
License: GNU Lesser General Public License v2.1
If the cursor is on a character that isn't defined in the braille table, then the compbrlAtCursor flag causes the character after the cursor to be removed. Maybe also with compbrlLeftCursor, I didn't test that.
Here's an example using the Python wrapper, since that was the easiest to test with. I think this is a problem in the C code, not the wrapper.
>>> import louis
>>> tables=['D:\\louis\\tables\\en-us-comp8.ctb','D:\\louis\\tables\\braille-patterns.cti']
>>> text=u'héllo'
>>> typeforms=(louis.plain_text,)*len(text)
>>> mode=louis.dotsIO|louis.pass1Only|louis.compbrlAtCursor
>>> cursorPos=0
>>> louis.translate(tables,text,typeforms,mode=mode,cursorPos=cursorPos)
<<< (u'\u8013\u8004\u8073\u802d\u8034\u8034\u8011\u8014\u8004\u8007\u8007\u8015', [0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4], [0, 1, 9, 10, 11], 0)
>>> cursorPos=1
>>> louis.translate(tables,text,typeforms,mode=mode,cursorPos=cursorPos)
<<< (u'\u8013\u8004\u8073\u802d\u8034\u8034\u8011\u8014\u8004\u8007\u8015', [0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 4], [0, 1, 1, 9, 10], 1)
>>> mode=louis.dotsIO|louis.pass1Only
>>> louis.translate(tables,text,typeforms,mode=mode,cursorPos=cursorPos)
<<< (u'\u8013\u8004\u8073\u802d\u8034\u8034\u8011\u8014\u8004\u8007\u8007\u8015', [0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4], [0, 1, 9, 10, 11], 1)
-*- mode: compilation; default-directory: "~/src/liblouis-mingw/" -*-
Compilation started at Mon Jun 1 16:30:24
make
Making all in gnulib
make[1]: Entering directory `/home/eglic/src/liblouis-mingw/gnulib'
make all-recursive
make[2]: Entering directory `/home/eglic/src/liblouis-mingw/gnulib'
make[3]: Entering directory `/home/eglic/src/liblouis-mingw/gnulib'
make[3]: Nothing to be done for `all-am'.
make[3]: Leaving directory `/home/eglic/src/liblouis-mingw/gnulib'
make[2]: Leaving directory `/home/eglic/src/liblouis-mingw/gnulib'
make[1]: Leaving directory `/home/eglic/src/liblouis-mingw/gnulib'
Making all in liblouis
make[1]: Entering directory `/home/eglic/src/liblouis-mingw/liblouis'
make all-am
make[2]: Entering directory `/home/eglic/src/liblouis-mingw/liblouis'
/bin/bash ../libtool --tag=CC --mode=link i586-mingw32msvc-gcc -std=gnu99 -g -O2 -Wl,--add-stdcall-alias -version-info 8:0:6 -no-undefined -avoid-version -o liblouis.la -rpath /tmp/liblouis-mingw32msvc/lib lou_backTranslateString.lo compileTranslationTable.lo logging.lo lou_translateString.lo wrappers.lo findTable.lo
libtool: link: rm -fr .libs/liblouis.dll.a
libtool: link: i586-mingw32msvc-gcc -std=gnu99 -shared .libs/lou_backTranslateString.o .libs/compileTranslationTable.o .libs/logging.o .libs/lou_translateString.o .libs/wrappers.o .libs/findTable.o -O2 -Wl,--add-stdcall-alias -o .libs/liblouis.dll -Wl,--enable-auto-image-base -Xlinker --out-implib -Xlinker .libs/liblouis.dll.a
Creating library file: .libs/liblouis.dll.a
.libs/findTable.o: In function `parseQuery':
/home/eglic/src/liblouis-mingw/liblouis/findTable.c:338: undefined reference to `_strndup'
/home/eglic/src/liblouis-mingw/liblouis/findTable.c:339: undefined reference to `_strndup'
.libs/findTable.o: In function `listFiles':
/home/eglic/src/liblouis-mingw/liblouis/findTable.c:570: undefined reference to `_strndup'
collect2: ld returned 1 exit status
make[2]: *** [liblouis.la] Error 1
make[2]: Leaving directory `/home/eglic/src/liblouis-mingw/liblouis'
make[1]: *** [all] Error 2
make[1]: Leaving directory `/home/eglic/src/liblouis-mingw/liblouis'
make: *** [all-recursive] Error 1
Compilation exited abnormally with code 2 at Mon Jun 1 16:30:24
Ideally all tables that are intended to be included in other tables should actually be included. We should not expect the user to know which tables to include for which purpose and at which point it should be included (the order of including tables matters). Display tables are an exception because they have a special meaning and they are always the first table in a table list.
So ideally the user should only have to specify two tables, one display table and one translation table. The translation table will contain all the necessary metadata to be able to select it based on a list of features (see #41).
See discussion at https://www.freelists.org/post/liblouis-liblouisxml/lou-translate-unicode-output.
Waiting for a patch from @simait.
A possible enhancement to the new opcodes introduced in issue #50 could be to combine certain groups of opcodes into a single opcode. E.g. { firstwordital
, firstwordbold
, firstwordunder
, ... } are combined into a single opcode named firstwordemph
which is followed by a class argument { ital
, bold
, under
, ... }. This could improve the readability and maintainability of both tables and code. Also it could make it less UEB specific.
So we're talking about these opcodes:
firstword*
lastwordbefore*
lastwordafter*
len*phrase
firstletter*
lastletter*
singleletter*
*word
*wordstop
* = {ital, bold, under, caps, script, trans1, trans2, trans3, trans4, trans5}
There are 9 × 10 = 90 possible combinations and each of them has its own opcode. The idea is to replace this with:
firstwordemph *
lastwordbeforeemph *
lastwordafteremph *
lenemphphrase *
firstletteremph *
lastletteremph *
singleletteremph *
emphword *
emphwordstop *
* = {ital, bold, under, ...}
*
must be an "emphasis class" previously defined with a rule of the form emphclass <name>
. Possibly ital
, bold
and under
could be predefined emphasis classes, but the possible classes are not limited to those values, nor are they limited to the list of 10 values that we have now. caps
and script
may have to be treated separately.
The difference with the current situation is that there are only 9 opcodes, that the names can be freely chosen, and that the possible classes are not limited.
The order of class definitions determines how typeform bits are mapped to the classes. The class order could also be documented in the table header.
Using the en-us-brf.dis, eo-g1.ctb
tables the string "defgDEFGdefg" translates to "DEFG..DEFG.'DEFG" when liblouis is compiled with ucs2. However when compiled with ucs4 it translates to "DEFG.D.E.F.G.'DEFG"
Input: 'defgDEFGdefg'
Expected: 'DEFG..DEFG.'DEFG' (length 16)
Received: 'DEFG.D.E.F.G.'DEFG' (length 18)
Diff: Expected '.' but received 'D' in index 5
This problem occurs in current master, i.e. before the ueb changes.
See branch "zstanecic_tables" at https://github.com/zstanecic/liblouis
To do:
Related issues:
Basically so that we can run the harness in make check
. On master, we ignore all the failing tests so that make check succeeds. This also allows us to selectively remove xfail flags so that we can focus on a few failing tests without getting tons of failures so that we can not see the wood for the trees.
Alternative to xfail is an "ignore" flag, but xfail is better because it notifies us when we can remove the flag.
Nocross is currently not affected by the opcodes nocont and compbrl. Nocross should probably be affected like all the other contraction opcodes.
I haven't heard of UIB. Did you mean UEB?
** New features
*** New Braille tables
The yaml tests use a function error_at_line
which is only available on systems that are based on glibc.
One solution would be to use the error module from gnulib
Make nocross
into a "prefix" rule, i.e. it must be combined with another rule (like noback
and nofor
)
For example:
nocross endword ...
would mean: only apply the contraction when the characters do not cross syllable boundaries AND are at the end of a word.
In order to ensure backwards compatiblity, nocross
would have to become an alias for nocross always
, although that may prove to be difficult to implement because of possible ambiguities.
When there are spaces within arithmetic equations, such as "12 + 2 = 14", the resulting UEB appears correct, with a numeric indicator before each number sequence. However, if there are no spaces around the operators, then the numeric indicator is not consistently applied.
Sample input, four equations with spaces, then the four equations without spaces
12 + 2 = 14
12 - 2 = 10
12 * 2 = 24
12 / 2 = 6
12+2=24
12-2=10
12*2=24
12/2=6
Output from lou_translate:
$ lou_translate -f en-ueb-g1.ctb < ueb-math-samples.txt
# ab "6 #b "7 #ad
# ab-#b "7 #aj
# ab "9 #b "7 #bd
# ab _/ #b "7 #f
# ab"6#b"7#bd
# ab-b"7#aj
# ab"9b"7#bd
# ab_/b"7#f
It appears that the numeric indicator is showing up correctly for the plus sign and equals symbol, but not for the minus sign, multiplication sign, or division sign.
This is using lou_translate v2.6.4.
Hi,
I would like to suggest that the "correct" opcode should be changed to also work in back-translation as an extra pass after the actual back-translation. It was primarily meant to deal with scanos and the like, and currently only works in forward translation. However, it would also be very useful in back-translation, because the result of back-translation is sometimes ambiguous, simply because Braille was made to be read by humans, not machines.
I don't have any good examples in English, but I am sure that others could find them. In Danish, for instance, all accented letters are written in the same way in 6 dots regardless of which accent is used. e acute and e grave look the same (5-15). Yes, what a system, but I don't have the power to change it, unfortunately. (smile) There must be similar if not so stupid examples in other languages.
Alternatively, one could of course use "nofor always", but it is less safe, more messy, and harder to decipher. besides, in my case, I would have to include the entries twice, once for grade 1 and once for grade 2.
I know this would create an incompatibility with tables that already use the "correct" opcode for scanos. They would have to write "noback correct" instead.
Best regards
Bue Vester-andersen
Wait until all the pull requests are merged. Try to keep the history.
When compiling with VS and warning level set > 1, you will receive quite a few warnings. At warning level 4, you get 178 lines of output. At level 3, which is a bit less "motherish", you still get about 80 lines of output. Many of the warnings are about the use of unsafe functions, e.g. _vsnprintf() vs. _vsn_printf_s(). Apparently, the save version will truncate its buffer if needed, where as the unsafe version might just override adjacent memory, potentially leading to nasty bugs.
There are also quite a few signed/unsigned mismatches.
Output at warning level 4 attached.
In compileTranslationTable.c, there are references to a "nobreak" opcode. However, it has never been implemented, and nobody seems to remember what it was supposed to do, anyway. There may be others like it.
Make Python bindings compatible with any version of Python. For example, to make the bindings work with a version of Python (2.7.8) installed via cygwin (on a Windows machine), I had to compile liblouis without ucs4. I'm not sure what caused the mismatch. Because the Python version is 2.7.8? Because it's on Windows? Because the way Python was compiled? The Python bindings should handle all these variables.
Hi,
If you use the "correct" opcode together with "swapcc", the last char of the string is being removed in stead of swapped.
Example:
swapcc swaptest b a
correct %swaptest %swaptest
This file is supposed to swap b with a in the input string before translating.
lou_trace en-us-g1.ctb,swaptest.uti
aac
1. correct
2. lowercase a 1
3. lowercase a 1
4. lowercase c 14
b is being correctly converted to a.
ac
1. correct
2. lowercase a 1
3. lowercase c 14
b is removed instead of converted.
everything is well except when b is the last char of the string.
Of course, this is not a very useful example. I am currently using the correct opcode to convert capital letters to small ones in order to have proper 6 dots Braille, and getting the same result.
I would very much like to help correcting these things myself. But I guess I will have to wait until my programming skills match what is needed to find ones way around the Liblouis code (smile). Until then, I will stick to the
tables.
Bue
The files liblouis.h and config.h in windows/include are always out of sync with the main files. Find a way to fix this. If we can't we should delete the windows directory.
See also:
I ran valgrind on the svn version of liblouis and lo and behold it reported some memory leaks (in Berts new table resolver code of all places). The analysis is straight forward once you see the problem: we have a strdup in a loop and overwrite the existing reference to it
for (subTable = strdup (tableList); ; subTable = cp + 1)
I guess there needs to be a call to free after the sprintf.
There is some code from @johnjboyer in the branch jboyer_refactor but the same commit contains a lot of unrelated changes. I will dissect and try to extract the useful stuff and then we'll test if there is a performance improvement.
Simon Aittamaa says:
I realize that Michael Gray has already answered this question, but I'll expand on it a bit since his answer might have been overlooked...
As mentioned by Michael Gray, this problem arises from the use of combining characters, see [1] and [2]. The letter 'ö', can either be represented as a glyph (0x00f6) or as 'o' (0x006f) and diaeresis/umlaut '¨' (0x0308).
Most systems use the glyph (at least for 'ö'), i.e. Linux and Windows while OSX uses the combination of 'o' and '¨', which is why you get the stray \x0308 in your result. There might be libraries that can combine unicode sequences into glyphs (libiconv?), but I haven't looked into that.
It might be that we have to decompose/normalize [3] all characters, e.g. expand 'ö' into the canonical form ('o','¨'), in order to avoid this problem completely. However, this would require moving away from the current approach where each character is a single uint16_t/uin32_t.
IMHO, the latter approach, i.e. using the normalized/canonical form would be better, since it's the prescribed means of checking for equivalence by the standard, but it would require a major overhaul of how characters/strings are handled in liblouis (which in itself might be a good thing?).
Arend Arends wrote:
In principle Liblouis and the tables could handle both forms (single glyphs and combinations of a character and a diacritic symbol). It seems that currently both Liblouis and most tables handle only the single glyph forms, so the most practical would be to provide an extra pass to convert strings with diacritic symbols.
Paul Wood wrote:
Is it possible to add this library and 'Normalise' the utf-8 characters? http://julialang.org/utf8proc/
In some languages, German, Danish, (others?), some rarely used letters are being used as partword contractions, e.g. q, w, x, z in Danish, and c, q, x, y in German. In the context of contracted Braille, a letsign will always have to be added to these letters. The "alwaysletsign characters" opcode should ensure that the given characters ar always preceeded by one letsign. I would suggest that this opcode is overruled by compbrl, but not nocont.
Hard-coding the letsign into the character definitions is not a good idea. It would mean that you have to Work with different sets of character defs for each Braille grade, and it makes a more unclean character definition section anyway.
Using the "always" opcode here is not good either. "always" is over-ruled by nocont. At least in Danish, file names and internet addresses must be written without contractions, but with proper use of letsigns. If letsigns are not used, back-translation will fail anyway, e.g. .txt, .zip, www.
There seems to be a line-length limit in the tables. Compare these examples (the second one has one more character than the first):
Example 1 (length 223):
class diacritics ÁáÉéÍíÓóÚúÝýĆćĹĺŃńŔশŹźǴǵǼǽḰḱḾḿṔṕẂẃṤṥȽꞓƚꞒɬꞭĂăĔĕĞğĬĭŎŏŬŭẮắẶặẰằẲẳẴẵḪḫČčĎďĚ켾ŇňŘřŠšŤťŽžǍǎǏǐǑǒǓǔǦǧǨǩǰȞȟṦṧÇçĢģĶķĻļŅņŖŗŞşŢţȨȩḐḑḨḩḈḉḜḝÂâÊêÎîÔôÛûĈĉĜĝĤĥĴĵŜŝŴŵŶŷẐẑẤấẾếỐốẬậỆệỘộẦầỀềỒồẨẩỂểỔổẪẫỄễỖỗḒḓḘḙḼḽṊṋṰṱṶṷȘșȚțʝꬶꬺꬻꭉ
Example 2 (length 224):
class diacritics ÁáÉéÍíÓóÚúÝýĆćĹĺŃńŔশŹźǴǵǼǽḰḱḾḿṔṕẂẃṤṥȽꞓƚꞒɬꞭĂăĔĕĞğĬĭŎŏŬŭẮắẶặẰằẲẳẴẵḪḫČčĎďĚ켾ŇňŘřŠšŤťŽžǍǎǏǐǑǒǓǔǦǧǨǩǰȞȟṦṧÇçĢģĶķĻļŅņŖŗŞşŢţȨȩḐḑḨḩḈḉḜḝÂâÊêÎîÔôÛûĈĉĜĝĤĥĴĵŜŝŴŵŶŷẐẑẤấẾếỐốẬậỆệỘộẦầỀềỒồẨẩỂểỔổẪẫỄễỖỗḒḓḘḙḼḽṊṋṰṱṶṷȘșȚțʝꬶꬺꬻꭉꭊ
Example 2 gives the error "error: opcode '\x00ad\x008a' not defined.".
Hi all,
I originally tried to report this via the website, but pressing on the Edit button after entering the bug title opens a download dialog in Firefox. (Misconfigured CGI gateway or wrong mime type perhaps?)
Tested in liblouis 2.5.4 and current master (b483d7a).
Str:
The original string was a very long Youtube URL, but I distilled it as far as I could.
I realise the UEBC-g2.ctb table is probably deprecated by now, but liblouis should still never end up in loops.
I haven't done any debugging yet to see where/why this is freezing. I'll try to take a look at it when I can, but that could be a while.
Jamie
The following directory has source files with missing license headers:
It would be great if appropriate headers could be added. The reason for this 'nit picking' is that I am working on the Chromium project (www.chromium.org) and we track licenses using file headers for compliance. Having complete information helps us with that and is a good practice in general;)
See #16.
Some relevant posts/threads on mailing list:
Some related issues:
See also the wiki article https://github.com/liblouis/liblouis/wiki/New-opcodes-for-UEB
Overview of the changes:
firstword*
lastwordbefore*
lastwordafter*
len*phrase
firstletter*
lastletter*
singleletter*
*word
*wordstop
* = {ital, bold, under, caps, script, trans1, trans2, trans3, trans4, trans5}
numericmodechars
for indicating that a character does not terminate the numeric mode.letsign
.nocontractsign
seqdelimiter
seqbeforechars
seqafterchars
seqafterpattern
numericnocontchars
capsign
begcaps
lenbegcaps
endcaps
Re: feature/ueb_update_code
For the Dutch braille tables (defined in nl-g0.utb) it is desirable to have an emphmodechars
opcode. The behavior is similar to capsmodechars
, with the following differences:
The default behavior without this opcode defined is to consider all characters to continue 'emphasis mode'. Examples (assume the entire phrase is emphasized):
Without emphmodechars
:
With emphmodechars -
:
Edge cases to further investigate:
Reported with NVDA at http://community.nvda-project.org/ticket/5106
Patch is at http://mail3.batol.net/~school510587/0001-Fix-greek-character-translations-in-zh-tw.ctb.patch
Similar to what I did in the Python tests: d84a957
A lot of big corps that ship Android devices would like to pre-install liblouis and cannot do so due to obligations in the LGPLv3 to do with a) the "installation information" provision and b) having to sublicense third party patents to every downstream user worldwide. The LGPLv2.1 doesn't have these provisions.
To change the license we need consent from all the contributors from the following list:
If you create too many classes (in the tables) you will get a "character class table overflow". It would be useful to be able to create more classes.
See http://www.freelists.org/post/liblouis-liblouisxml/letter-indicator-upate,13 for the PDF that @MikeGray-APH uses as his reference.
According to UEB and EBAE since 2011, a bullet like U+2022 should be translated as dots 456-256. (Reported by Lloyd Rasmussen)
U+2022 is defined in unicodedefs.cti 35-35, but this table is not included anywhere. Which brings me to the next issue.
liblouisutdml fails with liblouis master because of
readconfig.c:68:1: error: conflicting types for ‘FileInfo’
same story here: readconfig.c
inlcudes louis.h
and defines FileInfo
TBH I don't really know what the best way to fix this would be. In the long run this is quite annoying and limiting to liblouis.
Requested by @BueVest, see Re: Translation problems with some tables
When a pass2 rule reduces the number of Braille cells in the translation, the output positions are not updated and so the output positions array becomes wrong. In the worst case the output positions array can contain values which are invalid index values for the translation and so would lead to a crash/exception.
I have not tested this to see whether a pass2 rule which adds extra Braille cells also suffers from this bug, but at least in that case values in the output positions will still be valid index values for the translation and would not lead to a crash, it would just lead to incorrect mappings.
git head of liblouis and liblouisutdml aren't compatible because of redeclaration of enumerator ascii8
, that was introduced with 111e702. Maybe we could just rename ascii8
to ascii
.
make[2]: Entering directory '/usr/local/src/liblouisutdml/liblouisutdml'
/bin/bash ../libtool --tag=CC --mode=compile gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I.. -DLBU_PATH=\"/usr/local/share/liblouisutdml/lbu_files/\" -DLIBLOUIS_TABLES_PATH=\"/usr/local/share/liblouis/tables/\" -DLBULIB -I/usr/lib/jvm/java-7-openjdk-i386/include -I/usr/lib/jvm/java-7-openjdk-i386/include/linux -I/usr/local/include/liblouis -I/usr/include/libxml2 -g -O2 -MT liblouisutdml_la-change_table.lo -MD -MP -MF .deps/liblouisutdml_la-change_table.Tpo -c -o liblouisutdml_la-change_table.lo `test -f 'change_table.c' || echo './'`change_table.c
libtool: compile: gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I.. -DLBU_PATH=\"/usr/local/share/liblouisutdml/lbu_files/\" -DLIBLOUIS_TABLES_PATH=\"/usr/local/share/liblouis/tables/\" -DLBULIB -I/usr/lib/jvm/java-7-openjdk-i386/include -I/usr/lib/jvm/java-7-openjdk-i386/include/linux -I/usr/local/include/liblouis -I/usr/include/libxml2 -g -O2 -MT liblouisutdml_la-change_table.lo -MD -MP -MF .deps/liblouisutdml_la-change_table.Tpo -c change_table.c -fPIC -DPIC -o .libs/liblouisutdml_la-change_table.o
In file included from change_table.c:34:0:
louisutdml.h:120:3: error: redeclaration of enumerator 'ascii8'
ascii8
^
In file included from louisutdml.h:36:0,
from change_table.c:34:
/usr/local/include/liblouis/louis.h:480:42: note: previous definition of 'ascii8' was here
{ noEncoding, bigEndian, littleEndian, ascii8 } EncodingType;
^
Makefile:789: recipe for target 'liblouisutdml_la-change_table.lo' failed
make[2]: *** [liblouisutdml_la-change_table.lo] Error 1
make[2]: Leaving directory '/usr/local/src/liblouisutdml/liblouisutdml'
Makefile:647: recipe for target 'all' failed
make[1]: *** [all] Error 2
make[1]: Leaving directory '/usr/local/src/liblouisutdml/liblouisutdml'
Makefile:691: recipe for target 'all-recursive' failed
make: *** [all-recursive] Error 1
When migrating the tests from json the "comment": field was converted to a plain old YAML comment. Instead it would be nice if we could have some form of (optional) test description that describes what we are testing. This would allow for more descriptive failure messages. See also the API of the clojure.test is macro where you can pass an optional second argument msg
that can describe the test. A similar concept is used in RSpec where a test is defined as follows:
it "is empty when first created" do
expect(collection_class.new).to be_empty
end
Then you will get descriptive error messages like:
$ rspec spec/calculator_spec.rb
Failures:
1) Foo#is empty when first created
Failure/Error: expect(collection_class.new).to be_empty
[...]
To implement this you could have four valid types of tests:
# a word and a corresponding translation as before (A)
- [word, translation]
# a word, a corresponding translation and options as before (B)
- [word, translation, {opts}]
# a message, a word and a corresponding translation (C)
- [msg, word, translation]
# a message, a word, a corresponding translation and options (D)
- [msg, word, translation, {opts}]
The separation between the different cases can be done by arity and type of the third argument. If it is a map then we have the existing case B, if it is a scalar then we have the case C.
... suggesting the whole word is in caps. "AAAs" is correctly translated to ",,aaa,'s".
This happens with several tables including en-ueb-g1.ctb.
Issue reported by @torchtrust.
see also:
In listFiles 'list' is not initialized and a possible bogus value passed to list_con on first pass
static List *
listFiles(char * searchPath)
{
List * list;
list = list_conj(list, strdup(fileName), NULL, NULL, free);
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.