GithubHelp home page GithubHelp logo

caius's People

Contributors

apnadkarni avatar dbohdan avatar tobijk 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

Watchers

 avatar  avatar  avatar  avatar  avatar

caius's Issues

RFE - ability to run only tests that match a pattern

The tcltest package that is part of the Tcl core has the -match command line option that permits specification of a pattern. If specified, only tests whose names match the pattern are executed. This is very useful during development when (for example) enhancing a module feature and running the entire tests suite for the module is time consuming.

A similar capability for Caius where one could specify a pattern for the module and for the tests within the module would be useful.

Unable to get setup_before to be called

I have a simple test -

itcl::class FibonacciTests {
    inherit Testing::TestObject

    method setup_before {} {
        foreach subdir {stylesheets js images} {
            file copy -force -- [::woof::test::source_path samples public $subdir] [::woof::test::target_path public]
        }
    }

    method test-1 {} {}
}

exit [[FibonacciTests #auto] run $::argv]

Running the above, setup_before does not get called. Looking at the code for TestObj::setup and TestObj::teardown, I'm wondering at the following line:

foreach {class} [lreverse [$this info heritage]] {

The above loop would not include the leaf test class itself, would it? Changing the line to

foreach {class} [concat [$this info class] [lreverse [$this info heritage]]] {

fixed the problem. However, I'm not very familiar with Itcl either so perhaps I'm declaring my methods wrong?

/Ashok

Failure to process html tag attributes bracketed by single-quotes

The following test input where I used HTML in MD to get a nice table caused Caius to drop the second table from the output!

<table><tr>
<td>Array</td>
<td><a href='http://core.tcl.tk/akupries/array'>Core</a></td>
</tr></table>

<table><tr>
<td>Tcl</td>
<td><a href='http://core.tcl.tk/tcl'>Core</a></td>
</tr></table>

I found two ways of fixing this in the input:
(1) Remove the column contain the reference.
(2) Change the single-quotes around the href-url to double-quotes.

It seems that the processor chokes in some way on the single-quotes. As AFAIK HTML allows either single- or double-quotes around attribute values and markdown allows arbitrary HTML this looks to me a bug in the processor itself.

This looks to be line 325 in Tclssg's copy of markdown.tcl (proc "apply_templates", first occurence of "re_htmltag"). Replacing it with

set re_htmltag {<(/?)(\w+)(?:\s+\w+=(?:\"[^\"]+\"|'[^']+'))*\s*>}

and the problem was fixed. The new regex is based on the variation of the re_htmltag variable I found in line 431 (proc parse_inline) of the same file.

Markdown: ampersand in autolinks

Auto-linked URLs are not escaped. Per the mdtest test suite, the ampersand in the following

Auto-link with ampersand: <http://example.com/?foo=1&bar=2>

should be escaped. I fixed this in my code by adding the HtmlEscape line in this code:

                # HTML TAGS, COMMENTS AND AUTOLINKS
                if {[regexp -start $index $re_comment $text m]} {
                    append result $m
                    incr index [string length $m]
                    continue
                } elseif {[regexp -start $index $re_autolink $text m email link]} {
                    if {$link ne {}} {
                        set link [HtmlEscape $link]
                        append result "<a href=\"$link\">$link</a>"
                    } else {
...

For "HtmlEscape", read "html_escape".

Markdown: _references isn't cleared

Line 52 of Markdown::convert calls "array set" to initialize the _references variable; but "array set" does a merge rather than an assignment. You need to call "array unset ::Markdown::_references" just prior to eliminate old references:

        array unset ::Markdown::_references
        array set ::Markdown::_references [collect_references markdown]

RFE - ability to add constraints to tests

The tcltest package that is part of the Tcl core has the -constraints command line option that permits specification of constraints. In addition, constraints can be attached to tests. If constraints are attached to a test, it is only run if the corresponding constraint is enabled via the command line or programmatically. For example, there can be constraints that specify that tests only run on Windows, or only on multiprocessor systems or only if certain software is installed.

A similar capability for Caius would be useful.

Markdown: undefined refs

Undefined references in Markdown input cause a runtime error in markdown.tcl: it looks for the reference in ::Markdown::_references and can't find it. For example, try this:

Unknown ref: [foo]

I updated "parse_inline" as follows:

                    if {[info exists references_($ref)]} {
                        lassign $references_($ref) url title

                        set url [HtmlEscape [string trim $url {<> }]]
                        set txt [ParseInline $txt]
                        set title [ParseInline $title]

                        set match_found 1
                    } else {
                        # Unknown ref: just put in the matching text.
                        append result $m
                        continue
                    }

For "references_", read "Markdown::_references".

Bump Markdown package version

It's exciting to see compliance with John Gruber's original test suite in the Markdown package. The change should be reflected in the package version, which so far has remained the same (0.9).

WebDriver is unable to element by_partial_link_text with extend ASCII characters

I have a web interface that has extended ASCII characters in this case I am using the
element by_partial_link_text
with the following text Français
The page has the following html
Français
the script can find it if i remove all the extended ascii characters "Fran"
but in the future I will need to find the extended ASCII
If you would like to test it is online at:
https://www.ezcloudx.com/#/
it is from the internationalization pulldown top left.

pkgIndex.tcl of lib/Markdown is broken

There is an escape issue in "pkgIndex.tcl" file in lib/Markdown. Loading the package fails when the path to the library contains more than a single whitespace in series - e.g. C:\test__test\lib\Markdown". For me the following works:

package ifneeded Markdown 1.0 "
    source \[file join [list $dir] markdown.tcl\]
    source \[file join [list $dir] version.tcl\]
"

WebDriver failure with latest Selenium Server

I might be missing something in the execution. Any help would be greatly appreciated!

Install: Caius

https://github.com/tobijk/caius.git

Download: Selenium Server

https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.9.0/selenium-server-4.9.1.jar

Execute: Server Start

java -jar selenium-server-4.9.1.jar standalone --host "127.0.0.1" --port 4445 --http-logs true --log-level "FINE" ;

Execute: Client Start

package require WebDriver ;
set seleniumServer "http://127.0.0.1:4445" ;
set caps [namespace which [WebDriver::Capabilities #auto -browser_name firefox]] ;
set session [WebDriver::Session #auto $seleniumServer/wd/hub $caps] ;
# The previous cmd does not return. Several minutes later we get the following,
# and the server is still alive.
::unknownError0

Log: Server

23:25:03.365 INFO [LoggingOptions.configureLogEncoding] - Using the system default encoding
23:25:03.371 INFO [OpenTelemetryTracer.createTracer] - Using OpenTelemetry for tracing
23:25:03.459 DEBUG [AutoConfiguredOpenTelemetrySdkBuilder.build] - Global OpenTelemetry set to OpenTelemetrySdk{tracerProvider=SdkTracerProvider{clock=SystemClock{}, idGenerator=RandomIdGenerator{}, resource=Resource{schemaUrl=https://opentelemetry.io/schemas/1.19.0, attributes={service.name="unknown_service:java", telemetry.sdk.language="java", telemetry.sdk.name="opentelemetry", telemetry.sdk.version="1.25.0"}}, spanLimitsSupplier=SpanLimitsValue{maxNumberOfAttributes=128, maxNumberOfEvents=128, maxNumberOfLinks=128, maxNumberOfAttributesPerEvent=128, maxNumberOfAttributesPerLink=128, maxAttributeValueLength=2147483647}, sampler=ParentBased{root:AlwaysOnSampler,remoteParentSampled:AlwaysOnSampler,remoteParentNotSampled:AlwaysOffSampler,localParentSampled:AlwaysOnSampler,localParentNotSampled:AlwaysOffSampler}, spanProcessor=SimpleSpanProcessor{spanExporter=org.openqa.selenium.remote.tracing.opentelemetry.SeleniumSpanExporter$1@11c20519}}, meterProvider=SdkMeterProvider{clock=SystemClock{}, resource=Resource{schemaUrl=https://opentelemetry.io/schemas/1.19.0, attributes={service.name="unknown_service:java", telemetry.sdk.language="java", telemetry.sdk.name="opentelemetry", telemetry.sdk.version="1.25.0"}}, metricReaders=[], views=[]}, loggerProvider=SdkLoggerProvider{clock=SystemClock{}, resource=Resource{schemaUrl=https://opentelemetry.io/schemas/1.19.0, attributes={service.name="unknown_service:java", telemetry.sdk.language="java", telemetry.sdk.name="opentelemetry", telemetry.sdk.version="1.25.0"}}, logLimits=LogLimits{maxNumberOfAttributes=128, maxAttributeValueLength=2147483647}, logRecordProcessor=io.opentelemetry.sdk.logs.NoopLogRecordProcessor@701fc37a}, propagators=DefaultContextPropagators{textMapPropagator=MultiTextMapPropagator{textMapPropagators=[W3CTraceContextPropagator, W3CBaggagePropagator]}}} by autoconfiguration
23:25:04.101 INFO [NodeOptions.getSessionFactories] - Detected 4 available processors
23:25:04.115 INFO [NodeOptions.discoverDrivers] - Driver(s) already present on the host: 1
23:25:04.145 INFO [NodeOptions.report] - Adding Firefox for {"browserName": "firefox","platformName": "linux"} 4 times (Host)
23:25:04.166 INFO [Node.<init>] - Binding additional locator mechanisms: relative
23:25:04.203 DEBUG [GridModel.add] - Adding node with id fd1e12ec-cf8a-43c5-8681-4b88a67c1e3e and URI http://127.0.0.1:4445
23:25:04.204 DEBUG [LocalDistributor.updateNodeAvailability] - Health check result for http://127.0.0.1:4445 was UP
23:25:04.205 INFO [GridModel.setAvailability] - Switching Node fd1e12ec-cf8a-43c5-8681-4b88a67c1e3e (uri: http://127.0.0.1:4445) from DOWN to UP
23:25:04.206 INFO [LocalDistributor.add] - Added node fd1e12ec-cf8a-43c5-8681-4b88a67c1e3e at http://127.0.0.1:4445. Health check every 120s
23:25:04.226 DEBUG [MultithreadEventLoopGroup.<clinit>] - -Dio.netty.eventLoopThreads: 8
23:25:04.234 DEBUG [GlobalEventExecutor.<clinit>] - -Dio.netty.globalEventExecutor.quietPeriodSeconds: 1
23:25:04.244 DEBUG [InternalThreadLocalMap.<clinit>] - -Dio.netty.threadLocalMap.stringBuilder.initialSize: 1024
23:25:04.244 DEBUG [InternalThreadLocalMap.<clinit>] - -Dio.netty.threadLocalMap.stringBuilder.maxSize: 4096
23:25:04.266 DEBUG [PlatformDependent0.explicitNoUnsafeCause0] - -Dio.netty.noUnsafe: false
23:25:04.267 DEBUG [PlatformDependent0.javaVersion0] - Java version: 11
23:25:04.267 DEBUG [PlatformDependent0.<clinit>] - sun.misc.Unsafe.theUnsafe: available
23:25:04.268 DEBUG [PlatformDependent0.<clinit>] - sun.misc.Unsafe.copyMemory: available
23:25:04.268 DEBUG [PlatformDependent0.<clinit>] - sun.misc.Unsafe.storeFence: available
23:25:04.268 DEBUG [PlatformDependent0.<clinit>] - java.nio.Buffer.address: available
23:25:04.268 DEBUG [PlatformDependent0.<clinit>] - direct buffer constructor: unavailable: Reflective setAccessible(true) disabled
23:25:04.269 DEBUG [PlatformDependent0.<clinit>] - java.nio.Bits.unaligned: available, true
23:25:04.270 DEBUG [PlatformDependent0.<clinit>] - jdk.internal.misc.Unsafe.allocateUninitializedArray(int): unavailable: class io.netty.util.internal.PlatformDependent0$7 cannot access class jdk.internal.misc.Unsafe (in module java.base) because module java.base does not export jdk.internal.misc to unnamed module @c05fddc
23:25:04.271 DEBUG [PlatformDependent0.<clinit>] - java.nio.DirectByteBuffer.<init>(long, int): unavailable
23:25:04.273 DEBUG [PlatformDependent.unsafeUnavailabilityCause0] - sun.misc.Unsafe: available
23:25:04.274 DEBUG [PlatformDependent.estimateMaxDirectMemory] - maxDirectMemory: 4167041024 bytes (maybe)
23:25:04.274 DEBUG [PlatformDependent.tmpdir0] - -Dio.netty.tmpdir: /tmp (java.io.tmpdir)
23:25:04.274 DEBUG [PlatformDependent.bitMode0] - -Dio.netty.bitMode: 64 (sun.arch.data.model)
23:25:04.275 DEBUG [PlatformDependent.<clinit>] - -Dio.netty.maxDirectMemory: -1 bytes
23:25:04.275 DEBUG [PlatformDependent.<clinit>] - -Dio.netty.uninitializedArrayAllocationThreshold: -1
23:25:04.276 DEBUG [CleanerJava9.<clinit>] - java.nio.ByteBuffer.cleaner(): available
23:25:04.276 DEBUG [PlatformDependent.<clinit>] - -Dio.netty.noPreferDirect: false
23:25:04.278 DEBUG [NioEventLoop.<clinit>] - -Dio.netty.noKeySetOptimization: false
23:25:04.278 DEBUG [NioEventLoop.<clinit>] - -Dio.netty.selectorAutoRebuildThreshold: 512
23:25:04.283 DEBUG [PlatformDependent$Mpsc.<clinit>] - org.jctools-core.MpscChunkedArrayQueue: available
23:25:04.305 DEBUG [DefaultChannelId.<clinit>] - -Dio.netty.processId: 190894 (auto-detected)
23:25:04.308 DEBUG [NetUtil.<clinit>] - -Djava.net.preferIPv4Stack: false
23:25:04.309 DEBUG [NetUtil.<clinit>] - -Djava.net.preferIPv6Addresses: false
23:25:04.310 DEBUG [NetUtilInitializations.determineLoopback] - Loopback interface: lo (lo, 0:0:0:0:0:0:0:1%lo)
23:25:04.311 DEBUG [NetUtil$SoMaxConnAction.run] - /proc/sys/net/core/somaxconn: 4096
23:25:04.312 DEBUG [DefaultChannelId.<clinit>] - -Dio.netty.machineId: 94:c6:91:ff:fe:11:df:a9 (auto-detected)
23:25:04.319 DEBUG [ResourceLeakDetector.<clinit>] - -Dio.netty.leakDetection.level: simple
23:25:04.319 DEBUG [ResourceLeakDetector.<clinit>] - -Dio.netty.leakDetection.targetRecords: 4
23:25:04.341 DEBUG [PooledByteBufAllocator.<clinit>] - -Dio.netty.allocator.numHeapArenas: 8
23:25:04.341 DEBUG [PooledByteBufAllocator.<clinit>] - -Dio.netty.allocator.numDirectArenas: 8
23:25:04.341 DEBUG [PooledByteBufAllocator.<clinit>] - -Dio.netty.allocator.pageSize: 8192
23:25:04.341 DEBUG [PooledByteBufAllocator.<clinit>] - -Dio.netty.allocator.maxOrder: 9
23:25:04.342 DEBUG [PooledByteBufAllocator.<clinit>] - -Dio.netty.allocator.chunkSize: 4194304
23:25:04.342 DEBUG [PooledByteBufAllocator.<clinit>] - -Dio.netty.allocator.smallCacheSize: 256
23:25:04.342 DEBUG [PooledByteBufAllocator.<clinit>] - -Dio.netty.allocator.normalCacheSize: 64
23:25:04.342 DEBUG [PooledByteBufAllocator.<clinit>] - -Dio.netty.allocator.maxCachedBufferCapacity: 32768
23:25:04.342 DEBUG [PooledByteBufAllocator.<clinit>] - -Dio.netty.allocator.cacheTrimInterval: 8192
23:25:04.342 DEBUG [PooledByteBufAllocator.<clinit>] - -Dio.netty.allocator.cacheTrimIntervalMillis: 0
23:25:04.342 DEBUG [PooledByteBufAllocator.<clinit>] - -Dio.netty.allocator.useCacheForAllThreads: false
23:25:04.343 DEBUG [PooledByteBufAllocator.<clinit>] - -Dio.netty.allocator.maxCachedByteBuffersPerChunk: 1023
23:25:04.350 DEBUG [ByteBufUtil.<clinit>] - -Dio.netty.allocator.type: pooled
23:25:04.350 DEBUG [ByteBufUtil.<clinit>] - -Dio.netty.threadLocalDirectBufferSize: 0
23:25:04.350 DEBUG [ByteBufUtil.<clinit>] - -Dio.netty.maxThreadLocalCharBufferSize: 16384
23:25:04.369 DEBUG [LoggingHandler.channelRegistered] - [id: 0xb3aa8f7e] REGISTERED
23:25:04.373 DEBUG [LoggingHandler.bind] - [id: 0xb3aa8f7e] BIND: /127.0.0.1:4445
23:25:04.376 INFO [Standalone.execute] - Started Selenium Standalone 4.9.1 (revision eb2032df7f): http://127.0.0.1:4445
23:25:04.376 DEBUG [LoggingHandler.channelActive] - [id: 0xb3aa8f7e, L:/127.0.0.1:4445] ACTIVE
################################################################################
# WebDriver::Session
# set session [WebDriver::Session #auto $seleniumServer/wd/hub $caps] ;
################################################################################
23:26:05.668 DEBUG [LoggingHandler.channelRead] - [id: 0xb3aa8f7e, L:/127.0.0.1:4445] READ: [id: 0x1cb980c8, L:/127.0.0.1:4445 - R:/127.0.0.1:33345]
23:26:05.669 DEBUG [LoggingHandler.channelReadComplete] - [id: 0xb3aa8f7e, L:/127.0.0.1:4445] READ COMPLETE
23:26:05.690 DEBUG [AbstractByteBuf.<clinit>] - -Dio.netty.buffer.checkAccessible: true
23:26:05.690 DEBUG [AbstractByteBuf.<clinit>] - -Dio.netty.buffer.checkBounds: true
23:26:05.691 DEBUG [ResourceLeakDetectorFactory$DefaultResourceLeakDetectorFactory.newResourceLeakDetector] - Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@57973a03
23:26:05.735 DEBUG [ZlibCodecFactory.<clinit>] - -Dio.netty.noJdkZlibDecoder: false
23:26:05.736 DEBUG [ZlibCodecFactory.<clinit>] - -Dio.netty.noJdkZlibEncoder: false
23:26:05.747 DEBUG [Recycler.<clinit>] - -Dio.netty.recycler.maxCapacityPerThread: 4096
23:26:05.747 DEBUG [Recycler.<clinit>] - -Dio.netty.recycler.ratio: 8
23:26:05.747 DEBUG [Recycler.<clinit>] - -Dio.netty.recycler.chunkSize: 32
23:26:05.747 DEBUG [Recycler.<clinit>] - -Dio.netty.recycler.blocking: false
23:26:05.747 DEBUG [Recycler.<clinit>] - -Dio.netty.recycler.batchFastThreadLocalOnly: true
23:26:05.774 DEBUG [RequestConverter.channelRead0] - Incoming message: DefaultHttpRequest(decodeResult: success, version: HTTP/1.1)
POST /wd/hub/session HTTP/1.1
Host: 127.0.0.1:4445
User-Agent: Caius FT Framework
Connection: close
Accept: application/json;charset=utf-8
Accept-Encoding: gzip,deflate,compress
Content-Type: application/json;charset=utf-8
Content-Length: 487
23:26:05.774 DEBUG [RequestConverter.channelRead0] - Start of http request: DefaultHttpRequest(decodeResult: success, version: HTTP/1.1)
POST /wd/hub/session HTTP/1.1
Host: 127.0.0.1:4445
User-Agent: Caius FT Framework
Connection: close
Accept: application/json;charset=utf-8
Accept-Encoding: gzip,deflate,compress
Content-Type: application/json;charset=utf-8
Content-Length: 487
23:26:05.781 DEBUG [RequestConverter.channelRead0] - Incoming message: DefaultLastHttpContent(data: PooledSlicedByteBuf(ridx: 0, widx: 487, cap: 487/487, unwrapped: PooledUnsafeDirectByteBuf(ridx: 740, widx: 740, cap: 2048)), decoderResult: success)
23:26:05.785 DEBUG [RequestConverter.channelRead0] - End of http request: DefaultLastHttpContent(data: PooledSlicedByteBuf(ridx: 487, widx: 487, cap: 487/487, unwrapped: PooledUnsafeDirectByteBuf(ridx: 740, widx: 740, cap: 2048)), decoderResult: success)
23:26:05.837 DEBUG [SpanWrappedHttpHandler.execute] - Wrapping request. Before OpenTelemetryContext{tracer=io.opentelemetry.sdk.trace.SdkTracer@120d6fe6, context={}, span id=0000000000000000, trace id=00000000000000000000000000000000} and after OpenTelemetryContext{tracer=io.opentelemetry.sdk.trace.SdkTracer@120d6fe6, context={opentelemetry-trace-span-key=SdkSpan{traceId=0a4d56167357df63bfdb9deb447bebb5, spanId=60a7f44bf24dca0c, parentSpanContext=ImmutableSpanContext{traceId=00000000000000000000000000000000, spanId=0000000000000000, traceFlags=00, traceState=ArrayBasedTraceState{entries=[]}, remote=false, valid=false}, name=session_queue, kind=INTERNAL, attributes=AttributesMap{data={random.key=c66470e0-6cf5-4a7a-beba-2b71564e43fc}, capacity=128, totalAddedValues=1}, status=ImmutableStatusData{statusCode=UNSET, description=}, totalRecordedEvents=0, totalRecordedLinks=0, startEpochNanos=1686032765835000000, endEpochNanos=0}}, span id=60a7f44bf24dca0c, trace id=0a4d56167357df63bfdb9deb447bebb5}
23:26:05.840 DEBUG [HttpTracing.inject] - Injecting (POST) /session into OpenTelemetrySpan{traceId=0a4d56167357df63bfdb9deb447bebb5,spanId=60a7f44bf24dca0c} at org.openqa.selenium.remote.tracing.SpanWrappedHttpHandler:84
23:27:03.698 DEBUG [LocalDistributor.lambda$asRunnableHealthCheck$9] - Running healthcheck for Node http://127.0.0.1:4445
23:27:03.699 DEBUG [LocalDistributor.updateNodeAvailability] - Health check result for http://127.0.0.1:4445 was UP
23:29:03.698 DEBUG [LocalDistributor.lambda$asRunnableHealthCheck$9] - Running healthcheck for Node http://127.0.0.1:4445
23:29:03.699 DEBUG [LocalDistributor.updateNodeAvailability] - Health check result for http://127.0.0.1:4445 was UP

Escaping apostrophes

One of things I'm doing is running caius/Markdown against the mdtest tool's Markdown.mdtest; and one of the differences I see is that caius/Markdown escapes apostrophes as "'", which causes a false negative in the test suite. It's not wrong, certainly, but I'm never run into any problems with unescaped apostrophes, and I was wondering why you bothered.

Markdown: processor hangs indefinitely

The following input will cause Markdown::convert to hang indefinitely (at least, my variant of the code hangs, and I don't believe I've changed anything that would affect this):

* asterisk 1

* * *

It doesn't seem to matter what character is used as the list bullet. It happens with "*", "+", and "-".

I haven't started looking for a fix for this one; I thought you guys might find it more quickly.

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.