A templating language that looks like Lisp and compiles to HTML
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

oslo.js 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #!/usr/bin/env node
  2. const fs = require('fs')
  3. const path = require('path')
  4. const args = require('minimist')(process.argv.slice(2))
  5. const oslo = require('../src/index')
  6. const OsloError = require('../src/osloError')
  7. class OsloCLI {
  8. constructor(opts) {
  9. this.context = {}
  10. this.eval(opts)
  11. }
  12. eval(opts) {
  13. if (opts.l) {
  14. this.context = JSON.parse(fs.readFileSync(this.absolutePath(opts.l)))
  15. }
  16. let output
  17. if (opts.f && opts.f !== true) {
  18. output = this.file(path.join(process.cwd(), opts.f))
  19. } else if (opts.d && opts.d !== true) {
  20. if (!opts.o) {
  21. console.log(
  22. 'Output directory required. Invoke oslo with `-o path/to/output/directory`',
  23. )
  24. process.exit()
  25. }
  26. output = this.directory(
  27. this.absolutePath(opts.d),
  28. this.absolutePath(opts.o),
  29. )
  30. } else if (opts.e && opts.e !== true) {
  31. output = this.inline(opts.e)
  32. } else {
  33. this.printUsage()
  34. process.exit()
  35. }
  36. if (output.constructor == OsloError) {
  37. this.error(output)
  38. }
  39. if (opts.o) {
  40. this.output(opts, output)
  41. } else {
  42. process.stdout.write(output)
  43. process.stdout.write('\n')
  44. }
  45. }
  46. file(file) {
  47. const contents = fs.readFileSync(file).toString()
  48. return oslo(contents, this.context)
  49. }
  50. directory(directory) {
  51. let files = {}
  52. fs.readdirSync(directory).forEach(item => {
  53. const absolutePath = this.absolutePath(item, directory)
  54. if (fs.lstatSync(absolutePath).isDirectory()) {
  55. files = Object.assign(files, this.directory(absolutePath))
  56. } else {
  57. let output = this.file(absolutePath)
  58. files[absolutePath] = output
  59. }
  60. })
  61. return files
  62. }
  63. inline(source) {
  64. return oslo(source.toString(), this.context)
  65. }
  66. absolutePath(file, root = null) {
  67. if (!root) {
  68. root = process.cwd()
  69. }
  70. return path.join(root, file)
  71. }
  72. output(opts, output) {
  73. const absoluteOutputPath = this.absolutePath(opts.o)
  74. if (opts.f || opts.e) {
  75. fs.writeFile(absoluteOutputPath, output, function(err) {
  76. if (err) throw err
  77. })
  78. } else if (opts.d) {
  79. const absoluteInputPath = this.absolutePath(opts.d)
  80. Object.keys(output).forEach(function(file) {
  81. const absoluteOutputFilePath = file
  82. .replace(absoluteInputPath, absoluteOutputPath)
  83. .replace(/\.oslo$/, '.html')
  84. const parentDirectory = path.dirname(absoluteOutputFilePath)
  85. if (!fs.existsSync(parentDirectory)) {
  86. fs.mkdirSync(parentDirectory)
  87. }
  88. fs.writeFile(absoluteOutputFilePath, output[file], function(err) {
  89. if (err) throw err
  90. console.log(
  91. `Writing to ${absoluteOutputFilePath.replace(process.cwd(), '')}`,
  92. )
  93. })
  94. })
  95. }
  96. }
  97. printUsage() {
  98. console.log(
  99. `USAGE
  100. -d The path to a directory. The directory will be recursively scanned. An
  101. output directory is required with this option.
  102. oslo -d templates
  103. -e Pass oslo code directly.
  104. oslo -e '(div "Hello world")'
  105. -f The path to a single file.
  106. oslo -f index.oslo
  107. -l The path to a json file to use as context for compilation
  108. oslo -f index.oslo -l data.json
  109. -o Where to direct the output. If no path is provided, output will be directed
  110. to stdout. When used with -f, the argument should be the path to a file.
  111. When used with -d, the argument should be the path to a directory, which
  112. will be created if it does not already exist.
  113. oslo -f index.oslo -o index.html
  114. oslo -d templates -o html`,
  115. )
  116. }
  117. error(err) {
  118. console.log(err.message)
  119. process.exit()
  120. }
  121. }
  122. new OsloCLI(args)