Merge branch 'staging' into front-page

pull/1/head
Caleb James DeLisle 7 years ago
commit ffb5e555a0

@ -1,16 +1,11 @@
node_modules/ node_modules/
www/bower_components/ www/bower_components/
www/code/codemirror* www/common/pdfjs/
www/common/chainpad.js
storage/kad.js
www/common/otaml.js
server.js server.js
NetFluxWebsocketSrv.js
NetFluxWebsocketServer.js
WebRTCSrv.js
www/common/media-tag.js www/common/media-tag.js
www/scratch www/scratch
www/common/toolbar.js www/common/toolbar.js
www/common/hyperscript.js www/common/hyperscript.js
www/common/tippy.min.js

@ -25,7 +25,7 @@ module.exports = {
"default-src 'none'", "default-src 'none'",
"style-src 'unsafe-inline' 'self'", "style-src 'unsafe-inline' 'self'",
"script-src 'self'", "script-src 'self'",
"font-src 'self'", "font-src 'self' data:",
/* child-src is used to restrict iframes to a set of allowed domains. /* child-src is used to restrict iframes to a set of allowed domains.
* connect-src is used to restrict what domains can connect to the websocket. * connect-src is used to restrict what domains can connect to the websocket.
@ -67,7 +67,7 @@ module.exports = {
"connect-src 'self' ws: wss:", "connect-src 'self' ws: wss:",
// (insecure remote) images are included by users of the wysiwyg who embed photos in their pads // (insecure remote) images are included by users of the wysiwyg who embed photos in their pads
"img-src *", "img-src * blob:",
].join('; '), ].join('; '),
httpPort: 3000, httpPort: 3000,

@ -2,7 +2,7 @@
<html class="cp"> <html class="cp">
<!-- If this file is not called customize.dist/src/template.html, it is generated --> <!-- If this file is not called customize.dist/src/template.html, it is generated -->
<head> <head>
<title data-localization="main_title">Cryptpad: Zero Knowledge, Collaborative Real Time Editing</title> <title data-localization="main_title">CryptPad: Zero Knowledge, Collaborative Real Time Editing</title>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/> <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/> <link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/>

@ -4,8 +4,8 @@ define(function() {
/* Select the buttons displayed on the main page to create new collaborative sessions /* Select the buttons displayed on the main page to create new collaborative sessions
* Existing types : pad, code, poll, slide * Existing types : pad, code, poll, slide
*/ */
config.availablePadTypes = ['drive', 'pad', 'code', 'slide', 'poll', 'whiteboard', 'file']; config.availablePadTypes = ['drive', 'pad', 'code', 'slide', 'poll', 'whiteboard', 'file', 'contacts'];
config.registeredOnlyTypes = ['file']; config.registeredOnlyTypes = ['file', 'contacts'];
/* Cryptpad apps use a common API to display notifications to users /* Cryptpad apps use a common API to display notifications to users
* by default, notifications are hidden after 5 seconds * by default, notifications are hidden after 5 seconds

@ -2,7 +2,7 @@
<html class="cp"> <html class="cp">
<!-- If this file is not called customize.dist/src/template.html, it is generated --> <!-- If this file is not called customize.dist/src/template.html, it is generated -->
<head> <head>
<title data-localization="main_title">Cryptpad: Zero Knowledge, Collaborative Real Time Editing</title> <title data-localization="main_title">CryptPad: Zero Knowledge, Collaborative Real Time Editing</title>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/> <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/> <link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/>

@ -34,7 +34,8 @@ define([
// User admin menu // User admin menu
var $userMenu = $('#user-menu'); var $userMenu = $('#user-menu');
var userMenuCfg = { var userMenuCfg = {
$initBlock: $userMenu $initBlock: $userMenu,
'static': true
}; };
var $userAdmin = Cryptpad.createUserAdminMenu(userMenuCfg); var $userAdmin = Cryptpad.createUserAdminMenu(userMenuCfg);
$userAdmin.find('button').addClass('btn').addClass('btn-secondary'); $userAdmin.find('button').addClass('btn').addClass('btn-secondary');

@ -2,7 +2,7 @@
<html class="cp"> <html class="cp">
<!-- If this file is not called customize.dist/src/template.html, it is generated --> <!-- If this file is not called customize.dist/src/template.html, it is generated -->
<head> <head>
<title data-localization="main_title">Cryptpad: Zero Knowledge, Collaborative Real Time Editing</title> <title data-localization="main_title">CryptPad: Zero Knowledge, Collaborative Real Time Editing</title>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/> <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/> <link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/>

@ -46,6 +46,7 @@ define(req, function($, Default, Language) {
} }
messages._languages = map; messages._languages = map;
messages._languageUsed = language;
messages._checkTranslationState = function (cb) { messages._checkTranslationState = function (cb) {
if (typeof(cb) !== "function") { return; } if (typeof(cb) !== "function") { return; }

@ -162,7 +162,7 @@ define([
]) ])
]), ]),
h('button.btn.btn-secondary.login.half.first', Msg.login_login), h('button.btn.btn-secondary.login.half.first', Msg.login_login),
h('button.btn.btn-success.register.half.first', Msg.login_register), h('button.btn.btn-success.register.half', Msg.login_register),
h('p.separator', Msg.login_orNoLogin), h('p.separator', Msg.login_orNoLogin),
h('p#buttons.buttons'), h('p#buttons.buttons'),
h('p.driveLink', [ h('p.driveLink', [
@ -287,18 +287,10 @@ define([
}; };
loadingScreen = loadingScreen; // TODO use this loadingScreen = loadingScreen; // TODO use this
Pages['/settings/'] = Pages['/settings/index.html'] = function () {
return h('div#container');
};
Pages['/user/'] = Pages['/user/index.html'] = function () { Pages['/user/'] = Pages['/user/index.html'] = function () {
return h('div#container'); return h('div#container');
}; };
Pages['/profile/'] = Pages['/profile/index.html'] = function () {
return h('div#container');
};
Pages['/register/'] = Pages['/register/index.html'] = function () { Pages['/register/'] = Pages['/register/index.html'] = function () {
return [h('div#main', [ return [h('div#main', [
h('div.mainOverlay'), h('div.mainOverlay'),
@ -372,7 +364,7 @@ define([
h('button.btn.btn-primary.login.first', Msg.login_login), h('button.btn.btn-primary.login.first', Msg.login_login),
h('div.extra', [ h('div.extra', [
h('p', Msg.login_notRegistered), h('p', Msg.login_notRegistered),
h('button#register.btn.btn-success.register.first', Msg.login_register) h('button#register.btn.btn-success.register', Msg.login_register)
]) ])
]) ])
]) ])
@ -498,6 +490,10 @@ define([
return loadingScreen(); return loadingScreen();
}; };
Pages['/contacts/'] = Pages['/contacts/index.html'] = function () {
return loadingScreen();
};
Pages['/pad/'] = Pages['/pad/index.html'] = function () { Pages['/pad/'] = Pages['/pad/index.html'] = function () {
return loadingScreen(); return loadingScreen();
}; };
@ -510,5 +506,25 @@ define([
return loadingScreen(); return loadingScreen();
}; };
Pages['/invite/'] = Pages['/invite/index.html'] = function () {
return loadingScreen();
};
Pages['/settings/'] = Pages['/settings/index.html'] = function () {
return [
h('div#toolbar'),
h('div#container'),
loadingScreen()
];
};
Pages['/profile/'] = Pages['/profile/index.html'] = function () {
return [
h('div#toolbar'),
h('div#container'),
loadingScreen()
];
};
return Pages; return Pages;
}); });

@ -2,7 +2,7 @@
<html class="cp"> <html class="cp">
<!-- If this file is not called customize.dist/src/template.html, it is generated --> <!-- If this file is not called customize.dist/src/template.html, it is generated -->
<head> <head>
<title data-localization="main_title">Cryptpad: Zero Knowledge, Collaborative Real Time Editing</title> <title data-localization="main_title">CryptPad: Zero Knowledge, Collaborative Real Time Editing</title>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/> <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/> <link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/>

@ -19,7 +19,6 @@ html.cp, .cp body {
background-color: @page-white; //@base; background-color: @page-white; //@base;
color: @fore; color: @fore;
font-family: Ubuntu,Georgia,Cambria,serif;
height: 100%; height: 100%;
} }
.fa { .fa {
@ -28,9 +27,19 @@ html.cp, .cp body {
.cp { .cp {
// add font for tooltips
.tippy-popper {
font: normal normal normal 16px Arial, Helvetica, Tahoma, Verdana, Sans-Serif;
}
// override bootstrap colors // override bootstrap colors
.btn-primary { .btn-primary {
background-color: @cp-blue; background-color: @cp-blue;
&:hover {
color: #fff;
background-color: #025aa5;
border-color: #01549b;
}
} }
body { body {
@ -223,13 +232,13 @@ body.html {
margin: 0 auto; margin: 0 auto;
} }
.app-row { .app-row {
display: inline-block; display: flex;
white-space: nowrap; justify-content: center;
width: 700px; flex-flow: row wrap;
max-width: 100%; max-width: 100%;
margin: 0 auto; margin: 0 auto;
@media screen and (max-width: 1399px) { @media screen and (max-width: 1399px) {
display: block; display: flex;
} }
img { img {
@media screen and (max-width: @media-not-big) { @media screen and (max-width: @media-not-big) {
@ -425,6 +434,8 @@ noscript {
label { label {
margin-bottom: 0; margin-bottom: 0;
margin-left: 5px;
vertical-align: middle;
} }
button { button {
@ -432,7 +443,7 @@ noscript {
width: 100%; width: 100%;
cursor: pointer; cursor: pointer;
&.half { &.half {
width: ~"calc(50% - 2px)"; width: ~"calc(50% - 10px)";
&:not(.first) { &:not(.first) {
float: right; float: right;
} }
@ -569,10 +580,12 @@ noscript {
/* Pin limit */ /* Pin limit */
.limit-container { .limit-container {
display: inline-flex;
flex-flow: column-reverse;
width: 100%;
margin-top: 20px;
.cryptpad-limit-bar { .cryptpad-limit-bar {
display: inline-block; display: inline-block;
height: 26px;
width: 200px;
max-width: 40vw; max-width: 40vw;
margin: 3px; margin: 3px;
box-sizing: border-box; box-sizing: border-box;
@ -580,8 +593,10 @@ noscript {
background: white; background: white;
position: relative; position: relative;
text-align: center; text-align: center;
line-height: 24px;
vertical-align: middle; vertical-align: middle;
width: ~"calc(100% - 6px)";
height: 25px;
line-height: 25px;
.usage { .usage {
height: 100%; height: 100%;
display: inline-block; display: inline-block;
@ -604,12 +619,16 @@ noscript {
color: black; color: black;
text-shadow: 1px 0 2px white, 0 1px 2px white, -1px 0 2px white, 0 -1px 2px white; text-shadow: 1px 0 2px white, 0 1px 2px white, -1px 0 2px white, 0 -1px 2px white;
z-index: 2; z-index: 2;
font-size: 16px; font-size: @main-font-size;
font-weight: bold; font-weight: bold;
} }
} }
.upgrade { .upgrade {
margin-left: 10px; padding: 0;
line-height: 25px;
height: 25px;
margin: 0 3px;
border-radius: 0;
} }
} }
@ -621,10 +640,10 @@ noscript {
background-color: rgba(0,0,0,0.5); background-color: rgba(0,0,0,0.5);
color: white; color: white;
opacity: 0.7; opacity: 0.7;
font-family: Ubuntu,Georgia,Cambria,serif;
box-sizing: border-box; box-sizing: border-box;
z-index:10000; z-index:10000;
display: none; display: none;
font-family: -apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
#uploadStatus { #uploadStatus {
width: 80vw; width: 80vw;
border: 1px solid black; border: 1px solid black;

@ -1,3 +1,5 @@
@import "/customize/src/less/variables.less";
.fontface(@family, @src, @style: normal, @weight: 400, @fmt: 'truetype'){ .fontface(@family, @src, @style: normal, @weight: 400, @fmt: 'truetype'){
@font-face { @font-face {
font-family: @family; font-family: @family;
@ -37,3 +39,102 @@
background: linear-gradient(@start, @end); /* Standard syntax */ background: linear-gradient(@start, @end); /* Standard syntax */
} }
.placeholderColor (@color) {
&::-webkit-input-placeholder { /* WebKit, Blink, Edge */
color: @color;;
}
&:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
color: @color;
opacity: 1;
}
&::-moz-placeholder { /* Mozilla Firefox 19+ */
color: @color;
opacity: 1;
}
&:-ms-input-placeholder { /* Internet Explorer 10-11 */
color: @color;
}
&::-ms-input-placeholder { /* Microsoft Edge */
color: @color;
}
}
.avatar (@width) {
&.avatar {
overflow: hidden;
text-overflow: ellipsis;
font-size: 16px;
display: flex;
align-items: center;
&.clickable {
cursor: pointer;
&:hover {
background-color: rgba(0,0,0,0.3);
}
}
.default, media-tag {
display: inline-flex;
width: @width;
height: @width;
justify-content: center;
align-items: center;
border-radius: 4px;
overflow: hidden;
box-sizing: content-box;
}
.default {
.unselectable();
background: white;
color: black;
font-size: @width/1.2;
}
.right-col {
order: 10;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: flex;
flex-flow: column;
.name {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.friend {
padding: 0;
}
}
media-tag {
min-height: @width;
min-width: @width;
max-height: @width;
max-width: @width;
img {
min-width: 100%;
min-height: 100%;
max-width: none;
max-height: none; // To override 'media-tag img' in slide.less
}
}
}
}
.leftsideCategory {
.unselectable();
padding: 5px 20px;
margin: 15px 0;
cursor: pointer;
height: @toolbar-line-height;
line-height: @toolbar-line-height - 10px;
.fa {
width: 25px;
}
&:hover {
background: rgba(0,0,0,0.05);
}
&.active {
background: white;
}
}

@ -0,0 +1,97 @@
@import '/customize/src/less/variables.less';
@import '/customize/src/less/mixins.less';
@leftside-bg: #eee;
@leftside-color: #000;
@rightside-color: #000;
@description-color: #777;
@button-width: 400px;
@button-bg: #3066e5;
@button-alt-bg: #fff;
@button-red-bg: #e54e4e;
.cp {
input[type="text"] {
padding-left: 10px;
}
#container {
font-size: 16px;
display: flex;
flex: 1;
min-height: 0;
#leftSide {
color: @leftside-color;
width: 250px;
background: @leftside-bg;
display: flex;
flex-flow: column;
.categories {
flex: 1;
.category {
.leftsideCategory();
}
}
}
#rightSide {
flex: 1;
padding: 5px 20px;
color: @rightside-color;
overflow: auto;
.element {
label:not(.noTitle), .label {
display: block;
font-weight: bold;
margin-bottom: 0;
}
.description {
display: block;
color: @description-color;
margin-bottom: 5px;
}
margin-bottom: 20px;
}
[type="text"], button {
vertical-align: middle;
height: 40px;
box-sizing: border-box;
}
.inputBlock {
display: inline-flex;
width: @button-width;
input {
flex: 1;
border-radius: 0.25em 0 0 0.25em;
border: 1px solid #adadad;
border-right: 0px;
}
button {
border-radius: 0 0.25em 0.25em 0;
//border: 1px solid #adadad;
border-left: 0px;
}
}
button.btn {
background-color: @button-bg;
border-color: darken(@button-bg, 10%);
color: white;
&:hover {
background-color: darken(@button-bg, 10%);
}
&.btn-danger {
background-color: @button-red-bg;
border-color: darken(@button-red-bg, 10%);
color: white;
&:hover {
background-color: darken(@button-red-bg, 10%);
}
}
}
&>div {
margin: 10px 0;
}
}
}
}

@ -16,13 +16,18 @@
color: inherit; color: inherit;
} }
// Classes used in common-interface.js
.padColor { color: @toolbar-pad-bg; } .padColor { color: @toolbar-pad-bg; }
.codeColor { color: @toolbar-code-bg; } .codeColor { color: @toolbar-code-bg; }
.slideColor { color: @toolbar-slide-bg; } .slideColor { color: @toolbar-slide-bg; }
.pollColor { color: @toolbar-poll-bg; } .pollColor { color: @toolbar-poll-bg; }
.fileColor { color: @toolbar-file-bg; } .fileColor { color: @toolbar-file-bg; }
.friendsColor { color: @toolbar-friends-bg; }
.whiteboardColor { color: @toolbar-whiteboard-bg; } .whiteboardColor { color: @toolbar-whiteboard-bg; }
.driveColor { color: @toolbar-drive-bg; } .driveColor { color: @toolbar-drive-bg; }
.settingsColor { color: @toolbar-settings-bg; }
.profileColor { color: @toolbar-settings-bg; }
.defaultColor { color: @toolbar-default-bg; } .defaultColor { color: @toolbar-default-bg; }
.toolbar-container { .toolbar-container {
@ -55,7 +60,7 @@
} }
body .userlist-drawer { body .userlist-drawer {
font: normal normal normal 16px Arial,Helvetica,Tahoma,Verdana,Sans-Serif; font: normal normal normal @main-font-size Arial,Helvetica,Tahoma,Verdana,Sans-Serif;
min-width: 175px; min-width: 175px;
width: 175px; width: 175px;
display: block; display: block;
@ -94,7 +99,7 @@ body .userlist-drawer {
} }
& > p { & > p {
font: normal normal normal 16px Arial,Helvetica,Tahoma,Verdana,Sans-Serif; font: normal normal normal @main-font-size Arial,Helvetica,Tahoma,Verdana,Sans-Serif;
margin: 0; margin: 0;
padding: 0; padding: 0;
display: block; display: block;
@ -106,58 +111,18 @@ body .userlist-drawer {
margin: 10px 0; margin: 10px 0;
margin-bottom: 20px; margin-bottom: 20px;
&>span { &>span {
overflow: hidden;
text-overflow: ellipsis;
padding: 5px; padding: 5px;
background: rgba(0,0,0,0.1);
margin: 2px 0; margin: 2px 0;
font-size: 16px; background: rgba(0,0,0,0.1);
display: inline-flex; .avatar(30px);
align-items: center;
&.clickable {
cursor: pointer;
&:hover {
background-color: rgba(0,0,0,0.3);
}
}
.default, media-tag { .default, media-tag {
display: inline-flex;
width: 50px;
height: 50px;
justify-content: center;
align-items: center;
margin-right: 5px; margin-right: 5px;
border-radius: 10px / 6px;
overflow: hidden;
border: 1px solid black;
box-sizing: content-box;
}
.default {
.unselectable();
background: white;
color: black;
font-size: 40px;
}
.name {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
media-tag {
min-height: 50px;
min-width: 50px;
max-height: 50px;
max-width: 50px;
img {
min-width: 100%;
min-height: 100%;
max-width: none;
max-height: none; // To override 'media-tag img' in slide.less
flex-shrink: 0;
} }
} }
} }
.friend {
display: inline-block;
width: 20px;
} }
} }
@ -170,6 +135,11 @@ body {
background-color: darken(@bgcolor, 10%); background-color: darken(@bgcolor, 10%);
color: @color; color: @color;
} }
.friend {
&:hover {
color: darken(@color, 15%);
}
}
} }
.cryptpad-toolbar { .cryptpad-toolbar {
background-color: @bgcolor; background-color: @bgcolor;
@ -186,7 +156,7 @@ body {
} }
} }
.cryptpad-spinner, .cryptpad-state { .cryptpad-spinner, .cryptpad-state {
font-size: 16px; font-size: @main-font-size;
color: @color; color: @color;
} }
.cryptpad-limit { .cryptpad-limit {
@ -299,6 +269,21 @@ body {
@color: @toolbar-file-color; @color: @toolbar-file-color;
.addToolbarColors(@color, @bgcolor); .addToolbarColors(@color, @bgcolor);
} }
&.app-contacts {
@bgcolor: @toolbar-friends-bg;
@color: @toolbar-friends-color;
.addToolbarColors(@color, @bgcolor);
}
&.app-settings {
@bgcolor: @toolbar-settings-bg;
@color: @toolbar-settings-color;
.addToolbarColors(@color, @bgcolor);
}
&.app-profile {
@bgcolor: @toolbar-profile-bg;
@color: @toolbar-profile-color;
.addToolbarColors(@color, @bgcolor);
}
} }
@ -333,8 +318,8 @@ body .cryptpad-toolbar {
z-index: 9001; z-index: 9001;
.dropdown-bar { .dropdown-bar {
height: 100%; //height: 100%;
display: inline-block; //display: inline-block;
button { button {
height: 100%; height: 100%;
border-radius: 0; border-radius: 0;
@ -503,7 +488,7 @@ body .cryptpad-toolbar {
} }
button, select, .rightside-element { button, select, .rightside-element {
height: 32px; height: @toolbar-line-height;
box-sizing: border-box; box-sizing: border-box;
padding: 3px 10px; padding: 3px 10px;
margin: 0; margin: 0;
@ -613,7 +598,7 @@ body .cryptpad-toolbar {
flex: auto; flex: auto;
width: 100%; width: 100%;
order: 10; order: 10;
height: 32px; height: @toolbar-line-height;
line-height: initial; line-height: initial;
margin: 0; margin: 0;
.hoverable { .hoverable {
@ -624,24 +609,24 @@ body .cryptpad-toolbar {
display: inline-block; display: inline-block;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
font-size: 16px; font-size: @main-font-size;
height: 32px; height: @toolbar-line-height;
box-sizing: border-box; box-sizing: border-box;
line-height: 20px; line-height: 20px;
} }
.pencilIcon, .saveIcon { .pencilIcon, .saveIcon {
box-sizing: border-box; box-sizing: border-box;
height: 32px; height: @toolbar-line-height;
line-height: 16px; line-height: @main-font-size;
display: inline-block; display: inline-block;
.fa { .fa {
font-size: 16px; font-size: @main-font-size;
} }
} }
input { input {
height: 32px; height: @toolbar-line-height;
font-size: 16px; font-size: @main-font-size;
flex: 1; flex: 1;
max-width: none; max-width: none;
} }
@ -651,6 +636,32 @@ body .cryptpad-toolbar {
} }
} }
.app-slide {
@media screen and (max-width: @media-medium-screen) {
.cryptpad-toolbar-leftside {
flex-flow: row wrap;
width: 175px;
height: auto;
.cryptpad-spinner { order: 0; }
}
.cryptpad-toolbar-rightside {
height: 2*@toolbar-line-height;
}
}
@media screen and (max-width: 320px) {
.cryptpad-toolbar-leftside {
flex-flow: row wrap;
width: 175px;
height: auto;
padding-top: @toolbar-line-height;
.cryptpad-spinner { order: 0; }
}
.cryptpad-toolbar-rightside {
height: auto;
}
}
}
.cryptpad-toolbar-top { .cryptpad-toolbar-top {
display: flex; display: flex;
flex-flow: row; flex-flow: row;
@ -678,6 +689,9 @@ body .cryptpad-toolbar {
line-height: 25px; line-height: 25px;
white-space: nowrap; white-space: nowrap;
} }
.pageTitle {
padding: 0 5px;
}
.pencilIcon, .saveIcon { .pencilIcon, .saveIcon {
display: flex; display: flex;
align-items: center; align-items: center;
@ -755,7 +769,6 @@ body .cryptpad-toolbar {
&:hover { &:hover {
background-color: rgba(0,0,0,0.3); background-color: rgba(0,0,0,0.3);
} }
order: 2;
text-align: center; text-align: center;
font-size: 32px; font-size: 32px;
margin-left: 10px; margin-left: 10px;
@ -813,17 +826,21 @@ body .cryptpad-toolbar {
} }
.cryptpad-user { .cryptpad-user {
height: 100%; height: 100%;
display: inline-block; display: inline-flex;
order: 5; order: 5;
line-height: @toolbar-top-height; line-height: @toolbar-top-height;
color: white; color: white;
.cryptpad-upgrade { order: 1; }
.cryptpad-new { order: 2; }
.cryptpad-user-dropdown { order: 3; }
.cryptpad-backup { order: 4; }
&> * { &> * {
display: inline-block; display: inline-block;
height: 100%; height: 100%;
vertical-align: top; vertical-align: top;
} }
.cryptpad-upgrade { .cryptpad-upgrade {
height: 32px; height: @toolbar-line-height;
vertical-align: middle; vertical-align: middle;
cursor: pointer; cursor: pointer;
} }
@ -856,6 +873,21 @@ body .cryptpad-toolbar {
cursor: default; cursor: default;
font-size: 32px; font-size: 32px;
} }
&.avatar {
.avatar(48px);
media-tag {
margin: 8px;
}
border: 0;
}
}
}
p.accountData {
&> span {
font-weight: bold;
span {
font-weight: normal;
}
} }
} }
.cryptpad-backup { .cryptpad-backup {
@ -869,12 +901,14 @@ body .cryptpad-toolbar {
} }
} }
.cryptpad-toolbar-leftside { .cryptpad-toolbar-leftside {
height: 32px; //height: @toolbar-line-height;
&:empty { &:empty {
height: 0; height: 0;
} }
float: left; float: left;
margin-bottom: -1px; display: inline-flex;
align-items: center;
//margin-bottom: -1px;
.cryptpad-dropdown-users { .cryptpad-dropdown-users {
pre { pre {
/* needed for ckeditor */ /* needed for ckeditor */
@ -890,21 +924,26 @@ body .cryptpad-toolbar {
.dropdown-bar-content { .dropdown-bar-content {
margin-top: -1px; margin-top: -1px;
} }
.limit-container a {
height: 26px; & > span {
margin: 3px 0; height: @toolbar-line-height;
line-height: 26px;
padding: 0 5px;
box-sizing: border-box;
border: 1px solid transparent;
font-size: 14px;
&:hover {
text-decoration: none;
} }
#userButtons { order: 1; }
.shareButton { order: 2; }
.cryptpad-spinner { order: 3; }
#userButtons button {
width: 125px;
text-align: center;
}
.shareButton button {
width: 50px;
text-align: center;
} }
} }
.cryptpad-toolbar-rightside { .cryptpad-toolbar-rightside {
min-height: 32px; min-height: @toolbar-line-height;
overflow: hidden; overflow: hidden;
&:empty { &:empty {
min-height: 0; min-height: 0;
@ -924,7 +963,7 @@ body .cryptpad-toolbar {
box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.2); box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.2);
position: absolute; position: absolute;
right:0px; right:0px;
margin-top: 32px; margin-top: @toolbar-line-height;
min-width: 50px; min-width: 50px;
background: @dropdown-bg; background: @dropdown-bg;
display: flex; display: flex;
@ -937,7 +976,7 @@ body .cryptpad-toolbar {
&> span { &> span {
box-sizing: border-box; box-sizing: border-box;
min-width: 150px; min-width: 150px;
height: 32px; height: @toolbar-line-height;
border-radius: 0; border-radius: 0;
border: 0; border: 0;
} }
@ -1007,11 +1046,12 @@ body .cryptpad-toolbar {
} }
} }
.cryptpad-spinner { .cryptpad-spinner {
line-height: @toolbar-top-height; line-height: @toolbar-line-height;
padding: 0 20px;
&> span.fa { &> span.fa {
height: 20px; height: 20px;
width: 20px; width: 20px;
margin: 8px; //margin: 8px;
line-height: 20px; line-height: 20px;
font-size: 20px; font-size: 20px;
text-align: center; text-align: center;
@ -1022,16 +1062,6 @@ body .cryptpad-toolbar {
font-weight: bold; font-weight: bold;
text-transform: uppercase; text-transform: uppercase;
} }
.cryptpad-user {
p.accountData {
&> span {
font-weight: bold;
span {
font-weight: normal;
}
}
}
}
.cryptpad-dropdown-share { .cryptpad-dropdown-share {
a { a {
.fa { .fa {

@ -7,6 +7,8 @@
@old-base: #302B28; @old-base: #302B28;
@old-fore: #fafafa; @old-fore: #fafafa;
@main-font-size: 16px;
@cp-green: #46E981; @cp-green: #46E981;
@cp-accent: lighten(@cp-green, 20%); @cp-accent: lighten(@cp-green, 20%);
@ -73,7 +75,7 @@
// Dropdown // Dropdown
@dropdown-font: 16px -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; @dropdown-font: @main-font-size -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
@dropdown-bg: #f9f9f9; @dropdown-bg: #f9f9f9;
@dropdown-color: black; @dropdown-color: black;
@dropdown-bg-hover: #f1f1f1; @dropdown-bg-hover: #f1f1f1;
@ -97,8 +99,14 @@
@toolbar-drive-color: #fff; @toolbar-drive-color: #fff;
@toolbar-file-bg: #cd2532; @toolbar-file-bg: #cd2532;
@toolbar-file-color: #fff; @toolbar-file-color: #fff;
@toolbar-friends-bg: #607B8D;
@toolbar-friends-color: #fff;
@toolbar-default-bg: #ddd; @toolbar-default-bg: #ddd;
@toolbar-default-color: #000; @toolbar-default-color: #000;
@toolbar-settings-bg: #0087ff;
@toolbar-settings-color: #fff;
@toolbar-profile-bg: #0087ff;
@toolbar-profile-color: #fff;
@topbar-back: #fff; @topbar-back: #fff;
@ -127,3 +135,5 @@
-ms-user-select: none; -ms-user-select: none;
user-select: none; user-select: none;
} }
@toolbar-line-height: 32px;

@ -2,7 +2,7 @@
<html class="cp"> <html class="cp">
<!-- If this file is not called customize.dist/src/template.html, it is generated --> <!-- If this file is not called customize.dist/src/template.html, it is generated -->
<head> <head>
<title data-localization="main_title">Cryptpad: Zero Knowledge, Collaborative Real Time Editing</title> <title data-localization="main_title">CryptPad: Zero Knowledge, Collaborative Real Time Editing</title>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/> <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/> <link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/>

@ -12,7 +12,7 @@ $(function () {
var Messages = Cryptpad.Messages; var Messages = Cryptpad.Messages;
var $body = $('body'); var $body = $('body');
var isMainApp = function () { var isMainApp = function () {
return /^\/(pad|code|slide|poll|whiteboard|file|media|drive)\/$/.test(location.pathname); return /^\/(pad|code|slide|poll|whiteboard|file|media|contacts|drive|settings|profile)\/$/.test(location.pathname);
}; };
var rightLink = function (ref, loc, txt) { var rightLink = function (ref, loc, txt) {
@ -112,7 +112,7 @@ $(function () {
]) ])
]) ])
]), ]),
h('div.version-footer', "CryptPad v1.10.0 (Kraken)") h('div.version-footer', "CryptPad v1.11.0 (Lutin)")
])); ]));
var pathname = location.pathname; var pathname = location.pathname;
@ -145,9 +145,12 @@ $(function () {
} else if (/drive/.test(pathname)) { } else if (/drive/.test(pathname)) {
$('body').append(h('body', Pages[pathname]()).innerHTML); $('body').append(h('body', Pages[pathname]()).innerHTML);
require(['/drive/main.js'], ready); require(['/drive/main.js'], ready);
} else if (/file/.test(pathname)) { } else if (/\/file\//.test(pathname)) {
$('body').append(h('body', Pages[pathname]()).innerHTML); $('body').append(h('body', Pages[pathname]()).innerHTML);
require([ '/file/main.js' ], ready); require([ '/file/main.js' ], ready);
} else if (/contacts/.test(pathname)) {
$('body').append(h('body', Pages[pathname]()).innerHTML);
require([ '/contacts/main.js' ], ready);
} else if (/pad/.test(pathname)) { } else if (/pad/.test(pathname)) {
$('body').append(h('body', Pages[pathname]()).innerHTML); $('body').append(h('body', Pages[pathname]()).innerHTML);
require([ '/pad/main.js' ], ready); require([ '/pad/main.js' ], ready);
@ -157,6 +160,12 @@ $(function () {
} else if (/slide/.test(pathname)) { } else if (/slide/.test(pathname)) {
$('body').append(h('body', Pages[pathname]()).innerHTML); $('body').append(h('body', Pages[pathname]()).innerHTML);
require([ '/slide/main.js' ], ready); require([ '/slide/main.js' ], ready);
} else if (/^\/settings\//.test(pathname)) {
$('body').append(h('body', Pages[pathname]()).innerHTML);
require([ '/settings/main.js', ], ready);
} else if (/^\/profile\//.test(pathname)) {
$('body').append(h('body', Pages[pathname]()).innerHTML);
require([ '/profile/main.js', ], ready);
} }
}); });
@ -170,11 +179,7 @@ $(function () {
], function () { ], function () {
$body.append($topbar).append($main).append($footer); $body.append($topbar).append($main).append($footer);
if (/^\/settings\//.test(pathname)) { if (/^\/user\//.test(pathname)) {
require([ '/settings/main.js', ], function () {});
} else if (/^\/profile\//.test(pathname)) {
require([ '/profile/main.js'], function () {});
} else if (/^\/user\//.test(pathname)) {
require([ '/user/main.js'], function () {}); require([ '/user/main.js'], function () {});
} else if (/^\/register\//.test(pathname)) { } else if (/^\/register\//.test(pathname)) {
require([ '/register/main.js' ], function () {}); require([ '/register/main.js' ], function () {});
@ -183,6 +188,8 @@ $(function () {
} else if (/^\/($|^\/index\.html$)/.test(pathname)) { } else if (/^\/($|^\/index\.html$)/.test(pathname)) {
// TODO use different top bar // TODO use different top bar
require([ '/customize/main.js', ], function () {}); require([ '/customize/main.js', ], function () {});
} else if (/invite/.test(pathname)) {
require([ '/invite/main.js'], function () {});
} else { } else {
require([ '/customize/main.js', ], function () {}); require([ '/customize/main.js', ], function () {});
} }

@ -2,7 +2,7 @@
<html class="cp"> <html class="cp">
<!-- If this file is not called customize.dist/src/template.html, it is generated --> <!-- If this file is not called customize.dist/src/template.html, it is generated -->
<head> <head>
<title data-localization="main_title">Cryptpad: Zero Knowledge, Collaborative Real Time Editing</title> <title data-localization="main_title">CryptPad: Zero Knowledge, Collaborative Real Time Editing</title>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/> <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/> <link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/>

@ -12,6 +12,7 @@ define(function () {
out.type.poll = 'Encuesta'; out.type.poll = 'Encuesta';
out.type.slide = 'Presentación'; out.type.slide = 'Presentación';
out.type.whiteboard = 'Pizarra'; out.type.whiteboard = 'Pizarra';
out.type.contacts = 'Contactos';
out.disconnected = "Desconectado"; out.disconnected = "Desconectado";
out.synchronizing = "Sincronización"; out.synchronizing = "Sincronización";
@ -246,7 +247,6 @@ define(function () {
out.settings_backupTitle = "Copia de seguridad"; out.settings_backupTitle = "Copia de seguridad";
out.settings_backup = "Copia de seguridad"; out.settings_backup = "Copia de seguridad";
out.settings_restore = "Recuparar datos"; out.settings_restore = "Recuparar datos";
out.settings_resetTitle = "Limpiar tu drive";
out.settings_reset = "Quita todos los documentos de tu CryptDrive"; out.settings_reset = "Quita todos los documentos de tu CryptDrive";
out.settings_resetPrompt = "Esta acción eliminará todos tus documentos.<br>¿Seguro que quieres continuar?<br>Introduce “<em>I love CryptPad</em>” para confirmar."; out.settings_resetPrompt = "Esta acción eliminará todos tus documentos.<br>¿Seguro que quieres continuar?<br>Introduce “<em>I love CryptPad</em>” para confirmar.";
out.settings_resetDone = "¡Tu drive ahora está vacio!"; out.settings_resetDone = "¡Tu drive ahora está vacio!";
@ -294,7 +294,7 @@ define(function () {
'<span style="font-size:18px;"><p>', '<span style="font-size:18px;"><p>',
'Esto es&nbsp;<strong>CryptPad</strong>, el editor collaborativo en tiempo real Zero Knowledge. Todo está guardado cuando escribes.', 'Esto es&nbsp;<strong>CryptPad</strong>, el editor collaborativo en tiempo real Zero Knowledge. Todo está guardado cuando escribes.',
'<br>', '<br>',
'Comparte el enlace a este pad para editar con amigos o utiliza el botón <span style="background-color:#5cb85c;color:#ffffff;">&nbsp;Compartir&nbsp;</span> para obtener un <em>enlace solo lectura</em>&nbsp;que permite leer pero no escribir.', 'Comparte el enlace a este pad para editar con amigos o utiliza el botón <span class="fa fa-share-alt" style="border: 1px solid black;color:#000;">&nbsp;Compartir&nbsp;</span> para obtener un <em>enlace solo lectura</em>&nbsp;que permite leer pero no escribir.',
'</p>', '</p>',
'<p><em>', '<p><em>',
@ -485,5 +485,62 @@ define(function () {
out.canvas_opacityLabel = "Opacidad: {0}"; out.canvas_opacityLabel = "Opacidad: {0}";
out.canvas_widthLabel = "Talla: {0}"; out.canvas_widthLabel = "Talla: {0}";
// 1.10.0 - Kraken
out.moreActions = "Más acciones";
out.importButton = "Importar";
out.exportButton = "Exportar";
out.saveTitle = "Guardar título (enter)";
out.forgetButton = "Eliminar";
out.printText = "Imprimir";
out.slideOptionsText = "Opciones";
out.historyText = "Historial";
out.openLinkInNewTab = "Abrir enlace en pestaña nueva";
out.profileButton = "Perfíl";
out.profile_urlPlaceholder = "URL";
out.profile_namePlaceholder = "Nombre mostrado en su perfíl";
out.profile_avatar = "Imágen";
out.profile_upload = "Subir una imágen";
out.profile_error = "Error al crear tu perfíl: {0}";
out.profile_register = "Tienes que registrarte para crear perfíl";
out.profile_create = "Crear perfíl";
out.profile_description = "Descripción";
out.profile_fieldSaved = "Guardado: {0}";
out.download_mt_button = "Descargar";
out.updated_0_header_logoTitle = "Volver a tu CryptDrive";
out.header_logoTitle = out.updated_0_header_logoTitle;
// 1.11.0 - Lutin
out.realtime_unrecoverableError = "El motor de tiempo real a encontrado un error. Haga clic en OK para recargar la página.";
out.typing = "Escribiendo";
out.profile_inviteButton = "Connectar";
out.profile_inviteButtonTitle = "Crear un enlace de invitación para este usuario.";
out.profile_inviteExplanation = "Hacer clic en <strong>OK</strong> creará un enlace de mensaje seguro que <em>sólo {0} podrá ver.</em><br><br>El enlace será copiado a tu portapapeles y puede ser compartido publicamente.";
out.profile_viewMyProfile = "Ver mi perfíl";
out.userlist_addAsFriendTitle = 'Agregar "{0}" como contacto';
out.userlist_thisIsYou = 'Tú mismo ("{0}")';
out.contacts_title = "Contactos";
out.contacts_addError = "Error al agregar este contacto a la lista";
out.contacts_added = "Invitación acceptada";
out.contacts_rejected = "Invitación denegada";
out.contacts_request = "<em>{0}</em> quiere agregarte como contacto. <b>Acceptar</b>?";
out.contacts_send = "Enviar";
out.contacts_remove = "Eliminar este contacto";
out.contacts_confirmRemove = "Estás seguro que quieres eliminar <em>{0}</em> de tus contactos?";
out.contacts_info1 = "Estos son tus contactos. De aquí, puedes:";
out.contacts_info2 = "Hacer clic en el icono de tu contacto para chatear";
out.contacts_info3 = "Hacer doble-clic para ver su perfil";
out.contacts_info4 = "Cualquier participante puede eliminar definitivamente el historial de chat";
out.settings_cat_account = "Cuenta";
out.settings_cat_drive = "CryptDrive";
out.settings_backupCategory = "Copia de seguridad";
out.settings_resetNewTitle = "Limpiar CryptDrive";
out.settings_resetButton = "Eliminar";
out.settings_resetTipsAction = "Reiniciar";
out.settings_userFeedbackTitle = "Feedback";
out.settings_logoutEverywhereButton = "Cerar sesión";
out.upload_title = "Subir archivo";
return out; return out;
}); });

@ -9,10 +9,11 @@ define(function () {
out.type.code = 'Code'; out.type.code = 'Code';
out.type.poll = 'Sondage'; out.type.poll = 'Sondage';
out.type.slide = 'Présentation'; out.type.slide = 'Présentation';
out.type.drive = 'Drive'; out.type.drive = 'CryptDrive';
out.type.whiteboard = "Tableau Blanc"; out.type.whiteboard = "Tableau Blanc";
out.type.file = "Fichier"; out.type.file = "Fichier";
out.type.media = "Média"; out.type.media = "Média";
out.type.contacts = "Contacts";
out.button_newpad = 'Nouveau document texte'; out.button_newpad = 'Nouveau document texte';
out.button_newcode = 'Nouvelle page de code'; out.button_newcode = 'Nouvelle page de code';
@ -34,9 +35,12 @@ define(function () {
out.synced = "Tout est enregistré"; out.synced = "Tout est enregistré";
out.deleted = "Pad supprimé de votre CryptDrive"; out.deleted = "Pad supprimé de votre CryptDrive";
out.realtime_unrecoverableError = "Le moteur temps-réel a rencontré une erreur critique. Cliquez sur OK pour recharger la page.";
out.disconnected = 'Déconnecté'; out.disconnected = 'Déconnecté';
out.synchronizing = 'Synchronisation'; out.synchronizing = 'Synchronisation';
out.reconnecting = 'Reconnexion...'; out.reconnecting = 'Reconnexion...';
out.typing = "Édition";
out.lag = 'Latence'; out.lag = 'Latence';
out.readonly = 'Lecture seule'; out.readonly = 'Lecture seule';
out.anonymous = "Anonyme"; out.anonymous = "Anonyme";
@ -252,6 +256,28 @@ define(function () {
out.profile_description = "Description"; out.profile_description = "Description";
out.profile_fieldSaved = 'Nouvelle valeur enregistrée: {0}'; out.profile_fieldSaved = 'Nouvelle valeur enregistrée: {0}';
out.profile_viewMyProfile = "Voir mon profil";
// contacts/userlist
out.userlist_addAsFriendTitle = 'Ajouter "{0}" comme contact';
out.userlist_thisIsYou = 'Vous ("{0}")';
out.userlist_pending = "En attente...";
out.contacts_title = "Contacts";
out.contacts_addError = "Erreur lors de l'ajout de ce contact dans votre liste";
out.contacts_added = 'Invitation de contact acceptée';
out.contacts_rejected = 'Invitation de contact rejetée';
out.contacts_request = '<em>{0}</em> souhaite vous ajouter en tant que contact. <b>Accepter<b> ?';
out.contacts_send = 'Envoyer';
out.contacts_remove = 'Supprimer ce contact';
out.contacts_confirmRemove = 'Êtes-vous sûr de voulour supprimer <em>{0}</em> de vos contacts ?';
out.contacts_typeHere = "Entrez un message ici...";
out.contacts_info1 = "Voici vos contacts. Ici, vous pouvez :";
out.contacts_info2 = "Cliquer sur le nom d'un contact pour discuter avec lui";
out.contacts_info3 = "Double-cliquer sur son nom pour voir son profil";
out.contacts_info4 = "Chaque participant peut nettoyer définitivement l'historique d'une discussion";
// File manager // File manager
out.fm_rootName = "Documents"; out.fm_rootName = "Documents";
@ -294,7 +320,7 @@ define(function () {
out.updated_0_fm_info_trash = "Vider la corbeille permet de libérer de l'espace dans votre CryptDrive"; out.updated_0_fm_info_trash = "Vider la corbeille permet de libérer de l'espace dans votre CryptDrive";
out.fm_info_trash = out.updated_0_fm_info_trash; out.fm_info_trash = out.updated_0_fm_info_trash;
out.fm_info_allFiles = 'Contient tous les fichiers de "Documents", "Fichiers non triés" et "Corbeille". Vous ne pouvez pas supprimer ou déplacer des fichiers depuis cet endroit.'; // Same here out.fm_info_allFiles = 'Contient tous les fichiers de "Documents", "Fichiers non triés" et "Corbeille". Vous ne pouvez pas supprimer ou déplacer des fichiers depuis cet endroit.'; // Same here
out.fm_info_anonymous = 'Vous n\'êtes pas connectés, ces pads risquent donc d\'être supprimés (<a href="https://blog.cryptpad.fr/2017/05/17/You-gotta-log-in/" target="_blank">découvrez pourquoi</a>). ' + out.fm_info_anonymous = 'Vous n\'êtes pas connecté, ces pads risquent donc d\'être supprimés (<a href="https://blog.cryptpad.fr/2017/05/17/You-gotta-log-in/" target="_blank">découvrez pourquoi</a>). ' +
'<a href="/register/">Inscrivez-vous</a> ou <a href="/login/">connectez-vous</a> pour les maintenir en vie.'; '<a href="/register/">Inscrivez-vous</a> ou <a href="/login/">connectez-vous</a> pour les maintenir en vie.';
out.fm_alert_backupUrl = "Lien de secours pour ce CryptDrive.<br>" + out.fm_alert_backupUrl = "Lien de secours pour ce CryptDrive.<br>" +
"Il est <strong>fortement recommandé</strong> de garder ce lien pour vous-même.<br>" + "Il est <strong>fortement recommandé</strong> de garder ce lien pour vous-même.<br>" +
@ -375,27 +401,36 @@ define(function () {
]; ];
// Settings // Settings
out.settings_cat_account = "Compte";
out.settings_cat_drive = "CryptDrive";
out.settings_title = "Préférences"; out.settings_title = "Préférences";
out.settings_save = "Sauver"; out.settings_save = "Sauver";
out.settings_backupCategory = "Sauvegarde";
out.settings_backupTitle = "Créer ou restaurer une sauvegarde de vos données"; out.settings_backupTitle = "Créer ou restaurer une sauvegarde de vos données";
out.settings_backup = "Créer une sauvegarde"; out.settings_backup = "Sauvegarder";
out.settings_restore = "Restaurer une sauvegarde"; out.settings_restore = "Restaurer";
out.settings_resetTitle = "Vider votre drive";
out.settings_resetNewTitle = "Vider CryptDrive";
out.settings_resetButton = "Supprimer";
out.settings_reset = "Supprimer tous les fichiers et dossiers de votre CryptDrive"; out.settings_reset = "Supprimer tous les fichiers et dossiers de votre CryptDrive";
out.settings_resetPrompt = "Cette action va supprimer tous les pads de votre drive.<br>"+ out.settings_resetPrompt = "Cette action va supprimer tous les pads de votre drive.<br>"+
"Êtes-vous sûr de vouloir continuer ?<br>" + "Êtes-vous sûr de vouloir continuer ?<br>" +
"Tapez “<em>I love CryptPad</em>” pour confirmer."; "Tapez “<em>I love CryptPad</em>” pour confirmer.";
out.settings_resetDone = "Votre drive est désormais vide!"; out.settings_resetDone = "Votre drive est désormais vide!";
out.settings_resetError = "Texte de vérification incorrect. Votre CryptDrive n'a pas été modifié."; out.settings_resetError = "Texte de vérification incorrect. Votre CryptDrive n'a pas été modifié.";
out.settings_resetTips = "Astuces et informations dans CryptDrive";
out.settings_resetTipsAction ="Réinitialiser";
out.settings_resetTips = "Astuces";
out.settings_resetTipsButton = "Réinitialiser les astuces visibles dans CryptDrive"; out.settings_resetTipsButton = "Réinitialiser les astuces visibles dans CryptDrive";
out.settings_resetTipsDone = "Toutes les astuces sont de nouveau visibles."; out.settings_resetTipsDone = "Toutes les astuces sont de nouveau visibles.";
out.settings_importTitle = "Importer les pads récents de ce navigateur dans mon CryptDrive"; out.settings_importTitle = "Importer les pads récents de ce navigateur dans votre CryptDrive";
out.settings_import = "Importer"; out.settings_import = "Importer";
out.settings_importConfirm = "Êtes-vous sûr de vouloir importer les pads récents de ce navigateur dans le CryptDrive de votre compte utilisateur ?"; out.settings_importConfirm = "Êtes-vous sûr de vouloir importer les pads récents de ce navigateur dans le CryptDrive de votre compte utilisateur ?";
out.settings_importDone = "Importation terminée"; out.settings_importDone = "Importation terminée";
out.settings_userFeedbackTitle = "Retour d'expérience";
out.settings_userFeedbackHint1 = "CryptPad peut envoyer des retours d'expérience très limités vers le serveur, de manière à nous permettre d'améliorer l'expérience des utilisateurs. "; out.settings_userFeedbackHint1 = "CryptPad peut envoyer des retours d'expérience très limités vers le serveur, de manière à nous permettre d'améliorer l'expérience des utilisateurs. ";
out.settings_userFeedbackHint2 = "Le contenu de vos pads et les clés de déchiffrement ne seront jamais partagés avec le serveur."; out.settings_userFeedbackHint2 = "Le contenu de vos pads et les clés de déchiffrement ne seront jamais partagés avec le serveur.";
out.settings_userFeedback = "Activer l'envoi de retours d'expérience"; out.settings_userFeedback = "Activer l'envoi de retours d'expérience";
@ -409,10 +444,12 @@ define(function () {
out.settings_pinningError = "Un problème est survenu"; out.settings_pinningError = "Un problème est survenu";
out.settings_usageAmount = "Vos pads épinglés occupent {0} Mo"; out.settings_usageAmount = "Vos pads épinglés occupent {0} Mo";
out.settings_logoutEverywhereButton = "Se déconnecter";
out.settings_logoutEverywhereTitle = "Se déconnecter partout"; out.settings_logoutEverywhereTitle = "Se déconnecter partout";
out.settings_logoutEverywhere = "Se déconnecter de toutes les autres sessions."; out.settings_logoutEverywhere = "Se déconnecter de force de toutes les autres sessions.";
out.settings_logoutEverywhereConfirm = "Êtes-vous sûr ? Vous devrez vous reconnecter sur tous vos autres appareils."; out.settings_logoutEverywhereConfirm = "Êtes-vous sûr ? Vous devrez vous reconnecter sur tous vos autres appareils.";
out.upload_title = "Hébergement de fichiers";
out.upload_serverError = "Erreur interne: impossible d'importer le fichier pour l'instant."; out.upload_serverError = "Erreur interne: impossible d'importer le fichier pour l'instant.";
out.upload_uploadPending = "Vous avez déjà un fichier en cours d'importation. Souhaitez-vous l'annuler et importer ce nouveau fichier ?"; out.upload_uploadPending = "Vous avez déjà un fichier en cours d'importation. Souhaitez-vous l'annuler et importer ce nouveau fichier ?";
out.upload_success = "Votre fichier ({0}) a été importé avec succès et ajouté à votre CryptDrive."; out.upload_success = "Votre fichier ({0}) a été importé avec succès et ajouté à votre CryptDrive.";
@ -518,7 +555,7 @@ define(function () {
'<span style="font-size:16px;"><p>', '<span style="font-size:16px;"><p>',
'Voici <strong>CryptPad</strong>, l\'éditeur collaboratif en temps-réel Zero Knowledge. Tout est sauvegardé dés que vous le tapez.', 'Voici <strong>CryptPad</strong>, l\'éditeur collaboratif en temps-réel Zero Knowledge. Tout est sauvegardé dés que vous le tapez.',
'<br>', '<br>',
'Partagez le lien vers ce pad avec des amis ou utilisez le bouton <span style="background-color:#5cb85c;color:#ffffff;">&nbsp;Partager&nbsp;</span> pour obtenir le <em>lien de lecture-seule</em>, qui permet la lecture mais non la modification.', 'Partagez le lien vers ce pad avec des amis ou utilisez le bouton <span class="fa fa-share-alt" style="border: 1px solid black;color:#000;">&nbsp;Partager&nbsp;</span> pour obtenir le <em>lien de lecture-seule</em>, qui permet la lecture mais non la modification.',
'</p>', '</p>',
'<p>', '<p>',
'<em>', '<em>',

@ -9,10 +9,11 @@ define(function () {
out.type.code = 'Code'; out.type.code = 'Code';
out.type.poll = 'Poll'; out.type.poll = 'Poll';
out.type.slide = 'Presentation'; out.type.slide = 'Presentation';
out.type.drive = 'Drive'; out.type.drive = 'CryptDrive';
out.type.whiteboard = 'Whiteboard'; out.type.whiteboard = 'Whiteboard';
out.type.file = 'File'; out.type.file = 'File';
out.type.media = 'Media'; out.type.media = 'Media';
out.type.contacts = 'Contacts';
out.button_newpad = 'New Rich Text pad'; out.button_newpad = 'New Rich Text pad';
out.button_newcode = 'New Code pad'; out.button_newcode = 'New Code pad';
@ -36,9 +37,12 @@ define(function () {
out.synced = "Everything is saved"; out.synced = "Everything is saved";
out.deleted = "Pad deleted from your CryptDrive"; out.deleted = "Pad deleted from your CryptDrive";
out.realtime_unrecoverableError = "The realtime engine has encountered an unrecoverable error. Click OK to reload.";
out.disconnected = 'Disconnected'; out.disconnected = 'Disconnected';
out.synchronizing = 'Synchronizing'; out.synchronizing = 'Synchronizing';
out.reconnecting = 'Reconnecting...'; out.reconnecting = 'Reconnecting...';
out.typing = "Typing";
out.lag = 'Lag'; out.lag = 'Lag';
out.readonly = 'Read only'; out.readonly = 'Read only';
out.anonymous = "Anonymous"; out.anonymous = "Anonymous";
@ -254,6 +258,30 @@ define(function () {
out.profile_description = "Description"; out.profile_description = "Description";
out.profile_fieldSaved = 'New value saved: {0}'; out.profile_fieldSaved = 'New value saved: {0}';
out.profile_inviteButton = "Connect";
out.profile_inviteButtonTitle ='Create a link that will invite this user to connect with you.';
out.profile_inviteExplanation = "Clicking <strong>OK</strong> will create a link to a secure messaging session that <em>only {0} will be able to redeem.</em><br><br>The link will be copied to your clipboard and can be shared publicly.";
out.profile_viewMyProfile = "View my profile";
// contacts/userlist
out.userlist_addAsFriendTitle = 'Add "{0}" as a contact';
out.userlist_thisIsYou = 'This is you ("{0}")';
out.userlist_pending = "Pending...";
out.contacts_title = "Contacts";
out.contacts_addError = 'Error while adding that contact to the list';
out.contacts_added = 'Contact invite accepted.';
out.contacts_rejected = 'Contact invite rejected';
out.contacts_request = '<em>{0}</em> would like to add you as a contact. <b>Accept<b>?';
out.contacts_send = 'Send';
out.contacts_remove = 'Remove this contact';
out.contacts_confirmRemove = 'Are you sure you want to remove <em>{0}</em> from your contacts?';
out.contacts_typeHere = "Type a message here...";
out.contacts_info1 = "These are your contacts. From here, you can:";
out.contacts_info2 = "Click your contact's icon to chat with them";
out.contacts_info3 = "Double-click their icon to view their profile";
out.contacts_info4 = "Either participant can clear permanently a chat history";
// File manager // File manager
out.fm_rootName = "Documents"; out.fm_rootName = "Documents";
@ -380,27 +408,36 @@ define(function () {
out.register_alreadyRegistered = "This user already exists, do you want to log in?"; out.register_alreadyRegistered = "This user already exists, do you want to log in?";
// Settings // Settings
out.settings_cat_account = "Account";
out.settings_cat_drive = "CryptDrive";
out.settings_title = "Settings"; out.settings_title = "Settings";
out.settings_save = "Save"; out.settings_save = "Save";
out.settings_backupCategory = "Backup";
out.settings_backupTitle = "Backup or restore all your data"; out.settings_backupTitle = "Backup or restore all your data";
out.settings_backup = "Backup"; out.settings_backup = "Backup";
out.settings_restore = "Restore"; out.settings_restore = "Restore";
out.settings_resetTitle = "Clean your drive";
out.settings_resetNewTitle = "Clean CryptDrive";
out.settings_resetButton = "Remove";
out.settings_reset = "Remove all the files and folders from your CryptDrive"; out.settings_reset = "Remove all the files and folders from your CryptDrive";
out.settings_resetPrompt = "This action will remove all the pads from your drive.<br>"+ out.settings_resetPrompt = "This action will remove all the pads from your drive.<br>"+
"Are you sure you want to continue?<br>" + "Are you sure you want to continue?<br>" +
"Type “<em>I love CryptPad</em>” to confirm."; "Type “<em>I love CryptPad</em>” to confirm.";
out.settings_resetDone = "Your drive is now empty!"; out.settings_resetDone = "Your drive is now empty!";
out.settings_resetError = "Incorrect verification text. Your CryptDrive has not been changed."; out.settings_resetError = "Incorrect verification text. Your CryptDrive has not been changed.";
out.settings_resetTips = "Tips in CryptDrive";
out.settings_resetTipsAction = "Reset";
out.settings_resetTips = "Tips";
out.settings_resetTipsButton = "Reset the available tips in CryptDrive"; out.settings_resetTipsButton = "Reset the available tips in CryptDrive";
out.settings_resetTipsDone = "All the tips are now visible again."; out.settings_resetTipsDone = "All the tips are now visible again.";
out.settings_importTitle = "Import this browser's recent pads in my CryptDrive"; out.settings_importTitle = "Import this browser's recent pads in your CryptDrive";
out.settings_import = "Import"; out.settings_import = "Import";
out.settings_importConfirm = "Are you sure you want to import recent pads from this browser to your user account's CryptDrive?"; out.settings_importConfirm = "Are you sure you want to import recent pads from this browser to your user account's CryptDrive?";
out.settings_importDone = "Import completed"; out.settings_importDone = "Import completed";
out.settings_userFeedbackTitle = "Feedback";
out.settings_userFeedbackHint1 = "CryptPad provides some very basic feedback to the server, to let us know how to improve your experience. "; out.settings_userFeedbackHint1 = "CryptPad provides some very basic feedback to the server, to let us know how to improve your experience. ";
out.settings_userFeedbackHint2 = "Your pad's content will never be shared with the server."; out.settings_userFeedbackHint2 = "Your pad's content will never be shared with the server.";
out.settings_userFeedback = "Enable user feedback"; out.settings_userFeedback = "Enable user feedback";
@ -414,10 +451,12 @@ define(function () {
out.settings_pinningError = "Something went wrong"; out.settings_pinningError = "Something went wrong";
out.settings_usageAmount = "Your pinned pads occupy {0}MB"; out.settings_usageAmount = "Your pinned pads occupy {0}MB";
out.settings_logoutEverywhereButton = "Log out";
out.settings_logoutEverywhereTitle = "Log out everywhere"; out.settings_logoutEverywhereTitle = "Log out everywhere";
out.settings_logoutEverywhere = "Log out of all other web sessions"; out.settings_logoutEverywhere = "Force log out of all other web sessions";
out.settings_logoutEverywhereConfirm = "Are you sure? You will need to log in with all your devices."; out.settings_logoutEverywhereConfirm = "Are you sure? You will need to log in with all your devices.";
out.upload_title = "File upload";
out.upload_serverError = "Server Error: unable to upload your file at this time."; out.upload_serverError = "Server Error: unable to upload your file at this time.";
out.upload_uploadPending = "You already have an upload in progress. Cancel it and upload your new file?"; out.upload_uploadPending = "You already have an upload in progress. Cancel it and upload your new file?";
out.upload_success = "Your file ({0}) has been successfully uploaded and added to your drive."; out.upload_success = "Your file ({0}) has been successfully uploaded and added to your drive.";
@ -528,7 +567,7 @@ define(function () {
'<span style="font-size:16px;"><p>', '<span style="font-size:16px;"><p>',
'This is&nbsp;<strong>CryptPad</strong>, the Zero Knowledge realtime collaborative editor. Everything is saved as you type.', 'This is&nbsp;<strong>CryptPad</strong>, the Zero Knowledge realtime collaborative editor. Everything is saved as you type.',
'<br>', '<br>',
'Share the link to this pad to edit with friends or use the <span style="background-color:#5cb85c;color:#ffffff;">&nbsp;Share&nbsp;</span> button to share a <em>read-only link</em>&nbsp;which allows viewing but not editing.', 'Share the link to this pad to edit with friends or use the <span class="fa fa-share-alt" style="border: 1px solid black;color:#000;">&nbsp;Share&nbsp;</span> button to share a <em>read-only link</em>&nbsp;which allows viewing but not editing.',
'</p>', '</p>',
'<p><em>', '<p><em>',

@ -331,7 +331,7 @@ define(function () {
out.header_france = "<a href=\"http://www.xwiki.com/\" target=\"_blank\" rel=\"noopener noreferrer\">With <img class=\"bottom-bar-heart\" src=\"/customize/heart.png\" alt=\"love\" /> from <img class=\"bottom-bar-fr\" src=\"/customize/fr.png\" title=\"Franța\" alt=\"Franța\"/> by <img src=\"/customize/logo-xwiki.png\" alt=\"XWiki SAS\" class=\"bottom-bar-xwiki\"/></a>"; out.header_france = "<a href=\"http://www.xwiki.com/\" target=\"_blank\" rel=\"noopener noreferrer\">With <img class=\"bottom-bar-heart\" src=\"/customize/heart.png\" alt=\"love\" /> from <img class=\"bottom-bar-fr\" src=\"/customize/fr.png\" title=\"Franța\" alt=\"Franța\"/> by <img src=\"/customize/logo-xwiki.png\" alt=\"XWiki SAS\" class=\"bottom-bar-xwiki\"/></a>";
out.header_support = "<a href=\"http://ng.open-paas.org/\" title=\"OpenPaaS::ng\" target=\"_blank\" rel=\"noopener noreferrer\"> <img src=\"/customize/openpaasng.png\" alt=\"OpenPaaS-ng\" class=\"bottom-bar-openpaas\" /></a>"; out.header_support = "<a href=\"http://ng.open-paas.org/\" title=\"OpenPaaS::ng\" target=\"_blank\" rel=\"noopener noreferrer\"> <img src=\"/customize/openpaasng.png\" alt=\"OpenPaaS-ng\" class=\"bottom-bar-openpaas\" /></a>";
out.header_logoTitle = "Mergi la pagina principală"; out.header_logoTitle = "Mergi la pagina principală";
out.initialState = "<span style=\"font-size:16px;\"><p>Acesta este&nbsp;<strong>CryptPad</strong>, editorul colaborativ bazat pe tehnologia Zero Knowledge în timp real. Totul este salvat pe măsură ce scrii.<br>Partajează link-ul către acest pad pentru a edita cu prieteni sau folosește <span style=\"background-color:#5cb85c;color:#ffffff;\">&nbsp;Share&nbsp;</span> butonul pentru a partaja <em>read-only link</em>&nbsp;permițând vizualizarea dar nu și editarea.</p><p><em>Îndrăznește, începe să scrii...</em></p></span><p>&nbsp;<br></p>"; out.initialState = "<span style=\"font-size:16px;\"><p>Acesta este&nbsp;<strong>CryptPad</strong>, editorul colaborativ bazat pe tehnologia Zero Knowledge în timp real. Totul este salvat pe măsură ce scrii.<br>Partajează link-ul către acest pad pentru a edita cu prieteni sau folosește <span class=\"fa fa-share-alt\" style=\"border:1px solid black;color:#000;\">&nbsp;Share&nbsp;</span> butonul pentru a partaja <em>read-only link</em>&nbsp;permițând vizualizarea dar nu și editarea.</p><p><em>Îndrăznește, începe să scrii...</em></p></span><p>&nbsp;<br></p>";
out.codeInitialState = "/*\n Acesta este editorul colaborativ de cod bazat pe tehnologia Zero Knowledge CryptPad.\n Ce scrii aici este criptat, așa că doar oamenii care au link-ul pot să-l acceseze.\n Poți să alegi ce limbaj de programare pus n evidență și schema de culori UI n dreapta sus.\n*/"; out.codeInitialState = "/*\n Acesta este editorul colaborativ de cod bazat pe tehnologia Zero Knowledge CryptPad.\n Ce scrii aici este criptat, așa că doar oamenii care au link-ul pot să-l acceseze.\n Poți să alegi ce limbaj de programare pus n evidență și schema de culori UI n dreapta sus.\n*/";
out.slideInitialState = "# CryptSlide\n* Acesta este un editor colaborativ bazat pe tehnologia Zero Knowledge.\n* Ce scrii aici este criptat, așa că doar oamenii care au link-ul pot să-l acceseze.\n* Nici măcar serverele nu au acces la ce scrii tu.\n* Ce vezi aici, ce auzi aici, atunci când pleci, lași aici.\n\n-\n# Cum se folosește\n1. Scrie-ți conținutul slide-urilor folosind sintaxa markdown\n - Află mai multe despre sintaxa markdown [aici](http://www.markdowntutorial.com/)\n2. Separă-ți slide-urile cu -\n3. Click pe butonul \"Play\" pentru a vedea rezultatele - Slide-urile tale sunt actualizate în timp real."; out.slideInitialState = "# CryptSlide\n* Acesta este un editor colaborativ bazat pe tehnologia Zero Knowledge.\n* Ce scrii aici este criptat, așa că doar oamenii care au link-ul pot să-l acceseze.\n* Nici măcar serverele nu au acces la ce scrii tu.\n* Ce vezi aici, ce auzi aici, atunci când pleci, lași aici.\n\n-\n# Cum se folosește\n1. Scrie-ți conținutul slide-urilor folosind sintaxa markdown\n - Află mai multe despre sintaxa markdown [aici](http://www.markdowntutorial.com/)\n2. Separă-ți slide-urile cu -\n3. Click pe butonul \"Play\" pentru a vedea rezultatele - Slide-urile tale sunt actualizate în timp real.";
out.driveReadmeTitle = "Ce este CryptDrive?"; out.driveReadmeTitle = "Ce este CryptDrive?";

@ -470,7 +470,7 @@ define(function () {
'<span style="font-size:16px;"><p>', '<span style="font-size:16px;"><p>',
'這是&nbsp;<strong>CryptPad</strong>, 零知識即時協作編輯平台,當你輸入時一切已即存好。', '這是&nbsp;<strong>CryptPad</strong>, 零知識即時協作編輯平台,當你輸入時一切已即存好。',
'<br>', '<br>',
'分享這個工作檔案的網址連結給友人或是使用、 <span style="background-color:#5cb85c;color:#ffffff;">&nbsp;分享&nbsp;</span> 按鈕分享<em>唯讀的連結</em>&nbsp;其只能看不能編寫。', '分享這個工作檔案的網址連結給友人或是使用、 <span class="fa fa-share-alt" style="border: 1px solid black;color:#000;">&nbsp;分享&nbsp;</span> 按鈕分享<em>唯讀的連結</em>&nbsp;其只能看不能編寫。',
'</p>', '</p>',
'<p><em>', '<p><em>',

@ -1,7 +1,7 @@
{ {
"name": "cryptpad", "name": "cryptpad",
"description": "realtime collaborative visual editor with zero knowlege server", "description": "realtime collaborative visual editor with zero knowlege server",
"version": "1.10.0", "version": "1.11.0",
"dependencies": { "dependencies": {
"chainpad-server": "^1.0.1", "chainpad-server": "^1.0.1",
"express": "~4.10.1", "express": "~4.10.1",

@ -129,7 +129,7 @@ Still there are other low-lives in the world so using CryptPad over HTTPS is pro
## Setup using Docker ## Setup using Docker
See [Cryptpad-Docker](cryptpad-docker.md) See [Cryptpad-Docker](docs/cryptpad-docker.md)
## Translations ## Translations

@ -28,8 +28,8 @@ var WARN = function (e, output) {
}; };
var isValidId = function (chan) { var isValidId = function (chan) {
return chan && chan.length && /^[a-fA-F0-9]/.test(chan) || return chan && chan.length && /^[a-fA-F0-9]/.test(chan) &&
[32, 48].indexOf(chan.length) !== -1; [32, 48].indexOf(chan.length) > -1;
}; };
var uint8ArrayToHex = function (a) { var uint8ArrayToHex = function (a) {
@ -113,15 +113,21 @@ var isTooOld = function (time, now) {
return (now - time) > 300000; return (now - time) > 300000;
}; };
var expireSessions = function (Sessions) { var expireSession = function (Sessions, key) {
var now = +new Date();
Object.keys(Sessions).forEach(function (key) {
var session = Sessions[key]; var session = Sessions[key];
if (isTooOld(Sessions[key].atime, now)) { if (!session) { return; }
if (session.blobstage) { if (session.blobstage) {
session.blobstage.close(); session.blobstage.close();
} }
delete Sessions[key]; delete Sessions[key];
};
var expireSessions = function (Sessions) {
var now = +new Date();
Object.keys(Sessions).forEach(function (key) {
var session = Sessions[key];
if (session && isTooOld(session.atime, now)) {
expireSession(Sessions, key);
} }
}); });
}; };
@ -670,6 +676,29 @@ var makeFileStream = function (root, id, cb) {
}); });
}; };
var clearOwnedChannel = function (Env, channelId, unsafeKey, cb) {
if (typeof(channelId) !== 'string' || channelId.length !== 32) {
return cb('INVALID_ARGUMENTS');
}
if (!(Env.msgStore && Env.msgStore.getChannelMetadata)) {
return cb('E_NOT_IMPLEMENTED');
}
Env.msgStore.getChannelMetadata(channelId, function (e, metadata) {
if (e) { return cb(e); }
if (!(metadata && Array.isArray(metadata.owners))) { return void cb('E_NO_OWNERS'); }
// Confirm that the channel is owned by the user is question
if (metadata.owners.indexOf(unsafeKey) === -1) {
return void cb('INSUFFICIENT_PERMISSIONS');
}
return void Env.msgStore.clearChannel(channelId, function (e) {
cb(e);
});
});
};
var upload = function (Env, publicKey, content, cb) { var upload = function (Env, publicKey, content, cb) {
var paths = Env.paths; var paths = Env.paths;
var dec; var dec;
@ -846,6 +875,7 @@ var isAuthenticatedCall = function (call) {
'GET_LIMIT', 'GET_LIMIT',
'UPLOAD_COMPLETE', 'UPLOAD_COMPLETE',
'UPLOAD_CANCEL', 'UPLOAD_CANCEL',
'EXPIRE_SESSION',
].indexOf(call) !== -1; ].indexOf(call) !== -1;
}; };
@ -1046,7 +1076,16 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
} }
Respond(void 0, dict); Respond(void 0, dict);
}); });
case 'EXPIRE_SESSION':
return void setTimeout(function () {
expireSession(Sessions, safeKey);
Respond(void 0, "OK");
});
case 'CLEAR_OWNED_CHANNEL':
return void clearOwnedChannel(Env, msg[1], publicKey, function (e, response) {
if (e) { return void Respond(e); }
Respond(void 0, response);
});
// restricted to privileged users... // restricted to privileged users...
case 'UPLOAD': case 'UPLOAD':
if (!privileged) { return deny(); } if (!privileged) { return deny(); }

@ -6,6 +6,85 @@ var mkPath = function (env, channelId) {
return Path.join(env.root, channelId.slice(0, 2), channelId) + '.ndjson'; return Path.join(env.root, channelId.slice(0, 2), channelId) + '.ndjson';
}; };
var getMetadataAtPath = function (Env, path, cb) {
var remainder = '';
var stream = Fs.createReadStream(path, 'utf8');
var complete = function (err, data) {
var _cb = cb;
cb = undefined;
if (_cb) { _cb(err, data); }
};
stream.on('data', function (chunk) {
if (!/\n/.test(chunk)) {
remainder += chunk;
return;
}
stream.close();
var metadata = chunk.split('\n')[0];
var parsed = null;
try {
parsed = JSON.parse(metadata);
complete(void 0, parsed);
}
catch (e) {
console.log();
console.error(e);
complete('INVALID_METADATA');
}
});
stream.on('end', function () {
complete(null);
});
stream.on('error', function (e) { complete(e); });
};
var getChannelMetadata = function (Env, channelId, cb) {
var path = mkPath(Env, channelId);
getMetadataAtPath(Env, path, cb);
};
var closeChannel = function (env, channelName, cb) {
if (!env.channels[channelName]) { return; }
try {
env.channels[channelName].writeStream.close();
delete env.channels[channelName];
env.openFiles--;
cb();
} catch (err) {
cb(err);
}
};
var clearChannel = function (env, channelId, cb) {
var path = mkPath(env, channelId);
getMetadataAtPath(env, path, function (e, metadata) {
if (e) { return cb(e); }
if (!metadata) {
return void Fs.truncate(path, 0, function (err) {
if (err) {
return cb(err);
}
cb(void 0);
});
}
var len = JSON.stringify(metadata).length + 1;
// as long as closeChannel is synchronous, this should not cause
// any race conditions. truncate ought to return faster than a channel
// can be opened and read by another user. if that turns out not to be
// the case, we'll need to implement locking.
closeChannel(env, channelId, function (err) {
if (err) { cb(err); }
Fs.truncate(path, len, function (err) {
if (err) { return cb(err); }
cb();
});
});
});
};
var readMessages = function (path, msgHandler, cb) { var readMessages = function (path, msgHandler, cb) {
var remainder = ''; var remainder = '';
var stream = Fs.createReadStream(path, 'utf8'); var stream = Fs.createReadStream(path, 'utf8');
@ -49,22 +128,10 @@ var checkPath = function (path, callback) {
}; };
var removeChannel = function (env, channelName, cb) { var removeChannel = function (env, channelName, cb) {
var filename = Path.join(env.root, channelName.slice(0, 2), channelName + '.ndjson'); var filename = mkPath(env, channelName);
Fs.unlink(filename, cb); Fs.unlink(filename, cb);
}; };
var closeChannel = function (env, channelName, cb) {
if (!env.channels[channelName]) { return; }
try {
env.channels[channelName].writeStream.close();
delete env.channels[channelName];
env.openFiles--;
cb();
} catch (err) {
cb(err);
}
};
var flushUnusedChannels = function (env, cb, frame) { var flushUnusedChannels = function (env, cb, frame) {
var currentTime = +new Date(); var currentTime = +new Date();
@ -260,6 +327,12 @@ module.exports.create = function (conf, cb) {
getChannelSize: function (chanName, cb) { getChannelSize: function (chanName, cb) {
channelBytes(env, chanName, cb); channelBytes(env, chanName, cb);
}, },
getChannelMetadata: function (channelName, cb) {
getChannelMetadata(env, channelName, cb);
},
clearChannel: function (channelName, cb) {
clearChannel(env, channelName, cb);
},
}); });
}); });
setInterval(function () { setInterval(function () {

@ -6,6 +6,8 @@ define([
'css!/bower_components/components-font-awesome/css/font-awesome.min.css', 'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/code/code.less', 'less!/code/code.less',
'less!/customize/src/less/toolbar.less', 'less!/customize/src/less/toolbar.less',
'less!/customize/src/less/cryptpad.less',
'css!cm/lib/codemirror.css', 'css!cm/lib/codemirror.css',
'css!cm/addon/dialog/dialog.css', 'css!cm/addon/dialog/dialog.css',
'css!cm/addon/fold/foldgutter.css', 'css!cm/addon/fold/foldgutter.css',

@ -364,6 +364,21 @@ define([
return; return;
} }
UserList.getLastName(toolbar.$userNameButton, isNew); UserList.getLastName(toolbar.$userNameButton, isNew);
var fmConfig = {
dropArea: $iframe.find('.CodeMirror'),
body: $iframe.find('body'),
onUploaded: function (ev, data) {
//var cursor = editor.getCursor();
//var cleanName = data.name.replace(/[\[\]]/g, '');
//var text = '!['+cleanName+']('+data.url+')';
var parsed = Cryptpad.parsePadUrl(data.url);
var hexFileName = Cryptpad.base64ToHex(parsed.hashData.channel);
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
var mt = '<media-tag src="' + src + '" data-crypto-key="cryptpad:' + parsed.hashData.key + '"></media-tag>';
editor.replaceSelection(mt);
}
};
APP.FM = Cryptpad.createFileManager(fmConfig);
}; };
config.onRemote = function () { config.onRemote = function () {

@ -100,8 +100,18 @@ define([
var text = ''; var text = '';
lines.some(function (line) { lines.some(function (line) {
// lines including a c-style comment are also valuable
var clike = /^\s*(\/\*|\/\/)(.*)?(\*\/)*$/;
if (clike.test(line)) {
line.replace(clike, function (a, one, two) {
if (!(two && two.replace)) { return; }
text = two.replace(/\*\/\s*$/, '').trim();
});
return true;
}
// lisps? // lisps?
var lispy = /^\s*(;|#\|)(.*?)$/; var lispy = /^\s*(;|#\|)+(.*?)$/;
if (lispy.test(line)) { if (lispy.test(line)) {
line.replace(lispy, function (a, one, two) { line.replace(lispy, function (a, one, two) {
text = two; text = two;
@ -111,7 +121,7 @@ define([
// lines beginning with a hash are potentially valuable // lines beginning with a hash are potentially valuable
// works for markdown, python, bash, etc. // works for markdown, python, bash, etc.
var hash = /^#(.*?)$/; var hash = /^#+(.*?)$/;
if (hash.test(line)) { if (hash.test(line)) {
line.replace(hash, function (a, one) { line.replace(hash, function (a, one) {
text = one; text = one;
@ -119,16 +129,6 @@ define([
return true; return true;
} }
// lines including a c-style comment are also valuable
var clike = /^\s*(\/\*|\/\/)(.*)?(\*\/)*$/;
if (clike.test(line)) {
line.replace(clike, function (a, one, two) {
if (!(two && two.replace)) { return; }
text = two.replace(/\*\/\s*$/, '').trim();
});
return true;
}
// TODO make one more pass for multiline comments // TODO make one more pass for multiline comments
}); });

@ -54,7 +54,7 @@ Version 1
if (!hash) { return; } if (!hash) { return; }
var parsed = {}; var parsed = {};
var hashArr = fixDuplicateSlashes(hash).split('/'); var hashArr = fixDuplicateSlashes(hash).split('/');
if (['media', 'file', 'user'].indexOf(type) === -1) { if (['media', 'file', 'user', 'invite'].indexOf(type) === -1) {
parsed.type = 'pad'; parsed.type = 'pad';
if (hash.slice(0,1) !== '/' && hash.length >= 56) { if (hash.slice(0,1) !== '/' && hash.length >= 56) {
// Old hash // Old hash
@ -93,6 +93,16 @@ Version 1
} }
return parsed; return parsed;
} }
if (['invite'].indexOf(type) !== -1) {
parsed.type = 'invite';
if (hashArr[1] && hashArr[1] === '1') {
parsed.version = 1;
parsed.channel = hashArr[2];
parsed.pubkey = hashArr[3].replace(/-/g, '/');
return parsed;
}
return parsed;
}
return; return;
}; };
var parsePadUrl = Hash.parsePadUrl = function (href) { var parsePadUrl = Hash.parsePadUrl = function (href) {
@ -320,5 +330,11 @@ Version 1
return hash; return hash;
}; };
Hash.createInviteUrl = function (curvePublic, channel) {
channel = channel || Hash.createChannelId();
return window.location.origin + '/invite/#/1/' + channel +
'/' + curvePublic.replace(/\//g, '-') + '/';
};
return Hash; return Hash;
}); });

@ -5,8 +5,10 @@ define([
'/customize/application_config.js', '/customize/application_config.js',
'/bower_components/alertifyjs/dist/js/alertify.js', '/bower_components/alertifyjs/dist/js/alertify.js',
'/common/notify.js', '/common/notify.js',
'/common/visible.js' '/common/visible.js',
], function ($, Messages, Util, AppConfig, Alertify, Notify, Visible) { '/common/tippy.min.js',
'css!/common/tippy.css',
], function ($, Messages, Util, AppConfig, Alertify, Notify, Visible, Tippy) {
var UI = {}; var UI = {};
@ -251,9 +253,13 @@ define([
}); });
} }
UI.importContent = function (type, f) { UI.importContent = function (type, f, cfg) {
return function () { return function () {
var $files = $('<input type="file">').click(); var $files = $('<input>', {type:"file"});
if (cfg && cfg.accept) {
$files.attr('accept', cfg.accept);
}
$files.click();
$files.on('change', function (e) { $files.on('change', function (e) {
var file = e.target.files[0]; var file = e.target.files[0];
var reader = new FileReader(); var reader = new FileReader();
@ -270,6 +276,7 @@ define([
var $slideIcon = $('<span>', {"class": "fa fa-file-powerpoint-o file icon slideColor"}); var $slideIcon = $('<span>', {"class": "fa fa-file-powerpoint-o file icon slideColor"});
var $pollIcon = $('<span>', {"class": "fa fa-calendar file icon pollColor"}); var $pollIcon = $('<span>', {"class": "fa fa-calendar file icon pollColor"});
var $whiteboardIcon = $('<span>', {"class": "fa fa-paint-brush whiteboardColor"}); var $whiteboardIcon = $('<span>', {"class": "fa fa-paint-brush whiteboardColor"});
var $contactsIcon = $('<span>', {"class": "fa fa-users friendsColor"});
UI.getIcon = function (type) { UI.getIcon = function (type) {
var $icon; var $icon;
@ -280,11 +287,62 @@ define([
case 'slide': $icon = $slideIcon.clone(); break; case 'slide': $icon = $slideIcon.clone(); break;
case 'poll': $icon = $pollIcon.clone(); break; case 'poll': $icon = $pollIcon.clone(); break;
case 'whiteboard': $icon = $whiteboardIcon.clone(); break; case 'whiteboard': $icon = $whiteboardIcon.clone(); break;
case 'contacts': $icon = $contactsIcon.clone(); break;
default: $icon = $fileIcon.clone(); default: $icon = $fileIcon.clone();
} }
return $icon; return $icon;
}; };
// Tooltips
UI.addTooltips = function () {
var MutationObserver = window.MutationObserver;
var addTippy = function (el) {
if (el.nodeName === 'IFRAME') { return; }
console.log(el);
Tippy(el, {
position: 'bottom',
distance: 0,
performance: true,
delay: [500, 0]
});
};
var $body = $('body');
var $padIframe = $('#pad-iframe').contents().find('body');
$('[title]').each(function (i, el) {
addTippy(el);
});
$('#pad-iframe').contents().find('[title]').each(function (i, el) {
addTippy(el);
});
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.type === 'childList' && mutation.addedNodes.length) {
$body.find('[title]').each(function (i, el) {
addTippy(el);
});
if (!$padIframe.length) { return; }
$padIframe.find('[title]').each(function (i, el) {
addTippy(el);
});
}
});
});
observer.observe($('body')[0], {
attributes: false,
childList: true,
characterData: false,
subtree: true
});
if ($('#pad-iframe').length) {
observer.observe($('#pad-iframe').contents().find('body')[0], {
attributes: false,
childList: true,
characterData: false,
subtree: true
});
}
};
return UI; return UI;
}); });

@ -0,0 +1,761 @@
define([
'jquery',
'/bower_components/chainpad-crypto/crypto.js',
'/common/curve.js',
'/bower_components/marked/marked.min.js',
], function ($, Crypto, Curve, Marked) {
var Msg = {};
var Types = {
message: 'MSG',
update: 'UPDATE',
unfriend: 'UNFRIEND',
mapId: 'MAP_ID',
mapIdAck: 'MAP_ID_ACK'
};
// TODO
// - mute a channel (hide notifications or don't open it?)
var ready = [];
var pending = {};
var pendingRequests = [];
var parseMessage = function (content) {
return Marked(content);
};
var createData = Msg.createData = function (common, hash) {
var proxy = common.getProxy();
return {
channel: hash || common.createChannelId(),
displayName: proxy[common.displayNameKey],
profile: proxy.profile && proxy.profile.view,
edPublic: proxy.edPublic,
curvePublic: proxy.curvePublic,
avatar: proxy.profile && proxy.profile.avatar
};
};
var getFriend = function (common, pubkey) {
var proxy = common.getProxy();
if (pubkey === proxy.curvePublic) {
var data = createData(common);
delete data.channel;
return data;
}
return proxy.friends ? proxy.friends[pubkey] : undefined;
};
var removeFromFriendList = Msg.removeFromFriendList = function (common, curvePublic, cb) {
var proxy = common.getProxy();
if (!proxy.friends) {
return;
}
var friends = proxy.friends;
delete friends[curvePublic];
common.whenRealtimeSyncs(common.getRealtime(), cb);
};
var getFriendList = Msg.getFriendList = function (common) {
var proxy = common.getProxy();
if (!proxy.friends) { proxy.friends = {}; }
return proxy.friends;
};
Msg.getFriendChannelsList = function (common) {
var friends = getFriendList(common);
var list = [];
Object.keys(friends).forEach(function (key) {
if (key === "me") { return; }
list.push(friends[key].channel);
});
return list;
};
// Messaging tools
var avatars = {};
var addToFriendListUI = function (common, $block, open, remove, f) {
var proxy = common.getProxy();
var friends = proxy.friends || {};
if (f === "me") { return; }
var data = friends[f];
var $friend = $('<div>', {'class': 'friend avatar'}).appendTo($block);
$friend.data('key', f);
var $rightCol = $('<span>', {'class': 'right-col'});
$('<span>', {'class': 'name'}).text(data.displayName).appendTo($rightCol);
var $remove = $('<span>', {'class': 'remove fa fa-user-times'}).appendTo($rightCol);
$remove.attr('title', common.Messages.contacts_remove);
$friend.dblclick(function () {
if (data.profile) {
window.open('/profile/#' + data.profile);
}
});
$friend.click(function () {
open(data.curvePublic);
});
$remove.click(function (e) {
e.stopPropagation();
common.confirm(common.Messages._getKey('contacts_confirmRemove', [
common.fixHTML(data.displayName)
]), function (yes) {
if (!yes) { return; }
remove(data.curvePublic);
}, null, true);
});
if (data.avatar && avatars[data.avatar]) {
$friend.append(avatars[data.avatar]);
$friend.append($rightCol);
} else {
common.displayAvatar($friend, data.avatar, data.displayName, function ($img) {
if (data.avatar && $img) {
avatars[data.avatar] = $img[0].outerHTML;
}
$friend.append($rightCol);
});
}
$('<span>', {'class': 'status'}).appendTo($friend);
};
Msg.getFriendListUI = function (common, open, remove) {
var proxy = common.getProxy();
var $block = $('<div>');
var friends = proxy.friends || {};
Object.keys(friends).forEach(function (f) {
addToFriendListUI(common, $block, open, remove, f);
});
return $block;
};
Msg.createOwnedChannel = function (common, channelId, validateKey, owners, cb) {
var network = common.getNetwork();
network.join(channelId).then(function (wc) {
var cfg = {
validateKey: validateKey,
owners: owners
};
var msg = ['GET_HISTORY', wc.id, cfg];
network.sendto(network.historyKeeper, JSON.stringify(msg)).then(cb, function (err) {
throw new Error(err);
});
}, function (err) {
throw new Error(err);
});
};
var channels = Msg.channels = window.channels = {};
var pushMsg = function (common, channel, cryptMsg) {
var msg = channel.encryptor.decrypt(cryptMsg);
var parsedMsg = JSON.parse(msg);
if (parsedMsg[0] === Types.message) {
parsedMsg.shift();
channel.messages.push([cryptMsg.slice(0,64), parsedMsg]);
return true;
}
var proxy;
if (parsedMsg[0] === Types.update) {
proxy = common.getProxy();
if (parsedMsg[1] === common.getProxy().curvePublic) { return; }
var newdata = parsedMsg[3];
var data = getFriend(common, parsedMsg[1]);
var types = [];
Object.keys(newdata).forEach(function (k) {
if (data[k] !== newdata[k]) {
types.push(k);
data[k] = newdata[k];
}
});
channel.updateUI(types);
return;
}
if (parsedMsg[0] === Types.unfriend) {
proxy = common.getProxy();
removeFromFriendList(common, channel.friendEd, function () {
channel.wc.leave(Types.unfriend);
channel.removeUI();
});
return;
}
};
var updateMyData = function (common) {
var friends = getFriendList(common);
var mySyncData = friends.me;
var myData = createData(common);
if (!mySyncData || mySyncData.displayName !== myData.displayName
|| mySyncData.profile !== myData.profile
|| mySyncData.avatar !== myData.avatar) {
delete myData.channel;
Object.keys(channels).forEach(function (chan) {
var channel = channels[chan];
var msg = [Types.update, myData.curvePublic, +new Date(), myData];
var msgStr = JSON.stringify(msg);
var cryptMsg = channel.encryptor.encrypt(msgStr);
channel.wc.bcast(cryptMsg).then(function () {
channel.refresh();
}, function (err) {
console.error(err);
});
});
friends.me = myData;
}
};
var onChannelReady = function (common, chanId) {
if (ready.indexOf(chanId) !== -1) { return; }
ready.push(chanId);
channels[chanId].updateStatus();
var friends = getFriendList(common);
if (ready.length === Object.keys(friends).length) {
// All channels are ready
updateMyData(common);
}
return ready.length;
};
// Id message allows us to map a netfluxId with a public curve key
var onIdMessage = function (common, msg, sender) {
var channel;
var isId = Object.keys(channels).some(function (chanId) {
if (channels[chanId].userList.indexOf(sender) !== -1) {
channel = channels[chanId];
return true;
}
});
if (!isId) { return; }
var decryptedMsg = channel.encryptor.decrypt(msg);
console.log(decryptedMsg);
var parsed = JSON.parse(decryptedMsg);
if (parsed[0] !== Types.mapId && parsed[0] !== Types.mapIdAck) { return; }
if (parsed[2] !== sender || !parsed[1]) { return; }
channel.mapId[sender] = parsed[1];
channel.updateStatus();
if (parsed[0] !== Types.mapId) { return; } // Don't send your key if it's already an ACK
// Answer with your own key
var proxy = common.getProxy();
var network = common.getNetwork();
var rMsg = [Types.mapIdAck, proxy.curvePublic, channel.wc.myID];
var rMsgStr = JSON.stringify(rMsg);
var cryptMsg = channel.encryptor.encrypt(rMsgStr);
network.sendto(sender, cryptMsg);
};
var onDirectMessage = function (common, msg, sender) {
if (sender !== Msg.hk) { return void onIdMessage(common, msg, sender); }
var parsed = JSON.parse(msg);
if ((parsed.validateKey || parsed.owners) && parsed.channel) {
return;
}
if (parsed.state && parsed.state === 1 && parsed.channel) {
if (channels[parsed.channel]) {
// parsed.channel is Ready
// TODO: call a function that shows that the channel is ready? (remove a spinner, ...)
// channel[parsed.channel].ready();
channels[parsed.channel].ready = true;
onChannelReady(common, parsed.channel);
var updateTypes = channels[parsed.channel].updateOnReady;
if (updateTypes) {
channels[parsed.channel].updateUI(updateTypes);
}
}
return;
}
var chan = parsed[3];
if (!chan || !channels[chan]) { return; }
pushMsg(common, channels[chan], parsed[4]);
};
var onMessage = function (common, msg, sender, chan) {
if (!channels[chan.id]) { return; }
var isMessage = pushMsg(common, channels[chan.id], msg);
if (isMessage) {
// Don't notify for your own messages
if (channels[chan.id].wc.myID !== sender) {
channels[chan.id].notify();
}
channels[chan.id].refresh();
}
};
var createChatBox = function (common, $container, curvePublic) {
var data = getFriend(common, curvePublic);
var proxy = common.getProxy();
var $header = $('<div>', {'class': 'header avatar'}).appendTo($container);
/*
var $removeHistory = $('<button>', {
'class': 'remove-history'
}).text('remove chat history').click(function () {
Cryptpad.confirm('are you sure?', function (yes) {
if (!yes) { return; }
Cryptpad.clearOwnedChannel(data.channel, function (e) {
if (e) {
console.error(e);
Cryptpad.alert("Something went wrong");
return;
}
});
});
});
$removeHistory.appendTo($header); //rightCol);
*/
$('<div>', {'class': 'messages'}).appendTo($container);
var $inputBlock = $('<div>', {'class': 'input'}).appendTo($container);
// Input
var channel = channels[data.channel];
var $input = $('<textarea>').appendTo($inputBlock);
$input.attr('placeholder', common.Messages.contacts_typeHere);
var sending = false;
var send = function () {
if (sending) { return; }
if (!$input.val()) { return; }
// Send the message
var msg = [Types.message, proxy.curvePublic, +new Date(), $input.val()];
var msgStr = JSON.stringify(msg);
var cryptMsg = channel.encryptor.encrypt(msgStr);
sending = true;
channel.wc.bcast(cryptMsg).then(function () {
$input.val('');
pushMsg(common, channel, cryptMsg);
channel.refresh();
sending = false;
}, function (err) {
sending = false;
console.error(err);
});
};
$('<button>', {'class': 'btn btn-primary fa fa-paper-plane'})
//.text(common.Messages.contacts_send)
.appendTo($inputBlock).click(send);
/*$input.on('keypress', function (e) {
if (e.which === 13) { send(); }
});*/
var onKeyDown = function (e) {
if (e.keyCode === 13) {
if (e.ctrlKey) {
var val = this.value;
if (typeof this.selectionStart === "number" && typeof this.selectionEnd === "number") {
var start = this.selectionStart;
this.value = val.slice(0, start) + "\n" + val.slice(this.selectionEnd);
this.selectionStart = this.selectionEnd = start + 1;
} else if (document.selection && document.selection.createRange) {
this.focus();
var range = document.selection.createRange();
range.text = "\r\n";
range.collapse(false);
range.select();
}
return false;
}
send();
return false;
}
};
$input.on('keydown', onKeyDown);
// Header
var $rightCol = $('<span>', {'class': 'right-col'});
$('<span>', {'class': 'name'}).text(data.displayName).appendTo($rightCol);
if (data.avatar && avatars[data.avatar]) {
$header.append(avatars[data.avatar]);
$header.append($rightCol);
} else {
common.displayAvatar($header, data.avatar, data.displayName, function ($img) {
if (data.avatar && $img) {
avatars[data.avatar] = $img[0].outerHTML;
}
$header.append($rightCol);
});
}
};
Msg.init = function (common, $listContainer, $msgContainer) {
var network = common.getNetwork();
var proxy = common.getProxy();
Msg.hk = network.historyKeeper;
var friends = getFriendList(common);
network.on('message', function(msg, sender) {
onDirectMessage(common, msg, sender);
});
// Refresh the active channel
var refresh = function (curvePublic) {
if (Msg.active !== curvePublic) { return; }
var data = friends[curvePublic];
if (!data) { return; }
var channel = channels[data.channel];
if (!channel) { return; }
var $chat = $msgContainer.find('.chat').filter(function (idx, el) {
return $(el).data('key') === curvePublic;
});
if (!$chat.length) { return; }
// Add new messages
var messages = channel.messages;
var $messages = $chat.find('.messages');
var $msg, msg, date, name;
var last = typeof(channel.lastDisplayed) === 'number'? channel.lastDisplayed: -1;
for (var i = last + 1; i<messages.length; i++) {
msg = messages[i][1]; // 0 is the hash, 1 the array
$msg = $('<div>', {'class': 'message'}).appendTo($messages);
// date
date = msg[1] ? new Date(msg[1]).toLocaleString() : '?';
//$('<div>', {'class':'date'}).text(date).appendTo($msg);
$msg.attr('title', date);
// name
if (msg[0] !== channel.lastSender) {
name = getFriend(common, msg[0]).displayName;
$('<div>', {'class':'sender'}).text(name).appendTo($msg);
}
channel.lastSender = msg[0];
// content
//$('<div>', {'class':'content'}).text(msg[2]).appendTo($msg);
$('<div>', {'class':'content'}).html(parseMessage(msg[2])).appendTo($msg);
}
$messages.scrollTop($messages[0].scrollHeight);
channel.lastDisplayed = i-1;
channel.unnotify();
if (messages.length > 10) {
var lastKnownMsg = messages[messages.length - 11];
data.lastKnownHash = lastKnownMsg[0];
}
};
// Display a new channel
var display = function (curvePublic) {
$msgContainer.find('.info').hide();
var isNew = false;
var $chat = $msgContainer.find('.chat').filter(function (idx, el) {
return $(el).data('key') === curvePublic;
});
if (!$chat.length) {
$chat = $('<div>', {'class':'chat'})
.data('key', curvePublic).appendTo($msgContainer);
createChatBox(common, $chat, curvePublic);
isNew = true;
}
// Show the correct div
$msgContainer.find('.chat').hide();
$chat.show();
Msg.active = curvePublic;
refresh(curvePublic);
};
var remove = function (curvePublic) {
var data = getFriend(common, curvePublic);
var channel = channels[data.channel];
//var newdata = createData(common, data.channel);
var msg = [Types.unfriend, proxy.curvePublic, +new Date()];
var msgStr = JSON.stringify(msg);
var cryptMsg = channel.encryptor.encrypt(msgStr);
channel.wc.bcast(cryptMsg).then(function () {
removeFromFriendList(common, curvePublic, function () {
channel.wc.leave(Types.unfriend);
channel.removeUI();
});
}, function (err) {
console.error(err);
});
};
// Display friend list
common.getFriendListUI(common, display, remove).appendTo($listContainer);
// Notify on new messages
var notify = function (curvePublic) {
//if (Msg.active === curvePublic) { return; }
var $friend = $listContainer.find('.friend').filter(function (idx, el) {
return $(el).data('key') === curvePublic;
});
$friend.addClass('notify');
common.notify();
};
var unnotify = function (curvePublic) {
var $friend = $listContainer.find('.friend').filter(function (idx, el) {
return $(el).data('key') === curvePublic;
});
$friend.removeClass('notify');
};
var removeUI = function (curvePublic) {
var $friend = $listContainer.find('.friend').filter(function (idx, el) {
return $(el).data('key') === curvePublic;
});
var $chat = $msgContainer.find('.chat').filter(function (idx, el) {
return $(el).data('key') === curvePublic;
});
$friend.remove();
$chat.remove();
$msgContainer.find('.info').show();
};
var updateUI = function (curvePublic, types) {
var data = getFriend(common, curvePublic);
var chan = channels[data.channel];
if (!chan.ready) {
chan.updateOnReady = (chan.updateOnReady || []).concat(types);
return;
}
var $friend = $listContainer.find('.friend').filter(function (idx, el) {
return $(el).data('key') === curvePublic;
});
if (types.indexOf('displayName') >= 0) {
$friend.find('.name').text(data.displayName);
}
if (types.indexOf('avatar') >= 0) {
$friend.find('.default').remove();
$friend.find('media-tag').remove();
if (data.avatar && avatars[data.avatar]) {
$friend.prepend(avatars[data.avatar]);
} else {
common.displayAvatar($friend, data.avatar, data.displayName, function ($img) {
if (data.avatar && $img) {
avatars[data.avatar] = $img[0].outerHTML;
}
});
}
}
};
var updateStatus = function (curvePublic) {
var data = getFriend(common, curvePublic);
var chan = channels[data.channel];
var $friend = $listContainer.find('.friend').filter(function (idx, el) {
return $(el).data('key') === curvePublic;
});
var status = chan.userList.some(function (nId) {
return chan.mapId[nId] === curvePublic;
});
var statusText = status ? 'online' : 'offline';
$friend.find('.status').attr('class', 'status '+statusText);
};
// Open the channels
var openFriendChannel = function (f) {
if (f === "me") { return; }
var data = friends[f];
var keys = Curve.deriveKeys(data.curvePublic, proxy.curvePrivate);
var encryptor = Curve.createEncryptor(keys);
network.join(data.channel).then(function (chan) {
var channel = channels[data.channel] = {
friendEd: f,
keys: keys,
encryptor: encryptor,
messages: [],
refresh: function () { refresh(data.curvePublic); },
notify: function () { notify(data.curvePublic); },
unnotify: function () { unnotify(data.curvePublic); },
removeUI: function () { removeUI(data.curvePublic); },
updateUI: function (types) { updateUI(data.curvePublic, types); },
updateStatus: function () { updateStatus(data.curvePublic); },
wc: chan,
userList: [],
mapId: {}
};
chan.on('message', function (msg, sender) {
onMessage(common, msg, sender, chan);
});
var onJoining = function (peer) {
if (peer === Msg.hk) { return; }
if (channel.userList.indexOf(peer) !== -1) { return; }
channel.userList.push(peer);
var msg = [Types.mapId, proxy.curvePublic, chan.myID];
var msgStr = JSON.stringify(msg);
var cryptMsg = channel.encryptor.encrypt(msgStr);
network.sendto(peer, cryptMsg);
channel.updateStatus();
};
chan.members.forEach(function (peer) {
if (peer === Msg.hk) { return; }
if (channel.userList.indexOf(peer) !== -1) { return; }
channel.userList.push(peer);
});
chan.on('join', onJoining);
chan.on('leave', function (peer) {
var i = channel.userList.indexOf(peer);
while (i !== -1) {
channel.userList.splice(i, 1);
i = channel.userList.indexOf(peer);
}
channel.updateStatus();
});
var cfg = {
validateKey: keys.validateKey,
owners: [proxy.edPublic, data.edPublic],
lastKnownHash: data.lastKnownHash
};
var msg = ['GET_HISTORY', chan.id, cfg];
network.sendto(network.historyKeeper, JSON.stringify(msg))
.then($.noop, function (err) {
throw new Error(err);
});
}, function (err) {
console.error(err);
});
};
Object.keys(friends).forEach(openFriendChannel);
var checkNewFriends = function () {
Object.keys(friends).forEach(function (f) {
var $friend = $listContainer.find('.friend').filter(function (idx, el) {
return $(el).data('key') === f;
});
if (!$friend.length) {
openFriendChannel(f);
addToFriendListUI(common, $listContainer.find('> div'), display, remove, f);
}
});
};
common.onDisplayNameChanged(function () {
checkNewFriends();
updateMyData(common);
});
};
// Invitation
var addToFriendList = Msg.addToFriendList = function (common, data, cb) {
var proxy = common.getProxy();
if (!proxy.friends) {
proxy.friends = {};
}
var friends = proxy.friends;
var pubKey = data.curvePublic;
if (pubKey === proxy.curvePublic) { return void cb("E_MYKEY"); }
friends[pubKey] = data;
common.whenRealtimeSyncs(common.getRealtime(), function () {
cb();
common.pinPads([data.channel]);
});
common.changeDisplayName(proxy[common.displayNameKey]);
};
Msg.addDirectMessageHandler = function (common) {
var network = common.getNetwork();
if (!network) { return void console.error('Network not ready'); }
network.on('message', function (message, sender) {
var msg;
if (sender === network.historyKeeper) { return; }
try {
var parsed = common.parsePadUrl(window.location.href);
if (!parsed.hashData) { return; }
var chan = parsed.hashData.channel;
// Decrypt
var keyStr = parsed.hashData.key;
var cryptor = Crypto.createEditCryptor(keyStr);
var key = cryptor.cryptKey;
var decryptMsg;
try {
decryptMsg = Crypto.decrypt(message, key);
} catch (e) {
// If we can't decrypt, it means it is not a friend request message
}
if (!decryptMsg) { return; }
// Parse
msg = JSON.parse(decryptMsg);
if (msg[1] !== parsed.hashData.channel) { return; }
var msgData = msg[2];
var msgStr;
if (msg[0] === "FRIEND_REQ") {
msg = ["FRIEND_REQ_NOK", chan];
var todo = function (yes) {
if (yes) {
pending[sender] = msgData;
msg = ["FRIEND_REQ_OK", chan, createData(common, msgData.channel)];
}
msgStr = Crypto.encrypt(JSON.stringify(msg), key);
network.sendto(sender, msgStr);
};
var existing = getFriend(common, msgData.curvePublic);
if (existing) {
todo(true);
return;
}
var confirmMsg = common.Messages._getKey('contacts_request', [
common.fixHTML(msgData.displayName)
]);
common.confirm(confirmMsg, todo, null, true);
return;
}
if (msg[0] === "FRIEND_REQ_OK") {
var idx = pendingRequests.indexOf(sender);
if (idx !== -1) { pendingRequests.splice(idx, 1); }
addToFriendList(common, msgData, function (err) {
if (err) {
return void common.log(common.Messages.contacts_addError);
}
common.log(common.Messages.contacts_added);
var msg = ["FRIEND_REQ_ACK", chan];
var msgStr = Crypto.encrypt(JSON.stringify(msg), key);
network.sendto(sender, msgStr);
});
return;
}
if (msg[0] === "FRIEND_REQ_NOK") {
var i = pendingRequests.indexOf(sender);
if (i !== -1) { pendingRequests.splice(i, 1); }
common.log(common.Messages.contacts_rejected);
var proxy = common.getProxy();
common.changeDisplayName(proxy[common.displayNameKey]);
return;
}
if (msg[0] === "FRIEND_REQ_ACK") {
var data = pending[sender];
if (!data) { return; }
addToFriendList(common, data, function (err) {
if (err) {
return void common.log(common.Messages.contacts_addError);
}
common.log(common.Messages.contacts_added);
});
return;
}
// TODO: timeout ACK: warn the user
} catch (e) {
console.error("Cannot parse direct message", msg || message, "from", sender, e);
}
});
};
Msg.getPending = function () {
return pendingRequests;
};
Msg.inviteFromUserlist = function (common, netfluxId) {
var network = common.getNetwork();
var parsed = common.parsePadUrl(window.location.href);
if (!parsed.hashData) { return; }
// Message
var chan = parsed.hashData.channel;
var myData = createData(common);
var msg = ["FRIEND_REQ", chan, myData];
// Encryption
var keyStr = parsed.hashData.key;
var cryptor = Crypto.createEditCryptor(keyStr);
var key = cryptor.cryptKey;
var msgStr = Crypto.encrypt(JSON.stringify(msg), key);
// Send encrypted message
if (pendingRequests.indexOf(netfluxId) === -1) {
pendingRequests.push(netfluxId);
var proxy = common.getProxy();
common.changeDisplayName(proxy[common.displayNameKey]);
}
network.sendto(netfluxId, msgStr);
};
return Msg;
});

@ -52,17 +52,19 @@ define(function () {
name: exp.myUserName, name: exp.myUserName,
uid: Cryptpad.getUid(), uid: Cryptpad.getUid(),
avatar: Cryptpad.getAvatarUrl(), avatar: Cryptpad.getAvatarUrl(),
profile: Cryptpad.getProfileUrl() profile: Cryptpad.getProfileUrl(),
curvePublic: Cryptpad.getProxy().curvePublic
}; };
addToUserData(myData); addToUserData(myData);
Cryptpad.setAttribute('username', exp.myUserName, function (err) { /*Cryptpad.setAttribute('username', exp.myUserName, function (err) {
if (err) { if (err) {
console.log("Couldn't set username"); console.log("Couldn't set username");
console.error(err); console.error(err);
return; return;
} }
if (typeof cb === "function") { cb(); } if (typeof cb === "function") { cb(); }
}); });*/
if (typeof cb === "function") { cb(); }
}; };
exp.getLastName = function ($changeNameButton, isNew) { exp.getLastName = function ($changeNameButton, isNew) {
@ -81,7 +83,8 @@ define(function () {
name: "", name: "",
uid: Cryptpad.getUid(), uid: Cryptpad.getUid(),
avatar: Cryptpad.getAvatarUrl(), avatar: Cryptpad.getAvatarUrl(),
profile: Cryptpad.getProfileUrl() profile: Cryptpad.getProfileUrl(),
curvePublic: Cryptpad.getProxy().curvePublic
}; };
addToUserData(myData); addToUserData(myData);
onLocal(); onLocal();

@ -10,6 +10,7 @@ define([
'/common/common-userlist.js', '/common/common-userlist.js',
'/common/common-title.js', '/common/common-title.js',
'/common/common-metadata.js', '/common/common-metadata.js',
'/common/common-messaging.js',
'/common/common-codemirror.js', '/common/common-codemirror.js',
'/common/common-file.js', '/common/common-file.js',
'/file/file-crypto.js', '/file/file-crypto.js',
@ -19,7 +20,12 @@ define([
'/customize/application_config.js', '/customize/application_config.js',
'/common/media-tag.js', '/common/media-tag.js',
], function ($, Config, Messages, Store, Util, Hash, UI, History, UserList, Title, Metadata, ], function ($, Config, Messages, Store, Util, Hash, UI, History, UserList, Title, Metadata,
CodeMirror, Files, FileCrypto, Clipboard, Pinpad, AppConfig, MediaTag) { Messaging, CodeMirror, Files, FileCrypto, Clipboard, Pinpad, AppConfig, MediaTag) {
// Configure MediaTags to use our local viewer
if (MediaTag && MediaTag.PdfPlugin) {
MediaTag.PdfPlugin.viewer = '/common/pdfjs/web/viewer.html';
}
/* This file exposes functionality which is specific to Cryptpad, but not to /* This file exposes functionality which is specific to Cryptpad, but not to
any particular pad type. This includes functions for committing metadata any particular pad type. This includes functions for committing metadata
@ -35,6 +41,7 @@ define([
donateURL: 'https://accounts.cryptpad.fr/#/donate?on=' + origin, donateURL: 'https://accounts.cryptpad.fr/#/donate?on=' + origin,
upgradeURL: 'https://accounts.cryptpad.fr/#/?on=' + origin, upgradeURL: 'https://accounts.cryptpad.fr/#/?on=' + origin,
account: {}, account: {},
MediaTag: MediaTag,
}; };
// constants // constants
@ -69,6 +76,7 @@ define([
common.notify = UI.notify; common.notify = UI.notify;
common.unnotify = UI.unnotify; common.unnotify = UI.unnotify;
common.getIcon = UI.getIcon; common.getIcon = UI.getIcon;
common.addTooltips = UI.addTooltips;
// import common utilities for export // import common utilities for export
common.find = Util.find; common.find = Util.find;
@ -107,6 +115,18 @@ define([
common.findWeaker = Hash.findWeaker; common.findWeaker = Hash.findWeaker;
common.findStronger = Hash.findStronger; common.findStronger = Hash.findStronger;
common.serializeHash = Hash.serializeHash; common.serializeHash = Hash.serializeHash;
common.createInviteUrl = Hash.createInviteUrl;
// Messaging
common.initMessaging = Messaging.init;
common.addDirectMessageHandler = Messaging.addDirectMessageHandler;
common.inviteFromUserlist = Messaging.inviteFromUserlist;
common.createOwnedChannel = Messaging.createOwnedChannel;
common.getFriendList = Messaging.getFriendList;
common.getFriendChannelsList = Messaging.getFriendChannelsList;
common.getFriendListUI = Messaging.getFriendListUI;
common.createData = Messaging.createData;
common.getPendingInvites = Messaging.getPending;
// Userlist // Userlist
common.createUserList = UserList.create; common.createUserList = UserList.create;
@ -148,6 +168,14 @@ define([
} }
return; return;
}; };
common.getUserlist = function () {
if (store) {
if (store.getProxy() && store.getProxy().info) {
return store.getProxy().info.userList;
}
}
return;
};
common.getProfileUrl = function () { common.getProfileUrl = function () {
if (store && store.getProfile()) { if (store && store.getProfile()) {
return store.getProfile().view; return store.getProfile().view;
@ -158,7 +186,16 @@ define([
return store.getProfile().avatar; return store.getProfile().avatar;
} }
}; };
common.getDisplayName = function () {
if (getProxy()) {
return getProxy()[common.displayNameKey] || '';
}
return '';
};
var randomToken = function () {
return Math.random().toString(16).replace(/0./, '');
};
var feedback = common.feedback = function (action, force) { var feedback = common.feedback = function (action, force) {
if (force !== true) { if (force !== true) {
if (!action) { return; } if (!action) { return; }
@ -167,7 +204,7 @@ define([
} catch (e) { return void console.error(e); } } catch (e) { return void console.error(e); }
} }
var href = '/common/feedback.html?' + action + '=' + (+new Date()); var href = '/common/feedback.html?' + action + '=' + randomToken();
$.ajax({ $.ajax({
type: "HEAD", type: "HEAD",
url: href, url: href,
@ -177,7 +214,11 @@ define([
common.reportAppUsage = function () { common.reportAppUsage = function () {
var pattern = window.location.pathname.split('/') var pattern = window.location.pathname.split('/')
.filter(function (x) { return x; }).join('.'); .filter(function (x) { return x; }).join('.');
if (/^#\/1\/view\//.test(window.location.hash)) {
feedback(pattern + '_VIEW');
} else {
feedback(pattern); feedback(pattern);
}
}; };
common.reportScreenDimensions = function () { common.reportScreenDimensions = function () {
@ -185,6 +226,9 @@ define([
var w = window.innerWidth; var w = window.innerWidth;
feedback('DIMENSIONS:' + h + 'x' + w); feedback('DIMENSIONS:' + h + 'x' + w);
}; };
common.reportLanguage = function () {
feedback('LANG_' + Messages._languageUsed);
};
common.getUid = function () { common.getUid = function () {
if (store && store.getProxy() && store.getProxy().proxy) { if (store && store.getProxy() && store.getProxy().proxy) {
@ -199,13 +243,29 @@ define([
return; return;
}; };
common.infiniteSpinnerDetected = false;
var whenRealtimeSyncs = common.whenRealtimeSyncs = function (realtime, cb) { var whenRealtimeSyncs = common.whenRealtimeSyncs = function (realtime, cb) {
realtime.sync(); realtime.sync();
window.setTimeout(function () { window.setTimeout(function () {
if (realtime.getAuthDoc() === realtime.getUserDoc()) { if (realtime.getAuthDoc() === realtime.getUserDoc()) {
return void cb(); return void cb();
} }
var to = setTimeout(function () {
realtime.abort();
// don't launch more than one popup
if (common.infiniteSpinnerDetected) { return; }
// inform the user their session is in a bad state
common.confirm(Messages.realtime_unrecoverableError, function (yes) {
if (!yes) { return; }
window.location.reload();
});
common.infiniteSpinnerDetected = true;
}, 30000);
realtime.onSettle(function () { realtime.onSettle(function () {
clearTimeout(to);
cb(); cb();
}); });
}, 0); }, 0);
@ -304,6 +364,21 @@ define([
typeof(proxy.edPublic) === 'string'; typeof(proxy.edPublic) === 'string';
}; };
common.hasCurveKeys = function (proxy) {
return typeof(proxy) === 'object' &&
typeof(proxy.curvePrivate) === 'string' &&
typeof(proxy.curvePublic) === 'string';
};
common.getPublicKeys = function (proxy) {
proxy = proxy || common.getProxy();
if (!proxy || !proxy.edPublic || !proxy.curvePublic) { return; }
return {
curve: proxy.curvePublic,
ed: proxy.edPublic,
};
};
common.isArray = $.isArray; common.isArray = $.isArray;
/* /*
@ -711,6 +786,11 @@ define([
if (avatarChan) { list.push(avatarChan); } if (avatarChan) { list.push(avatarChan); }
} }
if (getProxy().friends) {
var fList = common.getFriendChannelsList(common);
list = list.concat(fList);
}
list.push(common.base64ToHex(userChannel)); list.push(common.base64ToHex(userChannel));
list.sort(); list.sort();
@ -867,6 +947,11 @@ define([
common.getPinnedUsage(todo); common.getPinnedUsage(todo);
}; };
common.clearOwnedChannel = function (channel, cb) {
if (!pinsReady()) { return void cb('RPC_NOT_READY'); }
rpc.clearOwnedChannel(channel, cb);
};
common.uploadComplete = function (cb) { common.uploadComplete = function (cb) {
if (!pinsReady()) { return void cb('RPC_NOT_READY'); } if (!pinsReady()) { return void cb('RPC_NOT_READY'); }
rpc.uploadComplete(cb); rpc.uploadComplete(cb);
@ -1009,7 +1094,7 @@ define([
.click(prepareFeedback(type)) .click(prepareFeedback(type))
.click(UI.importContent('text/plain', function (content, file) { .click(UI.importContent('text/plain', function (content, file) {
callback(content, file); callback(content, file);
})); }, {accept: data ? data.accept : undefined}));
} }
break; break;
case 'upload': case 'upload':
@ -1185,7 +1270,6 @@ define([
return button; return button;
}; };
var emoji_patt = /([\uD800-\uDBFF][\uDC00-\uDFFF])/; var emoji_patt = /([\uD800-\uDBFF][\uDC00-\uDFFF])/;
var isEmoji = function (str) { var isEmoji = function (str) {
return emoji_patt.test(str); return emoji_patt.test(str);
@ -1206,6 +1290,7 @@ define([
var emojis = emojiStringToArray(str); var emojis = emojiStringToArray(str);
return isEmoji(emojis[0])? emojis[0]: str[0]; return isEmoji(emojis[0])? emojis[0]: str[0];
}; };
$(window.document).on('decryption', function (e) { $(window.document).on('decryption', function (e) {
var decrypted = e.originalEvent; var decrypted = e.originalEvent;
if (decrypted.callback) { if (decrypted.callback) {
@ -1277,7 +1362,6 @@ define([
var $img = $('<media-tag>').appendTo($container); var $img = $('<media-tag>').appendTo($container);
$img.attr('src', src); $img.attr('src', src);
$img.attr('data-crypto-key', 'cryptpad:' + cryptKey); $img.attr('data-crypto-key', 'cryptpad:' + cryptKey);
MediaTag($img[0]);
var observer = new MutationObserver(function(mutations) { var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) { mutations.forEach(function(mutation) {
if (mutation.type === 'childList' && mutation.addedNodes.length) { if (mutation.type === 'childList' && mutation.addedNodes.length) {
@ -1288,28 +1372,33 @@ define([
} }
var $image = $img.find('img'); var $image = $img.find('img');
var onLoad = function () { var onLoad = function () {
var w = $image.width(); var img = new Image();
var h = $image.height(); img.onload = function () {
var w = img.width;
var h = img.height;
if (w>h) { if (w>h) {
$image.css('max-height', '100%'); $image.css('max-height', '100%');
$img.css('flex-direction', 'row'); $img.css('flex-direction', 'column');
if (cb) { cb($img); } if (cb) { cb($img); }
return; return;
} }
$image.css('max-width', '100%'); $image.css('max-width', '100%');
$img.css('flex-direction', 'column'); $img.css('flex-direction', 'row');
if (cb) { cb($img); } if (cb) { cb($img); }
}; };
img.src = $image.attr('src');
};
if ($image[0].complete) { onLoad(); } if ($image[0].complete) { onLoad(); }
$image.on('load', onLoad); $image.on('load', onLoad);
} }
}); });
});
observer.observe($img[0], { observer.observe($img[0], {
attributes: false, attributes: false,
childList: true, childList: true,
characterData: false characterData: false
}); });
}); MediaTag($img[0]);
}); });
} }
}; };
@ -1582,8 +1671,7 @@ define([
//var $userbig = $('<span>', {'class': 'big'}).append($displayedName.clone()); //var $userbig = $('<span>', {'class': 'big'}).append($displayedName.clone());
var $userButton = $('<div>').append($icon);//.append($userbig); var $userButton = $('<div>').append($icon);//.append($userbig);
if (account) { if (account) {
$userButton = $('<div>').append(accountName);
$userButton = $('<div>').append(accountName.slice(0,1).toUpperCase());
} }
/*if (account && config.displayNameCls) { /*if (account && config.displayNameCls) {
$userbig.append($('<span>', {'class': 'account-name'}).text('(' + accountName + ')')); $userbig.append($('<span>', {'class': 'account-name'}).text('(' + accountName + ')'));
@ -1600,6 +1688,23 @@ define([
}; };
var $userAdmin = createDropdown(dropdownConfigUser); var $userAdmin = createDropdown(dropdownConfigUser);
if (account && !config.static && store) {
var $avatar = $userAdmin.find('.buttonTitle');
var updateButton = function (newName) {
var profile = store.getProfile();
var url = profile && profile.avatar;
$avatar.html('');
common.displayAvatar($avatar, url, newName, function ($img) {
if ($img) {
$userAdmin.find('button').addClass('avatar');
}
});
};
common.onDisplayNameChanged(updateButton);
updateButton(common.getDisplayName());
}
$userAdmin.find('a.logout').click(function () { $userAdmin.find('a.logout').click(function () {
common.logout(); common.logout();
window.location.href = '/'; window.location.href = '/';
@ -1691,9 +1796,16 @@ define([
Store.ready(function (err, storeObj) { Store.ready(function (err, storeObj) {
store = common.store = env.store = storeObj; store = common.store = env.store = storeObj;
common.addDirectMessageHandler(common);
common.addTooltips();
var proxy = getProxy(); var proxy = getProxy();
var network = getNetwork(); var network = getNetwork();
if (Object.keys(proxy).length === 1) {
feedback("FIRST_APP_USE", true);
}
if (typeof(window.Proxy) === 'undefined') { if (typeof(window.Proxy) === 'undefined') {
feedback("NO_PROXIES"); feedback("NO_PROXIES");
} }
@ -1703,6 +1815,7 @@ define([
} }
common.reportScreenDimensions(); common.reportScreenDimensions();
common.reportLanguage();
$(function() { $(function() {
// Race condition : if document.body is undefined when alertify.js is loaded, Alertify // Race condition : if document.body is undefined when alertify.js is loaded, Alertify

@ -0,0 +1,51 @@
define([
'/common/curve.js',
'/bower_components/chainpad-listmap/chainpad-listmap.js',
], function (Curve, Listmap) {
var Edit = {};
Edit.create = function (config, cb) { //network, channel, theirs, mine, cb) {
var network = config.network;
var channel = config.channel;
var keys = config.keys;
try {
var encryptor = Curve.createEncryptor(keys);
var lm = Listmap.create({
network: network,
data: {},
channel: channel,
readOnly: false,
validateKey: keys.validateKey || undefined,
crypto: encryptor,
userName: 'lol',
logLevel: 1,
});
var done = function () {
// TODO make this abort and disconnect the session after the
// user has finished making changes to the object, and they
// have propagated.
};
lm.proxy
.on('create', function () {
console.log('created');
})
.on('ready', function () {
console.log('ready');
cb(lm, done);
})
.on('disconnect', function () {
console.log('disconnected');
})
.on('change', [], function (o, n, p) {
console.log(o, n, p);
});
} catch (e) {
console.error(e);
}
};
return Edit;
});

@ -0,0 +1,86 @@
define([
'/bower_components/tweetnacl/nacl-fast.min.js',
], function () {
var Nacl = window.nacl;
var Curve = {};
var concatenateUint8s = function (A) {
var len = 0;
var offset = 0;
A.forEach(function (uints) {
len += uints.length || 0;
});
var c = new Uint8Array(len);
A.forEach(function (x) {
c.set(x, offset);
offset += x.length;
});
return c;
};
var encodeBase64 = Nacl.util.encodeBase64;
var decodeBase64 = Nacl.util.decodeBase64;
var decodeUTF8 = Nacl.util.decodeUTF8;
var encodeUTF8 = Nacl.util.encodeUTF8;
Curve.encrypt = function (message, secret) {
var buffer = decodeUTF8(message);
var nonce = Nacl.randomBytes(24);
var box = Nacl.box.after(buffer, nonce, secret);
return encodeBase64(nonce) + '|' + encodeBase64(box);
};
Curve.decrypt = function (packed, secret) {
var unpacked = packed.split('|');
var nonce = decodeBase64(unpacked[0]);
var box = decodeBase64(unpacked[1]);
var message = Nacl.box.open.after(box, nonce, secret);
return encodeUTF8(message);
};
Curve.signAndEncrypt = function (msg, cryptKey, signKey) {
var packed = Curve.encrypt(msg, cryptKey);
return encodeBase64(Nacl.sign(decodeUTF8(packed), signKey));
};
Curve.openSigned = function (msg, cryptKey /*, validateKey STUBBED*/) {
var content = decodeBase64(msg).subarray(64);
return Curve.decrypt(encodeUTF8(content), cryptKey);
};
Curve.deriveKeys = function (theirs, mine) {
var pub = decodeBase64(theirs);
var secret = decodeBase64(mine);
var sharedSecret = Nacl.box.before(pub, secret);
var salt = decodeUTF8('CryptPad.signingKeyGenerationSalt');
// 64 uint8s
var hash = Nacl.hash(concatenateUint8s([salt, sharedSecret]));
var signKp = Nacl.sign.keyPair.fromSeed(hash.subarray(0, 32));
var cryptKey = hash.subarray(32, 64);
return {
cryptKey: encodeBase64(cryptKey),
signKey: encodeBase64(signKp.secretKey),
validateKey: encodeBase64(signKp.publicKey)
};
};
Curve.createEncryptor = function (keys) {
var cryptKey = decodeBase64(keys.cryptKey);
var signKey = decodeBase64(keys.signKey);
var validateKey = decodeBase64(keys.validateKey);
return {
encrypt: function (msg) {
return Curve.signAndEncrypt(msg, cryptKey, signKey);
},
decrypt: function (packed) {
return Curve.openSigned(packed, cryptKey, validateKey);
}
};
};
return Curve;
});

@ -143,7 +143,17 @@ define([
DiffMd.apply = function (newHtml, $content) { DiffMd.apply = function (newHtml, $content) {
var id = $content.attr('id'); var id = $content.attr('id');
if (!id) { throw new Error("The element must have a valid id"); } if (!id) { throw new Error("The element must have a valid id"); }
var $div = $('<div>', {id: id}).append(newHtml); var pattern = /(<media-tag src="([^"]*)" data-crypto-key="([^"]*)">)<\/media-tag>/g;
var newHtmlFixed = newHtml.replace(pattern, function (all, tag, src) {
var mt = tag;
if (mediaMap[src]) {
mediaMap[src].forEach(function (n) {
mt += n.outerHTML;
});
}
return mt + '</media-tag>';
});
var $div = $('<div>', {id: id}).append(newHtmlFixed);
var Dom = domFromHTML($('<div>').append($div).html()); var Dom = domFromHTML($('<div>').append($div).html());
var oldDom = domFromHTML($content[0].outerHTML); var oldDom = domFromHTML($content[0].outerHTML);
var patch = makeDiff(oldDom, Dom, id); var patch = makeDiff(oldDom, Dom, id);
@ -154,9 +164,11 @@ define([
var $mts = $content.find('media-tag:not(:has(*))'); var $mts = $content.find('media-tag:not(:has(*))');
$mts.each(function (i, el) { $mts.each(function (i, el) {
MediaTag(el); MediaTag(el);
console.log(el.outerHTML);
var observer = new MutationObserver(function(mutations) { var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) { mutations.forEach(function(mutation) {
if (mutation.type === 'childList') { if (mutation.type === 'childList') {
//console.log(el.outerHTML);
var list_values = [].slice.call(el.children); var list_values = [].slice.call(el.children);
mediaMap[el.getAttribute('src')] = list_values; mediaMap[el.getAttribute('src')] = list_values;
} }

@ -206,7 +206,8 @@ define([
} }
// if the user is logged in, but does not have signing keys... // if the user is logged in, but does not have signing keys...
if (Cryptpad.isLoggedIn() && !Cryptpad.hasSigningKeys(proxy)) { if (Cryptpad.isLoggedIn() && (!Cryptpad.hasSigningKeys(proxy) ||
!Cryptpad.hasCurveKeys(proxy))) {
return void requestLogin(); return void requestLogin();
} }
@ -218,8 +219,11 @@ define([
// Trigger userlist update when the avatar has changed // Trigger userlist update when the avatar has changed
Cryptpad.changeDisplayName(proxy[Cryptpad.displayNameKey]); Cryptpad.changeDisplayName(proxy[Cryptpad.displayNameKey]);
}); });
proxy.on('change', ['friends'], function () {
// Trigger userlist update when the avatar has changed
Cryptpad.changeDisplayName(proxy[Cryptpad.displayNameKey]);
});
proxy.on('change', [tokenKey], function () { proxy.on('change', [tokenKey], function () {
console.log('wut');
var localToken = tryParsing(localStorage.getItem(tokenKey)); var localToken = tryParsing(localStorage.getItem(tokenKey));
if (localToken !== proxy[tokenKey]) { if (localToken !== proxy[tokenKey]) {
return void requestLogin(); return void requestLogin();

@ -22,7 +22,12 @@ define([
// 16 bytes for a deterministic channel key // 16 bytes for a deterministic channel key
var channelSeed = dispense(16); var channelSeed = dispense(16);
// 32 bytes for a curve key // 32 bytes for a curve key
opt.curveSeed = dispense(32); var curveSeed = dispense(32);
var curvePair = Nacl.box.keyPair.fromSecretKey(new Uint8Array(curveSeed));
opt.curvePrivate = Nacl.util.encodeBase64(curvePair.secretKey);
opt.curvePublic = Nacl.util.encodeBase64(curvePair.publicKey);
// 32 more for a signing key // 32 more for a signing key
var edSeed = opt.edSeed = dispense(32); var edSeed = opt.edSeed = dispense(32);
@ -109,6 +114,9 @@ define([
res.edPrivate = opt.edPrivate; res.edPrivate = opt.edPrivate;
res.edPublic = opt.edPublic; res.edPublic = opt.edPublic;
res.curvePrivate = opt.curvePrivate;
res.curvePublic = opt.curvePublic;
// they tried to just log in but there's no such user // they tried to just log in but there's no such user
if (!isRegister && isProxyEmpty(rt.proxy)) { if (!isRegister && isProxyEmpty(rt.proxy)) {
rt.network.disconnect(); // clean up after yourself rt.network.disconnect(); // clean up after yourself

File diff suppressed because one or more lines are too long

@ -0,0 +1,828 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Class: AnnotationBorderStyle</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Class: AnnotationBorderStyle</h1>
<section>
<header>
<h2>AnnotationBorderStyle</h2>
</header>
<article>
<div class="container-overview">
<h4 class="name" id="AnnotationBorderStyle"><span class="type-signature"></span>new AnnotationBorderStyle<span class="signature">()</span><span class="type-signature"></span></h4>
<div class="description">
Contains all data regarding an annotation's border style.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="core_annotation.js.html">core/annotation.js</a>, <a href="core_annotation.js.html#line449">line 449</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id=".setDashArray"><span class="type-signature">(static) </span>setDashArray<span class="signature">(dashArray)</span><span class="type-signature"></span></h4>
<div class="description">
Set the dash array.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>dashArray</code></td>
<td class="type">
<span class="param-type">Array</span>
</td>
<td class="description last">The dash array with at least one element</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="core_annotation.js.html">core/annotation.js</a>, <a href="core_annotation.js.html#line521">line 521</a>
</li></ul></dd>
</dl>
<h4 class="name" id=".setHorizontalCornerRadius"><span class="type-signature">(static) </span>setHorizontalCornerRadius<span class="signature">(radius)</span><span class="type-signature"></span></h4>
<div class="description">
Set the horizontal corner radius (from a Border dictionary).
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>radius</code></td>
<td class="type">
<span class="param-type">integer</span>
</td>
<td class="description last">The horizontal corner radius</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="core_annotation.js.html">core/annotation.js</a>, <a href="core_annotation.js.html#line557">line 557</a>
</li></ul></dd>
</dl>
<h4 class="name" id=".setStyle"><span class="type-signature">(static) </span>setStyle<span class="signature">(style)</span><span class="type-signature"></span></h4>
<div class="description">
Set the style.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>style</code></td>
<td class="type">
<span class="param-type">Object</span>
</td>
<td class="description last">The style object</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="core_annotation.js.html">core/annotation.js</a>, <a href="core_annotation.js.html#line484">line 484</a>
</li></ul></dd>
<dt class="tag-see">See:</dt>
<dd class="tag-see">
<ul>
<li><a href="shared_util.js.html">shared/util.js</a></li>
</ul>
</dd>
</dl>
<h4 class="name" id=".setVerticalCornerRadius"><span class="type-signature">(static) </span>setVerticalCornerRadius<span class="signature">(radius)</span><span class="type-signature"></span></h4>
<div class="description">
Set the vertical corner radius (from a Border dictionary).
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>radius</code></td>
<td class="type">
<span class="param-type">integer</span>
</td>
<td class="description last">The vertical corner radius</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="core_annotation.js.html">core/annotation.js</a>, <a href="core_annotation.js.html#line571">line 571</a>
</li></ul></dd>
</dl>
<h4 class="name" id=".setWidth"><span class="type-signature">(static) </span>setWidth<span class="signature">(width)</span><span class="type-signature"></span></h4>
<div class="description">
Set the width.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>width</code></td>
<td class="type">
<span class="param-type">integer</span>
</td>
<td class="description last">The width</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="core_annotation.js.html">core/annotation.js</a>, <a href="core_annotation.js.html#line470">line 470</a>
</li></ul></dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Externals</h3><ul><li><a href="external-Promise.html">Promise</a></li></ul><h3>Classes</h3><ul><li><a href="AnnotationBorderStyle.html">AnnotationBorderStyle</a></li><li><a href="AnnotationFactory.html">AnnotationFactory</a></li><li><a href="PageViewport.html">PageViewport</a></li><li><a href="PDFDataRangeTransport.html">PDFDataRangeTransport</a></li><li><a href="PDFDocumentLoadingTask.html">PDFDocumentLoadingTask</a></li><li><a href="PDFDocumentProxy.html">PDFDocumentProxy</a></li><li><a href="PDFJS.html">PDFJS</a></li><li><a href="PDFPageProxy.html">PDFPageProxy</a></li><li><a href="PDFWorker.html">PDFWorker</a></li><li><a href="RenderTask.html">RenderTask</a></li></ul><h3>Global</h3><ul><li><a href="global.html#_UnsupportedManager">_UnsupportedManager</a></li><li><a href="global.html#arrayByteLength">arrayByteLength</a></li><li><a href="global.html#arraysToBytes">arraysToBytes</a></li><li><a href="global.html#createPromiseCapability">createPromiseCapability</a></li><li><a href="global.html#createValidAbsoluteUrl">createValidAbsoluteUrl</a></li><li><a href="global.html#getDocument">getDocument</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Jun 12 2017 08:43:32 GMT+0000 (Coordinated Universal Time)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

@ -0,0 +1,376 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Class: AnnotationFactory</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Class: AnnotationFactory</h1>
<section>
<header>
<h2>AnnotationFactory</h2>
</header>
<article>
<div class="container-overview">
<h4 class="name" id="AnnotationFactory"><span class="type-signature"></span>new AnnotationFactory<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="core_annotation.js.html">core/annotation.js</a>, <a href="core_annotation.js.html#line31">line 31</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="create"><span class="type-signature"></span>create<span class="signature">(xref, ref, pdfManager, idFactory)</span><span class="type-signature"> &rarr; {<a href="Annotation.html">Annotation</a>}</span></h4>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>xref</code></td>
<td class="type">
<span class="param-type">XRef</span>
</td>
<td class="description last"></td>
</tr>
<tr>
<td class="name"><code>ref</code></td>
<td class="type">
<span class="param-type">Object</span>
</td>
<td class="description last"></td>
</tr>
<tr>
<td class="name"><code>pdfManager</code></td>
<td class="type">
<span class="param-type">PDFManager</span>
</td>
<td class="description last"></td>
</tr>
<tr>
<td class="name"><code>idFactory</code></td>
<td class="type">
<span class="param-type">Object</span>
</td>
<td class="description last"></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="core_annotation.js.html">core/annotation.js</a>, <a href="core_annotation.js.html#line40">line 40</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type"><a href="Annotation.html">Annotation</a></span>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Externals</h3><ul><li><a href="external-Promise.html">Promise</a></li></ul><h3>Classes</h3><ul><li><a href="AnnotationBorderStyle.html">AnnotationBorderStyle</a></li><li><a href="AnnotationFactory.html">AnnotationFactory</a></li><li><a href="PageViewport.html">PageViewport</a></li><li><a href="PDFDataRangeTransport.html">PDFDataRangeTransport</a></li><li><a href="PDFDocumentLoadingTask.html">PDFDocumentLoadingTask</a></li><li><a href="PDFDocumentProxy.html">PDFDocumentProxy</a></li><li><a href="PDFJS.html">PDFJS</a></li><li><a href="PDFPageProxy.html">PDFPageProxy</a></li><li><a href="PDFWorker.html">PDFWorker</a></li><li><a href="RenderTask.html">RenderTask</a></li></ul><h3>Global</h3><ul><li><a href="global.html#_UnsupportedManager">_UnsupportedManager</a></li><li><a href="global.html#arrayByteLength">arrayByteLength</a></li><li><a href="global.html#arraysToBytes">arraysToBytes</a></li><li><a href="global.html#createPromiseCapability">createPromiseCapability</a></li><li><a href="global.html#createValidAbsoluteUrl">createValidAbsoluteUrl</a></li><li><a href="global.html#getDocument">getDocument</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Jun 12 2017 08:43:32 GMT+0000 (Coordinated Universal Time)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

@ -0,0 +1,234 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Class: PDFDataRangeTransport</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Class: PDFDataRangeTransport</h1>
<section>
<header>
<h2>PDFDataRangeTransport</h2>
</header>
<article>
<div class="container-overview">
<h4 class="name" id="PDFDataRangeTransport"><span class="type-signature"></span>new PDFDataRangeTransport<span class="signature">(length, initialData)</span><span class="type-signature"></span></h4>
<div class="description">
Abstract class to support range requests file loading.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>length</code></td>
<td class="type">
<span class="param-type">number</span>
</td>
<td class="description last"></td>
</tr>
<tr>
<td class="name"><code>initialData</code></td>
<td class="type">
<span class="param-type">Uint8Array</span>
</td>
<td class="description last"></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="display_api.js.html">display/api.js</a>, <a href="display_api.js.html#line431">line 431</a>
</li></ul></dd>
</dl>
</div>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Externals</h3><ul><li><a href="external-Promise.html">Promise</a></li></ul><h3>Classes</h3><ul><li><a href="AnnotationBorderStyle.html">AnnotationBorderStyle</a></li><li><a href="AnnotationFactory.html">AnnotationFactory</a></li><li><a href="PageViewport.html">PageViewport</a></li><li><a href="PDFDataRangeTransport.html">PDFDataRangeTransport</a></li><li><a href="PDFDocumentLoadingTask.html">PDFDocumentLoadingTask</a></li><li><a href="PDFDocumentProxy.html">PDFDocumentProxy</a></li><li><a href="PDFJS.html">PDFJS</a></li><li><a href="PDFPageProxy.html">PDFPageProxy</a></li><li><a href="PDFWorker.html">PDFWorker</a></li><li><a href="RenderTask.html">RenderTask</a></li></ul><h3>Global</h3><ul><li><a href="global.html#_UnsupportedManager">_UnsupportedManager</a></li><li><a href="global.html#arrayByteLength">arrayByteLength</a></li><li><a href="global.html#arraysToBytes">arraysToBytes</a></li><li><a href="global.html#createPromiseCapability">createPromiseCapability</a></li><li><a href="global.html#createValidAbsoluteUrl">createValidAbsoluteUrl</a></li><li><a href="global.html#getDocument">getDocument</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Jun 12 2017 08:43:32 GMT+0000 (Coordinated Universal Time)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,164 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Class: PDFWorker</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Class: PDFWorker</h1>
<section>
<header>
<h2>PDFWorker</h2>
</header>
<article>
<div class="container-overview">
<h4 class="name" id="PDFWorker"><span class="type-signature"></span>new PDFWorker<span class="signature">()</span><span class="type-signature"></span></h4>
<div class="description">
PDF.js web worker abstraction, it controls instantiation of PDF documents and
WorkerTransport for them. If creation of a web worker is not possible,
a "fake" worker will be used instead.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="display_api.js.html">display/api.js</a>, <a href="display_api.js.html#line1162">line 1162</a>
</li></ul></dd>
</dl>
</div>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Externals</h3><ul><li><a href="external-Promise.html">Promise</a></li></ul><h3>Classes</h3><ul><li><a href="AnnotationBorderStyle.html">AnnotationBorderStyle</a></li><li><a href="AnnotationFactory.html">AnnotationFactory</a></li><li><a href="PageViewport.html">PageViewport</a></li><li><a href="PDFDataRangeTransport.html">PDFDataRangeTransport</a></li><li><a href="PDFDocumentLoadingTask.html">PDFDocumentLoadingTask</a></li><li><a href="PDFDocumentProxy.html">PDFDocumentProxy</a></li><li><a href="PDFJS.html">PDFJS</a></li><li><a href="PDFPageProxy.html">PDFPageProxy</a></li><li><a href="PDFWorker.html">PDFWorker</a></li><li><a href="RenderTask.html">RenderTask</a></li></ul><h3>Global</h3><ul><li><a href="global.html#_UnsupportedManager">_UnsupportedManager</a></li><li><a href="global.html#arrayByteLength">arrayByteLength</a></li><li><a href="global.html#arraysToBytes">arraysToBytes</a></li><li><a href="global.html#createPromiseCapability">createPromiseCapability</a></li><li><a href="global.html#createValidAbsoluteUrl">createValidAbsoluteUrl</a></li><li><a href="global.html#getDocument">getDocument</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Jun 12 2017 08:43:32 GMT+0000 (Coordinated Universal Time)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

@ -0,0 +1,854 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Class: PageViewport</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Class: PageViewport</h1>
<section>
<header>
<h2>PageViewport</h2>
</header>
<article>
<div class="container-overview">
<h4 class="name" id="PageViewport"><span class="type-signature"></span>new PageViewport<span class="signature">()</span><span class="type-signature"></span></h4>
<div class="description">
PDF page viewport created based on scale, rotation and offset.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="shared_util.js.html">shared/util.js</a>, <a href="shared_util.js.html#line888">line 888</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="clone"><span class="type-signature"></span>clone<span class="signature">(args)</span><span class="type-signature"> &rarr; {<a href="PageViewport.html">PageViewport</a>}</span></h4>
<div class="description">
Clones viewport with additional properties.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>args</code></td>
<td class="type">
<span class="param-type">Object</span>
</td>
<td class="description last">(optional) If specified, may contain the 'scale' or
'rotation' properties to override the corresponding properties in
the cloned viewport.</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="shared_util.js.html">shared/util.js</a>, <a href="shared_util.js.html#line970">line 970</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
Cloned viewport.
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type"><a href="PageViewport.html">PageViewport</a></span>
</dd>
</dl>
<h4 class="name" id="convertToPdfPoint"><span class="type-signature"></span>convertToPdfPoint<span class="signature">(x, y)</span><span class="type-signature"> &rarr; {Object}</span></h4>
<div class="description">
Converts viewport coordinates to the PDF location. For examples, useful
for converting canvas pixel location into PDF one.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>x</code></td>
<td class="type">
<span class="param-type">number</span>
</td>
<td class="description last">X coordinate.</td>
</tr>
<tr>
<td class="name"><code>y</code></td>
<td class="type">
<span class="param-type">number</span>
</td>
<td class="description last">Y coordinate.</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="shared_util.js.html">shared/util.js</a>, <a href="shared_util.js.html#line1012">line 1012</a>
</li></ul></dd>
<dt class="tag-see">See:</dt>
<dd class="tag-see">
<ul>
<li>convertToViewportPoint</li>
</ul>
</dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
Object that contains 'x' and 'y' properties of the
point in the PDF coordinate space.
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Object</span>
</dd>
</dl>
<h4 class="name" id="convertToViewportPoint"><span class="type-signature"></span>convertToViewportPoint<span class="signature">(x, y)</span><span class="type-signature"> &rarr; {Object}</span></h4>
<div class="description">
Converts PDF point to the viewport coordinates. For examples, useful for
converting PDF location into canvas pixel coordinates.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>x</code></td>
<td class="type">
<span class="param-type">number</span>
</td>
<td class="description last">X coordinate.</td>
</tr>
<tr>
<td class="name"><code>y</code></td>
<td class="type">
<span class="param-type">number</span>
</td>
<td class="description last">Y coordinate.</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="shared_util.js.html">shared/util.js</a>, <a href="shared_util.js.html#line987">line 987</a>
</li></ul></dd>
<dt class="tag-see">See:</dt>
<dd class="tag-see">
<ul>
<li>convertToPdfPoint</li>
<li>convertToViewportRectangle</li>
</ul>
</dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
Object that contains 'x' and 'y' properties of the
point in the viewport coordinate space.
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Object</span>
</dd>
</dl>
<h4 class="name" id="convertToViewportRectangle"><span class="type-signature"></span>convertToViewportRectangle<span class="signature">(rect)</span><span class="type-signature"> &rarr; {Array}</span></h4>
<div class="description">
Converts PDF rectangle to the viewport coordinates.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>rect</code></td>
<td class="type">
<span class="param-type">Array</span>
</td>
<td class="description last">xMin, yMin, xMax and yMax coordinates.</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="shared_util.js.html">shared/util.js</a>, <a href="shared_util.js.html#line997">line 997</a>
</li></ul></dd>
<dt class="tag-see">See:</dt>
<dd class="tag-see">
<ul>
<li>convertToViewportPoint</li>
</ul>
</dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
Contains corresponding coordinates of the rectangle
in the viewport coordinate space.
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Array</span>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Externals</h3><ul><li><a href="external-Promise.html">Promise</a></li></ul><h3>Classes</h3><ul><li><a href="AnnotationBorderStyle.html">AnnotationBorderStyle</a></li><li><a href="AnnotationFactory.html">AnnotationFactory</a></li><li><a href="PageViewport.html">PageViewport</a></li><li><a href="PDFDataRangeTransport.html">PDFDataRangeTransport</a></li><li><a href="PDFDocumentLoadingTask.html">PDFDocumentLoadingTask</a></li><li><a href="PDFDocumentProxy.html">PDFDocumentProxy</a></li><li><a href="PDFJS.html">PDFJS</a></li><li><a href="PDFPageProxy.html">PDFPageProxy</a></li><li><a href="PDFWorker.html">PDFWorker</a></li><li><a href="RenderTask.html">RenderTask</a></li></ul><h3>Global</h3><ul><li><a href="global.html#_UnsupportedManager">_UnsupportedManager</a></li><li><a href="global.html#arrayByteLength">arrayByteLength</a></li><li><a href="global.html#arraysToBytes">arraysToBytes</a></li><li><a href="global.html#createPromiseCapability">createPromiseCapability</a></li><li><a href="global.html#createValidAbsoluteUrl">createValidAbsoluteUrl</a></li><li><a href="global.html#getDocument">getDocument</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Jun 12 2017 08:43:32 GMT+0000 (Coordinated Universal Time)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

@ -0,0 +1,493 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Class: RenderTask</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Class: RenderTask</h1>
<section>
<header>
<h2>RenderTask</h2>
</header>
<article>
<div class="container-overview">
<h4 class="name" id="RenderTask"><span class="type-signature"></span>new RenderTask<span class="signature">()</span><span class="type-signature"></span></h4>
<div class="description">
Allows controlling of the rendering tasks.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="display_api.js.html">display/api.js</a>, <a href="display_api.js.html#line2054">line 2054</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Members</h3>
<h4 class="name" id="promise"><span class="type-signature"></span>promise<span class="type-signature"></span></h4>
<div class="description">
Promise for rendering task completion.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="display_api.js.html">display/api.js</a>, <a href="display_api.js.html#line2072">line 2072</a>
</li></ul></dd>
</dl>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="cancel"><span class="type-signature"></span>cancel<span class="signature">()</span><span class="type-signature"></span></h4>
<div class="description">
Cancels the rendering task. If the task is currently rendering it will
not be cancelled until graphics pauses with a timeout. The promise that
this object extends will be rejected when cancelled.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="display_api.js.html">display/api.js</a>, <a href="display_api.js.html#line2081">line 2081</a>
</li></ul></dd>
</dl>
<h4 class="name" id="then"><span class="type-signature"></span>then<span class="signature">(onFulfilled, onRejected)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
<div class="description">
Registers callbacks to indicate the rendering task completion.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>onFulfilled</code></td>
<td class="type">
<span class="param-type">function</span>
</td>
<td class="description last">The callback for the rendering completion.</td>
</tr>
<tr>
<td class="name"><code>onRejected</code></td>
<td class="type">
<span class="param-type">function</span>
</td>
<td class="description last">The callback for the rendering failure.</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="display_api.js.html">display/api.js</a>, <a href="display_api.js.html#line2093">line 2093</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
A promise that is resolved after the onFulfilled or
onRejected callback.
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Promise</span>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Externals</h3><ul><li><a href="external-Promise.html">Promise</a></li></ul><h3>Classes</h3><ul><li><a href="AnnotationBorderStyle.html">AnnotationBorderStyle</a></li><li><a href="AnnotationFactory.html">AnnotationFactory</a></li><li><a href="PageViewport.html">PageViewport</a></li><li><a href="PDFDataRangeTransport.html">PDFDataRangeTransport</a></li><li><a href="PDFDocumentLoadingTask.html">PDFDocumentLoadingTask</a></li><li><a href="PDFDocumentProxy.html">PDFDocumentProxy</a></li><li><a href="PDFJS.html">PDFJS</a></li><li><a href="PDFPageProxy.html">PDFPageProxy</a></li><li><a href="PDFWorker.html">PDFWorker</a></li><li><a href="RenderTask.html">RenderTask</a></li></ul><h3>Global</h3><ul><li><a href="global.html#_UnsupportedManager">_UnsupportedManager</a></li><li><a href="global.html#arrayByteLength">arrayByteLength</a></li><li><a href="global.html#arraysToBytes">arraysToBytes</a></li><li><a href="global.html#createPromiseCapability">createPromiseCapability</a></li><li><a href="global.html#createValidAbsoluteUrl">createValidAbsoluteUrl</a></li><li><a href="global.html#getDocument">getDocument</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Jun 12 2017 08:43:32 GMT+0000 (Coordinated Universal Time)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,361 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: display/global.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: display/global.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>/* Copyright 2015 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
_UnsupportedManager, getDocument, LoopbackPort, PDFDataRangeTransport,
PDFWorker
} from './api';
import {
addLinkAttributes, CustomStyle, DEFAULT_LINK_REL, getFilenameFromUrl,
isExternalLinkTargetSet, isValidUrl, LinkTarget
} from './dom_utils';
import {
createBlob, createObjectURL, createPromiseCapability, deprecated,
getVerbosityLevel, globalScope, InvalidPDFException, isLittleEndian,
MissingPDFException, OPS, PageViewport, PasswordException, PasswordResponses,
removeNullCharacters, setVerbosityLevel, shadow, UnexpectedResponseException,
UnknownErrorException, UNSUPPORTED_FEATURES, Util, VERBOSITY_LEVELS, warn
} from '../shared/util';
import { AnnotationLayer } from './annotation_layer';
import { Metadata } from './metadata';
import { renderTextLayer } from './text_layer';
import { SVGGraphics } from './svg';
var isWorker = (typeof window === 'undefined');
// The global PDFJS object is now deprecated and will not be supported in
// the future. The members below are maintained for backward compatibility
// and shall not be extended or modified. If the global.js is included as
// a module, we will create a global PDFJS object instance or use existing.
if (!globalScope.PDFJS) {
globalScope.PDFJS = {};
}
var PDFJS = globalScope.PDFJS;
if (typeof PDFJSDev !== 'undefined') {
PDFJS.version = PDFJSDev.eval('BUNDLE_VERSION');
PDFJS.build = PDFJSDev.eval('BUNDLE_BUILD');
}
PDFJS.pdfBug = false;
if (PDFJS.verbosity !== undefined) {
setVerbosityLevel(PDFJS.verbosity);
}
delete PDFJS.verbosity;
Object.defineProperty(PDFJS, 'verbosity', {
get() {
return getVerbosityLevel();
},
set(level) {
setVerbosityLevel(level);
},
enumerable: true,
configurable: true,
});
PDFJS.VERBOSITY_LEVELS = VERBOSITY_LEVELS;
PDFJS.OPS = OPS;
PDFJS.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES;
PDFJS.isValidUrl = isValidUrl;
PDFJS.shadow = shadow;
PDFJS.createBlob = createBlob;
PDFJS.createObjectURL = function PDFJS_createObjectURL(data, contentType) {
return createObjectURL(data, contentType, PDFJS.disableCreateObjectURL);
};
Object.defineProperty(PDFJS, 'isLittleEndian', {
configurable: true,
get: function PDFJS_isLittleEndian() {
return shadow(PDFJS, 'isLittleEndian', isLittleEndian());
},
});
PDFJS.removeNullCharacters = removeNullCharacters;
PDFJS.PasswordResponses = PasswordResponses;
PDFJS.PasswordException = PasswordException;
PDFJS.UnknownErrorException = UnknownErrorException;
PDFJS.InvalidPDFException = InvalidPDFException;
PDFJS.MissingPDFException = MissingPDFException;
PDFJS.UnexpectedResponseException = UnexpectedResponseException;
PDFJS.Util = Util;
PDFJS.PageViewport = PageViewport;
PDFJS.createPromiseCapability = createPromiseCapability;
/**
* The maximum allowed image size in total pixels e.g. width * height. Images
* above this value will not be drawn. Use -1 for no limit.
* @var {number}
*/
PDFJS.maxImageSize = (PDFJS.maxImageSize === undefined ?
-1 : PDFJS.maxImageSize);
/**
* The url of where the predefined Adobe CMaps are located. Include trailing
* slash.
* @var {string}
*/
PDFJS.cMapUrl = (PDFJS.cMapUrl === undefined ? null : PDFJS.cMapUrl);
/**
* Specifies if CMaps are binary packed.
* @var {boolean}
*/
PDFJS.cMapPacked = PDFJS.cMapPacked === undefined ? false : PDFJS.cMapPacked;
/**
* By default fonts are converted to OpenType fonts and loaded via font face
* rules. If disabled, the font will be rendered using a built in font
* renderer that constructs the glyphs with primitive path commands.
* @var {boolean}
*/
PDFJS.disableFontFace = (PDFJS.disableFontFace === undefined ?
false : PDFJS.disableFontFace);
/**
* Path for image resources, mainly for annotation icons. Include trailing
* slash.
* @var {string}
*/
PDFJS.imageResourcesPath = (PDFJS.imageResourcesPath === undefined ?
'' : PDFJS.imageResourcesPath);
/**
* Disable the web worker and run all code on the main thread. This will
* happen automatically if the browser doesn't support workers or sending
* typed arrays to workers.
* @var {boolean}
*/
PDFJS.disableWorker = (PDFJS.disableWorker === undefined ?
false : PDFJS.disableWorker);
/**
* Path and filename of the worker file. Required when the worker is enabled
* in development mode. If unspecified in the production build, the worker
* will be loaded based on the location of the pdf.js file. It is recommended
* that the workerSrc is set in a custom application to prevent issues caused
* by third-party frameworks and libraries.
* @var {string}
*/
PDFJS.workerSrc = (PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc);
/**
* Defines global port for worker process. Overrides workerSrc and
* disableWorker setting.
*/
PDFJS.workerPort = (PDFJS.workerPort === undefined ? null : PDFJS.workerPort);
/**
* Disable range request loading of PDF files. When enabled and if the server
* supports partial content requests then the PDF will be fetched in chunks.
* Enabled (false) by default.
* @var {boolean}
*/
PDFJS.disableRange = (PDFJS.disableRange === undefined ?
false : PDFJS.disableRange);
/**
* Disable streaming of PDF file data. By default PDF.js attempts to load PDF
* in chunks. This default behavior can be disabled.
* @var {boolean}
*/
PDFJS.disableStream = (PDFJS.disableStream === undefined ?
false : PDFJS.disableStream);
/**
* Disable pre-fetching of PDF file data. When range requests are enabled
* PDF.js will automatically keep fetching more data even if it isn't needed
* to display the current page. This default behavior can be disabled.
*
* NOTE: It is also necessary to disable streaming, see above,
* in order for disabling of pre-fetching to work correctly.
* @var {boolean}
*/
PDFJS.disableAutoFetch = (PDFJS.disableAutoFetch === undefined ?
false : PDFJS.disableAutoFetch);
/**
* Enables special hooks for debugging PDF.js.
* @var {boolean}
*/
PDFJS.pdfBug = (PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug);
/**
* Enables transfer usage in postMessage for ArrayBuffers.
* @var {boolean}
*/
PDFJS.postMessageTransfers = (PDFJS.postMessageTransfers === undefined ?
true : PDFJS.postMessageTransfers);
/**
* Disables URL.createObjectURL usage.
* @var {boolean}
*/
PDFJS.disableCreateObjectURL = (PDFJS.disableCreateObjectURL === undefined ?
false : PDFJS.disableCreateObjectURL);
/**
* Disables WebGL usage.
* @var {boolean}
*/
PDFJS.disableWebGL = (PDFJS.disableWebGL === undefined ?
true : PDFJS.disableWebGL);
/**
* Specifies the |target| attribute for external links.
* The constants from PDFJS.LinkTarget should be used:
* - NONE [default]
* - SELF
* - BLANK
* - PARENT
* - TOP
* @var {number}
*/
PDFJS.externalLinkTarget = (PDFJS.externalLinkTarget === undefined ?
LinkTarget.NONE : PDFJS.externalLinkTarget);
/**
* Specifies the |rel| attribute for external links. Defaults to stripping
* the referrer.
* @var {string}
*/
PDFJS.externalLinkRel = (PDFJS.externalLinkRel === undefined ?
DEFAULT_LINK_REL : PDFJS.externalLinkRel);
/**
* Determines if we can eval strings as JS. Primarily used to improve
* performance for font rendering.
* @var {boolean}
*/
PDFJS.isEvalSupported = (PDFJS.isEvalSupported === undefined ?
true : PDFJS.isEvalSupported);
/**
* Opt-in to backwards incompatible API changes. NOTE:
* If the `PDFJS_NEXT` build flag is set, it will override this setting.
* @var {boolean}
*/
PDFJS.pdfjsNext = (PDFJS.pdfjsNext === undefined) ? false : PDFJS.pdfjsNext;
if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('MOZCENTRAL')) {
var savedOpenExternalLinksInNewWindow = PDFJS.openExternalLinksInNewWindow;
delete PDFJS.openExternalLinksInNewWindow;
Object.defineProperty(PDFJS, 'openExternalLinksInNewWindow', {
get() {
return PDFJS.externalLinkTarget === LinkTarget.BLANK;
},
set(value) {
if (value) {
deprecated('PDFJS.openExternalLinksInNewWindow, please use ' +
'"PDFJS.externalLinkTarget = PDFJS.LinkTarget.BLANK" instead.');
}
if (PDFJS.externalLinkTarget !== LinkTarget.NONE) {
warn('PDFJS.externalLinkTarget is already initialized');
return;
}
PDFJS.externalLinkTarget = value ? LinkTarget.BLANK : LinkTarget.NONE;
},
enumerable: true,
configurable: true,
});
if (savedOpenExternalLinksInNewWindow) {
/**
* (Deprecated) Opens external links in a new window if enabled.
* The default behavior opens external links in the PDF.js window.
*
* NOTE: This property has been deprecated, please use
* `PDFJS.externalLinkTarget = PDFJS.LinkTarget.BLANK` instead.
* @var {boolean}
*/
PDFJS.openExternalLinksInNewWindow = savedOpenExternalLinksInNewWindow;
}
}
PDFJS.getDocument = getDocument;
PDFJS.LoopbackPort = LoopbackPort;
PDFJS.PDFDataRangeTransport = PDFDataRangeTransport;
PDFJS.PDFWorker = PDFWorker;
PDFJS.hasCanvasTypedArrays = true; // compatibility.js ensures this invariant
PDFJS.CustomStyle = CustomStyle;
PDFJS.LinkTarget = LinkTarget;
PDFJS.addLinkAttributes = addLinkAttributes;
PDFJS.getFilenameFromUrl = getFilenameFromUrl;
PDFJS.isExternalLinkTargetSet = isExternalLinkTargetSet;
PDFJS.AnnotationLayer = AnnotationLayer;
PDFJS.renderTextLayer = renderTextLayer;
PDFJS.Metadata = Metadata;
PDFJS.SVGGraphics = SVGGraphics;
PDFJS.UnsupportedManager = _UnsupportedManager;
export {
globalScope,
isWorker,
PDFJS,
};
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Externals</h3><ul><li><a href="external-Promise.html">Promise</a></li></ul><h3>Classes</h3><ul><li><a href="AnnotationBorderStyle.html">AnnotationBorderStyle</a></li><li><a href="AnnotationFactory.html">AnnotationFactory</a></li><li><a href="PageViewport.html">PageViewport</a></li><li><a href="PDFDataRangeTransport.html">PDFDataRangeTransport</a></li><li><a href="PDFDocumentLoadingTask.html">PDFDocumentLoadingTask</a></li><li><a href="PDFDocumentProxy.html">PDFDocumentProxy</a></li><li><a href="PDFJS.html">PDFJS</a></li><li><a href="PDFPageProxy.html">PDFPageProxy</a></li><li><a href="PDFWorker.html">PDFWorker</a></li><li><a href="RenderTask.html">RenderTask</a></li></ul><h3>Global</h3><ul><li><a href="global.html#_UnsupportedManager">_UnsupportedManager</a></li><li><a href="global.html#arrayByteLength">arrayByteLength</a></li><li><a href="global.html#arraysToBytes">arraysToBytes</a></li><li><a href="global.html#createPromiseCapability">createPromiseCapability</a></li><li><a href="global.html#createValidAbsoluteUrl">createValidAbsoluteUrl</a></li><li><a href="global.html#getDocument">getDocument</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Jun 12 2017 08:43:32 GMT+0000 (Coordinated Universal Time)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

@ -0,0 +1,96 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: doc_helper.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: doc_helper.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>/* Copyright 2012 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* eslint-disable strict */
/*
NOTE: This file is created as a helper to assist with JSDoc html files.
It is not for use in the executable code.
*/
/**
* PDFJS scope object that contains all functions, objects and variables related
* to the PDF.js.
* @constructor
*/
function PDFJS() {
// Mock class constructor. See src/display/api.js.
}
/**
* Controls the logging level.
* The constants from PDFJS.VERBOSITY_LEVELS should be used:
* - errors
* - warnings [default]
* - infos
* @var {number}
*/
PDFJS.verbosity = PDFJS.VERBOSITY_LEVELS.warnings;
/**
* Represents the eventual result of an asynchronous operation.
* @external Promise
* @see {@link http://promisesaplus.com/ Promise/A+}
*/
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Externals</h3><ul><li><a href="external-Promise.html">Promise</a></li></ul><h3>Classes</h3><ul><li><a href="AnnotationBorderStyle.html">AnnotationBorderStyle</a></li><li><a href="AnnotationFactory.html">AnnotationFactory</a></li><li><a href="PageViewport.html">PageViewport</a></li><li><a href="PDFDataRangeTransport.html">PDFDataRangeTransport</a></li><li><a href="PDFDocumentLoadingTask.html">PDFDocumentLoadingTask</a></li><li><a href="PDFDocumentProxy.html">PDFDocumentProxy</a></li><li><a href="PDFJS.html">PDFJS</a></li><li><a href="PDFPageProxy.html">PDFPageProxy</a></li><li><a href="PDFWorker.html">PDFWorker</a></li><li><a href="RenderTask.html">RenderTask</a></li></ul><h3>Global</h3><ul><li><a href="global.html#_UnsupportedManager">_UnsupportedManager</a></li><li><a href="global.html#arrayByteLength">arrayByteLength</a></li><li><a href="global.html#arraysToBytes">arraysToBytes</a></li><li><a href="global.html#createPromiseCapability">createPromiseCapability</a></li><li><a href="global.html#createValidAbsoluteUrl">createValidAbsoluteUrl</a></li><li><a href="global.html#getDocument">getDocument</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Jun 12 2017 08:43:32 GMT+0000 (Coordinated Universal Time)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

@ -0,0 +1,137 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: External: Promise</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">External: Promise</h1>
<section>
<header>
<h2>Promise</h2>
</header>
<article>
<div class="container-overview">
<div class="description">Represents the eventual result of an asynchronous operation.</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="doc_helper.js.html">doc_helper.js</a>, <a href="doc_helper.js.html#line41">line 41</a>
</li></ul></dd>
<dt class="tag-see">See:</dt>
<dd class="tag-see">
<ul>
<li><a href="http://promisesaplus.com/">Promise/A+</a></li>
</ul>
</dd>
</dl>
</div>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Externals</h3><ul><li><a href="external-Promise.html">Promise</a></li></ul><h3>Classes</h3><ul><li><a href="AnnotationBorderStyle.html">AnnotationBorderStyle</a></li><li><a href="AnnotationFactory.html">AnnotationFactory</a></li><li><a href="PageViewport.html">PageViewport</a></li><li><a href="PDFDataRangeTransport.html">PDFDataRangeTransport</a></li><li><a href="PDFDocumentLoadingTask.html">PDFDocumentLoadingTask</a></li><li><a href="PDFDocumentProxy.html">PDFDocumentProxy</a></li><li><a href="PDFJS.html">PDFJS</a></li><li><a href="PDFPageProxy.html">PDFPageProxy</a></li><li><a href="PDFWorker.html">PDFWorker</a></li><li><a href="RenderTask.html">RenderTask</a></li></ul><h3>Global</h3><ul><li><a href="global.html#_UnsupportedManager">_UnsupportedManager</a></li><li><a href="global.html#arrayByteLength">arrayByteLength</a></li><li><a href="global.html#arraysToBytes">arraysToBytes</a></li><li><a href="global.html#createPromiseCapability">createPromiseCapability</a></li><li><a href="global.html#createValidAbsoluteUrl">createValidAbsoluteUrl</a></li><li><a href="global.html#getDocument">getDocument</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Jun 12 2017 08:43:32 GMT+0000 (Coordinated Universal Time)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 114 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 117 KiB

File diff suppressed because it is too large Load Diff

@ -0,0 +1,65 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Home</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Home</h1>
<h3> </h3>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Externals</h3><ul><li><a href="external-Promise.html">Promise</a></li></ul><h3>Classes</h3><ul><li><a href="AnnotationBorderStyle.html">AnnotationBorderStyle</a></li><li><a href="AnnotationFactory.html">AnnotationFactory</a></li><li><a href="PageViewport.html">PageViewport</a></li><li><a href="PDFDataRangeTransport.html">PDFDataRangeTransport</a></li><li><a href="PDFDocumentLoadingTask.html">PDFDocumentLoadingTask</a></li><li><a href="PDFDocumentProxy.html">PDFDocumentProxy</a></li><li><a href="PDFJS.html">PDFJS</a></li><li><a href="PDFPageProxy.html">PDFPageProxy</a></li><li><a href="PDFWorker.html">PDFWorker</a></li><li><a href="RenderTask.html">RenderTask</a></li></ul><h3>Global</h3><ul><li><a href="global.html#_UnsupportedManager">_UnsupportedManager</a></li><li><a href="global.html#arrayByteLength">arrayByteLength</a></li><li><a href="global.html#arraysToBytes">arraysToBytes</a></li><li><a href="global.html#createPromiseCapability">createPromiseCapability</a></li><li><a href="global.html#createValidAbsoluteUrl">createValidAbsoluteUrl</a></li><li><a href="global.html#getDocument">getDocument</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Jun 12 2017 08:43:32 GMT+0000 (Coordinated Universal Time)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

@ -0,0 +1,25 @@
/*global document */
(function() {
var source = document.getElementsByClassName('prettyprint source linenums');
var i = 0;
var lineNumber = 0;
var lineId;
var lines;
var totalLines;
var anchorHash;
if (source && source[0]) {
anchorHash = document.location.hash.substring(1);
lines = source[0].getElementsByTagName('li');
totalLines = lines.length;
for (; i < totalLines; i++) {
lineNumber++;
lineId = 'line' + lineNumber;
lines[i].id = lineId;
if (lineId === anchorHash) {
lines[i].className += ' selected';
}
}
}
})();

@ -0,0 +1,2 @@
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com",
/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]);

@ -0,0 +1,28 @@
var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a=
[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c<
f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&&
(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r=
{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length,
t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===
"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),
l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/,
q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g,
"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a),
a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}
for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value",
m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m=
a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue=
j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],
H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+
I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),
["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",
/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),
["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes",
hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b=
!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,
250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",
PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})();

File diff suppressed because it is too large Load Diff

@ -0,0 +1,354 @@
@font-face {
font-family: 'Open Sans';
font-weight: normal;
font-style: normal;
src: url('../fonts/OpenSans-Regular-webfont.eot');
src:
local('Open Sans'),
local('OpenSans'),
url('../fonts/OpenSans-Regular-webfont.eot?#iefix') format('embedded-opentype'),
url('../fonts/OpenSans-Regular-webfont.woff') format('woff'),
url('../fonts/OpenSans-Regular-webfont.svg#open_sansregular') format('svg');
}
@font-face {
font-family: 'Open Sans Light';
font-weight: normal;
font-style: normal;
src: url('../fonts/OpenSans-Light-webfont.eot');
src:
local('Open Sans Light'),
local('OpenSans Light'),
url('../fonts/OpenSans-Light-webfont.eot?#iefix') format('embedded-opentype'),
url('../fonts/OpenSans-Light-webfont.woff') format('woff'),
url('../fonts/OpenSans-Light-webfont.svg#open_sanslight') format('svg');
}
html
{
overflow: auto;
background-color: #fff;
font-size: 14px;
}
body
{
font-family: 'Open Sans', sans-serif;
line-height: 1.5;
color: #4d4e53;
background-color: white;
}
a, a:visited, a:active {
color: #0095dd;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
header
{
display: block;
padding: 0px 4px;
}
tt, code, kbd, samp {
font-family: Consolas, Monaco, 'Andale Mono', monospace;
}
.class-description {
font-size: 130%;
line-height: 140%;
margin-bottom: 1em;
margin-top: 1em;
}
.class-description:empty {
margin: 0;
}
#main {
float: left;
width: 70%;
}
article dl {
margin-bottom: 40px;
}
section
{
display: block;
background-color: #fff;
padding: 12px 24px;
border-bottom: 1px solid #ccc;
margin-right: 30px;
}
.variation {
display: none;
}
.signature-attributes {
font-size: 60%;
color: #aaa;
font-style: italic;
font-weight: lighter;
}
nav
{
display: block;
float: right;
margin-top: 28px;
width: 30%;
box-sizing: border-box;
border-left: 1px solid #ccc;
padding-left: 16px;
}
nav ul {
font-family: 'Lucida Grande', 'Lucida Sans Unicode', arial, sans-serif;
font-size: 100%;
line-height: 17px;
padding: 0;
margin: 0;
list-style-type: none;
}
nav ul a, nav ul a:visited, nav ul a:active {
font-family: Consolas, Monaco, 'Andale Mono', monospace;
line-height: 18px;
color: #4D4E53;
}
nav h3 {
margin-top: 12px;
}
nav li {
margin-top: 6px;
}
footer {
display: block;
padding: 6px;
margin-top: 12px;
font-style: italic;
font-size: 90%;
}
h1, h2, h3, h4 {
font-weight: 200;
margin: 0;
}
h1
{
font-family: 'Open Sans Light', sans-serif;
font-size: 48px;
letter-spacing: -2px;
margin: 12px 24px 20px;
}
h2, h3.subsection-title
{
font-size: 30px;
font-weight: 700;
letter-spacing: -1px;
margin-bottom: 12px;
}
h3
{
font-size: 24px;
letter-spacing: -0.5px;
margin-bottom: 12px;
}
h4
{
font-size: 18px;
letter-spacing: -0.33px;
margin-bottom: 12px;
color: #4d4e53;
}
h5, .container-overview .subsection-title
{
font-size: 120%;
font-weight: bold;
letter-spacing: -0.01em;
margin: 8px 0 3px 0;
}
h6
{
font-size: 100%;
letter-spacing: -0.01em;
margin: 6px 0 3px 0;
font-style: italic;
}
table
{
border-spacing: 0;
border: 0;
border-collapse: collapse;
}
td, th
{
border: 1px solid #ddd;
margin: 0px;
text-align: left;
vertical-align: top;
padding: 4px 6px;
display: table-cell;
}
thead tr
{
background-color: #ddd;
font-weight: bold;
}
th { border-right: 1px solid #aaa; }
tr > th:last-child { border-right: 1px solid #ddd; }
.ancestors { color: #999; }
.ancestors a
{
color: #999 !important;
text-decoration: none;
}
.clear
{
clear: both;
}
.important
{
font-weight: bold;
color: #950B02;
}
.yes-def {
text-indent: -1000px;
}
.type-signature {
color: #aaa;
}
.name, .signature {
font-family: Consolas, Monaco, 'Andale Mono', monospace;
}
.details { margin-top: 14px; border-left: 2px solid #DDD; }
.details dt { width: 120px; float: left; padding-left: 10px; padding-top: 6px; }
.details dd { margin-left: 70px; }
.details ul { margin: 0; }
.details ul { list-style-type: none; }
.details li { margin-left: 30px; padding-top: 6px; }
.details pre.prettyprint { margin: 0 }
.details .object-value { padding-top: 0; }
.description {
margin-bottom: 1em;
margin-top: 1em;
}
.code-caption
{
font-style: italic;
font-size: 107%;
margin: 0;
}
.prettyprint
{
border: 1px solid #ddd;
width: 80%;
overflow: auto;
}
.prettyprint.source {
width: inherit;
}
.prettyprint code
{
font-size: 100%;
line-height: 18px;
display: block;
padding: 4px 12px;
margin: 0;
background-color: #fff;
color: #4D4E53;
}
.prettyprint code span.line
{
display: inline-block;
}
.prettyprint.linenums
{
padding-left: 70px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.prettyprint.linenums ol
{
padding-left: 0;
}
.prettyprint.linenums li
{
border-left: 3px #ddd solid;
}
.prettyprint.linenums li.selected,
.prettyprint.linenums li.selected *
{
background-color: lightyellow;
}
.prettyprint.linenums li *
{
-webkit-user-select: text;
-moz-user-select: text;
-ms-user-select: text;
user-select: text;
}
.params .name, .props .name, .name code {
color: #4D4E53;
font-family: Consolas, Monaco, 'Andale Mono', monospace;
font-size: 100%;
}
.params td.description > p:first-child,
.props td.description > p:first-child
{
margin-top: 0;
padding-top: 0;
}
.params td.description > p:last-child,
.props td.description > p:last-child
{
margin-bottom: 0;
padding-bottom: 0;
}
.disabled {
color: #454545;
}

@ -0,0 +1,132 @@
/* Tomorrow Theme */
/* Original theme - https://github.com/chriskempson/tomorrow-theme */
/* Pretty printing styles. Used with prettify.js. */
/* SPAN elements with the classes below are added by prettyprint. */
/* plain text */
.pln {
color: #4d4d4c; }
@media screen {
/* string content */
.str {
color: #718c00; }
/* a keyword */
.kwd {
color: #8959a8; }
/* a comment */
.com {
color: #8e908c; }
/* a type name */
.typ {
color: #4271ae; }
/* a literal value */
.lit {
color: #f5871f; }
/* punctuation */
.pun {
color: #4d4d4c; }
/* lisp open bracket */
.opn {
color: #4d4d4c; }
/* lisp close bracket */
.clo {
color: #4d4d4c; }
/* a markup tag name */
.tag {
color: #c82829; }
/* a markup attribute name */
.atn {
color: #f5871f; }
/* a markup attribute value */
.atv {
color: #3e999f; }
/* a declaration */
.dec {
color: #f5871f; }
/* a variable name */
.var {
color: #c82829; }
/* a function name */
.fun {
color: #4271ae; } }
/* Use higher contrast and text-weight for printable form. */
@media print, projection {
.str {
color: #060; }
.kwd {
color: #006;
font-weight: bold; }
.com {
color: #600;
font-style: italic; }
.typ {
color: #404;
font-weight: bold; }
.lit {
color: #044; }
.pun, .opn, .clo {
color: #440; }
.tag {
color: #006;
font-weight: bold; }
.atn {
color: #404; }
.atv {
color: #060; } }
/* Style */
/*
pre.prettyprint {
background: white;
font-family: Consolas, Monaco, 'Andale Mono', monospace;
font-size: 12px;
line-height: 1.5;
border: 1px solid #ccc;
padding: 10px; }
*/
/* Specify class=linenums on a pre to get line numbering */
ol.linenums {
margin-top: 0;
margin-bottom: 0; }
/* IE indents via margin-left */
li.L0,
li.L1,
li.L2,
li.L3,
li.L4,
li.L5,
li.L6,
li.L7,
li.L8,
li.L9 {
/* */ }
/* Alternate shading for lines */
li.L1,
li.L3,
li.L5,
li.L7,
li.L9 {
/* */ }

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<link rel="shortcut icon" href="../images/favicon.ico">
<title>API</title>
<!-- Bootstrap core CSS-->
<link href="../css/bootstrap.min.css" rel="stylesheet">
<!-- Custom styles for this template-->
<link href="../css/main.css" rel="stylesheet">
</head>
<body>
<header class="navbar navbar-default navbar-static-top">
<div class="container">
<div class="navbar-header">
<button type="button" data-toggle="collapse" data-target=".navbar-collapse" class="navbar-toggle"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a href="#" class="navbar-brand"><img src="../images/logo.svg"></a>
</div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li><a href="../">Home</a></li>
<li><a href="../getting_started/">Getting Started</a></li>
<li><a href="../examples/">Examples</a></li>
<li><a href="https://github.com/mozilla/pdf.js/wiki/Frequently-Asked-Questions">FAQ</a></li>
<li class="active"><a href="../api/">API</a></li>
</ul>
</div>
</div>
</header>
<div class="container">
<div class="starter-template">
<section class="content"><h1 id="api"><span class="caps">API</span></h1>
<p>Were currently working on <a href="draft/index.html">better <span class="caps">API</span> docs</a>, but the <span class="caps">API</span> is well documented in <a href="https://github.com/mozilla/pdf.js/blob/master/src/display/api.js">api.js</a>.</p>
</section>
</div>
</div>
<div class="container">
<footer>
<p>&copy;Mozilla and individual contributors</p><p>PDF.js is licensed under <a href="https://github.com/mozilla/pdf.js/blob/master/LICENSE">Apache</a>,
documentation is licensed under <a href="http://creativecommons.org/licenses/by-sa/2.5/">CC BY-SA 2.5</a></p>
</footer>
</div>
<!-- Bootstrap core JavaScript-->
<script src="../js/jquery-2.1.0.min.js"></script>
<script src="../js/bootstrap.min.js"></script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -0,0 +1,119 @@
body {
}
.starter-template {
padding: 0 15px;
}
.navbar-brand {
padding: 4px 15px;
}
.navbar-brand img {
height: 42px;
}
.navbar {
border-color: #e5e7e8;
}
.navbar-default .navbar-nav > .active > a,
.navbar-default .navbar-nav > .active > a:hover,
.navbar-default .navbar-nav > .active > a:focus {
background-color: #fff;
border: 1px solid #e5e7e8;
border-width: 0 1px;
position: relative;
top: 1px;
}
footer {
padding-top: 40px;
padding-bottom: 40px;
margin-top: 100px;
color: #777;
text-align: center;
border-top: 1px solid #E5E5E5;
}
/* code styling */
code {
font-family: 'Anonymous Pro', monospace;
font-size: 0.85em;
color: #000;
}
pre code {
display: block;
line-height: 1.1;
}
p code {
padding: 0.1em 0.3em 0.2em;
border-radius: 0.3em;
position: relative;
top: -0.15em;
background: #444;
color: #fff;
white-space: nowrap;
}
/* syntax hl stuff */
code.lang-markdown {
color: #424242;
}
code.lang-markdown .header,
code.lang-markdown .strong {
font-weight: bold;
}
code.lang-markdown .emphasis {
font-style: italic;
}
code.lang-markdown .horizontal_rule,
code.lang-markdown .link_label,
code.lang-markdown .code,
code.lang-markdown .header,
code.lang-markdown .link_url {
color: #555;
}
code.lang-markdown .blockquote,
code.lang-markdown .bullet {
color: #bbb;
}
/* Tomorrow Theme */
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
/* Original theme - https://github.com/chriskempson/tomorrow-theme */
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
.tomorrow-comment, pre .comment, pre .title {
color: #8e908c;
}
.tomorrow-red, pre .variable, pre .attribute, pre .tag, pre .regexp, pre .ruby .constant, pre .xml .tag .title, pre .xml .pi, pre .xml .doctype, pre .html .doctype, pre .css .id, pre .css .class, pre .css .pseudo {
color: #c82829;
}
.tomorrow-orange, pre .number, pre .preprocessor, pre .built_in, pre .literal, pre .params, pre .constant {
color: #f5871f;
}
.tomorrow-yellow, pre .class, pre .ruby .class .title, pre .css .rules .attribute {
color: #eab700;
}
.tomorrow-green, pre .string, pre .value, pre .inheritance, pre .header, pre .ruby .symbol, pre .xml .cdata {
color: #718c00;
}
.tomorrow-aqua, pre .css .hexcolor {
color: #3e999f;
}
.tomorrow-blue, pre .function, pre .python .decorator, pre .python .title, pre .ruby .function .title, pre .ruby .title .keyword, pre .perl .sub, pre .javascript .title, pre .coffeescript .title {
color: #4271ae;
}
.tomorrow-purple, pre .keyword, pre .javascript .function {
color: #8959a8;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns="http://www.w3.org/2000/svg"
width="64"
height="64">
<path
d="M 4.8364028,0.4891005 32.096378,4.5726641 59.163597,0.4891005 54.680408,57.805097 32.096378,63.510899 8.3116209,57.805097 z"
style="fill:#e5e7e8;fill-opacity:1;fill-rule:nonzero;stroke:#cccccc" />
<path
d="M 32.096378,10.745857 53.925414,6.8301117 51.016574,53.81906 32.096378,58.517955 z"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<rect
width="34.027256"
height="19.136194"
x="3.7557135"
y="22.431904"
style="fill:#ff2600;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<rect
width="23.480518"
height="19.136194"
x="36.763767"
y="22.431904"
style="fill:#ff501a;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<g transform="matrix(0.42778543,0,0,0.42778543,58.617711,9.6737064)">
<path
d="m -120.53125,34.59375 0,35.1875 6.53125,0 0,-5.9375 0,-5.96875 8.875,0 4.15625,-3.71875 0,-7.71875 0,-7.71875 -4.21875,-4.125 -15.34375,0 z m 6.53125,6.8125 6.21875,0 0,10.21875 -6.21875,0 0,-10.21875 z"
style="fill:#ffffff;fill-opacity:1" />
<path
d="m -98.125,34.59375 0,35.1875 16.125,0 3.75,-3.625 0,-27.96875 -3.96875,-3.59375 -15.90625,0 z m 6.8125,6.8125 6.8125,0 0,21.5625 -6.8125,0 0,-21.5625 z" id="path3056"
style="fill:#ffffff;fill-opacity:1" />
<path
d="m -74.856072,34.602929 c 5.485697,0 10.971394,0 16.457091,0 0,2.269943 0,4.539887 0,6.80983 -3.404915,0 -6.809831,0 -10.214746,0 0,2.472069 0,4.944138 0,7.416206 2.93201,0.110496 5.864021,-0.110494 8.796031,0 l 0,3.366025 0,3.375914 c -2.93201,0.110495 -5.864021,-0.110495 -8.796031,0 l 0,7.146446 0,7.069702 c -2.080782,0 -4.161563,0 -6.242345,0 0,-11.728041 0,-23.456082 0,-35.184123 z"
style="fill:#ffffff;fill-opacity:1" />
<path
d="m -42.8813,67.942723 -2.181762,-1.844329 c 0,-1.986871 0,-3.973742 0,-5.960613 2.175363,6.7e-4 4.350725,0.0013 6.526088,0.002 0,0.94581 0,1.891619 0,2.837429 1.891619,0 3.783239,0 5.674858,0 0,-9.458098 0,-18.916195 0,-28.374293 2.175363,-1.26e-4 4.350725,-2.52e-4 6.526088,-3.78e-4 0,10.498614 0,20.997229 0,31.495843 -1.454508,1.229554 -2.909019,2.459106 -4.363529,3.688658 -3.333325,0 -6.666651,0 -9.999976,0 -0.727237,-0.614768 -1.454563,-1.229595 -2.181767,-1.844308 z"
style="fill:#ffffff;fill-opacity:1" />
<path
d="m -21.316836,67.942723 -2.109122,-1.844329 0,-5.978379 c 2.061011,0 4.392437,0.01978 6.453448,0.01978 0,0.94581 0,1.891619 0,2.837429 2.269943,0 4.539887,0 6.80983,0 0,-2.459105 0,-4.918211 0,-7.377316 -3.196954,0 -6.393909,0 -9.590863,0 l -3.745055,-3.688659 0,-6.80983 0,-6.80983 3.745055,-3.688658 c 3.863156,0 7.726313,0 11.5894692,0 l 4.2511106,3.688658 c -0.00204,1.797039 -0.00472,3.594077 -0.00737,5.391115 -2.0807816,0 -4.1615632,0 -6.2423448,0 0,-0.756648 0,-1.513295 0,-2.269943 -2.269943,0 -4.539887,0 -6.80983,0 0,2.459105 0,4.918211 0,7.377316 2.990126,0 5.980253,0 8.9703792,0 1.3605964,1.204585 4.0817956,3.613749 4.0817956,3.613749 0,4.555246 0,9.110492 0,13.665738 l -2.0892845,1.858745 -2.0892901,1.858745 -5.5180792,0 -5.51808,0 z"
style="fill:#ffffff;fill-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 933 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save