2023-11-25 11:56:14 +03:00
"use strict" ;
var _ _awaiter = ( this && this . _ _awaiter ) || function ( thisArg , _arguments , P , generator ) {
function adopt ( value ) { return value instanceof P ? value : new P ( function ( resolve ) { resolve ( value ) ; } ) ; }
return new ( P || ( P = Promise ) ) ( function ( resolve , reject ) {
function fulfilled ( value ) { try { step ( generator . next ( value ) ) ; } catch ( e ) { reject ( e ) ; } }
function rejected ( value ) { try { step ( generator [ "throw" ] ( value ) ) ; } catch ( e ) { reject ( e ) ; } }
function step ( result ) { result . done ? resolve ( result . value ) : adopt ( result . value ) . then ( fulfilled , rejected ) ; }
step ( ( generator = generator . apply ( thisArg , _arguments || [ ] ) ) . next ( ) ) ;
} ) ;
} ;
var _ _importDefault = ( this && this . _ _importDefault ) || function ( mod ) {
return ( mod && mod . _ _esModule ) ? mod : { "default" : mod } ;
} ;
Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
2023-12-07 22:56:11 +03:00
exports . parseSVG = exports . fetchSVGContent = exports . warpSvg = exports . getRandomEntityPath = exports . writeSVGToFile = exports . generateUniqueSVGPath = exports . createCharacterDirectory = exports . validateName = exports . numberOfFiles = exports . svgLinePathNames = exports . generateSvg = exports . printSVG = void 0 ;
2023-11-25 11:56:14 +03:00
const fs _1 = _ _importDefault ( require ( "fs" ) ) ;
const paths _1 = require ( "../paths" ) ;
const jsdom _1 = _ _importDefault ( require ( "jsdom" ) ) ;
/ * *
* Returns the number of files in a directory .
* @ param dir - The directory path .
* @ returns A promise that resolves to the number of files in the directory .
* /
const numberOfFiles = ( dir ) => _ _awaiter ( void 0 , void 0 , void 0 , function * ( ) {
try {
const files = yield fs _1 . default . promises . readdir ( dir ) ;
return files . length ;
}
catch ( err ) {
// File is not found
return 0 ;
}
} ) ;
exports . numberOfFiles = numberOfFiles ;
/ * *
* Returns a string with a valid name based on the input string .
* Replaces invalid characters with their corresponding names or "lower-" / "upper-" prefix .
* @ param name - The input string to be validated .
* @ returns A string with a valid name .
* /
const validateName = ( name ) => {
const map = {
"?" : "questionMark" ,
"*" : "asterisk" ,
"/" : "slash" ,
"\\" : "backslash" ,
":" : "colon" ,
"|" : "pipe" ,
"<" : "lessThan" ,
">" : "greaterThan" ,
'"' : "doubleQuote" ,
"'" : "singleQuote" ,
"@" : "at" ,
"#" : "hash" ,
$ : "dollar" ,
"%" : "percent" ,
"^" : "caret" ,
"&" : "ampersand" ,
"(" : "leftParenthesis" ,
")" : "rightParenthesis" ,
"-" : "hyphen" ,
_ : "underscore" ,
"=" : "equal" ,
"+" : "plus" ,
"{" : "leftCurlyBrace" ,
"}" : "rightCurlyBrace" ,
"[" : "leftSquareBracket" ,
"]" : "rightSquareBracket" ,
"," : "comma" ,
"." : "period" ,
"!" : "exclamationMark" ,
"~" : "tilde" ,
"`" : "graveAccent" ,
} ;
const numbers = {
"0" : "zero" ,
"1" : "one" ,
"2" : "two" ,
"3" : "three" ,
"4" : "four" ,
"5" : "five" ,
"6" : "six" ,
"7" : "seven" ,
"8" : "eight" ,
"9" : "nine" ,
} ;
if ( name in map )
return map [ name ] ;
if ( name in numbers )
return numbers [ name ] ;
// distingush between upper and lower case
if ( isUpperCase ( name ) )
return ` upper- ${ name } ` ;
return ` lower- ${ name } ` ;
} ;
exports . validateName = validateName ;
const isUpperCase = ( char ) => {
return char === char . toUpperCase ( ) ;
} ;
/ * *
* Returns a random entity path for a given user and character name .
* @ param userName - The name of the user .
* @ param charName - The title of the character .
* @ returns A promise that resolves to a string representing the path to the random entity or empty .
* /
2023-12-07 22:56:11 +03:00
const getRandomEntityPath = ( username , charName ) => _ _awaiter ( void 0 , void 0 , void 0 , function * ( ) {
2023-11-25 11:56:14 +03:00
try {
2023-12-07 22:56:11 +03:00
const basePath = ` ${ paths _1 . PROFILES _PATH } / ${ username } / ${ charName } ` ;
2023-11-25 11:56:14 +03:00
const characters = yield fs _1 . default . promises . readdir ( basePath ) ;
const randomIndex = Math . floor ( Math . random ( ) * characters . length ) ;
return ` ${ basePath } / ${ characters [ randomIndex ] } ` ;
}
catch ( err ) {
console . error ( "Could not get random entity path" ) ;
return "" ;
}
} ) ;
2023-12-07 22:56:11 +03:00
exports . getRandomEntityPath = getRandomEntityPath ;
2023-11-25 11:56:14 +03:00
/ * *
* Checks if a given character path contains any special characters .
* Special characters include : questionMark , asterisk , slash , backslash , colon , pipe , lessThan , greaterThan ,
* doubleQuote , singleQuote , at , hash , dollar , percent , caret , ampersand , leftParenthesis , rightParenthesis ,
* hyphen , underscore , equal , plus , leftCurlyBrace , rightCurlyBrace , leftSquareBracket , rightSquareBracket ,
* comma , period , exclamationMark , tilde , graveAccent .
*
* @ param charPath - The character path to check .
* @ returns True if the character path contains any special characters , false otherwise .
* /
const isSpecialChar = ( charPath ) => {
const specialLocatedTop = [
"singleQuote" ,
"doubleQuote" ,
"graveAccent" ,
"asterisk" ,
"caret" ,
] ;
const specialLocatedMiddle = [
"colon" ,
"lessThan" ,
"greaterThan" ,
"leftParenthesis" ,
"rightParenthesis" ,
"hyphen" ,
"equal" ,
"plus" ,
"leftCurlyBrace" ,
"rightCurlyBrace" ,
"leftSquareBracket" ,
"rightSquareBracket" ,
"exclamationMark" ,
"tilde" ,
] ;
2023-12-07 22:56:11 +03:00
const specialLocatedBottom = [
"underscore" ,
"questionMark" ,
"slash" ,
"backslash" ,
"pipe" ,
"exclamationMark" ,
"comma" ,
"period" ,
] ;
2023-11-25 11:56:14 +03:00
let isSpecial = false ;
let position = "bottom" ;
for ( const special of specialLocatedTop ) {
if ( charPath . includes ( special ) ) {
isSpecial = true ;
position = "top" ;
break ;
}
}
if ( ! isSpecial ) {
for ( const special of specialLocatedMiddle ) {
if ( charPath . includes ( special ) ) {
isSpecial = true ;
position = "middle" ;
break ;
}
}
}
if ( ! isSpecial ) {
for ( const special of specialLocatedBottom ) {
if ( charPath . includes ( special ) ) {
isSpecial = true ;
position = "bottom" ;
break ;
}
}
}
return { isSpecial , position } ;
} ;
2023-12-07 22:56:11 +03:00
const specialWidthGlyphs = ( glyphPath ) => {
const symbols = {
colon : {
width : 5 ,
maxWidth : 7 ,
height : 15 ,
maxHeight : 20 ,
} ,
lessThan : {
width : 15 ,
height : 20 ,
maxWidth : 25 ,
maxHeight : 30 ,
} ,
greaterThan : {
width : 15 ,
height : 20 ,
maxWidth : 25 ,
maxHeight : 30 ,
} ,
leftParenthesis : {
width : 8 ,
height : 20 ,
maxWidth : 16 ,
maxHeight : 40 ,
} ,
rightParenthesis : {
width : 8 ,
height : 20 ,
maxWidth : 16 ,
maxHeight : 40 ,
} ,
hyphen : {
width : 10 ,
height : 2 ,
maxWidth : 20 ,
maxHeight : 4 ,
} ,
equal : {
width : 10 ,
height : 5 ,
maxWidth : 20 ,
maxHeight : 10 ,
} ,
plus : {
width : 10 ,
height : 10 ,
maxWidth : 20 ,
maxHeight : 20 ,
} ,
leftCurlyBrace : {
width : 12 ,
height : 25 ,
maxWidth : 24 ,
maxHeight : 50 ,
} ,
rightCurlyBrace : {
width : 12 ,
height : 25 ,
maxWidth : 24 ,
maxHeight : 50 ,
} ,
leftSquareBracket : {
width : 8 ,
height : 20 ,
maxWidth : 16 ,
maxHeight : 40 ,
} ,
rightSquareBracket : {
width : 8 ,
height : 20 ,
maxWidth : 16 ,
maxHeight : 40 ,
} ,
exclamationMark : {
width : 6 ,
height : 30 ,
maxWidth : 9 ,
maxHeight : 30 ,
} ,
tilde : {
width : 20 ,
height : 8 ,
maxWidth : 30 ,
maxHeight : 10 ,
} ,
comma : {
width : 5 ,
height : 10 ,
maxWidth : 10 ,
maxHeight : 20 ,
} ,
dot : {
width : 5 ,
height : 5 ,
maxWidth : 10 ,
maxHeight : 10 ,
} ,
questionMark : {
width : 10 ,
height : 30 ,
maxWidth : 20 ,
maxHeight : 40 ,
} ,
underscore : {
width : 10 ,
height : 2 ,
maxWidth : 20 ,
maxHeight : 4 ,
} ,
pipe : {
width : 5 ,
height : 30 ,
maxWidth : 10 ,
maxHeight : 40 ,
} ,
one : {
width : 5 ,
height : 30 ,
maxWidth : 10 ,
maxHeight : 40 ,
} ,
"lower-m" : {
width : 20 ,
height : 30 ,
maxWidth : 30 ,
maxHeight : 40 ,
} ,
"lower-q" : {
width : 20 ,
height : 30 ,
maxWidth : 30 ,
maxHeight : 40 ,
} ,
"lower-y" : {
width : 20 ,
height : 30 ,
maxWidth : 30 ,
maxHeight : 40 ,
} ,
"lower-g" : {
width : 20 ,
height : 30 ,
maxWidth : 30 ,
maxHeight : 40 ,
} ,
"lower-p" : {
width : 20 ,
height : 30 ,
maxWidth : 30 ,
maxHeight : 40 ,
} ,
"lower-j" : {
width : 20 ,
height : 30 ,
maxWidth : 30 ,
maxHeight : 40 ,
} ,
"lower-i" : {
width : 5 ,
height : 30 ,
maxWidth : 10 ,
maxHeight : 40 ,
} ,
"lower-l" : {
width : 10 ,
height : 40 ,
maxWidth : 10 ,
maxHeight : 40 ,
} ,
} ;
let isSpecialGlyph = false ;
let values = {
width : 20 ,
height : 30 ,
maxWidth : 30 ,
maxHeight : 40 ,
} ;
for ( const symbol in symbols ) {
if ( glyphPath . includes ( symbol ) ) {
isSpecialGlyph = true ;
values = symbols [ symbol ] ;
break ;
}
}
return { isSpecialGlyph , values } ;
} ;
2023-11-25 11:56:14 +03:00
/ * *
* Determines if the given character path should extend below the baseline .
* @ param charPath The character path to check .
* @ returns A boolean indicating whether the character path should extend below the baseline .
* /
const extendBelowBaseline = ( charPath ) => {
const extendBelowBaseline = [
"lower-q" ,
"lower-y" ,
"lower-g" ,
"lower-p" ,
"lower-j" ,
] ;
let extend = false ;
for ( const char of extendBelowBaseline ) {
if ( charPath . includes ( char ) ) {
extend = true ;
break ;
}
}
return extend ;
} ;
/ * *
* Returns an object containing an array of SVG paths for each word in the input text and an array of missing characters .
* @ param userName - The name of the user .
* @ param text - The input text to generate SVG paths for .
* @ returns An object containing an array of SVG paths for each word in the input text and an array of missing characters .
* /
const svgLinePathNames = ( userName , text ) => _ _awaiter ( void 0 , void 0 , void 0 , function * ( ) {
let paths = [ ] ;
let missing = [ ] ;
const words = text . split ( " " ) ;
for ( const word of words ) {
let wordPath = [ ] ;
const chars = word . trim ( ) . split ( "" ) ;
for ( const c of chars ) {
const cName = validateName ( c ) ;
const path = yield getRandomEntityPath ( userName , cName ) ;
if ( path === "" ) {
missing . push ( c ) ;
}
else {
wordPath . push ( path ) ;
}
}
paths . push ( wordPath ) ;
}
return {
missing ,
paths ,
} ;
} ) ;
exports . svgLinePathNames = svgLinePathNames ;
/ * *
* Parses an SVG string and returns the SVG element and its paths .
* @ param svg - The SVG string to parse .
* @ returns An object containing the SVG element and its paths .
* /
const parseSVG = ( svg ) => {
2023-12-07 22:56:11 +03:00
const dom = new jsdom _1 . default . JSDOM ( svg , { contentType : "image/svg+xml" } ) ;
const svgElement = dom . window . document . querySelector ( "g" ) ;
2023-11-25 11:56:14 +03:00
return {
parent : svgElement ,
} ;
} ;
2023-12-07 22:56:11 +03:00
exports . parseSVG = parseSVG ;
2023-11-25 11:56:14 +03:00
/ * *
* Returns a random number between the given minimum and maximum values , with an optional percentage range .
* @ param min The minimum value for the random number .
* @ param max The maximum value for the random number .
* @ param percentage The percentage range for the random number . Defaults to 25 % .
* @ returns A random number between the given minimum and maximum values .
* /
const getRandomNumber = ( min , max , percentage = 25 , scale = 1 ) => {
const howRandom = Math . round ( ( max - min ) * ( percentage / 100 ) ) ;
const randomNumber = Math . floor ( Math . random ( ) * ( howRandom + 1 ) ) ;
return Math . round ( min + randomNumber ) * scale ;
} ;
// Get standard values for the characters
const getStandardValues = ( isSpecial , position ) => {
// Standard values for the characters
const standard = {
char _width : 20 ,
2023-12-07 22:56:11 +03:00
char _height : 30 ,
2023-11-25 11:56:14 +03:00
space _width : 10 ,
special _char _located _top _width : 5 ,
special _char _located _middle _width : 15 ,
special _char _located _top _max _width : 10 ,
special _char _located _middle _max _width : 20 ,
special _char _located _bottom _width : 5 ,
2023-12-07 22:56:11 +03:00
special _char _located _bottom _max _width : 10 ,
2023-11-25 11:56:14 +03:00
special _char _height _top : 10 ,
special _char _height _middle : 20 ,
special _char _height _bottom : 30 ,
max _char _width : 30 ,
2023-12-07 22:56:11 +03:00
max _char _height : 40 ,
2023-11-25 11:56:14 +03:00
} ;
const standerdWidth = isSpecial
? position === "top"
? standard . special _char _located _top _width
: position === "middle"
? standard . special _char _located _middle _width
: standard . special _char _located _bottom _width
: standard . char _width ;
const standerdMaxWidth = isSpecial
? position === "top"
? standard . special _char _located _top _max _width
: position === "middle"
? standard . special _char _located _middle _max _width
: standard . special _char _located _bottom _max _width
: standard . max _char _width ;
const standerdHeight = isSpecial
? position === "top"
? standard . special _char _height _top
: position === "middle"
? standard . special _char _height _middle
: standard . special _char _height _bottom
2023-12-07 22:56:11 +03:00
: standard . char _height ;
2023-11-25 11:56:14 +03:00
const standerdMaxHeight = isSpecial
? position === "top"
? standard . special _char _height _top
: position === "middle"
? standard . special _char _height _middle
: standard . special _char _height _bottom
: standard . max _char _height ;
return { standerdWidth , standerdMaxWidth , standerdHeight , standerdMaxHeight } ;
} ;
// Get Random Defects
const getRandomDefects = ( defects , scaleFactor , charPath = "" ) => {
const { baseline , kerning , letterSize , lineSpacing , indent } = defects ;
2023-12-07 22:56:11 +03:00
const { isSpecialGlyph , values } = specialWidthGlyphs ( charPath ) ;
if ( isSpecialGlyph ) {
const { width , height , maxWidth , maxHeight } = values ;
const letterSizeWidthRandom = getRandomNumber ( width , maxWidth , letterSize , scaleFactor ) ;
const letterSizeRandomHeight = getRandomNumber ( height , maxHeight , letterSize , scaleFactor ) ;
return {
indentRandom : 0 ,
lineSpacingRandom : 0 ,
kerningDeffects : 0 ,
baselineOffset : 0 ,
letterSizeWidthRandom ,
letterSizeRandomHeight ,
} ;
}
2023-11-25 11:56:14 +03:00
const { isSpecial , position } = isSpecialChar ( charPath ) ;
const { standerdWidth , standerdMaxWidth , standerdHeight , standerdMaxHeight } = getStandardValues ( isSpecial , position ) ;
const indentRandom = getRandomNumber ( 0 , 80 , indent , scaleFactor ) ;
const lineSpacingRandom = getRandomNumber ( 0 , 30 , lineSpacing , scaleFactor ) ;
2023-12-07 22:56:11 +03:00
const kerningDeffects = getRandomNumber ( 5 , - 5 , kerning , scaleFactor ) ;
2023-11-25 11:56:14 +03:00
const baselineOffset = getRandomNumber ( 0 , 10 , baseline , scaleFactor ) ;
const letterSizeWidthRandom = getRandomNumber ( standerdWidth , standerdMaxWidth , letterSize , scaleFactor ) ;
const letterSizeRandomHeight = getRandomNumber ( standerdHeight , standerdMaxHeight , letterSize , scaleFactor ) ;
return {
indentRandom ,
lineSpacingRandom ,
kerningDeffects ,
baselineOffset ,
letterSizeWidthRandom ,
letterSizeRandomHeight ,
} ;
} ;
2023-12-07 22:56:11 +03:00
const fetchSVGContent = ( path ) => {
return fs _1 . default . readFileSync ( path , "utf-8" ) ;
} ;
exports . fetchSVGContent = fetchSVGContent ;
2023-11-25 11:56:14 +03:00
/ * *
* Assembles a word by processing each character and generating SVG elements .
*
* @ param { AssembleWord } options - The options for assembling the word .
* @ param { string } options . word - The word to assemble .
* @ param { number } options . offsetX - The initial X offset .
* @ param { number } options . offsetY - The initial Y offset .
* @ param { number } options . scaleFactor - The scale factor for the word .
* @ param { number } options . indentRandom - The random indentation for the word .
* @ param { Defects } options . defects - The defects for the word .
*
* @ returns { Object } - The assembled word elements , the height of the word , and the updated X offset .
* /
const assembleWord = ( { word , offsetX , offsetY , scaleFactor , indentRandom , defects , } ) => {
2023-12-07 22:56:11 +03:00
const space _width = 30 ;
2023-11-25 11:56:14 +03:00
let wordElements = [ ] ;
let wordHeight = 0 ;
if ( word . length === 0 ) {
offsetX += space _width ;
}
else {
offsetX += indentRandom ;
for ( let j = 0 ; j < word . length ; j ++ ) {
const char = word [ j ] ;
2023-12-07 22:56:11 +03:00
const { kerningDeffects } = getRandomDefects ( defects , scaleFactor ) ;
2023-11-25 11:56:14 +03:00
const { isSpecial , position } = isSpecialChar ( char ) ;
const { letterSizeWidthRandom , letterSizeRandomHeight } = getRandomDefects ( defects , scaleFactor , char ) ;
// You need to load the SVG content from the file
2023-12-07 22:56:11 +03:00
const svgFileContent = fetchSVGContent ( char ) ;
2023-11-25 11:56:14 +03:00
// Get the width and height of the SVG and its paths children
const { parent } = parseSVG ( svgFileContent ) ;
const width = parent === null || parent === void 0 ? void 0 : parent . getAttribute ( "width" ) ;
const height = parent === null || parent === void 0 ? void 0 : parent . getAttribute ( "height" ) ;
// Scale down the width to the standerd width while keeping the aspect ratio
2023-12-07 22:56:11 +03:00
// const widthScale = letterSizeWidthRandom / Number(width);
// const heightScale = letterSizeRandomHeight / Number(height);
2023-11-25 11:56:14 +03:00
// Calculate the scaled width and height
2023-12-07 22:56:11 +03:00
// const scale = Math.pow(
// Math.min(widthScale, heightScale),
// 1 / scaleFactor
// );
const scale = scaleFactor ;
const scaledWidth = Number ( width ) * scale ;
const scaledHeight = Number ( height ) * scale ;
2023-11-25 11:56:14 +03:00
// Change the width and height of the SVG
parent === null || parent === void 0 ? void 0 : parent . setAttribute ( "width" , String ( scaledWidth ) ) ;
parent === null || parent === void 0 ? void 0 : parent . setAttribute ( "height" , String ( scaledHeight ) ) ;
2023-12-07 22:56:11 +03:00
// Add translation and scale to the SVG content
parent === null || parent === void 0 ? void 0 : parent . setAttribute ( "transform" , ` translate( ${ offsetX } , ${ offsetY } ) scale( ${ scale } ) ` ) ;
2023-11-25 11:56:14 +03:00
// Add the SVG content to the SVG content variable
offsetX += scaledWidth + kerningDeffects ;
wordElements . push ( {
element : parent ,
isSpecial ,
position ,
extendBelowBaseline : extendBelowBaseline ( char ) ,
} ) ;
2023-12-07 22:56:11 +03:00
wordHeight = Math . max ( wordHeight , scaledHeight ) ;
2023-11-25 11:56:14 +03:00
}
// Add a space between words
offsetX += space _width * scaleFactor ;
}
return { wordElements , wordHeight , offsetX } ;
} ;
/ * *
* Assembles a line of text into SVG elements .
*
* @ param { AssembleLine } options - The options for assembling the line .
* @ param { number } options . defects - The number of defects in the line .
* @ param { number } options . scaleFactor - The scale factor for the line .
* @ param { string [ ] } options . line - The words in the line .
* @ param { number } options . offsetY - The vertical offset of the line .
* @ returns { Object } - The assembled line content and updated vertical offset .
* /
const assembleLine = ( { defects , scaleFactor , line , offsetY , } ) => {
const { indentRandom , lineSpacingRandom } = getRandomDefects ( defects , scaleFactor ) ;
let lineContent = "" ;
// Add a line container for each line of text
let lineHeight = 0 ;
let offsetX = indentRandom ;
let lineElements = [ ] ;
2023-12-07 22:56:11 +03:00
// Detect the empty line
const lineArray = line . flat ( ) ;
if ( lineArray . length === 0 ) {
offsetY += 50 * scaleFactor + lineSpacingRandom ;
return { lineContent , offsetY , offsetX } ;
}
2023-11-25 11:56:14 +03:00
for ( let i = 0 ; i < line . length ; i ++ ) {
const word = line [ i ] ;
const { wordElements , wordHeight , offsetX : newOffsetX , } = assembleWord ( {
word ,
offsetX ,
offsetY ,
scaleFactor ,
indentRandom ,
defects ,
} ) ;
// Update the offset
offsetX = newOffsetX ;
lineHeight = Math . max ( lineHeight , wordHeight ) ;
lineElements = lineElements . concat ( wordElements ) ;
}
2023-12-07 22:56:11 +03:00
// Align the line elements to the bottom of the line
const aligned = verticalAlign ( lineElements , lineHeight , offsetY , scaleFactor , defects ) ;
[ lineElements , lineHeight ] = [ aligned . lineElements , aligned . lineHeight ] ;
offsetY += lineHeight || 10 * scaleFactor + lineSpacingRandom ;
2023-11-25 11:56:14 +03:00
// Append the line elements to the SVG content
lineElements . forEach ( ( e ) => {
lineContent += e . element . outerHTML ;
} ) ;
return { lineContent , offsetY , offsetX } ;
} ;
2023-12-07 22:56:11 +03:00
const verticalAlign = ( lineElements , lineHeight , offsetY , scaleFactor , defects ) => {
// Align the line elements to the bottom of the line
let extended = false ;
const extendValue = 10 * scaleFactor ;
lineElements . forEach ( ( e ) => {
const { element , isSpecial , position , extendBelowBaseline } = e ;
// Match all numbers in style attribute
const style = element . getAttribute ( "transform" ) ;
const regex = /[-+]?[0-9]*\.?[0-9]+/g ;
const { baselineOffset } = getRandomDefects ( defects , scaleFactor ) ;
const [ x , y , s ] = style . match ( regex ) ;
const elementHeight = parseInt ( element . getAttribute ( "height" ) ) ;
const lineYOffset = Math . abs ( lineHeight - elementHeight ) ;
const elementOffset = Math . abs ( lineHeight - elementHeight ) ;
if ( isSpecial ) {
if ( position === "top" ) {
element . setAttribute ( "transform" , ` translate( ${ x } , ${ offsetY } ) scale( ${ s } ) ` ) ;
}
else if ( position === "middle" ) {
element . setAttribute ( "transform" , ` translate( ${ x } , ${ Number ( y ) + lineYOffset / 2 } ) scale( ${ s } ) ` ) ;
}
else {
element . setAttribute ( "transform" , ` translate( ${ x } , ${ Number ( y ) + lineYOffset } ) scale( ${ s } ) ` ) ;
}
}
else {
if ( extendBelowBaseline ) {
element . setAttribute ( "transform" , ` translate( ${ x } , ${ Number ( y ) + lineYOffset + extendValue } ) scale( ${ s } ) ` ) ;
extended = true ;
}
else {
element . setAttribute ( "transform" , ` translate( ${ x } , ${ Number ( y ) + elementOffset + baselineOffset } ) scale( ${ s } ) ` ) ;
}
}
} ) ;
// Fix the line height
if ( extended )
lineHeight += extendValue ;
// Add line margin
lineHeight += 3 * scaleFactor ;
return { lineElements , lineHeight } ;
} ;
const warpSvg = ( svg , width , height ) => {
// Create empty SVG document
const dom = new jsdom _1 . default . JSDOM ( ) ;
const svgWrapper = dom . window . document . createElementNS ( "http://www.w3.org/2000/svg" , "svg" ) ;
// Set the SVG width and height
svgWrapper . setAttribute ( "width" , String ( width ) ) ;
svgWrapper . setAttribute ( "height" , String ( height ) ) ;
// Add the SVG content to the SVG document
svgWrapper . innerHTML = svg ;
return svgWrapper === null || svgWrapper === void 0 ? void 0 : svgWrapper . outerHTML ;
} ;
exports . warpSvg = warpSvg ;
2023-11-25 11:56:14 +03:00
/ * *
* Writes the SVG content to a file and returns the server file path .
* @ param svgContent - The SVG content to be written to the file .
* @ returns The server file path of the generated SVG file .
* /
const writeSVG = ( svgContent , totalHeight , totalWidth ) => _ _awaiter ( void 0 , void 0 , void 0 , function * ( ) {
// wrap the SVG content in an SVG document
const outputFile = ` <svg width=" ${ totalWidth } " height=" ${ totalHeight } " xmlns="http://www.w3.org/2000/svg"> ${ svgContent } </svg> ` ; // Change this to your desired SVG content
2023-12-07 22:56:11 +03:00
// const outputFile = svgFlatten(svgContent).pathify().value();
2023-11-25 11:56:14 +03:00
// Write the SVG content to a file
const svgFilePath = ` ${ paths _1 . STATIC _PATH } /generated.svg ` ; // Change this to your desired file path
fs _1 . default . writeFileSync ( svgFilePath , outputFile ) ;
// Return the SVG file path
const basePath = ` ${ process . env . BASE _URL || "http://localhost" } ` ;
const port = process . env . PORT || "5000" ;
// Date.now() is used to prevent caching (cache busting)
const serverFilePath = ` ${ basePath } : ${ port } /static/generated.svg?v= ${ Date . now ( ) } ` ;
return serverFilePath ;
} ) ;
2023-12-07 22:56:11 +03:00
const generateSvg = ( options ) => _ _awaiter ( void 0 , void 0 , void 0 , function * ( ) {
const { paths , scaleFactor = 1 , defects } = options ;
2023-11-25 11:56:14 +03:00
let svgContent = "" ;
let offsetY = 0 ;
let totalHeight = 0 ;
let totalWidth = 0 ;
// Iterate over the lines, words and chars creating the SVG content
paths . forEach ( ( line ) => {
const { lineContent , offsetY : newOffsetY , offsetX , } = assembleLine ( {
defects ,
scaleFactor ,
line ,
offsetY ,
} ) ;
svgContent += lineContent ;
offsetY = newOffsetY ;
totalHeight = Math . max ( totalHeight , offsetY ) ;
totalWidth = Math . max ( totalWidth , offsetX ) ;
} ) ;
// Write the SVG content to a file
const serverFilePath = yield writeSVG ( svgContent , totalHeight , totalWidth ) ;
2023-12-07 22:56:11 +03:00
return { serverFilePath , totalWidth , totalHeight } ;
2023-11-25 11:56:14 +03:00
} ) ;
exports . generateSvg = generateSvg ;
/ * *
* Renders an SVG file to a connected plotter .
* @ param inputPath - The path to the input SVG file .
* @ param outputPath - Optional . The path to the output SVG file .
* @ returns An error if one occurs during the rendering process .
* /
const printSVG = ( inputPath ) => _ _awaiter ( void 0 , void 0 , void 0 , function * ( ) {
// Execute the following command : axicli inputPath usin os.system
const { execSync } = require ( "child_process" ) ;
try {
2023-12-07 22:56:11 +03:00
const command = ` axicli " ${ inputPath } " ` ;
2023-11-25 11:56:14 +03:00
const result = execSync ( command , { encoding : "utf-8" } ) ;
// Process the result and return an object
return {
success : true ,
message : ` success: ${ result } ` ,
} ;
}
catch ( error ) {
const errorMessage = error ;
return {
success : false ,
message : ` error: ${ errorMessage . message } ` ,
} ;
}
} ) ;
exports . printSVG = printSVG ;
// Function to create the character directory
const createCharacterDirectory = ( userPath , charTitle ) => _ _awaiter ( void 0 , void 0 , void 0 , function * ( ) {
const characters = yield fs _1 . default . promises . readdir ( userPath ) ;
if ( ! characters . includes ( charTitle ) ) {
yield fs _1 . default . promises . mkdir ( ` ${ userPath } / ${ charTitle } ` ) ;
}
} ) ;
exports . createCharacterDirectory = createCharacterDirectory ;
// Function to generate a unique SVG filename
const generateUniqueSVGPath = ( characterDir ) => _ _awaiter ( void 0 , void 0 , void 0 , function * ( ) {
const characterLength = yield numberOfFiles ( characterDir ) ;
2023-12-07 22:56:11 +03:00
return ` ${ characterDir } / ${ characterLength } .svg ` ;
2023-11-25 11:56:14 +03:00
} ) ;
exports . generateUniqueSVGPath = generateUniqueSVGPath ;
// Function to write SVG content to a file
const writeSVGToFile = ( svgPath , svgContent ) => _ _awaiter ( void 0 , void 0 , void 0 , function * ( ) {
yield fs _1 . default . promises . writeFile ( svgPath , svgContent ) ;
} ) ;
exports . writeSVGToFile = writeSVGToFile ;