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

Support single file component (VueJS) #122

Closed
abou7mied opened this issue Jul 18, 2017 · 39 comments
Closed

Support single file component (VueJS) #122

abou7mied opened this issue Jul 18, 2017 · 39 comments
Labels
core dependency tree generation

Comments

@abou7mied
Copy link

I'm using VueJS and single file components (.vue files) which have dependencies but madge shows that .vue files has no deps.

The file structure is like that

<template>
...
</template>
<style>
...
</style>
<script>
  import file from './file.js';
...
</script>
@mrjoelkemp
Copy link
Contributor

Thanks for contributing!

This is an interesting case. It looks like an html parser (or a naive regex if possible) could be used to grab the imports out of inlined script tags. This could be made part of precinct for a .vue extension, but it would be nice to plug that in as a config from madge instead of precinct ballooning for all new frameworks.

This isn't a trivial change, but possible.

@abou7mied
Copy link
Author

abou7mied commented Jul 18, 2017

Maybe you can implement an interface for extracting js code for any extension and add option like --extract-from-extension vue and madge will search for file with name extractor-vue.js

module.exports = function (contents, callback) {
  callback("text", contents.match(/something/));
  // in case of referring files like using src attribute
  callback("refer", "./referred-file.js");
}

and call the interface, maybe you can create extractors directory in the repo which have predefined extractors for popular frameworks.

I forgot to indicate in previous comment that the script tag may refer to another file using the src attribute so the return of the interface maybe text or reference

It's just an idea maybe you have a good one.

@abou7mied
Copy link
Author

abou7mied commented Jul 18, 2017

I asked in Vue support about how to get script contents and they replied there are vue-template-compiler

const compiler = require('vue-template-compiler')
const output = compiler.parseComponent(`<script>import file from './file'</script>`, {pad: 'line'});

console.log("output.script", output.script);
/*
output.script { type: 'script',
  content: 'import file from \'./file\'',
  start: 8,
  attrs: {},
  end: 33 }
*/

So now we can get the contents of the script tag and src attribute if it exists.

I think make an interface for madge to handle files with custom extensions is a good idea we can make one extractor madge-extractor.js file and it should handle multiple extension

module.exports = (extension, contents, callback) => {
  let isReference = false
  if (extension === "vue") {
    const compiler = require('vue-template-compiler')
    const output = compiler.parseComponent(contents, {pad: 'line'})
    if(output.script){
      isReference = output.script.attrs.src;
      if(!isReference)
        contents = output.script.content
    }
  }

  /*  callback(isReference?, reference|contents) */
  callback(isReference, isReference ? isReference : contents);

}
madge app.js --extensions js,vue --extractor madge-extractor.js

@mrjoelkemp
Copy link
Contributor

Thanks for digging into this. Can regular components have the .vue extension or only these special template files?

If only the special case applies, then the path forward is similar to how we want to add TypeScript support #64. You need the code you wrote in precinct. You may not need to modify filing-cabinet since it defaults to an es6 resolver. Although, if you're using webpack, you may or may not (on mobile, sorry I can't verify) need to support the additional .vue extension in the config for enhanced-resolve.

I'm open to reviewing PRs for the effort. A good first step is to hack precinct and maybe filing-cabinet within madge's node_modules (or npm link if you're saavy) to get a proof of concept together.

@pahen
Copy link
Owner

pahen commented Aug 9, 2017

Sounds like a good time to pick up the extension/plugin support again :)

How about something like how the webpack loaders work? Would that be suitable for precinct @mrjoelkemp? See https://webpack.js.org/concepts/loaders/

@mrjoelkemp
Copy link
Contributor

That sounds good. Would madge be the supplier of the html detective and partial-resolver (like the resolvers in filing-cabinet)? Or would you pass that off to users of madge to supply their own detective/resolver combo (i.e., language pack)?

@mrjoelkemp
Copy link
Contributor

