Git Product home page Git Product logo

blade's Introduction

Blade Logo

Blade Programming Language

Build Status Gitter License Coverage Status Version

Blade is a modern general-purpose programming language focused on enterprise Web, IoT, and secure application development. Blade offers a comprehensive set of tools and libraries out of the box leading to reduced reliance on third-party packages.

Blade comes equipped with an integrated package management system, simplifying the management of both internal and external dependencies and a self-hostable repository server making it ideal for private organizational and personal use. Its intuitive syntax and gentle learning curve ensure an accessible experience for developers of all skill levels. Leveraging the best features from JavaScript, Python, Ruby, and Dart, Blade provides a familiar and robust ecosystem that enables developers to harness the strengths of these languages effortlessly.

Example

The following code implements a simple backend API that runs on port 3000:

import http

var server = http.server(3000)
server.handle('GET', '/', @(req, res) {
  res.json(req)
})

echo 'Listening on Port 3000...'
server.listen()

What's interesting about Blade

  • Built-in package manager and repository server: Package management is built into the language module system. Blade also comes with Nyssa. Nyssa is a package manager and self-hosted repository server highly suitable for private use.
  • Zero-dependency full-stack web development: Blade comes with a built-in web server and a rich set of tools and libraries that support it, making it easy to build composable full-stack web applications out of the box:
    • Built-in Model-View-Template (MVT) based HTTP web server.
    • Built-in testing framework.
    • Built-in Object Relation Mapping support — Planned!
    • Built-in support for multiple databases.
    • Built-in web template engine — Wire.
    • Built-in routing library.
    • Built-in mail library with SMTP, IMAP, and POP3 support.
    • Built-in device integrations (such as support for COM/Ports, USB, etc.) — Planned!
    • Built-in cryptography library.
    • Built-in support for media processing (Image, audio, video, etc.) — Planned!
    • And more.
  • Function promotion: A feature of the Blade language that makes it easy to reuse any code from an imported module.
  • Access modifiers: Unlike JavaScript and Python, Blade supports access modifiers for variables, properties, functions, classes, modules, etc.
  • Decorator functions: Decorator functions are a set of class methods in Blade that makes extending the functionality of existing code super easy.
  • Easy to extend with C modules: Blade supports external extensions built in C with a built-in extension compiler via Nyssa. This feature makes it easy to extend language features with C modules.

Showcase of other uses

While Blade focuses on Web and IoT, it is also great for general software development. Below are a few showcases of libraries using Blade for other impressive stuff:

  • jsonrpc: A JSON-RPC library for Blade programming language.
  • tar: Pure Blade library for creating and extracting TAR archives.

Installation

To install Blade, please follow the instructions in the Building guide.

Usage

To start using Blade, please refer to the Tutorial section of the online documentation.

API Documentation

API documentation for Blade is under active development and can be found at bladelang.com.

Community

Contributing

We need your help to make Blade great! The Blade community is as friendly and welcoming as possible. All kinds of contributions like pull requests, suggestions, typo fixes in documentation, feature request, bug reports, and others are highly appreciated. Please refer to the Contributing guide for more information.

License

Blade is licensed under the 2-clause BSDL License.

blade's People

Contributors

brian3647 avatar galexite avatar horridmodz avatar mcfriend99 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

blade's Issues

Merge nyssa into Blade

The Nyssa project needs to be merged into Blade while the original project archived as soon as branch odyssey gets merged to main.

Failed to compile

Describe the bug

A clear and concise description of what the bug is.

To Reproduce

Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior

A clear and concise description of what you expected to happen.

Screenshots

If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context

Add any other context about the problem here.

Program execution that use Cygwin utilities disable Ansi sequence (cmd.exe terminal)

Windows 10 21H1
cmake version 3.21.4
VSC 2019 - 16.11.6 / MSVC v142 / kit SDK Windows 10 (10.0.19041.0)

install Cygwin/mingw64 if necessary

try this script:

import os

echo '\x1B[31m' + ' Hello foo: before c++/\msys64 use ' + '\x1B[0m'
os.exec('C:\\msys64\\mingw64\\bin\\c++ --version')
echo '\x1B[32m' + ' Hello foo:  after c++/\msys64 use ' + '\x1B[0m'

echo ""
echo '\x1B[31m' + ' Hello foo: before c++/cygwin use ' + '\x1B[0m'
os.exec('C:\\cygwin64\\bin\\c++ --version')
echo '\x1B[32m' + ' Hello foo:  after c++/cygwin use ' + '\x1B[0m'

result:

Hello foo: before c++/\msys64 use 
Hello foo:  after c++/\msys64 use 

Hello foo: before c++/cygwin use 
←[32m Hello foo:  after c++/cygwin use ←[0m

P.S. easier to test the 'bug': download wgrib2.exe and all cygwin dll at:
https://ftp.cpc.ncep.noaa.gov/wd51we/wgrib2/Windows10/v3.0.2/

echo '\x1B[31m' + ' Hello foo: before wgrib2 use ' + '\x1B[0m'
os.exec('path_to_wgrib2\\wgrib2 --version')
echo '\x1B[32m' + ' Hello foo:  after wgrib2 use ' + '\x1B[0m'

fix for segmentation fault

The segmentation fault in free_objects() occurs due to b_obj_string fields being errorneously freed twice, which results in those objects becoming invalid.

The fields in question are name in b_obj_closure, name in b_obj_func, name in b_obj_class and mode & path in b_obj_file.

Additionally, leaks occur whenever copy_string() is called with an empty string, as well as unnecessary b_obj_string creation in io_module_(stdin|stdout|stderr) for the field mode (which is already created during call to new_file).

After fixing that, there should be no longer a segmentation fault, although there are approximately 10 blocks that I suspect are created during calls to strdup.

You can find most of them with the regex '(->|.)\b(name|mode|path)\b', i.e. with grep.

`module '_ssl' not found`

Platform

Windows 10

Blade Version

v0.0.82 (from the releases)

Issue

Using the example application in the README:

import http
import json

var server = http.server(3000)
server.on_receive(|request, response| {
    response.headers['Content-Type'] = 'application/json'
  response.write(json.encode(request))
})

echo 'Listening on Port 3000...'
server.listen()

Results in the error: Unhandled Exception: module '_ssl' not found.

Is it not possible to run an HTTP server without SSL?

README code example

Often times what gets me and many other people to not look further into projects, is the lack of very minimal examples.
I think the README should contain a tiny example, so that people can get a feel for the language right away. Since the language is very small, it doesn't really make that much sense to have a hello world example.

I propose something like:

def sum(numbers) {
    var result = 0

    for num in number {
        result += num
    }

    print(result)
}

sum([1, 2, 3, 4]) # this will print "10"

This presents the developer with information about:

  • functions
    • defining functions
    • calling functions
    • function arguments
  • variables
  • for loops
  • assignment
  • printing
  • arrays
  • single-line comments

Generate documentation with comments

Creating documentation not only for Blade, but also for user-made modules would be nice with regular comments.

/* doc
  prints the sum of `a` and `b`
*/
def add(a, b) {
  print(a + b)
}
# doc prints the resulting value of `a` subtracted by `b`
def sub(a, b) {
  print(a + b)
}

Then the output could look like:


def add(a, b)

prints the sum of a and b

def sub(a, b)

prints the resulting value of a subtracted by b


This would allow anyone to add documentation to their own application / module very easily. It would also make it easy to create a tool that generates the documentation. This also groups documentation together with the specific code, making it easier to navigate and edit. It would also be familiar to devs, that are used to adding documentation with ///.

For the documentation generator, I guess these comments could be added to a map / dictionary like so:

{
  'def add(a, b)': 'prints the sum of `a` and `b`',
  'def sub(a, b)': 'prints the resulting value of `a` subtracted by `b`',
}

Where depending on the input flags, this dictionary can easily output the documentation in markdown, HTML, JSON or something completely else.

Multi-line (Block) comments failed

os: Windows 10/21H1
blade: 0.0.6/MSVC or MSYS2

Multi-line comments (at least at the script end) failed.
For MSYS2-compiled blade:

echo "Hello blade world"
/*
var a = 11111111111
*/

Result:

SyntaxError:
    File: bug_10.b, Line: 4
    Error: unexpected character ³
SyntaxError:
    File: bug_10.b, Line: 4
    Error: unexpected character £

For MSVC-compiled blade:

echo "Hello blade world"
/*
var a = 11111
*/

Result:

SyntaxError:
    File: bug_10.b, Line: 4
    Error at '*': expected expression

Depending on the length of the multi-line comment, the comment is taken into account or not.

Remove REPL `"nil"` printing

Is your feature request related to a problem? Please describe.

print(10) in the REPL outputs 10nil
It does not look nice when printing, that it is followed by nil.

Describe the solution you'd like

print(10) should print 10 and not include nil.

This can be fixed by changing:
https://github.com/blade-lang/blade/blob/main/src/vm.c#L1549-L1553

Currently this is the code:

if (vm->is_repl) {
  echo_value(peek(vm, 0));
} else {
  print_value(peek(vm, 0));
}

I propose:

if (vm->is_repl) {
  // maybe have a variable to avoid peeking twice
  if (!IS_NIL(peek(vm, 0))) {
    echo_value(peek(vm, 0));
  }
} else {
  print_value(peek(vm, 0));
}

I'm curious as to why this is a thing. Is this a bug or is it for something like debugging? If wanted I can go ahead and PR this.

-h prints to stderr

Describe the bug

When running <blade> -h, the help message is printed to stderr, ignoring if it is a failure or not:

src/blade.c

...
void show_usage(char *argv[], bool fail) {
  fprintf(stderr, "Usage: %s [-[h | d | j | v | g]] [filename]\n", argv[0]);
  ...
  exit(fail ? EXIT_FAILURE : EXIT_SUCCESS);
}

To Reproduce

Steps to reproduce the behavior:

  1. Install blade
  2. Run blade -h

Expected behavior

If it's not a failure, print to stdout.

Desktop (please complete the following information):

  • OS: Pop!_OS 21.04 x86_64

Professional looking new logo and icon for Blade

Hi All,

The current Blade icon and logo are not very professional or attractive. Using this issue to request help from designers to help create one that looks cool and professional.

Thanks in advance.

Regards

A loop that creates a long list is unexpectedly interrupted

Windows 10 / 21H1
Blade 0.0.6 (latest)

The following script that creates a list of 'n' numbers breaks if 'n' is above 406

 def create_list(list_len) {
     var list = []
     echo "Trying to create a ${list_len}-elements list"
	     iter var j = 0; j < list_len; j++ {
		     list += [j]
	     }
     echo "      list content: " + list[0] + ", " + list[1] + " ... " + list[-2] + ", " + list[-1]
}
 
 var n = 500
 echo ""
 create_list(n);

echo "\nEnd of script"

Result if 'n' equals 500:

 Trying to create a 500-elements list

Result if 'n' equals 400:

 Trying to create a 400-elements list
           list content: 0, 1 ... 398, 399

 End of script

Potential Security Issue

Hello,

We recently received multiple vulnerability disclosures against your repository. I couldn't find an e-mail to contact or a security process to follow, so created this issue instead.

If you would like me to e-mail over the details or put them on the GitHub Issue, I'm more than happy to facilitate this for you. Otherwise, you can access the advisories here and here and here.

It is private to you and the discloser of the report.

If you have any questions, let me know.

-- Jamie from huntr.dev

Not Found error when compressing directories in windows

Describe the bug

When using the zip module to compress a directory on the Windows OS, paths with names starting in a . such as .git, .gitignore etc causes a file not found error.

To Reproduce

import zip

zip.compress('/my/git/repo', 'dest.zip')

Expected behavior

Correctly compressed zip archive

OS

  • Windows

Application hangs on dictionary accessing

main.b

import http
import .router { * }

var router = Router()
router.get("/favicon.ico", |request, response| {
  echo "It got the icon!"
  response.headers['Content-Type'] = 'text/html'
  response.write("<h1>Hello World!</h1>")
})
router.serve(3000)

router.b

import http
import json

class Router {
  var get_routes = {}

  serve(port) {
    var server = http.server(port)
    server.on_receive(|request, response| {
      print(request.path + "\n")
      var next = self.get_routes[path]
      print("next is ${next}")

      if (next != nil) {
        next(request, response)
      } else {
        response.headers['Content-Type'] = 'text/html'
        response.write("<h1>404, Not Found!</h1>")
      }
    })

    echo 'Listening on Port ${port}...'
    server.listen()
  }

  get(path, fn) {
    # if (path in self.get_routes)
    if (self.get_routes.get(path) != nil) {
      die Exception('${path} already exists!')
    }

    self.get_routes[path] = fn
  }
}

This is what I see in the console:

Listening on Port 3000...
/ 

This is what I expected to see in the console:

Listening on Port 3000...
/ 
next is {/favicon.ico: <function |(2) at 000001ccf80b1f50>}

Import not working when running in dotted path

Describe the bug

Whenever Blade is installed in a path with containing the . character (for example using the Autoinstall script), imports stop working.

To Reproduce

Steps to reproduce the behavior:

  1. Install Blade using the Autoinstall script for Linux and OSX
  2. Launch the Blade REPL
  3. Try to import any library.
  4. See error

Expected behavior

Import should work properly whether the application directory contains .s in it's path or not.

Additional context

This is due to how merge_paths in src/pathinfo.c currently works.

Add support for operator overloading

Is your feature request related to a problem? Please describe.

As it stands, Blade classes are first class and can be used in almost anything including iterables, values and more. It will greatly increase consistency to have Blade classes support operator overloading from classes.

Proposed Solution

Since today, Blade classes can become iterators by implementing the @iter and @itern decorators, Blade can employ decorators for operator overloading support.

E.g.

class A {
    @+(a2) {
        return self.value + a2.value
    }
}

var a1 = A()
a1.value = 5

var a2 = A()
a2.value = 7

echo a1 + a2

The above sample code should print 12 to terminal.

Alternative Solution

As an alternative, we could use a keyword operator.

For example:

class A {
    operator + {
        return self.value + __arg__.value
    }
}

var a1 = A()
a1.value = 5

var a2 = A()
a2.value = 7

echo a1 + a2

This will at best require an extra conditionally valid keyword __arg__.

Reassigning/overwriting file variable breaks a loop that creates a long string

OS: Windows 10 Professional version: 21H1
Blade version : 0.0.6

Run the following script,

var str_len = 1500
#str_len = 200
var file_id = file('foo')
file_id = file('bar')
# Loop for creating 'str' string
var str = ''
iter var idx = 0; idx < str_len; idx++ {
    str += '1'
}
echo 'End of iter loop'

Result: the last line is not executed because the loop that creates the string stops before the end and interrupts the script.

If you either uncomment line 2 # str_len = 200 (the string length is reduced to 200 characters) or comment line 4 file_id = file('bar') (file_id is no longer overwrited), End of iter loop is displayed as expected.

Key visible but not possible to use in dictionary

OS

Windows 10

Blade Version

v0.0.83

Description

I have found a really interesting case.

I have a dictionary like this:

{0: /foo/bar, 1: foo, 2: bar, firstname: foo, wildcard: bar}

Now all of the following don't work:

echo mydict.contains("wildcard") # false
for key, value in request.params {
  echo '"${key}" = "${value}"'
}
# "0" = "/foo/bar"
# "1" = "foo"
# "2" = "bar"
# "firstname" = "foo"
# "wildcard

# Yes, the last one is not a mistake, it actually just prints "wildcard without closing it

So even though doing echo mydict shows the key is there, something is wrong with it, so I cannot retrieve the value.

This can be seen on dev branch on: https://github.com/BenStigsen/router/tree/dev
Going to localhost:3000/foo/bar will not show bar even though it's in the dictionary.

I don't have a shorter reproducible example than the one in my repo.

Specifically L19-L29 gets the route, then matches on the regex. If there's a match, then it sets req.params to the regex matches.
L45 replaces something like /route/* with the regex /route/(?P<wildcard>.*), so that the wildcard gets stored in the wildcard key, in the returned regex dictionary.

Package Manager?

Hello. I am kind of curious, will there be a package manager for this programming language? Examples could be pip for Python, or Cargo for Rust. This could be a good step in making this language usable for a lot of people. If you want, I could add a PR or an entirely different repository for this. Although, I don't have a good name for the package manager or the packages.

Expose AST as a standard library module

It would be useful to expose parsing Blade code as a standard library module for the purposes of writing utilities, generating documentation and a language server, for example.

Inconsistent socket behaviour across platforms

Socket doesn't work well on Windows

Due to how the socket constants such as AF_INET are defined in the socket.b library file, it does not account for the different values that may be encountered on the different platforms.

Expected behavior

The socket module constants should tally with their native value.

Prescribed solution

Bind the values from C into the _socket module and import them in the socket module for clear definition and script level documentation so that people reading the socket.b file can tell the values are declared.

Creation of a programming language based on Blade.

Hello,

We want to create a programming language for professional, personal and utility needs. We want to base ourselves on your language, which we find very interesting in its simplicity and speed. Can we fork your project? Or take over the project for free?

Cordially,
Zuygui

Kut Package Manager

I writing an package manager for your language. What informations are important on the package structure in your language ?

Cordialy

Installation Error

I followed the instructions for installation, however once I get to curl the repo, I get an error 46% into the make saying the following:

[ 46%] Built target linenoise
cc: fatal error: Killed signal terminated program cc1
compilation terminated.
gmake[2]: *** [thirdparty/pcre2/CMakeFiles/pcre2.dir/build.make:251: thirdparty/pcre2/CMakeFiles/pcre2.dir/pcre2_match.c.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:351: thirdparty/pcre2/CMakeFiles/pcre2.dir/all] Error 2
gmake: *** [Makefile:114: all] Error 2
cp: cannot create directory '/home/root/.blade': No such file or directory
mv: cannot stat '/home/root/.blade': No such file or directory
Linking Blade...

Desktop:

  • OS: Raspbian / Raspberry Pi OS
  • Version: 11 (Bullseye)

Double backslashes with a single backslash replacement fails

Windows 10 21H1
cmake version 3.21.4
VSC 2019 - 16.11.6 / MSVC v142 / kit SDK Windows 10 (10.0.19041.0)

try this script:

var str = 'C:\\\\foo\\\\bar'

print("'" + str + "'.replace('\\\\', '/') ->  ")
echo str.replace('\\\\', '/')
echo ""

print("'" + str + "'.replace('\\\\', '.') ->  ")
echo str.replace('\\\\', '.')
echo ""

print("'" + str + "'.replace('\\\\', '\\') ->  ")
echo str.replace('\\\\', '\\')

result:

'C:\\foo\\bar'.replace('\\', '/') ->  C://foo//bar

'C:\\foo\\bar'.replace('\\', '.') ->  C:..foo..bar

'C:\\foo\\bar'.replace('\\', '\') ->  Unhandled Exception: RegexError: bad escape sequence in replacement string
  StackTrace:
    File: bug_3.b, Line: 12, In: <script>

Merge qi into Blade

Merging qi — the testing package originally available as a Nyssa package at mcfriend99/qi into Blade as a Nyssa feature that can be invoke with nyssa test.

Make Blade documentation self-hosted

This task intends to replace the existing bladelang.com website with a new version that's completely built in Blade. Nyssa documentation and Getting Started link will also be effectively pointing to it as Nyssa documentation will now be hosted along with Blade.

echo not requiring parenthesis

Long time since I've been here, but I've been following the project closely.
One thing that I have not been a fan of, is the exception with echo not requiring braces.
It's inconsistent and I'm not quite sure I understand the purpose of it?

Replacing `# comments` with `// comments`

Currently comments are being made like so:

# Hello World

/* 
Hello
There
World 
*/

This to me does not make sense. Not only is this inconsistent with languages like JS, C, Python and a whole bunch of other languages. But it's also a bit harder to remember.
My proposal is to use // comment instead as it makes switching to Blade easier. It's easier to remember, not only because of other languages, but also because one character less is used.

If this isn't going to be changed to // that is fine, but I do at least propose some more consistency between single line and multiline comments. In JS, C and many more languages this is the / character, since it is used for both single-line and multiline. In Lua this is --, etc...

Proposal to refocus the language on Web, IoT and Security while remaining general-purpose

TL;DR

I'm raising a proposal to refocus Blade language and its continued development on built-in support and focus on Web, IoT and secure application development without needing to install any third-party package and without losing it's ability for general-purpose development.

Content

After multiple considerations, I begin to feel that while being a general-purpose language, Blade will benefit a lot more from crafting a niche for itself as a general-purpose batteries-included language with a focus on Web, IoT and secure application development where third-party packages are completely optional.

In order to achieve this, Blade will need to begin to provide tooling to support this goals. This will include at a bare minimum the following tools:

  • Built-in testing framework.
  • Built-in ORM support.
  • Built-in support for more databases.
  • Built-in support for media processing (Image, audio, video etc).
  • Built-in templating engine.
  • Built-in routing library.
  • Built-in cryptographic library.
  • A more advanced/robust HTTP server implementation (we'll need to go beyond basics and aspire to achieve built-in production grade http server in the http module with support for UDP).
  • A more robust http client implementation in the http module.
  • Built-in device integrations (such as support for COM/Ports, USB etc).
  • Built-in mail library.
  • Built-in package management library (it will encourage adoption for Blade).
  • Built-in C extension builder/packager.

Just to mention a few.

Along with this proposal, I have proposed some major changes to the Blade distribution.

  1. Merge Nyssa into Blade as the built-in package manager.
  2. Merge qi into Blade as the built-in testing framework.
  3. Merge wire into Blade as the built-in template engine.
  4. Merge kite into Blade as the default C extension builder/packager.
  5. Merge miniroute as the built-in router.
  6. Merge mysql int Blade as the built-in MySQL database integration.

What does this mean for the next release.

This proposal is aimed to start taking effect at version 0.0.86. The next release should be unaffected by this to allow more time for bug-fixes and testing for the proposed mergers.

Who can vote?

Everybody.

How to Vote

To vote on this proposal, kindly drop a comment or a like.

❤️‍🔥 @mcfriend99

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.