Faces.js, a JavaScript library for generating vector-based cartoon faces
zengm.com
zengm.com
Never saw such a nose in my life
'Tis a nose of parchment
It is six times as big but
'tis a nose like my nose
https://www.youtube.com/watch?v=bNQKYolhZkgHe has a bunch of other interesting things like this, too: https://www.redblobgames.com/
https://www.youtube.com/watch?v=fgOqvyPif3g
(no affiliation)
[1] http://www-cs-students.stanford.edu/~amitp/game-programming/...
import { display, generate } from "facesjs";
// Generate a random face
const face = generate();
// Display in a div with id "my-div-id"
display("my-div-id", face);
Beautiful API.I absolutely am looking for an excuse to use faces.js somewhere.
What you see now is already after another contributor came through and redid all my artwork. You don't want to know what it looked like back before then lol
Let's say I want to add a random face to every div with class "face". With this API have to generate ids. With an API that returns a root element it's trivial and it's not duplicating work (inserting elements into the DOM) that already exists.
Taking a selector would not be much better because it would again be duplicating work and make it harder to customize usage.
Taking a parent element for it to insert into would also be a poor API because it makes it harder to insert next to a sibling.
A good API would be one of
const face = generate()
someElem.appendChild(face);
or const face = generate()
someElem.appendChild(face.domElement);
or const face = generate()
someElem.appendChild(face.html()); // assumes it can render to something else tooTo extend the documentation example, wouldn't you just have "my-div-id-sibling" already and call
display("my-div-id", face);
display('my-div-id-sibling", someOtherFace);
Like almost all discussions that use language like "good API" or "bad API" this seems to me entirely personal preference. Personally I find anything where I end up having to call appendChild() myself a bad API. document.querySelectorAll('classIWantFacesIn').forEach(elem => {
const face = generate();
elem.id = `face-${crypto.randomUUID()}`; // this line should not be needed
display(elem.id, face);
});
With the current API I'm required to make ids and make sure they don't collide with other elements. Vs document.querySelectorAll('classIWantFacesIn').forEach(elem => {
const face = generate();
elem.appendChild(face.domElement);
});
Now, no id is needed. It's objectively a better API to not need the id.A nice thing about the current API is the face objects can be trivially serialized to JSON, which I need do in the application I originally wrote the library for.
Also the `display` function works with a DOM element as the first argument too, in which case you don't need to make up an ID. That's how I use it.
That being said, the API might not be perfect, but you should at least appreciate that it's been stable since v1 in 2015!
That said, I wouldn't have spoken up if someone hadn't claimed the API was good. Any one who makes a useful library that provides useful functionality people want is great!
> it's been stable since v1 in 2015!
That's awesome!
Consider...
// insert after every link
document.querySelectorAll('a.funny').forEach(elem =>
const face = generate();
const parentForFace = document.createElement('span');
elem.appendChild(parentForFace);
display(parentForFace);
});
vs // insert after every link
document.querySelectorAll('a.funny').forEach(elem =>
const face = generate();
elem.after(face.domElement);
});
Taking a parent element is still a poor APISo, it now lives as an Extism[0] wasm plugin you can call from those languages: https://modsurfer.dylibso.com/module?hash=2050e7f7a129a48df0...
The most clear information about it is at: https://extism.org, but its a bit focused on the primary use case for Extism, being a universal plugin system.
There is a C PDK (https://github.com/extism/c-pdk) which you'd probably want to use in a new wrapper around your library in C++, and compile it to wasm32 freestanding or WASI, but without emscripten. Extism doesn't currently have an interop layer to emscripten.
I find the wording a bit off here. Responsible security involves transparency along the supply chain and minimum trust, certainly not talking about worries and giving them up with ease.
I agree we should do more to specifically call out these security benefits - and also how a user could impact that default security.
Question: Does extism plan to support Python as a plugin language? That seems like a big gap right now
Edit: I see this issue tracking it https://github.com/extism/extism/issues/116 and the project is ongoing https://github.com/extism/python-pdk/issues/2
Python is pretty tricky given most users want libraries with native/C dependencies. With those and the Python runtime, the wasm tends to bloat up to tens of MB, rather unideal for a plug-in.
If you have time, please comment on that issue though and share some thoughts or use cases so we can better prioritize support!
Any pointers on all the steps to running this? Should I expect node to create a js file that could be served together with the HTML file? Or would my hosting server need to have node, and run it every time there is a request? Thanks in advance, I'm sorry for the confusion.
you can bypass node, npm install, etc for a prototype entirely in an html file leveraging an import map.
this is the importmap i load for all my pages: https://github.com/tylerchilds/plan98/blob/6120e6a80a3d48438...
to support faces, i’d add an entry: “facesjs”: “https://esm.sh/facesjs@4.0.0”
which should get rid of the import path issue, and to support legacy browsers that still might have that error:
Thanks again! Great website and projects, by the way.
[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guid...
if it helps, my last commit touches the primary aspects of modules.
overall, i’m integrating a test payment flow on https://thelanding.page
this commit[0] i export two functions from my payment debugger module (i am intentionally overloading the word module to additionally bind a view; this is a personal hot take and not general guidance, just in case you see how i use ‘@sillonious/module’).
so i expose payment-debugger.js in the index.html file import map as @sillonious/payments.
i import that module in the message-pay component.
when the user clicks buy now, i call the newPayment function (which ultimately lands in client.js, after traversing the network; in case you’re curious about the full route). i also set a timer that’ll check the payment status every five seconds for 15 minutes. displaying a timeout message is a not yet implemented edge case.
[0]: https://github.com/tylerchilds/plan98/commit/db3c037345077fe...
Genuine question - what does that phrase mean to you?
I've only ever heard it in the context of television shows (meaning "has been renewed for so many seasons that the writers have run out of ideas and have started forcing the characters into ever wackier situations to generate novelty") - and while it's intuitivve to map from that meaning to a more generic "has gone on for too long and thus become bad", the translation is fascinating. When you said this, were you intentionally using a term from another domain with a different meaning in the confidence that your audience could translate it appropriately, or does the phrase "jump the shark" really just mean "be old, and thus bad" to you?
(Asking from a purely non-prescriptivist non-judgemental perspective! I'm interested in understanding your thought process, not in judging or correcting you)
silicon valley was running out of ideas, but steve ballmer famously delivered the Developers, developers, developers speech paving the way for capturing developer market share, for a platform with platform developers is no platform at all.
there’s tooling that solves technical problems and tooling that business problems.
a system has “jumped the shark” when there are at least five ways to accomplish the same thing and the audience was just trying to have some happy days on the tubes.
my core hunch is that the ecosystem is a compile target versus a respected platform and that’s where i believe the shark has been jumped.
the web is cool, if only we stopped trying to jump it and befriend the shark already.
the long answer is, i’ve got a bespoke markdown like syntax i’m using for both a web publishing and screenplay authoring. i feel no difference between telling stories in interactive web formats or printed pages.
maybe i’m jumping the shark.
server side multi page demo: https://sillyz.computer/sagas/sillyz.computer/en-us/000-000....
if you press esc in the top left, you can play with that in the repl.
if you visit: https://sillyz.computer, that same text based adventure wizard journey as an embedded widget is the lower post it note.
this is the folder i’m using for localizing that journey: https://github.com/tylerchilds/plan98/tree/plan98/client/pub...
any of the short hand web components dynamically load from: https://github.com/tylerchilds/plan98/tree/plan98/client/pub...
full circle— i’m very much playing across domains with the jumping the shark reference
Jumped the shark means roughly the same thing as "lost the plot". In that, the current state of affairs has entered into absurd territories.
Among other things, it accepts an arbitrary key, and will always generate the same avatar for the same key. Very handy for apps which need to generate user-specific avatars.
Code is Apache license, and you can do whatever you want with the output. If you want to be nice, lmk if you use it somewhere, I like seeing it in the wild!
* There is a band called "4 non blondes"