Complete coffee -> JS conversion of docs

This commit is contained in:
Luiz Américo 2018-12-17 20:05:10 -03:00
parent d5d8e3c613
commit 5274136477
9 changed files with 245 additions and 248 deletions

View File

@ -37,29 +37,29 @@ covered by another annotation and the user won't be able to click it.
Here is an example that uses a few of the annotation types.
# Add the link text
// Add the link text
doc.fontSize(25)
.fillColor('blue')
.text('This is a link!', 20, 0)
.text('This is a link!', 20, 0);
# Measure the text
width = doc.widthOfString('This is a link!')
height = doc.currentLineHeight()
// Measure the text
const width = doc.widthOfString('This is a link!');
const height = doc.currentLineHeight();
# Add the underline and link annotations
doc.underline(20, 0, width, height, color: 'blue')
.link(20, 0, width, height, 'http://google.com/')
// Add the underline and link annotations
doc.underline(20, 0, width, height, {color: 'blue'})
.link(20, 0, width, height, 'http://google.com/');
# Create the highlighted text
// Create the highlighted text
doc.moveDown()
.fillColor('black')
.highlight(20, doc.y, doc.widthOfString('This text is highlighted!'), height)
.text('This text is highlighted!')
.text('This text is highlighted!');
# Create the crossed out text
// Create the crossed out text
doc.moveDown()
.strike(20, doc.y, doc.widthOfString('STRIKE!'), height)
.text('STRIKE!')
.text('STRIKE!');
The output of this example looks like this.
@ -70,11 +70,13 @@ that is the fault of the PDF spec itself. Calculating a rectangle manually isn't
fun, but PDFKit makes it easier for a few common annotations applied to text, including
links, underlines, and strikes. Here's an example showing two of them:
doc.fontSize 20
.fillColor 'red'
.text 'Another link!', 20, 0,
doc.fontSize(20)
.fillColor('red')
.text('Another link!', 20, 0, {
link: 'http://apple.com/',
underline: true
}
);
The output is as you'd expect:

View File

