Home Reference Source

src/document.js

import url from 'url'
import { propertyHider } from './util'

import { resolve, relative } from 'path'

import isAbsolutePath from 'path-is-absolute'
import Collection from './collection'

export const DefaultPatterns = [
  '**/*.{js,md,yml,json,svg,html,css,scss,less,json}',
  '!node_modules/**'
]

export const patterns = DefaultPatterns

export class Document {

  static fs = require('mem-fs').create();

  static patterns = DefaultPatterns;

  static mountCollection(base, options = {}) {
    return Collection.mount(base, options)
  }

  constructor (vFileOrPath, options = {}) {
    const hide = propertyHider(this)

    const originalURI = normalizeUri(
      vFileOrPath.path ? vFileOrPath.path : vFileOrPath
    )

    hide('options', options)
    hide('originalURI', originalURI)
    hide('parsedURI', url.parse(this.originalURI))
    hide('url', this.parsedURI.href)
    hide('uri', this.url)
    hide('path', this.parsedURI.path)
    hide('fs', this.constructor.fs)

    Object.defineProperty(this, 'file', {
      enumerable: false,
      configurable: true,
      get: function() {
        delete this.file
        return this.file = this.readFile()
      }
    })

    this.id = this.baseRelativePath.replace(/\.\w+$/, '')
  }

  readFile() {
    return this.fs.get(this.path)
  }

  get baseRelativePath() {
    return relative(
      this.options.base || process.cwd(),
      this.path
    )
  }

  get cacheKey() {
    return this.file
      ? [Math.floor(this.stat.mtime / 100), this.stat.size].join(':')
      : this.id
  }

  get isRemote() {
    return this.uri.protocol.indexOf('http') !== -1
  }
}

export default Document

export function buildDocumentId (url, base = process.cwd()) {
  return url.parse(url).pathname.replace(base, '')
}

export function normalizeUri (input) {
  if (typeof input !== 'string') {
    throw('Must pass the URI as a string')
  }

  const parsed = url.parse(input)

  const isFilePath = parsed.protocol === null || parsed.protocol.indexOf('file') !== -1
  const isRemoteUrl = !isFilePath && parsed.protocol.indexOf('http') !== -1
  const isAbsoluteFilePath = isFilePath && isAbsolutePath(parsed.path)

  if (isRemoteUrl) {
    return url.format(parsed)
  }

  if (isFilePath && isAbsoluteFilePath) {
    return url.format({
      protocol: 'file:',
      slashes: true,
      pathname: parsed.path,
    })
  } else {
    return url.format({
      protocol: 'file:',
      slashes: true,
      pathname: resolve(process.cwd(), parsed.path),
    })
  }

  return input
}