GithubHelp home page GithubHelp logo

danielnaber / openthesaurus Goto Github PK

View Code? Open in Web Editor NEW
161.0 15.0 27.0 9.21 MB

web-based thesaurus search and management

Home Page: https://www.openthesaurus.de

License: GNU Affero General Public License v3.0

Shell 0.67% Groovy 84.22% Java 6.72% CSS 7.55% JavaScript 0.85%

openthesaurus's Introduction

OpenThesaurus

OpenThesaurus (www.openthesaurus.de), a web-based thesaurus management tool

Copyright (C) 2009 vionto GmbH, Berlin
Copyright (C) 2011-2022 Daniel Naber, www.danielnaber.de

OpenThesaurus is a web-based tool for the development and maintenance of thesauri and ontologies. It requires a Java application server or servlet container (e.g. Apache Tomcat) and is typically used with MySQL as a stand-alone database (other databases may work but have not been tested).

See https://github.com/OpenTaal/opentaal-openthesaurus/blob/master/README.md for more detailed installation instructions.

Building

If you want to build OpenThesaurus on your own you will need Grails 3.3.1.

For development, your database needs to be configured in grails-app/conf/application.yml. Use grails run-app to directly start the web-application in development mode. It is then available at http://localhost:8080/.

Use grails war to build a web application which can be deployed to a Java servlet container like Tomcat.

Setup for users who install the .war file

Note: this section hasn't been updated for some time, we suggest building as documented above

