Compare commits

..

27 Commits

Author SHA1 Message Date
Jamie Peabody
f3e90b7588 chore(release): 4.3.9 2022-01-19 21:49:12 +00:00
Jamie Peabody
650daaff63 fix(#161): Fixed issue with options.ignorews (#162) 2022-01-19 21:46:43 +00:00
Jamie Peabody
fdfbf8d131 chore(release): 4.3.8 2021-11-21 17:23:18 +00:00
Jamie Peabody
79cb0ddd6a refactor: Split code into individual files and tidier code (#160)
* refactor: split code into separate files

* chore: removed unused test code

* refactor: no longer depends on jQuery.extend

* docs: merged changes into CHANGELOG.md

Co-authored-by: Jamie Peabody <jpeabody@axway.com>
2021-11-21 17:22:04 +00:00
Jamie Peabody
dfdba3c020 ci: allow merge type 2021-11-21 13:56:30 +00:00
Jamie Peabody
b930b8bbd6 chore(release): 4.3.7 2021-11-21 13:19:47 +00:00
Jamie Peabody
4d5c6fa67c chore: removed unused dev-deps 2021-11-21 13:18:16 +00:00
Jamie Peabody
94bee71aea chore(release): 4.3.6 2021-11-21 13:08:27 +00:00
Jamie Peabody
08e7b9735a ci: update tag latest 2021-11-21 13:06:51 +00:00
Jamie Peabody
26cb3f7220 ci: update tag latest 2021-11-21 13:01:09 +00:00
Jamie Peabody
97dc439cd4 ci: use token 2021-11-21 12:56:32 +00:00
Jamie Peabody
51189f2155 ci: use token 2021-11-21 12:52:50 +00:00
Jamie Peabody
c8e0b8e88a ci: use token 2021-11-21 12:43:01 +00:00
Jamie Peabody
7732f9fab5 ci: update publish CI 2021-11-21 12:29:39 +00:00
Jamie Peabody
e1763b3b9d ci: update publish CI 2021-11-21 12:27:48 +00:00
Jamie Peabody
0de9e87df8 ci: added standard-version 2021-11-21 12:22:50 +00:00
Jamie Peabody
aa4d934cdd chore: removed bower.json 2021-11-21 12:21:11 +00:00
Jamie Peabody
a92b408ce5 chore(ci): added git-conventional-commits 2021-11-21 11:00:15 +00:00
Jamie Peabody
ca1df3e4d4 chore(docs): added contributing.md 2021-11-21 10:59:43 +00:00
Jamie Peabody
addc610457 chore(ci): added workflows 2021-11-21 10:59:22 +00:00
Jamie Peabody
623a93b838 fix build 2021-10-03 16:56:35 +01:00
Jamie Peabody
615e1afd97 patch(#139): fixes inline diff rendering issue with whitespace (#158)
Co-authored-by: Jamie Peabody <jpeabody@axway.com>
2021-10-03 16:49:44 +01:00
Jamie Peabody
b9bc901dd2 patch(#152): fixes resize issue when using zoom 2021-10-02 14:19:15 +01:00
Jamie Peabody
b49c9ce40f Updated README.md
Fixed tgz installation instructions.
2021-09-30 08:05:07 +01:00
Jamie Peabody
712cbe8472 patch(#151): resets the current diff when setValue, clear, lhs, or rhs are called 2021-06-23 21:57:38 +01:00
Jamie Peabody
8c541ba51c Updated changes and bumped version 2021-05-19 07:57:54 +01:00
david weil
aa36977685 Updated README options : s/ignorews/ignoreaccents/ (#149)
Fixed option name in documentation
2021-05-19 07:53:47 +01:00
32 changed files with 2319 additions and 7506 deletions

3
.git-hooks/commit-msg Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/sh
npx git-conventional-commits commit-msg-hook "$1"

48
.github/workflows/npm-publish.yaml vendored Normal file
View File

@@ -0,0 +1,48 @@
name: Publish to npm
on:
workflow_dispatch:
inputs:
tag:
description: 'NPM Tag'
required: false
default: 'next'
jobs:
tag-and-publish:
runs-on: ubuntu-latest
steps:
- name: Setup node
uses: actions/setup-node@v1
with:
node-version: 14
registry-url: https://registry.npmjs.org
- name: Git checkout
uses: actions/checkout@v2
- name: Install dependencies
run: npm install
env:
CI: true
- name: Test
run: npm run test
- name: Build
run: npm run build:dist
- name: Release
uses: oleksiyrudenko/gha-git-credentials@v2.1
with:
token: '${{ secrets.CI_TOKEN }}'
name: 'Jamie Peabody'
email: 'jamie.peabody@gmail.com'
- run: npm run release
- run: git push --follow-tags origin master
- name: Publish
run: npm publish --access public --tag ${{ github.event.inputs.tag }}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

34
.github/workflows/npm-release.yaml vendored Normal file
View File

@@ -0,0 +1,34 @@
name: Release latest on npm
on:
workflow_dispatch:
inputs:
jobs:
tag-and-publish:
runs-on: ubuntu-latest
steps:
- name: Setup node
uses: actions/setup-node@v1
with:
node-version: 10
registry-url: https://registry.npmjs.org
- name: Git checkout
uses: actions/checkout@v2
- name: Get package version
run: |
export VERSION=`cat package.json | grep '"version"' | sed -E 's/\s+"version": "(.*)",/\1/'`
echo "PKG_VERSION=$VERSION" >> $GITHUB_ENV
- name: Update dist-tag
run: npm dist-tag add mergely@${PKG_VERSION} latest
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Remove 'next' dist-tag
run: npm dist-tag rm mergely next
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

41
.github/workflows/run-tests.yaml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: Run tests
# on: [push, pull_request]
on:
push:
branches-ignore:
- 'master'
tags-ignore:
- 'v*'
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x] #, 12.x, 14.x, 15.x
name: Node.js ${{ matrix.node-version }}
steps:
- name: Git checkout
uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: npm install
env:
CI: true
- name: Test
run: npm run test
- name: Build
run: npm run build:dist

46
.versionrc Normal file
View File

@@ -0,0 +1,46 @@
{
"types": [
{
"type": "feat",
"section": "Features"
},
{
"type": "fix",
"section": "Bug Fixes"
},
{
"type": "chore",
"section": "General",
"hidden": false
},
{
"type": "style",
"section": "General",
"hidden": false
},
{
"type": "refactor",
"section": "General",
"hidden": false
},
{
"type": "perf",
"section": "General",
"hidden": false
},
{
"type": "test",
"section": "General",
"hidden": false
},
{
"type": "docs",
"section": "Documentation",
"hidden": false
},
{
"type": "ci",
"hidden": true
}
]
}

View File

@@ -1,75 +1,131 @@
# Changes
# Changelog
## 4.2.4
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### 4.3.9 (2022-01-19)
### Bug Fixes
* **#161:** Fixed issue with `options.ignorews` ([#162](https://github.com/wickedest/Mergely/issues/162)) ([650daaf](https://github.com/wickedest/Mergely/commit/650daaff63503f6426f64b12d8b33cfca6ef7185))
### 4.3.8 (2021-11-21)
### General
* Split code into individual files and tidier code ([#160](https://github.com/wickedest/Mergely/issues/160)) ([79cb0dd](https://github.com/wickedest/Mergely/commit/79cb0ddd6a07886435b0e17b0bac33416e67716d))
### 4.3.7 (2021-11-21)
### General
* removed unused dev-deps ([4d5c6fa](https://github.com/wickedest/Mergely/commit/4d5c6fa67c92dad461cfd3a7cc991e9b1ec4531b))
### 4.3.6 (2021-11-21)
### [4.3.5](https://github.com/wickedest/Mergely/compare/v4.0.13...v4.3.5) (2021-11-21)
### Features
* **#132:** added option to ignore accented characters ([#136](https://github.com/wickedest/Mergely/issues/136)) ([5a0cd15](https://github.com/wickedest/Mergely/commit/5a0cd15ddd54fdd60b42247e6f373a6a8e47d25d)), closes [#132](https://github.com/wickedest/Mergely/issues/132) [#132](https://github.com/wickedest/Mergely/issues/132)
* **#137:** added 'summary' method ([4610ed3](https://github.com/wickedest/Mergely/commit/4610ed353557300e45d98e31cf384bc996dbac58)), closes [#137](https://github.com/wickedest/Mergely/issues/137)
### General
* updated dependencies ([85b02ad](https://github.com/wickedest/Mergely/commit/85b02add899b90e4d6ced4474cfdee98838d272a))
----
### 4.3.5
* patch: fixed issue with build
### 4.3.4
* patch: Fixes inline diff rendering issue with whitespace [#139](https://github.com/wickedest/Mergely/issues/139).
### 4.3.3
* patch: Fixes resize issue when using zoom [#152](https://github.com/wickedest/Mergely/issues/152).
### 4.3.2
* patch: Reset the current change position when [setValue](https://mergely.com/doc##options_callbacks), [clear](https://mergely.com/doc#clear), [lhs](https://mergely.com/doc#lhs) or [rhs](https://mergely.com/doc#rhs) are called.
### 4.3.1
* patch: Updated README.md to fix incorrect option name.
### 4.3.0
* feat: Added `summary` method
### 4.2.4
* patch: fixes [#142](https://github.com/wickedest/Mergely/issues/142). Added README.md to examples.
## 4.2.3
### 4.2.3
* patch: fixes [#147](https://github.com/wickedest/Mergely/issues/147). Fixes the css style for the currently selected change.
## 4.2.2:
### 4.2.2:
* patch: fixes issue where initial change was not being set causing next/prev and merge actions to not work as expected.
## 4.2.1:
### 4.2.1:
* chore: updated dependencies, cleared security issues
## 4.2.0:
### 4.2.0:
* minor: added new option `ignoreaccents` to ignore accented characters.
## 4.1.2:
### 4.1.2:
* patch: fixes issue #134 where the readme had broken links.
## 4.1.1:
### 4.1.1:
* patch: fixes issue #95 where cursor was not focusing correctly on init.
## 4.1.0:
### 4.1.0:
* minor: emits 'updated' event after every change.
* patch: fixes `scrollTo` that no longer functioned after a codemirror update.
* patch: fixes `loaded` being called prematurely and after every resize, and is now is called once, after the 'updated' event.
## 4.0.16:
### 4.0.16:
* patch: fixes rendering beyond change constraint
## 4.0.15
### 4.0.15
* patch: removed unnecessary addon mark-selected
## 4.0.14
### 4.0.14
* patch: fixes issue #104 where diff text conflicted with selected text
## 4.0.13
### 4.0.13
* patch: fixed issue where `lhs_cmsettings` and `lhs_cmsettings` were ignored
* patch: updated documentation
* patch: fixed typos
* patch: fixes issue #115 merging deleted line(s) from lhs would munge rhs text
* patch: fixes two typos in README.md
## 4.0.11
### 4.0.11
* patch: fixes typo in example ajax.html
## 4.0.10
### 4.0.10
* patch: fixes bad 4.0.9 artifacts
## 4.0.9
### 4.0.9
* patch: fixes issue #106 merge edge-case with add
## 4.0.8
### 4.0.8
* chore: updated webpack
## 4.0.7
### 4.0.7
* chore: updated documentation
## 4.0.6
### 4.0.6
* patch: fixes issue #89 missing merge buttons
## 4.0.5
### 4.0.5
* patch: fixes issue #85 XSS vulnerability with DOM id
## 4.0.2
### 4.0.2
* patch: fixes issue #83 poor rendering performance
## 4.0.0
### 4.0.0
### Breaking changes

11
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,11 @@
# Contributing to Mergely
## Testing
```bash
npm run test
```
## Conventional commits
Mergely is using [conventional commits](https://www.conventionalcommits.org/en/v1.0.0), and [standard-version](https://www.npmjs.com/package/standard-version).

View File

@@ -25,8 +25,8 @@ Unpack mergely.tgz into a folder, for example, `./lib`, and add the following to
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.32.0/codemirror.min.js"></script>
<link rel="stylesheet" media="all" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.32.0/codemirror.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.32.0/addon/search/searchcursor.min.js"></script>
<script src="lib/mergely/lib/mergely.js" type="text/javascript"></script>
<link rel="stylesheet" media="all" href="lib/mergely/lib/mergely.css" />
<script src="package/lib/mergely.js" type="text/javascript"></script>
<link rel="stylesheet" media="all" href="package/lib/mergely.css" />
```
Create a div for the editor in `<body>`.
@@ -100,7 +100,7 @@ $(document).ready(function () {
|<a name="fgcolor"></a>fgcolor|string\|number\|object|`{a:'#4ba3fa', c:'#a3a3a3', d:'#ff7f7f', ca:'#4b73ff', cc:'#434343', cd:'#ff4f4f'}`|The foreground color that mergely marks changes with on the canvas. The value **a** is additions, **c** changes, **d** deletions, and the prefix *c* indicates current/active change (e.g. **cd** current delection).|
|<a name="ignorews"></a>ignorews|boolean|`false`|Ignores white-space.|
|<a name="ignorecase"></a>ignorecase|boolean|`false`|Ignores case when differientiating.|
|<a name="ignoreaccents"></a>ignorews|boolean|`false`|Ignores accented characters.|
|<a name="ignoreaccents"></a>ignoreaccents|boolean|`false`|Ignores accented characters.|
|<a name="lcs"></a>lcs|boolean|`true`|Enables/disables LCS computation for paragraphs (word-by-word changes). Disabling can give a performance gain for large documents.|
|<a name="license"></a>license|string|`lgpl`|The choice of license to use with Mergely. Valid values are: `lgpl`, `gpl`, `mpl` or `lgpl-separate-notice`, `gpl-separate-notice`, `mpl-separate-notice` (the license requirements are met in a separate notice file).|
|<a name="line_numbers"></a>line_numbers|boolean|`true`|Enables/disables line numbers. Enabling line numbers will toggle the visibility of the line number margins.|

View File

@@ -1,36 +0,0 @@
{
"name": "Mergely",
"version": "4.0.0",
"homepage": "https://github.com/wickedest/Mergely",
"description": "Merge and diff documents online",
"main": [
"lib/mergely.js",
"lib/mergely.css"
],
"keywords": [
"merge",
"diff"
],
"ignore": [
"LICENSE.html",
"README.md",
"doc",
"editor",
"examples",
"test"
],
"license": [
"GPL",
"LGPL",
"MPL"
],
"repository": {
"type": "git",
"url": "git://github.com/wickedest/Mergely"
},
"dependencies": {
"mergely": "https://github.com/wickedest/Mergely.git#3.4.3",
"jquery": "<=2.1.3",
"codemirror": "<=5.11.0"
}
}

1
commitlint.config.js Normal file
View File

@@ -0,0 +1 @@
module.exports = {extends: ['@commitlint/config-conventional']};

View File

@@ -2,18 +2,29 @@ require('codemirror/addon/selection/mark-selection.js');
require('codemirror/lib/codemirror.css');
require('../src/mergely.css');
var lhs = `\
the quick red fox
jumped over the hairy dog
`;
var rhs = `\
the quick brown fox
jumped over the lazy dog
`;
$(document).ready(function () {
$('#mergely').mergely({
license: 'lgpl',
ignorews: true,
cmsettings: {
readOnly: false
},
_debug: '',
lhs: function(setValue) {
setValue('the quick red fox\njumped over the hairy dog');
setValue(lhs);
},
rhs: function(setValue) {
setValue('the quick brown fox\njumped over the lazy dog');
setValue(rhs);
}
});
});

View File

@@ -0,0 +1,41 @@
{
"convention" : {
"commitTypes": [
"build",
"chore",
"ci",
"feat",
"fix",
"docs",
"style",
"refactor",
"perf",
"test",
"merge"
],
"commitScopes": [],
"releaseTagGlobPattern": "v[0-9].*",
"issueRegexPattern": "(^|\\s)#\\d+(\\s|$)"
},
"changelog" : {
"commitTypes": [
"feat",
"fix",
"perf",
"merge"
],
"commitIgnoreRegexPattern": "^WIP ",
"headlines": {
"feat": "Features",
"fix": "Bug Fixes",
"perf": "Performance Improvements",
"merge": "Merged Branches",
"breakingChange": "BREAKING CHANGES"
},
"commitUrl": "https://github.com/wickedest/Mergely/commit/%commit%",
"commitRangeUrl": "https://github.com/wickedest/Mergely/compare/%from%...%to%?diff=split",
"issueUrl": "https://github.com/wickedest/Mergely/issues/%issue%"
}
}

View File

@@ -1,5 +1,6 @@
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const webpackConfig = require('./webpack.dev.js');
module.exports = function(config) {
config.set({
@@ -36,32 +37,7 @@ module.exports = function(config) {
captureConsole: true,
mocha: {}
},
webpack: {
entry: './src/mergely.js',
module: {
rules: [{
test: /\.(js)$/,
exclude: /node_modules/,
use: ['babel-loader']
}]
},
resolve: {
extensions: ['.js'],
alias: {
CodeMirror: path.join(__dirname, 'node_modules', 'codemirror'),
jQuery: path.join(__dirname, 'node_modules', 'jquery')
}
},
plugins: [
new CopyWebpackPlugin({
patterns: [{
from: 'src/mergely.css',
to: 'mergely.css',
toType: 'file'
}]
})
]
},
webpack: webpackConfig,
webpackServer: {
noInfo: true
}

View File

@@ -1,6 +1,6 @@
{
"name": "mergely",
"version": "4.3.0",
"version": "4.3.9",
"description": "A javascript UI for diff/merge",
"directories": {
"doc": "doc",
@@ -36,6 +36,8 @@
"devDependencies": {
"@babel/core": "^7.1.6",
"@babel/preset-env": "^7.1.6",
"@commitlint/config-conventional": "^15.0.0",
"@commitlint/prompt-cli": "^15.0.0",
"@webpack-cli/init": "^1.0.1",
"babel-loader": "^8.0.4",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
@@ -43,9 +45,8 @@
"codemirror": "^5.50.2",
"copy-webpack-plugin": "^6.2.1",
"css-loader": "^5.0.0",
"file-loader": "^6.1.1",
"git-conventional-commits": "^1.1.0",
"html-webpack-plugin": "^4.5.0",
"image-webpack-loader": "^7.0.1",
"jquery": "^3.5.1",
"karma": "^5.2.3",
"karma-chai": "^0.1.0",
@@ -55,15 +56,18 @@
"karma-mocha-reporter": "^2.2.5",
"karma-webpack": "^4.0.2",
"mocha": "^8.1.3",
"standard-version": "^9.3.2",
"style-loader": "^2.0.0",
"webpack": "^4.44.2",
"webpack-cli": "^4.0.0",
"webpack-dev-server": "^3.11.0"
},
"scripts": {
"build": "rm -rf lib && webpack --config ./webpack.prod.js",
"build": "npm run test && npm run build:dist",
"build:dist": "rm -rf lib && webpack --config ./webpack.prod.js",
"start": "webpack serve --config webpack.dev.js",
"debug": "karma start --browsers=Chrome --single-run=false",
"test": "karma start",
"test:chrome": "karma start --browsers Chrome --singleRun=false"
"release": "standard-version -a"
}
}

28
src/diff-parser.js Normal file
View File

@@ -0,0 +1,28 @@
const changeExp = new RegExp(/(^(?![><\-])*\d+(?:,\d+)?)([acd])(\d+(?:,\d+)?)/);
function DiffParser(diff) {
const changes = [];
let change_id = 0;
// parse diff
const diff_lines = diff.split(/\n/);
for (var i = 0; i < diff_lines.length; ++i) {
if (diff_lines[i].length == 0) continue;
const change = {};
const test = changeExp.exec(diff_lines[i]);
if (test == null) continue;
// lines are zero-based
const fr = test[1].split(',');
change['lhs-line-from'] = fr[0] - 1;
if (fr.length == 1) change['lhs-line-to'] = fr[0] - 1;
else change['lhs-line-to'] = fr[1] - 1;
const to = test[3].split(',');
change['rhs-line-from'] = to[0] - 1;
if (to.length == 1) change['rhs-line-to'] = to[0] - 1;
else change['rhs-line-to'] = to[1] - 1;
change['op'] = test[2];
changes[change_id++] = change;
}
return changes;
};
module.exports = DiffParser;

1479
src/diff-view.js Normal file

File diff suppressed because one or more lines are too long

291
src/diff.js Normal file
View File

@@ -0,0 +1,291 @@
function diff(lhs, rhs, options = {}) {
const {
ignorews = false,
ignoreaccents = false,
ignorecase = false
} = options;
this.codeify = new CodeifyText(lhs, rhs, {
ignorews,
ignoreaccents,
ignorecase
});
const lhs_ctx = {
codes: this.codeify.getCodes('lhs'),
modified: {}
};
const rhs_ctx = {
codes: this.codeify.getCodes('rhs'),
modified: {}
};
const vector_d = [];
const vector_u = [];
this._lcs(lhs_ctx, 0, lhs_ctx.codes.length, rhs_ctx, 0, rhs_ctx.codes.length, vector_u, vector_d);
this._optimize(lhs_ctx);
this._optimize(rhs_ctx);
this.items = this._create_diffs(lhs_ctx, rhs_ctx);
};
diff.prototype.changes = function() {
return this.items;
};
diff.prototype.getLines = function(side) {
return this.codeify.getLines(side);
};
diff.prototype.normal_form = function() {
let nf = '';
for (let index = 0; index < this.items.length; ++index) {
const item = this.items[index];
let lhs_str = '';
let rhs_str = '';
let change = 'c';
if (item.lhs_deleted_count == 0 && item.rhs_inserted_count > 0) change = 'a';
else if (item.lhs_deleted_count > 0 && item.rhs_inserted_count == 0) change = 'd';
if (item.lhs_deleted_count == 1) lhs_str = item.lhs_start + 1;
else if (item.lhs_deleted_count == 0) lhs_str = item.lhs_start;
else lhs_str = (item.lhs_start + 1) + ',' + (item.lhs_start + item.lhs_deleted_count);
if (item.rhs_inserted_count == 1) rhs_str = item.rhs_start + 1;
else if (item.rhs_inserted_count == 0) rhs_str = item.rhs_start;
else rhs_str = (item.rhs_start + 1) + ',' + (item.rhs_start + item.rhs_inserted_count);
nf += lhs_str + change + rhs_str + '\n';
const lhs_lines = this.getLines('lhs');
const rhs_lines = this.getLines('rhs');
if (rhs_lines && lhs_lines) {
let i;
// if rhs/lhs lines have been retained, output contextual diff
for (i = item.lhs_start; i < item.lhs_start + item.lhs_deleted_count; ++i) {
nf += '< ' + lhs_lines[i] + '\n';
}
if (item.rhs_inserted_count && item.lhs_deleted_count) nf += '---\n';
for (i = item.rhs_start; i < item.rhs_start + item.rhs_inserted_count; ++i) {
nf += '> ' + rhs_lines[i] + '\n';
}
}
}
return nf;
};
diff.prototype._lcs = function(lhs_ctx, lhs_lower, lhs_upper, rhs_ctx, rhs_lower, rhs_upper, vector_u, vector_d) {
while ( (lhs_lower < lhs_upper) && (rhs_lower < rhs_upper) && (lhs_ctx.codes[lhs_lower] == rhs_ctx.codes[rhs_lower]) ) {
++lhs_lower;
++rhs_lower;
}
while ( (lhs_lower < lhs_upper) && (rhs_lower < rhs_upper) && (lhs_ctx.codes[lhs_upper - 1] == rhs_ctx.codes[rhs_upper - 1]) ) {
--lhs_upper;
--rhs_upper;
}
if (lhs_lower == lhs_upper) {
while (rhs_lower < rhs_upper) {
rhs_ctx.modified[ rhs_lower++ ] = true;
}
}
else if (rhs_lower == rhs_upper) {
while (lhs_lower < lhs_upper) {
lhs_ctx.modified[ lhs_lower++ ] = true;
}
}
else {
const sms = this._sms(lhs_ctx, lhs_lower, lhs_upper, rhs_ctx, rhs_lower, rhs_upper, vector_u, vector_d);
this._lcs(lhs_ctx, lhs_lower, sms.x, rhs_ctx, rhs_lower, sms.y, vector_u, vector_d);
this._lcs(lhs_ctx, sms.x, lhs_upper, rhs_ctx, sms.y, rhs_upper, vector_u, vector_d);
}
};
diff.prototype._sms = function(lhs_ctx, lhs_lower, lhs_upper, rhs_ctx, rhs_lower, rhs_upper, vector_u, vector_d) {
const max = lhs_ctx.codes.length + rhs_ctx.codes.length + 1;
const kdown = lhs_lower - rhs_lower;
const kup = lhs_upper - rhs_upper;
const delta = (lhs_upper - lhs_lower) - (rhs_upper - rhs_lower);
const odd = (delta & 1) != 0;
const offset_down = max - kdown;
const offset_up = max - kup;
const maxd = ((lhs_upper - lhs_lower + rhs_upper - rhs_lower) / 2) + 1;
vector_d[ offset_down + kdown + 1 ] = lhs_lower;
vector_u[ offset_up + kup - 1 ] = lhs_upper;
const ret = { x:0, y:0 }
let x;
let y;
for (let d = 0; d <= maxd; ++d) {
for (let k = kdown - d; k <= kdown + d; k += 2) {
if (k == kdown - d) {
x = vector_d[ offset_down + k + 1 ];//down
}
else {
x = vector_d[ offset_down + k - 1 ] + 1;//right
if ((k < (kdown + d)) && (vector_d[ offset_down + k + 1 ] >= x)) {
x = vector_d[ offset_down + k + 1 ];//down
}
}
y = x - k;
// find the end of the furthest reaching forward D-path in diagonal k.
while ((x < lhs_upper) && (y < rhs_upper) && (lhs_ctx.codes[x] == rhs_ctx.codes[y])) {
x++; y++;
}
vector_d[ offset_down + k ] = x;
// overlap ?
if (odd && (kup - d < k) && (k < kup + d)) {
if (vector_u[offset_up + k] <= vector_d[offset_down + k]) {
ret.x = vector_d[offset_down + k];
ret.y = vector_d[offset_down + k] - k;
return (ret);
}
}
}
// Extend the reverse path.
for (k = kup - d; k <= kup + d; k += 2) {
// find the only or better starting point
if (k == kup + d) {
x = vector_u[offset_up + k - 1]; // up
} else {
x = vector_u[offset_up + k + 1] - 1; // left
if ((k > kup - d) && (vector_u[offset_up + k - 1] < x))
x = vector_u[offset_up + k - 1]; // up
}
y = x - k;
while ((x > lhs_lower) && (y > rhs_lower) && (lhs_ctx.codes[x - 1] == rhs_ctx.codes[y - 1])) {
// diagonal
x--;
y--;
}
vector_u[offset_up + k] = x;
// overlap ?
if (!odd && (kdown - d <= k) && (k <= kdown + d)) {
if (vector_u[offset_up + k] <= vector_d[offset_down + k]) {
ret.x = vector_d[offset_down + k];
ret.y = vector_d[offset_down + k] - k;
return (ret);
}
}
}
}
throw "the algorithm should never come here.";
};
diff.prototype._optimize = function(ctx) {
let start = 0;
let end = 0;
while (start < ctx.codes.length) {
while ((start < ctx.codes.length) && (ctx.modified[start] == undefined || ctx.modified[start] == false)) {
start++;
}
end = start;
while ((end < ctx.codes.length) && (ctx.modified[end] == true)) {
end++;
}
if ((end < ctx.codes.length) && (ctx.codes[start] == ctx.codes[end])) {
ctx.modified[start] = false;
ctx.modified[end] = true;
}
else {
start = end;
}
}
};
diff.prototype._create_diffs = function(lhs_ctx, rhs_ctx) {
const items = [];
let lhs_start = 0;
let rhs_start = 0;
let lhs_line = 0;
let rhs_line = 0;
while (lhs_line < lhs_ctx.codes.length || rhs_line < rhs_ctx.codes.length) {
if ((lhs_line < lhs_ctx.codes.length) && (!lhs_ctx.modified[lhs_line])
&& (rhs_line < rhs_ctx.codes.length) && (!rhs_ctx.modified[rhs_line])) {
// equal lines
lhs_line++;
rhs_line++;
}
else {
// maybe deleted and/or inserted lines
lhs_start = lhs_line;
rhs_start = rhs_line;
while (lhs_line < lhs_ctx.codes.length && (rhs_line >= rhs_ctx.codes.length || lhs_ctx.modified[lhs_line]))
lhs_line++;
while (rhs_line < rhs_ctx.codes.length && (lhs_line >= lhs_ctx.codes.length || rhs_ctx.modified[rhs_line]))
rhs_line++;
if ((lhs_start < lhs_line) || (rhs_start < rhs_line)) {
// store a new difference-item
items.push({
lhs_start: lhs_start,
rhs_start: rhs_start,
lhs_deleted_count: lhs_line - lhs_start,
rhs_inserted_count: rhs_line - rhs_start
});
}
}
}
return items;
};
function CodeifyText(lhs, rhs, options) {
this._max_code = 0;
this._diff_codes = {};
this.ctxs = {};
this.options = options;
if (typeof lhs === 'string') {
this.lhs = lhs.split('\n');
} else {
this.lhs = lhs;
}
if (typeof rhs === 'string') {
this.rhs = rhs.split('\n');
} else {
this.rhs = rhs;
}
};
CodeifyText.prototype.getCodes = function(side) {
if (!this.ctxs.hasOwnProperty(side)) {
var ctx = this._diff_ctx(this[side]);
this.ctxs[side] = ctx;
ctx.codes.length = Object.keys(ctx.codes).length;
}
return this.ctxs[side].codes;
}
CodeifyText.prototype.getLines = function(side) {
return this.ctxs[side].lines;
}
CodeifyText.prototype._diff_ctx = function(lines) {
var ctx = {i: 0, codes: {}, lines: lines};
this._codeify(lines, ctx);
return ctx;
}
CodeifyText.prototype._codeify = function(lines, ctx) {
var code = this._max_code;
for (var i = 0; i < lines.length; ++i) {
var line = lines[i];
if (this.options.ignorews) {
line = line.replace(/\s+/g, '');
}
if (this.options.ignorecase) {
line = line.toLowerCase();
}
if (this.options.ignoreaccents) {
line = line.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
}
var aCode = this._diff_codes[line];
if (aCode != undefined) {
ctx.codes[i] = aCode;
}
else {
this._max_code++;
this._diff_codes[line] = this._max_code;
ctx.codes[i] = this._max_code;
}
}
}
module.exports = diff;

90
src/lcs.js Normal file
View File

@@ -0,0 +1,90 @@
const diff = require('./diff');
const DiffParser = require('./diff-parser');
function LCS(x, y, options) {
function getPositionOfWords(text, options) {
var exp = new RegExp(/[^\s]/g);
var map = {};
var match;
var item = 0;
var p0 = 0;
var p1;
var ws0;
while ((match = exp.exec(text))) {
// if previous ws, then calculate whether not not this should be
// included as part of the diff
if (!options.ignorews && ws0 && ws0 <= match.index - 1) {
map[ item++ ] = {
p0: ws0,
p1: match.index - 1,
ws0,
word: text.slice(ws0, match.index)
};
}
// add the words to be matched in diff
p0 = match.index;
p1 = p0 + match[0].length - 1;
ws0 = p1 + 2;
map[ item++ ] = {
p0,
p1,
ws0,
word: text.slice(p0, p1 + 1)
};
}
return map;
}
this.options = options;
if (options.ignorews) {
this.xmap = getPositionOfWords(x, this.options);
this.ymap = getPositionOfWords(y, this.options);
const xmap = this.xmap;
this.x = Object.keys(xmap).map(function (i) { return xmap[i].word; });
const ymap = this.ymap;
this.y = Object.keys(ymap).map(function (i) { return ymap[i].word; });
} else {
this.x = x.split('');
this.y = y.split('');
}
};
LCS.prototype.clear = function () {
this.ready = 0;
};
LCS.prototype.diff = function (added, removed) {
const d = new diff(this.x, this.y, {
ignorews: !!this.options.ignorews,
ignoreaccents: !!this.options.ignoreaccents
});
const changes = DiffParser(d.normal_form());
for (let i = 0; i < changes.length; ++i) {
const change = changes[i];
if (this.options.ignorews) {
if (change.op != 'a') {
const from = this.xmap[change['lhs-line-from']].p0;
const to = this.xmap[change['lhs-line-to']].p1 + 1;
removed(from, to);
}
if (change.op !== 'd') {
const from = this.ymap[change['rhs-line-from']].p0;
const to = this.ymap[change['rhs-line-to']].p1 + 1;
added(from, to);
}
} else {
if (change.op != 'a') {
const from = change['lhs-line-from'];
const to = change['lhs-line-to'] + 1;
removed(from, to);
}
if (change.op !== 'd') {
const from = change['rhs-line-from'];
const to = change['rhs-line-to'] + 1;
added(from, to);
}
}
}
};
module.exports = LCS;

File diff suppressed because one or more lines are too long

View File

@@ -4,8 +4,8 @@ class Timer {
}
static stop() {
var t1 = Date.now();
var td = t1 - Timer.t0;
const t1 = Date.now();
const td = t1 - Timer.t0;
Timer.t0 = t1;
return td;
}

View File

@@ -1,34 +0,0 @@
<!doctype html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Tests</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script type="text/javascript" src="../lib/codemirror.js"></script>
<script type="text/javascript" src="../lib/mergely.js"></script>
<script type="text/javascript" src="lib/jsunit/jsunit.js"></script>
<script type="text/javascript" src="lib/jsunit/stacktrace.js"></script>
<script type="text/javascript" src="lib/jsunit/tipTip.js"></script>
<script type="text/javascript" src="tests.js"></script>
<script type="text/javascript" src="macbeth.js"></script>
<link type="text/css" rel="stylesheet" href="../lib/codemirror.css" />
<link type="text/css" rel="stylesheet" href="../lib/mergely.css" />
<link rel="stylesheet" href="lib/jsunit/jsunit.css">
<link rel="stylesheet" href="lib/jsunit/tipTip.css">
</head>
<body>
<table id="tests">
<tr>
<th>Module</th>
<th>Test Name</th>
<th>State</th>
<th>Retry</th>
<th>Stack</th>
</tr>
</table>
</body>
</html>

View File

@@ -1,15 +0,0 @@
body { font-family: courier new; font-size: 0.75em; }
table { border-collapse: collapse; width: 100%; text-align: left; vertical-align: top; }
.stack span,
.failed span,
.passed span {
width: 60px;
display: block;
text-align: center;
font-size: 0.85em;
border-radius: 4px; -moz-border-radius: 4px; -webkit-border-radius: 4px;
}
.failed span { background-color: #FFCC66; border: 1px solid black; color: black; cursor: help; }
.passed span { background-color: #66BB66; border: 1px solid green; color: green; }
.stack span { background-color: #efefef; border: 1px solid #444; color: #444; cursor: help; }

View File

@@ -1,198 +0,0 @@
var JsUnit = (function () {
var JsUnit = {
modules : {},
config : {
onStartModule: function(module) { },
onEndModule: function(module) { },
onStartTest: function(module, test) { },
onEndTest: function(module, test) { },
onResult: function(module, test) { },
}
};
JsUnit.PASSED = 'passed';
JsUnit.FAILED = 'failed';
JsUnit._mixin = function(src, dest) {
return $.extend({}, src, dest);
}
JsUnit.module = function(name) {
this.modules[name] = {name: name, tests:[]};
this._module = name;
}
JsUnit.test = function(name, run) {
var module = this.modules[this._module];
module.tests.push({
name: name,
run: run,
assertions: []
});
}
JsUnit._assert = function(result, value, message, passed) {
var stack = [];
if (!passed) {
if (printStackTrace != undefined) {
var trace = printStackTrace();
for (key in trace) {
stack.push({
method: trace[key].split('@')[0],
location: trace[key].split('@')[1]
});
}
}
else {
console.warn('missing required library:','https://raw.github.com/eriwen/javascript-stacktrace/master/stacktrace.js');
}
}
this._running.assertions.push({
expected: value,
message: message,
stack: stack,
passed: function() { return passed; }
});
}
JsUnit.equal = function(result, value, message) {
JsUnit._assert(result, value, message || 'Result was not equal as expected', result == value);
}
JsUnit.notEqual = function(result, value, message) {
JsUnit._assert(result, value, message || 'Result did not evaluate to false as expected', result != value);
}
JsUnit.okay = function(result, message) {
JsUnit._assert(result, null, message || 'Result did not evaluate to true as expected', !(!result));
}
JsUnit.throws = function(func, message) {
try {
func();
}
catch (err) {
return;
}
JsUnit.okay(false, message || 'Did not throw as expected');
}
JsUnit.run = function(config) {
var settings = this._mixin(this.config, config);
for (var mkey in this.modules) {
var module = this.modules[mkey];
settings.onStartModule(module);
for (var tkey in module.tests) {
var test = module.tests[tkey];
var tthis = this;
test.rerun = function() {
try {
settings.onStartTest(module, this);
tthis._running = this;
this.assertions = [];
var success = true;
this.passed = function() { return success; }
this.run();
for (var akey in this.assertions) {
var assertion = this.assertions[akey];
success &= assertion.passed();
}
settings.onResult(module, this);
settings.onEndTest(module, this);
}
catch (ex) {
console.log('Exception', ex);
this.ex = ex;
success = false;
settings.onResult(module, this);
settings.onEndTest(module, this);
}
}
test.rerun();
}
settings.onEndModule(module);
}
}
JsUnit.getCurrentUrl = function(changes) {
var options = {
protocol: window.document.location.protocol,
host: window.document.location.hostname,
port: window.document.location.port,
path: window.document.location.pathname,
user: '',
pass: ''
};
options = JsUnit._mixin(options, changes);
var userpass = (options.user && options.pass) ? (options.user + ':' + options.pass + '@') : '';
if (options.protocol.substr(-1) != ':') options.protocol += ':';
return options.protocol + '//' + userpass + options.host + ':' + options.port + options.path;
}
JsUnit.include = function(file) {
if (document.createElement && document.getElementsByTagName) {
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', file);
script.setAttribute('async', 'async');
head.appendChild(script);
}
else {
console.error('Failed to include', file);
}
}
JsUnit.start = function() {
this.run({
onStartModule: function(module) {
var test;
for (var i = 0; i < module.tests.length; ++i) {
// add all the tests
test = module.tests[i];
var node = $('<tr id="' + test.name + '"><td>' + module.name + '</td><td>' + test.name + '</td><td class="state"><span class="details" title=""></span></td><td><button>retry</button></td><td class="stack"></td></tr>');
$('#tests').append(node);
// closure
(function(y) {
$('#' + y.name + ' button').click(function(){
//test = module.tests[i];
console.log('test', y.name);
console.log('test.rerun', y, y.rerun);
console.log('rerunning', y);
y.rerun();
return false;
});
})(test);
}
},
onResult: function(module, test) {
var id = '#' + test.name;
var message = '';
var stack = '';
var state = 'passed';
if (!test.passed()) {
$(id + ' .stack').html('<span>stack</span>');
state = 'failed';
if (test.ex) {
message += test.ex + '\n' + test.ex.stack;
}
for (var i in test.assertions) {
var assertion = test.assertions[i];
if (!assertion.passed()) {
message += assertion.message.replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
message += '<br />';
for (var key in assertion.stack) {
stack += assertion.stack[key].location + '<br />';
}
}
}
}
$(id + ' .state').attr('class', ' state ' + state);
$(id + ' .details').attr('title', message).html(state);
$(id + ' .stack').attr('title', stack);
$(id + ' .stack').tipTip({delay: 100, fadeIn:0, fadeOut:100, defaultPosition: 'left', maxWidth: '640px'});
$(id + ' .details').tipTip({delay: 100, fadeIn:0, fadeOut:100, defaultPosition: 'right'})
}
});
}
return JsUnit;
}());

View File

@@ -1,416 +0,0 @@
// Domain Public by Eric Wendelin http://eriwen.com/ (2008)
// Luke Smith http://lucassmith.name/ (2008)
// Loic Dachary <loic@dachary.org> (2008)
// Johan Euphrosine <proppy@aminche.com> (2008)
// Oyvind Sean Kinsey http://kinsey.no/blog (2010)
// Victor Homyakov <victor-homyakov@users.sourceforge.net> (2010)
/**
* Main function giving a function stack trace with a forced or passed in Error
*
* @cfg {Error} e The error to create a stacktrace from (optional)
* @cfg {Boolean} guess If we should try to resolve the names of anonymous functions
* @return {Array} of Strings with functions, lines, files, and arguments where possible
*/
function printStackTrace(options) {
options = options || {guess: true};
var ex = options.e || null, guess = !!options.guess;
var p = new printStackTrace.implementation(), result = p.run(ex);
return (guess) ? p.guessAnonymousFunctions(result) : result;
}
printStackTrace.implementation = function() {
};
printStackTrace.implementation.prototype = {
/**
* @param {Error} ex The error to create a stacktrace from (optional)
* @param {String} mode Forced mode (optional, mostly for unit tests)
*/
run: function(ex, mode) {
ex = ex || this.createException();
// examine exception properties w/o debugger
//for (var prop in ex) {alert("Ex['" + prop + "']=" + ex[prop]);}
mode = mode || this.mode(ex);
if (mode === 'other') {
return this.other(arguments.callee);
} else {
return this[mode](ex);
}
},
createException: function() {
try {
this.undef();
} catch (e) {
return e;
}
},
/**
* Mode could differ for different exception, e.g.
* exceptions in Chrome may or may not have arguments or stack.
*
* @return {String} mode of operation for the exception
*/
mode: function(e) {
if (e['arguments'] && e.stack) {
return 'chrome';
} else if (typeof e.message === 'string' && typeof window !== 'undefined' && window.opera) {
// e.message.indexOf("Backtrace:") > -1 -> opera
// !e.stacktrace -> opera
if (!e.stacktrace) {
return 'opera9'; // use e.message
}
// 'opera#sourceloc' in e -> opera9, opera10a
if (e.message.indexOf('\n') > -1 && e.message.split('\n').length > e.stacktrace.split('\n').length) {
return 'opera9'; // use e.message
}
// e.stacktrace && !e.stack -> opera10a
if (!e.stack) {
return 'opera10a'; // use e.stacktrace
}
// e.stacktrace && e.stack -> opera10b
if (e.stacktrace.indexOf("called from line") < 0) {
return 'opera10b'; // use e.stacktrace, format differs from 'opera10a'
}
// e.stacktrace && e.stack -> opera11
return 'opera11'; // use e.stacktrace, format differs from 'opera10a', 'opera10b'
} else if (e.stack) {
return 'firefox';
}
return 'other';
},
/**
* Given a context, function name, and callback function, overwrite it so that it calls
* printStackTrace() first with a callback and then runs the rest of the body.
*
* @param {Object} context of execution (e.g. window)
* @param {String} functionName to instrument
* @param {Function} function to call with a stack trace on invocation
*/
instrumentFunction: function(context, functionName, callback) {
context = context || window;
var original = context[functionName];
context[functionName] = function instrumented() {
callback.call(this, printStackTrace().slice(4));
return context[functionName]._instrumented.apply(this, arguments);
};
context[functionName]._instrumented = original;
},
/**
* Given a context and function name of a function that has been
* instrumented, revert the function to it's original (non-instrumented)
* state.
*
* @param {Object} context of execution (e.g. window)
* @param {String} functionName to de-instrument
*/
deinstrumentFunction: function(context, functionName) {
if (context[functionName].constructor === Function &&
context[functionName]._instrumented &&
context[functionName]._instrumented.constructor === Function) {
context[functionName] = context[functionName]._instrumented;
}
},
/**
* Given an Error object, return a formatted Array based on Chrome's stack string.
*
* @param e - Error object to inspect
* @return Array<String> of function calls, files and line numbers
*/
chrome: function(e) {
var stack = (e.stack + '\n').replace(/^\S[^\(]+?[\n$]/gm, '').
replace(/^\s+(at eval )?at\s+/gm, '').
replace(/^([^\(]+?)([\n$])/gm, '{anonymous}()@$1$2').
replace(/^Object.<anonymous>\s*\(([^\)]+)\)/gm, '{anonymous}()@$1').split('\n');
stack.pop();
return stack;
},
/**
* Given an Error object, return a formatted Array based on Firefox's stack string.
*
* @param e - Error object to inspect
* @return Array<String> of function calls, files and line numbers
*/
firefox: function(e) {
return e.stack.replace(/(?:\n@:0)?\s+$/m, '').replace(/^\(/gm, '{anonymous}(').split('\n');
},
opera11: function(e) {
// "Error thrown at line 42, column 12 in <anonymous function>() in file://localhost/G:/js/stacktrace.js:\n"
// "Error thrown at line 42, column 12 in <anonymous function: createException>() in file://localhost/G:/js/stacktrace.js:\n"
// "called from line 7, column 4 in bar(n) in file://localhost/G:/js/test/functional/testcase1.html:\n"
// "called from line 15, column 3 in file://localhost/G:/js/test/functional/testcase1.html:\n"
var ANON = '{anonymous}', lineRE = /^.*line (\d+), column (\d+)(?: in (.+))? in (\S+):$/;
var lines = e.stacktrace.split('\n'), result = [];
for (var i = 0, len = lines.length; i < len; i += 2) {
var match = lineRE.exec(lines[i]);
if (match) {
var location = match[4] + ':' + match[1] + ':' + match[2];
var fnName = match[3] || "global code";
fnName = fnName.replace(/<anonymous function: (\S+)>/, "$1").replace(/<anonymous function>/, ANON);
result.push(fnName + '@' + location + ' -- ' + lines[i + 1].replace(/^\s+/, ''));
}
}
return result;
},
opera10b: function(e) {
// "<anonymous function: run>([arguments not available])@file://localhost/G:/js/stacktrace.js:27\n" +
// "printStackTrace([arguments not available])@file://localhost/G:/js/stacktrace.js:18\n" +
// "@file://localhost/G:/js/test/functional/testcase1.html:15"
var lineRE = /^(.*)@(.+):(\d+)$/;
var lines = e.stacktrace.split('\n'), result = [];
for (var i = 0, len = lines.length; i < len; i++) {
var match = lineRE.exec(lines[i]);
if (match) {
var fnName = match[1]? (match[1] + '()') : "global code";
result.push(fnName + '@' + match[2] + ':' + match[3]);
}
}
return result;
},
/**
* Given an Error object, return a formatted Array based on Opera 10's stacktrace string.
*
* @param e - Error object to inspect
* @return Array<String> of function calls, files and line numbers
*/
opera10a: function(e) {
// " Line 27 of linked script file://localhost/G:/js/stacktrace.js\n"
// " Line 11 of inline#1 script in file://localhost/G:/js/test/functional/testcase1.html: In function foo\n"
var ANON = '{anonymous}', lineRE = /Line (\d+).*script (?:in )?(\S+)(?:: In function (\S+))?$/i;
var lines = e.stacktrace.split('\n'), result = [];
for (var i = 0, len = lines.length; i < len; i += 2) {
var match = lineRE.exec(lines[i]);
if (match) {
var fnName = match[3] || ANON;
result.push(fnName + '()@' + match[2] + ':' + match[1] + ' -- ' + lines[i + 1].replace(/^\s+/, ''));
}
}
return result;
},
// Opera 7.x-9.2x only!
opera9: function(e) {
// " Line 43 of linked script file://localhost/G:/js/stacktrace.js\n"
// " Line 7 of inline#1 script in file://localhost/G:/js/test/functional/testcase1.html\n"
var ANON = '{anonymous}', lineRE = /Line (\d+).*script (?:in )?(\S+)/i;
var lines = e.message.split('\n'), result = [];
for (var i = 2, len = lines.length; i < len; i += 2) {
var match = lineRE.exec(lines[i]);
if (match) {
result.push(ANON + '()@' + match[2] + ':' + match[1] + ' -- ' + lines[i + 1].replace(/^\s+/, ''));
}
}
return result;
},
// Safari, IE, and others
other: function(curr) {
var ANON = '{anonymous}', fnRE = /function\s*([\w\-$]+)?\s*\(/i, stack = [], fn, args, maxStackSize = 10;
while (curr && curr['arguments'] && stack.length < maxStackSize) {
fn = fnRE.test(curr.toString()) ? RegExp.$1 || ANON : ANON;
args = Array.prototype.slice.call(curr['arguments'] || []);
stack[stack.length] = fn + '(' + this.stringifyArguments(args) + ')';
curr = curr.caller;
}
return stack;
},
/**
* Given arguments array as a String, subsituting type names for non-string types.
*
* @param {Arguments} object
* @return {Array} of Strings with stringified arguments
*/
stringifyArguments: function(args) {
var result = [];
var slice = Array.prototype.slice;
for (var i = 0; i < args.length; ++i) {
var arg = args[i];
if (arg === undefined) {
result[i] = 'undefined';
} else if (arg === null) {
result[i] = 'null';
} else if (arg.constructor) {
if (arg.constructor === Array) {
if (arg.length < 3) {
result[i] = '[' + this.stringifyArguments(arg) + ']';
} else {
result[i] = '[' + this.stringifyArguments(slice.call(arg, 0, 1)) + '...' + this.stringifyArguments(slice.call(arg, -1)) + ']';
}
} else if (arg.constructor === Object) {
result[i] = '#object';
} else if (arg.constructor === Function) {
result[i] = '#function';
} else if (arg.constructor === String) {
result[i] = '"' + arg + '"';
} else if (arg.constructor === Number) {
result[i] = arg;
}
}
}
return result.join(',');
},
sourceCache: {},
/**
* @return the text from a given URL
*/
ajax: function(url) {
var req = this.createXMLHTTPObject();
if (req) {
try {
req.open('GET', url, false);
//req.overrideMimeType('text/plain');
//req.overrideMimeType('text/javascript');
req.send(null);
//return req.status == 200 ? req.responseText : '';
return req.responseText;
} catch (e) {
}
}
return '';
},
/**
* Try XHR methods in order and store XHR factory.
*
* @return <Function> XHR function or equivalent
*/
createXMLHTTPObject: function() {
var xmlhttp, XMLHttpFactories = [
function() {
return new XMLHttpRequest();
}, function() {
return new ActiveXObject('Msxml2.XMLHTTP');
}, function() {
return new ActiveXObject('Msxml3.XMLHTTP');
}, function() {
return new ActiveXObject('Microsoft.XMLHTTP');
}
];
for (var i = 0; i < XMLHttpFactories.length; i++) {
try {
xmlhttp = XMLHttpFactories[i]();
// Use memoization to cache the factory
this.createXMLHTTPObject = XMLHttpFactories[i];
return xmlhttp;
} catch (e) {
}
}
},
/**
* Given a URL, check if it is in the same domain (so we can get the source
* via Ajax).
*
* @param url <String> source url
* @return False if we need a cross-domain request
*/
isSameDomain: function(url) {
return typeof location !== "undefined" && url.indexOf(location.hostname) !== -1; // location may not be defined, e.g. when running from nodejs.
},
/**
* Get source code from given URL if in the same domain.
*
* @param url <String> JS source URL
* @return <Array> Array of source code lines
*/
getSource: function(url) {
// TODO reuse source from script tags?
if (!(url in this.sourceCache)) {
this.sourceCache[url] = this.ajax(url).split('\n');
}
return this.sourceCache[url];
},
guessAnonymousFunctions: function(stack) {
for (var i = 0; i < stack.length; ++i) {
var reStack = /\{anonymous\}\(.*\)@(.*)/,
reRef = /^(.*?)(?::(\d+))(?::(\d+))?(?: -- .+)?$/,
frame = stack[i], ref = reStack.exec(frame);
if (ref) {
var m = reRef.exec(ref[1]);
if (m) { // If falsey, we did not get any file/line information
var file = m[1], lineno = m[2], charno = m[3] || 0;
if (file && this.isSameDomain(file) && lineno) {
var functionName = this.guessAnonymousFunction(file, lineno, charno);
stack[i] = frame.replace('{anonymous}', functionName);
}
}
}
}
return stack;
},
guessAnonymousFunction: function(url, lineNo, charNo) {
var ret;
try {
ret = this.findFunctionName(this.getSource(url), lineNo);
} catch (e) {
ret = 'getSource failed with url: ' + url + ', exception: ' + e.toString();
}
return ret;
},
findFunctionName: function(source, lineNo) {
// FIXME findFunctionName fails for compressed source
// (more than one function on the same line)
// TODO use captured args
// function {name}({args}) m[1]=name m[2]=args
var reFunctionDeclaration = /function\s+([^(]*?)\s*\(([^)]*)\)/;
// {name} = function ({args}) TODO args capture
// /['"]?([0-9A-Za-z_]+)['"]?\s*[:=]\s*function(?:[^(]*)/
var reFunctionExpression = /['"]?([0-9A-Za-z_]+)['"]?\s*[:=]\s*function\b/;
// {name} = eval()
var reFunctionEvaluation = /['"]?([0-9A-Za-z_]+)['"]?\s*[:=]\s*(?:eval|new Function)\b/;
// Walk backwards in the source lines until we find
// the line which matches one of the patterns above
var code = "", line, maxLines = Math.min(lineNo, 20), m, commentPos;
for (var i = 0; i < maxLines; ++i) {
// lineNo is 1-based, source[] is 0-based
line = source[lineNo - i - 1];
commentPos = line.indexOf('//');
if (commentPos >= 0) {
line = line.substr(0, commentPos);
}
// TODO check other types of comments? Commented code may lead to false positive
if (line) {
code = line + code;
m = reFunctionExpression.exec(code);
if (m && m[1]) {
return m[1];
}
m = reFunctionDeclaration.exec(code);
if (m && m[1]) {
//return m[1] + "(" + (m[2] || "") + ")";
return m[1];
}
m = reFunctionEvaluation.exec(code);
if (m && m[1]) {
return m[1];
}
}
}
return '(?)';
}
};

View File

@@ -1,113 +0,0 @@
/* TipTip CSS - Version 1.2 */
#tiptip_holder {
display: none;
position: absolute;
top: 0;
left: 0;
z-index: 99999;
}
#tiptip_holder.tip_top {
padding-bottom: 5px;
}
#tiptip_holder.tip_bottom {
padding-top: 5px;
}
#tiptip_holder.tip_right {
padding-left: 5px;
}
#tiptip_holder.tip_left {
padding-right: 5px;
}
#tiptip_content {
font-size: 11px;
color: #fff;
text-shadow: 0 0 2px #000;
padding: 4px 8px;
border: 1px solid rgba(255,255,255,0.25);
background-color: rgb(25,25,25);
background-color: rgba(25,25,25,0.92);
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(transparent), to(#000));
border-radius: 3px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
box-shadow: 0 0 2px #ccc;
-webkit-box-shadow: 0 0 2px #ccc;
-moz-box-shadow: 0 0 2px #ccc;
}
#tiptip_arrow, #tiptip_arrow_inner {
position: absolute;
border-color: transparent;
border-style: solid;
border-width: 6px;
height: 0;
width: 0;
}
#tiptip_holder.tip_top #tiptip_arrow {
border-top-color: #fff;
border-top-color: rgba(255,255,255,0.35);
}
#tiptip_holder.tip_bottom #tiptip_arrow {
border-bottom-color: #fff;
border-bottom-color: rgba(255,255,255,0.35);
}
#tiptip_holder.tip_right #tiptip_arrow {
border-right-color: #fff;
border-right-color: rgba(255,255,255,0.35);
}
#tiptip_holder.tip_left #tiptip_arrow {
border-left-color: #fff;
border-left-color: rgba(255,255,255,0.35);
}
#tiptip_holder.tip_top #tiptip_arrow_inner {
margin-top: -7px;
margin-left: -6px;
border-top-color: rgb(25,25,25);
border-top-color: rgba(25,25,25,0.92);
}
#tiptip_holder.tip_bottom #tiptip_arrow_inner {
margin-top: -5px;
margin-left: -6px;
border-bottom-color: rgb(25,25,25);
border-bottom-color: rgba(25,25,25,0.92);
}
#tiptip_holder.tip_right #tiptip_arrow_inner {
margin-top: -6px;
margin-left: -5px;
border-right-color: rgb(25,25,25);
border-right-color: rgba(25,25,25,0.92);
}
#tiptip_holder.tip_left #tiptip_arrow_inner {
margin-top: -6px;
margin-left: -7px;
border-left-color: rgb(25,25,25);
border-left-color: rgba(25,25,25,0.92);
}
/* Webkit Hacks */
@media screen and (-webkit-min-device-pixel-ratio:0) {
#tiptip_content {
padding: 4px 8px 5px 8px;
background-color: rgba(45,45,45,0.88);
}
#tiptip_holder.tip_bottom #tiptip_arrow_inner {
border-bottom-color: rgba(45,45,45,0.88);
}
#tiptip_holder.tip_top #tiptip_arrow_inner {
border-top-color: rgba(20,20,20,0.92);
}
}

View File

@@ -1,191 +0,0 @@
/*
* TipTip
* Copyright 2010 Drew Wilson
* www.drewwilson.com
* code.drewwilson.com/entry/tiptip-jquery-plugin
*
* Version 1.3 - Updated: Mar. 23, 2010
*
* This Plug-In will create a custom tooltip to replace the default
* browser tooltip. It is extremely lightweight and very smart in
* that it detects the edges of the browser window and will make sure
* the tooltip stays within the current window size. As a result the
* tooltip will adjust itself to be displayed above, below, to the left
* or to the right depending on what is necessary to stay within the
* browser window. It is completely customizable as well via CSS.
*
* This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
(function($){
$.fn.tipTip = function(options) {
var defaults = {
activation: "hover",
keepAlive: false,
maxWidth: "200px",
edgeOffset: 3,
defaultPosition: "bottom",
delay: 400,
fadeIn: 200,
fadeOut: 200,
attribute: "title",
content: false, // HTML or String to fill TipTIp with
enter: function(){},
exit: function(){}
};
var opts = $.extend(defaults, options);
// Setup tip tip elements and render them to the DOM
if($("#tiptip_holder").length <= 0){
var tiptip_holder = $('<div id="tiptip_holder" style="max-width:'+ opts.maxWidth +';"></div>');
var tiptip_content = $('<div id="tiptip_content"></div>');
var tiptip_arrow = $('<div id="tiptip_arrow"></div>');
$("body").append(tiptip_holder.html(tiptip_content).prepend(tiptip_arrow.html('<div id="tiptip_arrow_inner"></div>')));
} else {
var tiptip_holder = $("#tiptip_holder");
var tiptip_content = $("#tiptip_content");
var tiptip_arrow = $("#tiptip_arrow");
}
return this.each(function(){
var org_elem = $(this);
if(opts.content){
var org_title = opts.content;
} else {
var org_title = org_elem.attr(opts.attribute);
}
if(org_title != ""){
if(!opts.content){
org_elem.removeAttr(opts.attribute); //remove original Attribute
}
var timeout = false;
if(opts.activation == "hover"){
org_elem.hover(function(){
active_tiptip();
}, function(){
if(!opts.keepAlive){
deactive_tiptip();
}
});
if(opts.keepAlive){
tiptip_holder.hover(function(){}, function(){
deactive_tiptip();
});
}
} else if(opts.activation == "focus"){
org_elem.focus(function(){
active_tiptip();
}).blur(function(){
deactive_tiptip();
});
} else if(opts.activation == "click"){
org_elem.click(function(){
active_tiptip();
return false;
}).hover(function(){},function(){
if(!opts.keepAlive){
deactive_tiptip();
}
});
if(opts.keepAlive){
tiptip_holder.hover(function(){}, function(){
deactive_tiptip();
});
}
}
function active_tiptip(){
opts.enter.call(this);
tiptip_content.html(org_title);
tiptip_holder.hide().removeAttr("class").css("margin","0");
tiptip_arrow.removeAttr("style");
var top = parseInt(org_elem.offset()['top']);
var left = parseInt(org_elem.offset()['left']);
var org_width = parseInt(org_elem.outerWidth());
var org_height = parseInt(org_elem.outerHeight());
var tip_w = tiptip_holder.outerWidth();
var tip_h = tiptip_holder.outerHeight();
var w_compare = Math.round((org_width - tip_w) / 2);
var h_compare = Math.round((org_height - tip_h) / 2);
var marg_left = Math.round(left + w_compare);
var marg_top = Math.round(top + org_height + opts.edgeOffset);
var t_class = "";
var arrow_top = "";
var arrow_left = Math.round(tip_w - 12) / 2;
if(opts.defaultPosition == "bottom"){
t_class = "_bottom";
} else if(opts.defaultPosition == "top"){
t_class = "_top";
} else if(opts.defaultPosition == "left"){
t_class = "_left";
} else if(opts.defaultPosition == "right"){
t_class = "_right";
}
var right_compare = (w_compare + left) < parseInt($(window).scrollLeft());
var left_compare = (tip_w + left) > parseInt($(window).width());
if((right_compare && w_compare < 0) || (t_class == "_right" && !left_compare) || (t_class == "_left" && left < (tip_w + opts.edgeOffset + 5))){
t_class = "_right";
arrow_top = Math.round(tip_h - 13) / 2;
arrow_left = -12;
marg_left = Math.round(left + org_width + opts.edgeOffset);
marg_top = Math.round(top + h_compare);
} else if((left_compare && w_compare < 0) || (t_class == "_left" && !right_compare)){
t_class = "_left";
arrow_top = Math.round(tip_h - 13) / 2;
arrow_left = Math.round(tip_w);
marg_left = Math.round(left - (tip_w + opts.edgeOffset + 5));
marg_top = Math.round(top + h_compare);
}
var top_compare = (top + org_height + opts.edgeOffset + tip_h + 8) > parseInt($(window).height() + $(window).scrollTop());
var bottom_compare = ((top + org_height) - (opts.edgeOffset + tip_h + 8)) < 0;
if(top_compare || (t_class == "_bottom" && top_compare) || (t_class == "_top" && !bottom_compare)){
if(t_class == "_top" || t_class == "_bottom"){
t_class = "_top";
} else {
t_class = t_class+"_top";
}
arrow_top = tip_h;
marg_top = Math.round(top - (tip_h + 5 + opts.edgeOffset));
} else if(bottom_compare | (t_class == "_top" && bottom_compare) || (t_class == "_bottom" && !top_compare)){
if(t_class == "_top" || t_class == "_bottom"){
t_class = "_bottom";
} else {
t_class = t_class+"_bottom";
}
arrow_top = -12;
marg_top = Math.round(top + org_height + opts.edgeOffset);
}
if(t_class == "_right_top" || t_class == "_left_top"){
marg_top = marg_top + 5;
} else if(t_class == "_right_bottom" || t_class == "_left_bottom"){
marg_top = marg_top - 5;
}
if(t_class == "_left_top" || t_class == "_left_bottom"){
marg_left = marg_left + 5;
}
tiptip_arrow.css({"margin-left": arrow_left+"px", "margin-top": arrow_top+"px"});
tiptip_holder.css({"margin-left": marg_left+"px", "margin-top": marg_top+"px"}).attr("class","tip"+t_class);
if (timeout){ clearTimeout(timeout); }
timeout = setTimeout(function(){ tiptip_holder.stop(true,true).fadeIn(opts.fadeIn); }, opts.delay);
}
function deactive_tiptip(){
opts.exit.call(this);
if (timeout){ clearTimeout(timeout); }
tiptip_holder.fadeOut(opts.fadeOut);
}
}
});
}
})(jQuery);

View File

@@ -1,31 +0,0 @@
/*
RequireJS 1.0.2 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
Available via the MIT or new BSD license.
see: http://github.com/jrburke/requirejs for details
*/
var requirejs,require,define;
(function(){function J(a){return M.call(a)==="[object Function]"}function E(a){return M.call(a)==="[object Array]"}function Z(a,c,h){for(var k in c)if(!(k in K)&&(!(k in a)||h))a[k]=c[k];return d}function N(a,c,d){a=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+a);if(d)a.originalError=d;return a}function $(a,c,d){var k,j,q;for(k=0;q=c[k];k++){q=typeof q==="string"?{name:q}:q;j=q.location;if(d&&(!j||j.indexOf("/")!==0&&j.indexOf(":")===-1))j=d+"/"+(j||q.name);a[q.name]={name:q.name,location:j||
q.name,main:(q.main||"main").replace(ea,"").replace(aa,"")}}}function V(a,c){a.holdReady?a.holdReady(c):c?a.readyWait+=1:a.ready(!0)}function fa(a){function c(b,l){var f,a;if(b&&b.charAt(0)===".")if(l){p.pkgs[l]?l=[l]:(l=l.split("/"),l=l.slice(0,l.length-1));f=b=l.concat(b.split("/"));var c;for(a=0;c=f[a];a++)if(c===".")f.splice(a,1),a-=1;else if(c==="..")if(a===1&&(f[2]===".."||f[0]===".."))break;else a>0&&(f.splice(a-1,2),a-=2);a=p.pkgs[f=b[0]];b=b.join("/");a&&b===f+"/"+a.main&&(b=f)}else b.indexOf("./")===
0&&(b=b.substring(2));return b}function h(b,l){var f=b?b.indexOf("!"):-1,a=null,d=l?l.name:null,i=b,e,h;f!==-1&&(a=b.substring(0,f),b=b.substring(f+1,b.length));a&&(a=c(a,d));b&&(a?e=(f=m[a])&&f.normalize?f.normalize(b,function(b){return c(b,d)}):c(b,d):(e=c(b,d),h=E[e],h||(h=g.nameToUrl(e,null,l),E[e]=h)));return{prefix:a,name:e,parentMap:l,url:h,originalName:i,fullName:a?a+"!"+(e||""):e}}function k(){var b=!0,l=p.priorityWait,f,a;if(l){for(a=0;f=l[a];a++)if(!s[f]){b=!1;break}b&&delete p.priorityWait}return b}
function j(b,l,f){return function(){var a=ga.call(arguments,0),c;if(f&&J(c=a[a.length-1]))c.__requireJsBuild=!0;a.push(l);return b.apply(null,a)}}function q(b,l){var a=j(g.require,b,l);Z(a,{nameToUrl:j(g.nameToUrl,b),toUrl:j(g.toUrl,b),defined:j(g.requireDefined,b),specified:j(g.requireSpecified,b),isBrowser:d.isBrowser});return a}function o(b){var l,a,c,C=b.callback,i=b.map,e=i.fullName,ba=b.deps;c=b.listeners;if(C&&J(C)){if(p.catchError.define)try{a=d.execCb(e,b.callback,ba,m[e])}catch(k){l=k}else a=
d.execCb(e,b.callback,ba,m[e]);if(e)(C=b.cjsModule)&&C.exports!==void 0&&C.exports!==m[e]?a=m[e]=b.cjsModule.exports:a===void 0&&b.usingExports?a=m[e]:(m[e]=a,F[e]&&(Q[e]=!0))}else e&&(a=m[e]=C,F[e]&&(Q[e]=!0));if(D[b.id])delete D[b.id],b.isDone=!0,g.waitCount-=1,g.waitCount===0&&(I=[]);delete R[e];if(d.onResourceLoad&&!b.placeholder)d.onResourceLoad(g,i,b.depArray);if(l)return a=(e?h(e).url:"")||l.fileName||l.sourceURL,c=l.moduleTree,l=N("defineerror",'Error evaluating module "'+e+'" at location "'+
a+'":\n'+l+"\nfileName:"+a+"\nlineNumber: "+(l.lineNumber||l.line),l),l.moduleName=e,l.moduleTree=c,d.onError(l);for(l=0;C=c[l];l++)C(a)}function r(b,a){return function(f){b.depDone[a]||(b.depDone[a]=!0,b.deps[a]=f,b.depCount-=1,b.depCount||o(b))}}function u(b,a){var f=a.map,c=f.fullName,h=f.name,i=L[b]||(L[b]=m[b]),e;if(!a.loading)a.loading=!0,e=function(b){a.callback=function(){return b};o(a);s[a.id]=!0;w()},e.fromText=function(b,a){var l=O;s[b]=!1;g.scriptCount+=1;g.fake[b]=!0;l&&(O=!1);d.exec(a);
l&&(O=!0);g.completeLoad(b)},c in m?e(m[c]):i.load(h,q(f.parentMap,!0),e,p)}function v(b){D[b.id]||(D[b.id]=b,I.push(b),g.waitCount+=1)}function B(b){this.listeners.push(b)}function t(b,a){var f=b.fullName,c=b.prefix,d=c?L[c]||(L[c]=m[c]):null,i,e;f&&(i=R[f]);if(!i&&(e=!0,i={id:(c&&!d?M++ +"__p@:":"")+(f||"__r@"+M++),map:b,depCount:0,depDone:[],depCallbacks:[],deps:[],listeners:[],add:B},y[i.id]=!0,f&&(!c||L[c])))R[f]=i;c&&!d?(f=t(h(c),!0),f.add(function(){var a=h(b.originalName,b.parentMap),a=t(a,
!0);i.placeholder=!0;a.add(function(b){i.callback=function(){return b};o(i)})})):e&&a&&(s[i.id]=!1,g.paused.push(i),v(i));return i}function x(b,a,f,c){var b=h(b,c),d=b.name,i=b.fullName,e=t(b),k=e.id,j=e.deps,n;if(i){if(i in m||s[k]===!0||i==="jquery"&&p.jQuery&&p.jQuery!==f().fn.jquery)return;y[k]=!0;s[k]=!0;i==="jquery"&&f&&S(f())}e.depArray=a;e.callback=f;for(f=0;f<a.length;f++)if(k=a[f])k=h(k,d?b:c),n=k.fullName,a[f]=n,n==="require"?j[f]=q(b):n==="exports"?(j[f]=m[i]={},e.usingExports=!0):n===
"module"?e.cjsModule=j[f]={id:d,uri:d?g.nameToUrl(d,null,c):void 0,exports:m[i]}:n in m&&!(n in D)&&(!(i in F)||i in F&&Q[n])?j[f]=m[n]:(i in F&&(F[n]=!0,delete m[n],T[k.url]=!1),e.depCount+=1,e.depCallbacks[f]=r(e,f),t(k,!0).add(e.depCallbacks[f]));e.depCount?v(e):o(e)}function n(b){x.apply(null,b)}function z(b,a){if(!b.isDone){var c=b.map.fullName,d=b.depArray,g,i,e,k;if(c){if(a[c])return m[c];a[c]=!0}if(d)for(g=0;g<d.length;g++)if(i=d[g])if((e=h(i).prefix)&&(k=D[e])&&z(k,a),(e=D[i])&&!e.isDone&&
s[i])i=z(e,a),b.depCallbacks[g](i);return c?m[c]:void 0}}function A(){var b=p.waitSeconds*1E3,a=b&&g.startTime+b<(new Date).getTime(),b="",c=!1,h=!1,j;if(!(g.pausedCount>0)){if(p.priorityWait)if(k())w();else return;for(j in s)if(!(j in K)&&(c=!0,!s[j]))if(a)b+=j+" ";else{h=!0;break}if(c||g.waitCount){if(a&&b)return j=N("timeout","Load timeout for modules: "+b),j.requireType="timeout",j.requireModules=b,d.onError(j);if(h||g.scriptCount){if((G||ca)&&!W)W=setTimeout(function(){W=0;A()},50)}else{if(g.waitCount){for(H=
0;b=I[H];H++)z(b,{});g.paused.length&&w();X<5&&(X+=1,A())}X=0;d.checkReadyState()}}}}var g,w,p={waitSeconds:7,baseUrl:"./",paths:{},pkgs:{},catchError:{}},P=[],y={require:!0,exports:!0,module:!0},E={},m={},s={},D={},I=[],T={},M=0,R={},L={},F={},Q={},Y=0;S=function(b){if(!g.jQuery&&(b=b||(typeof jQuery!=="undefined"?jQuery:null))&&!(p.jQuery&&b.fn.jquery!==p.jQuery)&&("holdReady"in b||"readyWait"in b))if(g.jQuery=b,n(["jquery",[],function(){return jQuery}]),g.scriptCount)V(b,!0),g.jQueryIncremented=
!0};w=function(){var b,a,c,h,j,i;Y+=1;if(g.scriptCount<=0)g.scriptCount=0;for(;P.length;)if(b=P.shift(),b[0]===null)return d.onError(N("mismatch","Mismatched anonymous define() module: "+b[b.length-1]));else n(b);if(!p.priorityWait||k())for(;g.paused.length;){j=g.paused;g.pausedCount+=j.length;g.paused=[];for(h=0;b=j[h];h++)a=b.map,c=a.url,i=a.fullName,a.prefix?u(a.prefix,b):!T[c]&&!s[i]&&(d.load(g,i,c),c.indexOf("empty:")!==0&&(T[c]=!0));g.startTime=(new Date).getTime();g.pausedCount-=j.length}Y===
1&&A();Y-=1};g={contextName:a,config:p,defQueue:P,waiting:D,waitCount:0,specified:y,loaded:s,urlMap:E,urlFetched:T,scriptCount:0,defined:m,paused:[],pausedCount:0,plugins:L,needFullExec:F,fake:{},fullExec:Q,managerCallbacks:R,makeModuleMap:h,normalize:c,configure:function(b){var a,c,d;b.baseUrl&&b.baseUrl.charAt(b.baseUrl.length-1)!=="/"&&(b.baseUrl+="/");a=p.paths;d=p.pkgs;Z(p,b,!0);if(b.paths){for(c in b.paths)c in K||(a[c]=b.paths[c]);p.paths=a}if((a=b.packagePaths)||b.packages){if(a)for(c in a)c in
K||$(d,a[c],c);b.packages&&$(d,b.packages);p.pkgs=d}if(b.priority)c=g.requireWait,g.requireWait=!1,g.takeGlobalQueue(),w(),g.require(b.priority),w(),g.requireWait=c,p.priorityWait=b.priority;if(b.deps||b.callback)g.require(b.deps||[],b.callback)},requireDefined:function(b,a){return h(b,a).fullName in m},requireSpecified:function(b,a){return h(b,a).fullName in y},require:function(b,c,f){if(typeof b==="string"){if(J(c))return d.onError(N("requireargs","Invalid require call"));if(d.get)return d.get(g,
b,c);c=h(b,c);b=c.fullName;return!(b in m)?d.onError(N("notloaded","Module name '"+c.fullName+"' has not been loaded yet for context: "+a)):m[b]}(b&&b.length||c)&&x(null,b,c,f);if(!g.requireWait)for(;!g.scriptCount&&g.paused.length;)g.takeGlobalQueue(),w();return g.require},takeGlobalQueue:function(){U.length&&(ha.apply(g.defQueue,[g.defQueue.length-1,0].concat(U)),U=[])},completeLoad:function(b){var a;for(g.takeGlobalQueue();P.length;)if(a=P.shift(),a[0]===null){a[0]=b;break}else if(a[0]===b)break;
else n(a),a=null;a?n(a):n([b,[],b==="jquery"&&typeof jQuery!=="undefined"?function(){return jQuery}:null]);S();d.isAsync&&(g.scriptCount-=1);w();d.isAsync||(g.scriptCount-=1)},toUrl:function(a,c){var d=a.lastIndexOf("."),h=null;d!==-1&&(h=a.substring(d,a.length),a=a.substring(0,d));return g.nameToUrl(a,h,c)},nameToUrl:function(a,h,f){var j,k,i,e,m=g.config,a=c(a,f&&f.fullName);if(d.jsExtRegExp.test(a))h=a+(h?h:"");else{j=m.paths;k=m.pkgs;f=a.split("/");for(e=f.length;e>0;e--)if(i=f.slice(0,e).join("/"),
j[i]){f.splice(0,e,j[i]);break}else if(i=k[i]){a=a===i.name?i.location+"/"+i.main:i.location;f.splice(0,e,a);break}h=f.join("/")+(h||".js");h=(h.charAt(0)==="/"||h.match(/^\w+:/)?"":m.baseUrl)+h}return m.urlArgs?h+((h.indexOf("?")===-1?"?":"&")+m.urlArgs):h}};g.jQueryCheck=S;g.resume=w;return g}function ia(){var a,c,d;if(n&&n.readyState==="interactive")return n;a=document.getElementsByTagName("script");for(c=a.length-1;c>-1&&(d=a[c]);c--)if(d.readyState==="interactive")return n=d;return null}var ja=
/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,ka=/require\(\s*["']([^'"\s]+)["']\s*\)/g,ea=/^\.\//,aa=/\.js$/,M=Object.prototype.toString,r=Array.prototype,ga=r.slice,ha=r.splice,G=!!(typeof window!=="undefined"&&navigator&&document),ca=!G&&typeof importScripts!=="undefined",la=G&&navigator.platform==="PLAYSTATION 3"?/^complete$/:/^(complete|loaded)$/,da=typeof opera!=="undefined"&&opera.toString()==="[object Opera]",K={},t={},U=[],n=null,X=0,O=!1,d,r={},I,v,x,y,u,z,A,H,B,S,W;if(typeof define==="undefined"){if(typeof requirejs!==
"undefined")if(J(requirejs))return;else r=requirejs,requirejs=void 0;typeof require!=="undefined"&&!J(require)&&(r=require,require=void 0);d=requirejs=function(a,c,d){var k="_",j;!E(a)&&typeof a!=="string"&&(j=a,E(c)?(a=c,c=d):a=[]);if(j&&j.context)k=j.context;d=t[k]||(t[k]=fa(k));j&&d.configure(j);return d.require(a,c)};d.config=function(a){return d(a)};require||(require=d);d.toUrl=function(a){return t._.toUrl(a)};d.version="1.0.2";d.jsExtRegExp=/^\/|:|\?|\.js$/;v=d.s={contexts:t,skipAsync:{}};if(d.isAsync=
d.isBrowser=G)if(x=v.head=document.getElementsByTagName("head")[0],y=document.getElementsByTagName("base")[0])x=v.head=y.parentNode;d.onError=function(a){throw a;};d.load=function(a,c,h){d.resourcesReady(!1);a.scriptCount+=1;d.attach(h,a,c);if(a.jQuery&&!a.jQueryIncremented)V(a.jQuery,!0),a.jQueryIncremented=!0};define=function(a,c,d){var k,j;typeof a!=="string"&&(d=c,c=a,a=null);E(c)||(d=c,c=[]);!c.length&&J(d)&&d.length&&(d.toString().replace(ja,"").replace(ka,function(a,d){c.push(d)}),c=(d.length===
1?["require"]:["require","exports","module"]).concat(c));if(O&&(k=I||ia()))a||(a=k.getAttribute("data-requiremodule")),j=t[k.getAttribute("data-requirecontext")];(j?j.defQueue:U).push([a,c,d])};define.amd={multiversion:!0,plugins:!0,jQuery:!0};d.exec=function(a){return eval(a)};d.execCb=function(a,c,d,k){return c.apply(k,d)};d.addScriptToDom=function(a){I=a;y?x.insertBefore(a,y):x.appendChild(a);I=null};d.onScriptLoad=function(a){var c=a.currentTarget||a.srcElement,h;if(a.type==="load"||c&&la.test(c.readyState))n=
null,a=c.getAttribute("data-requirecontext"),h=c.getAttribute("data-requiremodule"),t[a].completeLoad(h),c.detachEvent&&!da?c.detachEvent("onreadystatechange",d.onScriptLoad):c.removeEventListener("load",d.onScriptLoad,!1)};d.attach=function(a,c,h,k,j,n){var o;if(G)return k=k||d.onScriptLoad,o=c&&c.config&&c.config.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script"),o.type=j||"text/javascript",o.charset="utf-8",o.async=!v.skipAsync[a],c&&o.setAttribute("data-requirecontext",
c.contextName),o.setAttribute("data-requiremodule",h),o.attachEvent&&!da?(O=!0,n?o.onreadystatechange=function(){if(o.readyState==="loaded")o.onreadystatechange=null,o.attachEvent("onreadystatechange",k),n(o)}:o.attachEvent("onreadystatechange",k)):o.addEventListener("load",k,!1),o.src=a,n||d.addScriptToDom(o),o;else ca&&(importScripts(a),c.completeLoad(h));return null};if(G){u=document.getElementsByTagName("script");for(H=u.length-1;H>-1&&(z=u[H]);H--){if(!x)x=z.parentNode;if(A=z.getAttribute("data-main")){if(!r.baseUrl)u=
A.split("/"),z=u.pop(),u=u.length?u.join("/")+"/":"./",r.baseUrl=u,A=z.replace(aa,"");r.deps=r.deps?r.deps.concat(A):[A];break}}}d.checkReadyState=function(){var a=v.contexts,c;for(c in a)if(!(c in K)&&a[c].waitCount)return;d.resourcesReady(!0)};d.resourcesReady=function(a){var c,h;d.resourcesDone=a;if(d.resourcesDone)for(h in a=v.contexts,a)if(!(h in K)&&(c=a[h],c.jQueryIncremented))V(c.jQuery,!1),c.jQueryIncremented=!1};d.pageLoaded=function(){if(document.readyState!=="complete")document.readyState=
"complete"};if(G&&document.addEventListener&&!document.readyState)document.readyState="loading",window.addEventListener("load",d.pageLoaded,!1);d(r);if(d.isAsync&&typeof setTimeout!=="undefined")B=v.contexts[r.context||"_"],B.requireWait=!0,setTimeout(function(){B.requireWait=!1;B.takeGlobalQueue();B.jQueryCheck();B.scriptCount||B.resume();d.checkReadyState()},0)}})();

View File

@@ -1,11 +0,0 @@
/*
RequireJS text 0.27.0 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
Available via the MIT or new BSD license.
see: http://github.com/jrburke/requirejs for details
*/
(function(){var k=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"],n=/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,o=/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im,i=typeof location!=="undefined"&&location.href,p=i&&location.protocol&&location.protocol.replace(/\:/,""),q=i&&location.hostname,r=i&&(location.port||void 0),j=[];define(function(){var g,h,l;typeof window!=="undefined"&&window.navigator&&window.document?h=function(a,b){var c=g.createXhr();c.open("GET",a,!0);c.onreadystatechange=
function(){c.readyState===4&&b(c.responseText)};c.send(null)}:typeof process!=="undefined"&&process.versions&&process.versions.node?(l=require.nodeRequire("fs"),h=function(a,b){b(l.readFileSync(a,"utf8"))}):typeof Packages!=="undefined"&&(h=function(a,b){var c=new java.io.File(a),e=java.lang.System.getProperty("line.separator"),c=new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(c),"utf-8")),d,f,g="";try{d=new java.lang.StringBuffer;(f=c.readLine())&&f.length()&&
f.charAt(0)===65279&&(f=f.substring(1));for(d.append(f);(f=c.readLine())!==null;)d.append(e),d.append(f);g=String(d.toString())}finally{c.close()}b(g)});return g={version:"0.27.0",strip:function(a){if(a){var a=a.replace(n,""),b=a.match(o);b&&(a=b[1])}else a="";return a},jsEscape:function(a){return a.replace(/(['\\])/g,"\\$1").replace(/[\f]/g,"\\f").replace(/[\b]/g,"\\b").replace(/[\n]/g,"\\n").replace(/[\t]/g,"\\t").replace(/[\r]/g,"\\r")},createXhr:function(){var a,b,c;if(typeof XMLHttpRequest!==
"undefined")return new XMLHttpRequest;else for(b=0;b<3;b++){c=k[b];try{a=new ActiveXObject(c)}catch(e){}if(a){k=[c];break}}if(!a)throw Error("createXhr(): XMLHttpRequest not available");return a},get:h,parseName:function(a){var b=!1,c=a.indexOf("."),e=a.substring(0,c),a=a.substring(c+1,a.length),c=a.indexOf("!");c!==-1&&(b=a.substring(c+1,a.length),b=b==="strip",a=a.substring(0,c));return{moduleName:e,ext:a,strip:b}},xdRegExp:/^((\w+)\:)?\/\/([^\/\\]+)/,useXhr:function(a,b,c,e){var d=g.xdRegExp.exec(a),
f;if(!d)return!0;a=d[2];d=d[3];d=d.split(":");f=d[1];d=d[0];return(!a||a===b)&&(!d||d===c)&&(!f&&!d||f===e)},finishLoad:function(a,b,c,e,d){c=b?g.strip(c):c;d.isBuild&&d.inlineText&&(j[a]=c);e(c)},load:function(a,b,c,e){var d=g.parseName(a),f=d.moduleName+"."+d.ext,m=b.toUrl(f),h=e&&e.text&&e.text.useXhr||g.useXhr;!i||h(m,p,q,r)?g.get(m,function(b){g.finishLoad(a,d.strip,b,c,e)}):b([f],function(a){g.finishLoad(d.moduleName+"."+d.ext,d.strip,a,c,e)})},write:function(a,b,c){if(b in j){var e=g.jsEscape(j[b]);
c.asModule(a+"!"+b,"define(function () { return '"+e+"';});\n")}},writeFile:function(a,b,c,e,d){var b=g.parseName(b),f=b.moduleName+"."+b.ext,h=c.toUrl(b.moduleName+"."+b.ext)+".js";g.load(f,c,function(){var b=function(a){return e(h,a)};b.asModule=function(a,b){return e.asModule(a,h,b)};g.write(a,f,b,d)},d)}}})})();

File diff suppressed because it is too large Load Diff

View File

@@ -1,25 +0,0 @@
require.config({
paths: {
'codemirror': '../lib/codemirror',
'mergely': '../lib/mergely',
'jsunit': 'lib/jsunit/jsunit'
}
});
var OPTIONS = {debug:false};
require([
'codemirror',
'mergely',
'jsunit',
//test modules
'tests',
], function(
mergely,
codemirror,
JsUnit,
tests
){
tests();
JsUnit.start();
});

File diff suppressed because it is too large Load Diff

View File

@@ -10,6 +10,38 @@ const $ = jQuery;
}
})(jQuery);
const defaultOptions = {
autoupdate: true,
autoresize: true,
rhs_margin: 'right',
wrap_lines: false,
line_numbers: true,
lcs: true,
sidebar: true,
viewport: false,
ignorews: false,
ignorecase: false,
ignoreaccents: false,
fadein: 'fast',
resize_timeout: 500,
change_timeout: 150,
fgcolor: {
a: '#4ba3fa',
c: '#a3a3a3',
d: '#ff7f7f',
ca: '#4b73ff',
cc: '#434343',
cd: '#ff4f4f'
},
bgcolor: '#eee',
vpcolor: 'rgba(0, 0, 200, 0.5)',
license: '',
width: 'auto',
height: 'auto',
cmsettings: {
styleSelectedText: true
}
};
describe('mergely', function () {
function init(options) {
@@ -97,6 +129,54 @@ describe('mergely', function () {
done();
});
});
it('initializes with default options', function (done) {
$(document).ready(() => {
const editor = init();
const el = $('#mergely');
const options = el.mergely('options');
expect(options).to.deep.include(defaultOptions);
expect(options.lhs).to.be.a('function');
expect(options.rhs).to.be.a('function');
expect(options.loaded).to.be.a('function');
expect(options.resize).to.be.a('function');
expect(options.resized).to.be.a('function');
done();
});
});
it('initializes with options', function (done) {
$(document).ready(() => {
const userOptions = {
autoupdate: false,
fgcolor: {
a: 'red',
c: 'green',
d: 'blue'
},
cmsettings: {
lineSeparator: '\n',
readOnly: true
},
rhs_cmsettings: {
readOnly: false
}
};
const editor = init(userOptions);
const el = $('#mergely');
const options = el.mergely('options');
expect(options).to.deep.include({
...defaultOptions,
...userOptions
});
expect(options.lhs).to.be.a('function');
expect(options.rhs).to.be.a('function');
expect(options.loaded).to.be.a('function');
expect(options.resize).to.be.a('function');
expect(options.resized).to.be.a('function');
done();
});
});
});
describe('get', () => {
@@ -625,7 +705,6 @@ describe('mergely', function () {
const { mergely } = $('#mergely');
$('#mergely').on('updated', () => {
console.log('updated');
const diff = $('#mergely').mergely('diff');;
expect(diff).to.equal('');
done();