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 🙏

© 2024 – Pkg Stats / Ryan Hefner

sfc-composer

v0.8.2

Published

[![npm version][npm-version-src]][npm-version-href] [![npm downloads][npm-downloads-src]][npm-downloads-href] [![Github Actions][github-actions-src]][github-actions-href]

Downloads

838

Readme

sfc-composer

npm version npm downloads Github Actions

👨‍🔬 Pre-compiler helpers for Single File Components

Currently supports: .vue, .svelte, .astro

🕹️ Playground

Usage

Install package:

pnpm install sfc-composer
import { MagicSFC as MagicVueSFC } from 'sfc-composer/vue'
import { MagicSFC as MagicSvelteSFC } from 'sfc-composer/svelte'
import { MagicSFC as MagicAstroSFC } from 'sfc-composer/astro'

Internals

⚙️ MagicSFC class

MagicSFC<T> is the root interface supplied to be extended by framework-specific child classes.

  • scripts: MagicBlock<T>[]

    Referring to <script> or any JavaScript/TypeScript contexts of SFCs.

  • templates: MagicBlock<T>[]

    Referring to <template> parts of SFCs.

  • styles: MagicBlock<T>[]

    Referring to <style> parts of SFCs.

  • customs: MagicBlock<T>[]

    Custom blocks from frameworks parsers supporting that feature.

  • getSourcemap(options?: SourceMapOptions): SourceMap

    Generates a version 3 sourcemap like MagicString.

  • getTransformResult(): TransformResult

    Compatible with Vite transform() hook result.

  • parse(): Promise<MagicSFC>

    Uses the parser to update MagicSFC blocks.

Should be implemented by child classes.

Learn more about all the usages by looking at the tests!

⚙️ How MagicSFC works

When using the parse function, MagicSFC will split the supplied component using your framework native tooling.

The parsing result will be splitted into a standard format recognizing templates, scripts and styles blocks.

Each of these MagicBlock will preserve the original shape from the parser, but will also expose all the relevant MagicString functions.

Each of these function, when called, will both apply your changes on the local block.

You also get access to _loc and _source on every MagicBlock, which are standard copies of the block positioning and content.

When calling result, you will get the code as a string, and an appropriate SourceMap object.

Look at the implementation.

⚙️ createSFC functions

Frameworks exports a createSfc function that makes generating SFCs programatically easier.

They all support the same input aguments:

import { createSFC as createVueSFC } from 'sfc-composer/vue'
import { createSFC as createSvelteSFC } from 'sfc-composer/svelte'
import { createSFC as createAstroSFC } from 'sfc-composer/astro'

const writeableSFC = {
  templates: [
    {
      content: '<div>Hello World!</div>'
    }
  ],
  scripts: [
    {
      content: 'console.log(`Hello World!`)'
    }
  ],
  styles: [
    {
      content: 'div { color: red; }'
    }
  ]
}

// Will output a valid Svelte SFC
createSvelteSFC(writeableSFC)

// Will output a valid Astro SFC
createAstroSFC(writeableSFC)

// Will output a valid Vue SFC
createVueSFC({
  ...writeableSFC,
  // Vue also natively supports `customs` block in its parser.
  customs: [
    {
      type: 'i18n',
      content: '{ "fr": "Bonjour!", "en": "Hello!" }',
    }
  ]
})

MagicVueSFC

import { MagicSFC as MagicVueSFC } from 'sfc-composer/vue'
import { parse } from 'vue/compiler-sfc'

async function transformVueSFC() {
  const sfc = new MagicVueSFC(
    '<template><div>Hello World!</div></template>'
    + '<script setup>let test: string</script>'
    + '<style scoped>div { color: red; }</style>',
    {
      parser: parse
    }
  )

  // Process the SFC code through the parser
  await sfc.parse()

  // Append to the <script> tag
  sfc.scripts[0].append(' = `Hello World`')

  return sfc.result()

  // {
  //    code: '<template><div>Hello World!</div></template>\n\n<script setup>let test: string = `Hello World`</script>\n\n<style scoped>div { color: red; }</style>'
  //    map: SourceMap
  // }
}