The openthesaurus.war file needs to be deployed to your servlet container. Please refer to the container's documentation on how to do that.

  1. Copy your JDBC database connector *.jar file to the WEB-INF/lib directory. If you use MySQL, you can get the database connector at https://dev.mysql.com/downloads/connector/j/

  2. Configure your database access in WEB-INF/classes/datasource.properties.
    A typical MySQL-based configuration for datasource.properties looks like this:

      dataSource.url=jdbc:mysql://127.0.0.1:3306/openthesaurus?useUnicode=true&characterEncoding=utf-8
      dataSource.driverClassName=com.mysql.jdbc.Driver
      dataSource.username=dbuser
      dataSource.password=xyz
      dataSource.dbCreate=update
    

    With these settings, the database openthesaurus needs to be created first manually using the database's tools. The tables will be automatically created by OpenThesaurus on its first startup.

  3. For now, an in-memory database needs to be set up and updated regularly by accessing the page synset/createMemoryDatabase before OpenThesaurus can be used. This can be done by calling a command like this:

     curl -I http://localhost:8080/openthesaurus/synset/createMemoryDatabase
    

    Since the size of in-memory tables is 16M by default, after a while the above operation might start to fail (you will get 500 Internal Server Error as response at the above URL and you will see memWordsTmp is full in your server logs. In this case what you need to do is increase max_heap_table_size in MySQL. You can use SHOW VARIABLES to see the current value of this variable in your installation.

  4. Set the values in WEB-INF/classes/openthesaurus.properties

  5. For bigger data sets it might be necessary to create indexes manually in your database:

     ALTER TABLE `term` ADD INDEX ( `word` ) 
     ALTER TABLE `term` ADD INDEX ( `normalized_word` ) 
     ALTER TABLE `synset` ADD INDEX ( `is_visible` ) 
    
  6. In case you run into problems with searching for special characters, it might be required to modify all tables whose collation is latin1_swedish_ci to utf8_general_ci, like this:

     ALTER TABLE `term` CHANGE `word` `word` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
     ALTER TABLE `term` CHANGE `normalized_word` `normalized_word` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
     ALTER TABLE `term` CHANGE `user_comment` `user_comment` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
     ALTER TABLE `wikipedia_links` CHANGE `link` `link` VARCHAR( 100 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
     ALTER TABLE `wikipedia_pages` CHANGE `title` `title` VARCHAR( 100 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;  
     ALTER TABLE `wiktionary` CHANGE `headword` `headword` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
        CHANGE `meanings` `meanings` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
        CHANGE `synonyms` `synonyms` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
     ALTER TABLE `user_event` CHANGE `old_value` `old_value` LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
     ALTER TABLE `user_event` CHANGE `new_value` `new_value` LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
     ALTER TABLE `user_event` CHANGE `class` `class` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
     ALTER TABLE `user_event` CHANGE `change_desc` `change_desc` LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
     ALTER TABLE `user_event` CHANGE `ip_address` `ip_address` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
     ALTER TABLE `user_event` CHANGE `word` `word` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;    
    
  7. The default administration account is admin with the password admin - make sure this is changed after your first login. If you are logged in as admin, the OpenThesaurus homepage will show a link to the administration page.

Data Import

Data from the old PHP-based version of OpenThesaurus can be imported by calling http://localhost:8080/openthesaurus/import/index. Please check the result carefully as it has only been tested with the German data so far.

License

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with this program. If not, see http://www.gnu.org/licenses/.

openthesaurus's People

Contributors

danielnaber avatar kstuart avatar pandermusubi avatar pkt avatar randers00 avatar tiff avatar

Stargazers

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

Watchers

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

openthesaurus's Issues

Mark releases and offer WAR files

Please start tagging certain commits as releases and offer a WAR file for that release for the then current stable version of Ubuntu and LTS version. For now that would be current stable 17.04 (as of October 19th 17.10) and LTS 16.04.

Suppress search Popup

Sometimes when entering a page the search popup appears, although it shouldn't. Example:

Now the newly opened tab will become visible, but the search popup will open without actually using the search field (tested with Firefox).

add small help for superordiate terms

add "[?]" link, just like for associations, explaining what superordinate terms are: A is a superordinate term of B if you can say "B is an A", e.g. a car is a vehicle

Feature: Sentiment-Filter (German)

Falls es stimmt, wäre es witzig, wenn man Wörter nach der Stimmung filtern könnte, die man für seinen Text bzw. Absatz haben möchte:

So bewirken dunkle Vokale (a, o und u) eine eher finstere, aber auch ruhige Stimmung. Im Gegensatz dazu erzeugen helle Vokale (e und i) eine fröhliche, aufgeregte Stimmung. Harte Konsonanten (k,p,r und t) wirken eher aggressiv und abweisend, weiche Konsonanten (b, d, f, m und n) hingegen beruhigend.

(https://www.sputnik-agentur.de/blog/wie-texte-wirken-was-steht-zwischen-den-zeilen/)

Hunspell produces not expected spell suggestions

$ cd core/dictionaries/de
$ echo gebärdensprache | hunspell -d de_DE_frami
Hunspell 1.7.0
& gebärdensprache 4 0: Gebärdensprache, -gebärdensprache, sprachgebundene, sprachgebunden
so it can be reproduced on the command line without libreoffice involved so its not an issue within LibreOffice code and is presumably due to the o rule of
gebärdensprache/ozm in the de_DE_frami.dic/aff, i.e. specific to the spelling dictionary itself

Same also present in Dutch dictionary (https://github.com/OpenTaal/opentaal-hunspell). Recent changes there might give some pointers.

Co-Admin gesucht

openthesaurus.de ist das führende (und wohl auch einzige) freie deutschsprachige Synonymwörterbuch. Unsere Daten werden in LibreOffice genutzt und unsere Website hat über 20.000 Visits pro Tag.

Um den Betrieb von OpenThesaurus zu stabilisieren, suche ich einen ehrenamtlichen Co-Admin. Kenntnisse im Bereich Linux und Webserver sollten vorhanden sein. Aufgabe ist es, mit mir zusammen den Server so aufzusetzen, dass es nicht zu Unterbrechungen im Betrieb kommt und dass eine gute Performance garantiert ist.

Kontakt hier oder per Mail (siehe https://www.openthesaurus.de/about/imprint).

Allow transcripts of umlauts

For all users of openthesaurus not using a german keyboard layout and not knowing how to use compose keys, it would be very nice to have an automatic conversion for umlauts:

  • ue -> ü
  • ae -> ä
  • oe -> ö
  • ss or sz -> ß

dict.cc is doing the same

Sample Error Json

Is there any example on how an errornous json/xml response could look like?

Thank you for this service!

register fails because mail cannot be sent

Where can sending mails be configured?

org.springframework.mail.MailAuthenticationException: Authentication failed; nested exception is javax.mail.AuthenticationFailedException: f
	at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:424)
	at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:345)
	at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:340)
	at grails.plugins.mail.MailMessageBuilder.sendMessage(MailMessageBuilder.groovy:130)
	at grails.plugins.mail.MailService.sendMail(MailService.groovy:53)
	at grails.plugins.mail.MailService.sendMail(MailService.groovy:57)
	at grails.plugins.mail.SendMail$Trait$Helper.sendMail(SendMail.groovy:31)
	at openthesaurus.UserController.doRegister(UserController.groovy:186)
	at org.grails.core.DefaultGrailsControllerClass$MethodHandleInvoker.invoke(DefaultGrailsControllerClass.java:223)
	at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:188)
	at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
	at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
	at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
	at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
	at org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:115)
	at org.springframework.boot.web.support.ErrorPageFilter.access$000(ErrorPageFilter.java:59)
	at org.springframework.boot.web.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:90)
	at org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:108)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: javax.mail.AuthenticationFailedException: failed to connect, no password specified?
	at javax.mail.Service.connect(Service.java:400)
	at org.springframework.mail.javamail.JavaMailSenderImpl.connectTransport(JavaMailSenderImpl.java:501)
	at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:421)
	... 25 common frames omitted