@ -9,16 +9,15 @@
const fs = require('fs');
const vm = require('vm');
const md = require('markdown').markdown;
const coffee = require('coffee-script');
const CodeMirror = require('codemirror/addon/runmode/runmode.node');
const PDFDocument = require('../');
process.chdir(__dirname);
// setup code mirror coffeescript mode
const filename = require.resolve('codemirror/mode/coffeescript/coffeescript');
const coffeeMode = fs.readFileSync(filename, 'utf8');
vm.runInNewContext(coffeeMode, {CodeMirror});
// setup code mirror javascript mode
const filename = require.resolve('codemirror/mode/javascript/javascript');
const jsMode = fs.readFileSync(filename, 'utf8');
vm.runInNewContext(jsMode, {CodeMirror});
// style definitions for markdown
const styles = {
@ -142,7 +141,7 @@ class Node {
// use code mirror to syntax highlight the code block
var code = this.content[0].text;
this.content = [];
CodeMirror.runMode(code, 'coffeescript', (text, style) => {
CodeMirror.runMode(code, 'javascript', (text, style) => {
const color = colors[style] || colors.default;
const opts = {
color,
@ -158,11 +157,11 @@ class Node {
case 'img':
// images are used to generate inline example output
// compiles the coffeescript to JS so it can be run
// stores the JS so it can be run
// in the render method
this.type = 'example';
code = codeBlocks[this.attrs.alt];
if (code) { this.code = coffee.compile(code); }
if (code) { this.code = code; }
this.height = +this.attrs.title || 0;
break;
}
@ -266,7 +265,7 @@ class Node {
}
}
// reads and renders a markdown/literate coffeescript file to the document
// reads and renders a markdown/literate javascript file to the document
const render = function(doc, filename) {
codeBlocks = [];
const tree = md.parse(fs.readFileSync(filename, 'utf8'));

View File

@ -1,15 +1,7 @@
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* DS205: Consider reworking code to avoid use of IIFEs
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
const jade = require('jade');
const { markdown } = require('markdown');
const fs = require('fs');
const vm = require('vm');
const coffee = require('coffee-script');
const {exec} = require('child_process');
const PDFDocument = require('../');
@ -53,60 +45,50 @@ let imageIndex = 0;
const generateImages = function(tree) {
// find code blocks
const codeBlocks = [];
for (var node of Array.from(tree)) {
for (var node of tree) {
if (node[0] === 'code_block') {
codeBlocks.push(node[1]);
}
}
return (() => {
const result = [];
for (node of Array.from(tree)) {
if ((node[0] === 'para') && Array.isArray(node[1]) && (node[1][0] === 'img')) {
// compile the code
const attrs = node[1][1];
let code = codeBlocks[attrs.alt];
if (code) { code = coffee.compile(code); }
delete attrs.height; // used for pdf generation
for (node of tree) {
if ((node[0] === 'para') && Array.isArray(node[1]) && (node[1][0] === 'img')) {
// compile the code
const attrs = node[1][1];
let code = codeBlocks[attrs.alt];
delete attrs.height; // used for pdf generation
// create a PDF and run the example
const doc = new PDFDocument;
const f = `img/${imageIndex++}`;
var file = fs.createWriteStream(`${f}.pdf`);
doc.pipe(file);
doc.translate(doc.x, doc.y);
doc.scale(0.8);
doc.x = (doc.y = 0);
// create a PDF and run the example
const doc = new PDFDocument;
const f = `img/${imageIndex++}`;
var file = fs.createWriteStream(`${f}.pdf`);
doc.pipe(file);
doc.translate(doc.x, doc.y);
doc.scale(0.8);
doc.x = (doc.y = 0);
vm.runInNewContext(code, {
doc,
lorem
}
);
delete attrs.title;
delete attrs.alt;
attrs.href = `${f}.png`;
// write the PDF, convert to PNG using the mac `sips`
// command line tool, and trim with graphicsmagick
(f =>
file.on('finish', () =>
exec(`sips -s format png ${f}.pdf --out ${f}.png`, function() {
fs.unlink(`${f}.pdf`);
return exec(`gm convert ${f}.png -trim ${f}.png`);
})
)
)(f);
result.push(doc.end());
} else {
result.push(undefined);
vm.runInNewContext(code, {
doc,
lorem
}
);
delete attrs.title;
delete attrs.alt;
attrs.href = `${f}.png`;
// write the PDF, convert to PNG using the mac `sips`
// command line tool, and trim with graphicsmagick
file.on('finish', () =>
exec(`sips -s format png ${f}.pdf --out ${f}.png`, function() {
fs.unlink(`${f}.pdf`);
exec(`gm convert ${f}.png -trim ${f}.png`);
})
)
}
return result;
})();
}
};
const pages = [];
@ -114,7 +96,7 @@ for (let file of Array.from(files)) {
let content = fs.readFileSync(file, 'utf8');
// turn github highlighted code blocks into normal markdown code blocks
content = content.replace(/^```coffeescript\n((:?.|\n)*?)\n```/mg, (m, $1) => ` ${$1.split('\n').join('\n ')}`);
content = content.replace(/^```javascript\n((:?.|\n)*?)\n```/mg, (m, $1) => ` ${$1.split('\n').join('\n ')}`);
const tree = markdown.parse(content);
const headers = extractHeaders(tree);

View File

@ -13,21 +13,21 @@ Creating a PDFKit document is quite simple. Just require the `pdfkit` module
in your CoffeeScript or JavaScript source file and create an instance of the
`PDFDocument` class.
PDFDocument = require 'pdfkit'
doc = new PDFDocument
const PDFDocument = require('pdfkit');
const doc = new PDFDocument;
`PDFDocument` instances are readable Node streams. They don't get saved anywhere automatically,
but you can call the `pipe` method to send the output of the PDF document to another
writable Node stream as it is being written. When you're done with your document, call
the `end` method to finalize it. Here is an example showing how to pipe to a file or an HTTP response.
doc.pipe fs.createWriteStream('/path/to/file.pdf') # write to PDF
doc.pipe res # HTTP response
doc.pipe(fs.createWriteStream('/path/to/file.pdf')); // write to PDF
doc.pipe(res); // HTTP response
# add stuff to PDF here using methods described below...
// add stuff to PDF here using methods described below...
# finalize the PDF and end the stream
doc.end()
// finalize the PDF and end the stream
doc.end();
The `write` and `output` methods found in PDFKit before version 0.5 are now deprecated.
@ -48,27 +48,28 @@ To get a Blob from a `PDFDocument`, you should pipe it to a [blob-stream](https:
which is a module that generates a Blob from any Node-style stream. The following example uses Browserify to load
`PDFKit` and `blob-stream`, but if you're not using Browserify, you can load them in whatever way you'd like (e.g. script tags).
# require dependencies
PDFDocument = require 'pdfkit'
blobStream = require 'blob-stream'
// require dependencies
const PDFDocument = require('pdfkit');
const blobStream = require('blob-stream');
# create a document the same way as above
doc = new PDFDocument
// create a document the same way as above
const doc = new PDFDocument;
# pipe the document to a blob
stream = doc.pipe(blobStream())
// pipe the document to a blob
const stream = doc.pipe(blobStream());
# add your content to the document here, as usual
// add your content to the document here, as usual
# get a blob when you're done
doc.end()
stream.on 'finish', ->
# get a blob you can do whatever you like with
blob = stream.toBlob('application/pdf')
// get a blob when you're done
doc.end();
stream.on('finish', function() {
// get a blob you can do whatever you like with
const blob = stream.toBlob('application/pdf');
# or get a blob URL for display in the browser
url = stream.toBlobURL('application/pdf')
iframe.src = url
// or get a blob URL for display in the browser
const url = stream.toBlobURL('application/pdf');
iframe.src = url;
});
You can see an interactive in-browser demo of PDFKit [here](http://pdfkit.org/demo/browser.html).
@ -87,8 +88,7 @@ quite simple!
To add some content every time a page is created, either by calling `addPage()` or automatically, you can use the `pageAdded` event.
doc.on 'pageAdded', ->
doc.text "Page Title"
doc.on('pageAdded', () => doc.text("Page Title"));
You can also set some options for the page, such as its size and orientation.
@ -110,18 +110,20 @@ on all sides.
For example:
# Add a 50 point margin on all sides
doc.addPage
margin: 50
// Add a 50 point margin on all sides
doc.addPage({
margin: 50});
# Add different margins on each side
doc.addPage
margins:
top: 50
bottom: 50
left: 72
// Add different margins on each side
doc.addPage({
margins: {
top: 50,
bottom: 50,
left: 72,
right: 72
}
});
## Switching to previous pages
@ -142,28 +144,31 @@ never need to call it. Finally, there is a `bufferedPageRange` method, which re
of pages that are currently buffered. Here is a small example that shows how you might add page
numbers to a document.
# create a document, and enable bufferPages mode
doc = new PDFDocument
bufferPages: true
// create a document, and enable bufferPages mode
let i;
let end;
const doc = new PDFDocument({
bufferPages: true});
# add some content...
doc.addPage()
# ...
doc.addPage()
// add some content...
doc.addPage();
// ...
doc.addPage();
# see the range of buffered pages
range = doc.bufferedPageRange() # => { start: 0, count: 2 }
// see the range of buffered pages
const range = doc.bufferedPageRange(); // => { start: 0, count: 2 }
for i in [range.start...range.start + range.count]
doc.switchToPage(i)
doc.text "Page #{i + 1} of #{range.count}"
for (i = range.start, end = range.start + range.count, range.start <= end; i < end; i++;) {
doc.switchToPage(i);
doc.text(`Page ${i + 1} of ${range.count}`);
}
# manually flush pages that have been buffered
doc.flushPages()
// manually flush pages that have been buffered
doc.flushPages();
# or, if you are at the end of the document anyway,
# doc.end() will call it for you automatically.
doc.end()
// or, if you are at the end of the document anyway,
// doc.end() will call it for you automatically.
doc.end();
## Setting document metadata

View File

@ -21,29 +21,29 @@ When a `fit` or `cover` array is provided, PDFKit accepts these additional optio
Here is an example showing some of these options.
# Scale proprotionally to the specified width
doc.image('images/test.jpeg', 0, 15, width: 300)
.text('Proportional to width', 0, 0)
// Scale proprotionally to the specified width
doc.image('images/test.jpeg', 0, 15, {width: 300})
.text('Proportional to width', 0, 0);
# Fit the image within the dimensions
doc.image('images/test.jpeg', 320, 15, fit: [100, 100])
// Fit the image within the dimensions
doc.image('images/test.jpeg', 320, 15, {fit: [100, 100]})
.rect(320, 15, 100, 100)
.stroke()
.text('Fit', 320, 0)
.text('Fit', 320, 0);
# Stretch the image
doc.image('images/test.jpeg', 320, 145, width: 200, height: 100)
.text('Stretch', 320, 130)
// Stretch the image
doc.image('images/test.jpeg', 320, 145, {width: 200, height: 100})
.text('Stretch', 320, 130);
# Scale the image
doc.image('images/test.jpeg', 320, 280, scale: 0.25)
.text('Scale', 320, 265)
// Scale the image
doc.image('images/test.jpeg', 320, 280, {scale: 0.25})
.text('Scale', 320, 265);
# Fit the image in the dimensions, and center it both horizontally and vertically
doc.image('images/test.jpeg', 430, 15, fit: [100, 100], align: 'center', valign: 'center')
// Fit the image in the dimensions, and center it both horizontally and vertically
doc.image('images/test.jpeg', 430, 15, {fit: [100, 100], align: 'center', valign: 'center'})
.rect(430, 15, 100, 100)
.stroke()
.text('Centered', 430, 0)
.text('Centered', 430, 0);
* * *

View File

@ -6,14 +6,14 @@ Outlines are the heirachical bookmarks that display in some PDF readers. Current
Here is an example of adding a bookmark with a single child bookmark.
# Get a reference to the Outline root
outline = doc.outline
// Get a reference to the Outline root
const { outline } = doc;
# Add a top-level bookmark
top = outline.addItem('Top Level')
// Add a top-level bookmark
const top = outline.addItem('Top Level');
# Add a sub-section
top.addItem('Sub-section')
// Add a sub-section
top.addItem('Sub-section');
## Options
@ -21,8 +21,8 @@ The `options` parameter currently only has one property: `expanded`. If this val
In this example the 'Top Level' section will be expanded to show 'Sub-section'.
# Add a top-level bookmark
top = outline.addItem('Top Level', { expanded: true })
// Add a top-level bookmark
const top = outline.addItem('Top Level', { expanded: true });
# Add a sub-section
top.addItem('Sub-section')
// Add a sub-section
top.addItem('Sub-section');

View File

@ -81,10 +81,8 @@ PDFKit supports also the following paper sizes. The dimensions in brackets are i
In order to use the predefined sizes, the name of the size (as named in the lists above) should be passed to either the `PDFDocument` constructor or the `addPage()` function in the `size` property of the `options` object, as shown in the example below, using `A7` as the preferred size.
# Passing size to the constructor
doc = new PDFDocument
size: 'A7'
// Passing size to the constructor
const doc = new PDFDocument({size: 'A7'});
# Passing size to the addPage function
doc.addPage
size: 'A7'
// Passing size to the addPage function
doc.addPage({size: 'A7'});

View File

@ -6,7 +6,7 @@ PDFKit makes adding text to documents quite simple, and includes many options
to customize the display of the output. Adding text to a document is as simple
as calling the `text` method.
doc.text 'Hello world!'
doc.text('Hello world!')
Internally, PDFKit keeps track of the current X and Y position of text as it
is added to the document. This way, subsequent calls to the `text` method will
@ -14,7 +14,7 @@ automatically appear as new lines below the previous line. However, you can
modify the position of text by passing X and Y coordinates to the `text`
method after the text itself.
doc.text 'Hello world!', 100, 100
doc.text('Hello world!', 100, 100)
If you want to move down or up by lines, just call the `moveDown` or `moveUp`
method with the number of lines you'd like to move (1 by default).
@ -39,30 +39,38 @@ four options: `left` (the default), `center`, `right`, and `justify`. They
work just as they do in your favorite word processor, but here is an example
showing their use in a text box.
lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam in suscipit purus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus nec hendrerit felis. Morbi aliquam facilisis risus eu lacinia. Sed eu leo in turpis fringilla hendrerit. Ut nec accumsan nisl.'
const lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam in suscipit purus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus nec hendrerit felis. Morbi aliquam facilisis risus eu lacinia. Sed eu leo in turpis fringilla hendrerit. Ut nec accumsan nisl.';
doc.fontSize 8
doc.text 'This text is left aligned. ' + lorem,
width: 410
doc.fontSize(8);
doc.text(`This text is left aligned. ${lorem}`, {
width: 410,
align: 'left'
}
);
doc.moveDown()
doc.text 'This text is centered. ' + lorem,
width: 410
doc.moveDown();
doc.text(`This text is centered. ${lorem}`, {
width: 410,
align: 'center'
}
);
doc.moveDown()
doc.text 'This text is right aligned. ' + lorem,
width: 410
doc.moveDown();
doc.text(`This text is right aligned. ${lorem}`, {
width: 410,
align: 'right'
}
);
doc.moveDown()
doc.text 'This text is justified. ' + lorem,
width: 410
doc.moveDown();
doc.text(`This text is justified. ${lorem}`, {
width: 410,
align: 'justify'
}
);
# draw bounding rectangle
doc.rect(doc.x, 0, 410, doc.y).stroke()
// draw bounding rectangle
doc.rect(doc.x, 0, 410, doc.y).stroke();
The output of this example, looks like this:
@ -103,14 +111,15 @@ Additionally, the fill and stroke color and opacity methods described in the
Here is an example combining some of the options above, wrapping a piece of text into three columns, in a specified width and height.
lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam in suscipit purus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus nec hendrerit felis. Morbi aliquam facilisis risus eu lacinia. Sed eu leo in turpis fringilla hendrerit. Ut nec accumsan nisl. Suspendisse rhoncus nisl posuere tortor tempus et dapibus elit porta. Cras leo neque, elementum a rhoncus ut, vestibulum non nibh. Phasellus pretium justo turpis. Etiam vulputate, odio vitae tincidunt ultricies, eros odio dapibus nisi, ut tincidunt lacus arcu eu elit. Aenean velit erat, vehicula eget lacinia ut, dignissim non tellus. Aliquam nec lacus mi, sed vestibulum nunc. Suspendisse potenti. Curabitur vitae sem turpis. Vestibulum sed neque eget dolor dapibus porttitor at sit amet sem. Fusce a turpis lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;'
const lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam in suscipit purus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus nec hendrerit felis. Morbi aliquam facilisis risus eu lacinia. Sed eu leo in turpis fringilla hendrerit. Ut nec accumsan nisl. Suspendisse rhoncus nisl posuere tortor tempus et dapibus elit porta. Cras leo neque, elementum a rhoncus ut, vestibulum non nibh. Phasellus pretium justo turpis. Etiam vulputate, odio vitae tincidunt ultricies, eros odio dapibus nisi, ut tincidunt lacus arcu eu elit. Aenean velit erat, vehicula eget lacinia ut, dignissim non tellus. Aliquam nec lacus mi, sed vestibulum nunc. Suspendisse potenti. Curabitur vitae sem turpis. Vestibulum sed neque eget dolor dapibus porttitor at sit amet sem. Fusce a turpis lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;';
doc.text lorem,
columns: 3
columnGap: 15
height: 100
width: 465
doc.text(lorem, {
columns: 3,
columnGap: 15,
height: 100,
width: 465,
align: 'justify'
});
The output looks like this:
@ -143,12 +152,12 @@ The options given to the first `text` call are also retained for subsequent call
`continued` one, but of course you can override them. In the following example, the `width`
option from the first `text` call is retained by the second call.
doc.fillColor 'green'
.text lorem.slice(0, 500),
width: 465
continued: yes
.fillColor 'red'
.text lorem.slice(500)
doc.fillColor('green')
.text(lorem.slice(0, 500), {
width: 465,
continued: true
}).fillColor('red')
.text(lorem.slice(500));
Here is the output:
@ -187,22 +196,22 @@ to be extracted from the collection.
Here is an example showing how to set the font in each case.
# Set the font size
doc.fontSize(18)
// Set the font size
doc.fontSize(18);
# Using a standard PDF font
// Using a standard PDF font
doc.font('Times-Roman')
.text('Hello from Times Roman!')
.moveDown(0.5)
.moveDown(0.5);
# Using a TrueType font (.ttf)
// Using a TrueType font (.ttf)
doc.font('fonts/GoodDog.ttf')
.text('This is Good Dog!')
.moveDown(0.5)
.moveDown(0.5);
# Using a collection font (.ttc or .dfont)
// Using a collection font (.ttc or .dfont)
doc.font('fonts/Chalkboard.ttc', 'Chalkboard-Bold')
.text('This is Chalkboard, not Comic Sans.')
.text('This is Chalkboard, not Comic Sans.');
The output of this example looks like this:
@ -212,12 +221,12 @@ Another nice feature of the PDFKit font support, is the ability to register a
font file under a name for use later rather than entering the path to the font
every time you want to use it.
# Register a font
doc.registerFont('Heading Font', 'fonts/Chalkboard.ttc', 'Chalkboard-Bold')
// Register a font
doc.registerFont('Heading Font', 'fonts/Chalkboard.ttc', 'Chalkboard-Bold');
# Use the font later
// Use the font later
doc.font('Heading Font')
.text('This is a heading.')
.text('This is a heading.');
That's about all there is too it for text in PDFKit. Let's move on now to
images.

View File

@ -18,12 +18,12 @@ and `quadraticCurveTo` all draw from the current point (which you can set with
curves use two control points and quadratic curves use just one. Here is an
example that illustrates defining a path.
doc.moveTo(0, 20) # set the current point
.lineTo(100, 160) # draw a line
.quadraticCurveTo(130, 200, 150, 120) # draw a quadratic curve
.bezierCurveTo(190, -40, 200, 200, 300, 150) # draw a bezier curve
.lineTo(400, 90) # draw another line
.stroke() # stroke the path
doc.moveTo(0, 20) // set the current point
.lineTo(100, 160) // draw a line
.quadraticCurveTo(130, 200, 150, 120) // draw a quadratic curve
.bezierCurveTo(190, -40, 200, 200, 300, 150) // draw a bezier curve
.lineTo(400, 90) // draw another line
.stroke(); // stroke the path
The output of this example looks like this:
@ -67,8 +67,8 @@ pairs), and it will create the shape by moving to the first point, and then
drawing lines to each consecutive point. Here is how you'd draw a triangle
with the polygon helper.
doc.polygon [100, 0], [50, 100], [150, 100]
doc.stroke()
doc.polygon([100, 0], [50, 100], [150, 100]);
doc.stroke();
The output of this example looks like this:
@ -104,38 +104,38 @@ Some of these are pretty self explanatory, but let's go through a few of them.
The `lineCap` and `lineJoin` properties accept constants describing what they
should do. This is best illustrated by an example.
# these examples are easier to see with a large line width
doc.lineWidth(25)
// these examples are easier to see with a large line width
doc.lineWidth(25);
# line cap settings
// line cap settings
doc.lineCap('butt')
.moveTo(50, 20)
.lineTo(100, 20)
.stroke()
.stroke();
doc.lineCap('round')
.moveTo(150, 20)
.lineTo(200, 20)
.stroke()
.stroke();
# square line cap shown with a circle instead of a line so you can see it
// square line cap shown with a circle instead of a line so you can see it
doc.lineCap('square')
.moveTo(250, 20)
.circle(275, 30, 15)
.stroke()
.stroke();
# line join settings
// line join settings
doc.lineJoin('miter')
.rect(50, 100, 50, 50)
.stroke()
.stroke();
doc.lineJoin('round')
.rect(150, 100, 50, 50)
.stroke()
.stroke();
doc.lineJoin('bevel')
.rect(250, 100, 50, 50)
.stroke()
.stroke();
The output of this example looks like this.
@ -156,8 +156,8 @@ The following example draws a circle with a dashed line where the space
between the dashes is double the length of each dash.
doc.circle(100, 50, 50)
.dash(5, space: 10)
.stroke()
.dash(5, {space: 10})
.stroke();
The output of this example looks like this:
@ -205,21 +205,21 @@ fillColor method), and an optional opacity.
You can see both linear and radial gradients in the following example:
# Create a linear gradient
grad = doc.linearGradient(50, 0, 150, 100)
// Create a linear gradient
let grad = doc.linearGradient(50, 0, 150, 100);
grad.stop(0, 'green')
.stop(1, 'red')
.stop(1, 'red');
doc.rect 50, 0, 100, 100
doc.fill grad
doc.rect(50, 0, 100, 100);
doc.fill(grad);
# Create a radial gradient
grad = doc.radialGradient(300, 50, 0, 300, 50, 50)
// Create a radial gradient
grad = doc.radialGradient(300, 50, 0, 300, 50, 50);
grad.stop(0, 'orange', 0)
.stop(1, 'orange', 1)
.stop(1, 'orange', 1);
doc.circle 300, 50, 50
doc.fill grad
doc.circle(300, 50, 50);
doc.fill(grad);
Here is the output from the this example:
@ -232,19 +232,19 @@ example. The winding rule is an optional attribute to the `fill` and
`fillAndStroke` methods, and there are two values to choose from: `non-zero`
and `even-odd`.
# Initial setup
// Initial setup
doc.fillColor('red')
.translate(-100, -50)
.scale(0.8)
.scale(0.8);
# Draw the path with the non-zero winding rule
// Draw the path with the non-zero winding rule
doc.path('M 250,75 L 323,301 131,161 369,161 177,301 z')
.fill('non-zero')
.fill('non-zero');
# Draw the path with the even-odd winding rule
// Draw the path with the even-odd winding rule
doc.translate(280, 0)
.path('M 250,75 L 323,301 131,161 369,161 177,301 z')
.fill('even-odd')
.fill('even-odd');
You'll notice that I used the `scale` and `translate` transformations in this
example. We'll cover those in a minute. The output of this example, with some
@ -291,9 +291,9 @@ We used the `scale` and `translate` transformations above, so here is an
example of using the `rotate` transformation. We'll set the origin of the
rotation to the center of the rectangle.
doc.rotate(20, origin: [150, 70])
doc.rotate(20, {origin: [150, 70]})
.rect(100, 20, 100, 100)
.fill('gray')
.fill('gray');
This example produces the following effect.
@ -307,16 +307,18 @@ parts of the drawing. Everything falling inside the clipping path after it is
created is visible, and everything outside the path is invisible. Here is an
example that clips a checkerboard pattern to the shape of a circle.
# Create a clipping path
// Create a clipping path
doc.circle(100, 100, 100)
.clip()
.clip();
# Draw a checkerboard pattern
for row in [0...10]
for col in [0...10]
color = if (col % 2) - (row % 2) then '#eee' else '#4183C4'
// Draw a checkerboard pattern
for (let row = 0; row < 10; row++) {
for (let col = 0; col < 10; col++) {
const color = (col % 2) - (row % 2) ? '#eee' : '#4183C4';
doc.rect(row * 20, col * 20, 20, 20)
.fill(color)
.fill(color);
}
}
The result of this example is the following: