Skip to content

Commit

Permalink
Merge pull request #27 from Cherry/feat/text-wrapping
Browse files Browse the repository at this point in the history
  • Loading branch information
Cherry authored Dec 9, 2023
2 parents 731e58a + f550cde commit 96c99c2
Show file tree
Hide file tree
Showing 11 changed files with 305 additions and 124 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@ jobs:
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
# Override language selection by uncommenting this and choosing your languages
# with:
# languages: go, javascript, csharp, python, cpp, java

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
uses: github/codeql-action/autobuild@v2

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
Expand All @@ -48,4 +48,4 @@ jobs:
# make release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2
7 changes: 0 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@
"publish:prod": "wrangler deploy --env production --verbose",
"publish:staging": "wrangler deploy --env staging --verbose",
"start:dev": "wrangler dev",
"test": "vitest"
"test": "vitest run",
"test:watch": "vitest watch"
},
"devDependencies": {
"@adaptivelink/pops": "0.5.7",
"@cloudflare/kv-asset-handler": "0.3.0",
"@cloudflare/workers-types": "4.20231121.0",
"@cloudfour/simple-svg-placeholder": "1.1.0",
"@nodecraft/eslint-config": "31.0.1",
"@types/sanitize-html": "2.9.5",
"@typescript-eslint/eslint-plugin": "6.13.2",
Expand Down
3 changes: 3 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ <h3>Available API Options</h3>

<dt><code>textColor</code></dt>
<dd>Color of the text. For transparency, use an <code>rgba</code> or <code>hsla</code> value. Defaults to <code>rgba(0,0,0,0.5)</code></dd>

<dt><code>textwrap</code></dt>
<dd>Wrap text to fit within the image (to best ability). Will not alter font size, so especially long string may still appear outside of the image. Defaults to <code>false</code></dd>
</dl>

<h4>Example URL</h4>
Expand Down
75 changes: 63 additions & 12 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
} from 'vitest';
import { unstable_dev } from 'wrangler';

import { getKeys } from './utils';

import type { UnstableDevWorker } from 'wrangler';

