Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can support for vue projects be added? #142

Open
wendell0316 opened this issue Feb 2, 2024 · 5 comments
Open

Can support for vue projects be added? #142

wendell0316 opened this issue Feb 2, 2024 · 5 comments
Assignees
Labels
core enhancement New feature or request

Comments

@wendell0316
Copy link

Summary

Details

Standard questions

Please answer these questions to help us investigate your issue more quickly:

Question Answer
Would you consider contributing a PR?
@wendell0316 wendell0316 added the enhancement New feature or request label Feb 2, 2024
@antoine-coulon
Copy link
Owner

Hello @wendell0316,

That's definitely something we can do yes. Let's support @vuejs in skott.

@antoine-coulon antoine-coulon self-assigned this Feb 2, 2024
@Dykam
Copy link

Dykam commented Aug 14, 2024

Maybe of use to make it easier to see what changes need to be made, this is what I needed to do to get .vue files kind of working.

Some things I noted for myself:

  • It's hard to add another file type
    • I initially added a new dependencyResolver but that did nothing, nor did (as far as I identified) adding more file extensions to the config
    • I don't suppose kExpectedModuleExtensions was made to be modified, but it worked.
  • It's impossible to add another module walker other than with some type casts and fakery.
    • Neither via the config object nor manually instantiating Skott.
  • SkottLogger isn't exposed.
  • Can't use renderTerminalApplication, as I needed a custom Skott instance, but I was looking to print cycles so that wasn't too difficult.
  • Vue SFC files can contain multiple(!) script tags. Here I just joined both results, this made more sense and the vast majority of files will only contain scriptSetup anyway.
    • I fed the extracted JS or TS to the right walker.
import { parse } from "@vue/compiler-sfc";
import { defaultConfig, Skott } from "skott";
import { FileSystemReader } from "skott/filesystem/file-reader";
import { FileSystemWriter } from "skott/filesystem/file-writer";
import { kExpectedModuleExtensions } from "skott/modules/resolvers/base-resolver";
import { ModuleWalker, ModuleWalkerSelector } from "skott/modules/walkers/common";

kExpectedModuleExtensions.add(".vue");

export const createSkott = ({ cwd }: { cwd: string }) => {
  const moduleWalkerSelector = new ModuleWalkerSelector();
  return new Skott(
    defaultConfig,
    new FileSystemReader({ cwd, ignorePatterns: [] }),
    new FileSystemWriter(),
    new (class {
      selectAppropriateModuleWalker(fileName: string): ModuleWalker {
        if (fileName.endsWith(".vue")) {
          return {
            async walk(options) {
              const parsed = parse(options.fileContent, { filename: options.fileName });
              const moduleDeclarations = new Set<string>();

              for (const blockType of ["script", "scriptSetup"]) {
                if (parsed.descriptor[blockType]?.content) {
                  const walker = moduleWalkerSelector.selectAppropriateModuleWalker(
                    `foo.${parsed.descriptor[blockType]?.lang ?? "js"}`
                  );
                  const walkerResult = await walker.walk({
                    ...options,
                    fileContent: parsed.descriptor[blockType].content,
                    fileName: `${options.fileName}-${blockType}.${parsed.descriptor[blockType].lang ?? "js"}`,
                  });
                  for (const moduleDeclaration of walkerResult.moduleDeclarations) {
                    moduleDeclarations.add(moduleDeclaration);
                  }
                }
              }

              return { moduleDeclarations };
            },
          };
        }
        return moduleWalkerSelector.selectAppropriateModuleWalker(fileName);
      }
    })() as ModuleWalkerSelector,
    {
      failure: () => {},
      info: () => {},
      success: () => {},
      startInfo: () => () => {},
    }
  );
};

@antoine-coulon
Copy link
Owner

Hello @Dykam,

Thanks for investigating that topic, you're raising interesting points. I'll have a more precise look when I'll be back from holidays (currently on my phone).

But let me answer you few things, indeed this is not an easy thing to do from an external perspective (adding Vue support), currently the only way to make it properly work with Vue would be to extend internals. But this is not something I want to do, I would rather have plugins that we can plug in to make Vue work with skott.

skott was initially designed to natively support JS/TS plus JSX.
Nonetheless I always had in mind to make skott a fit for other ecosystems or even supporting all file extensions for the JS ecosystem (Vue, Astro, etc) by making skott more flexible through some sort of plugins or runtime configuration to make it support other languages with their own parsers without having to dive into internals (I'm a huge fan of Vite or Rollup like plugin extensions).

Consequently what I can suggest is that I'll be taking a closer look at that beginning of next month and I'll be considering that enhancement and new design to make skott able to easily support Vue but also use the opportunity to make it flexible for other ecosystems/languages in general.

@Dykam
Copy link

Dykam commented Aug 24, 2024

All things considered, it was surprisingly easy to add the support, and I'm using it currently as part of a CI pipeline for cycle checking. Actual changes to make this easier are quite small, unless you of course want to redesign the API around a plugin system. My main issue is that I can no longer use renderTerminalApplication, or otherwise use the easy command line interface normally integrated. Other than that it's working pretty much flawless.

@antoine-coulon
Copy link
Owner

Glad to hear that, feel free to open a PR with the changes so that we can take a look at them together. I won't start the new design anytime soon, so it should not be a blocker

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants