forked from mystiq/hydrogen-web
commit
02e422f3ac
14 changed files with 2453 additions and 64 deletions
|
@ -10,7 +10,7 @@
|
|||
"lint": "eslint --cache src/",
|
||||
"lint-ci": "eslint src/",
|
||||
"test": "impunity --entry-point src/main.js --force-esm-dirs lib/ src/",
|
||||
"start": "node scripts/serve-local.js",
|
||||
"start": "snowpack dev --port 3000",
|
||||
"build": "node --experimental-modules scripts/build.mjs",
|
||||
"postinstall": "node ./scripts/post-install.js"
|
||||
},
|
||||
|
@ -39,7 +39,7 @@
|
|||
"eslint": "^7.25.0",
|
||||
"fake-indexeddb": "^3.1.2",
|
||||
"finalhandler": "^1.1.1",
|
||||
"impunity": "^1.0.0",
|
||||
"impunity": "^1.0.1",
|
||||
"mdn-polyfills": "^5.20.0",
|
||||
"node-html-parser": "^4.0.0",
|
||||
"postcss": "^8.1.1",
|
||||
|
@ -51,6 +51,8 @@
|
|||
"rollup": "^2.26.4",
|
||||
"rollup-plugin-cleanup": "^3.1.1",
|
||||
"serve-static": "^1.13.2",
|
||||
"snowpack": "^3.8.3",
|
||||
"typescript": "^4.3.5",
|
||||
"xxhashjs": "^0.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
|
@ -15,6 +15,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {build as snowpackBuild, loadConfiguration} from "snowpack"
|
||||
import cheerio from "cheerio";
|
||||
import fsRoot from "fs";
|
||||
const fs = fsRoot.promises;
|
||||
|
@ -45,8 +46,11 @@ import flexbugsFixes from "postcss-flexbugs-fixes";
|
|||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const projectDir = path.join(__dirname, "../");
|
||||
const snowpackOutPath = path.join(projectDir, "snowpack-build-output");
|
||||
const cssSrcDir = path.join(projectDir, "src/platform/web/ui/css/");
|
||||
const srcDir = path.join(projectDir, "src/");
|
||||
const snowpackConfig = await loadConfiguration({buildOptions: {out: snowpackOutPath}}, "snowpack.config.js");
|
||||
const snowpackOutDir = snowpackConfig.buildOptions.out.substring(projectDir.length);
|
||||
const srcDir = path.join(projectDir, `${snowpackOutDir}/src/`);
|
||||
const isPathInSrcDir = path => path.startsWith(srcDir);
|
||||
|
||||
const parameters = new commander.Command();
|
||||
|
@ -56,14 +60,27 @@ parameters
|
|||
.option("--override-css <main css file>", "pass in an alternative main css file")
|
||||
parameters.parse(process.argv);
|
||||
|
||||
/**
|
||||
* We use Snowpack to handle the translation of TypeScript
|
||||
* into JavaScript. We thus can't bundle files straight from
|
||||
* the src directory, since some of them are TypeScript, and since
|
||||
* they may import Node modules. We thus bundle files after they
|
||||
* have been processed by Snowpack. This function returns paths
|
||||
* to the files that have already been pre-processed in this manner.
|
||||
*/
|
||||
function srcPath(src) {
|
||||
return path.join(snowpackOutDir, 'src', src);
|
||||
}
|
||||
|
||||
async function build({modernOnly, overrideImports, overrideCss}) {
|
||||
await snowpackBuild({config: snowpackConfig});
|
||||
// get version number
|
||||
const version = JSON.parse(await fs.readFile(path.join(projectDir, "package.json"), "utf8")).version;
|
||||
let importOverridesMap;
|
||||
if (overrideImports) {
|
||||
importOverridesMap = await readImportOverrides(overrideImports);
|
||||
}
|
||||
const devHtml = await fs.readFile(path.join(projectDir, "index.html"), "utf8");
|
||||
const devHtml = await fs.readFile(path.join(snowpackOutPath, "index.html"), "utf8");
|
||||
const doc = cheerio.load(devHtml);
|
||||
const themes = [];
|
||||
findThemes(doc, themeName => {
|
||||
|
@ -77,13 +94,13 @@ async function build({modernOnly, overrideImports, overrideCss}) {
|
|||
// copy olm assets
|
||||
const olmAssets = await copyFolder(path.join(projectDir, "lib/olm/"), assets.directory);
|
||||
assets.addSubMap(olmAssets);
|
||||
await assets.write(`hydrogen.js`, await buildJs("src/main.js", ["src/platform/web/Platform.js"], importOverridesMap));
|
||||
await assets.write(`hydrogen.js`, await buildJs(srcPath("main.js"), [srcPath("platform/web/Platform.js")], importOverridesMap));
|
||||
if (!modernOnly) {
|
||||
await assets.write(`hydrogen-legacy.js`, await buildJsLegacy("src/main.js", [
|
||||
'src/platform/web/legacy-polyfill.js',
|
||||
'src/platform/web/LegacyPlatform.js'
|
||||
await assets.write(`hydrogen-legacy.js`, await buildJsLegacy(srcPath("main.js"), [
|
||||
srcPath('platform/web/legacy-polyfill.js'),
|
||||
srcPath('platform/web/LegacyPlatform.js')
|
||||
], importOverridesMap));
|
||||
await assets.write(`worker.js`, await buildJsLegacy("src/platform/web/worker/main.js", ['src/platform/web/worker/polyfill.js']));
|
||||
await assets.write(`worker.js`, await buildJsLegacy(srcPath("platform/web/worker/main.js"), [srcPath('platform/web/worker/polyfill.js')]));
|
||||
}
|
||||
// copy over non-theme assets
|
||||
const baseConfig = JSON.parse(await fs.readFile(path.join(projectDir, "assets/config.json"), {encoding: "utf8"}));
|
||||
|
@ -97,13 +114,14 @@ async function build({modernOnly, overrideImports, overrideCss}) {
|
|||
await buildManifest(assets);
|
||||
// all assets have been added, create a hash from all assets name to cache unhashed files like index.html
|
||||
assets.addToHashForAll("index.html", devHtml);
|
||||
let swSource = await fs.readFile(path.join(projectDir, "src/platform/web/service-worker.js"), "utf8");
|
||||
assets.addToHashForAll("sw.js", swSource);
|
||||
let swSource = await fs.readFile(path.join(snowpackOutPath, "service-worker.js"), "utf8");
|
||||
assets.addToHashForAll("service-worker.js", swSource);
|
||||
|
||||
const globalHash = assets.hashForAll();
|
||||
|
||||
await buildServiceWorker(swSource, version, globalHash, assets);
|
||||
await buildHtml(doc, version, baseConfig, globalHash, modernOnly, assets);
|
||||
await removeDirIfExists(snowpackOutPath);
|
||||
console.log(`built hydrogen ${version} (${globalHash}) successfully with ${assets.size} files`);
|
||||
}
|
||||
|
||||
|
@ -156,7 +174,7 @@ async function buildHtml(doc, version, baseConfig, globalHash, modernOnly, asset
|
|||
const configJSON = JSON.stringify(Object.assign({}, baseConfig, {
|
||||
worker: assets.has("worker.js") ? assets.resolve(`worker.js`) : null,
|
||||
downloadSandbox: assets.resolve("download-sandbox.html"),
|
||||
serviceWorker: "sw.js",
|
||||
serviceWorker: "service-worker.js",
|
||||
olm: {
|
||||
wasm: assets.resolve("olm.wasm"),
|
||||
legacyBundle: assets.resolve("olm_legacy.js"),
|
||||
|
@ -324,7 +342,7 @@ async function buildServiceWorker(swSource, version, globalHash, assets) {
|
|||
swSource = replaceStringInSource("NOTIFICATION_BADGE_ICON", assets.resolve("icon.png"));
|
||||
|
||||
// service worker should not have a hashed name as it is polled by the browser for updates
|
||||
await assets.writeUnhashed("sw.js", swSource);
|
||||
await assets.writeUnhashed("service-worker.js", swSource);
|
||||
}
|
||||
|
||||
async function buildCssBundles(buildFn, themes, assets, mainCssFile = null) {
|
||||
|
|
|
@ -75,7 +75,7 @@ async function populateLib() {
|
|||
const olmDstDir = path.join(libDir, "olm/");
|
||||
await fs.mkdir(olmDstDir);
|
||||
for (const file of ["olm.js", "olm.wasm", "olm_legacy.js"]) {
|
||||
await fs.symlink(path.join(olmSrcDir, file), path.join(olmDstDir, file));
|
||||
await fs.copyFile(path.join(olmSrcDir, file), path.join(olmDstDir, file));
|
||||
}
|
||||
// transpile node-html-parser to esm
|
||||
await fs.mkdir(path.join(libDir, "node-html-parser/"));
|
||||
|
@ -83,12 +83,6 @@ async function populateLib() {
|
|||
require.resolve('node-html-parser/dist/index.js'),
|
||||
path.join(libDir, "node-html-parser/index.js")
|
||||
);
|
||||
// Symlink dompurify
|
||||
await fs.mkdir(path.join(libDir, "dompurify/"));
|
||||
await fs.symlink(
|
||||
require.resolve('dompurify/dist/purify.es.js'),
|
||||
path.join(libDir, "dompurify/index.js")
|
||||
);
|
||||
// transpile another-json to esm
|
||||
await fs.mkdir(path.join(libDir, "another-json/"));
|
||||
await commonjsToESM(
|
||||
|
|
38
snowpack.config.js
Normal file
38
snowpack.config.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
// Snowpack Configuration File
|
||||
// See all supported options: https://www.snowpack.dev/reference/configuration
|
||||
|
||||
/** @type {import("snowpack").SnowpackUserConfig } */
|
||||
module.exports = {
|
||||
mount: {
|
||||
// More specific paths before less specific paths (if they overlap)
|
||||
"src/platform/web/docroot": "/",
|
||||
"src": "/src",
|
||||
"lib": {url: "/lib", static: true },
|
||||
"assets": "/assets",
|
||||
/* ... */
|
||||
},
|
||||
exclude: [
|
||||
/* Avoid scanning scripts which use dev-dependencies and pull in babel, rollup, etc. */
|
||||
'**/node_modules/**/*',
|
||||
'**/scripts/**',
|
||||
'**/target/**',
|
||||
'**/prototypes/**',
|
||||
'**/src/matrix/storage/memory/**',
|
||||
'**/src/platform/web/legacy-polyfill.js',
|
||||
'**/src/platform/web/worker/polyfill.js'
|
||||
],
|
||||
plugins: [
|
||||
/* ... */
|
||||
],
|
||||
packageOptions: {
|
||||
/* ... */
|
||||
},
|
||||
devOptions: {
|
||||
open: "none",
|
||||
hmr: false,
|
||||
/* ... */
|
||||
},
|
||||
buildOptions: {
|
||||
/* ... */
|
||||
},
|
||||
};
|
|
@ -18,20 +18,26 @@ limitations under the License.
|
|||
import {EventKey} from "../EventKey.js";
|
||||
export const PENDING_FRAGMENT_ID = Number.MAX_SAFE_INTEGER;
|
||||
|
||||
interface FragmentIdComparer {
|
||||
compare: (a: number, b: number) => number
|
||||
}
|
||||
|
||||
export class BaseEntry {
|
||||
constructor(fragmentIdComparer) {
|
||||
protected _fragmentIdComparer: FragmentIdComparer
|
||||
|
||||
constructor(fragmentIdComparer: FragmentIdComparer) {
|
||||
this._fragmentIdComparer = fragmentIdComparer;
|
||||
}
|
||||
|
||||
get fragmentId() {
|
||||
get fragmentId(): number {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
get entryIndex() {
|
||||
get entryIndex(): number {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
compare(otherEntry) {
|
||||
compare(otherEntry: BaseEntry): number {
|
||||
if (this.fragmentId === otherEntry.fragmentId) {
|
||||
return this.entryIndex - otherEntry.entryIndex;
|
||||
} else if (this.fragmentId === PENDING_FRAGMENT_ID) {
|
||||
|
@ -44,9 +50,9 @@ export class BaseEntry {
|
|||
}
|
||||
}
|
||||
|
||||
asEventKey() {
|
||||
asEventKey(): EventKey {
|
||||
return new EventKey(this.fragmentId, this.entryIndex);
|
||||
}
|
||||
|
||||
updateFrom() {}
|
||||
updateFrom(other: BaseEntry) {}
|
||||
}
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {BaseEntry} from "./BaseEntry.js";
|
||||
import {BaseEntry} from "./BaseEntry";
|
||||
import {REDACTION_TYPE} from "../../common.js";
|
||||
import {createAnnotation, ANNOTATION_RELATION_TYPE, getRelationFromContent} from "../relations.js";
|
||||
import {PendingAnnotation} from "../PendingAnnotation.js";
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {BaseEntry} from "./BaseEntry.js";
|
||||
import {BaseEntry} from "./BaseEntry";
|
||||
import {Direction} from "../Direction.js";
|
||||
import {isValidFragmentId} from "../common.js";
|
||||
import {KeyLimits} from "../../../storage/common.js";
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {PENDING_FRAGMENT_ID} from "./BaseEntry.js";
|
||||
import {PENDING_FRAGMENT_ID} from "./BaseEntry";
|
||||
import {BaseEventEntry} from "./BaseEventEntry.js";
|
||||
|
||||
export class PendingEventEntry extends BaseEventEntry {
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
downloadSandbox: "assets/download-sandbox.html",
|
||||
defaultHomeServer: "matrix.org",
|
||||
// NOTE: uncomment this if you want the service worker for local development
|
||||
// serviceWorker: "sw.js",
|
||||
// serviceWorker: "service-worker.js",
|
||||
// NOTE: provide push config if you want push notifs for local development
|
||||
// see assets/config.json for what the config looks like
|
||||
// push: {...},
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import DOMPurify from "../../../lib/dompurify/index.js"
|
||||
import DOMPurify from "dompurify"
|
||||
|
||||
class HTMLParseResult {
|
||||
constructor(bodyNode) {
|
||||
|
|
1
sw.js
1
sw.js
|
@ -1 +0,0 @@
|
|||
src/platform/web/service-worker.js
|
8
tsconfig.json
Normal file
8
tsconfig.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"strictNullChecks": true,
|
||||
"noEmit": true,
|
||||
"target": "es6"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
}
|
Loading…
Reference in a new issue