describe('Worker', () => {
Expand Down Expand Up @@ -43,32 +45,81 @@ describe('Worker', () => {
expect(resp.status).toBe(200);

const text = await resp.text();
expect(text).toBe('<svg xmlns="http://www.w3.org/2000/svg" width="350" height="100" viewBox="0 0 350 100"> <rect fill="#ddd" width="350" height="100"/> <text fill="rgba(0,0,0,0.5)" font-family="sans-serif" font-size="20" dy="7" font-weight="bold" x="50%" y="50%" text-anchor="middle">Hello World</text> </svg>');
expect(text).toBe('<svg xmlns="http://www.w3.org/2000/svg" width="350" height="100" viewBox="0 0 350 100"><rect fill="#ddd" width="350" height="100"/><text fill="rgba(0,0,0,0.5)" font-family="sans-serif" font-size="20" dy="7" font-weight="bold" x="50%" y="50%" text-anchor="middle">Hello World</text></svg>');
});

test.each([
// basic tests
[
{
width: 350,
height: 100,
},
'<svg xmlns="http://www.w3.org/2000/svg" width="350" height="100" viewBox="0 0 350 100"><rect fill="#ddd" width="350" height="100"/><text fill="rgba(0,0,0,0.5)" font-family="sans-serif" font-size="20" dy="7" font-weight="bold" x="50%" y="50%" text-anchor="middle">350×100</text></svg>',
],
[
{
width: 200,
height: 100,
bgColor: '#000',
textColor: 'rgba(255,255,255,0.5)',
},
'<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100" viewBox="0 0 200 100"><rect fill="#000" width="200" height="100"/><text fill="rgba(255,255,255,0.5)" font-family="sans-serif" font-size="20" dy="7" font-weight="bold" x="50%" y="50%" text-anchor="middle">200×100</text></svg>',
],
[
'?width=350&height=100',
'<svg xmlns="http://www.w3.org/2000/svg" width="350" height="100" viewBox="0 0 350 100"> <rect fill="#ddd" width="350" height="100"/> <text fill="rgba(0,0,0,0.5)" font-family="sans-serif" font-size="20" dy="7" font-weight="bold" x="50%" y="50%" text-anchor="middle">350×100</text> </svg>',
{
width: 140,
height: 100,
bgColor: '#313131',
textColor: '#dfdfde',
},
'<svg xmlns="http://www.w3.org/2000/svg" width="140" height="100" viewBox="0 0 140 100"><rect fill="#313131" width="140" height="100"/><text fill="#dfdfde" font-family="sans-serif" font-size="20" dy="7" font-weight="bold" x="50%" y="50%" text-anchor="middle">140×100</text></svg>',
],
[
'?width=200&height=100&bgColor=%23000&textColor=rgba(255,255,255,0.5)',
'<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100" viewBox="0 0 200 100"> <rect fill="#000" width="200" height="100"/> <text fill="rgba(255,255,255,0.5)" font-family="sans-serif" font-size="20" dy="7" font-weight="bold" x="50%" y="50%" text-anchor="middle">200×100</text> </svg>',
{
width: 350,
height: 100,
text: 'placeholders.dev',
},
'<svg xmlns="http://www.w3.org/2000/svg" width="350" height="100" viewBox="0 0 350 100"><rect fill="#ddd" width="350" height="100"/><text fill="rgba(0,0,0,0.5)" font-family="sans-serif" font-size="20" dy="7" font-weight="bold" x="50%" y="50%" text-anchor="middle">placeholders.dev</text></svg>',
],
[
'?width=140&height=100&bgColor=%23313131&textColor=%23dfdfde',
'<svg xmlns="http://www.w3.org/2000/svg" width="140" height="100" viewBox="0 0 140 100"> <rect fill="#313131" width="140" height="100"/> <text fill="#dfdfde" font-family="sans-serif" font-size="20" dy="7" font-weight="bold" x="50%" y="50%" text-anchor="middle">140×100</text> </svg>',
{
width: 1055,
height: 100,
text: 'Hello World',
bgColor: '#434343',
textColor: '#dfdfde',
},
'<svg xmlns="http://www.w3.org/2000/svg" width="1055" height="100" viewBox="0 0 1055 100"><rect fill="#434343" width="1055" height="100"/><text fill="#dfdfde" font-family="sans-serif" font-size="20" dy="7" font-weight="bold" x="50%" y="50%" text-anchor="middle">Hello World</text></svg>',
],
// text wrapping
[
'?width=350&height=100&text=placeholders.dev',
'<svg xmlns="http://www.w3.org/2000/svg" width="350" height="100" viewBox="0 0 350 100"> <rect fill="#ddd" width="350" height="100"/> <text fill="rgba(0,0,0,0.5)" font-family="sans-serif" font-size="20" dy="7" font-weight="bold" x="50%" y="50%" text-anchor="middle">placeholders.dev</text> </svg>',
{
width: 250,
height: 200,
text: 'This text is too long',
bgColor: '#f7f6f6',
textWrap: false,
},
'<svg xmlns="http://www.w3.org/2000/svg" width="250" height="200" viewBox="0 0 250 200"><rect fill="#f7f6f6" width="250" height="200"/><text fill="rgba(0,0,0,0.5)" font-family="sans-serif" font-size="40" dy="14" font-weight="bold" x="50%" y="50%" text-anchor="middle">This text is too long</text></svg>',
],
[
'?width=1055&height=100&text=Hello%20World&bgColor=%23434343&textColor=%23dfdfde',
'<svg xmlns="http://www.w3.org/2000/svg" width="1055" height="100" viewBox="0 0 1055 100"> <rect fill="#434343" width="1055" height="100"/> <text fill="#dfdfde" font-family="sans-serif" font-size="20" dy="7" font-weight="bold" x="50%" y="50%" text-anchor="middle">Hello World</text> </svg>',
{
width: 250,
height: 200,
text: 'This text is too long',
bgColor: '#f7f6f6',
textWrap: true,
},
'<svg xmlns="http://www.w3.org/2000/svg" width="250" height="200" viewBox="0 0 250 200"><rect fill="#f7f6f6" width="250" height="200"/><foreignObject width="250" height="200"><div xmlns="http://www.w3.org/1999/xhtml" style="align-items: center;box-sizing: border-box;color: rgba(0,0,0,0.5);display: flex;font-family: sans-serif;font-size: 40px;font-weight: bold;height: 100%;line-height: 1.2;justify-content: center;padding: 0.5em;text-align: center;width: 100%;">This text is too long</div> </foreignObject></svg>',
],
])('should return accurate svg image with query params %s', async (query, expected) => {
const req = new Request(`https://example.com/api/${query}`, { method: 'GET' });
const searchParams = new URLSearchParams();
for (const key of getKeys(query)) {
searchParams.set(key, String(query[key]));
}
const req = new Request(`https://example.com/api/?${searchParams.toString()}`, { method: 'GET' });
const resp = await worker.fetch(req.url);
expect(resp.status).toBe(200);

Expand Down
9 changes: 6 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { getAssetFromKV } from '@cloudflare/kv-asset-handler';
import generateSVG, { type Options } from '@cloudfour/simple-svg-placeholder';
import manifestJSON from '__STATIC_CONTENT_MANIFEST';

import { sanitizers } from './sanitizers';
import { type Options, simpleSvgPlaceholder } from './simple-svg-placeholder';
import { type Env } from './types';
import { addHeaders } from './utils';
import {
Expand All @@ -25,7 +25,10 @@ async function handleEvent(request: Request, env: Env, ctx: ExecutionContext) {
// when in dev, we serve from `/api`
if (url.host === 'images.placeholders.dev' || url.pathname.startsWith('/api')) {
// do our API work
let response = await cache.match(url, { ignoreMethod: true }); // try to find match for this request in the edge cache
let response;
if (url.host === 'images.placeholders.dev') {
response = await cache.match(url, { ignoreMethod: true }); // try to find match for this request in the edge cache
}
if (response) {
// use cache found on Cloudflare edge. Set X-Worker-Cache header for helpful debug
const newHdrs = new Headers(response.headers);
Expand Down Expand Up @@ -63,7 +66,7 @@ async function handleEvent(request: Request, env: Env, ctx: ExecutionContext) {
}
}
}
response = new Response(generateSVG(imageOptions), {
response = new Response(simpleSvgPlaceholder(imageOptions), {
headers: {
'content-type': 'image/svg+xml; charset=utf-8',
'access-control-allow-origin': '*',
Expand Down
Loading

0 comments on commit 96c99c2

Please sign in to comment.