Skip to content

Commit

Permalink
separate ai1 (for plain browser env) and everything (for module loaders)
Browse files Browse the repository at this point in the history
  • Loading branch information
laobubu committed Jun 15, 2018
1 parent 1f63c7f commit 40aa62e
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 76 deletions.
20 changes: 20 additions & 0 deletions dev/HyperMD.config.js
Expand Up @@ -54,6 +54,12 @@ exports.bundleFiles = [
output: "ai1.js",
name: "HyperMD",
uglify: true,
banner: [
"//-----------------------------------------------//",
"// !! This file is for Plain Browser Env ONLY !! //",
"// !! Not Work With Bundlers !! //",
"//-----------------------------------------------//",
].join("\n"),
},
{
// not necessary but maybe you just want the core utils?
Expand All @@ -63,6 +69,20 @@ exports.bundleFiles = [
},
]

exports.banner = `
/*!
* HyperMD, copyright (c) by laobubu
* Distributed under an MIT license: http://laobubu.net/HyperMD/LICENSE
*
* Break the Wall between writing and preview, in a Markdown Editor.
*
* HyperMD makes Markdown editor on web WYSIWYG, based on CodeMirror
*
* Homepage: http://laobubu.net/HyperMD/
* Issues: https://github.com/laobubu/HyperMD/issues
*/
`.trim()