Is it fine to have the most recently registered language pack win in the case of conflicts (i.e., when folks override an existing file extension's language pack)? Or should it get chained (like a linked list within a hashmap) on conflicts (where every registered language pack for that extension gets run on the original source?

@Christopher-Wirt
Copy link

Just a bump here to ask about progress. Madge is a pretty exciting project, but my repo has a mix of vue and JSX files.

@Enity
Copy link

Enity commented Dec 16, 2018

const recursive = require('recursive-readdir');
const replace = require('replace-in-file');
const { extname } = require('path');
const { readFile, writeFile, unlink } = require('fs');
const { promisify } = require('util');

const readFileAsync = promisify(readFile);
const unlinkAsync = promisify(unlink);
const writeFileAsync = promisify(writeFile);

async function main(path = './') {
    const files = await getAllFiles(path);
    await Promise.all(files.map(file => replaceVueImportsWithJs(file)));

    const vueFiles = getVueFiles(files);
    await Promise.all(vueFiles.map(file => replaceVueFilesWithJs(file)));
}

async function getAllFiles(path) {
    return await recursive(path);
}

function getVueFiles(files) {
    return files.filter(f => f.includes('.vue'));
}

async function replaceVueImportsWithJs(file) {
    await replace({
        files: file,
        from: /\.vue/gm,
        to: '.js',
    });
}

async function replaceVueFilesWithJs(vueFile) {
    const script = await extractScript(vueFile);
    const newFileName = vueFile.replace(extname(vueFile), '.js');
    await unlinkAsync(vueFile);
    return writeFileAsync(newFileName, script, 'utf8');

    async function extractScript(file) {
        const content = await readFileAsync(file, 'utf8');
        return content.split('<script>')[1].split('</script>')[0];
    }
}

main('./src');

I just wrote a small script, which replaces all vue files and their imports with js)
its a hack but solves the problem

ATTENTION

This script edits and deletes original files, i just use git to bring changes back

@Mk-Etlinger
Copy link

Mk-Etlinger commented Mar 7, 2019

@Enity If I could upvote you more, I def would. Thanks for your quick and dirty script =) It helped me handoff a mess of a Vue app to another Dev. Cheers!

Also, love this project. It's incredible!

@maxim-usikov
Copy link

any news?

@songlairui
Copy link

songlairui commented Mar 5, 2020

I create a polyfill for vue project.

gist: https://gist.github.com/songlairui/287eaac29cda65cd5f1f7471b6661503
demo: https://github.com/songlairui/demo-madge-vue

image

@grokpot
Copy link

grokpot commented May 25, 2020

FYI, Nuxt.js just released the Components Module which I anticipate will grow in popularity. Whoever takes up this issue should keep that in mind.
@atinux maybe you know someone in the Vue community who would be interested in getting Madge and Vue to play together :)

@bailnl
Copy link

bailnl commented Nov 20, 2020

any news?

@reuwi
Copy link

reuwi commented Dec 20, 2020

Three years passed, has any progress...?

@mrjoelkemp
Copy link
Contributor

@reuwi please feel free to submit a PR.

@airene
Copy link

airene commented Jun 9, 2021

I create a polyfill for vue project.

gist: https://gist.github.com/songlairui/287eaac29cda65cd5f1f7471b6661503
demo: https://github.com/songlairui/demo-madge-vue

image

I think it's a good way then @Enity's method,
when I use madge 4.0.2 , songlairui's polyfill can't work,it confuse me one day.

finally,I found madge add precinct to dependencies since 3.9.x,but not use it ,the reason is when dependency-tree require(precinct) and then polyfill require(precinct) ,these are two 'instance' of precinct.

I had to use const precinct = require('./node_modules/dependency-tree/node_modules/precinct') to keep this ployfill working.

By the way,Madge is great tools for check project's file relations, and why does madge add precinct dependence, madge dependence dependency-tree has depend on precinct yet? @pahen @mrjoelkemp

Thanks a lot!

@PabloLION PabloLION added the core dependency tree generation label Jan 28, 2023
@Havunen
Copy link
Contributor

Havunen commented Feb 18, 2023

I needed this feature and implemented the support for Vue, I can create PRs soon

@Havunen
Copy link
Contributor

Havunen commented Feb 18, 2023

I created a new detective vue package to handle vue single file components https://github.com/Havunen/detective-vue2

Created PR to node-precinct dependents/node-precinct#112

Support for vue single file components to node-filing-cabinet dependents/node-filing-cabinet#111

Then new version of precinct and node-filing-cabinet needs to be published and possibly bump the dependencies here: https://github.com/dependents/node-dependency-tree

Then finally PR could be created to add support to Madge

@Havunen
Copy link
Contributor

Havunen commented Feb 23, 2023

@mrjoelkemp can you review the PRs please, it would be nice for madge to support vue files 😀

@mikeslattery
Copy link

This is way out of scope, but a tree-sitter parser would be more robust and able to handle all of kinds of alternate syntaxes, such as vue, svelte, tsx and non-js files such as html, pug, postcss and mixed variants such as svelte-pug, vue-scss-typescript.