Learn more by looking at the tests.

createVueSFC

import { createSFC as createVueSFC } from 'sfc-composer/vue'

const MagicVueSFC = createVueSFC({
  templates: [
    {
      content: '<div>{{ msg }}</div>',
    }
  ],
  script: [
    {
      content: 'export default { data() { return { msg: "Hello, world!" } } }'
    },
    {
      content: 'const setupMsg = "Hello from setup!"',
    }
  ],
  styles: [
    {
      lang: 'scss',
      scoped: true,
      content: '.text { color: red; }',
    },
  ],
})

🖨️ Will output

<script>
export default { data() { return { msg: "Hello, world!" } }
</script>

<script setup>
const setupMsg = "Hello from setup!"
</script>

<template>
<div>{{ msg }}</div>
</template>

<style scoped lang="scss">
.text { color: red; }
</style>

Learn more by looking at the tests!

MagicSvelteSFC

import { MagicSFC as MagicSvelteSFC } from 'sfc-composer/svelte'
import { preprocess } from 'svelte/compiler'

async function transformSvelteSFC() {
  const sfc = new MagicSvelteSFC(
    '<script>let test: string</script>\n\n'
    + '<div>Hello World!</div>\n\n'
    + '<style>div { color: red; }</style>',
    {
      parser: preprocess
    }
  )

  // Process the SFC code through the parser
  await sfc.parse()

  // Append to the <script> tag
  sfc.scripts[0].append(' = `Hello World`')

  return sfc.result()

  // {
  //    code: '<script>let test: string = `Hello World`</script>\n\n<div>Hello World!</div>\n\n<style>div { color: red; }</style>'
  //    map: SourceMap
  // }
}

Learn more by looking at the tests!

createSvelteSFC

import { createSFC as createSvelteSFC } from 'sfc-composer/svelte'

const MagicVueSFC = createSvelteSFC({
  templates: [
    {
      content: '<div>{msg}</div>',
    }
  ],
  script: [
    {
      content: 'let test = `Hello World!`;'
    }
  ],
  styles: [
    {
      content: '.text { color: red; }',
    },
  ],
})

🖨️ Will output

<script>
let test = `Hello World!`;
</script>

<script setup>
const setupMsg = "Hello from setup!"
</script>

<div>{msg}</div>

<style>
.text { color: red; }
</style>

Learn more by looking at the tests!

MagicAstroSFC

import { MagicSFC as MagicAstroSFC } from 'sfc-composer/astro'
import { preprocess } from '@astrojs/compiler'

async function transformAstroSFC() {
  const sfc = new MagicAstroSFC(
    '---\nlet test: string\n---\n\n'
    + '<div>Hello World!</div>\n\n'
    + '<style>div { color: red; }</style>',
    {
      parser: preprocess
    }
  )

  // Process the SFC code through the parser
  await sfc.parse()

  // Append to the <script> tag
  sfc.scripts[0].append('test = `Hello World`')

  return sfc.result()

  // {
  //    code: '---\nlet test: string\ntest = `Hello World`\n---\n\n<div>Hello World!</div>\n\n<style>div { color: red; }</style>'
  //    map: SourceMap
  // }
}

Learn more by looking at the tests!

createAstroSFC

import { createSFC as createAstroSFC } from 'sfc-composer/astro'

const MagicVueSFC = createAstroSFC({
  templates: [
    {
      content: '<div>{msg}</div>',
    }
  ],
  script: [
    {
      content: 'let test = `Hello World!`;',
      attrs: {
        frontmatter: true
      }
    },
    {
      content: 'let secondTest = `Hello World`;'
    }
  ],
  styles: [
    {
      content: '.text { color: red; }',
    },
  ],
})

🖨️ Will output

---
let test = `Hello World!`;
---

<script>
let secondTest = `Hello World`;
</script>

<div>{msg}</div>

<style>
.text { color: red; }
</style>

Learn more by looking at the tests!

Development

  • Clone this repository
  • Install latest LTS version of Node.js
  • Enable Corepack using corepack enable
  • Install dependencies using pnpm install
  • Run interactive tests using pnpm dev

License

Made with 💚

Published under MIT License.