/**
* Get modules' object name in plain browser env
*
Expand Down
17 changes: 15 additions & 2 deletions dev/docgen/make_powerpacks.ts
Expand Up @@ -2,7 +2,7 @@ import * as ts from "typescript"
import * as path from "path"
import * as glob from "glob"
import { program, srcPath } from "./base"
import { commentsToText, makeLink, getComponentURL, makeComponentLink } from "./genUtils"
import { commentsToText, makeLink, getComponentURL, makeTypeString } from "./genUtils"
import { getNamedDeclarations } from "./tsUtil";
import { getLineNo } from "./strUtil";

Expand Down Expand Up @@ -68,7 +68,20 @@ export function* make(): IterableIterator<string> {
if (v.length != 1) return
var node = v[0]

exported_str.push("* " + makeLink(k, getComponentURL(normalizedName, "#L" + getLineNo(sf.text, node.getStart(sf)))))
var typeInfo = ""
if (node['type']) typeInfo = makeTypeString(node['type'], sf, false)
else if (ts.isFunctionDeclaration(node)) {
let args = node.parameters
typeInfo = "`function(" + sf.text.slice(args.pos, args.end) + ")"
if (node.type) typeInfo += ": " + node.type.getText(sf)
typeInfo += "`"
}

exported_str.push(
"* " +
makeLink("**" + k + "**", getComponentURL(normalizedName, "#L" + getLineNo(sf.text, node.getStart(sf)))) +
(typeInfo ? " Type: " + typeInfo : "")
)
})

if (exported_str.length) {
Expand Down
7 changes: 3 additions & 4 deletions dev/docgen/tsUtil.ts
Expand Up @@ -51,14 +51,13 @@ export function getNamedDeclarations(sf: ts.SourceFile): Map<string, ReadonlyArr
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.TypeLiteral:
case SyntaxKind.VariableDeclaration:
name = getDeclarationName(<ts.Declaration>node)
addDeclaration(name, <ts.Declaration>node);
break;

case SyntaxKind.VariableDeclarationList:
let vdlNode = <ts.VariableDeclarationList>node;
vdlNode.declarations.forEach(vdNode => {
case SyntaxKind.VariableStatement:
let vsNode = <ts.VariableStatement>node;
vsNode.declarationList.declarations.forEach(vdNode => {
name = getDeclarationName(vdNode)
addDeclaration(name, vdNode)
})
Expand Down
96 changes: 52 additions & 44 deletions dev/post-build.js
Expand Up @@ -34,44 +34,40 @@ config.bundleFiles.forEach(item => {
// Make TypeScript-built files work in plain browser environment

/**
* **tsc** may compile files to UMD modules.
* However, TypeScript's UMD declaration is not compatible with plain browser env nor some bundler (like parcel-bunder)
* and we shall do a post-process here.
* **tsc** built AMD modules, let's do a post-process and convert them to UMD modules
*
* This doesn't matter while developing (compatible with require.js)
*
* @param {string} file "addon/foobar.js", will be overwritten
*/
function patchUMD(file) {
utils.processTextFile(file, (data) => {
const doneMark = `//[HyperMD] UMD for plain environment!`
if (data.includes(doneMark)) return

var tmp = data.match(/define\((\[.+?\]),\s*(\w+)/)
if (!tmp) return

var factoryFnName = tmp[2]
var modules = JSON.parse(tmp[1]).slice(2) // skip require and exports

var requiredModules = [] // ["codemirror", "../addon/xxx"]
var lutBody = [] // [ 'if (m === "../addon/fold") return HyperMD.Fold' ]
var exportsAlias = null // "HyperMD.FooBar" global name in plain env

{ // build lut and requiredModules
let lut = {}
for (const mod of modules) {
if (mod == "require" || mod == "exports") continue;
if (mod in lut) continue;
let globalName = lut[mod] = config.getGlobalName(mod, file)
requiredModules.push(mod)
if (globalName) lutBody.push(`if (m === ${JSON.stringify(mod)}) return ${globalName};`)
else if (mod[0] == '.' && !/\.css$/.test(mod)) {
// "./not-exported/module"
console.warn(`[HyperMD] "${file}" 's dependency "${mod}" is NOT accessible in plain browser env!`)
}
}
const doneMark = `//[HyperMD] UMD patched!`
if (data.includes(doneMark)) return;

var tmp = data.match(/\bdefine\((\[.+?\]),\s*/)
if (!tmp) return;

// data format:
//
// ... LEADING COMMENTS ...
// define(["require", "exports", "module1", "module2", "module3"], function (require, exports, foo, bar, baz) {
// ... MAIN CODE ...
// });

var data_head = data.slice(0, tmp.index) // comments before define([
var data_tail = data.slice(tmp.index + tmp[0].length) // function(require, exports, xxx) { ... });
var actualRefCount = data_tail.slice(0, data_tail.indexOf(')')).split(',').length - 2 // (argument count of mod function) - 2

{ // dynamic require is forbidden
if (data_tail.indexOf('require(') !== -1) throw new Error("[HyperMD] require('xxx') is not allowed in " + file)
}

/** @type {string[]} */
var modules = JSON.parse(tmp[1]).slice(2) // "require" and "exports" are excluded
var exportsAlias = "" // "HyperMD.FooBar" global name in plain env
var moduleGlobalNames = [] // ["CodeMirror", "MathJax", "HyperMD", "HyperMD.Fold"] global names in plain env

{ // decide exportsAlias
let fileModName = file.replace(/\.[jt]s$|^\.[\/\\]/ig, '').replace(/\\/g, '/') // => "addon/foobar"
exportsAlias = config.getGlobalName(fileModName)
Expand All @@ -91,24 +87,36 @@ function patchUMD(file) {
}
}

// pbe = plain browser env
var pbeInsertPos = data.indexOf('}', tmp.index + tmp[0].length) + 1
var pbeInsert = `
else { ${doneMark}
${factoryFnName}(function (m){
${lutBody.join("\n ")}
}, ${exportsAlias});
}`
{ // check bad references and build moduleGlobalNames
for (let i = 0; i < modules.length; i++) {
let mod = modules[i]
if (mod == "require" || mod == "exports") throw new Error("WTF?");

// add explicit require("")-s for factory(require, exports)
var textBeforePBE = data.slice(0, pbeInsertPos)
var reqInsertPos = textBeforePBE.lastIndexOf(factoryFnName, tmp.index)
reqInsertPos = textBeforePBE.lastIndexOf("{", reqInsertPos) + 1 // pos after "{"
var reqInsert = requiredModules.map(x => `\n require(${JSON.stringify(x)});`).join("")
let tmp = /^(\.[\.\/]*\/)(core\/.+|everything)$/.exec(mod)
if (tmp) {
let corrected = tmp[1] + "core"
console.warn(`[HyperMD][WARN] Please import "${corrected}" instead of "${mod}". Found in ${file}`)
mod = modules[i] = corrected
}

if (i < actualRefCount) {
let globalName = config.getGlobalName(mod, file)
moduleGlobalNames.push(globalName || "null")

if (!globalName)
console.warn(`[HyperMD][WARN] Module "${mod}" is NOT accessible in plain browser env! Found in ${file}`)
}
}
}

textBeforePBE = textBeforePBE.slice(0, reqInsertPos) + reqInsert + textBeforePBE.slice(reqInsertPos)
var interopData = `
(function (mod){ ${doneMark}
/*commonjs*/ ("object"==typeof exports&&"undefined"!=typeof module) ? mod(null, exports, ${modules.map(x => `require("${x}")`).join(", ")}) :
/*amd*/ ("function"==typeof define&&define.amd) ? define(${ JSON.stringify(["require", "exports"].concat(modules))}, mod) :
/*plain env*/ mod(null, ${exportsAlias}, ${moduleGlobalNames.slice(0, actualRefCount).join(", ")});
})(`

data = textBeforePBE + pbeInsert + data.slice(pbeInsertPos)
data = data_head + interopData + data_tail

return data
})
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Expand Up @@ -122,7 +122,7 @@ requirejs.config({

require([
'codemirror/lib/codemirror',
'hypermd/ai1', // If you doesn't want ai1 (all in one) build, see demo/index.js
'hypermd/everything', // Want to tailor and pick components? Please see demo/index.js

// Load these modes if you want highlighting ...
"codemirror/mode/htmlmixed/htmlmixed", // for embedded HTML
Expand Down
2 changes: 1 addition & 1 deletion docs/zh-CN/index.md
Expand Up @@ -121,7 +121,7 @@ requirejs.config({

require([
'codemirror/lib/codemirror',
'hypermd/ai1', // 如果不想用 ai1 (all in one) 版本, 参考 demo/index.js
'hypermd/everything', // 如果想选择性地只载入部分组件, 参考 demo/index.js

// 如果需要为特殊元素添加语法高亮,请载入对应的模式
"codemirror/mode/htmlmixed/htmlmixed", // Markdown 内嵌HTML
Expand Down
26 changes: 5 additions & 21 deletions rollup.config.js
@@ -1,27 +1,8 @@
import * as path from 'path'
import buble from 'rollup-plugin-buble'
import typescript from 'rollup-plugin-typescript2'
import { uglify } from 'rollup-plugin-uglify'

const watchMode = process.argv.includes("-w")
const makeAi1 = process.argv.includes("--with-ai1") || !watchMode

const srcDir = path.join(__dirname, "src")
const { components, globalNames, externalNames, bundleFiles } = require(__dirname + '/dev/HyperMD.config')

const banner = `
/*!
* HyperMD, copyright (c) by laobubu
* Distributed under an MIT license: http://laobubu.net/HyperMD/LICENSE
*
* Break the Wall between writing and preview, in a Markdown Editor.
*
* HyperMD makes Markdown editor on web WYSIWYG, based on CodeMirror
*
* Homepage: http://laobubu.net/HyperMD/
* Issues: https://github.com/laobubu/HyperMD/issues
*/
`.trim()
const { banner, globalNames, externalNames, bundleFiles } = require(__dirname + '/dev/HyperMD.config')

const plugins = {
ts: typescript({
Expand Down Expand Up @@ -61,6 +42,9 @@ bundleFiles.forEach(item => {
if (item.uglify) item_plugins.push(plugins.uglify) // optional: uglify
item_plugins.push(plugins.buble) // Essential: Buble

var _banner = banner
if (item.banner) _banner += "\n" + item.banner

var out = {
input: "./" + item.entry,
external: isExternal,
Expand All @@ -69,7 +53,7 @@ bundleFiles.forEach(item => {
format: 'umd',
name: item.name,
globals: globalNames,
banner,
banner: _banner,
},
plugins: item_plugins
}
Expand Down
3 changes: 1 addition & 2 deletions src/addon/fold-html.ts
Expand Up @@ -6,11 +6,10 @@

import * as CodeMirror from 'codemirror'
import { Position } from 'codemirror'
import { Addon, FlipFlop, suggestedEditorConfig, debounce, watchSize } from '../core'
import { Addon, suggestedEditorConfig, visitElements, watchSize } from '../core'
import { cm_t } from '../core/type'
import { builtinFolder, breakMark, FolderFunc, RequestRangeResult } from './fold'
import './read-link'
import { visitElements } from '../core/utils';

/********************************************************************************** */
/**
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"module": "umd",
"module": "amd",
"target": "es5",
"lib": [
"es5",
Expand Down

0 comments on commit 40aa62e

Please sign in to comment.