npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dufeut/xkin

v0.2.0

Published

Browser-ready bundles for Monaco Editor, Babel, Prettier, SASS, CSSO, Terser & Showdown

Downloads

171

Readme

@dufeut/xkin

Browser-ready bundles for Monaco Editor, Babel, Prettier, SASS, CSSO, Terser, Showdown and Preact, all behind one global Xkin API. You don't need a bundler; add them with <script> tags.

npm license

Install

npm install @dufeut/xkin
# or
pnpm add @dufeut/xkin

The package is published under the @dufeut scope. Install @dufeut/xkin, not xkin.

Quick start

From a CDN

<script src="https://cdn.jsdelivr.net/npm/@dufeut/xkin/dist/xkin.editor.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@dufeut/xkin/dist/xkin.tools.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@dufeut/xkin/dist/xkin.styles.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@dufeut/xkin/dist/xkin.engine.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@dufeut/xkin/dist/xkin.min.js"></script>

Use https://unpkg.com/@dufeut/xkin/dist/... if you prefer unpkg. In production, pin a version, for example @dufeut/[email protected].

From node_modules

Serve or copy the package's dist/ folder and reference it:

<script src="/node_modules/@dufeut/xkin/dist/xkin.editor.min.js"></script>
<script src="/node_modules/@dufeut/xkin/dist/xkin.tools.min.js"></script>
<script src="/node_modules/@dufeut/xkin/dist/xkin.styles.min.js"></script>
<script src="/node_modules/@dufeut/xkin/dist/xkin.engine.min.js"></script>
<script src="/node_modules/@dufeut/xkin/dist/xkin.min.js"></script>

Keep dist/editor/ next to xkin.editor.min.js. Monaco loads its language workers and chunks from that folder at runtime.

Hello world

<div id="editor" style="height: 400px"></div>
<script>
  const editor = Xkin.editor({
    element: document.getElementById("editor"),
    value: "const App = () => <h1>Hello</h1>;",
    language: "typescript",
  });
</script>

Bundles

Each bundle is independent. Load only the ones you need, but load xkin.min.js last, because it wraps the others.

| File | Global | Provides | Needed for | | -------------------- | ------------ | ---------------------------------------- | ------------------------------------------------ | | xkin.editor.min.js | XkinEditor | Monaco Editor (+ dist/editor/ workers) | editor, set_*, models, types, set_compiler | | xkin.tools.min.js | XkinTools | Babel, Prettier, Terser, Showdown | tsx, format, markdown, mdx | | xkin.styles.min.js | XkinStyles | SASS, CSSO, PostCSS (CSS Modules) | sass, css_modules | | xkin.engine.min.js | XkinEngine | Preact + preact-render-to-string | engine, render_mdx | | xkin.min.js | Xkin | Unified API + Nanostores | Always | | xkin.d.ts | — | Type declarations for the Xkin global | Editor autocompletion (optional) |

Monaco ships with these languages: json, html, css, scss, javascript, typescript, python, sql, graphql, markdown, yaml.


API reference

All methods use snake_case. Methods marked async return a Promise.

| Area | Methods | | --------------------- | ---------------------------------------------------- | | Editor | editor, set_theme, set_language, set_content | | Models | create_model, get_model, delete_model | | Types | add_types, set_types, get_types, $types | | Compiler | set_compiler | | Tools | tsx, format, markdown, mdx | | Styles | sass, css_modules | | Engine | engine, render_mdx | | Store | store |

Editor

Xkin.editor(options) creates a Monaco editor and returns the Monaco editor instance. JSX/TSX is enabled out of the box, with h/Fragment as the pragma.

const editor = Xkin.editor({
  element: document.getElementById("container"),
  value: "console.log('hello');",
  language: "typescript",
  theme: "vs-dark",
  read_only: false,
  minimap: false,
  font_size: 14,
});

| Option | Type | Default | Description | | --------------- | ------------- | -------------- | ----------------------------------------------- | | element | HTMLElement | — | Container element (required) | | value | string | "" | Initial content | | language | string | "javascript" | Monaco language id | | theme | string | "vs-dark" | "vs", "vs-dark", "hc-black", "hc-light" | | read_only | boolean | false | Make the editor read-only | | minimap | boolean | false | Show the minimap | | scroll_beyond | boolean | false | Allow scrolling past the last line | | font_size | number | 14 | Font size in px | | auto_layout | boolean | true | Resize automatically with the container | | ...rest | — | — | Passed through to monaco.editor.create |

Xkin.set_theme("vs"); // global theme
Xkin.set_language(editor.getModel(), "javascript"); // change model language

set_content

Replaces the editor content without losing undo history. Use it after formatting, for example:

const formatted = await Xkin.format({ source: editor.getValue() });
Xkin.set_content(editor, formatted);
// Ctrl+Z still works

Models

