Commit 479ca79

Anton Medvedev <anton@medv.io>
2021-08-13 03:11:39
Add support for bash code blocks in markdown scripts
1 parent 8fefed0
Changed files (3)
examples/markdown.md
@@ -19,3 +19,18 @@ We can use imports here as well:
 ```js
 await import('./basics.mjs')
 ```
+
+A bash code (with `bash` or `sh` language tags) also will be executed:
+
+```bash
+VAR=$(date)
+echo "$VAR" | wc -c
+```
+
+Other code blocks are ignored:
+
+```css
+body .hero {
+    margin: 42px;
+}
+```
index.mjs
@@ -36,7 +36,16 @@ export function $(pieces, ...args) {
     }
     cmd += s + pieces[++i]
   }
-  if (verbose) console.log('$', colorize(cmd))
+  if (verbose) {
+    if (/\n/.test(cmd)) {
+      console.log(cmd
+        .split('\n')
+        .map((line, i) => (i === 0 ? '$' : '>') + ' ' + colorize(line))
+        .join('\n'))
+    } else {
+      console.log('$', colorize(cmd))
+    }
+  }
   let options = {
     cwd: $.cwd,
     shell: typeof $.shell === 'string' ? $.shell : true,
@@ -58,16 +67,19 @@ export function $(pieces, ...args) {
     process.stdin.pipe(child.stdin)
   }
   let stdout = '', stderr = '', combined = ''
+
   function onStdout(data) {
     if (verbose) process.stdout.write(data)
     stdout += data
     combined += data
   }
+
   function onStderr(data) {
     if (verbose) process.stderr.write(data)
     stderr += data
     combined += data
   }
+
   child.stdout.on('data', onStdout)
   child.stderr.on('data', onStderr)
   promise._stop = () => {
zx.mjs
@@ -138,9 +138,15 @@ function transformMarkdown(source) {
         if (/^( {4}|\t)/.test(line) && prevLineIsEmpty) {
           output.push(line)
           state = 'tab'
-        } else if (/^```(js)?$/.test(line)) {
+        } else if (/^```(js|javascript)$/.test(line)) {
           output.push('')
-          state = 'code'
+          state = 'js'
+        } else if (/^```(sh|bash)$/.test(line)) {
+          output.push('await $`')
+          state = 'bash'
+        } else if (/^```.*$/.test(line)) {
+          output.push('')
+          state = 'other'
         } else {
           prevLineIsEmpty = line === ''
           output.push('// ' + line)
@@ -156,7 +162,7 @@ function transformMarkdown(source) {
           state = 'root'
         }
         break
-      case 'code':
+      case 'js':
         if (/^```$/.test(line)) {
           output.push('')
           state = 'root'
@@ -164,8 +170,25 @@ function transformMarkdown(source) {
           output.push(line)
         }
         break
+      case 'bash':
+        if (/^```$/.test(line)) {
+          output.push('`')
+          state = 'root'
+        } else {
+          output.push(line)
+        }
+        break
+      case 'other':
+        if (/^```$/.test(line)) {
+          output.push('')
+          state = 'root'
+        } else {
+          output.push('// ' + line)
+        }
+        break
     }
   }
+  console.log(output.join('\n'))
   return output.join('\n')
 }