@crystalfp
Copy link

Any news? This addition will be really useful. I'm running madge 6.1.0
Thanks!
mario

@Havunen
Copy link
Contributor

Havunen commented Sep 14, 2023

Can you please merge the PRs? @pahen @XhmikosR

@frankykubo
Copy link

Is this still active?

@Havunen
Copy link
Contributor

Havunen commented Nov 28, 2023

Madge has dependencies to these packages which have pending PRs
dependents/node-filing-cabinet#111
dependents/node-precinct#124

@freemedom
Copy link

freemedom commented Dec 8, 2023

For vue3, Enity's script needed some changes due to typescript support such as <script lang="ts"> <script setup lang="ts"> <script lang="tsx"> and the advent of .ts files. And need to handle cases where the vue file does not contain <script> tags.
I will post some changes later.

@xiaolee55
Copy link

xiaolee55 commented Jan 22, 2024

I create a polyfill for vue project.

gist: https://gist.github.com/songlairui/287eaac29cda65cd5f1f7471b6661503 demo: https://github.com/songlairui/demo-madge-vue

image

thats not work for me , I change 2

  1. change filing-cabinet,use tsLookup to handle .vue file
image 2. use decoratePrecinct to change precinct.paperwork

only use decoratePrecient
image

require it
image

result: thats work

image

@calandnong
Copy link

I create a polyfill for vue project.
gist: https://gist.github.com/songlairui/287eaac29cda65cd5f1f7471b6661503 demo: https://github.com/songlairui/demo-madge-vue
image

thats not work for me , I change 2

  1. change filing-cabinet,use tsLookup to handle .vue file

image 2. use decoratePrecinct to change precinct.paperwork
only use decoratePrecient image

require it image

result: thats work

image

就得是这个啊,靓仔,非常希望这个能力可以支持进去,因为当前vue已经非常热门了。

@calandnong
Copy link

@pahen 麻烦看看这个哈

@kqhasaki
Copy link

kqhasaki commented Apr 3, 2024

Just ran into this case, would really appreciate introduce .vue support. Is this still active?

@Havunen
Copy link
Contributor

Havunen commented Apr 15, 2024

Support for vue single file components have been implemented!

Madge has dependencies to these packages which have pending PRs
dependents/node-filing-cabinet#111
dependents/node-precinct#124

Now we just need to bump madge dependencies
#411

@cainrus
Copy link

cainrus commented May 30, 2024

@Havunen Are there any blockers for updating the dependencies? It seems like something fast and easy

@crystalfp
Copy link

crystalfp commented Jun 13, 2024

Anxiously waiting VUE file support. Currently .vue files are found, but no dependency is extracted from the <script setup lang="ts"> section.
Initially was thinking that the "@/" in the import path was not recognized, but also changing it to "src/" changed nothing. BTW in tsconfig.json there is "paths": {"@/*": ["src/*"]},
I'm running madge 7.0.0

@Havunen
Copy link
Contributor

Havunen commented Jun 14, 2024

@crystalfp which version of detective-vue2 do you have in your node_modules installed? latest should be 2.0.3 https://github.com/dependents/detective-vue2/blob/main/package.json

@crystalfp
Copy link

crystalfp commented Jun 14, 2024

Don't have any detective-vue2 anywhere.
I have madge installed globally. and under AppData\Roaming\npm\node_modules\madge\node_modules
There are various detective-* but no detective-vue2.
I try to reinstall madge and see if this makes any difference.

No, even reinstalling it the detective-vue2 package does not appear.
I have detective-{less,amd,postcss,stylus,cjs,es6,sass,scss,typescript}

@crystalfp
Copy link

Installing detective-vue2 package globally changed nothing.

@pavel-zh-revolist
Copy link

Does someone can share some mokey patch of Madge to support Vue SFC? Maybe some one could create a PR/Fork to support Vue SFC?

@Havunen
Copy link
Contributor

Havunen commented Jul 4, 2024

The vue support has landed to master branch but it is not released to npm.
https://github.com/pahen/madge/commits/master/

image

@pahen Could you create a new release so this old issue could be closed.

@pahen
Copy link
Owner

pahen commented Aug 5, 2024

The vue support has landed to master branch but it is not released to npm. https://github.com/pahen/madge/commits/master/

@pahen Could you create a new release so this old issue could be closed.

Release v8.0.0 now :)

@pahen pahen closed this as completed Aug 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core dependency tree generation
Projects
None yet
Development

Successfully merging a pull request may close this issue.