Low-level Monaco models addressed by virtual file paths (/lib/utils.ts → file:///lib/utils.ts). Models let files import each other inside the editor.

Xkin.create_model(
  "/lib/utils.ts",
  "export const add = (a: number, b: number) => a + b;",
);
Xkin.create_model("/data.json", "{}", "json"); // optional language (default "typescript")
Xkin.get_model("/lib/utils.ts"); // model or null
Xkin.delete_model("/lib/utils.ts");

If a model already exists at that path, create_model updates its content instead of creating a duplicate.

Types

Inject global .d.ts declarations into Monaco's TypeScript/JavaScript language service. The type list is reactive (a Nanostores atom).

Xkin.add_types([
  { path: "globals.d.ts", content: "declare const $router: Router;" },
]);                     // merge by path

Xkin.set_types([...]);  // replace all
Xkin.get_types();       // read current list

Xkin.$types.subscribe((libs) => console.log("Types:", libs.length));

Autocompletion for the Xkin API

The package includes a self-contained xkin.d.ts. Inject it so the editor offers autocompletion for Xkin itself:

const url = "https://cdn.jsdelivr.net/npm/@dufeut/xkin/dist/xkin.d.ts";
const types = await fetch(url).then((r) => r.text());
Xkin.add_types([{ path: "xkin.d.ts", content: types }]);

Compiler

Xkin.set_compiler(options) configures the TypeScript compiler options for both TS and JS. Enum options accept readable strings or Monaco's numeric values.

Xkin.set_compiler({
  jsx: "React",
  jsxFactory: "h",
  jsxFragmentFactory: "Fragment",
  target: "ESNext",
  module: "ESNext",
  moduleResolution: "NodeJs",
});

| Option | Accepted strings | | ------------------ | ---------------------------------------------------------------------------------- | | jsx | "None", "Preserve", "React", "ReactNative", "ReactJSX", "ReactJSXDev" | | target | "ES3", "ES5", "ES2015" – "ES2022", "ESNext" | | module | "None", "CommonJS", "AMD", "UMD", "System", "ES2015", "ESNext", etc. | | moduleResolution | "Classic", "NodeJs", "Node16", "NodeNext", "Bundler" |

set_compiler replaces the compiler options. It does not merge them. Include every option you need.


Tools

tsx (async)

Transforms TypeScript/JSX to JavaScript with Babel, using the h/Fragment pragma. Terser can minify the output.

const { code } = await Xkin.tsx({
  source: "const App = () => <div>Hello</div>;",
  compress: true, // default false
  mangle: true, // default false
});

format (async)

Formats code with Prettier.

const formatted = await Xkin.format({
  source: "const x=1;const y=2;",
  parser: "babel", // default
  tabWidth: 2,
  printWidth: 80,
  semi: true,
  singleQuote: false,
  useTabs: false,
});

| Parser | Languages | | ---------------- | ---------------------- | | babel | JavaScript, JSX | | babel-ts | TypeScript, TSX | | typescript | TypeScript (native) | | css | CSS | | scss | SCSS | | less | Less | | html | HTML | | vue | Vue SFC | | angular | Angular templates | | markdown | Markdown | | mdx | MDX | | graphql | GraphQL | | yaml | YAML | | json | JSON | | json-stringify | JSON (stringify style) |

markdown

Converts Markdown to HTML with Showdown. This call is synchronous. options are passed straight to Showdown's options.

const html = Xkin.markdown({
  source: "# Hello\n\nThis is **bold** text.",
  options: {
    tables: true,
    tasklists: true,
    strikethrough: true,
    ghCodeBlocks: true,
    simplifiedAutoLink: true,
    openLinksInNewWindow: true,
    emoji: true,
  },
});

mdx (async)

Compiles Markdown with embedded ui-* components into a JSON-serializable tree. Pair it with render_mdx to render the tree to HTML with your own components.

const { tree, symbols } = await Xkin.mdx({
  source: `# Profile

<ui-card title="Hello" />

Some **markdown** text.`,
  md: { tables: true }, // Showdown options
});

// symbols => ["card"]                 (ui-* tags used, without the prefix)
// tree    => { tag, props, children } (plain objects, safe to JSON.stringify)
  • Custom components must use the ui- prefix (<ui-button />, <ui-card>…</ui-card>).
  • symbols lists each component name used, without the ui- prefix. Use it to load only the components a document needs.
  • The tree is plain data, so you can cache it, store it, or send it over the network.

Styles

sass (async)

Compiles SCSS to CSS. Set compressed: true to minify the result with CSSO.

const { css } = await Xkin.sass({
  source: "$color: red; .box { color: $color; }",
  compressed: true,
});

css*modules *(async)_

Scopes CSS class names and accepts SCSS input. Names are built as namespace__class__hash with an FNV-1a hash.

const { css, tokens } = await Xkin.css_modules({
  source: "$color: red; .title { color: $color; }",
  namespace: "app", // optional prefix
  idSize: 8, // hash length, default 8
});
// tokens => { title: "app__title__a1b2c3d4" }

Engine

engine

Gives direct access to the Preact runtime.

const { h, Fragment, render, createElement, renderToString } = Xkin.engine;

render(h("h1", null, "Hello"), document.body);

render_mdx

Renders a tree from mdx to an HTML string. Map each ui-* tag to a Preact component, keyed by the full tag name:

const { h } = Xkin.engine;

const { tree } = await Xkin.mdx({
  source: '# Hi\n\n<ui-card title="Hello" />',
});

const html = Xkin.render_mdx(tree, {
  "ui-card": ({ title }) => h("div", { class: "card" }, title),
});
// => "<div><h1 id=\"hi\">Hi</h1>…<div class=\"card\">Hello</div>…</div>"

Tags with no mapping render as plain elements.


Store

Re-exports Nanostores for reactive state.

const { atom, computed, map } = Xkin.store;

const $count = atom(0);
const $double = computed($count, (n) => n * 2);

$double.subscribe((v) => console.log(v));
$count.set(2); // logs 4

Development

pnpm install
pnpm build        # builds every bundle into dist/
pnpm test

To try every feature, open index.html in a browser after building. It is the interactive playground.

Individual bundles: build:editor, build:tools, build:styles, build:engine, build:main.

License

MIT