Support the semantic distance between two word senses

Hello together,

Is it possible to support a semantic distance as a score between a search query and the shown words/synonyms?

Wordnet explains the functionality on their FAQ below "How can I calculate the semantic distance between two word senses?"
https://wordnet.princeton.edu/frequently-asked-questions

Germanet has something similar described below their tools page as Semantic Relatedness API
http://www.sfs.uni-tuebingen.de/GermaNet/tools.shtml

This feature would be great if you like to use OpenThesaurus as a Search Query Enricher and you need to weight the semantic distance scores for your result presentation.

Feature request: Add a link to the RSS feed to https://www.openthesaurus.de/userEvent/list

Currently, if I want to subscribe to the RSS feed with the most recent changes to the OT data, I have to go to the About page in order to learn that this feature exists.
At the same time, the main page of OT has a link to the page https://www.openthesaurus.de/userEvent/list with a link text of "Daten-Änderungen".
I would like to suggest to add a link on the page https://www.openthesaurus.de/userEvent/list to https://www.openthesaurus.de/feed that says something similar to "Sie können die aktuellen Änderungen auch als RSS_Feed abonnieren."

add descriptions to synsets

Dear openthesaurus-team,

it would be great to have a short text-description for each synset.
Could this be added to the corpus?

regression: URL with "+" broken

The URL https://www.openthesaurus.de/synonyme/weh+tun used to work, but now the "+" ends up as a plus in the search field, leading to no results.

