prettier-plugin-svelte icon indicating copy to clipboard operation
prettier-plugin-svelte copied to clipboard

usage in the browser

Open ElioStalteri opened this issue 5 years ago • 9 comments

I tried to make it work in the browser as described here https://prettier.io/docs/en/browser.html but didn't worked. I would like to use it in the REPL component. Does anyone knows something about how to make it work??

Thanks in advance.

ElioStalteri avatar Dec 22 '19 20:12 ElioStalteri

Without seeing what you tried, it's hard to debug anything, but from that page it sounds like you need to manually load all of the parsers this plugin uses as well as the plugin itself.

Conduitry avatar May 04 '20 13:05 Conduitry

@ElioStalteri hi, I've managed to make it work, that's how:

  1. the problem is that bundled code of svelte-pritter-plugin plugin contains var prettier = require('prettier'); (as soon as prettier is external dependency in rollup config)
  2. prettier requires fs and module which are not available in browser environment
  3. in fact svelte-prettier-plugin uses only part of prettier which doesn't need fs
  4. so you can make alias for fs and module in your bundler config so that thees modules are loaded from empty stubs

In case of webpack:

// stub.js:
export default {};

// webpack.config.js
const stub = path.resolve(__dirname, 'stub.js');
module.exports = {
   ...
  resolve: {
    alias: {
      'fs': stub,
      'module': stub
    }
 }

And then you can export this function to prettify svelte source code in browser (copied from my project as is, you might not need some of plugins):

const prettier = require("prettier/standalone");
const tsParser = require('prettier/parser-typescript');
const babylonParser = require('prettier/parser-babylon');
const cssParser = require('prettier/parser-postcss');
const sveltePlugin = require('prettier-plugin-svelte');

export const prettierFormatSvelte = (src) => {
  try {
    return prettier.format(
      src,
      {
        parser: 'svelte',
        plugins: [
          babylonParser,
          tsParser,
          cssParser,
          sveltePlugin
        ],
        svelteStrictMode: false,
        svelteIndentScriptAndStyle: false,
      },
    );
  } catch (e) {
    console.log('prettier failed', [e]);
    return src;
  }
}

Hope this helps

dubrowsky avatar Jan 24 '21 18:01 dubrowsky

I was able to get this working by replacing the two require imports with top-level esm imports

mateomorris avatar Jul 04 '22 02:07 mateomorris

@mateomorris Can you give code example on how you made it work please.

nbsharath avatar Sep 29 '23 08:09 nbsharath

I'm looking to use this plugin in a browser context. As of v3.1.2, this error is still being thrown. It would be amazing to solve for the browser use case.

Here are the previous attempts I could find:

  • https://github.com/sveltejs/prettier-plugin-svelte/pull/257
  • https://github.com/sveltejs/prettier-plugin-svelte/pull/142
  • https://github.com/sveltejs/prettier-plugin-svelte/pull/239

This is my code, in case it's useful. It works fine using Vite as the build tool and running in a Web Worker, until I add the Svelte plugin:

import { format } from 'prettier/standalone';
import * as prettierPluginBabel from 'prettier/plugins/babel';
import * as prettierPluginEstree from 'prettier/plugins/estree';
import * as prettierPluginHtml from 'prettier/plugins/html';
import * as prettierPluginMarkdown from 'prettier/plugins/markdown';
import * as prettierPluginCSS from 'prettier/plugins/postcss';
// import * as prettierPluginYaml from 'prettier/plugins/yaml';
// import * as prettierPluginGraphql from 'prettier/plugins/graphql';
// import * as prettierPluginAngular from 'prettier/plugins/angular';
import * as prettierPluginTypescript from 'prettier/plugins/typescript';
import * as prettierPluginSvelte from 'prettier-plugin-svelte';

import { FileId } from '../../types';

const parsers = {
  js: 'babel',
  jsx: 'babel',
  mjs: 'babel',
  cjs: 'babel',
  ts: 'typescript',
  tsx: 'typescript',
  css: 'css',
  //   '.less': 'less',
  //   '.scss': 'scss',
  html: 'html',
  json: 'json',
  json5: 'json5',
  //   '.graphql': 'graphql',
  //   '.gql': 'graphql',
  md: 'markdown',
  markdown: 'markdown',
  //   '.yaml': 'yaml',
  //   '.yml': 'yaml',
  //   '.vue': 'vue',
  //   '.component.html': 'angular',
  svelte: 'svelte',
};

const plugins = [
  prettierPluginBabel,
  prettierPluginEstree,
  prettierPluginHtml,
  prettierPluginMarkdown,
  prettierPluginTypescript,
  prettierPluginCSS,
  prettierPluginSvelte,
];

onmessage = async ({
  data,
}: {
  data: {
    // The text content of the file
    fileText: string;

    // The file extension
    // Supported extensions: https://prettier.io/docs/en/options.html#parser
    // The editor only supports
    // - JavaScript
    // - TypeScript
    // - HTML
    // - CSS
    // - JSON
    // - Markdown

    fileExtension: string;

    // The file id
    fileId: FileId;
  };
}) => {
  const { fileExtension, fileText, fileId } = data;
  const parser = parsers[fileExtension];

  if (!parser) {
    postMessage({
      fileId,
      error: `Unsupported file extension for Prettier: ${fileExtension}`,
    });
    return;
  }

  try {
    const fileTextPrettified = await format(fileText, {
      parser,
      plugins,

      // This helps with Markdown files
      proseWrap: 'always',

      // Opinionated code style for JavaScript
      singleQuote: true,
      printWidth: 60,
    });

    postMessage({
      fileId,
      fileTextPrettified,
    });
  } catch (error) {
    postMessage({
      fileId,
      error: error.toString(),
    });
  }
};

I'm eager to get this to work and may consider opening a PR at some point if I can get it to work.

curran avatar Jan 27 '24 17:01 curran

I was able to get past the Buffer error with this Nasty Hack:

import * as prettierPluginSvelte from 'prettier-plugin-svelte';
import { Buffer } from 'buffer';
globalThis.Buffer = Buffer;

Then the next error is:

Uncaught (in promise) TypeError: (0 , import_module.createRequire) is not a function
    at node_modules/prettier/index.mjs (prettier-SZN2M7JT.js?v=a60f1243:8457:48)
    at __init (chunk-WGAPYIUP.js?v=a60f1243:16:56)
    at prettier-SZN2M7JT.js?v=a60f1243:25055:1

This seems to be due to the fact that the only build distributed to NPM is a CommonJS build.

I wonder if we can take inspiration from the built-in Prettier plugins (like prettier/plugins/html or prettier/plugins/markdown) regarding how they are built and distributed. That might be half the battle right there! I wonder if just adding an ES build might work.

curran avatar Jan 27 '24 17:01 curran

Here's where the built-in Prettier plugins get built:

https://github.com/prettier/prettier/blob/main/scripts/build/build-javascript-module.js

It's a real can of worms, lots of custom stuff with ESBuild.

curran avatar Jan 28 '24 11:01 curran

Usage in the browser is now semi-possible using prettier-plugin-svelte/browser, see the repo readme for more details. For a full resolution, it should be easily possible to use it together with import maps, which isn't possible currently because the compiler.cjs module is retreived without the needed application/javascript content-type on CDNs.

dummdidumm avatar Feb 13 '24 13:02 dummdidumm