Vue Playground在线交互式解释器支持less

参考 vue 官方 Vue Playground

q1.png

Vue Playground,它提供一个在线的可交互编辑环境,实现在线上直接调试文档提供的案例代码, 而且十分的轻量。

1、什么是REPL(交互式解释器)

REPL(Read Eval Print Loop:交互式解释器) 表示一个我们可以在其中输入命令或者代码,并且可以接收到解释器响应的一个环境。主要有四大特征组成。

  • 读取 Read - 读取用户输入,解析输入的数据结构并存储在内存中。
  • 执行 Eval - 执行输入的数据结构
  • 打印 Print - 输出结果
  • 循环 Loop - 循环操作以上步骤直到用户退出。

也就是说我们现在所用的所有代码编辑器其实都是一个REPL(交互式解释器)

2、什么是在线REPL(交互解释器)

我们日常使用的代码编辑器大多是通过软件包下载到本地安装的,因为在本地系统环境下可以得到更好更流畅的交互和编译体验。但是在某些场景下,网页版的交互解释器更具有优势,比如

  • 我有一段代码,我想分享给别人看看,通过网页URL的形式明显比传输代码包的形式更方便
  • 我写了一个组件,需要有个预览地址或者内嵌一个iframe预览链接放在我的文档里面
  • 我想在最简环境下复现一个bug,但是我又觉得重新开一个项目太麻烦,我希望有一个网页,打开就能直接写代码,最好我常用的依赖都内置在上面
  • 可以把在线编辑的代码下载下来在本地运行

很巧,上面这些场景Vue的Playground都比较好的解决了

3、存在的问题

虽然 Vue 的 Playground 具备了在线交互解释器的所有特征,但是他只预置了Vue的运行环境,假设我想预置更多的模块,比如我想让他天然支持less,支持scss,应该怎么做呢?

4、如何实现

首先打开Vue Playground的源码可以发现,整个交互解释器的核心在@vue/repl这个依赖中,Vue Playground也只是对@vue/repl进行了集成。

@vue/repl 源码

4.1 下载源码

直接 git clone https://github.com/vuejs/repl.git

4.2 安装库

安装库 pnpm i

安装less pnpm i less -D

安装less type pnpm i --save-dev @types/less

4.3 修改源码

(1) 导入 less

./src/transform.ts

import { Store, File } from './store'
import {
  SFCDescriptor,
  BindingMetadata,
  shouldTransformRef,
  transformRef,
  CompilerOptions
} from 'vue/compiler-sfc'
import { transform } from 'sucrase'
// 新增 导入 less
import less from 'less'

...

(2)在 compileFile 方法里面加入.less判断

export async function compileFile(
  store: Store,
  { filename, code, compiled }: File
) {
  if (!code.trim()) {
    store.state.errors = []
    return
  }

  if (filename.endsWith('.css')) {
    compiled.css = code
    store.state.errors = []
    return
  }

  // 加入 less文件判断
  if (filename.endsWith('.less')) {
    const outStyle = await less.render(code) // 使用less.render将 less code 转换成css
    compiled.css = outStyle.css
    store.state.errors = []
    return
  }

  ...
}

(3)移除判断 lang


if (
    descriptor.styles.some((s) => s.lang) ||
    (descriptor.template && descriptor.template.lang)
  ) {
    store.state.errors = [
      `lang="x" pre-processors for <template> or <style> are currently not ` +
        `supported.`
    ]
    return
  }

// 改为
if (
    // descriptor.styles.some((s) => s.lang) || // 主要移除这段代码
    (descriptor.template && descriptor.template.lang)
  ) {
    store.state.errors = [
      `lang="x" pre-processors for <template> or <style> are currently not ` +
        `supported.`
    ]
    return
  }

(4)添加 lang=less 判断

找到 styles 代码如下:

// styles
  let css = ''
  for (const style of descriptor.styles) {
    if (style.module) {
      store.state.errors = [
        `<style module> is not supported in the playground.`
      ]
      return
    }

    // 添加新代码
    let contentStyle = style.content
    if (style.lang === 'less') {
      const outStyle = await less.render(contentStyle)
      contentStyle = outStyle.css
    }

    const styleResult = await store.compiler.compileStyleAsync({
      ...store.options?.style,
      source: contentStyle,  // 这里将 style.content 修改为 contentStyle
      filename,
      id,
      scoped: style.scoped,
      modules: !!style.module
    })
    if (styleResult.errors.length) {
      // postcss uses pathToFileURL which isn't polyfilled in the browser
      // ignore these errors for now
      if (!styleResult.errors[0].message.includes('pathToFileURL')) {
        store.state.errors = styleResult.errors
      }
      // proceed even if css compile errors
    } else {
      css += styleResult.code + '\n'
    }
  }

4.4 修改支持 .less 文件的添加

./src/editor/FileSelector.vue

找到 doneAddFile 方法,修改添加 .less 过滤

function doneAddFile() {
  if (!pending.value) return
  const filename = pendingFilename.value

  if (!/\.(vue|js|ts|css|less)$/.test(filename)) { // 添加 |less
    store.state.errors = [
      `Playground only supports *.vue, *.js, *.ts, *.css files.`
    ]
    return
  }

  if (filename in store.state.files) {
    store.state.errors = [`File "${filename}" already exists.`]
    return
  }

  store.state.errors = []
  cancelAddFile()
  store.addFile(filename)
}

5、测试编译 less

在示例中加入 less 代码或者 导入 less 代码

<script setup>
import './aa.less' // 导入 less
import {list} from './t.ts'
import { ref } from 'vue'

const msg = ref('Hello world!')
console.log(list)
</script>

<template>
  <h1>{{ msg }}</h1>
  <div class="test">
    111
    <div class="test-page">
      page1233
    </div>
  </div>
  <input v-model="msg">
</template>
<style lang="less" scoped>
  h1{
    color:red
  }
  .test{
    font-size:18px;
    &-page{
      font-size:30px;
    }
  }
</style>

效果如下:

q2.png

aa.less 代码:

q3.png

参考:https://juejin.cn/post/7064864648729722887

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容