(https://www.openthesaurus.de/synonyme/weh tun still works.)

Error executing tag <g:set>: No row with the given identifier exists: [com.vionto.vithesaurus.Term#88967]]

Quick fix:

\u openthesaurus
SELECT * FROM `term` WHERE `id` = 88967; => keine Treffer (sonst ist es ein anderes Problem)
select * from term_link where target_term_id = 88967 limit 1;
select * from synset_link where target_term_id = 88967 limit 1;
SELECT * FROM `term` WHERE `id` = 40740; => hier die synset-id anschauen
https://www.openthesaurus.de/synonyme/edit/{synset_id} => Server error? Wenn nicht, anderes Problem
delete from term_link where target_term_id = 88967 limit 1;
https://www.openthesaurus.de/synonyme/edit/{synset_id} => Server error sollte gelöst sein

What happens when a term gets deleted? It seems the term_link doesn't get removed?

Feature request: Add a character table with umlauts and other special characters

I've been thinking about how OT could help (a) users with non-German keyboards, (b) users who are struggling with entering common accented characters that often occur in loan words, such as à, é, ç, ğ etc., because the process of entering those on their respective device might be cumbersome or not widely known.

The basic idea is that OT could have an icon (or maybe a text that says "Sonderzeichen") next to each input field that when clicked/touched opens a modal (?) dialog that displays special characters from at least German, French, Italian, Spanish, and maybe Polish, Czech, and Turkish, typically in a table of some kind. When a character in the table is clicked/touched, the respective character should (obviously) be entered at the cursor position. The dialog should probably not close automatically after insertion so the user can add several special characters in one go.

I would not restrict this to the search box, but make it available literally everywhere where users are supposed to enter text. It might encourage OT contributors to contribute with better spelling quality. My suggestion addresses the same problem that motivates issue #16, but in a more generic way.

Requests per minute limitation and Tor network

Just coming by here by chance - and just one comment: I see there is a limit of one request per second which should be more that sufficient for most IP addresses. This might be an issue for a larger group sharing the same IP address.

One such case is users with a need of increased anonymity and who are relying on Tor (see torproject.org for some background). Everyone using Tor and accessing openthesaurus will have one of the Exit-nodes IP addresses assigned on the request. So my suggestion would be to allow these IP addresses a higher rater (in case this is needed at all; currently everything is working perfectly well). Still some rate limit is usefull for these IPs as well; just higher maybe.

The Tor Exit node IPs can easily checked for at: https://check.torproject.org/cgi-bin/TorBulkExitList.py which also links to a plain-text full list of IPs (V4 and V6).

Keep on with the great work - it's an awesome and indispensable tool to learn German!

fix "more than one term link"

happens at http://www.openthesaurus.de/term/edit/37149

Stacktrace follows:
java.lang.Exception: More than one term link for term weitermachen: [weitermachen<--Antonym-->abbrechen, weitermachen<--Antonym-->aufstecken, weitermachen<--Antonym-->(es) aufgeben]
at TermController$_closure3.doCall(TermController.groovy:59)
at TermController$_closure3.doCall(TermController.groovy)
at java.lang.Thread.run(Thread.java:722)

Where is Term.java located/defined?

I currently make some tests if its possible to upgrade grails to latest version (to solve #27)

However, currently I have problems while running the (new) grails app using grails run-app as the class TermLinkInfo.java cannot import class Term. I didnt have that exception on latest master, though

I failed to find class Term in the src folder.
Am I blind or is it like hard to spot? Can you tell me where its located?

ignore responses to outdated asynchronous requests

For the search-as-you-type feature, onValueChange() starts an Ajax requests whose response will be written to the page. As the server response time isn't always the same it sometimes happens that an older requests overwrites a more recent one. For example, the user might have searched for "foo", but will see the result for "fo".

Add uppercase character(s) with French circonflexe to word characters

When trying to add the phrase "Raison d'Être" to OT (capitalization recommended by Duden), I get this error:

Die Eigenschaft [word] des Typs [class com.vionto.vithesaurus.Term] mit dem Wert [Raison d'Être] entspricht nicht dem vorgegebenen Muster [[ 0-9a-zA-ZöäüÖÄÜßëçèéêáàóòÈÉÁÀÓÒãñíîş{}"?*=()-+/.,'_:<>;%‰°![]²³Œ€&#ūαΑβΒγΓδΔεΕζΖηΗθΘιΙκΚλΛμΜνΝξΞοΟπΠρΡσΣτΤυΥφΦχΧψΨωΩάΆέΈίΊήΉύΎϊϋΰΐœţ]+]

Seems to me that at least the character Ê should be added to the RegEx here.

Feature request: .org domain

Hi,
imo the .org domain would be a good addition to the site. For me, it would be the fitting tld for such a project.

exception on deleting term from synset

Delete a term at e.g. http://localhost:8080/synonyme/edit/11637 - the term will be deleted but it seems the logging fails.

failed to lazily initialize a collection, could not initialize proxy - no Session. Stacktrace follows:

java.lang.reflect.InvocationTargetException: null
        at org.grails.core.DefaultGrailsControllerClass$ReflectionInvoker.invoke(DefaultGrailsControllerClass.java:211)
        at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:188)
        at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
        at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
        at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
        at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection, could not initialize proxy - no Session
        at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:584)
        at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:201)
        at org.hibernate.collection.internal.AbstractPersistentCollection.readElementExistence(AbstractPersistentCollection.java:313)
        at org.hibernate.collection.internal.PersistentSet.contains(PersistentSet.java:154)
        at com.vionto.vithesaurus.Term.compareTo(Term.groovy:162)
        at java.util.TimSort.countRunAndMakeAscending(TimSort.java:356)
        at java.util.TimSort.sort(TimSort.java:220)
        at java.util.Arrays.sort(Arrays.java:1512)
        at java.util.ArrayList.sort(ArrayList.java:1454)
        at java.util.Collections.sort(Collections.java:175)
        at com.vionto.vithesaurus.Synset.toDetailedString(Synset.groovy:249)
        at com.vionto.vithesaurus.LogInfo.<init>(LogInfo.groovy:90)
        at openthesaurus.SynsetController.update(SynsetController.groovy:732)
        ... 14 common frames omitted

Make users aware that they can use transripted umlauts

As per #16, OpenThesaurus now supports transcripted umlauts and 'ss' for 'ß'. Users should be made aware of this new functionality in some way. I suggest an unobtrusive balloon tip that is triggered when the input field gets focus. The balloon could say something like 'Tip: Type ae for ä and ss for ß'. Also, it should have a close button and ideally stay closed for the rest of the session after the user closed it.

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.