mgeisler / textwrap

An efficient and powerful Rust library for word wrapping text.
MIT License
446 stars 44 forks source link

Is it possible to ship an npm package ? #507

Open bacloud23 opened 1 year ago

bacloud23 commented 1 year ago

Hi, Thank you for this bright solution @mgeisler

I have no expertise in webassembly or rust. and also I would like to be able to run it on Node server. I know there is a way but is there an easy way ?

Thanks again

mgeisler commented 1 year ago

@yanna92yar, I had not considered bundling this up for NPM. Would that be useful for others to use it quickly?

bacloud23 commented 1 year ago

Hey @mgeisler I abondonned the part of thé project that was trying to make canvas.

But I will be happy to share my installation as it worked as web assembly pckg in a node environment. If this helps in anyway

Edit: my bad we were talking about an npm package. Mine is a docker image (installs wasm/rust) that compiles using wasm as suggested in doc, packs the folder in node_modules, which works fine in node.

Anyway if you are interested I can clean and send code later :)

mgeisler commented 1 year ago

Edit: my bad we were talking about an npm package. Mine is a docker image (installs wasm/rust) that compiles using wasm as suggested in doc, packs the folder in node_modules, which works fine in node.

Yeah, I guess we'll do something similar if we publish such a package: build it with a GitHub Action and then upload the resolving Wasm file.

It's been a few years since I published a npm package (and that was with normal JavaScript) :smile: So I would be curious to see the package.json file needed to make the package a well-behaved citizen in the npm universe.

bacloud23 commented 1 year ago

@mgeisler me neither ^^ no expert in packaging here ^^ I would have loved to help with the Github actionas well.

But anyway, I'm sur the matrix of versions is good here in this Dockerfile :

Having this repository along with the example folder, inside my npm project (to be able to import textwrap): git clone https://github.com/mgeisler/textwrap.git

FROM node:16-alpine
WORKDIR /usr/src/app
RUN apk add --update bash && rm -rf /var/cache/apk/* && \
    apk add build-base curl

COPY package*.json ./
RUN npm cache clean --force && rm -rf node_modules

RUN curl https://sh.rustup.rs -sSf | \
    sh -s -- -y
ENV PATH=/root/.cargo/bin:$PATH

RUN chmod +x $HOME/.cargo/env
RUN source "$HOME/.cargo/env"
RUN curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

COPY . .

RUN wasm-pack build --target nodejs /usr/src/app/lingua-rs/
RUN wasm-pack build --target nodejs /usr/src/app/textwrap/examples/wasm/ && \
    npm pack /usr/src/app/textwrap/examples/wasm/pkg/ && \
    npm i textwrap-wasm-demo-0.1.0.tgz
RUN npm i

# EXPOSE 3000
CMD [ "npm", "run", "start" ]

I struggled with the dependency version name, so no need to add it in my package.json, so I had to add npm i textwrap-wasm-demo-0.1.0.tgz in the dockerfile, and if I log in docker image and get the version name, and add it in package.json, it didn't work for some reason.

(same process worked fine for another dependency I had: "lingua": "file:./lingua-rs/pkg",)

Next issue, I had with import, so I switched to old require. This is an example:

import { createRequire } from 'module'
const require = createRequire(import.meta.url)
const { draw_wrapped_text, WasmOptions, WasmPenalties } = require('textwrap-wasm-demo')

const { createCanvas, GlobalFonts } = require('@napi-rs/canvas')
let fontpath = 'OpenSans_Condensed-Italic.ttf'
let fontFamily = 'sans-serif'
GlobalFonts.registerFromPath(fontpath, fontFamily)

export function loadTransformCanvas({
    text,
    canvasWidth,
    canvasHeight,
    fontSize,
    penalities: {
        nlinePenalty,
        overflowPenalty,
        shortLineFraction,
        shortLastLinePenalty,
        hyphenPenalty,
    },
    options: { lineWidth, breakWords, wordSeparator, wordSplitter, wrapAlgorithm },
}) {
    const canvas = createCanvas(canvasWidth, canvasHeight)
    let ctx = canvas.getContext('2d')
    ctx.clearRect(0, 0, canvasWidth, canvasHeight)
    ctx.font = `${fontSize}px ${fontFamily}`

    const penalties = new WasmPenalties(
        nlinePenalty,
        overflowPenalty,
        shortLineFraction,
        shortLastLinePenalty,
        hyphenPenalty
    )

    let options = new WasmOptions(
        lineWidth,
        breakWords,
        wordSeparator,
        wordSplitter,
        wrapAlgorithm,
        penalties
    )
    draw_wrapped_text(ctx, options, text, penalties)
    return ctx.canvas.toBuffer('image/png')
}

Having the file dangling in root folder: OpenSans_Condensed-Italic.ttf

Note thé canvas in node environment require('@napi-rs/canvas') this is why I asked before how to use the library without a Canvas and just get the raw values 😅..

So this was my attempt with packaging textwrap that I abandoned because lacking time..

bacloud23 commented 6 months ago

Hi Martin, Any news, are you considering to ship a npm package as well .?

Kindky

mgeisler commented 6 months ago

Hi @bacloud23, I am not using npm myself these days, so someone else should publish a package. Perhaps you can look into it?