Skip to content

Commit

Permalink
move font registration into _getFontSize method, init once
Browse files Browse the repository at this point in the history
  • Loading branch information
mdtanrikulu committed Dec 14, 2023
1 parent 6ee3637 commit 3d3705f
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 24 deletions.
Binary file removed src/assets/DejaVuSans-Bold.ttf
Binary file not shown.
28 changes: 28 additions & 0 deletions src/service/metadata.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import avaTest, { ExecutionContext, TestFn } from 'ava';
import { TestContext } from '../../mock/interface';
import { Metadata } from './metadata';
import { Version } from '../base';

const test = avaTest as TestFn<TestContext>;

test('should compute metadata correctly', async (t: ExecutionContext<TestContext>) => {
const nickMetadataObj = {
name: 'nick.eth',
description: 'nick.eth, an ENS name.',
created_date: 1571924851000,
tokenId: '0x5d5727cb0fb76e4944eafb88ec9a3cf0b3c9025a4b2f947729137c5d7f84f68f',
version: Version.v1,
last_request_date: Date.now()
};
const testMetadata = new Metadata(nickMetadataObj);

t.is(testMetadata.name, nickMetadataObj.name);
t.is(testMetadata.description, nickMetadataObj.description);
t.is(testMetadata.attributes[0].value, nickMetadataObj.created_date * 1000);
t.is(testMetadata.version, Version.v1);
});

test('should return correct font size', async (t: ExecutionContext<TestContext>) => {
const textSize = Metadata._getFontSize('nick.eth');
t.is(textSize, 32);
});
69 changes: 45 additions & 24 deletions src/service/metadata.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import {ens_normalize} from '@adraffy/ens-normalize';
import {
CanvasRenderingContext2D,
createCanvas,
registerFont
} from 'canvas';
import { Version } from '../base';
import {
CANVAS_FONT_PATH,
Expand All @@ -9,19 +14,13 @@ import base64EncodeUnicode from '../utils/base64encode';
import { isASCII, findCharacterSet } from '../utils/characterSet';
import { getCodePointLength, getSegmentLength } from '../utils/charLength';

// no ts declaration files
const { createCanvas, registerFont } = require('canvas');


try {
// registerFont(CANVAS_FONT_PATH, { family: 'Satoshi' });
registerFont(CANVAS_EMOJI_FONT_PATH, { family: 'Noto Color Emoji' });
} catch(error) {
console.warn("Font registeration is failed.");
console.warn(error);
interface Attribute {
trait_type: string,
display_type: string,
value: any
}


export interface MetadataInit {
name : string;
description? : string;
Expand All @@ -36,7 +35,7 @@ export interface MetadataInit {
export interface Metadata {
name : string;
description : string;
attributes : object[];
attributes : Attribute[];
name_length? : number;
segment_length? : number;
image : string;
Expand All @@ -51,20 +50,24 @@ export interface Metadata {

export class Metadata {
static MAX_CHAR = 60;
static ctx: CanvasRenderingContext2D;

constructor({
name,
description,
created_date,
tokenId,
version,
last_request_date
last_request_date,
}: MetadataInit) {
const label = this.getLabel(name);
this.is_normalized = this._checkNormalized(name);
this.name = this.formatName(name, tokenId);
this.description = this.formatDescription(name, description);
this.attributes = this.initializeAttributes(created_date, label);
this.url = this.is_normalized ? `https://app.ens.domains/name/${name}` : null;
this.url = this.is_normalized
? `https://app.ens.domains/name/${name}`
: null;
this.last_request_date = last_request_date;
this.version = version;
}
Expand All @@ -84,19 +87,23 @@ export class Metadata {

formatDescription(name: string, description?: string) {
const baseDescription = description || `${this.name}, an ENS name.`;
const normalizedNote = !this.is_normalized ? ` (${name} is not in normalized form)` : '';
const normalizedNote = !this.is_normalized
? ` (${name} is not in normalized form)`
: '';
const asciiWarning = this.generateAsciiWarning(this.getLabel(name));
return `${baseDescription}${normalizedNote}${asciiWarning}`;
}

generateAsciiWarning(label: string) {
if (!isASCII(label)) {
return ' ⚠️ ATTENTION: This name contains non-ASCII characters as shown above. ' +
return (
' ⚠️ ATTENTION: This name contains non-ASCII characters as shown above. ' +
'Please be aware that there are characters that look identical or very ' +
'similar to English letters, especially characters from Cyrillic and Greek. ' +
'Also, traditional Chinese characters can look identical or very similar to ' +
'simplified variants. For more information: ' +
'https://en.wikipedia.org/wiki/IDN_homograph_attack';
'https://en.wikipedia.org/wiki/IDN_homograph_attack'
);
}
return '';
}
Expand Down Expand Up @@ -129,7 +136,7 @@ export class Metadata {
];
}

addAttribute(attribute: object) {
addAttribute(attribute: Attribute) {
this.attributes.push(attribute);
}

Expand All @@ -152,7 +159,12 @@ export class Metadata {

const { domain, subdomainText } = this.processSubdomain(name, isSubdomain);
const { processedDomain, domainFontSize } = this.processDomain(domain);
const svg = this._generateByVersion(domainFontSize, subdomainText, isSubdomain, processedDomain);
const svg = this._generateByVersion(
domainFontSize,
subdomainText,
isSubdomain,
processedDomain
);

try {
this.setImage('data:image/svg+xml;base64,' + base64EncodeUnicode(svg));
Expand All @@ -165,7 +177,7 @@ export class Metadata {
processSubdomain(name: string, isSubdomain: boolean) {
let subdomainText;
let domain = name;

if (isSubdomain && !name.includes('...')) {
const labels = name.split('.');
let subdomain = labels.slice(0, labels.length - 2).join('.') + '.';
Expand Down Expand Up @@ -241,11 +253,20 @@ export class Metadata {
}

static _getFontSize(name: string): number {
const canvas = createCanvas(270, 270, 'svg');
const ctx = canvas.getContext('2d');
ctx.font =
'20px Satoshi, Noto Color Emoji, Apple Color Emoji, sans-serif';
const fontMetrics = ctx.measureText(name);
if (!this.ctx) {
try {
registerFont(CANVAS_FONT_PATH, { family: 'Satoshi' });
registerFont(CANVAS_EMOJI_FONT_PATH, { family: 'Noto Color Emoji' });
} catch (error) {
console.warn('Font registration is failed.');
console.warn(error);
}
const canvas = createCanvas(270, 270, 'svg');
this.ctx = canvas.getContext('2d');
this.ctx.font =
'20px Satoshi, Noto Color Emoji, Apple Color Emoji, sans-serif';
}
const fontMetrics = this.ctx.measureText(name);
const fontSize = Math.floor(20 * (200 / fontMetrics.width));
return fontSize < 34 ? fontSize : 32;
}
Expand Down

0 comments on commit 3d3705f

Please sign in to comment.